mbailey-ruby-xen 0.0.1 → 0.0.2

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