mbailey-ruby-xen 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/History.txt CHANGED
@@ -1,3 +1,8 @@
1
+ === 0.0.2 / 2008-09-11
2
+
3
+ * Broke out classes into separate files
4
+ * Added rspec outline
5
+
1
6
  === 0.0.1 / 2008-09-08
2
7
 
3
8
  * Initial import
data/Manifest.txt CHANGED
@@ -6,3 +6,11 @@ bin/ruby-xen
6
6
  lib/ruby-xen.rb
7
7
  test/test_ruby-xen.rb
8
8
  lib/ruby-xen/domain.rb
9
+ lib/xen/backup.rb
10
+ lib/xen/command.rb
11
+ lib/xen/config.rb
12
+ lib/xen/slice.rb
13
+ lib/xen/host.rb
14
+ lib/xen/image.rb
15
+ lib/xen/instance.rb
16
+ lib/templates/domu.cfg.erb
data/README.rdoc CHANGED
@@ -25,13 +25,12 @@ ruby-xen can also be used by ruby code or from irb.
25
25
  require 'rubygems'
26
26
  require 'ruby-xen'
27
27
 
28
-
29
- domain = Xen::Domain.find(:example)
30
- domain.running? # true
31
- domain.stop
32
- domain.running? # false
33
- domain.start
34
- domain.running? # true
28
+ slice = Xen::Slice.find(:example)
29
+ slice.running? # true
30
+ slice.stop
31
+ slice.running? # false
32
+ slice.start
33
+ slice.running? # true
35
34
 
36
35
  == REQUIREMENTS:
37
36
 
@@ -49,7 +48,7 @@ or open source applications. More details found here:
49
48
  http://www.gnu.org/licenses/gpl.html
50
49
 
51
50
  ruby-xen
52
- Copyright (C) 2008 Mike Bailey and Nick Markfleet
51
+ Copyright (C) 2008 Mike Bailey and Nick Marfleet
53
52
 
54
53
  This program is free software; you can redistribute it and/or
55
54
  modify it under the terms of the GNU General Public License
data/Rakefile CHANGED
@@ -1,12 +1,12 @@
1
1
  # -*- ruby -*-
2
2
 
3
- require 'rubygems'
4
- require 'hoe'
5
- require './lib/ruby-xen.rb'
6
-
7
- Hoe.new('ruby-xen', RubyXen::VERSION) do |p|
8
- # p.rubyforge_name = 'ruby-xenx' # if different than lowercase project name
9
- p.developer('Mike Bailey', 'mike@bailey.net.au')
10
- end
3
+ # require 'rubygems'
4
+ # require 'hoe'
5
+ # require './lib/ruby-xen.rb'
6
+ #
7
+ # Hoe.new('ruby-xen', Xen::VERSION) do |p|
8
+ # # p.rubyforge_name = 'ruby-xenx' # if different than lowercase project name
9
+ # p.developer('Mike Bailey', 'mike@bailey.net.au')
10
+ # end
11
11
 
12
12
  # vim: syntax=Ruby
data/lib/ruby-xen.rb CHANGED
@@ -23,18 +23,24 @@ module Xen
23
23
  # the object expires.
24
24
  INSTANCE_OBJECT_LIFETIME = 1
25
25
 
26
- # DRY up some classes (children of Domain) with some module funkiness.
26
+ TEMPLATE_DIR = File.expand_path(File.dirname(__FILE__) + '/../lib/templates')
27
+
28
+ # Extension for Xen domU config files
29
+ CONFIG_FILE_EXTENSION = '.cfg'
30
+
31
+ # DRY up some classes (children of Slice) with some module funkiness.
27
32
  module Parentable
28
- # Returns the parent Domain object (d) for a sub-object.
33
+ # Returns the parent Slice object (d) for a sub-object.
29
34
  # We ensure d.instance.object_id == self.object_id
30
35
  #
31
36
  # ==== Example
32
37
  # i = Xen::Instance.all[2]
