mbailey-ruby-xen 0.0.2 → 0.0.3

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/lib/xen/lvm.rb ADDED
@@ -0,0 +1,33 @@
1
+ require 'open4'
2
+
3
+ module Xen
4
+
5
+ class VolumeGroup
6
+
7
+ attr_reader :name, :size
8
+
9
+ def initialize(name, size)
10
+ @name = name
11
+ @size = size
12
+ end
13
+
14
+ def self.find(name=nil)
15
+ name ||= nil
16
+ # XXX deal with not found error
17
+ cmd = "vgs --options=vg_name,vg_size --separator=' ' --noheadings --units=g --nosuffix #{name}"
18
+ output = Xen::Command.run cmd
19
+ result = output.collect { |line|
20
+ name, size = line.strip.split(' ')
21
+ new name, size
22
+ }
23
+ name ? result[0] : result
24
+ end
25
+
26
+ def free
27
+ cmd = "vgs --options=vg_free --separator=' ' --noheadings --units=g --nosuffix #{@name}"
28
+ Xen::Command.run cmd
29
+ end
30
+
31
+ end
32
+
33
+ end
data/lib/xen/slice.rb CHANGED
@@ -1,55 +1,129 @@
1
- class Xen::Slice
2
- attr_accessor :name, :image, :config
1
+ module Xen
2
+ class Slice
3
+ attr_accessor :name, :image, :config_file, :backups
4
+
5
+ def self.find(*args)
6
+ options = args.extract_options!
7
+ case args.first
8
+ when :all then Xen::ConfigFile.find(:all, options).collect { |config_file| new :name => config_file.name }
9
+ when :running then Xen::Instance.find(:all, options).collect { |instance| new :name => instance.name }
10
+ # Retrieve a Slice by name
11
+ else Xen::ConfigFile.find_by_name(args.first) && new(:name => args.first)
12
+ end
13
+ end
14
+
15
+ def self.all(options={})
16
+ self.find(:all, options)
17
+ end
18
+
19
+ def initialize(*args)
20
+ options = args.extract_options!
21
+ @name = options[:name]
22
+ @config_file = options[:config_file]
23
+ @instance = options[:instance]
24
+ @instance_cache_expires = Time.now
25
+ @backups = Array(options[:backups])
26
+ end
3
27
 
4
- def initialize(name)
5
- @name = name
6
- @config = Xen::Config.find(name)
7
- @instance = Xen::Instance.find(name)
8
- @image = Xen::Image.find(name)
9
- end
28
+ def create_image(*args)
29
+ options = args.extract_options!.stringify_keys
30
+
31
+ # Load default values for options that have not been set
32
+ options.reverse_merge! Xen::XenToolsConf.find.to_hash
33
+
34
+ # Set some derived options
35
+ options.reverse_merge! 'hostname' => name # Name host after this slice
36
+ options['dhcp'] = true unless options['ip']
37
+ options['swap'] ||= options['memory'].to_i * 2
38
+ if options['root_pass']
39
+ options['role'] = 'passwd'
40
+ options['role-args'] = options['root_pass']
41
+ end
42
+ unless [nil,''].include?(options['tarball'])
43
+ options['install-method'] = 'tar'
44
+ options['install-source'] = options['tarball']
45
+ options.delete('dist')
46
+ end
47
+
48
+ args = %w(hostname dist memory size
49
+ force boot
50
+ role role-args roledir
51
+ dir lvm mirror
52
+ ip mac netmask broadcast gateway dhcp
53
+ swap
54
+ accounts admins cache config fs image image-dev initrd
55
+ keep kernel modules output install hooks partitions
56
+ passwd tar-cmd extension swap-dev noswap ide arch
57
+ install-method install-source template evms)
58
+ # Remove options that are not in allowed argument list
59
+ options.keys.each { |key| options.delete(key) unless args.include?(key) }
60
+
61
+ Xen::Command.create_image(options)
62
+ end
63
+
64
+ # Cache Xen instance info to reduce system calls to xm command.
65
+ # It still needs to be checked regularly as operations like shutdown
66
+ # and create can take a while.
67
+ def instance
68
+ if @instance_cache_expires > Time.now
69
+ @instance
70
+ else
71
+ @instance_cache_expires = Time.now + Xen::INSTANCE_OBJECT_LIFETIME
72
+ @instance = Xen::Instance.find(@name) if @name
73
+ end
74
+ end
10
75
 
