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.
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>