fog-vsphere 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +0 -4
  3. data/CHANGELOG.md +8 -0
  4. data/CONTRIBUTORS.md +6 -0
  5. data/fog-vsphere.gemspec +1 -1
  6. data/lib/fog/vsphere/compute.rb +47 -3
  7. data/lib/fog/vsphere/models/compute/cdrom.rb +65 -0
  8. data/lib/fog/vsphere/models/compute/cdroms.rb +18 -0
  9. data/lib/fog/vsphere/models/compute/datacenter.rb +4 -0
  10. data/lib/fog/vsphere/models/compute/folder.rb +4 -0
  11. data/lib/fog/vsphere/models/compute/server.rb +8 -0
  12. data/lib/fog/vsphere/models/compute/storage_pod.rb +19 -0
  13. data/lib/fog/vsphere/models/compute/storage_pods.rb +22 -0
  14. data/lib/fog/vsphere/models/compute/volume.rb +1 -0
  15. data/lib/fog/vsphere/requests/compute/create_folder.rb +10 -0
  16. data/lib/fog/vsphere/requests/compute/create_vm.rb +163 -4
  17. data/lib/fog/vsphere/requests/compute/folder_destroy.rb +26 -0
  18. data/lib/fog/vsphere/requests/compute/get_folder.rb +4 -2
  19. data/lib/fog/vsphere/requests/compute/get_storage_pod.rb +31 -0
  20. data/lib/fog/vsphere/requests/compute/list_datacenters.rb +1 -1
  21. data/lib/fog/vsphere/requests/compute/list_datastores.rb +2 -1
  22. data/lib/fog/vsphere/requests/compute/list_networks.rb +2 -1
  23. data/lib/fog/vsphere/requests/compute/list_storage_pods.rb +45 -0
  24. data/lib/fog/vsphere/requests/compute/list_virtual_machines.rb +8 -4
  25. data/lib/fog/vsphere/requests/compute/list_vm_cdroms.rb +30 -0
  26. data/lib/fog/vsphere/requests/compute/list_vm_interfaces.rb +34 -13
  27. data/lib/fog/vsphere/requests/compute/list_vm_snapshots.rb +5 -1
  28. data/lib/fog/vsphere/requests/compute/modify_vm_cdrom.rb +25 -0
  29. data/lib/fog/vsphere/requests/compute/modify_vm_interface.rb +19 -2
  30. data/lib/fog/vsphere/requests/compute/modify_vm_volume.rb +1 -1
  31. data/lib/fog/vsphere/requests/compute/upload_iso.rb +34 -0
  32. data/lib/fog/vsphere/requests/compute/vm_clone.rb +68 -25
  33. data/lib/fog/vsphere/requests/compute/vm_reconfig_cdrom.rb +68 -0
  34. data/lib/fog/vsphere/version.rb +1 -1
  35. data/tests/models/compute/servers_tests.rb +1 -1
  36. data/tests/requests/compute/folder_destroy_tests.rb +21 -0
  37. data/tests/requests/compute/list_storage_pods_test.rb +10 -0
  38. data/tests/requests/compute/list_vm_cdroms_tests.rb +10 -0
  39. data/tests/requests/compute/modify_vm_cdrom_tests.rb +21 -0
  40. data/tests/requests/compute/vm_reconfig_cdrom_tests.rb +15 -0
  41. metadata +28 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7a75eea9b7c7c8861cbdd259740a3be4910ab46d
4
- data.tar.gz: a7cc4a8d5fc471e589fada237661d54064480236
3
+ metadata.gz: 4f0eaac527da91308fec5066b89407f48b10c7ec
4
+ data.tar.gz: 150e3dc5e72cb0c27d617bf65b2d7db259edb609
5
5
  SHA512:
6
- metadata.gz: 75979dcdf4fc9f215bb473b46a83480f73ce6992a1c36b9a9d527f471118b62b5f6844ce10a509007a48d7696636ad5a734a528e66c2c1fed32d1cead471808f
7
- data.tar.gz: 0a22422a0bca780cb478dddef9b47b186848fb3a051a09c972002762cb04c800f22c4847cf7b5e95233ec9483470f32d50317153f962cd5d135c22da00c50109
6
+ metadata.gz: c03d49413d12ba37d6a02365932583cafc87634cafaf55c8bceadc687ef08a9e0f9134b7928eb2aed94099ef01ee395340d5b10f76351e3870c0e7e409baec5a
7
+ data.tar.gz: 2d78b5e76edff6315f2601fc1830ae395c2419b3e159632a3ad0261d2309c7271d3a303c16ad1b5883fa40ef73e43bfa8958ec92c868d1e0c32d3e78e7124da1
data/.travis.yml CHANGED
@@ -6,8 +6,6 @@ matrix:
6
6
  - rvm: jruby-head
