ruby-xen 0.0.3 → 0.1.0
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/Manifest.txt +6 -4
- data/README.rdoc +26 -20
- data/lib/ruby-xen.rb +60 -10
- data/lib/templates/domu.cfg.erb +1 -1
- data/lib/templates/exclude_from_backups +2 -0
- data/lib/templates/xen-tools.conf.erb +289 -0
- data/lib/xen/backup.rb +71 -33
- data/lib/xen/command.rb +94 -60
- data/lib/xen/config_file.rb +159 -0
- data/lib/xen/host.rb +59 -5
- data/lib/xen/instance.rb +53 -51
- data/lib/xen/lvm.rb +40 -0
- data/lib/xen/slice.rb +118 -65
- data/lib/xen/xen_tools_conf.rb +56 -0
- data/test/test_ruby-xen.rb +2 -2
- metadata +29 -7
- data/lib/xen/config.rb +0 -146
- data/lib/xen/image.rb +0 -12
data/lib/xen/instance.rb
CHANGED
@@ -1,66 +1,68 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
module Xen
|
2
|
+
class Instance
|
3
|
+
include Xen::Parentable
|
4
|
+
attr_reader :name, :domid, :memory, :cpu_time, :vcpus, :state, :start_time
|
4
5
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
6
|
+
def initialize(options={})
|
7
|
+
@name = options[:name]
|
8
|
+
@domid = options[:domid]
|
9
|
+
@memory = options[:memory]
|
10
|
+
@cpu_time = options[:cpu_time]
|
11
|
+
@vcpus = options[:vcpus]
|
12
|
+
@state = options[:state]
|
13
|
+
@start_time = Time.at(options[:start_time].to_f) if options[:start_time]
|
14
|
+
end
|
14
15
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
16
|
+
def self.find(*args)
|
17
|
+
options = args.extract_options!
|
18
|
+
case args.first
|
19
|
+
when :all then all
|
20
|
+
else find_by_name(args.first)
|
21
|
+
end
|
20
22
|
end
|
21
|
-
end
|
22
23
|
|
23
|
-
|
24
|
-
|
25
|
-
|
24
|
+
def self.all
|
25
|
+
Xen::Command.detailed_instance_list.collect do |instance|
|
26
|
+
new(instance)
|
27
|
+
end
|
26
28
|
end
|
27
|
-
end
|
28
29
|
|
29
|
-
|
30
|
-
|
31
|
-
|
30
|
+
def self.find_by_name(name)
|
31
|
+
Xen::Command.detailed_instance_list(name).each do |instance|
|
32
|
+
return new(instance)
|
33
|
+
end
|
34
|
+
return false
|
32
35
|
end
|
33
|
-
return false
|
34
|
-
end
|
35
36
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
37
|
+
def self.create(name)
|
38
|
+
output = Xen::Command.start_instance(name.to_s + Xen::CONFIG_FILE_EXTENSION)
|
39
|
+
$? == 0 ? true : false
|
40
|
+
end
|
40
41
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
42
|
+
def self.shutdown(name)
|
43
|
+
output = Xen::Command.shutdown_instance(name)
|
44
|
+
$? == 0 ? true : false
|
45
|
+
end
|
45
46
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
47
|
+
# A convenience wrapper for <tt>find(:dom0)</tt>.</tt>.
|
48
|
+
def self.dom0(*args)
|
49
|
+
find_by_name(:dom0)
|
50
|
+
end
|
50
51
|
|
51
|
-
|
52
|
-
|
53
|
-
|
52
|
+
def uptime
|
53
|
+
start_time ? Time.now - start_time : nil
|
54
|
+
end
|
54
55
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
56
|
+
def reboot
|
57
|
+
`xm reboot #{name}`
|
58
|
+
$? == 0 ? true : false
|
59
|
+
end
|
59
60
|
|
60
|
-
|
61
|
-
|
61
|
+
def destroy
|
62
|
+
end
|
62
63
|
|
63
|
-
|
64
|
-
|
64
|
+
def pause
|
65
|
+
end
|
65
66
|
|
66
|
-
end
|
67
|
+
end
|
68
|
+
end
|
data/lib/xen/lvm.rb
ADDED
@@ -0,0 +1,40 @@
|
|
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
|
+
begin
|
19
|
+
output = Xen::Command.run cmd
|
20
|
+
result = output.collect { |line|
|
21
|
+
name, size = line.strip.split(' ')
|
22
|
+
new name, size
|
23
|
+
}
|
24
|
+
rescue # don't die if `vgs` command missing
|
25
|
+
end
|
26
|
+
name ? result[0] : result
|
27
|
+
end
|
28
|
+
|
29
|
+
def free
|
30
|
+
cmd = "vgs --options=vg_free --separator=' ' --noheadings --units=g --nosuffix #{@name}"
|
31
|
+
begin
|
32
|
+
result = Xen::Command.run cmd
|
33
|
+
rescue # don't die if `vgs` command missing
|
34
|
+
end
|
35
|
+
result
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
data/lib/xen/slice.rb
CHANGED
@@ -1,80 +1,133 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
module Xen
|
2
|
+
class Slice
|
3
|
+
attr_accessor :name, :image, :config_file, :backups
|
3
4
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
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
|
11
13
|
end
|
12
|
-
end
|
13
14
|
|
14
|
-
|
15
|
-
|
16
|
-
|
15
|
+
def self.all(options={})
|
16
|
+
self.find(:all, options)
|
17
|
+
end
|
17
18
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
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
|
26
27
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
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)
|
41
62
|
end
|
42
|
-
|
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
|
43
75
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
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
|
80
|
+
end
|
49
81
|
|
50
|
-
|
51
|
-
|
52
|
-
|
82
|
+
def backups
|
83
|
+
Xen::Backup.find(name)
|
84
|
+
end
|
85
|
+
|
86
|
+
def create_backup(options = {})
|
87
|
+
Xen::Backup.create(name, :options)
|
88
|
+
end
|
53
89
|
|
54
|
-
|
55
|
-
|
56
|
-
|
90
|
+
def state
|
91
|
+
self.instance ? :running : :stopped
|
92
|
+
end
|
57
93
|
|
58
|
-
|
59
|
-
|
60
|
-
|
94
|
+
def first_ip
|
95
|
+
config_file.vifs.first.ip if config_file and config_file.vifs
|
96
|
+
end
|
97
|
+
|
98
|
+
def running?
|
99
|
+
self.instance ? true : false
|
100
|
+
end
|
61
101
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
102
|
+
def start
|
103
|
+
Xen::Instance.create(@name)
|
104
|
+
@instance = Xen::Instance.find(@name)
|
105
|
+
end
|
66
106
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
107
|
+
def stop
|
108
|
+
Xen::Instance.shutdown(@name)
|
109
|
+
@instance = Xen::Instance.find(@name)
|
110
|
+
end
|
71
111
|
|
72
|
-
|
73
|
-
|
74
|
-
|
112
|
+
def config_file_newer_than_instance?
|
113
|
+
instance && config_file.updated_at > instance.start_time
|
114
|
+
end
|
75
115
|
|
76
|
-
|
77
|
-
|
78
|
-
|
116
|
+
def save
|
117
|
+
@config_file.save
|
118
|
+
end
|
119
|
+
|
120
|
+
def root_disk
|
121
|
+
config_file.vbds.detect { |vbd| vbd.name == "#{name}-disk" } unless config_file.nil?
|
122
|
+
end
|
123
|
+
|
124
|
+
# Primary IP
|
125
|
+
def ip
|
126
|
+
config_file.vifs[0].ip
|
127
|
+
end
|
79
128
|
|
80
|
-
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
|
133
|
+
|
@@ -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
|
data/test/test_ruby-xen.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
1
|
require '../lib/ruby-xen'
|
2
|
-
c = Xen::
|
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: ruby-xen
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Bailey
|
@@ -10,10 +10,29 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date:
|
13
|
+
date: 2009-09-02 00:00:00 +10:00
|
14
14
|
default_executable:
|
15
|
-
dependencies:
|
16
|
-
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: activesupport
|
18
|
+
type: :runtime
|
19
|
+
version_requirement:
|
20
|
+
version_requirements: !ruby/object:Gem::Requirement
|
21
|
+
requirements:
|
22
|
+
- - ">="
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: "0"
|
25
|
+
version:
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: open4
|
28
|
+
type: :runtime
|
29
|
+
version_requirement:
|
30
|
+
version_requirements: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: "0"
|
35
|
+
version:
|
17
36
|
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
37
|
email: mike@bailey.net.au
|
19
38
|
executables: []
|
@@ -34,12 +53,15 @@ files:
|
|
34
53
|
- test/test_ruby-xen.rb
|
35
54
|
- lib/xen/backup.rb
|
36
55
|
- lib/xen/command.rb
|
37
|
-
- lib/xen/
|
56
|
+
- lib/xen/config_file.rb
|
38
57
|
- lib/xen/host.rb
|
39
|
-
- lib/xen/image.rb
|
40
58
|
- lib/xen/instance.rb
|
59
|
+
- lib/xen/lvm.rb
|
41
60
|
- lib/xen/slice.rb
|
61
|
+
- lib/xen/xen_tools_conf.rb
|
42
62
|
- lib/templates/domu.cfg.erb
|
63
|
+
- lib/templates/exclude_from_backups
|
64
|
+
- lib/templates/xen-tools.conf.erb
|
43
65
|
has_rdoc: true
|
44
66
|
homepage: http://github.com/mbailey/ruby-xen
|
45
67
|
post_install_message:
|
@@ -63,7 +85,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
63
85
|
requirements: []
|
64
86
|
|
65
87
|
rubyforge_project:
|
66
|
-
rubygems_version: 1.
|
88
|
+
rubygems_version: 1.3.1
|
67
89
|
signing_key:
|
68
90
|
specification_version: 2
|
69
91
|
summary: Ruby library for managing Xen virtual hosts
|