33
- # d = i.domain
34
- # # i.object_id == d.instance.object_id
38
+ # s = i.slice
39
+ # i.object_id == s.instance.object_id # true
35
40
  #
36
- def domain
37
- d = Xen::Domain.new(name)
41
+ def slice
42
+ d = Xen::Slice.new(name)
43
+ # Insert the current object into the newly created Slice's attributes
38
44
  d.instance_variable_set("@#{self.class.to_s.sub('Xen::','').downcase}", self)
39
45
  d
40
46
  end
@@ -44,7 +50,7 @@ end
44
50
  require "#{File.dirname(__FILE__)}/xen/backup"
45
51
  require "#{File.dirname(__FILE__)}/xen/command"
46
52
  require "#{File.dirname(__FILE__)}/xen/config"
47
- require "#{File.dirname(__FILE__)}/xen/domain"
53
+ require "#{File.dirname(__FILE__)}/xen/slice"
48
54
  require "#{File.dirname(__FILE__)}/xen/host"
49
55
  require "#{File.dirname(__FILE__)}/xen/image"
50
56
  require "#{File.dirname(__FILE__)}/xen/instance"
@@ -0,0 +1,40 @@
1
+ #
2
+ # Configuration file for the Xen instance <%= name %>, created
3
+ # by ruby-xen on <%= Time.now %>.
4
+ #
5
+
6
+ #
7
+ # Kernel + memory size
8
+ #
9
+ kernel = '<%= kernel %>'
10
+ ramdisk = '<%= ramdisk %>'
11
+ memory = '<%= memory %>'
12
+
13
+ #
14
+ # Disk device(s).
15
+ #
16
+ root = '<%= root %>'
17
+ disk = [
18
+ '<%= Array(vbds).collect{|d| d.to_str}.join("',\n\t'") %>'
19
+ ]
20
+
21
+ #
22
+ # Hostname
23
+ #
24
+ name = '<%= name %>'
25
+
26
+ #
27
+ # Networking
28
+ #
29
+ vif = [
30
+ '<%= Array(vifs).collect{|v| v.to_str}.join("',\n\t'") %>'
31
+ ]
32
+
33
+ #
34
+ # Behaviour
35
+ #
36
+ on_poweroff = '<%= on_poweroff %>'
37
+ on_reboot = '<%= on_reboot %>'
38
+ on_crash = '<%= on_crash %>'
39
+
40
+ extra = '<%= extra %>'
data/lib/xen/command.rb CHANGED
@@ -1,8 +1,30 @@
1
1
  class Xen::Command