7
7
  fast_finish: true
8
8
  include:
9
- - rvm: 1.8.7
10
- gemfile: gemfiles/Gemfile.1.9.2-
11
9
  - rvm: 1.9.3
12
10
  gemfile: gemfiles/Gemfile.1.9.2+
13
11
  - rvm: 2.0.0
@@ -18,8 +16,6 @@ matrix:
18
16
  gemfile: Gemfile
19
17
  - rvm: 2.2.0
20
18
  gemfile: Gemfile
21
- - rvm: jruby-18mode
22
- gemfile: gemfiles/Gemfile.1.9.2-
23
19
  - rvm: jruby-19mode
24
20
  gemfile: gemfiles/Gemfile.1.9.2+
25
21
  - rvm: jruby-head
data/CHANGELOG.md ADDED
@@ -0,0 +1,8 @@
1
+ * Fix update_vm_interface
2
+ * Add add folder.destroy
3
+ * Implement CD-ROM options
4
+ * Implement storage pods
5
+ * Fix nil error when snapshots is called on a VM without snapshots
6
+ * No longer support Ruby 1.8
7
+ * Allow setting of boot order when using api > 5.0
8
+ * Select the most recent API version instead of 4.1
data/CONTRIBUTORS.md CHANGED
@@ -4,6 +4,7 @@
4
4
  * Carlos Sanchez <csanchez@maestrodev.com>
5
5
  * Chris Thompson <chris.thompson@govdelivery.com>
6
6
  * Chris Thompson <teaforthecat@gmail.com>
7
+ * Christopher Oliver <coliver@datapipe.com>
7
8
  * Cyrus Team <cyrusteam@cyruslists.com>
8
9
  * Darren Foo <stonith@users.noreply.github.com>
9
10
  * Dominic Cleal <dcleal@redhat.com>
@@ -14,6 +15,8 @@
14
15
  * Francois Herbert <francois@herbert.org.nz>
15
16
  * Ivan Nečas <inecas@redhat.com>
16
17
  * Ivo Reznicek <ireznice@googlemail.com>
18
+ * J.R. Garcia <jr@garciaole.com>
19
+ * J.R. Garcia <jrg@vmware.com>
17
20
  * James Herdman <james.herdman@me.com>
18
21
  * Jeff McCune <jeff@puppetlabs.com>
19
22
  * Justin Clayton <justin.clayton@gettyimages.com>
@@ -42,11 +45,14 @@
42
45
  * Oscar Elfving <sofam84@gmail.com>
43
46
  * Paul Thornthwaite <paul@brightbox.co.uk>
44
47
  * Paul Thornthwaite <tokengeek@gmail.com>
48
+ * Paulo Henrique Lopes Ribeiro <plribeiro3000@gmail.com>
49
+ * Rich Daley <rdaley@williamhill.co.uk>
45
50
  * Rich Lane <rlane@club.cc.cmu.edu>
46
51
  * Samuel Keeley <samuel@dropbox.com>
47
52
  * Shlomi Zadok <shlomi@ben-hanna.com>
48
53
  * Simon Josi <me@yokto.net>
49
54
  * Tejas Ravindra Mandke <tejas@identified.com>
55
+ * Timo Goebel <timo.goebel@dm.de>
50
56
  * Timur Alperovich <timur@maginatics.com>
51
57
  * Wesley Beary <geemus+github@gmail.com>
52
58
  * Wesley Beary <geemus@gmail.com>
data/fog-vsphere.gemspec CHANGED
@@ -21,7 +21,7 @@ Gem::Specification.new do |spec|
21
21
 
22
22
  spec.required_ruby_version = '>= 1.8.7'
23
23
 
24
- spec.add_runtime_dependency 'fog-core', '~> 1.32'
24
+ spec.add_runtime_dependency 'fog-core'
25
25
  spec.add_runtime_dependency 'rbvmomi', '~> 1.8'
