ruby-xen 0.0.1 → 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.
@@ -1,3 +1,13 @@
1
+ === 0.0.3 / 2008-09-21
2
+
3
+ * fleshed out :backup class
4
+ * Xen::Commands are now easily called by backgroundjob (bj)
5
+
6
+ === 0.0.2 / 2008-09-11
7
+
8
+ * Broke out classes into separate files
9
+ * Added rspec outline
10
+
1
11
  === 0.0.1 / 2008-09-08
2
12
 
3
13
  * Initial import
@@ -4,5 +4,13 @@ README.rdoc
4
4
  Rakefile
5
5
  bin/ruby-xen
6
6
  lib/ruby-xen.rb
7
- test/test-ruby-xen.rb
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
@@ -1,6 +1,9 @@
1
1
  = ruby-xen
2
2
 
3
- * FIX (url)
3
+ # Warning! Not ready yet - project started Sep 2008
4
+
5
+ http://github.com/mbailey/ruby-xen
6
+
4
7
 
5
8
  == DESCRIPTION:
6
9
 
@@ -19,11 +22,20 @@ ruby-xen can also be used by ruby code or from irb.
19
22
 
20
23
  == SYNOPSIS:
21
24
 
22
- FIX (code sample of usage)
25
+ require 'rubygems'
26
+ require 'ruby-xen'
27
+
28
+ slice = Xen::Slice.find(:example)
29
+ slice.running? # true
30
+ slice.stop
31
+ slice.running? # false
32
+ slice.start
33
+ slice.running? # true
23
34
 
24
35
  == REQUIREMENTS:
25
36
 
