fog-libvirt 0.0.1
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 +23 -0
- data/Gemfile +9 -0
- data/LICENSE.md +20 -0
- data/README.md +29 -0
- data/Rakefile +122 -0
- data/fog-libvirt.gemspec +49 -0
- data/lib/fog/bin/libvirt.rb +58 -0
- data/lib/fog/libvirt/compute.rb +136 -0
- data/lib/fog/libvirt/models/compute/README.md +76 -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 +29 -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 +401 -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 +54 -0
- data/lib/fog/libvirt/models/compute/templates/volume.xml.erb +26 -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 +122 -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/get_node_info.rb +37 -0
- data/lib/fog/libvirt/requests/compute/list_domains.rb +105 -0
- data/lib/fog/libvirt/requests/compute/list_interfaces.rb +57 -0
- data/lib/fog/libvirt/requests/compute/list_networks.rb +55 -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 +88 -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_display.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 +18 -0
- data/tests/helper.rb +17 -0
- data/tests/helpers/formats_helper.rb +98 -0
- data/tests/helpers/formats_helper_tests.rb +110 -0
- data/tests/helpers/mock_helper.rb +14 -0
- data/tests/helpers/succeeds_helper.rb +9 -0
- data/tests/libvirt/compute_tests.rb +17 -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 +27 -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 +58 -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 +14 -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/update_display.rb +13 -0
- metadata +355 -0
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'fog/core/model'
|
2
|
+
|
3
|
+
module Fog
|
4
|
+
module Compute
|
5
|
+
class Libvirt
|
6
|
+
class Node < Fog::Model
|
7
|
+
identity :uuid
|
8
|
+
|
9
|
+
attribute :model
|
10
|
+
attribute :memory
|
11
|
+
attribute :cpus
|
12
|
+
attribute :mhz
|
13
|
+
attribute :nodes
|
14
|
+
attribute :sockets
|
15
|
+
attribute :cores
|
16
|
+
attribute :threads
|
17
|
+
attribute :type
|
18
|
+
attribute :version
|
19
|
+
attribute :uri
|
20
|
+
attribute :node_free_memory
|
21
|
+
attribute :max_vcpus
|
22
|
+
attribute :manufacturer
|
23
|
+
attribute :product
|
24
|
+
attribute :serial
|
25
|
+
attribute :hostname
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'fog/core/collection'
|
2
|
+
require 'fog/libvirt/models/compute/node'
|
3
|
+
|
4
|
+
module Fog
|
5
|
+
module Compute
|
6
|
+
class Libvirt
|
7
|
+
class Nodes < Fog::Collection
|
8
|
+
model Fog::Compute::Libvirt::Node
|
9
|
+
|
10
|
+
def all(filter={ })
|
11
|
+
load(service.get_node_info)
|
12
|
+
end
|
13
|
+
|
14
|
+
def get
|
15
|
+
all.first
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'fog/core/model'
|
2
|
+
|
3
|
+
module Fog
|
4
|
+
module Compute
|
5
|
+
class Libvirt
|
6
|
+
class Pool < Fog::Model
|
7
|
+
attr_reader :xml
|
8
|
+
|
9
|
+
identity :uuid
|
10
|
+
|
11
|
+
attribute :persistent
|
12
|
+
attribute :autostart
|
13
|
+
attribute :active
|
14
|
+
attribute :name
|
15
|
+
attribute :allocation
|
16
|
+
attribute :capacity
|
17
|
+
attribute :num_of_volumes
|
18
|
+
attribute :state
|
19
|
+
|
20
|
+
def initialize(attributes={} )
|
21
|
+
# Can be created by passing in XML
|
22
|
+
@xml = attributes.delete(:xml)
|
23
|
+
super(attributes)
|
24
|
+
end
|
25
|
+
|
26
|
+
def save
|
27
|
+
raise Fog::Errors::Error.new('Creating a new pool requires proper xml') unless xml
|
28
|
+
self.uuid = (persistent ? service.define_pool(xml) : service.create_pool(xml)).uuid
|
29
|
+
reload
|
30
|
+
end
|
31
|
+
|
32
|
+
# Start the pool = make it active
|
33
|
+
# Performs a libvirt create (= start)
|
34
|
+
def start
|
35
|
+
service.pool_action uuid, :create
|
36
|
+
end
|
37
|
+
|
38
|
+
# Stop the pool = make it non-active
|
39
|
+
# Performs a libvirt destroy (= stop)
|
40
|
+
def stop
|
41
|
+
service.pool_action uuid, :destroy
|
42
|
+
end
|
43
|
+
|
44
|
+
# Shuts down the pool
|
45
|
+
def shutdown
|
46
|
+
stop
|
47
|
+
end
|
48
|
+
|
49
|
+
# Build this storage pool
|
50
|
+
def build
|
51
|
+
service.pool_action uuid, :build
|
52
|
+
end
|
53
|
+
|
54
|
+
# Destroys the storage pool
|
55
|
+
def destroy
|
56
|
+
# Shutdown pool if active
|
57
|
+
service.pool_action uuid, :destroy if active?
|
58
|
+
# If this is a persistent domain we need to undefine it
|
59
|
+
service.pool_action uuid, :undefine if persistent?
|
60
|
+
end
|
61
|
+
|
62
|
+
# Is the pool active or not?
|
63
|
+
def active?
|
64
|
+
active
|
65
|
+
end
|
66
|
+
|
67
|
+
# Will the pool autostart or not?
|
68
|
+
def auto_start?
|
69
|
+
autostart
|
70
|
+
end
|
71
|
+
|
72
|
+
# Is the pool persistent or not?
|
73
|
+
def persistent?
|
74
|
+
persistent
|
75
|
+
end
|
76
|
+
|
77
|
+
# Retrieves the volumes of this pool
|
78
|
+
def volumes
|
79
|
+
service.list_pool_volumes uuid
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'fog/core/collection'
|
2
|
+
require 'fog/libvirt/models/compute/pool'
|
3
|
+
|
4
|
+
module Fog
|
5
|
+
module Compute
|
6
|
+
class Libvirt
|
7
|
+
class Pools < Fog::Collection
|
8
|
+
model Fog::Compute::Libvirt::Pool
|
9
|
+
|
10
|
+
def all(filter = {})
|
11
|
+
load(service.list_pools(filter))
|
12
|
+
end
|
13
|
+
|
14
|
+
def get(uuid)
|
15
|
+
self.all(:uuid => uuid).first
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,401 @@
|
|
1
|
+
require 'fog/compute/models/server'
|
2
|
+
require 'fog/libvirt/models/compute/util/util'
|
3
|
+
require 'net/ssh/proxy/command'
|
4
|
+
|
5
|
+
module Fog
|
6
|
+
module Compute
|
7
|
+
class Libvirt
|
8
|
+
class Server < Fog::Compute::Server
|
9
|
+
include Fog::Compute::LibvirtUtil
|
10
|
+
attr_reader :xml
|
11
|
+
|
12
|
+
identity :id, :aliases => 'uuid'
|
13
|
+
|
14
|
+
attribute :cpus
|
15
|
+
attribute :cputime
|
16
|
+
attribute :os_type
|
17
|
+
attribute :memory_size
|
18
|
+
attribute :max_memory_size
|
19
|
+
attribute :name
|
20
|
+
attribute :arch
|
21
|
+
attribute :persistent
|
22
|
+
attribute :domain_type
|
23
|
+
attribute :uuid
|
24
|
+
attribute :autostart
|
25
|
+
attribute :nics
|
26
|
+
attribute :volumes
|
27
|
+
attribute :active
|
28
|
+
attribute :boot_order
|
29
|
+
attribute :display
|
30
|
+
|
31
|
+
attribute :state
|
32
|
+
|
33
|
+
# The following attributes are only needed when creating a new vm
|
34
|
+
#TODO: Add depreciation warning
|
35
|
+
attr_accessor :iso_dir, :iso_file
|
36
|
+
attr_accessor :network_interface_type ,:network_nat_network, :network_bridge_name
|
37
|
+
attr_accessor :volume_format_type, :volume_allocation,:volume_capacity, :volume_name, :volume_pool_name, :volume_template_name, :volume_path
|
38
|
+
attr_accessor :password
|
39
|
+
|
40
|
+
# Can be created by passing in :xml => "<xml to create domain/server>"
|
41
|
+
# or by providing :template_options => {
|
42
|
+
# :name => "", :cpus => 1, :memory_size => 256 , :volume_template
|
43
|
+
# }
|
44
|
+
|
45
|
+
def initialize(attributes={} )
|
46
|
+
@xml = attributes.delete(:xml)
|
47
|
+
verify_boot_order(attributes[:boot_order])
|
48
|
+
super defaults.merge(attributes)
|
49
|
+
initialize_nics
|
50
|
+
initialize_volumes
|
51
|
+
end
|
52
|
+
|
53
|
+
def new?
|
54
|
+
uuid.nil?
|
55
|
+
end
|
56
|
+
|
57
|
+
def save
|
58
|
+
raise Fog::Errors::Error.new('Saving an existing server may create a duplicate') unless new?
|
59
|
+
create_or_clone_volume unless xml or @volumes
|
60
|
+
@xml ||= to_xml
|
61
|
+
self.id = (persistent ? service.define_domain(xml) : service.create_domain(xml)).uuid
|
62
|
+
reload
|
63
|
+
rescue => e
|
64
|
+
raise Fog::Errors::Error.new("Error saving the server: #{e}")
|
65
|
+
end
|
66
|
+
|
67
|
+
def start
|
68
|
+
return true if active?
|
69
|
+
action_status = service.vm_action(uuid, :create)
|
70
|
+
reload
|
71
|
+
action_status
|
72
|
+
end
|
73
|
+
|
74
|
+
def mac
|
75
|
+
nics.first.mac if nics && nics.first
|
76
|
+
end
|
77
|
+
|
78
|
+
def disk_path
|
79
|
+
volumes.first.path if volumes and volumes.first
|
80
|
+
end
|
81
|
+
|
82
|
+
def destroy(options={ :destroy_volumes => false})
|
83
|
+
poweroff unless stopped?
|
84
|
+
service.vm_action(uuid, :undefine)
|
85
|
+
volumes.each { |vol| vol.destroy } if options[:destroy_volumes]
|
86
|
+
true
|
87
|
+
end
|
88
|
+
|
89
|
+
def reboot
|
90
|
+
action_status = service.vm_action(uuid, :reboot)
|
91
|
+
reload
|
92
|
+
action_status
|
93
|
+
end
|
94
|
+
|
95
|
+
def poweroff
|
96
|
+
action_status = service.vm_action(uuid, :destroy)
|
97
|
+
reload
|
98
|
+
action_status
|
99
|
+
end
|
100
|
+
|
101
|
+
def shutdown
|
102
|
+
action_status = service.vm_action(uuid, :shutdown)
|
103
|
+
reload
|
104
|
+
action_status
|
105
|
+
end
|
106
|
+
|
107
|
+
def resume
|
108
|
+
action_status = service.vm_action(uuid, :resume)
|
109
|
+
reload
|
110
|
+
action_status
|
111
|
+
end
|
112
|
+
|
113
|
+
def suspend
|
114
|
+
action_status = service.vm_action(uuid, :suspend)
|
115
|
+
reload
|
116
|
+
action_status
|
117
|
+
end
|
118
|
+
|
119
|
+
def stopped?
|
120
|
+
state == "shutoff"
|
121
|
+
end
|
122
|
+
|
123
|
+
def ready?
|
124
|
+
state == "running"
|
125
|
+
end
|
126
|
+
|
127
|
+
#alias methods
|
128
|
+
alias_method :halt, :poweroff
|
129
|
+
alias_method :stop, :shutdown
|
130
|
+
alias_method :active?, :active
|
131
|
+
|
132
|
+
def volumes
|
133
|
+
# lazy loading of volumes
|
134
|
+
@volumes ||= (@volumes_path || []).map{|path| service.volumes.all(:path => path).first }
|
135
|
+
end
|
136
|
+
|
137
|
+
def private_ip_address
|
138
|
+
ip_address(:private)
|
139
|
+
end
|
140
|
+
|
141
|
+
def public_ip_address
|
142
|
+
ip_address(:public)
|
143
|
+
end
|
144
|
+
|
145
|
+
def ssh(commands)
|
146
|
+
requires :ssh_ip_address, :username
|
147
|
+
|
148
|
+
ssh_options={}
|
149
|
+
ssh_options[:password] = password unless password.nil?
|
150
|
+
ssh_options[:proxy]= ssh_proxy unless ssh_proxy.nil?
|
151
|
+
|
152
|
+
super(commands, ssh_options)
|
153
|
+
end
|
154
|
+
|
155
|
+
def ssh_proxy
|
156
|
+
# if this is a direct connection, we don't need a proxy to be set.
|
157
|
+
return nil unless connection.uri.ssh_enabled?
|
158
|
+
user_string= service.uri.user ? "-l #{service.uri.user}" : ""
|
159
|
+
Net::SSH::Proxy::Command.new("ssh #{user_string} #{service.uri.host} nc %h %p")
|
160
|
+
end
|
161
|
+
|
162
|
+
# Transfers a file
|
163
|
+
def scp(local_path, remote_path, upload_options = {})
|
164
|
+
requires :ssh_ip_address, :username
|
165
|
+
|
166
|
+
scp_options = {}
|
167
|
+
scp_options[:password] = password unless self.password.nil?
|
168
|
+
scp_options[:key_data] = [private_key] if self.private_key
|
169
|
+
scp_options[:proxy]= ssh_proxy unless self.ssh_proxy.nil?
|
170
|
+
|
171
|
+
Fog::SCP.new(ssh_ip_address, username, scp_options).upload(local_path, remote_path, upload_options)
|
172
|
+
end
|
173
|
+
|
174
|
+
# Sets up a new key
|
175
|
+
def setup(credentials = {})
|
176
|
+
requires :public_key, :ssh_ip_address, :username
|
177
|
+
|
178
|
+
credentials[:proxy]= ssh_proxy unless ssh_proxy.nil?
|
179
|
+
credentials[:password] = password unless self.password.nil?
|
180
|
+
credentails[:key_data] = [private_key] if self.private_key
|
181
|
+
|
182
|
+
commands = [
|
183
|
+
%{mkdir .ssh},
|
184
|
+
# %{passwd -l #{username}}, #Not sure if we need this here
|
185
|
+
# %{echo "#{Fog::JSON.encode(attributes)}" >> ~/attributes.json}
|
186
|
+
]
|
187
|
+
if public_key
|
188
|
+
commands << %{echo "#{public_key}" >> ~/.ssh/authorized_keys}
|
189
|
+
end
|
190
|
+
|
191
|
+
# wait for domain to be ready
|
192
|
+
Timeout::timeout(360) do
|
193
|
+
begin
|
194
|
+
Timeout::timeout(8) do
|
195
|
+
Fog::SSH.new(ssh_ip_address, username, credentials.merge(:timeout => 4)).run('pwd')
|
196
|
+
end
|
197
|
+
rescue Errno::ECONNREFUSED
|
198
|
+
sleep(2)
|
199
|
+
retry
|
200
|
+
rescue Net::SSH::AuthenticationFailed, Timeout::Error
|
201
|
+
retry
|
202
|
+
end
|
203
|
+
end
|
204
|
+
Fog::SSH.new(ssh_ip_address, username, credentials).run(commands)
|
205
|
+
end
|
206
|
+
|
207
|
+
def update_display attrs = {}
|
208
|
+
service.update_display attrs.merge(:uuid => uuid)
|
209
|
+
reload
|
210
|
+
end
|
211
|
+
|
212
|
+
# can't use deprecate method, as the value is part of the display hash
|
213
|
+
def vnc_port
|
214
|
+
Fog::Logger.deprecation("#{self.class} => #vnc_port is deprecated, use #display[:port] instead [light_black](#{caller.first})[/]")
|
215
|
+
display[:port]
|
216
|
+
end
|
217
|
+
|
218
|
+
private
|
219
|
+
attr_accessor :volumes_path
|
220
|
+
|
221
|
+
# This retrieves the ip address of the mac address
|
222
|
+
# It returns an array of public and private ip addresses
|
223
|
+
# Currently only one ip address is returned, but in the future this could be multiple
|
224
|
+
# if the server has multiple network interface
|
225
|
+
def addresses(service_arg=service, options={})
|
226
|
+
mac=self.mac
|
227
|
+
|
228
|
+
# Aug 24 17:34:41 juno arpwatch: new station 10.247.4.137 52:54:00:88:5a:0a eth0.4
|
229
|
+
# Aug 24 17:37:19 juno arpwatch: changed ethernet address 10.247.4.137 52:54:00:27:33:00 (52:54:00:88:5a:0a) eth0.4
|
230
|
+
# Check if another ip_command string was provided
|
231
|
+
ip_command_global=service_arg.ip_command.nil? ? 'grep $mac /var/log/arpwatch.log|sed -e "s/new station//"|sed -e "s/changed ethernet address//g" |sed -e "s/reused old ethernet //" |tail -1 |cut -d ":" -f 4-| cut -d " " -f 3' : service_arg.ip_command
|
232
|
+
ip_command_local=options[:ip_command].nil? ? ip_command_global : options[:ip_command]
|
233
|
+
|
234
|
+
ip_command="mac=#{mac}; server_name=#{name}; "+ip_command_local
|
235
|
+
|
236
|
+
ip_address=nil
|
237
|
+
|
238
|
+
if service_arg.uri.ssh_enabled?
|
239
|
+
|
240
|
+
# Retrieve the parts we need from the service to setup our ssh options
|
241
|
+
user=service_arg.uri.user #could be nil
|
242
|
+
host=service_arg.uri.host
|
243
|
+
keyfile=service_arg.uri.keyfile
|
244
|
+
port=service_arg.uri.port
|
245
|
+
|
246
|
+
# Setup the options
|
247
|
+
ssh_options={}
|
248
|
+
ssh_options[:keys]=[ keyfile ] unless keyfile.nil?
|
249
|
+
ssh_options[:port]=port unless keyfile.nil?
|
250
|
+
ssh_options[:paranoid]=true if service_arg.uri.no_verify?
|
251
|
+
|
252
|
+
begin
|
253
|
+
result=Fog::SSH.new(host, user, ssh_options).run(ip_command)
|
254
|
+
rescue Errno::ECONNREFUSED
|
255
|
+
raise Fog::Errors::Error.new("Connection was refused to host #{host} to retrieve the ip_address for #{mac}")
|
256
|
+
rescue Net::SSH::AuthenticationFailed
|
257
|
+
raise Fog::Errors::Error.new("Error authenticating over ssh to host #{host} and user #{user}")
|
258
|
+
end
|
259
|
+
|
260
|
+
# Check for a clean exit code
|
261
|
+
if result.first.status == 0
|
262
|
+
ip_address=result.first.stdout.strip
|
263
|
+
else
|
264
|
+
# We got a failure executing the command
|
265
|
+
raise Fog::Errors::Error.new("The command #{ip_command} failed to execute with a clean exit code")
|
266
|
+
end
|
267
|
+
|
268
|
+
else
|
269
|
+
# It's not ssh enabled, so we assume it is
|
270
|
+
if service_arg.uri.transport=="tls"
|
271
|
+
raise Fog::Errors::Error.new("TlS remote transport is not currently supported, only ssh")
|
272
|
+
end
|
273
|
+
|
274
|
+
# Execute the ip_command locally
|
275
|
+
# Initialize empty ip_address string
|
276
|
+
ip_address=""
|
277
|
+
|
278
|
+
IO.popen("#{ip_command}") do |p|
|
279
|
+
p.each_line do |l|
|
280
|
+
ip_address+=l
|
281
|
+
end
|
282
|
+
status=Process.waitpid2(p.pid)[1].exitstatus
|
283
|
+
if status!=0
|
284
|
+
raise Fog::Errors::Error.new("The command #{ip_command} failed to execute with a clean exit code")
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
#Strip any new lines from the string
|
289
|
+
ip_address=ip_address.chomp
|
290
|
+
end
|
291
|
+
|
292
|
+
# The Ip-address command has been run either local or remote now
|
293
|
+
|
294
|
+
if ip_address==""
|
295
|
+
#The grep didn't find an ip address result"
|
296
|
+
ip_address=nil
|
297
|
+
else
|
298
|
+
# To be sure that the command didn't return another random string
|
299
|
+
# We check if the result is an actual ip-address
|
300
|
+
# otherwise we return nil
|
301
|
+
unless ip_address=~/^(\d{1,3}\.){3}\d{1,3}$/
|
302
|
+
raise Fog::Errors::Error.new(
|
303
|
+
"The result of #{ip_command} does not have valid ip-address format\n"+
|
304
|
+
"Result was: #{ip_address}\n"
|
305
|
+
)
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
return { :public => [ip_address], :private => [ip_address]}
|
310
|
+
end
|
311
|
+
|
312
|
+
def ip_address(key)
|
313
|
+
addresses[key].nil? ? nil : addresses[key].first
|
314
|
+
end
|
315
|
+
|
316
|
+
def initialize_nics
|
317
|
+
if nics
|
318
|
+
nics.map! { |nic| nic.is_a?(Hash) ? service.nics.new(nic) : nic }
|
319
|
+
else
|
320
|
+
self.nics = [service.nics.new({:type => network_interface_type, :bridge => network_bridge_name, :network => network_nat_network})]
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
def initialize_volumes
|
325
|
+
if attributes[:volumes] && !attributes[:volumes].empty?
|
326
|
+
@volumes = attributes[:volumes].map { |vol| vol.is_a?(Hash) ? service.volumes.new(vol) : vol }
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
330
|
+
def create_or_clone_volume
|
331
|
+
options = {:name => volume_name || default_volume_name}
|
332
|
+
# Check if a disk template was specified
|
333
|
+
if volume_template_name
|
334
|
+
template_volume = service.volumes.all(:name => volume_template_name).first
|
335
|
+
raise Fog::Errors::Error.new("Template #{volume_template_name} not found") unless template_volume
|
336
|
+
begin
|
337
|
+
volume = template_volume.clone("#{options[:name]}")
|
338
|
+
rescue => e
|
339
|
+
raise Fog::Errors::Error.new("Error creating the volume : #{e}")
|
340
|
+
end
|
341
|
+
else
|
342
|
+
# If no template volume was given, let's create our own volume
|
343
|
+
options[:pool_name] = volume_pool_name if volume_pool_name
|
344
|
+
options[:format_type] = volume_format_type if volume_format_type
|
345
|
+
options[:capacity] = volume_capacity if volume_capacity
|
346
|
+
options[:allocation] = volume_allocation if volume_allocation
|
347
|
+
|
348
|
+
begin
|
349
|
+
volume = service.volumes.create(options)
|
350
|
+
rescue => e
|
351
|
+
raise Fog::Errors::Error.new("Error creating the volume : #{e}")
|
352
|
+
end
|
353
|
+
end
|
354
|
+
@volumes.nil? ? @volumes = [volume] : @volumes << volume
|
355
|
+
end
|
356
|
+
|
357
|
+
def default_iso_dir
|
358
|
+
"/var/lib/libvirt/images"
|
359
|
+
end
|
360
|
+
|
361
|
+
def default_volume_name
|
362
|
+
"#{name}.#{volume_format_type || 'img'}"
|
363
|
+
end
|
364
|
+
|
365
|
+
def defaults
|
366
|
+
{
|
367
|
+
:persistent => true,
|
368
|
+
:cpus => 1,
|
369
|
+
:memory_size => 256 *1024,
|
370
|
+
:name => randomized_name,
|
371
|
+
:os_type => "hvm",
|
372
|
+
:arch => "x86_64",
|
373
|
+
:domain_type => "kvm",
|
374
|
+
:iso_dir => default_iso_dir,
|
375
|
+
:network_interface_type => "network",
|
376
|
+
:network_nat_network => "default",
|
377
|
+
:network_bridge_name => "br0",
|
378
|
+
:boot_order => default_boot_order,
|
379
|
+
:display => default_display
|
380
|
+
}
|
381
|
+
end
|
382
|
+
|
383
|
+
def default_boot_order
|
384
|
+
%w[hd cdrom network]
|
385
|
+
end
|
386
|
+
|
387
|
+
def verify_boot_order order = []
|
388
|
+
if order
|
389
|
+
order.each do |b|
|
390
|
+
raise "invalid boot order, possible values are: hd, network and/or cdrom" unless default_boot_order.include?(b)
|
391
|
+
end
|
392
|
+
end
|
393
|
+
end
|
394
|
+
|
395
|
+
def default_display
|
396
|
+
{:port => '-1', :listen => '127.0.0.1', :type => 'vnc', :password => '' }
|
397
|
+
end
|
398
|
+
end
|
399
|
+
end
|
400
|
+
end
|
401
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'fog/core/collection'
|
2
|
+
require 'fog/libvirt/models/compute/server'
|
3
|
+
|
4
|
+
module Fog
|
5
|
+
module Compute
|
6
|
+
class Libvirt
|
7
|
+
class Servers < Fog::Collection
|
8
|
+
model Fog::Compute::Libvirt::Server
|
9
|
+
|
10
|
+
def all(filter={})
|
11
|
+
load(service.list_domains(filter))
|
12
|
+
end
|
13
|
+
|
14
|
+
def get(uuid)
|
15
|
+
data = service.list_domains(:uuid => uuid)
|
16
|
+
new data.first if data
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
<domain type='<%= domain_type %>'>
|
2
|
+
<name><%= name %></name>
|
3
|
+
<memory><%= memory_size %></memory>
|
4
|
+
<vcpu><%= cpus %></vcpu>
|
5
|
+
<os>
|
6
|
+
<type arch='<%= arch %>'><%= os_type %></type>
|
7
|
+
<% boot_order.each do |dev| -%>
|
8
|
+
<boot dev='<%= dev %>'/>
|
9
|
+
<% end -%>
|
10
|
+
</os>
|
11
|
+
<features>
|
12
|
+
<acpi/>
|
13
|
+
<apic/>
|
14
|
+
<pae/>
|
15
|
+
</features>
|
16
|
+
<clock offset='utc'/>
|
17
|
+
<devices>
|
18
|
+
<% volumes.each do |vol| -%>
|
19
|
+
<disk type='file' device='disk'>
|
20
|
+
<driver name='qemu' type='<%= vol.format_type %>'/>
|
21
|
+
<source file='<%= vol.path %>'/>
|
22
|
+
<%# we need to ensure a unique target dev -%>
|
23
|
+
<target dev='vd<%= ('a'..'z').to_a[volumes.index(vol)] %>' bus='virtio'/>
|
24
|
+
</disk>
|
25
|
+
<% end -%>
|
26
|
+
<% if iso_file -%>
|
27
|
+
<disk type='file' device='cdrom'>
|
28
|
+
<driver name='qemu' type='raw'/>
|
29
|
+
<source file='<%= "#{iso_dir}/#{iso_file}" %>'/>
|
30
|
+
<target dev='hdc' bus='ide'/>
|
31
|
+
<readonly/>
|
32
|
+
<address type='drive' controller='0' bus='1' unit='0'/>
|
33
|
+
</disk>
|
34
|
+
<% end -%>
|
35
|
+
<% nics.each do |nic| -%>
|
36
|
+
<interface type='<%= nic.type %>'>
|
37
|
+
<source <%= nic.type == 'bridge' ? "bridge='#{nic.bridge}'" : "network='#{nic.network}'" %> />
|
38
|
+
<model type='<%= nic.model %>'/>
|
39
|
+
</interface>
|
40
|
+
<% end -%>
|
41
|
+
<serial type='pty'>
|
42
|
+
<target port='0'/>
|
43
|
+
</serial>
|
44
|
+
<console type='pty'>
|
45
|
+
<target port='0'/>
|
46
|
+
</console>
|
47
|
+
<input type='tablet' bus='usb'/>
|
48
|
+
<input type='mouse' bus='ps2'/>
|
49
|
+
<graphics type='<%= display[:type] %>' port='<%= display[:port] %>' autoport='yes' <% if display[:listen] and !(display[:listen].empty?) %> listen='<%= display[:listen] %>'<% end %> <% if display[:password] and !(display[:password].empty?) %>passwd='<%=display[:password] %>'<% end %> />
|
50
|
+
<video>
|
51
|
+
<model type='cirrus' vram='9216' heads='1'/>
|
52
|
+
</video>
|
53
|
+
</devices>
|
54
|
+
</domain>
|
@@ -0,0 +1,26 @@
|
|
1
|
+
<volume>
|
2
|
+
<name><%= name %></name>
|
3
|
+
<allocation unit="<%= split_size_unit(allocation)[1] %>"><%= split_size_unit(allocation)[0] %></allocation>
|
4
|
+
<capacity unit="<%= split_size_unit(capacity)[1] %>"><%= split_size_unit(capacity)[0] %></capacity>
|
5
|
+
<target>
|
6
|
+
<format type="<%= format_type %>"/>
|
7
|
+
<permissions>
|
8
|
+
<owner>0</owner>
|
9
|
+
<group>0</group>
|
10
|
+
<mode>0744</mode>
|
11
|
+
<label>virt_image_t</label>
|
12
|
+
</permissions>
|
13
|
+
</target>
|
14
|
+
<% if backing_volume -%>
|
15
|
+
<backingStore>
|
16
|
+
<path><%= backing_volume.path %></path>
|
17
|
+
<format type="<%= backing_volume.format_type %>"/>
|
18
|
+
<permissions>
|
19
|
+
<owner>0</owner>
|
20
|
+
<group>0</group>
|
21
|
+
<mode>0744</mode>
|
22
|
+
<label>virt_image_t</label>
|
23
|
+
</permissions>
|
24
|
+
</backingStore>
|
25
|
+
<% end -%>
|
26
|
+
</volume>
|