26
26
 
27
27
  spec.add_development_dependency 'bundler', '~> 1.10'
@@ -33,6 +33,8 @@ module Fog
33
33
  collection :networks
34
34
  model :datastore
35
35
  collection :datastores
36
+ model :storage_pod
37
+ collection :storage_pods
36
38
  model :folder
37
39
  collection :folders
38
40
  model :customvalue
@@ -41,6 +43,8 @@ module Fog
41
43
  collection :customfields
42
44
  model :scsicontroller
43
45
  model :process
46
+ model :cdrom
47
+ collection :cdroms
44
48
 
45
49
  request_path 'fog/vsphere/requests/compute'
46
50
  request :current_time
@@ -63,6 +67,8 @@ module Fog
63
67
  request :get_network
64
68
  request :list_datastores
65
69
  request :get_datastore
70
+ request :list_storage_pods
71
+ request :get_storage_pod
66
72
  request :list_compute_resources
67
73
  request :get_compute_resource
68
74
  request :list_templates
@@ -73,11 +79,14 @@ module Fog
73
79
  request :list_vm_interfaces
74
80
  request :modify_vm_interface
75
81
  request :modify_vm_volume
82
+ request :modify_vm_cdrom
76
83
  request :list_vm_volumes
84
+ request :list_vm_cdroms
77
85
  request :get_virtual_machine
78
86
  request :vm_reconfig_hardware
79
87
  request :vm_reconfig_memory
80
88
  request :vm_reconfig_cpus
89
+ request :vm_reconfig_cdrom
81
90
  request :vm_config_vnc
82
91
  request :create_folder
83
92
  request :list_server_types
@@ -93,6 +102,8 @@ module Fog
93
102
  request :list_child_snapshots
94
103
  request :revert_to_snapshot
95
104
  request :list_processes
105
+ request :upload_iso
106
+ request :folder_destroy
96
107
 
97
108
  module Shared
98
109
  attr_reader :vsphere_is_vcenter
@@ -237,6 +248,17 @@ module Fog
237
248
  "status" => "ok",
238
249
  "summary" => "VM Network",
239
250
  }],
251
+ "cdroms" =>
252
+ [{
253
+ "name" => "CD-/DVD-Drive 1",
254
+ "filename" => nil,
255
+ "key" => 3000,
256
+ "controller_key" => 200,
257
+ "unit_number" => 0,
258
+ "start_connected" => false,
259
+ "allow_guest_control" => true,
260
+ "connected" => false,
261
+ }],
240
262
  "hypervisor" => "gunab.puppetlabs.lan",
241
263
  "guest_id" => "rhel6_64Guest",
242
264
  "tools_state" => "toolsOk",
@@ -308,7 +330,7 @@ module Fog
308
330
  "tools_state" => "toolsOk",
309
331
  "name" => "jefftest",
310
332
  "operatingsystem" => "Red Hat Enterprise Linux 6 (64-bit)",
311
- "path" => "/",
333
+ "path" => "/Solutions/wibble",
312
334
  "tools_version" => "guestToolsUnmanaged",
313
335
  "ipaddress" => "192.168.100.187",
314
336
  "uuid" => "42329da7-e8ab-29ec-1892-d6a4a964912a",
@@ -318,8 +340,30 @@ module Fog
318
340
  }
319
341
  },
320
342
  :datacenters => {
321
- "Solutions" => {:name => "Solutions", :status => "grey"}
343
+ "Solutions" => {:name => "Solutions", :status => "grey", :path => ['Solutions']}
344
+ },
345
+ :folders => {
346
+ 'wibble' => {
347
+ 'name' => 'wibble',
348
+ 'datacenter' => 'Solutions',
349
+ 'path' => '/Solutions/wibble',
350
+ 'type' => 'vm'
351
+ },
352
+ 'empty' => {
353
+ 'name' => 'empty',
354
+ 'datacenter' => 'Solutions',
355
+ 'path' => '/Solutions/empty',
356
+ 'type' => 'vm'
357
+ }
322
358
  },
359
+ :storage_pods =>
360
+ [{:id => "group-p123456",
361
+ :name => "Datastore Cluster 1",
362
+ :freespace => "4856891834368",
363
+ :capacity => "7132061630464",
364
+ :datacenter => "Solutions",
365
+ },
366
+ ],
323
367
  :clusters =>
