virt 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +20 -0
- data/LICENSE.txt +674 -0
- data/README.rdoc +82 -0
- data/Rakefile +53 -0
- data/VERSION +1 -0
- data/lib/virt/connection.rb +32 -0
- data/lib/virt/guest.rb +102 -0
- data/lib/virt/host.rb +80 -0
- data/lib/virt/interface.rb +34 -0
- data/lib/virt/pool.rb +53 -0
- data/lib/virt/util.rb +26 -0
- data/lib/virt/volume.rb +69 -0
- data/lib/virt.rb +23 -0
- data/templates/guest.xml.erb +54 -0
- data/templates/volume.xml.erb +8 -0
- data/test/connection_test.rb +24 -0
- data/test/guest_test.rb +40 -0
- data/test/host_test.rb +43 -0
- data/test/interface_test.rb +16 -0
- data/test/pool_test.rb +35 -0
- data/test/test_helper.rb +3 -0
- data/test/volume_test.rb +28 -0
- data/virt.gemspec +83 -0
- metadata +161 -0
data/README.rdoc
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
= virt
|
2
|
+
|
3
|
+
Simple to use ruby interface to libvirt.
|
4
|
+
|
5
|
+
Libvirt is located at http://libvirt.org/ruby
|
6
|
+
|
7
|
+
== Contributing
|
8
|
+
|
9
|
+
* Fork the project
|
10
|
+
* Start a feature/bugfix branch
|
11
|
+
* Commit and push until you are happy with your contribution
|
12
|
+
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
13
|
+
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
14
|
+
|
15
|
+
== RDOC
|
16
|
+
|
17
|
+
for full API please visit http://rdoc.info/github/ohadlevy/virt
|
18
|
+
|
19
|
+
== Examples
|
20
|
+
|
21
|
+
=== Connectivity Options
|
22
|
+
uri = "qemu:///system" # libvirt running locally
|
23
|
+
uri = "qemu:/fqdn//system" # used for QEMU+TLS connection
|
24
|
+
uri = "qemu+ssh:/user@fqdn//system" # used for SSH connection
|
25
|
+
uri = "qemu+tcp:/fqdn//system" # used for non secured tcp connection
|
26
|
+
|
27
|
+
==== Establish the connection
|
28
|
+
conn = Virt.connect(uri)
|
29
|
+
|
30
|
+
==== get the hypervisor
|
31
|
+
host = conn.host
|
32
|
+
|
33
|
+
==== get the list of running guests
|
34
|
+
host.running_guests
|
35
|
+
|
36
|
+
==== get the list of stopped guests
|
37
|
+
host.defined_guests
|
38
|
+
|
39
|
+
====or a simple hash of both
|
40
|
+
host.guests
|
41
|
+
|
42
|
+
==== create a new guest
|
43
|
+
|
44
|
+
guest=Virt::Guest.new({:name => "test123"})
|
45
|
+
guest.vcpu = 2
|
46
|
+
guest.volume.size = 10 # in GB
|
47
|
+
|
48
|
+
guest.save
|
49
|
+
guest.start
|
50
|
+
|
51
|
+
puts guest.mac
|
52
|
+
|
53
|
+
guest.stop
|
54
|
+
Many more options exists, make sure checkout the api/tests
|
55
|
+
|
56
|
+
==== list of host bridges
|
57
|
+
host.interfaces # physical interfaces
|
58
|
+
host.networks # virtual / NAT interfaces
|
59
|
+
|
60
|
+
==== Storage
|
61
|
+
|
62
|
+
host.storage_pools
|
63
|
+
|
64
|
+
host.volumes
|
65
|
+
|
66
|
+
|
67
|
+
|
68
|
+
== Copyright
|
69
|
+
Copyright (c) 2011 Ohad Levy
|
70
|
+
|
71
|
+
This program and entire repository is free software: you can redistribute it and/or modify
|
72
|
+
it under the terms of the GNU General Public License as published by
|
73
|
+
the Free Software Foundation, either version 3 of the License, or
|
74
|
+
any later version.
|
75
|
+
|
76
|
+
This program is distributed in the hope that it will be useful,
|
77
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
78
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
79
|
+
GNU General Public License for more details.
|
80
|
+
|
81
|
+
You should have received a copy of the GNU General Public License
|
82
|
+
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
data/Rakefile
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
begin
|
4
|
+
Bundler.setup(:default, :development)
|
5
|
+
rescue Bundler::BundlerError => e
|
6
|
+
$stderr.puts e.message
|
7
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
+
exit e.status_code
|
9
|
+
end
|
10
|
+
require 'rake'
|
11
|
+
require 'jeweler'
|
12
|
+
Jeweler::Tasks.new do |gem|
|
13
|
+
# Gem::Specification... see http://docs.rubygems.org/read/chapter/20
|
14
|
+
gem.name = "virt"
|
15
|
+
gem.homepage = "https://github.com/ohadlevy/virt"
|
16
|
+
gem.license = "GPLv3"
|
17
|
+
gem.summary = %Q{Simple to use ruby interface to libvirt}
|
18
|
+
gem.description = %Q{Simplied interface to use ruby the libvirt ruby library}
|
19
|
+
gem.email = "ohadlevy@gmail.com"
|
20
|
+
gem.authors = ["Ohad Levy"]
|
21
|
+
|
22
|
+
#gem.add_runtime_dependency 'libvirt', '> 0.2.0'
|
23
|
+
#gem.add_development_dependency 'rspec', '> 1.2.3'
|
24
|
+
end
|
25
|
+
Jeweler::RubygemsDotOrgTasks.new
|
26
|
+
|
27
|
+
require 'rake/testtask'
|
28
|
+
Rake::TestTask.new(:test) do |test|
|
29
|
+
test.libs << 'lib' << 'test'
|
30
|
+
test.pattern = 'test/*test*.rb'
|
31
|
+
test.verbose = true
|
32
|
+
test.warning = true
|
33
|
+
end
|
34
|
+
|
35
|
+
require 'rcov/rcovtask'
|
36
|
+
Rcov::RcovTask.new do |test|
|
37
|
+
test.libs << 'test'
|
38
|
+
test.pattern = 'test/**/test_*.rb'
|
39
|
+
test.verbose = true
|
40
|
+
end
|
41
|
+
|
42
|
+
task :default => :test
|
43
|
+
|
44
|
+
require 'rake/rdoctask'
|
45
|
+
Rake::RDocTask.new do |rdoc|
|
46
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
47
|
+
|
48
|
+
rdoc.rdoc_dir = 'rdoc'
|
49
|
+
rdoc.title = "hello-gem #{version}"
|
50
|
+
rdoc.rdoc_files.include('README*')
|
51
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
52
|
+
end
|
53
|
+
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'libvirt'
|
2
|
+
module Virt
|
3
|
+
class Connection
|
4
|
+
attr_reader :connection
|
5
|
+
|
6
|
+
def initialize uri
|
7
|
+
raise("Must provide a guest to connect to") unless uri
|
8
|
+
@connection = Libvirt::open uri
|
9
|
+
end
|
10
|
+
|
11
|
+
def closed?
|
12
|
+
connection.closed?
|
13
|
+
end
|
14
|
+
|
15
|
+
def secure?
|
16
|
+
connection.encrypted?
|
17
|
+
end
|
18
|
+
|
19
|
+
def version
|
20
|
+
connection.libversion
|
21
|
+
end
|
22
|
+
|
23
|
+
def disconnect
|
24
|
+
connection.close
|
25
|
+
end
|
26
|
+
|
27
|
+
def host
|
28
|
+
Host.new
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
data/lib/virt/guest.rb
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
module Virt
|
2
|
+
class Guest
|
3
|
+
include Virt::Util
|
4
|
+
attr_reader :name, :xml_desc
|
5
|
+
attr_accessor :memory, :vcpu, :arch, :volume, :interface, :template_path
|
6
|
+
|
7
|
+
def initialize options = {}
|
8
|
+
@connection = Virt.connection
|
9
|
+
@name = options[:name] || raise("Must provide a name")
|
10
|
+
# If our domain exists, we ignore the provided options and defaults
|
11
|
+
fetch_guest
|
12
|
+
@memory ||= options[:memory] || default_memory_size
|
13
|
+
@vcpu ||= options[:vcpu] || default_vcpu_count
|
14
|
+
@arch ||= options[:arch] || default_arch
|
15
|
+
|
16
|
+
@template_path = options[:template_path] || default_template_path
|
17
|
+
@volume = Volume.new options
|
18
|
+
@interface = Interface.new options.merge({:mac => @mac})
|
19
|
+
end
|
20
|
+
|
21
|
+
def new?
|
22
|
+
@domain.nil?
|
23
|
+
end
|
24
|
+
|
25
|
+
def save
|
26
|
+
@domain = @connection.connection.define_domain_xml(xml)
|
27
|
+
fetch_info
|
28
|
+
!new?
|
29
|
+
end
|
30
|
+
|
31
|
+
def start
|
32
|
+
raise "Guest not created, can't start" if new?
|
33
|
+
@domain.create unless running?
|
34
|
+
running?
|
35
|
+
end
|
36
|
+
|
37
|
+
def running?
|
38
|
+
return false if new?
|
39
|
+
@domain.active?
|
40
|
+
rescue
|
41
|
+
# some versions of libvirt do not support checking for active state
|
42
|
+
@connection.connection.list_domains.each do |did|
|
43
|
+
return true if @connection.connection.lookup_domain_by_id(did).name == name
|
44
|
+
end
|
45
|
+
false
|
46
|
+
end
|
47
|
+
|
48
|
+
def stop
|
49
|
+
raise "Guest not created, can't stop" if new?
|
50
|
+
@domain.destroy
|
51
|
+
!running?
|
52
|
+
rescue Libvirt::Error
|
53
|
+
# domain is not running
|
54
|
+
true
|
55
|
+
end
|
56
|
+
|
57
|
+
def destroy
|
58
|
+
return true if new?
|
59
|
+
stop if running?
|
60
|
+
@domain = @domain.undefine
|
61
|
+
new?
|
62
|
+
end
|
63
|
+
|
64
|
+
def uuid
|
65
|
+
@domain.uuid unless new?
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
def fetch_guest
|
71
|
+
@domain = @connection.connection.lookup_domain_by_name(name)
|
72
|
+
fetch_info
|
73
|
+
rescue Libvirt::RetrieveError
|
74
|
+
end
|
75
|
+
|
76
|
+
def fetch_info
|
77
|
+
return if @domain.nil?
|
78
|
+
@xml_desc = @domain.xml_desc
|
79
|
+
@memory = @domain.max_memory
|
80
|
+
@vcpu = document("domain/vcpu")
|
81
|
+
@arch = document("domain/os/type", "arch")
|
82
|
+
@mac = document("domain/devices/interface/mac", "address")
|
83
|
+
@interface.mac = @mac if @interface
|
84
|
+
end
|
85
|
+
|
86
|
+
def default_memory_size
|
87
|
+
1048576
|
88
|
+
end
|
89
|
+
|
90
|
+
def default_vcpu_count
|
91
|
+
1
|
92
|
+
end
|
93
|
+
|
94
|
+
def default_arch
|
95
|
+
"x86_64"
|
96
|
+
end
|
97
|
+
|
98
|
+
def default_template_path
|
99
|
+
"guest.xml.erb"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
data/lib/virt/host.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
module Virt
|
2
|
+
class Host < Virt::Connection
|
3
|
+
# Represents a Physical host which runs the libvirt daemon
|
4
|
+
|
5
|
+
attr_reader :connection
|
6
|
+
def initialize
|
7
|
+
@connection = Virt.connection.connection
|
8
|
+
end
|
9
|
+
|
10
|
+
def name
|
11
|
+
connection.hostname
|
12
|
+
end
|
13
|
+
|
14
|
+
def guests
|
15
|
+
{:running => running_guests, :defined => defined_guests}
|
16
|
+
end
|
17
|
+
|
18
|
+
def running_guests
|
19
|
+
connection.list_domains.map do |domain|
|
20
|
+
find_guest_by_id(domain)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def defined_guests
|
25
|
+
connection.list_defined_domains.map do |domain|
|
26
|
+
find_guest_by_name domain
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Available libvirt interfaces, excluding lo
|
31
|
+
def interfaces
|
32
|
+
connection.list_interfaces.delete_if{|i| i == "lo"}.sort
|
33
|
+
rescue => e
|
34
|
+
raise "This function is not supported by the hypervisor: #{e}"
|
35
|
+
end
|
36
|
+
|
37
|
+
def interface iface
|
38
|
+
connection.lookup_interface_by_name(iface)
|
39
|
+
end
|
40
|
+
|
41
|
+
# libvirt internal networks
|
42
|
+
def networks
|
43
|
+
connection.list_networks.map do |network|
|
44
|
+
connection.lookup_network_by_name(network).bridge_name
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def storage_pools
|
49
|
+
connection.list_storage_pools.map {|p| Pool.new({:name => p})}
|
50
|
+
end
|
51
|
+
|
52
|
+
# Returns a Virt::Pool object based on the pool name
|
53
|
+
def storage_pool pool
|
54
|
+
Pool.new({:name => pool.is_a?(Libvirt::StoragePool) ? pool.name : pool })
|
55
|
+
rescue Libvirt::RetrieveError
|
56
|
+
end
|
57
|
+
|
58
|
+
# Returns a hash of pools and their volumes objects.
|
59
|
+
def volumes
|
60
|
+
pools = {}
|
61
|
+
storage_pools.each do |storage|
|
62
|
+
pools[storage.name] = storage.volumes
|
63
|
+
end
|
64
|
+
pools
|
65
|
+
end
|
66
|
+
|
67
|
+
def find_guest_by_name name
|
68
|
+
if connection.lookup_domain_by_name name
|
69
|
+
return Guest.new({:name => name})
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def find_guest_by_id id
|
74
|
+
id.to_a.map do |did|
|
75
|
+
return Guest.new({:name => connection.lookup_domain_by_id(did).name})
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Virt
|
2
|
+
class Interface
|
3
|
+
attr_accessor :mac, :model, :type, :device
|
4
|
+
|
5
|
+
def initialize options = {}
|
6
|
+
@connection = Virt.connection
|
7
|
+
@device = options[:device] || default_device
|
8
|
+
@type = options[:type] || default_type
|
9
|
+
@model = options[:model] || default_model
|
10
|
+
@mac = options[:mac]
|
11
|
+
end
|
12
|
+
|
13
|
+
def new?
|
14
|
+
mac.nil?
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def default_device
|
20
|
+
@connection.host.interfaces.first
|
21
|
+
rescue
|
22
|
+
"br0"
|
23
|
+
end
|
24
|
+
|
25
|
+
def default_type
|
26
|
+
"bridge"
|
27
|
+
end
|
28
|
+
|
29
|
+
def default_model
|
30
|
+
"virtio"
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
data/lib/virt/pool.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
module Virt
|
2
|
+
# implements Libvirt pool, at the moment it is assumed to be a file based pool.
|
3
|
+
class Pool
|
4
|
+
include Virt::Util
|
5
|
+
attr_reader :name
|
6
|
+
def initialize options = {}
|
7
|
+
@name = options[:name] || raise("Must Provide a pool name")
|
8
|
+
@connection = Virt.connection
|
9
|
+
fetch_pool
|
10
|
+
end
|
11
|
+
|
12
|
+
alias :to_s :name
|
13
|
+
|
14
|
+
def save
|
15
|
+
raise "not implemented"
|
16
|
+
end
|
17
|
+
|
18
|
+
def new?
|
19
|
+
@pool.nil?
|
20
|
+
end
|
21
|
+
|
22
|
+
def volumes
|
23
|
+
@pool.list_volumes
|
24
|
+
end
|
25
|
+
|
26
|
+
%w{name key path}.each do |method|
|
27
|
+
define_method "find_volume_by_#{method}" do |value|
|
28
|
+
begin
|
29
|
+
@pool.send("lookup_volume_by_#{method}", value)
|
30
|
+
rescue Libvirt::RetrieveError
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def path
|
36
|
+
document "pool/target/path"
|
37
|
+
end
|
38
|
+
|
39
|
+
def create_vol vol
|
40
|
+
raise "Must provide a Virt::Volume object" unless vol.is_a?(Virt::Volume)
|
41
|
+
raise "Pool not saved, cant create volume" if new?
|
42
|
+
@pool.create_vol_xml vol.xml
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def fetch_pool
|
48
|
+
if @pool = @connection.connection.lookup_storage_pool_by_name(name)
|
49
|
+
@xml_desc = @pool.xml_desc
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/lib/virt/util.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require "rexml/document"
|
2
|
+
require 'erb'
|
3
|
+
|
4
|
+
module Virt
|
5
|
+
module Util
|
6
|
+
# return templated xml to be used by libvirt
|
7
|
+
def xml
|
8
|
+
ERB.new(template, nil, '-').result(binding)
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
# template file that contain our xml template
|
13
|
+
def template
|
14
|
+
File.read("#{File.dirname(__FILE__)}/../../templates/#{template_path}")
|
15
|
+
rescue => e
|
16
|
+
warn "failed to read template #{template_path}: #{e}"
|
17
|
+
end
|
18
|
+
|
19
|
+
# finds a value from xml
|
20
|
+
def document path, attribute=nil
|
21
|
+
return nil if new?
|
22
|
+
xml = REXML::Document.new(@xml_desc)
|
23
|
+
attribute.nil? ? xml.elements[path].text : xml.elements[path].attributes[attribute]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/virt/volume.rb
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
module Virt
|
2
|
+
class Volume
|
3
|
+
include Virt::Util
|
4
|
+
attr_reader :name, :pool, :path, :type, :allocated_size, :size, :template_path, :key
|
5
|
+
|
6
|
+
def initialize options = {}
|
7
|
+
@connection = Virt.connection
|
8
|
+
self.name = options[:name] || raise("Volume requires a name")
|
9
|
+
@type = options[:type] || default_type
|
10
|
+
@allocated_size = options[:allocated_size] || default_allocated_size
|
11
|
+
@template_path = options[:template_path] || default_template_path
|
12
|
+
@size = options[:size] || default_size
|
13
|
+
@pool = @connection.host.storage_pool(options[:pool] || "default")
|
14
|
+
fetch_volume
|
15
|
+
end
|
16
|
+
|
17
|
+
def new?
|
18
|
+
@vol.nil?
|
19
|
+
end
|
20
|
+
|
21
|
+
def save
|
22
|
+
raise "volume already exists, can't save" unless new?
|
23
|
+
#validations
|
24
|
+
#update?
|
25
|
+
@vol=pool.create_vol(self)
|
26
|
+
!new?
|
27
|
+
end
|
28
|
+
|
29
|
+
def destroy
|
30
|
+
return true if new?
|
31
|
+
@vol.delete
|
32
|
+
fetch_volume
|
33
|
+
new?
|
34
|
+
end
|
35
|
+
|
36
|
+
def path
|
37
|
+
"#{pool.path}/#{name}"
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def name= name
|
43
|
+
raise "invalid name" if name.nil?
|
44
|
+
@name = name
|
45
|
+
@name += ".img" unless name.match(/.*\.img$/)
|
46
|
+
end
|
47
|
+
|
48
|
+
def default_type
|
49
|
+
"raw"
|
50
|
+
end
|
51
|
+
|
52
|
+
def default_allocated_size
|
53
|
+
0
|
54
|
+
end
|
55
|
+
|
56
|
+
# default image size in GB
|
57
|
+
def default_size
|
58
|
+
8
|
59
|
+
end
|
60
|
+
|
61
|
+
def default_template_path
|
62
|
+
"volume.xml.erb"
|
63
|
+
end
|
64
|
+
|
65
|
+
def fetch_volume
|
66
|
+
@vol = pool.find_volume_by_name(name)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
data/lib/virt.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'virt/util'
|
2
|
+
require 'virt/connection'
|
3
|
+
require 'virt/host'
|
4
|
+
require 'virt/guest'
|
5
|
+
require 'virt/pool'
|
6
|
+
require 'virt/volume'
|
7
|
+
require 'virt/interface'
|
8
|
+
module Virt
|
9
|
+
|
10
|
+
class << self
|
11
|
+
|
12
|
+
def connect uri
|
13
|
+
@connection = Virt::Connection.new uri
|
14
|
+
end
|
15
|
+
|
16
|
+
def connection
|
17
|
+
return @connection if @connection and !@connection.closed?
|
18
|
+
raise "No Connection or connection has been closed"
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
<domain type='kvm'>
|
2
|
+
<name><%= name %></name>
|
3
|
+
<%- if uuid -%>
|
4
|
+
<uuid><%= uuid %></uuid>
|
5
|
+
<%- end -%>
|
6
|
+
<memory><%= memory %></memory>
|
7
|
+
<currentMemory><%= memory %></currentMemory>
|
8
|
+
<vcpu><%= vcpu %></vcpu>
|
9
|
+
<os>
|
10
|
+
<type arch='<%= arch %>'>hvm</type>
|
11
|
+
<boot dev='network'/>
|
12
|
+
<%- if volume -%>
|
13
|
+
<boot dev='hd'/>
|
14
|
+
<%- end -%>
|
15
|
+
</os>
|
16
|
+
<features>
|
17
|
+
<acpi/>
|
18
|
+
<apic/>
|
19
|
+
<pae/>
|
20
|
+
</features>
|
21
|
+
<clock offset='utc'/>
|
22
|
+
<on_poweroff>destroy</on_poweroff>
|
23
|
+
<on_reboot>restart</on_reboot>
|
24
|
+
<on_crash>restart</on_crash>
|
25
|
+
<devices>
|
26
|
+
<%- if volume -%>
|
27
|
+
<disk type='file' device='disk'>
|
28
|
+
<driver name='qemu' type='raw'/>
|
29
|
+
<source file='<%= volume.path %>'/>
|
30
|
+
<target dev='vda' bus='virtio'/>
|
31
|
+
</disk>
|
32
|
+
<%- end -%>
|
33
|
+
<%- if interface -%>
|
34
|
+
<interface type='<%= interface.type %>'>
|
35
|
+
<%- if interface.mac -%>
|
36
|
+
<mac address='<%= interface.mac %>'/>
|
37
|
+
<%- end -%>
|
38
|
+
<source <%= interface.type %>='<%= interface.device %>'/>
|
39
|
+
<model type='<%= interface.model %>'/>
|
40
|
+
</interface>
|
41
|
+
<%- end -%>
|
42
|
+
<serial type='pty'>
|
43
|
+
<target port='0'/>
|
44
|
+
</serial>
|
45
|
+
<console type='pty'>
|
46
|
+
<target port='0'/>
|
47
|
+
</console>
|
48
|
+
<input type='mouse' bus='ps2'/>
|
49
|
+
<graphics type='vnc' port='-1' autoport='yes' keymap='en-us'/>
|
50
|
+
<video>
|
51
|
+
<model type='cirrus' vram='9216' heads='1'/>
|
52
|
+
</video>
|
53
|
+
</devices>
|
54
|
+
</domain>
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'test/test_helper'
|
2
|
+
|
3
|
+
class Virt::ConnectionTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
hostname = "h01.sat.lab"
|
7
|
+
uri = "qemu+ssh://root@#{hostname}/system"
|
8
|
+
@conn = Virt.connect uri
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_should_be_able_to_connect
|
12
|
+
assert !@conn.closed?
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_should_be_able_to_disconnect
|
16
|
+
@conn.disconnect
|
17
|
+
assert @conn.closed?
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_should_return_a_version
|
21
|
+
assert @conn.version
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
data/test/guest_test.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'test/test_helper'
|
2
|
+
|
3
|
+
class Virt::GuestTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
hostname = "h01.sat.lab"
|
7
|
+
uri = "qemu+ssh://root@#{hostname}/system"
|
8
|
+
Virt.connect(uri)
|
9
|
+
@guest = Virt::Guest.new({:name => "test-host-#{Time.now.to_i}"})
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_should_be_new
|
13
|
+
assert @guest.new?
|
14
|
+
assert @guest.interface.new?
|
15
|
+
assert_nil @guest.interface.mac
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_should_be_able_to_save
|
19
|
+
assert @guest.save
|
20
|
+
assert !@guest.interface.new?
|
21
|
+
assert_not_nil @guest.interface.mac
|
22
|
+
@guest.destroy
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_should_be_able_to_destroy
|
26
|
+
assert @guest.save
|
27
|
+
assert @guest.destroy
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_should_be_able_to_save_and_start
|
31
|
+
@guest = Virt::Guest.new({:name => "test-host-#{Time.now.to_i}", :device => "br180"})
|
32
|
+
assert @guest.volume.save
|
33
|
+
assert @guest.save
|
34
|
+
assert @guest.start
|
35
|
+
assert @guest.stop
|
36
|
+
assert @guest.volume.destroy
|
37
|
+
assert @guest.destroy
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|