11
- def instance
12
- if @instance && @instance.object_expires > Time.now
13
- @instance
14
- else
15
- @instance = Xen::Instance.find(@name)
76
+ # XXX We're assuming other processes aren't going to edit config_files
77
+ # This is reasonable in simple cases.
78
+ def config_file
79
+ @config_file ||= Xen::ConfigFile.find(name) if @name
16
80
  end
17
- end
18
81
 
19
- def self.find(*args)
20
- options = args.extract_options!
21
- case args.first
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
- else Xen::Config.find_by_name(args.first) && self.new(args.first)
82
+ def backups
83
+ Xen::Backup.find(name)
26
84
  end
27
- end
28
85
 
29
- def all(options={})
30
- self.find(:all, options)
31
- end
86
+ def create_backup(options = {})
87
+ Xen::Backup.create(name, :options)
88
+ end
32
89
 
33
- def state
34
- self.instance ? :running : :stopped
35
- end
90
+ def state
91
+ self.instance ? :running : :stopped
92
+ end
36
93
 
37
- def running?
38
- self.instance ? true : false
39
- end
94
+ def running?
95
+ self.instance ? true : false
96
+ end
40
97
 
41
- def start
42
- Xen::Instance.create(@name)
43
- @instance = Xen::Instance.find(@name)
44
- end
98
+ def start
99
+ Xen::Instance.create(@name)
100
+ @instance = Xen::Instance.find(@name)
101
+ end
45
102
 
46
- def stop
47
- Xen::Instance.shutdown(@name)
48
- @instance = Xen::Instance.find(@name)
49
- end
103
+ def stop
104
+ Xen::Instance.shutdown(@name)
105
+ @instance = Xen::Instance.find(@name)
106
+ end
50
107
 
51
- def config_newer_than_instance?
52
- instance && config.updated_at > instance.start_time
53
- end
108
+ def config_file_newer_than_instance?
109
+ instance && config_file.updated_at > instance.start_time
110
+ end
111
+
112
+ def save
113
+ @config_file.save
114
+ end
115
+
116
+ def root_disk
117
+ config_file.vbds.detect { |vbd| vbd.name == "#{name}-disk" } unless config_file.nil?
118
+ end
119
+
120
+ # Primary IP
121
+ def ip
122
+ config_file.vifs[0].ip
123
+ end
54
124
 