324
368
  [{:id => "1d4d9a3f-e4e8-4c40-b7fc-263850068fa4",
325
369
  :name => "Solutionscluster",
@@ -417,7 +461,7 @@ module Fog
417
461
  # Negotiate the API revision
418
462
  if not revision
419
463
  rev = @connection.serviceContent.about.apiVersion
420
- @connection.rev = [ rev, ENV['FOG_VSPHERE_REV'] || '4.1' ].min
464
+ @connection.rev = [ rev, ENV['FOG_VSPHERE_REV'] || '4.1' ].max
421
465
  end
422
466
 
423
467
  @vsphere_is_vcenter = @connection.serviceContent.about.apiType == "VirtualCenter"
@@ -0,0 +1,65 @@
1
+ module Fog
2
+ module Compute
3
+ class Vsphere
4
+ class Cdrom < Fog::Model
5
+ identity :key
6
+
7
+ attribute :filename
8
+ attribute :name, :default => "CD-/DVD-ROM Drive"
9
+ attribute :controller_key
10
+ attribute :unit_number
11
+ attribute :start_connected
12
+ attribute :allow_guest_control
13
+ attribute :connected
14
+
15
+ has_one_identity :server, :servers, :aliases => :instance_uuid
16
+
17
+ def to_s
18
+ name
19
+ end
20
+
21
+ def destroy
22
+ requires :instance_uuid, :key, :unit_number
23
+
24
+ service.destroy_vm_cdrom(self)
25
+ true
26
+ end
27
+
28
+ def save
29
+ requires :instance_uuid
30
+
31
+ if unit_number.nil?
32
+ used_unit_numbers = server.cdroms.map { |cdrom| cdrom.unit_number }
33
+ max_unit_number = used_unit_numbers.max
34
+
35
+ if max_unit_number > server.cdroms.size
36
+ # If the max ID exceeds the number of cdroms, there must be a hole in the range. Find a hole and use it.
37
+ self.unit_number = max_unit_number.times.to_a.find { |i| used_unit_numbers.exclude?(i) }
38
+ else
39
+ self.unit_number = max_unit_number + 1
40
+ end
41
+ else
42
+ if server.cdroms.any? { |cdrom| cdrom.unit_number == self.unit_number && cdrom.id != self.id }
43
+ raise "A cdrom already exists with that unit_number, so we can't save the new cdrom"
44
+ end
45
+ end
46
+
47
+ data = service.add_vm_cdrom(self)
48
+
49
+ if data['task_state'] == 'success'
50
+ # We have to query vSphere to get the cdrom attributes since the task handle doesn't include that info.
51
+ created = server.cdroms.get(unit_number)
52
+
53
+ self.key = created.key
54
+ self.filename = created.filename
55
+ self.unit_number = created.unit_number
56
+
57
+ true
58
+ else
59
+ false
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,18 @@
1
+ module Fog
2
+ module Compute
3
+ class Vsphere
4
+ class Cdroms < Fog::Collection
5
+ attribute :instance_uuid, :alias => :server_id
6
+ model Fog::Compute::Vsphere::Cdrom
7
+
8
+ def all(filters = {})
9
+ load service.list_vm_cdroms(instance_uuid)
10
+ end
11
+
12
+ def get(unit_number)
13
+ all.find { |cdrom| cdrom.unit_number == unit_number }
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -19,6 +19,10 @@ module Fog
19
19
  service.datastores({ :datacenter => path.join("/") }.merge(filters))
20
20
  end
21
21
 
22
+ def storage_pods filters = { }
23
+ service.storage_pods({ :datacenter => path.join("/") }.merge(filters))
24
+ end
25
+
22
26
  def vm_folders filters = { }
23
27
  service.folders({ :datacenter => path.join("/"), :type => :vm }.merge(filters))
24
28
  end
@@ -18,6 +18,10 @@ module Fog
18
18
  def to_s
19
19
  name
20
20
  end
21
+
22
+ def destroy
23
+ service.folder_destroy(path, datacenter)
24
+ end
21
25
  end
22
26
  end
23
27
  end
@@ -237,6 +237,14 @@ module Fog
237
237
  end
238
238
  end
239
239
 
240
+ def cdroms(opts = {})
241
+ service.cdroms(:instance_uuid => self.id).all(opts)
242
+ end
243
+
244
+ def cdrom(key)
245
+ cdroms.get(key)
246
+ end
247
+
240
248
  def guest_processes(opts = {})
241
249
  fail 'VM tools must be running' unless tools_running?
242
250
  service.list_processes(self.id, opts)
@@ -0,0 +1,19 @@
1
+ module Fog
2
+ module Compute
3
+ class Vsphere
4
+ class StoragePod < Fog::Model
5
+ identity :id
6
+
7
+ attribute :name
8
+ attribute :datacenter
9
+ attribute :type
10
+ attribute :freespace
11
+ attribute :capacity
12
+
13
+ def to_s
14
+ name
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,22 @@
1
+ require 'fog/core/collection'
2
+ require 'fog/vsphere/models/compute/storage_pod'
3
+
4
+ module Fog
5
+ module Compute
6
+ class Vsphere
7
+ class StoragePods < Fog::Collection
8
+ model Fog::Compute::Vsphere::StoragePod
9
+ attribute :datacenter
10
+
11
+ def all(filters = {})
12
+ load service.list_storage_pods(filters.merge(datacenter: datacenter))
13
+ end
14
+
15
+ def get(id)
16
+ requires :datacenter
17
+ new service.get_storage_pod(id, datacenter)
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -6,6 +6,7 @@ module Fog
6
6
  identity :id
7
7
 
8
8
  attribute :datastore
9
+ attribute :storage_pod
9
10
  attribute :mode
10
11
  attribute :size
11
12
  attribute :thin
@@ -17,6 +17,16 @@ module Fog
17
17
  end
18
18
  end
19
19
  end
20
+ class Mock
21
+ def create_folder(datacenter, path, name)
22
+ self.data[:folders][name] = {
23
+ 'name' => name,
24
+ 'datacenter' => datacenter,
25
+ 'path' => "#{path}/#{name}",
26
+ 'type' => 'vm'
27
+ }
28
+ end
29
+ end
20
30
  end
21
31
  end
22
32
  end
@@ -19,13 +19,20 @@ module Fog
19
19
  vm_cfg[:cpuHotAddEnabled] = attributes[:cpuHotAddEnabled] if attributes.key?(:cpuHotAddEnabled)
20
20
  vm_cfg[:memoryHotAddEnabled] = attributes[:memoryHotAddEnabled] if attributes.key?(:memoryHotAddEnabled)
21
21
  vm_cfg[:firmware] = attributes[:firmware] if attributes.key?(:firmware)
22
+ vm_cfg[:bootOptions] = boot_options(attributes) if attributes.key?(:boot_order)
22
23
  resource_pool = if attributes[:resource_pool]
23
24
  get_raw_resource_pool(attributes[:resource_pool], attributes[:cluster], attributes[:datacenter])
24
25
  else
25
26
  get_raw_cluster(attributes[:cluster], attributes[:datacenter]).resourcePool
26
27
  end
27
28
  vmFolder = get_raw_vmfolder(attributes[:path], attributes[:datacenter])
28
- vm = vmFolder.CreateVM_Task(:config => vm_cfg, :pool => resource_pool).wait_for_completion
29
+ # if any volume has a storage_pod set, we deploy the vm on a storage pod instead of the defined datastores
30
+ pod = get_storage_pod(attributes)
31
+ if pod
32
+ vm = create_vm_on_storage_pod(pod, vm_cfg, vmFolder, resource_pool, attributes[:datacenter])
33
+ else
34
+ vm = create_vm_on_datastore(vm_cfg, vmFolder, resource_pool)
35
+ end
29
36
  vm.config.instanceUuid
30
37
  rescue => e
31
38
  raise e, "failed to create vm: #{e}"
@@ -33,9 +40,47 @@ module Fog
33
40
 
34
41
  private
35
42
 
43
+ def create_vm_on_datastore(vm_cfg, vmFolder, resource_pool)
44
+ vm = vmFolder.CreateVM_Task(:config => vm_cfg, :pool => resource_pool).wait_for_completion
45
+ end
46
+
47
+ def create_vm_on_storage_pod(storage_pod, vm_cfg, vmFolder, resource_pool, datacenter)
48
+ pod_spec = RbVmomi::VIM::StorageDrsPodSelectionSpec.new(
49
+ :storagePod => get_raw_storage_pod(storage_pod, datacenter),
50
+ )
51
+ storage_spec = RbVmomi::VIM::StoragePlacementSpec.new(
52
+ :type => 'create',
53
+ :folder => vmFolder,
54
+ :resourcePool => resource_pool,
55
+ :podSelectionSpec => pod_spec,
56
+ :configSpec => vm_cfg,
57
+ )
58
+ srm = @connection.serviceContent.storageResourceManager
59
+ result = srm.RecommendDatastores(:storageSpec => storage_spec)
60
+
61
+ # if result array contains recommendation, we can apply it
62
+ if key = result.recommendations.first.key
63
+ result = srm.ApplyStorageDrsRecommendation_Task(:key => [key]).wait_for_completion
64
+ vm = result.vm
65
+ else
66
+ raise "Could not create vm on storage pod, did not get a storage recommendation"
67
+ end
68
+ vm
69
+ end
70
+
71
+ # check if a storage pool is set on any of the volumes and return the first result found or nil
72
+ # return early if vsphere revision is lower than 5 as this is not supported
73
+ def get_storage_pod attributes
74
+ return unless @vsphere_rev.to_f >= 5
75
+ volume = attributes[:volumes].detect {|volume| !( volume.storage_pod.nil? || volume.storage_pod.empty? ) }
76
+ volume.storage_pod if volume
77
+ end
78
+
36
79
  # this methods defines where the vm config files would be located,
37
80
  # by default we prefer to keep it at the same place the (first) vmdk is located
81
+ # if we deploy the vm on a storage pool, we have to return an empty string
38
82
  def vm_path_name attributes
83
+ return '' if get_storage_pod(attributes)
39
84
  datastore = attributes[:volumes].first.datastore unless attributes[:volumes].empty?
40
85
  datastore ||= 'datastore1'
41
86
  "[#{datastore}]"
@@ -49,11 +94,73 @@ module Fog
49
94
 
50
95
  if (disks = attributes[:volumes])
51
96
  devices << create_controller(attributes[:scsi_controller]||attributes["scsi_controller"]||{})
52
- devices << disks.map { |disk| create_disk(disk, disks.index(disk)) }
97
+ devices << disks.map { |disk| create_disk(disk, disks.index(disk), :add, 1000, get_storage_pod(attributes)) }
98
+ end
99
+
100
+ if (cdroms = attributes[:cdroms])
101
+ devices << cdroms.map { |cdrom| create_cdrom(cdrom, cdroms.index(cdrom)) }
53
102
  end
54
103
  devices.flatten
55
104
  end
56
105
 
106
+ def boot_options attributes
107
+ # NOTE: you must be using vsphere_rev 5.0 or greater to set boot_order
108
+ # e.g. Fog::Compute.new(provider: "vsphere", vsphere_rev: "5.5", etc)
109
+ return unless @vsphere_rev.to_f >= 5
110
+ RbVmomi::VIM::VirtualMachineBootOptions.new(
111
+ :bootOrder => boot_order(attributes)
112
+ )
113
+ end
114
+
115
+ def boot_order attributes
116
+ # attributes[:boot_order] may be an array like this ['network', 'disk']
117
+ # stating, that we want to prefer network boots over disk boots
118
+ boot_order = []
119
+ attributes[:boot_order].each do |boot_device|
120
+ case boot_device
121
+ when 'network'
122
+ if nics = attributes[:interfaces]
123
+ # key is based on 4000 + the interface index
124
+ # we allow booting from all network interfaces, the first interface has the highest priority
125
+ nics.each do |nic|
126
+ boot_order << RbVmomi::VIM::VirtualMachineBootOptionsBootableEthernetDevice.new(
127
+ :deviceKey => 4000 + nics.index(nic),
128
+ )
129
+ end
130
+ end
131
+ when 'disk'
132
+ if disks = attributes[:volumes]
133
+ disks.each do |disk|
134
+ # we allow booting from all harddisks, the first disk has the highest priority
135
+ boot_order << RbVmomi::VIM::VirtualMachineBootOptionsBootableDiskDevice.new(
136
+ :deviceKey => disk.key || get_disk_device_key(disks.index(disk)),
137
+ )
138
+ end
139
+ end
140
+ when 'cdrom'
141
+ boot_order << RbVmomi::VIM::VirtualMachineBootOptionsBootableCdromDevice.new()
142
+ when 'floppy'
143
+ boot_order << RbVmomi::VIM::VirtualMachineBootOptionsBootableFloppyDevice.new()
144
+ else
145
+ raise "failed to create boot device because \"#{boot_device}\" is unknown"
146
+ end
147
+ end
148
+ boot_order
149
+ end
150
+
151
+ def get_disk_device_key(index)
152
+ # disk key is based on 2000 + the SCSI ID + the controller bus * 16
153
+ # the scsi host adapter appears as SCSI ID 7, so we have to skip that
154
+ # host adapter key is based on 1000 + bus id
155
+ # fog assumes that there is only a single scsi controller, see device_change()
156
+ if (index > 6) then
157
+ _index = index + 1
158
+ else
159
+ _index = index
160
+ end
161
+ 2000 + _index
162
+ end
163
+
57
164
  def create_nic_backing nic, attributes
58
165
  raw_network = get_raw_network(nic.network, attributes[:datacenter], if nic.virtualswitch then nic.virtualswitch end)
59
166
 
@@ -121,19 +228,25 @@ module Fog
121
228
  end
122
229
  end
123
230
 
124
- def create_disk disk, index = 0, operation = :add, controller_key = 1000
231
+ def create_disk disk, index = 0, operation = :add, controller_key = 1000, storage_pod = nil
125
232
  if (index > 6) then
126
233
  _index = index + 1
127
234
  else
128
235
  _index = index
129
236
  end
237
+ # If we deploy the vm on a storage pod, datastore has to be an empty string
238
+ if storage_pod
239
+ datastore ''
240
+ else
241
+ datastore = "[#{disk.datastore}]"
242
+ end
130
243
  payload = {
131
244
  :operation => operation,
132
245
  :fileOperation => operation == :add ? :create : :destroy,
133
246
  :device => RbVmomi::VIM.VirtualDisk(
134
247
  :key => disk.key || _index,
135
248
  :backing => RbVmomi::VIM.VirtualDiskFlatVer2BackingInfo(
136
- :fileName => "[#{disk.datastore}]",
249
+ :fileName => datastore,
137
250
  :diskMode => disk.mode.to_sym,
138
251
  :thinProvisioned => disk.thin
139
252
  ),
@@ -150,6 +263,22 @@ module Fog
150
263
  payload
151
264
  end
152
265
 
266
+ def create_cdrom cdrom, index = 0, operation = :add, controller_key = 200
267
+ {
268
+ :operation => operation,
269
+ :device => RbVmomi::VIM.VirtualCdrom(
270
+ :key => cdrom.key || index,
271
+ :backing => RbVmomi::VIM::VirtualCdromRemoteAtapiBackingInfo(deviceName: ''),
272
+ :controllerKey => controller_key,
273
+ connectable: RbVmomi::VIM::VirtualDeviceConnectInfo(
274
+ startConnected: false,
275
+ connected: false,
276
+ allowGuestControl: true,
277
+ ),
278
+ )
279
+ }
280
+ end
281
+
153
282
  def extra_config attributes
154
283
  [
155
284
  {
@@ -162,6 +291,36 @@ module Fog
162
291
 
163
292
  class Mock
164
293
  def create_vm attributes = { }
294
+ id = SecureRandom.uuid
295
+ vm = {
296
+ 'id' => id,
297
+ 'uuid' => id,
298
+ 'instance_uuid' => id,
299
+ 'mo_ref' => "vm-#{rand 99999}",
300
+ 'datacenter' => attributes[:datacenter],
301
+ 'name' => attributes[:name],
302
+ 'interfaces' => attributes[:interfaces].map {{
303
+ 'mac' => 'f2:b5:46:b5:d8:d7'
304
+ }}
305
+ }
306
+ self.data[:servers][id] = vm
307
+ id
308
+ end
309
+
310
+ def create_cdrom cdrom, index = 0, operation = :add, controller_key = 200
311
+ {
312
+ :operation => operation,
313
+ :device => {
314
+ :key => cdrom.key || index,
315
+ :backing => { deviceName: '' },
316
+ :controllerKey => controller_key,
317
+ connectable: {
318
+ startConnected: false,
319
+ connected: false,
320
+ allowGuestControl: true,
321
+ },
322
+ }
323
+ }
165
324
  end
166
325
  end
167
326
  end