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 +5 -0
- data/Manifest.txt +8 -0
- data/README.rdoc +7 -8
- data/Rakefile +8 -8
- data/lib/ruby-xen.rb +13 -7
- data/lib/templates/domu.cfg.erb +40 -0
- data/lib/xen/command.rb +27 -5
- data/lib/xen/config.rb +95 -8
- data/lib/xen/host.rb +3 -4
- data/lib/xen/instance.rb +9 -26
- data/lib/xen/{domain.rb → slice.rb} +12 -4
- data/test/test_ruby-xen.rb +3 -0
- metadata +4 -3
data/History.txt
CHANGED
data/Manifest.txt
CHANGED
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
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
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
|
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',
|
8
|
-
|
9
|
-
|
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
|
-
|
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
|
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
|
-
#
|
34
|
-
#
|
38
|
+
# s = i.slice
|
39
|
+
# i.object_id == s.instance.object_id # true
|
35
40
|
#
|
36
|
-
def
|
37
|
-
d = Xen::
|
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/
|
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
|
-
|
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
|
-
|
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, :
|
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
|
-
@
|
14
|
-
@
|
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}
|
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}
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
26
|
-
|
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
|
-
|
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 =
|
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 =
|
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::
|
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.
|
23
|
-
when :running then Xen::Instance.find(:all, options).collect { |instance| instance.
|
24
|
-
# Retrieve a
|
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
|
data/test/test_ruby-xen.rb
CHANGED
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.
|
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-
|
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/
|
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:
|