fog-libvirt-csem 0.9.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.
- checksums.yaml +7 -0
- data/CONTRIBUTORS.md +24 -0
- data/Gemfile +9 -0
- data/LICENSE.md +20 -0
- data/README.md +83 -0
- data/Rakefile +127 -0
- data/fog-libvirt-csem.gemspec +49 -0
- data/lib/fog/bin/libvirt.rb +58 -0
- data/lib/fog/libvirt/compute.rb +140 -0
- data/lib/fog/libvirt/models/compute/README.md +92 -0
- data/lib/fog/libvirt/models/compute/interface.rb +25 -0
- data/lib/fog/libvirt/models/compute/interfaces.rb +20 -0
- data/lib/fog/libvirt/models/compute/network.rb +33 -0
- data/lib/fog/libvirt/models/compute/networks.rb +20 -0
- data/lib/fog/libvirt/models/compute/nic.rb +50 -0
- data/lib/fog/libvirt/models/compute/nics.rb +12 -0
- data/lib/fog/libvirt/models/compute/node.rb +29 -0
- data/lib/fog/libvirt/models/compute/nodes.rb +20 -0
- data/lib/fog/libvirt/models/compute/pool.rb +84 -0
- data/lib/fog/libvirt/models/compute/pools.rb +20 -0
- data/lib/fog/libvirt/models/compute/server.rb +514 -0
- data/lib/fog/libvirt/models/compute/servers.rb +21 -0
- data/lib/fog/libvirt/models/compute/templates/network.xml.erb +6 -0
- data/lib/fog/libvirt/models/compute/templates/pool.xml.erb +6 -0
- data/lib/fog/libvirt/models/compute/templates/server.xml.erb +155 -0
- data/lib/fog/libvirt/models/compute/templates/volume.xml.erb +30 -0
- data/lib/fog/libvirt/models/compute/util/uri.rb +138 -0
- data/lib/fog/libvirt/models/compute/util/util.rb +32 -0
- data/lib/fog/libvirt/models/compute/volume.rb +129 -0
- data/lib/fog/libvirt/models/compute/volumes.rb +20 -0
- data/lib/fog/libvirt/requests/compute/clone_volume.rb +18 -0
- data/lib/fog/libvirt/requests/compute/create_domain.rb +17 -0
- data/lib/fog/libvirt/requests/compute/create_volume.rb +16 -0
- data/lib/fog/libvirt/requests/compute/define_domain.rb +17 -0
- data/lib/fog/libvirt/requests/compute/define_pool.rb +16 -0
- data/lib/fog/libvirt/requests/compute/destroy_interface.rb +18 -0
- data/lib/fog/libvirt/requests/compute/destroy_network.rb +17 -0
- data/lib/fog/libvirt/requests/compute/dhcp_leases.rb +37 -0
- data/lib/fog/libvirt/requests/compute/get_node_info.rb +37 -0
- data/lib/fog/libvirt/requests/compute/libversion.rb +18 -0
- data/lib/fog/libvirt/requests/compute/list_domains.rb +128 -0
- data/lib/fog/libvirt/requests/compute/list_interfaces.rb +57 -0
- data/lib/fog/libvirt/requests/compute/list_networks.rb +63 -0
- data/lib/fog/libvirt/requests/compute/list_pool_volumes.rb +19 -0
- data/lib/fog/libvirt/requests/compute/list_pools.rb +71 -0
- data/lib/fog/libvirt/requests/compute/list_volumes.rb +106 -0
- data/lib/fog/libvirt/requests/compute/mock_files/domain.xml +40 -0
- data/lib/fog/libvirt/requests/compute/pool_action.rb +19 -0
- data/lib/fog/libvirt/requests/compute/update_autostart.rb +18 -0
- data/lib/fog/libvirt/requests/compute/update_display.rb +36 -0
- data/lib/fog/libvirt/requests/compute/upload_volume.rb +31 -0
- data/lib/fog/libvirt/requests/compute/vm_action.rb +19 -0
- data/lib/fog/libvirt/requests/compute/volume_action.rb +18 -0
- data/lib/fog/libvirt/version.rb +5 -0
- data/lib/fog/libvirt.rb +16 -0
- data/minitests/server/server_test.rb +64 -0
- data/minitests/server/user_data_iso_test.rb +77 -0
- data/minitests/test_helper.rb +18 -0
- data/tests/helper.rb +17 -0
- data/tests/helpers/formats_helper.rb +100 -0
- data/tests/helpers/formats_helper_tests.rb +107 -0
- data/tests/helpers/mock_helper.rb +14 -0
- data/tests/helpers/succeeds_helper.rb +9 -0
- data/tests/libvirt/compute_tests.rb +19 -0
- data/tests/libvirt/models/compute/interface_tests.rb +27 -0
- data/tests/libvirt/models/compute/interfaces_tests.rb +14 -0
- data/tests/libvirt/models/compute/network_tests.rb +31 -0
- data/tests/libvirt/models/compute/networks_tests.rb +13 -0
- data/tests/libvirt/models/compute/nic_tests.rb +31 -0
- data/tests/libvirt/models/compute/nics_tests.rb +10 -0
- data/tests/libvirt/models/compute/pool_tests.rb +27 -0
- data/tests/libvirt/models/compute/pools_tests.rb +13 -0
- data/tests/libvirt/models/compute/server_tests.rb +63 -0
- data/tests/libvirt/models/compute/servers_tests.rb +14 -0
- data/tests/libvirt/models/compute/volume_tests.rb +38 -0
- data/tests/libvirt/models/compute/volumes_tests.rb +15 -0
- data/tests/libvirt/requests/compute/create_domain_tests.rb +21 -0
- data/tests/libvirt/requests/compute/define_domain_tests.rb +11 -0
- data/tests/libvirt/requests/compute/dhcp_leases_tests.rb +15 -0
- data/tests/libvirt/requests/compute/update_autostart_tests.rb +12 -0
- data/tests/libvirt/requests/compute/update_display.rb +13 -0
- metadata +335 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
module Fog
|
|
2
|
+
module Libvirt
|
|
3
|
+
class Compute
|
|
4
|
+
class Real
|
|
5
|
+
def get_node_info
|
|
6
|
+
node_hash = Hash.new
|
|
7
|
+
node_info = client.node_get_info
|
|
8
|
+
[:model, :memory, :cpus, :mhz, :nodes, :sockets, :cores, :threads].each do |param|
|
|
9
|
+
node_hash[param] = node_info.send(param) rescue nil
|
|
10
|
+
end
|
|
11
|
+
[:type, :version, :node_free_memory, :max_vcpus].each do |param|
|
|
12
|
+
node_hash[param] = client.send(param) rescue nil
|
|
13
|
+
end
|
|
14
|
+
node_hash[:uri] = client.uri
|
|
15
|
+
xml = client.sys_info rescue nil
|
|
16
|
+
[:uuid, :manufacturer, :product, :serial].each do |attr|
|
|
17
|
+
node_hash[attr] = node_attr(attr, xml) rescue nil
|
|
18
|
+
end if xml
|
|
19
|
+
|
|
20
|
+
node_hash[:hostname] = client.hostname
|
|
21
|
+
[node_hash]
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def node_attr attr, xml
|
|
27
|
+
xml_element(xml, "sysinfo/system/entry[@name='#{attr}']").strip
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
class Mock
|
|
32
|
+
def get_node_info
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
module Fog
|
|
2
|
+
module Libvirt
|
|
3
|
+
class Compute
|
|
4
|
+
class Real
|
|
5
|
+
def list_domains(filter = { })
|
|
6
|
+
data=[]
|
|
7
|
+
|
|
8
|
+
if filter.key?(:uuid)
|
|
9
|
+
data << client.lookup_domain_by_uuid(filter[:uuid])
|
|
10
|
+
elsif filter.key?(:name)
|
|
11
|
+
data << client.lookup_domain_by_name(filter[:name])
|
|
12
|
+
else
|
|
13
|
+
client.list_defined_domains.each { |name| data << catchLibvirtExceptions { client.lookup_domain_by_name(name) } } unless filter[:defined] == false
|
|
14
|
+
client.list_domains.each { |id| data << catchLibvirtExceptions { client.lookup_domain_by_id(id) } } unless filter[:active] == false
|
|
15
|
+
end
|
|
16
|
+
data.compact.map { |d| domain_to_attributes d }.compact
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Catch Libvirt exceptions to avoid race conditions involving
|
|
20
|
+
# concurrent libvirt operations from other processes. For example,
|
|
21
|
+
# domains being undefined while fog-libvirt is trying to work with
|
|
22
|
+
# domain lists.
|
|
23
|
+
def catchLibvirtExceptions
|
|
24
|
+
yield
|
|
25
|
+
rescue ::Libvirt::RetrieveError, ::Libvirt::Error
|
|
26
|
+
nil
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
module Shared
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
def domain_display xml
|
|
34
|
+
attrs = {}
|
|
35
|
+
[:type, :port, :password, :listen].each do |element|
|
|
36
|
+
attrs[element] = xml_element(xml, "domain/devices/graphics",element.to_s) rescue nil
|
|
37
|
+
end
|
|
38
|
+
attrs.reject{|k,v| v.nil? or v == ""}
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def domain_volumes xml
|
|
42
|
+
vols_by_file = xml_elements(xml, "domain/devices/disk/source", "file")
|
|
43
|
+
vols_by_name = xml_elements(xml, "domain/devices/disk/source", "name")
|
|
44
|
+
vols = []
|
|
45
|
+
vols_by_file.zip(vols_by_name).each do |by_file,by_name|
|
|
46
|
+
vols.push(by_file.nil? ? by_name : by_file)
|
|
47
|
+
end
|
|
48
|
+
vols
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def boot_order xml
|
|
52
|
+
xml_elements(xml, "domain/os/boot", "dev")
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def domain_interfaces xml
|
|
56
|
+
ifs = xml_elements(xml, "domain/devices/interface")
|
|
57
|
+
ifs.map { |i|
|
|
58
|
+
nics.new({
|
|
59
|
+
:type => i['type'],
|
|
60
|
+
:mac => (i/'mac').first[:address],
|
|
61
|
+
:network => ((i/'source').first[:network] rescue nil),
|
|
62
|
+
:bridge => ((i/'source').first[:bridge] rescue nil),
|
|
63
|
+
:model => ((i/'model').first[:type] rescue nil),
|
|
64
|
+
}.reject{|k,v| v.nil?})
|
|
65
|
+
}
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def domain_to_attributes(dom)
|
|
69
|
+
states= %w(nostate running blocked paused shutting-down shutoff crashed pmsuspended)
|
|
70
|
+
|
|
71
|
+
begin
|
|
72
|
+
{
|
|
73
|
+
:id => dom.uuid,
|
|
74
|
+
:uuid => dom.uuid,
|
|
75
|
+
:name => dom.name,
|
|
76
|
+
:max_memory_size => dom.info.max_mem,
|
|
77
|
+
:cputime => dom.info.cpu_time,
|
|
78
|
+
:memory_size => dom.info.memory,
|
|
79
|
+
:cpus => dom.info.nr_virt_cpu,
|
|
80
|
+
:autostart => dom.autostart?,
|
|
81
|
+
:os_type => dom.os_type,
|
|
82
|
+
:active => dom.active?,
|
|
83
|
+
:display => domain_display(dom.xml_desc),
|
|
84
|
+
:boot_order => boot_order(dom.xml_desc),
|
|
85
|
+
:nics => domain_interfaces(dom.xml_desc),
|
|
86
|
+
:volumes_path => domain_volumes(dom.xml_desc),
|
|
87
|
+
:state => states[dom.info.state]
|
|
88
|
+
}
|
|
89
|
+
rescue ::Libvirt::RetrieveError, ::Libvirt::Error
|
|
90
|
+
# Catch libvirt exceptions to avoid race conditions involving
|
|
91
|
+
# concurrent libvirt operations (like from another process)
|
|
92
|
+
return nil
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
class Mock
|
|
98
|
+
def list_domains(filter = { })
|
|
99
|
+
dom1 = mock_domain 'fog-dom1'
|
|
100
|
+
dom2 = mock_domain 'fog-dom2'
|
|
101
|
+
dom3 = mock_domain 'a-fog-dom3'
|
|
102
|
+
[dom1, dom2, dom3]
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def mock_domain name
|
|
106
|
+
xml = read_xml 'domain.xml'
|
|
107
|
+
{
|
|
108
|
+
:id => "dom.uuid",
|
|
109
|
+
:uuid => "dom.uuid",
|
|
110
|
+
:name => name,
|
|
111
|
+
:max_memory_size => 8,
|
|
112
|
+
:cputime => 7,
|
|
113
|
+
:memory_size => 6,
|
|
114
|
+
:cpus => 5,
|
|
115
|
+
:autostart => false,
|
|
116
|
+
:os_type => "RHEL6",
|
|
117
|
+
:active => false,
|
|
118
|
+
:vnc_port => 5910,
|
|
119
|
+
:boot_order => boot_order(xml),
|
|
120
|
+
:nics => domain_interfaces(xml),
|
|
121
|
+
:volumes_path => domain_volumes(xml),
|
|
122
|
+
:state => 'shutoff'
|
|
123
|
+
}
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
module Fog
|
|
2
|
+
module Libvirt
|
|
3
|
+
class Compute
|
|
4
|
+
class Real
|
|
5
|
+
def list_interfaces(filter = { })
|
|
6
|
+
data=[]
|
|
7
|
+
if filter.keys.empty?
|
|
8
|
+
active_networks = client.list_interfaces rescue []
|
|
9
|
+
defined_networks = client.list_defined_interfaces rescue []
|
|
10
|
+
(active_networks + defined_networks).each do |ifname|
|
|
11
|
+
data << interface_to_attributes(client.lookup_interface_by_name(ifname))
|
|
12
|
+
end
|
|
13
|
+
else
|
|
14
|
+
data = [interface_to_attributes(get_interface_by_filter(filter))]
|
|
15
|
+
end
|
|
16
|
+
data.compact
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
# Retrieve the interface by mac or by name
|
|
21
|
+
def get_interface_by_filter(filter)
|
|
22
|
+
case filter.keys.first
|
|
23
|
+
when :mac
|
|
24
|
+
client.lookup_interface_by_mac(filter[:mac])
|
|
25
|
+
when :name
|
|
26
|
+
client.lookup_interface_by_name(filter[:name])
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def interface_to_attributes(net)
|
|
31
|
+
return if net.nil? || net.name == 'lo'
|
|
32
|
+
{
|
|
33
|
+
:mac => net.mac,
|
|
34
|
+
:name => net.name,
|
|
35
|
+
:active => net.active?
|
|
36
|
+
}
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
class Mock
|
|
41
|
+
def list_interfaces(filters={ })
|
|
42
|
+
if1 = mock_interface 'if1'
|
|
43
|
+
if2 = mock_interface 'if2'
|
|
44
|
+
[if1, if2]
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def mock_interface name
|
|
48
|
+
{
|
|
49
|
+
:mac => 'aa:bb:cc:dd:ee:ff',
|
|
50
|
+
:name => name,
|
|
51
|
+
:active => true
|
|
52
|
+
}
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
module Fog
|
|
2
|
+
module Libvirt
|
|
3
|
+
class Compute
|
|
4
|
+
class Real
|
|
5
|
+
def list_networks(filter = { })
|
|
6
|
+
data=[]
|
|
7
|
+
if filter.keys.empty?
|
|
8
|
+
(client.list_networks + client.list_defined_networks).each do |network_name|
|
|
9
|
+
data << network_to_attributes(client.lookup_network_by_name(network_name))
|
|
10
|
+
end
|
|
11
|
+
else
|
|
12
|
+
data = [network_to_attributes(get_network_by_filter(filter))]
|
|
13
|
+
end
|
|
14
|
+
data
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
private
|
|
18
|
+
# Retrieve the network by uuid or name
|
|
19
|
+
def get_network_by_filter(filter)
|
|
20
|
+
case filter.keys.first
|
|
21
|
+
when :uuid
|
|
22
|
+
client.lookup_network_by_uuid(filter[:uuid])
|
|
23
|
+
when :name
|
|
24
|
+
client.lookup_network_by_name(filter[:name])
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# bridge name may not be defined in some networks, we should skip that in such case
|
|
29
|
+
def network_to_attributes(net)
|
|
30
|
+
return if net.nil?
|
|
31
|
+
|
|
32
|
+
begin
|
|
33
|
+
bridge_name = net.bridge_name
|
|
34
|
+
rescue ::Libvirt::Error
|
|
35
|
+
bridge_name = ''
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
{
|
|
39
|
+
:uuid => net.uuid,
|
|
40
|
+
:name => net.name,
|
|
41
|
+
:bridge_name => bridge_name
|
|
42
|
+
}
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
class Mock
|
|
47
|
+
def list_networks(filters={ })
|
|
48
|
+
[ {
|
|
49
|
+
:uuid => 'a29146ea-39b2-412d-8f53-239eef117a32',
|
|
50
|
+
:name => 'net1',
|
|
51
|
+
:bridge_name => 'virbr0'
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
:uuid => 'fbd4ac68-cbea-4f95-86ed-22953fd92384',
|
|
55
|
+
:name => 'net2',
|
|
56
|
+
:bridge_name => 'virbr1'
|
|
57
|
+
}
|
|
58
|
+
]
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module Fog
|
|
2
|
+
module Libvirt
|
|
3
|
+
class Compute
|
|
4
|
+
class Real
|
|
5
|
+
def list_pool_volumes(uuid)
|
|
6
|
+
pool = client.lookup_storage_pool_by_uuid uuid
|
|
7
|
+
pool.list_volumes.map do |volume_name|
|
|
8
|
+
volume_to_attributes(pool.lookup_volume_by_name(volume_name))
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
class Mock
|
|
14
|
+
def list_pool_volumes(uuid)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
module Fog
|
|
2
|
+
module Libvirt
|
|
3
|
+
class Compute
|
|
4
|
+
class Real
|
|
5
|
+
def list_pools(filter = { })
|
|
6
|
+
data=[]
|
|
7
|
+
if filter.key?(:name)
|
|
8
|
+
data << find_pool_by_name(filter[:name])
|
|
9
|
+
elsif filter.key?(:uuid)
|
|
10
|
+
data << find_pool_by_uuid(filter[:uuid])
|
|
11
|
+
else
|
|
12
|
+
(client.list_storage_pools + client.list_defined_storage_pools).each do |name|
|
|
13
|
+
data << find_pool_by_name(name)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
data.compact
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
def pool_to_attributes(pool)
|
|
21
|
+
states=[:inactive, :building, :running, :degrated, :inaccessible]
|
|
22
|
+
{
|
|
23
|
+
:uuid => pool.uuid,
|
|
24
|
+
:persistent => pool.persistent?,
|
|
25
|
+
:autostart => pool.autostart?,
|
|
26
|
+
:active => pool.active?,
|
|
27
|
+
:name => pool.name,
|
|
28
|
+
:allocation => pool.info.allocation,
|
|
29
|
+
:capacity => pool.info.capacity,
|
|
30
|
+
:num_of_volumes => pool.num_of_volumes,
|
|
31
|
+
:state => states[pool.info.state]
|
|
32
|
+
}
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def find_pool_by_name name
|
|
36
|
+
pool_to_attributes(client.lookup_storage_pool_by_name(name))
|
|
37
|
+
rescue ::Libvirt::RetrieveError
|
|
38
|
+
nil
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def find_pool_by_uuid uuid
|
|
42
|
+
pool_to_attributes(client.lookup_storage_pool_by_uuid(uuid))
|
|
43
|
+
rescue ::Libvirt::RetrieveError
|
|
44
|
+
nil
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
class Mock
|
|
49
|
+
def list_pools(filter = { })
|
|
50
|
+
pool1 = mock_pool 'pool1'
|
|
51
|
+
pool2 = mock_pool 'pool1'
|
|
52
|
+
[pool1, pool2]
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def mock_pool name
|
|
56
|
+
{
|
|
57
|
+
:uuid => 'pool.uuid',
|
|
58
|
+
:persistent => true,
|
|
59
|
+
:autostart => true,
|
|
60
|
+
:active => true,
|
|
61
|
+
:name => name,
|
|
62
|
+
:allocation => 123456789,
|
|
63
|
+
:capacity => 123456789,
|
|
64
|
+
:num_of_volumes => 3,
|
|
65
|
+
:state => :running
|
|
66
|
+
}
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
module Fog
|
|
2
|
+
module Libvirt
|
|
3
|
+
class Compute
|
|
4
|
+
class Real
|
|
5
|
+
def list_volumes(filter = { })
|
|
6
|
+
data = []
|
|
7
|
+
if filter.keys.empty?
|
|
8
|
+
raw_volumes do |pool|
|
|
9
|
+
pool.list_volumes.each do |volume_name|
|
|
10
|
+
begin
|
|
11
|
+
data << volume_to_attributes(pool.lookup_volume_by_name(volume_name))
|
|
12
|
+
rescue ::Libvirt::RetrieveError
|
|
13
|
+
# Catch libvirt exceptions to avoid race conditions involving
|
|
14
|
+
# concurrent libvirt operations (like from another process)
|
|
15
|
+
next
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
else
|
|
20
|
+
data << get_volume(filter)
|
|
21
|
+
end
|
|
22
|
+
data.compact
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def volume_to_attributes(vol)
|
|
28
|
+
format_type = xml_element(vol.xml_desc, "/volume/target/format", "type") rescue nil # not all volumes have types, e.g. LVM
|
|
29
|
+
return nil if format_type == "dir"
|
|
30
|
+
|
|
31
|
+
begin
|
|
32
|
+
{
|
|
33
|
+
:pool_name => vol.pool.name,
|
|
34
|
+
:key => vol.key,
|
|
35
|
+
:id => vol.key,
|
|
36
|
+
:path => vol.path,
|
|
37
|
+
:name => vol.name,
|
|
38
|
+
:format_type => format_type,
|
|
39
|
+
:allocation => bytes_to_gb(vol.info.allocation),
|
|
40
|
+
:capacity => bytes_to_gb(vol.info.capacity),
|
|
41
|
+
}
|
|
42
|
+
rescue ::Libvirt::RetrieveError, ::Libvirt::Error
|
|
43
|
+
return nil # If there are issues during stat of volume file
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def bytes_to_gb bytes
|
|
48
|
+
bytes / 1024**3
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def raw_volumes
|
|
52
|
+
client.list_storage_pools.each do |pool_name|
|
|
53
|
+
pool = client.lookup_storage_pool_by_name(pool_name)
|
|
54
|
+
yield(pool)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def get_volume filter = { }, raw = false
|
|
59
|
+
raw_volumes do |pool|
|
|
60
|
+
vol = case filter.keys.first
|
|
61
|
+
when :name
|
|
62
|
+
pool.lookup_volume_by_name(filter[:name]) rescue nil
|
|
63
|
+
when :key
|
|
64
|
+
pool.lookup_volume_by_key(filter[:key]) rescue nil
|
|
65
|
+
when :path
|
|
66
|
+
pool.lookup_volume_by_path(filter[:path]) rescue nil
|
|
67
|
+
end
|
|
68
|
+
if vol
|
|
69
|
+
return raw ? vol : volume_to_attributes(vol)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
nil
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
class Mock
|
|
78
|
+
def list_volumes(filters={ })
|
|
79
|
+
vol1 = mock_volume 'vol1'
|
|
80
|
+
vol2 = mock_volume 'vol2'
|
|
81
|
+
vols = [vol1, vol2]
|
|
82
|
+
|
|
83
|
+
if filters.keys.empty?
|
|
84
|
+
return vols
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
key = filters.keys.first
|
|
88
|
+
vols.select { |v| v[key] == filters[key] }
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def mock_volume name
|
|
92
|
+
{
|
|
93
|
+
:pool_name => 'vol.pool.name',
|
|
94
|
+
:key => "vol.#{name}", # needs to match id
|
|
95
|
+
:id => "vol.#{name}",
|
|
96
|
+
:path => "path/to/disk", # used by in mock_files/domain.xml
|
|
97
|
+
:name => name,
|
|
98
|
+
:format_type => 'raw',
|
|
99
|
+
:allocation => 123,
|
|
100
|
+
:capacity => 123,
|
|
101
|
+
}
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
<domain type='kvm'>
|
|
2
|
+
<name>fog-449765558356062</name>
|
|
3
|
+
<memory>262144</memory>
|
|
4
|
+
<vcpu>1</vcpu>
|
|
5
|
+
<os>
|
|
6
|
+
<type arch='x86_64'>hvm</type>
|
|
7
|
+
<boot dev='hd'/>
|
|
8
|
+
<boot dev='cdrom'/>
|
|
9
|
+
<boot dev='network'/>
|
|
10
|
+
</os>
|
|
11
|
+
<features>
|
|
12
|
+
<acpi/>
|
|
13
|
+
<apic/>
|
|
14
|
+
<pae/>
|
|
15
|
+
</features>
|
|
16
|
+
<clock offset='utc'/>
|
|
17
|
+
<devices>
|
|
18
|
+
<interface type='network'>
|
|
19
|
+
<mac address="aa:bb:cc:dd:ee:ff" />
|
|
20
|
+
<source network='net1' />
|
|
21
|
+
<model type='virtio'/>
|
|
22
|
+
</interface>
|
|
23
|
+
<serial type='pty'>
|
|
24
|
+
<target port='0'/>
|
|
25
|
+
</serial>
|
|
26
|
+
<console type='pty'>
|
|
27
|
+
<target port='0'/>
|
|
28
|
+
</console>
|
|
29
|
+
<input type='mouse' bus='ps2'/>
|
|
30
|
+
<graphics type='vnc' port='-1' autoport='yes'/>
|
|
31
|
+
<video>
|
|
32
|
+
<model type='cirrus' vram='9216' heads='1'/>
|
|
33
|
+
</video>
|
|
34
|
+
<disk type='file' device='disk'>
|
|
35
|
+
<driver name='qemu' type='raw'/>
|
|
36
|
+
<source file='path/to/disk'/>
|
|
37
|
+
<target dev='vda' bus='virtio'/>
|
|
38
|
+
</disk>
|
|
39
|
+
</devices>
|
|
40
|
+
</domain>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module Fog
|
|
2
|
+
module Libvirt
|
|
3
|
+
class Compute
|
|
4
|
+
class Real
|
|
5
|
+
def pool_action(uuid, action)
|
|
6
|
+
pool = client.lookup_storage_pool_by_uuid uuid
|
|
7
|
+
pool.send(action)
|
|
8
|
+
true
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
class Mock
|
|
13
|
+
def pool_action(uuid, action)
|
|
14
|
+
true
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module Fog
|
|
2
|
+
module Libvirt
|
|
3
|
+
class Compute
|
|
4
|
+
class Real
|
|
5
|
+
def update_autostart(uuid, value)
|
|
6
|
+
domain = client.lookup_domain_by_uuid(uuid)
|
|
7
|
+
domain.autostart = value
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
class Mock
|
|
12
|
+
def update_autostart(uuid, value)
|
|
13
|
+
value
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
module Fog
|
|
2
|
+
module Libvirt
|
|
3
|
+
class Compute
|
|
4
|
+
class Real
|
|
5
|
+
def update_display(options = { })
|
|
6
|
+
raise ArgumentError, "uuid is a required parameter" unless options.key? :uuid
|
|
7
|
+
|
|
8
|
+
domain = client.lookup_domain_by_uuid(options[:uuid])
|
|
9
|
+
|
|
10
|
+
display = { }
|
|
11
|
+
display[:type] = options[:type] || 'vnc'
|
|
12
|
+
display[:port] = (options[:port] || -1).to_s
|
|
13
|
+
display[:listen] = options[:listen].to_s if options[:listen]
|
|
14
|
+
display[:passwd] = options[:password].to_s if options[:password]
|
|
15
|
+
display[:autoport] = 'yes' if display[:port] == '-1'
|
|
16
|
+
new_keymap = options[:keymap] || xml_elements(domain.xml_desc, "graphics", "keymap")[0]
|
|
17
|
+
display[:keymap] = new_keymap unless new_keymap.nil?
|
|
18
|
+
|
|
19
|
+
builder = Nokogiri::XML::Builder.new { graphics_ (display) }
|
|
20
|
+
xml = Nokogiri::XML(builder.to_xml).root.to_s
|
|
21
|
+
|
|
22
|
+
domain.update_device(xml, 0)
|
|
23
|
+
# if we got no exceptions, then we're good'
|
|
24
|
+
true
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
class Mock
|
|
29
|
+
def update_display(options = { })
|
|
30
|
+
raise ArgumentError, "uuid is a required parameter" unless options.key? :uuid
|
|
31
|
+
true
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
module Fog
|
|
2
|
+
module Libvirt
|
|
3
|
+
class Compute
|
|
4
|
+
class Real
|
|
5
|
+
def upload_volume(pool_name, volume_name, file_path)
|
|
6
|
+
volume = client.lookup_storage_pool_by_name(pool_name).lookup_volume_by_name(volume_name)
|
|
7
|
+
stream = client.stream
|
|
8
|
+
|
|
9
|
+
image_file = File.open(file_path, "rb")
|
|
10
|
+
volume.upload(stream, 0, image_file.size)
|
|
11
|
+
stream.sendall do |_opaque, n|
|
|
12
|
+
begin
|
|
13
|
+
r = image_file.read(n)
|
|
14
|
+
r ? [r.length, r] : [0, ""]
|
|
15
|
+
rescue Exception => e
|
|
16
|
+
[-1, ""]
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
stream.finish
|
|
20
|
+
ensure
|
|
21
|
+
image_file.close if image_file
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
class Mock
|
|
26
|
+
def upload_volume(pool_name, volume_name, file_path)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module Fog
|
|
2
|
+
module Libvirt
|
|
3
|
+
class Compute
|
|
4
|
+
class Real
|
|
5
|
+
def vm_action(uuid, action, *args)
|
|
6
|
+
domain = client.lookup_domain_by_uuid(uuid)
|
|
7
|
+
domain.send(action, *args)
|
|
8
|
+
true
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
class Mock
|
|
13
|
+
def vm_action(uuid, action)
|
|
14
|
+
true
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module Fog
|
|
2
|
+
module Libvirt
|
|
3
|
+
class Compute
|
|
4
|
+
class Real
|
|
5
|
+
def volume_action(key, action, options={})
|
|
6
|
+
get_volume({:key => key}, true).send(action)
|
|
7
|
+
true
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
class Mock
|
|
12
|
+
def volume_action(action, options={})
|
|
13
|
+
true
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|