26
- xen-tools (http://www.xen-tools.org/software/xen-tools/)
37
+ ruby-xen must be run as root as it uses Xen's 'xm' command.
38
+ xen-tools must be installed (http://www.xen-tools.org/software/xen-tools/)
27
39
 
28
40
  == INSTALL:
29
41
 
@@ -36,7 +48,7 @@ or open source applications. More details found here:
36
48
  http://www.gnu.org/licenses/gpl.html
37
49
 
38
50
  ruby-xen
39
- Copyright (C) 2008 Mike Bailey and Nick Markfleet
51
+ Copyright (C) 2008 Mike Bailey and Nick Marfleet
40
52
 
41
53
  This program is free software; you can redistribute it and/or
42
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
@@ -1,4 +1,80 @@
1
- class RubyXen
2
- VERSION = '1.0.0'
1
+ module Xen
2
+ # General configuration for ruby-xen
3
+
4
+ # Location of Xen config files
5
+ XEN_DOMU_CONFIG_DIR = '/etc/xen'
6
+ # XEN_DOMU_CONFIG_DIR = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '/spec/fixtures/xen_domu_configs'))
7
+
8
+ # We don't want out library to hit Xen too often (premature optimization perhaps?)
9
+ # so we keep information about Xen instances in an object. Specify how long before
10
+ # the object expires.
11
+ INSTANCE_OBJECT_LIFETIME = 5 # seconds
12
+
13
+ # General location for config file templates
14
+ TEMPLATE_DIR = File.expand_path(File.dirname(__FILE__) + '/../lib/templates')
15
+
16
+ # Extension for Xen domU config files
17
+ CONFIG_FILE_EXTENSION = '.cfg'
18
+
19
+ # Directory for backups of system images
20
+ BACKUP_DIR='/var/xen_images'
21
+
22
+ # FIle extension for backups
23
+ BACKUP_FILE_EXT = '.tar'
3
24
  end
4
- require "#{File.dirname(__FILE__)}/ruby-xen/domain"
25
+
26
+ class Array #:nodoc:
27
+ # Extracts options from a set of arguments. Removes and returns the last
28
+ # element in the array if it's a hash, otherwise returns a blank hash.
29
+ #
30
+ # def options(*args)
31
+ # args.extract_options!
32
+ # end
33
+ #
34
+ # options(1, 2) # => {}
35
+ # options(1, 2, :a => :b) # => {:a=>:b}
36
+ def extract_options!
37
+ last.is_a?(::Hash) ? pop : {}
38
+ end
39
+ end
40
+
41
+ class Hash #:nodoc:
42
+ # Converts a Hash into an array of key=val formatted strings
43
+ #
44
+ # puts { :nics => 2, :vcpus => 1, :memory => 64 }.to_args
45
+ #
46
+ # produces:
47
+ #
48
+ # ["memory=64", "nics=2", "vcpus=1"]
49
+ def to_args
50
+ collect{|k,v| "#{k}=#{v}"}
51
+ end
52
+ end
53
+
54
+ module Xen
55
+ # DRY up some classes (children of Slice) with some module funkiness.
56
+ module Parentable
57
+ # Returns the parent Slice object (d) for a sub-object.
58
+ # We ensure d.instance.object_id == self.object_id
59
+ #
60
+ # ==== Example
61
+ # i = Xen::Instance.all[2]
62
+ # s = i.slice
63
+ # i.object_id == s.instance.object_id # true
64
+ #
65
+ def slice
66
+ d = Xen::Slice.new(name)
67
+ # Insert the current object into the newly created Slice's attributes
68
+ d.instance_variable_set("@#{self.class.to_s.sub('Xen::','').downcase}", self)
69
+ d
70
+ end
71
+ end
72
+ end
73
+
74
+ require "#{File.dirname(__FILE__)}/xen/backup"
75
+ require "#{File.dirname(__FILE__)}/xen/command"
76
+ require "#{File.dirname(__FILE__)}/xen/config"
77
+ require "#{File.dirname(__FILE__)}/xen/slice"
78
+ require "#{File.dirname(__FILE__)}/xen/host"
79
+ require "#{File.dirname(__FILE__)}/xen/image"
80
+ 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 %>'
@@ -0,0 +1,42 @@
1
+ class Xen::Backup
2
+ include Xen::Parentable
3
+
4
+ attr_accessor :name, :version
5
+
6
+ def self.create(*args)
7
+ options = args.extract_options!
8
+ name = args.first
9
+ version = options[:version] || generate_version
10
+ Xen::Command.backup_slice(name, version)
11
+ new(name, version)
12
+ end
13
+
14
+ def initialize(*args)
15
+ options = args.extract_options!
16
+ @name = args.first
17
+ @version = options[:version]
18
+ end
19
+
20
+ def self.find(*args)
21
+ # return all
22
+ slice = args.first
23
+ Dir.glob("#{Xen::BACKUP_DIR}/*-*#{Xen::BACKUP_FILE_EXT}").collect { |file|
24
+ if match = File.basename(file, Xen::BACKUP_FILE_EXT).match(/(#{ slice || '.*' })-(.*)/)
25
+ new(match[1], :version => match[2])
26
+ end
27
+ }.compact
28
+ end
29
+
30
+ def filename
31
+ "#{@name}-#{@version}#{Xen::BACKUP_FILE_EXT}"
32
+ end
33
+
34
+ def fullpath
35
+ File.join(Xen::BACKUP_DIR, filename)
36
+ end
37
+
38
+ def size
39
+ File.size(fullpath)
40
+ end
41
+
42
+ end
@@ -0,0 +1,73 @@
1
+ class Xen::Command
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
+ # Return the size of a logical volume in gigabytes
11
+ def self.lv_size(vg_name, lv_name)
12
+ cmd = "lvs --noheadings --nosuffix --options lv_size --units g #{vg_name}/#{lv_name}"
13
+ `#{cmd}`.strip
14
+ end
15
+
16
+ # Return list of logical volumes
17
+ def self.lv_list(vg_name)
18
+ cmd = "lvs --noheadings --nosuffix --options vg_name,lv_name,lv_size --units g #{vg_name}"
19
+ raw = `#{cmd}`
20
+ raw.scan(/(\S+)\s+(\S+)\s+(\S+)/).collect{ |vg_name, lv_name, size|
21
+ {
22
+ :vg => vg_name,
23
+ :name => lv_name,
24
+ :size => size
25
+ }
26
+ }
27
+ end
28
+
29
+ def self.vg_list
30
+ cmd = "vgs --noheadings --units g --nosuffix --options vg_name,vg_size,vg_free,lv_count,max_lv"
31
+ raw = `#{cmd}`
32
+ raw.scan(/(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)/).collect{ |vg_name, vg_size, vg_free, lv_count, max_lv|
33
+ {
34
+ :name => vg_name,
35
+ :size => vg_size,
36
+ :free => vg_free,
37
+ :lv_count => lv_count,
38
+ :max_lv => max_lv
39
+ }
40
+ }
41
+ end
42
+
43
+ def self.detailed_instance_list(name='')
44
+ cmd = "xm list --long #{name}"
45
+ raw_entries = `#{cmd}`.split(/\n\(domain/)
46
+ raw_entries.collect do |entry|
47
+ attributes = entry.scan(/\((name|domid|memory|vcpus|state|cpu_time|start_time) (.*)\)/)
48
+ attributes.inject({}) { |m, (key, val)| m[key.to_sym] = val; m }
49
+ end
50
+ end
51
+
52
+ def self.start_instance(config_file)
53
+ `xm create #{config_file}`
54
+ end
55
+
56
+ def self.shutdown_instance(name, blocking=false)
57
+ `xm shutdown #{'-w' if blocking} #{name}`
58
+ end
59
+
60
+ # Xen::Command.create_image('memory=512', :size => '10Gb')
61
+ # => "xm-create-image memory=512 size=10Gb"
62
+ #
63
+ def self.create_image(*args)
64
+ options = args.extract_options!
65
+ cmd = "xm-create-image #{args.concat(options.to_args).join(' ')}"
66
+ `cmd`
67
+ end
68
+
69
+ def self.xm_info
70
+ result = `xm info`
71
+ result.scan(/(\S+)\s*:\s*([^\n]+)/).inject({}){ |m, (i,j)| m[i.to_sym] = j; m }
72
+ end
73
+ end
@@ -0,0 +1,146 @@
1
+ require 'erb'
2
+
3
+ class Xen::Config
4
+ # The config files for each Xen domU
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)) if File.exists?(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 Block Device
115
+ #
116
+ # We're only supporting Logical Volumes. No loopback devices.
117
+ #
118
+ # http://wiki.xensource.com/xenwiki/XenStorage
119
+ #
120
+ # == Example
121
+ #
122
+ # disk = [ 'phy:xendisks/example-disk,sda1,w',
123
+ # 'phy:xendisks/example-swap,sda2,w',
124
+ # 'phy:assets/example-assets,sdb1,w' ]
125
+ class Xen::Vbd
126
+ attr_accessor :name, :vg, :domu, :mode
127
+ def initialize(name, vg, domu, mode='w')
128
+ @name, @vg, @domu, @mode = name, vg, domu, mode
129
+ end
130
+
131
+ def self.from_str(value)
132
+ dom0, domu, mode = value.split(',')
133
+ vg, name = dom0.split(/[\/:]/).slice(-2, 2)
134
+ new(name, vg, domu, mode)
135
+ end
136
+
137
+ def size
138
+ Xen::Command.lv_size(@vg, @name)
139
+ end
140
+
141
+ def to_str
142
+ "phy:#{vg}/#{lv},#{domu},#{mode}"
143
+ end
144
+ end
145
+
146
+
@@ -0,0 +1,10 @@
1
+ class Xen::Host
2
+ attr_reader :host, :machine, :total_memory, :free_memory
3
+
4
+ def initialize
5
+ Xen::Command.xm_info.each do |i,j|
6
+ instance_variable_set("@#{i}", j)
7
+ end
8
+ end
9
+
10
+ end
@@ -0,0 +1,12 @@
1
+ # class Xen::Image
2
+ # include Xen::Parentable
3
+ # attr_accessor :name
4
+ #
5
+ # def initialize(name)
6
+ # @name = name
7
+ # end
8
+ #
9
+ # def self.find(name)
10
+ # new name
11
+ # end
12
+ # end
@@ -0,0 +1,66 @@
1
+ class Xen::Instance
2
+ include Xen::Parentable
3
+ attr_reader :name, :domid, :memory, :cpu_time, :vcpus, :state, :start_time
4
+
5
+ def initialize(name, options={})
6
+ @name = name
7
+ @domid = options[:domid]
8
+ @memory = options[:memory]
9
+ @cpu_time = options[:cpu_time]
10
+ @vcpus = options[:vcpus]
11
+ @state = options[:state]
12
+ @start_time = Time.at(options[:start_time].to_f) if options[:start_time]
13
+ end
14
+
15
+ def self.find(*args)
16
+ options = args.extract_options!
17
+ case args.first
18
+ when :all then all
19
+ else find_by_name(args.first)
20
+ end
21
+ end
22
+
23
+ def self.all
24
+ Xen::Command.detailed_instance_list.collect do |instance|
25
+ new(name, instance)
26
+ end
27
+ end
28
+
29
+ def self.find_by_name(name)
30
+ Xen::Command.detailed_instance_list(name).each do |instance|
31
+ return new(name, instance)
32
+ end
33
+ return false
34
+ end
35
+
36
+ def self.create(name)
37
+ output = Xen::Command.start_instance(name.to_s + Xen::CONFIG_FILE_EXTENSION)
38
+ $? == 0 ? true : false
39
+ end
40
+
41
+ def self.shutdown(name)
42
+ output = Xen::Command.shutdown_instance(name)
43
+ $? == 0 ? true : false
44
+ end
45
+
46
+ # A convenience wrapper for <tt>find(:dom0)</tt>.</tt>.
47
+ def self.dom0(*args)
48
+ find_by_name(:dom0)
49
+ end
50
+
51
+ def uptime
52
+ start_time ? Time.now - start_time : nil
53
+ end
54
+
55
+ def reboot
56
+ `xm reboot #{name}`
57
+ $? == 0 ? true : false
58
+ end
59
+
60
+ def destroy
61
+ end
62
+
63
+ def pause
64
+ end
65
+
66
+ end
@@ -0,0 +1,80 @@
1
+ class Xen::Slice
2
+ attr_accessor :name, :image, :config, :backups
3
+
4
+ def self.find(*args)
5
+ options = args.extract_options!
6
+ case args.first
7
+ when :all then Xen::Config.find(:all, options).collect { |config| config.slice }
8
+ when :running then Xen::Instance.find(:all, options).collect { |instance| instance.slice }
9
+ # Retrieve a Slice by name
10
+ else Xen::Config.find_by_name(args.first) && self.new(args.first)
11
+ end
12
+ end
13
+
14
+ def self.all(options={})
15
+ self.find(:all, options)
16
+ end
17
+
18
+ def initialize(*args)
19
+ options = args.extract_options! # remove trailing hash (not used)
20
+ @name = args.first
21
+ @config = options[:config]
22
+ @instance = options[:instance]
23
+ @instance_cache_expires = Time.now
24
+ @backups = Array(options[:backups])
25
+ end
26
+
27
+ def create_image(args)
28
+ args = hash.collect{|k,v| "#{k}=#{v}"}
29
+ Xen::Command.create_image
30
+ end
31
+
32
+ # Cache Xen instance info to reduce system calls to xm command.
33
+ # It still needs to be checked regularly as operations like shutdown
34
+ # and create can take a while.
35
+ def instance
36
+ if @instance_cache_expires > Time.now
37
+ @instance
38
+ else
39
+ @instance_cache_expires = Time.now + Xen::INSTANCE_OBJECT_LIFETIME
40
+ @instance = Xen::Instance.find(@name) if @name
41
+ end
42
+ end
43
+
44
+ # XXX We're assuming other processes aren't going to edit configs
45
+ # This is reasonable in simple cases.
46
+ def config
47
+ @config ||= Xen::Config.find(name) if @name
48
+ end
49
+
50
+ def backups
51
+ Xen::Backup.find(name)
52
+ end
53
+
54
+ def state
55
+ self.instance ? :running : :stopped
56
+ end
57
+
58
+ def running?
59
+ self.instance ? true : false
60
+ end
61
+
62
+ def start
63
+ Xen::Instance.create(@name)
64
+ @instance = Xen::Instance.find(@name)
65
+ end
66
+
67
+ def stop
68
+ Xen::Instance.shutdown(@name)
69
+ @instance = Xen::Instance.find(@name)
70
+ end
71
+
72
+ def config_newer_than_instance?
73
+ instance && config.updated_at > instance.start_time
74
+ end
75
+
76
+ def save
77
+ @config.save
78
+ end
79
+
80
+ 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: ruby-xen
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.3
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 +10:00
13
+ date: 2008-09-21 00:00:00 +10:00
14
14
  default_executable:
15
15
  dependencies: []
16
16
 
@@ -32,13 +32,20 @@ files:
32
32
  - bin/ruby-xen
33
33
  - lib/ruby-xen.rb
34
34
  - test/test_ruby-xen.rb
35
- - lib/ruby-xen/domain.rb
35
+ - lib/xen/backup.rb
36
+ - lib/xen/command.rb
37
+ - lib/xen/config.rb
38
+ - lib/xen/host.rb
39
+ - lib/xen/image.rb
40
+ - lib/xen/instance.rb
41
+ - lib/xen/slice.rb
42
+ - lib/templates/domu.cfg.erb
36
43
  has_rdoc: true
37
- homepage: http://github.com/schacon/grit
44
+ homepage: http://github.com/mbailey/ruby-xen
38
45
  post_install_message:
39
46
  rdoc_options:
40
47
  - --main
41
- - README.txt
48
+ - README.rdoc
42
49
  require_paths:
43
50
  - lib
44
51
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -1,229 +0,0 @@
1
- class Array #:nodoc:
2
- # Extracts options from a set of arguments. Removes and returns the last
3
- # element in the array if it's a hash, otherwise returns a blank hash.
4
- #
5
- # def options(*args)
6
- # args.extract_options!
7
- # end
8
- #
9
- # options(1, 2) # => {}
10
- # options(1, 2, :a => :b) # => {:a=>:b}
11
- def extract_options!
12
- last.is_a?(::Hash) ? pop : {}
13
- end
14
- end
15
-
16
- module Xen
17
- class Host
18
-
19
- attr_reader :host, :machine, :total_memory, :free_memory
20
- def initialize
21
- result = `xm info`
22
- result.scan(/(\S+)\s*:\s*([^\n]+)/).each do |i,j|
23
- instance_variable_set("@#{i}", j)
24
- end
25
- end
26
-
27
- end
28
-
29
-
30
- class Domain
31
-
32
- attr_accessor :name, :image, :config, :instance
33
-
34
- def initialize(name)
35
- @name = name
36
- @config = Xen::Config.find(name)
37
- @instance = Xen::Instance.find(name)
38
- @image = Xen::Image.find(name)
39
- end
40
-
41
- def self.find(*args)
42
- options = args.extract_options!
43
- case args.first
44
- when :all then Xen::Config.find(:all, options).collect { |config| Xen::Domain.new(config.name) }
45
- when :running then Xen::Instance.find(:all, options).collect { |instance| Xen::Domain.new(instance.name) }
46
- # Retrieve a Domain by name
47
- else Xen::Config.find_by_name(args.first) && self.new(args.first)
48
- end
49
- end
50
-
51
- def running?
52
- @instance
53
- end
54
-
55
- end
56
-
57
-
58
- class Config
59
-
60
- attr_reader :name, :memory, :ip
61
-
62
- def initialize(*args)
63
- options = args.extract_options!
64
- @name = args.first
65
- @memory = options[:memory] || nil
66
- @ip = options[:ip] || nil
67
- end
68
-
69
- def self.find(*args)
70
- options = args.extract_options!
71
- case args.first
72
- when :all then all
73
- else find_by_name(args.first)
74
- end
75
- end
76
-
77
- def self.all
78
- result = `xen-list-images`
79
- configs = result.scan(/Name: (\w+)\nMemory: (\w+)\nIP: (\S+)/)
80
- configs.collect do |config|
81
- name, memory, ip = config
82
- new(name, :memory => memory, :ip => ip)
83
- end
84
- end
85
-
86
- def self.find_by_name(name)
87
- return new('Domain-0') if name == 'Domain-0'
88
- all.detect {|config| puts config; config.name == name.to_s}
89
- end
90
-
91
- end
92
-
93
-
94
- class Image
95
-
96
- attr_accessor :name
97
-
98
- def initialize(name)
99
- @name = name
100
- end
101
-
102
- def self.find(name)
103
- new name
104
- end
105
-
106
- def find_one(name, options)
107
- if result = find_every(options).first
108
- result
109
- else
110
- raise RecordNotFound, "Couldn't find domain with name=#{name}"
111
- end
112
- end
113
- end
114
-
115
-
116
- class Instance
117
-
118
- attr_reader :name, :domid, :memory, :cpu_time, :vcpus, :state, :start_time
119
-
120
- def initialize(name, options={})
121
- @name = name
122
- @domid = options[:domid] || nil
123
- @memory = options[:memory] || nil
124
- @cpu_time = options[:cpu_time] || nil
125
- @vcpus = options[:vcpus] || nil
126
- @state = options[:state] || nil
127
- @start_time = options[:start_time] || nil
128
- end
129
-
130
- def self.find(*args)
131
- options = args.extract_options!
132
- case args.first
133
- when :all then all
134
- else find_by_name(args.first)
135
- end
136
- end
137
-
138
- def self.all
139
- result = `xm list`
140
- # XXX check for failed command
141
- result_array = result.split("\n")
142
- result_array.shift
143
- result_array.collect do |domain|
144
- name, domid, memory, vcpus, state, cpu_time = domain.scan(/[^ ,]+/)
145
- new(name, :domid => domid, :memory => memory, :cpu_time => cpu_time)
146
- end
147
- end
148
-
149
- def self.find_by_name(name)
150
- all.detect{|domain| domain.name == name.to_s }
151
- end
152
-
153
- # XXX Rails version - we need some error checking!
154
- #
155
- # def self.find_by_name(name, options)
156
- # if result = find_every(options)
157
- # result.detect{ |domain| domain.name == name }
158
- # else
159
- # raise RecordNotFound, "Couldn't find domain with name=#{name}"
160
- # end
161
- # end
162
-
163
- # A convenience wrapper for <tt>find(:dom0)</tt>.</tt>.
164
- def dom0(*args)
165
- find_by_name(:dom0)
166
- end
167
-
168
- # This is an alias for find(:all). You can pass in all the same arguments to this method as you can
169
- # to find(:all)
170
- def all(*args)
171
- find(:all, *args)
172
- end
173
-
174
- def uptime
175
- start_time ? Time.now - start_time : nil
176
- end
177
-
178
- def running?
179
- output = `xm list #{name}`
180
- $? == 0 ? true : false
181
- end
182
-
183
- def start
184
- output = `xm create #{name}.cfg`
185
- $? == 0 ? true : false
186
- end
187
-
188
- def shutdown
189
- output = `xm shutdown #{name}`
190
- $? == 0 ? true : false
191
- end
192
-
193
- def reboot
194
- `xm reboot #{name}`
195
- $? == 0 ? true : false
196
- end
197
-
198
- def destroy
199
- end
200
-
201
- def pause
202
- end
203
-
204
- end
205
-
206
- class Backup
207
- end
208
-
209
- # class XenTools
210
- #
211
- # def self.xen_list_images
212
- # puts "returning list of images"
213
- # end
214
- #
215
- # def xen_create_image
216
- # puts "creating image"
217
- # end
218
- #
219
- # def xen_delete_image
220
- # puts "creating image"
221
- # end
222
- #
223
- # def xen_archive_image
224
- # puts "archiving image"
225
- # end
226
- #
227
- # end
228
-
229
- end