2
- def self.xm_list
3
- `xm list`
2
+ # def self.xm_list
3
+ # raw = `xm list`.scan(/(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)/)
4
+ # headers = raw.delete_at(0)
5
+ # raw.map do |row|
6
+ # headers.enum_with_index.inject({}) { |m, (head, i)| m[head] = row[i]; m }
7
+ # end
8
+ # end
9
+
10
+ def self.detailed_instance_list(name='')
11
+ raw_entries = `xm list --long #{name}`.split(/\n\(domain/)
12
+ raw_entries.collect do |entry|
13
+ attributes = entry.scan(/\((name|domid|memory|vcpus|state|cpu_time|start_time) (.*)\)/)
14
+ attributes.inject({}) { |m, (key, val)| m[key.to_sym] = val; m }
15
+ end
4
16
  end
17
+
18
+ def self.create(config_file)
19
+ `xm create #{config_file}`
20
+ end
21
+
22
+ def self.shutdown(name, blocking=false)
23
+ `xm shutdown #{'-w' if blocking} #{name}`
24
+ end
25
+
5
26
  def self.xm_info
6
- `xm info`
7
- end
8
- end
27
+ result = `xm info`
28
+ result.scan(/(\S+)\s*:\s*([^\n]+)/).inject({}){ |m, (i,j)| m[i.to_sym] = j; m }
29
+ end
30
+ end
data/lib/xen/config.rb CHANGED
@@ -1,7 +1,9 @@
1
+ require 'erb'
2
+
1
3
  # The Xen config files on disk
2
4
  class Xen::Config
3
5
  include Xen::Parentable
4
- attr_accessor :name, :kernel, :ramdisk, :memory, :root, :disk, :vif, :on_poweroff, :on_reboot, :on_crash, :extra
6
+ attr_accessor :name, :kernel, :ramdisk, :memory, :root, :vbds, :vifs, :on_poweroff, :on_reboot, :on_crash, :extra
5
7
 
6
8
  def initialize(*args)
7
9
  options = args.extract_options!
@@ -10,8 +12,8 @@ class Xen::Config
10
12
  @ramdisk = options[:ramdisk]
11
13
  @memory = options[:memory]
12
14
  @root = options[:root]
13
- @disk = options[:disk]
14
- @vif = options[:vif]
15
+ @vbds = options[:vbds]
16
+ @vifs = options[:vifs]
15
17
  @on_poweroff = options[:on_poweroff]
16
18
  @on_reboot = options[:on_reboot]
17
19
  @on_crash = options[:on_crash]
@@ -27,7 +29,7 @@ class Xen::Config
27
29
  end
28
30
 
29
31
  def self.all
30
- config_files = Dir.glob("#{Xen::XEN_DOMU_CONFIG_DIR}/*.cfg")
32
+ config_files = Dir.glob("#{Xen::XEN_DOMU_CONFIG_DIR}/*#{Xen::CONFIG_FILE_EXTENSION}")
31
33
  config_files.collect do |filename|
32
34
  create_from_config_file(File.read(filename))
33
35
  end
@@ -35,18 +37,103 @@ class Xen::Config
35
37
 
36
38
  def self.find_by_name(name)
37
39
  return new('Domain-0') if name == 'Domain-0'
38
- filename = "#{Xen::XEN_DOMU_CONFIG_DIR}/#{name}.cfg"
40
+ filename = "#{Xen::XEN_DOMU_CONFIG_DIR}/#{name}#{Xen::CONFIG_FILE_EXTENSION}"
39
41
  create_from_config_file(File.read(filename))
40
42
  end
43
+
44
+ def config_file
45
+ "#{Xen::XEN_DOMU_CONFIG_DIR}/#{name}#{Xen::CONFIG_FILE_EXTENSION}"
46
+ end
47
+
48
+ def auto_file
49
+ "#{Xen::XEN_DOMU_CONFIG_DIR}/auto/#{name}#{Xen::CONFIG_FILE_EXTENSION}"
50
+ end
51
+
52
+ def updated_at
53
+ File.mtime(config_file)
54
+ end
55
+
56
+ # Set to true|false to enable|disable autostart of slice
57
+ def auto=(value)
58
+ filename = File.basename(config_file)
59
+ if value == true
60
+ File.symlink("../#{filename}", auto_file)
61
+ else
62
+ File.unlink(auto_file)
63
+ end
64
+ end
65
+
66
+ # Returns true|false depending on whether slice is set to start automatically
67
+ def auto
68
+ File.symlink?(auto_file) && File.expand_path(File.readlink(auto_file), File.dirname(auto_file)) == config_file
69
+ end
41
70
 
42
71
  def self.create_from_config_file(config)
43
72
  name, kernel, ramdisk, memory, root, disk, vif, on_poweroff, on_reboot, on_crash, extra = nil
44
73
  eval(config)
45
- new(name, :disk => disk, :kernel => kernel, :ramdisk => ramdisk, :memory => memory, :root => root, :disk => disk, :vif => vif, :on_poweroff => on_poweroff, :on_reboot => on_reboot, :on_crash => on_crash, :extra => extra)
74
+ vifs = Array(vif).collect { |v| Xen::Vif.from_str(v) }
75
+ vbds = Array(disk).collect { |d| Xen::Vbd.from_str(d) }
76
+ new(name, :disk => disk, :kernel => kernel, :ramdisk => ramdisk, :memory => memory, :root => root, :vbds => vbds, :vifs => vifs, :on_poweroff => on_poweroff, :on_reboot => on_reboot, :on_crash => on_crash, :extra => extra)
46
77
  end
47
78
 
48
79
  def save
49
- puts "I saved the config!"
80
+ template = ERB.new IO.read(Xen::TEMPLATE_DIR + '/domu.cfg.erb')
81
+ File.open(config_file, 'w'){ |f| f.write template.result(binding) }
50
82
  end
51
83
 
52
- end
84
+ end
85
+
86
+
87
+ # Virtual Network Interface
88
+ #
89
+ # http://wiki.xensource.com/xenwiki/XenNetworking
90
+ #
91
+ class Xen::Vif
92
+ attr_accessor :ip, :mac, :bridge, :vifname
93
+ def initialize(*args)
94
+ options = args.extract_options!
95
+ @ip = options[:ip]
96
+ @mac = options[:mac]
97
+ @bridge = options[:bridge]
98
+ @vifname = options[:vifname]
99
+ end
100
+
101
+ def self.from_str(value)
102
+ options = value.scan(/(\w+)=([^,]+)/).inject({}){ |m, (k, v)| m[k.to_sym] = v; m }
103
+ new(options)
104
+ end
105
+
106
+ def to_str
107
+ %w(ip mac bridge vifname).collect { |key|
108
+ "#{key}=#{instance_variable_get('@' + key)}" if !instance_variable_get('@'+key).nil?
109
+ }.compact.join(',')
110
+ end
111
+ end
112
+
113
+
114
+ # Virtual Network Interface
115
+ #
116
+ # http://wiki.xensource.com/xenwiki/XenStorage
117
+ #
118
+ # == Example
119
+ #
120
+ # disk = [ 'phy:xendisks/example-disk,sda1,w',
121
+ # 'phy:xendisks/example-swap,sda2,w',
122
+ # 'phy:assets/example-assets,sdb1,w' ]
123
+ class Xen::Vbd
124
+ attr_accessor :dom0, :domu, :mode
125
+ def initialize(dom0, domu, mode='w')
126
+ @dom0, @domu, @mode = dom0, domu, mode
127
+ end
128
+
129
+ def self.from_str(value)
130
+ dom0, domu, mode = value.split(',')
131
+ new(dom0, domu, mode)
132
+ end
133
+
134
+ def to_str
135
+ "#{dom0},#{domu},#{mode}"
136
+ end
137
+ end
138
+
139
+
data/lib/xen/host.rb CHANGED
@@ -1,10 +1,9 @@
1
1
  class Xen::Host
2
2
  attr_reader :host, :machine, :total_memory, :free_memory
3
-
3
+
4
4
  def initialize
5
- result = Xen:Command.xm_info
6
- result.scan(/(\S+)\s*:\s*([^\n]+)/).each do |i,j|
5
+ Xen::Command.xm_info.each do |i,j|
7
6
  instance_variable_set("@#{i}", j)
8
7
  end
9
8
  end
10
- end
9
+ end
data/lib/xen/instance.rb CHANGED
@@ -9,7 +9,7 @@ class Xen::Instance
9
9
  @cpu_time = options[:cpu_time]
10
10
  @vcpus = options[:vcpus]
11
11
  @state = options[:state]
12
- @start_time = options[:start_time]
12
+ @start_time = Time.at(options[:start_time].to_f) if options[:start_time]
13
13
  @object_expires = Time.now + Xen::INSTANCE_OBJECT_LIFETIME
14
14
  end
15
15
 
@@ -22,37 +22,25 @@ class Xen::Instance
22
22
  end
23
23
 
24
24
  def self.all
25
- result = Xen::Command.xm_list
26
- # XXX check for failed command
27
- result_array = result.split("\n")
28
- result_array.shift
29
- result_array.collect do |domain|
30
- name, domid, memory, vcpus, state, cpu_time = domain.scan(/[^ ,]+/)
31
- new(name, :domid => domid, :memory => memory, :cpu_time => cpu_time)
25
+ Xen::Command.detailed_instance_list.collect do |instance|
26
+ new(name, instance)
32
27
  end
33
28
  end
34
29
 
35
30
  def self.find_by_name(name)
36
- all.detect{|domain| domain.name == name.to_s }
31
+ Xen::Command.detailed_instance_list(name).each do |instance|
32
+ return new(name, instance)
33
+ end
34
+ return false
37
35
  end
38
36
 
39
- # XXX Rails version - we need some error checking!
40
- #
41
- # def self.find_by_name(name, options)
42
- # if result = find_every(options)
43
- # result.detect{ |domain| domain.name == name }
44
- # else
45
- # raise RecordNotFound, "Couldn't find domain with name=#{name}"
46
- # end
47
- # end
48
-
49
37
  def self.create(name)
50
- output = `xm create #{name}.cfg`
38
+ output = Xen::Command.create(name.to_s + Xen::CONFIG_FILE_EXTENSION)
51
39
  $? == 0 ? true : false
52
40
  end
53
41
 
54
42
  def self.shutdown(name)
55
- output = `xm shutdown #{name}`
43
+ output = Xen::Command.shutdown(name)
56
44
  $? == 0 ? true : false
57
45
  end
58
46
 
@@ -65,11 +53,6 @@ class Xen::Instance
65
53
  start_time ? Time.now - start_time : nil
66
54
  end
67
55
 
68
- def running?
69
- output = `xm list #{name}`
70
- $? == 0 ? true : false
71
- end
72
-
73
56
  def reboot
74
57
  `xm reboot #{name}`
75
58
  $? == 0 ? true : false
@@ -1,4 +1,4 @@
1
- class Xen::Domain
1
+ class Xen::Slice
2
2
  attr_accessor :name, :image, :config
3
3
 
4
4
  def initialize(name)
@@ -19,9 +19,9 @@ class Xen::Domain
19
19
  def self.find(*args)
20
20
  options = args.extract_options!
21
21
  case args.first
22
- when :all then Xen::Config.find(:all, options).collect { |config| config.domain }
23
- when :running then Xen::Instance.find(:all, options).collect { |instance| instance.domain }
24
- # Retrieve a Domain by name
22
+ when :all then Xen::Config.find(:all, options).collect { |config| config.slice }
23
+ when :running then Xen::Instance.find(:all, options).collect { |instance| instance.slice }
24
+ # Retrieve a Slice by name
25
25
  else Xen::Config.find_by_name(args.first) && self.new(args.first)
26
26
  end
27
27
  end
@@ -30,6 +30,10 @@ class Xen::Domain
30
30
  self.find(:all, options)
31
31
  end
32
32
 
33
+ def state
34
+ self.instance ? :running : :stopped
35
+ end
36
+
33
37
  def running?
34
38
  self.instance ? true : false
35
39
  end
@@ -44,4 +48,8 @@ class Xen::Domain
44
48
  @instance = Xen::Instance.find(@name)
45
49
  end
46
50
 
51
+ def config_newer_than_instance?
52
+ instance && config.updated_at > instance.start_time
53
+ end
54
+
47
55
  end
@@ -0,0 +1,3 @@
1
+ require '../lib/ruby-xen'
2
+ c = Xen::Config.new
3
+ c.save
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mbailey-ruby-xen
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Bailey
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2008-09-08 00:00:00 -07:00
13
+ date: 2008-09-11 00:00:00 -07:00
14
14
  default_executable:
15
15
  dependencies: []
16
16
 
@@ -35,10 +35,11 @@ files:
35
35
  - lib/xen/backup.rb
36
36
  - lib/xen/command.rb
37
37
  - lib/xen/config.rb
38
- - lib/xen/domain.rb
38
+ - lib/xen/slice.rb
39
39
  - lib/xen/host.rb
40
40
  - lib/xen/image.rb
41
41
  - lib/xen/instance.rb
42
+ - lib/templates/domu.cfg.erb
42
43
  has_rdoc: true
43
44
  homepage: http://github.com/schacon/grit
44
45
  post_install_message: