mbailey-ruby-xen 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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
-