fog-libvirt-csem 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. checksums.yaml +7 -0
  2. data/CONTRIBUTORS.md +24 -0
  3. data/Gemfile +9 -0
  4. data/LICENSE.md +20 -0
  5. data/README.md +83 -0
  6. data/Rakefile +127 -0
  7. data/fog-libvirt-csem.gemspec +49 -0
  8. data/lib/fog/bin/libvirt.rb +58 -0
  9. data/lib/fog/libvirt/compute.rb +140 -0
  10. data/lib/fog/libvirt/models/compute/README.md +92 -0
  11. data/lib/fog/libvirt/models/compute/interface.rb +25 -0
  12. data/lib/fog/libvirt/models/compute/interfaces.rb +20 -0
  13. data/lib/fog/libvirt/models/compute/network.rb +33 -0
  14. data/lib/fog/libvirt/models/compute/networks.rb +20 -0
  15. data/lib/fog/libvirt/models/compute/nic.rb +50 -0
  16. data/lib/fog/libvirt/models/compute/nics.rb +12 -0
  17. data/lib/fog/libvirt/models/compute/node.rb +29 -0
  18. data/lib/fog/libvirt/models/compute/nodes.rb +20 -0
  19. data/lib/fog/libvirt/models/compute/pool.rb +84 -0
  20. data/lib/fog/libvirt/models/compute/pools.rb +20 -0
  21. data/lib/fog/libvirt/models/compute/server.rb +514 -0
  22. data/lib/fog/libvirt/models/compute/servers.rb +21 -0
  23. data/lib/fog/libvirt/models/compute/templates/network.xml.erb +6 -0
  24. data/lib/fog/libvirt/models/compute/templates/pool.xml.erb +6 -0
  25. data/lib/fog/libvirt/models/compute/templates/server.xml.erb +155 -0
  26. data/lib/fog/libvirt/models/compute/templates/volume.xml.erb +30 -0
  27. data/lib/fog/libvirt/models/compute/util/uri.rb +138 -0
  28. data/lib/fog/libvirt/models/compute/util/util.rb +32 -0
  29. data/lib/fog/libvirt/models/compute/volume.rb +129 -0
  30. data/lib/fog/libvirt/models/compute/volumes.rb +20 -0
  31. data/lib/fog/libvirt/requests/compute/clone_volume.rb +18 -0
  32. data/lib/fog/libvirt/requests/compute/create_domain.rb +17 -0
  33. data/lib/fog/libvirt/requests/compute/create_volume.rb +16 -0
  34. data/lib/fog/libvirt/requests/compute/define_domain.rb +17 -0
  35. data/lib/fog/libvirt/requests/compute/define_pool.rb +16 -0
  36. data/lib/fog/libvirt/requests/compute/destroy_interface.rb +18 -0
  37. data/lib/fog/libvirt/requests/compute/destroy_network.rb +17 -0
  38. data/lib/fog/libvirt/requests/compute/dhcp_leases.rb +37 -0
  39. data/lib/fog/libvirt/requests/compute/get_node_info.rb +37 -0
  40. data/lib/fog/libvirt/requests/compute/libversion.rb +18 -0
  41. data/lib/fog/libvirt/requests/compute/list_domains.rb +128 -0
  42. data/lib/fog/libvirt/requests/compute/list_interfaces.rb +57 -0
  43. data/lib/fog/libvirt/requests/compute/list_networks.rb +63 -0
  44. data/lib/fog/libvirt/requests/compute/list_pool_volumes.rb +19 -0
  45. data/lib/fog/libvirt/requests/compute/list_pools.rb +71 -0
  46. data/lib/fog/libvirt/requests/compute/list_volumes.rb +106 -0
  47. data/lib/fog/libvirt/requests/compute/mock_files/domain.xml +40 -0
  48. data/lib/fog/libvirt/requests/compute/pool_action.rb +19 -0
  49. data/lib/fog/libvirt/requests/compute/update_autostart.rb +18 -0
  50. data/lib/fog/libvirt/requests/compute/update_display.rb +36 -0
  51. data/lib/fog/libvirt/requests/compute/upload_volume.rb +31 -0
  52. data/lib/fog/libvirt/requests/compute/vm_action.rb +19 -0
  53. data/lib/fog/libvirt/requests/compute/volume_action.rb +18 -0
  54. data/lib/fog/libvirt/version.rb +5 -0
  55. data/lib/fog/libvirt.rb +16 -0
  56. data/minitests/server/server_test.rb +64 -0
  57. data/minitests/server/user_data_iso_test.rb +77 -0
  58. data/minitests/test_helper.rb +18 -0
  59. data/tests/helper.rb +17 -0
  60. data/tests/helpers/formats_helper.rb +100 -0
  61. data/tests/helpers/formats_helper_tests.rb +107 -0
  62. data/tests/helpers/mock_helper.rb +14 -0
  63. data/tests/helpers/succeeds_helper.rb +9 -0
  64. data/tests/libvirt/compute_tests.rb +19 -0
  65. data/tests/libvirt/models/compute/interface_tests.rb +27 -0
  66. data/tests/libvirt/models/compute/interfaces_tests.rb +14 -0
  67. data/tests/libvirt/models/compute/network_tests.rb +31 -0
  68. data/tests/libvirt/models/compute/networks_tests.rb +13 -0
  69. data/tests/libvirt/models/compute/nic_tests.rb +31 -0
  70. data/tests/libvirt/models/compute/nics_tests.rb +10 -0
  71. data/tests/libvirt/models/compute/pool_tests.rb +27 -0
  72. data/tests/libvirt/models/compute/pools_tests.rb +13 -0
  73. data/tests/libvirt/models/compute/server_tests.rb +63 -0
  74. data/tests/libvirt/models/compute/servers_tests.rb +14 -0
  75. data/tests/libvirt/models/compute/volume_tests.rb +38 -0
  76. data/tests/libvirt/models/compute/volumes_tests.rb +15 -0
  77. data/tests/libvirt/requests/compute/create_domain_tests.rb +21 -0
  78. data/tests/libvirt/requests/compute/define_domain_tests.rb +11 -0
  79. data/tests/libvirt/requests/compute/dhcp_leases_tests.rb +15 -0
  80. data/tests/libvirt/requests/compute/update_autostart_tests.rb +12 -0
  81. data/tests/libvirt/requests/compute/update_display.rb +13 -0
  82. metadata +335 -0