55
- end
125
+ end
126
+ end
127
+
128
+
129
+
@@ -0,0 +1,56 @@
1
+ module Xen
2
+ # puts Xen::XenToolsConf.load.to_hash.inspect
3
+
4
+ class XenToolsConf
5
+
6
+ # XXX underscorize :install-method, install-source, copy_cmd, tar-cmd
7
+ attr_accessor :dir, :lvm, :install__method, :install__source, :copy_cmd,
8
+ :tar_cmd, :debootstrap__cmd, :size, :memory, :swap, :noswap,
9
+ :fs,
10
+ :dist, :image, :gateway,
11
+ :netmask, :broadcast, :dhcp, :cache, :passwd, :accounts,
12
+ :kernel, :initrd, :mirror, :ext3_options, :ext2_options,
13
+ :xfs_options, :reiser_options, :boot, :serial_device,
14
+ :disk_device, :output, :extension
15
+
16
+ def initialize(*args)
17
+ end
18
+
19
+ def self.find(file=nil)
20
+ file ||= Xen::XEN_TOOLS_CONFIG_FILE
21
+ xtc = new # Create a new XenToolsConf object
22
+ xtc.load_from_config_file(File.readlines(file))
23
+ xtc
24
+ end
25
+
26
+ def load_from_config_file(file_contents)
27
+ file_contents.reject! { |line| line.match /^\s*#/ } # Ignore commented out lines
28
+ file_contents.grep(/(.*) = (.*)/).each { |setting|
29
+ setting.scan(/\s*(.+?)\s*=\s*([^#]+)/).each { |match|
30
+ key, val = match
31
+ instance_variable_set("@#{key.strip.underscorize}", val.strip)
32
+ }
33
+ }
34
+ end
35
+
36
+ def to_hash
37
+ self.instance_variables.inject({}) { |m, variable_name|
38
+ m[variable_name.sub('@','').ununderscorize] = instance_variable_get(variable_name); m
39
+ }
40
+ end
41
+
42
+ def to_file
43
+ template = ERB.new(IO.read(File.join(TEMPLATES_BASE, 'xen-tools.conf.erb')))
44
+ template.result(binding)
45
+ end
46
+
47
+ def save(filename=nil)
48
+ filename ||= Xen::XEN_TOOLS_CONFIG_FILE
49
+ File.open(filename, 'w') do |f|
50
+ f.write(to_file)
51
+ end
52
+ # XXX check for errors
53
+ end
54
+
55
+ end
56
+ end
@@ -1,3 +1,3 @@
1
1
  require '../lib/ruby-xen'
2
- c = Xen::Config.new
3
- c.save
2
+ c = Xen::ConfigFile.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.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Bailey
@@ -10,10 +10,27 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2008-09-11 00:00:00 -07:00
13
+ date: 2008-09-21 00:00:00 -07:00
14
14
  default_executable:
15
- dependencies: []
16
-
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: activesupport
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: open4
27
+ version_requirement:
28
+ version_requirements: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: "0"
33
+ version:
17
34
  description: ruby-xen allows you to manage Xen virtual servers via Ruby. It currently wraps the command line tools provided by Xen (xm) as well as Steve Kemps excellent Xen-tools (http://www.xen-tools.org/software/xen-tools/).
18
35
  email: mike@bailey.net.au
19
36
  executables: []
@@ -34,14 +51,16 @@ files:
34
51
  - test/test_ruby-xen.rb
35
52
  - lib/xen/backup.rb
36
53
  - lib/xen/command.rb
37
- - lib/xen/config.rb
38
- - lib/xen/slice.rb
54
+ - lib/xen/config_file.rb
39
55
  - lib/xen/host.rb
40
- - lib/xen/image.rb
41
56
  - lib/xen/instance.rb
57
+ - lib/xen/lvm.rb
58
+ - lib/xen/slice.rb
59
+ - lib/xen/xen_tools_conf.rb
42
60
  - lib/templates/domu.cfg.erb
61
+ - lib/templates/xen-tools.conf.erb
43
62
  has_rdoc: true
44
- homepage: http://github.com/schacon/grit
63
+ homepage: http://github.com/mbailey/ruby-xen
45
64
  post_install_message:
46
65
  rdoc_options:
47
66
  - --main
data/lib/xen/config.rb DELETED
@@ -1,139 +0,0 @@
1
- require 'erb'
2
-
3
- # The Xen config files on disk
4
- class Xen::Config
5
- include Xen::Parentable
6
- attr_accessor :name, :kernel, :ramdisk, :memory, :root, :vbds, :vifs, :on_poweroff, :on_reboot, :on_crash, :extra
7
-
8
- def initialize(*args)
9
- options = args.extract_options!
10
- @name = args.first
11
- @kernel = options[:kernel]
12
- @ramdisk = options[:ramdisk]
13
- @memory = options[:memory]
14
- @root = options[:root]
15
- @vbds = options[:vbds]
16
- @vifs = options[:vifs]
17
- @on_poweroff = options[:on_poweroff]
18
- @on_reboot = options[:on_reboot]
19
- @on_crash = options[:on_crash]
20
- @extra = options[:extra]
21
- end
22
-
23
- def self.find(*args)
24
- options = args.extract_options!
25
- case args.first
26
- when :all then all
27
- else find_by_name(args.first)
28
- end
29
- end
30
-
31
- def self.all
32
- config_files = Dir.glob("#{Xen::XEN_DOMU_CONFIG_DIR}/*#{Xen::CONFIG_FILE_EXTENSION}")
33
- config_files.collect do |filename|
34
- create_from_config_file(File.read(filename))
35
- end
36
- end
37
-
38
- def self.find_by_name(name)
39
- return new('Domain-0') if name == 'Domain-0'
40
- filename = "#{Xen::XEN_DOMU_CONFIG_DIR}/#{name}#{Xen::CONFIG_FILE_EXTENSION}"
41
- create_from_config_file(File.read(filename))
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
70
-
71
- def self.create_from_config_file(config)
72
- name, kernel, ramdisk, memory, root, disk, vif, on_poweroff, on_reboot, on_crash, extra = nil
73
- eval(config)
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)
77
- end
78
-
79
- def save
80
- template = ERB.new IO.read(Xen::TEMPLATE_DIR + '/domu.cfg.erb')
81
- File.open(config_file, 'w'){ |f| f.write template.result(binding) }
82
- end
83
-
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
-