@@ -0,0 +1,514 @@
1
+ require 'fog/compute/models/server'
2
+ require 'fog/libvirt/models/compute/util/util'
3
+ require 'fileutils'
4
+
5
+ module Fog
6
+ module Libvirt
7
+ class Compute
8
+ class Server < Fog::Compute::Server
9
+ include Fog::Libvirt::Util
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
+ attribute :cpu
31
+ attribute :hugepages
32
+ attribute :guest_agent
33
+ attribute :virtio_rng
34
+
35
+ attribute :state
36
+
37
+ # The following attributes are only needed when creating a new vm
38
+ #TODO: Add depreciation warning
39
+ attr_accessor :iso_dir, :iso_file
40
+ attr_accessor :network_interface_type ,:network_nat_network, :network_bridge_name
41
+ attr_accessor :volume_format_type, :volume_allocation,:volume_capacity, :volume_name, :volume_pool_name, :volume_template_name, :volume_path
42
+ attr_accessor :password
43
+ attr_accessor :user_data
44
+
45
+ # Can be created by passing in :xml => "<xml to create domain/server>"
46
+ # or by providing :template_options => {
47
+ # :name => "", :cpus => 1, :memory_size => 256 , :volume_template
48
+ # }
49
+
50
+ def initialize(attributes={} )
51
+ @xml = attributes.delete(:xml)
52
+ verify_boot_order(attributes[:boot_order])
53
+ super defaults.merge(attributes)
54
+ initialize_nics
55
+ initialize_volumes
56
+ @user_data = attributes.delete(:user_data)
57
+ end
58
+
59
+ def new?
60
+ uuid.nil?
61
+ end
62
+
63
+ def save
64
+ raise Fog::Errors::Error.new('Saving an existing server may create a duplicate') unless new?
65
+ create_or_clone_volume unless xml or @volumes
66
+ create_user_data_iso if user_data
67
+ @xml ||= to_xml
68
+ self.id = (persistent ? service.define_domain(xml) : service.create_domain(xml)).uuid
69
+ reload
70
+ rescue => e
71
+ raise Fog::Errors::Error.new("Error saving the server: #{e}")
72
+ end
73
+
74
+ def start
75
+ return true if active?
76
+ action_status = service.vm_action(uuid, :create)
77
+ reload
78
+ action_status
79
+ end
80
+
81
+ def update_autostart(value)
82
+ service.update_autostart(uuid, value)
83
+ end
84
+
85
+ def mac
86
+ nics.first.mac if nics && nics.first
87
+ end
88
+
89
+ def disk_path
90
+ volumes.first.path if volumes and volumes.first
91
+ end
92
+
93
+ def destroy(options={ :destroy_volumes => false})
94
+ poweroff unless stopped?
95
+ service.vm_action(uuid, :undefine, 4) # Remove NVRAM if exists
96
+ volumes.each { |vol| vol.destroy } if options[:destroy_volumes]
97
+ true
98
+ end
99
+
100
+ def reboot
101
+ action_status = service.vm_action(uuid, :reboot)
102
+ reload
103
+ action_status
104
+ end
105
+
106
+ def poweroff
107
+ action_status = service.vm_action(uuid, :destroy)
108
+ reload
109
+ action_status
110
+ end
111
+
112
+ def shutdown
113
+ action_status = service.vm_action(uuid, :shutdown)
114
+ reload
115
+ action_status
116
+ end
117
+
118
+ def resume
119
+ action_status = service.vm_action(uuid, :resume)
120
+ reload
121
+ action_status
122
+ end
123
+
124
+ def suspend
125
+ action_status = service.vm_action(uuid, :suspend)
126
+ reload
127
+ action_status
128
+ end
129
+
130
+ def stopped?
131
+ state == "shutoff"
132
+ end
133
+
134
+ def ready?
135
+ state == "running"
136
+ end
137
+
138
+ #alias methods
139
+ alias_method :halt, :poweroff
140
+ alias_method :stop, :shutdown
141
+ alias_method :active?, :active
142
+ alias_method :autostart?, :autostart
143
+
144
+ def volumes
145
+ # lazy loading of volumes
146
+ @volumes ||= (@volumes_path || []).map{|path| service.volumes.all(:path => path).first }
147
+ end
148
+
149
+ def private_ip_address
150
+ ip_address(:private)
151
+ end
152
+
153
+ def public_ip_address
154
+ ip_address(:public)
155
+ end
156
+
157
+ def ssh(commands)
158
+ requires :ssh_ip_address, :username
159
+
160
+ ssh_options={}
161
+ ssh_options[:password] = password unless password.nil?
162
+ ssh_options[:proxy]= ssh_proxy unless ssh_proxy.nil?
163
+
164
+ super(commands, ssh_options)
165
+ end
166
+
167
+ def ssh_proxy
168
+ begin
169
+ require 'net/ssh/proxy/command'
170
+ rescue LoadError
171
+ Fog::Logger.warning("'net/ssh' missing, please install and try again.")
172
+ exit(1)
173
+ end
174
+ # if this is a direct connection, we don't need a proxy to be set.
175
+ return nil unless connection.uri.ssh_enabled?
176
+ user_string= service.uri.user ? "-l #{service.uri.user}" : ""
177
+ Net::SSH::Proxy::Command.new("ssh #{user_string} #{service.uri.host} nc %h %p")
178
+ end
179
+
180
+ # Transfers a file
181
+ def scp(local_path, remote_path, upload_options = {})
182
+ requires :ssh_ip_address, :username
183
+
184
+ scp_options = {}
185
+ scp_options[:password] = password unless self.password.nil?
186
+ scp_options[:key_data] = [private_key] if self.private_key
187
+ scp_options[:proxy]= ssh_proxy unless self.ssh_proxy.nil?
188
+
189
+ Fog::SCP.new(ssh_ip_address, username, scp_options).upload(local_path, remote_path, upload_options)
190
+ end
191
+
192
+ # Sets up a new key
193
+ def setup(credentials = {})
194
+ requires :public_key, :ssh_ip_address, :username
195
+
196
+ credentials[:proxy]= ssh_proxy unless ssh_proxy.nil?
197
+ credentials[:password] = password unless self.password.nil?
198
+ credentials[:key_data] = [private_key] if self.private_key
199
+
200
+ commands = [
201
+ %{mkdir .ssh},
202
+ # %{passwd -l #{username}}, #Not sure if we need this here
203
+ # %{echo "#{Fog::JSON.encode(attributes)}" >> ~/attributes.json}
204
+ ]
205
+ if public_key
206
+ commands << %{echo "#{public_key}" >> ~/.ssh/authorized_keys}
207
+ end
208
+
209
+ # wait for domain to be ready
210
+ Timeout::timeout(360) do
211
+ begin
212
+ Timeout::timeout(8) do
213
+ Fog::SSH.new(ssh_ip_address, username, credentials.merge(:timeout => 4)).run('pwd')
214
+ end
215
+ rescue Errno::ECONNREFUSED
216
+ sleep(2)
217
+ retry
218
+ rescue Net::SSH::AuthenticationFailed, Timeout::Error
219
+ retry
220
+ end
221
+ end
222
+ Fog::SSH.new(ssh_ip_address, username, credentials).run(commands)
223
+ end
224
+
225
+ def update_display attrs = {}
226
+ service.update_display attrs.merge(:uuid => uuid)
227
+ reload
228
+ end
229
+
230
+ # can't use deprecate method, as the value is part of the display hash
231
+ def vnc_port
232
+ Fog::Logger.deprecation("#{self.class} => #vnc_port is deprecated, use #display[:port] instead [light_black](#{caller.first})[/]")
233
+ display[:port]
234
+ end
235
+
236
+ def generate_config_iso(user_data, &blk)
237
+ Dir.mktmpdir('config') do |wd|
238
+ generate_config_iso_in_dir(wd, user_data, &blk)
239
+ end
240
+ end
241
+
242
+ def generate_config_iso_in_dir(dir_path, user_data, &blk)
243
+ FileUtils.touch(File.join(dir_path, "meta-data"))
244
+ File.open(File.join(dir_path, 'user-data'), 'w') { |f| f.write user_data }
245
+
246
+ isofile = Tempfile.new(['init', '.iso']).path
247
+ unless system("genisoimage -output #{isofile} -volid cidata -joliet -rock #{File.join(dir_path, 'user-data')} #{File.join(dir_path, 'meta-data')}")
248
+ raise Fog::Errors::Error.new("Couldn't generate cloud-init iso disk with genisoimage.")
249
+ end
250
+ blk.call(isofile)
251
+ end
252
+
253
+ def create_user_data_iso
254
+ generate_config_iso(user_data) do |iso|
255
+ vol = service.volumes.create(:name => cloud_init_volume_name, :capacity => "#{File.size(iso)}b", :allocation => "0G")
256
+ vol.upload_image(iso)
257
+ @iso_file = cloud_init_volume_name
258
+ @iso_dir = File.dirname(vol.path) if vol.path
259
+ end
260
+ end
261
+
262
+ def cloud_init_volume_name
263
+ "#{name}-cloud-init.iso"
264
+ end
265
+
266
+ private
267
+ attr_accessor :volumes_path
268
+
269
+ # This tests the library version before redefining the address
270
+ # method for this instance to use a method compatible with
271
+ # earlier libvirt libraries, or uses the dhcp method from more
272
+ # recent releases.
273
+ def addresses(service_arg=service, options={})
274
+ addresses_method = self.method(:addresses_dhcp)
275
+ # check if ruby-libvirt was compiled against a new enough version
276
+ # that can use dhcp_leases, as otherwise it will not provide the
277
+ # method dhcp_leases on any of the network objects.
278
+ has_dhcp_leases = true
279
+ begin
280
+ service.networks.first.dhcp_leases(self.mac)
281
+ rescue NoMethodError
282
+ has_dhcp_leases = false
283
+ rescue
284
+ # assume some other odd exception.
285
+ end
286
+
287
+ # if ruby-libvirt not compiled with support, or remote library is
288
+ # too old (must be newer than 1.2.8), then use old fallback
289
+ if not has_dhcp_leases or service.libversion() < 1002008
290
+ addresses_method = self.method(:addresses_ip_command)
291
+ end
292
+
293
+ # replace current definition for this instance with correct one for
294
+ # detected libvirt to perform check once for connection
295
+ (class << self; self; end).class_eval do
296
+ define_method(:addresses, addresses_method)
297
+ end
298
+ addresses(service_arg, options)
299
+ end
300
+
301
+ def ssh_ip_command(ip_command, uri)
302
+ # Retrieve the parts we need from the service to setup our ssh options
303
+ user=uri.user #could be nil
304
+ host=uri.host
305
+ keyfile=uri.keyfile
306
+ port=uri.port
307
+
308
+ # Setup the options
309
+ ssh_options={}
310
+ ssh_options[:keys]=[ keyfile ] unless keyfile.nil?
311
+ ssh_options[:port]=port unless keyfile.nil?
312
+ ssh_options[:paranoid]=true if uri.no_verify?
313
+
314
+ begin
315
+ result=Fog::SSH.new(host, user, ssh_options).run(ip_command)
316
+ rescue Errno::ECONNREFUSED
317
+ raise Fog::Errors::Error.new("Connection was refused to host #{host} to retrieve the ip_address for #{mac}")
318
+ rescue Net::SSH::AuthenticationFailed
319
+ raise Fog::Errors::Error.new("Error authenticating over ssh to host #{host} and user #{user}")
320
+ end
321
+
322
+ # Check for a clean exit code
323
+ if result.first.status == 0
324
+ return result.first.stdout.strip
325
+ else
326
+ # We got a failure executing the command
327
+ raise Fog::Errors::Error.new("The command #{ip_command} failed to execute with a clean exit code")
328
+ end
329
+ end
330
+
331
+ def local_ip_command(ip_command)
332
+ # Execute the ip_command locally
333
+ # Initialize empty ip_address string
334
+ ip_address=""
335
+
336
+ IO.popen("#{ip_command}") do |p|
337
+ p.each_line do |l|
338
+ ip_address+=l
339
+ end
340
+ status=Process.waitpid2(p.pid)[1].exitstatus
341
+ if status!=0
342
+ raise Fog::Errors::Error.new("The command #{ip_command} failed to execute with a clean exit code")
343
+ end
344
+ end
345
+
346
+ #Strip any new lines from the string
347
+ ip_address.chomp
348
+ end
349
+
350
+ # Locale-friendly removal of non-alpha nums
351
+ DOMAIN_CLEANUP_REGEXP = Regexp.compile('[\W_-]')
352
+
353
+ # This retrieves the ip address of the mac address using ip_command
354
+ # It returns an array of public and private ip addresses
355
+ # Currently only one ip address is returned, but in the future this could be multiple
356
+ # if the server has multiple network interface
357
+ def addresses_ip_command(service_arg=service, options={})
358
+ mac=self.mac
359
+
360
+ # Aug 24 17:34:41 juno arpwatch: new station 10.247.4.137 52:54:00:88:5a:0a eth0.4
361
+ # 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
362
+ # Check if another ip_command string was provided
363
+ 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
364
+ ip_command_local=options[:ip_command].nil? ? ip_command_global : options[:ip_command]
365
+
366
+ ip_command="mac=#{mac}; server_name=#{name.gsub(DOMAIN_CLEANUP_REGEXP, '_')}; "+ip_command_local
367
+
368
+ ip_address=nil
369
+
370
+ if service_arg.uri.ssh_enabled?
371
+ ip_address=ssh_ip_command(ip_command, service_arg.uri)
372
+ else
373
+ # It's not ssh enabled, so we assume it is
374
+ if service_arg.uri.transport=="tls"
375
+ raise Fog::Errors::Error.new("TlS remote transport is not currently supported, only ssh")
376
+ end
377
+ ip_address=local_ip_command(ip_command)
378
+ end
379
+
380
+ # The Ip-address command has been run either local or remote now
381
+
382
+ if ip_address==""
383
+ #The grep didn't find an ip address result"
384
+ ip_address=nil
385
+ else
386
+ # To be sure that the command didn't return another random string
387
+ # We check if the result is an actual ip-address
388
+ # otherwise we return nil
389
+ unless ip_address=~/^(\d{1,3}\.){3}\d{1,3}$/
390
+ raise Fog::Errors::Error.new(
391
+ "The result of #{ip_command} does not have valid ip-address format\n"+
392
+ "Result was: #{ip_address}\n"
393
+ )
394
+ end
395
+ end
396
+
397
+ return { :public => [ip_address], :private => [ip_address]}
398
+ end
399
+
400
+ # This retrieves the ip address of the mac address using dhcp_leases
401
+ # It returns an array of public and private ip addresses
402
+ # Currently only one ip address is returned, but in the future this could be multiple
403
+ # if the server has multiple network interface
404
+ def addresses_dhcp(service_arg=service, options={})
405
+ mac=self.mac
406
+
407
+ ip_address = nil
408
+ nic = self.nics.find {|nic| nic.mac==mac}
409
+ if !nic.nil?
410
+ service.networks.all.each do |net|
411
+ if net.name == nic.network
412
+ leases = net.dhcp_leases(mac, 0)
413
+ # Assume the lease expiring last is the current IP address
414
+ ip_address = leases.sort_by { |lse| lse["expirytime"] }.last["ipaddr"] if !leases.empty?
415
+ break
416
+ end
417
+ end
418
+ end
419
+
420
+ return { :public => [ip_address], :private => [ip_address] }
421
+ end
422
+
423
+ def ip_address(key)
424
+ addresses[key].nil? ? nil : addresses[key].first
425
+ end
426
+
427
+ def initialize_nics
428
+ if nics
429
+ nics.map! { |nic| nic.is_a?(Hash) ? service.nics.new(nic) : nic }
430
+ else
431
+ self.nics = [service.nics.new({:type => network_interface_type, :bridge => network_bridge_name, :network => network_nat_network})]
432
+ end
433
+ end
434
+
435
+ def initialize_volumes
436
+ if attributes[:volumes] && !attributes[:volumes].empty?
437
+ @volumes = attributes[:volumes].map { |vol| vol.is_a?(Hash) ? service.volumes.new(vol) : vol }
438
+ end
439
+ end
440
+
441
+ def create_or_clone_volume
442
+ options = {:name => volume_name || default_volume_name}
443
+ # Check if a disk template was specified
444
+ if volume_template_name
445
+ template_volume = service.volumes.all(:name => volume_template_name).first
446
+ raise Fog::Errors::Error.new("Template #{volume_template_name} not found") unless template_volume
447
+ begin
448
+ volume = template_volume.clone("#{options[:name]}")
449
+ rescue => e
450
+ raise Fog::Errors::Error.new("Error creating the volume : #{e}")
451
+ end
452
+ else
453
+ # If no template volume was given, let's create our own volume
454
+ options[:pool_name] = volume_pool_name if volume_pool_name
455
+ options[:format_type] = volume_format_type if volume_format_type
456
+ options[:capacity] = volume_capacity if volume_capacity
457
+ options[:allocation] = volume_allocation if volume_allocation
458
+
459
+ begin
460
+ volume = service.volumes.create(options)
461
+ rescue => e
462
+ raise Fog::Errors::Error.new("Error creating the volume : #{e}")
463
+ end
464
+ end
465
+ @volumes.nil? ? @volumes = [volume] : @volumes << volume
466
+ end
467
+
468
+ def default_iso_dir
469
+ "/var/lib/libvirt/images"
470
+ end
471
+
472
+ def default_volume_name
473
+ "#{name}.#{volume_format_type || 'img'}"
474
+ end
475
+
476
+ def defaults
477
+ {
478
+ :persistent => true,
479
+ :cpus => 1,
480
+ :memory_size => 256 *1024,
481
+ :name => randomized_name,
482
+ :os_type => "hvm",
483
+ :arch => "x86_64",
484
+ :domain_type => "kvm",
485
+ :autostart => false,
486
+ :iso_dir => default_iso_dir,
487
+ :network_interface_type => "network",
488
+ :network_nat_network => "default",
489
+ :network_bridge_name => "br0",
490
+ :boot_order => %w[hd cdrom network],
491
+ :display => default_display,
492
+ :cpu => {},
493
+ :hugepages => false,
494
+ :guest_agent => true,
495
+ :virtio_rng => {},
496
+ }
497
+ end
498
+
499
+ def verify_boot_order order = []
500
+ valid_boot_media = %w[cdrom fd hd network]
501
+ if order
502
+ order.each do |b|
503
+ raise "invalid boot order, possible values are any combination of: #{valid_boot_media.join(', ')}" unless valid_boot_media.include?(b)
504
+ end
505
+ end
506
+ end
507
+
508
+ def default_display
509
+ {:port => '-1', :listen => '127.0.0.1', :type => 'vnc', :password => '' }
510
+ end
511
+ end
512
+ end
513
+ end
514
+ end
@@ -0,0 +1,21 @@
1
+ require 'fog/core/collection'
2
+ require 'fog/libvirt/models/compute/server'
3
+
4
+ module Fog
5
+ module Libvirt
6
+ class Compute
7
+ class Servers < Fog::Collection
8
+ model Fog::Libvirt::Compute::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,6 @@
1
+ <network>
2
+ <name><%= name %></name>
3
+ <forward mode='<%= network_mode %>'/>
4
+ <bridge name='<%= bridge_name %>' stp='on' delay='0' />
5
+ </ip>
6
+ </network>
@@ -0,0 +1,6 @@
1
+ <pool type="dir">
2
+ <name><%= name %></name>
3
+ <target>
4
+ <path><%= path %></path>
5
+ </target>
6
+ </pool>