fog-vsphere 1.3.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0274b352d3f0ba9537632985666d0b9ab20b7377
4
- data.tar.gz: 04fe32fe536cebb26e20aa1259aff7fbd27f11fe
3
+ metadata.gz: d70aa872274ad6369ff9abccb2f116eda6a5e9f9
4
+ data.tar.gz: 4946c00124f4948ed32a177054f34a8c19427e16
5
5
  SHA512:
6
- metadata.gz: a41b6cb9084bfe613cb9ac940e1dca77b8d508c29a6c4561c5d8921aac88480bd0f218360f359bca7f817a69109fdf8175857aa9759c39b4a07df81fc9b66168
7
- data.tar.gz: c74aab1fa50371cb87bb0ddcf3feed952bdf9400a54759b3e68457648d9e72fc74f26aefe9813c25bfafa3af5dd66e8e473d4f89f08ff3f05d44af27b6792035
6
+ metadata.gz: 6b7e631c01fa5d2e1a412ff1a9106d37239644f6ce5dcb42ef0b603ce338af6ce373bd0458a277b32211c1c5f7cb9b1a919a6dd999dea3fecd4534a7991ed2f4
7
+ data.tar.gz: d877b5c7c0fbedbd284e7bd782302989162ce0d9e57daed93e4c63ea136b91b54a743b2d65c7b680717971965b89dca8834439185bca10b6a5509aa2c5c48166
@@ -1,3 +1,7 @@
1
+ ## v1.4.0
2
+
3
+ * Add ability for VMs to have multiple SCSI controllers
4
+
1
5
  ## v1.3.0
2
6
 
3
7
  * Add the add_vm_controller method
@@ -100,6 +100,7 @@ module Fog
100
100
  request :list_vm_customvalues
101
101
  request :list_customfields
102
102
  request :get_vm_first_scsi_controller
103
+ request :list_vm_scsi_controllers
103
104
  request :set_vm_customvalue
104
105
  request :vm_take_snapshot
105
106
  request :list_vm_snapshots
@@ -6,6 +6,7 @@ module Fog
6
6
  class Server < Fog::Compute::Server
7
7
  extend Fog::Deprecation
8
8
  deprecate(:ipaddress, :public_ip_address)
9
+ deprecate(:scsi_controller, :scsi_controllers)
9
10
 
10
11
  # This will be the instance uuid which is globally unique across
11
12
  # a vSphere deployment.
@@ -45,7 +46,7 @@ module Fog
45
46
  attribute :instance_uuid # move this --> id
46
47
  attribute :guest_id
47
48
  attribute :hardware_version
48
- attribute :scsi_controller # this is the first scsi controller. Right now no more of them can be used.
49
+ attribute :scsi_controllers, :type => :array
49
50
  attribute :cpuHotAddEnabled
50
51
  attribute :memoryHotAddEnabled
51
52
  attribute :firmware
@@ -57,7 +58,7 @@ module Fog
57
58
  initialize_interfaces
58
59
  initialize_volumes
59
60
  initialize_customvalues
60
- initialize_scsi_controller
61
+ initialize_scsi_controllers
61
62
  end
62
63
 
63
64
  # Lazy Loaded Attributes
@@ -255,8 +256,12 @@ module Fog
255
256
  attributes[:customvalues] ||= id.nil? ? [] : service.customvalues( :vm => self )
256
257
  end
257
258
 
259
+ def scsi_controllers
260
+ self.attributes[:scsi_controllers] ||= service.list_vm_scsi_controllers(id)
261
+ end
262
+
258
263
  def scsi_controller
259
- self.attributes[:scsi_controller] ||= service.get_vm_first_scsi_controller(id)
264
+ scsi_controllers.first
260
265
  end
261
266
 
262
267
  def folder
@@ -313,7 +318,7 @@ module Fog
313
318
 
314
319
  def initialize_volumes
315
320
  if attributes[:volumes] and attributes[:volumes].is_a?(Array)
316
- self.attributes[:volumes].map! { |vol| vol.is_a?(Hash) ? service.volumes.new(vol) : vol }
321
+ self.attributes[:volumes].map! { |vol| vol.is_a?(Hash) ? service.volumes.new({:server => self}.merge(vol)) : vol }
317
322
  end
318
323
  end
319
324
 
@@ -323,9 +328,20 @@ module Fog
323
328
  end
324
329
  end
325
330
 
326
- def initialize_scsi_controller
327
- if attributes[:scsi_controller] and attributes[:scsi_controller].is_a?(Hash)
328
- Fog::Compute::Vsphere::SCSIController.new(self.attributes[:scsi_controller])
331
+ def initialize_scsi_controllers
332
+ if attributes[:scsi_controllers] && attributes[:scsi_controllers].is_a?(Array)
333
+ self.attributes[:scsi_controllers].map! do |controller|
334
+ controller.is_a?(Hash) ? Fog::Compute::Vsphere::SCSIController.new(controller) : controller
335
+ end
336
+ elsif attributes[:scsi_controller] && attributes[:scsi_controller].is_a?(Hash)
337
+ self.attributes[:scsi_controllers] = [
338
+ Fog::Compute::Vsphere::SCSIController.new(self.attributes[:scsi_controller])
339
+ ]
340
+ elsif attributes[:volumes] && attributes[:volumes].is_a?(Array) && !attributes[:volumes].empty?
341
+ # Create a default scsi controller if there are any disks but no controller defined
342
+ self.attributes[:scsi_controllers] = [
343
+ Fog::Compute::Vsphere::SCSIController.new
344
+ ]
329
345
  end
330
346
  end
331
347
  end
@@ -5,6 +5,7 @@ module Fog
5
5
  DISK_SIZE_TO_GB = 1048576
6
6
  identity :id
7
7
 
8
+ has_one :server, Server
8
9
  attribute :datastore
9
10
  attribute :storage_pod
10
11
  attribute :mode
@@ -16,12 +17,9 @@ module Fog
16
17
  attribute :size_gb
17
18
  attribute :key
18
19
  attribute :unit_number
19
- attribute :server_id
20
-
21
- def initialize(attributes={} )
22
- # Assign server first to prevent race condition with persisted?
23
- self.server_id = attributes.delete(:server_id)
20
+ attribute :controller_key, :type => :integer, :default => 1000
24
21
 
22
+ def initialize(attributes={})
25
23
  super defaults.merge(attributes)
26
24
  end
27
25
 
@@ -48,25 +46,7 @@ module Fog
48
46
  raise Fog::Errors::Error.new('Resaving an existing object may create a duplicate') if persisted?
49
47
  requires :server_id, :size, :datastore
50
48
 
51
- # When adding volumes to vsphere, if our unit_number is 7 or higher, vsphere will increment the unit_number
52
- # This is due to SCSI ID 7 being reserved for the pvscsi controller
53
- # When referring to a volume that already added using a unit_id of 7 or higher, we must refer to the actual SCSI ID
54
- if unit_number.nil?
55
- # Vsphere maps unit_numbers 7 and greater to a higher SCSI ID since the pvscsi driver reserves SCSI ID 7
56
- used_unit_numbers = server.volumes.map { |volume| volume.unit_number < 7 ? volume.unit_number : volume.unit_number - 1 }
57
- max_unit_number = used_unit_numbers.max
58
-
59
- if max_unit_number > server.volumes.size
60
- # If the max ID exceeds the number of volumes, there must be a hole in the range. Find a hole and use it.
61
- self.unit_number = max_unit_number.times.to_a.find { |i| used_unit_numbers.exclude?(i) }
62
- else
63
- self.unit_number = max_unit_number + 1
64
- end
65
- else
66
- if server.volumes.any? { |volume| volume.unit_number == self.unit_number && volume.id != self.id }
67
- raise "A volume already exists with that unit_number, so we can't save the new volume"
68
- end
69
- end
49
+ set_unit_number
70
50
 
71
51
  data = service.add_vm_volume(self)
72
52
 
@@ -80,6 +60,7 @@ module Fog
80
60
 
81
61
  self.id = created.id
82
62
  self.key = created.key
63
+ self.controller_key = created.controllerKey
83
64
  self.filename = created.filename
84
65
 
85
66
  true
@@ -88,9 +69,22 @@ module Fog
88
69
  end
89
70
  end
90
71
 
91
- def server
92
- requires :server_id
93
- service.servers.get(server_id)
72
+ def server_id
73
+ requires :server
74
+ server.id
75
+ end
76
+
77
+ def set_unit_number
78
+ # When adding volumes to vsphere, if our unit_number is 7 or higher, vsphere will increment the unit_number
79
+ # This is due to SCSI ID 7 being reserved for the pvscsi controller
80
+ # When referring to a volume that already added using a unit_id of 7 or higher, we must refer to the actual SCSI ID
81
+ if unit_number.nil?
82
+ self.unit_number = calculate_free_unit_number
83
+ else
84
+ if server.volumes.select { |vol| vol.controller_key == controller_key }.any? { |volume| volume.unit_number == self.unit_number && volume.id != self.id }
85
+ raise "A volume already exists with that unit_number, so we can't save the new volume"
86
+ end
87
+ end
94
88
  end
95
89
 
96
90
  private
@@ -102,6 +96,17 @@ module Fog
102
96
  :mode => "persistent"
103
97
  }
104
98
  end
99
+
100
+ def calculate_free_unit_number
101
+ requires :controller_key
102
+
103
+ # Vsphere maps unit_numbers 7 and greater to a higher SCSI ID since the pvscsi driver reserves SCSI ID 7
104
+ used_unit_numbers = server.volumes
105
+ .select { |vol| vol.unit_number && vol.controller_key == controller_key }.map(&:unit_number) + [7]
106
+ free_unit_numbers = (0..15).to_a - used_unit_numbers
107
+
108
+ free_unit_numbers.first
109
+ end
105
110
  end
106
111
  end
107
112
  end
@@ -20,7 +20,7 @@ module Fog
20
20
  raise 'volumes should have vm or template'
21
21
  end
22
22
 
23
- self.each { |volume| volume.server_id = server.id }
23
+ self.each { |volume| volume.server = server }
24
24
  self
25
25
  end
26
26
 
@@ -20,7 +20,7 @@ module Fog
20
20
  vm_cfg[:cpuHotAddEnabled] = attributes[:cpuHotAddEnabled] if attributes.key?(:cpuHotAddEnabled)
21
21
  vm_cfg[:memoryHotAddEnabled] = attributes[:memoryHotAddEnabled] if attributes.key?(:memoryHotAddEnabled)
22
22
  vm_cfg[:firmware] = attributes[:firmware] if attributes.key?(:firmware)
23
- vm_cfg[:bootOptions] = boot_options(attributes) if attributes.key?(:boot_order) || attributes.key?(:boot_retry)
23
+ vm_cfg[:bootOptions] = boot_options(attributes, vm_cfg) if attributes.key?(:boot_order) || attributes.key?(:boot_retry)
24
24
  resource_pool = if attributes[:resource_pool] && attributes[:resource_pool] != 'Resources'
25
25
  get_raw_resource_pool(attributes[:resource_pool], attributes[:cluster], attributes[:datacenter])
26
26
  else
@@ -97,9 +97,12 @@ module Fog
97
97
  devices << nics.map { |nic| create_interface(nic, nics.index(nic), :add, attributes) }
98
98
  end
99
99
 
100
+ if (scsi_controllers = (attributes[:scsi_controllers] || attributes["scsi_controller"]))
101
+ devices << scsi_controllers.each_with_index.map { |controller, index| create_controller(controller, index) }
102
+ end
103
+
100
104
  if (disks = attributes[:volumes])
101
- devices << create_controller(attributes[:scsi_controller]||attributes["scsi_controller"]||{})
102
- devices << disks.map { |disk| create_disk(disk, disks.index(disk), :add, 1000, get_storage_pod(attributes)) }
105
+ devices << disks.map { |disk| create_disk(disk, :add, get_storage_pod(attributes)) }
103
106
  end
104
107
 
105
108
  if (cdroms = attributes[:cdroms])
@@ -108,12 +111,12 @@ module Fog
108
111
  devices.flatten
109
112
  end
110
113
 
111
- def boot_options attributes
114
+ def boot_options(attributes, vm_cfg)
112
115
  # NOTE: you must be using vsphere_rev 5.0 or greater to set boot_order
113
116
  # e.g. Fog::Compute.new(provider: "vsphere", vsphere_rev: "5.5", etc)
114
117
  options = {}
115
118
  if @vsphere_rev.to_f >= 5 and attributes[:boot_order]
116
- options[:bootOrder] = boot_order(attributes)
119
+ options[:bootOrder] = boot_order(attributes, vm_cfg)
117
120
  end
118
121
 
119
122
  # Set attributes[:boot_retry] to a delay in miliseconds to enable boot retries
@@ -121,11 +124,11 @@ module Fog
121
124
  options[:bootRetryEnabled] = true
122
125
  options[:bootRetryDelay] = attributes[:boot_retry]
123
126
  end
124
-
127
+
125
128
  options.empty? ? nil : RbVmomi::VIM::VirtualMachineBootOptions.new(options)
126
129
  end
127
130
 
128
- def boot_order attributes
131
+ def boot_order(attributes, vm_cfg)
129
132
  # attributes[:boot_order] may be an array like this ['network', 'disk']
130
133
  # stating, that we want to prefer network boots over disk boots
131
134
  boot_order = []
@@ -142,18 +145,17 @@ module Fog
142
145
  end
143
146
  end
144
147
  when 'disk'
145
- if disks = attributes[:volumes]
146
- disks.each do |disk|
147
- # we allow booting from all harddisks, the first disk has the highest priority
148
- boot_order << RbVmomi::VIM::VirtualMachineBootOptionsBootableDiskDevice.new(
149
- :deviceKey => disk.key || get_disk_device_key(disks.index(disk)),
150
- )
151
- end
148
+ disks = vm_cfg[:deviceChange].map {|dev| dev[:device]}.select { |dev| dev.is_a? RbVmomi::VIM::VirtualDisk }
149
+ disks.each do |disk|
150
+ # we allow booting from all harddisks, the first disk has the highest priority
151
+ boot_order << RbVmomi::VIM::VirtualMachineBootOptionsBootableDiskDevice.new(
152
+ :deviceKey => get_disk_device_key(disk.controllerKey, disk.unitNumber)
153
+ )
152
154
  end
153
155
  when 'cdrom'
154
- boot_order << RbVmomi::VIM::VirtualMachineBootOptionsBootableCdromDevice.new()
156
+ boot_order << RbVmomi::VIM::VirtualMachineBootOptionsBootableCdromDevice.new
155
157
  when 'floppy'
156
- boot_order << RbVmomi::VIM::VirtualMachineBootOptionsBootableFloppyDevice.new()
158
+ boot_order << RbVmomi::VIM::VirtualMachineBootOptionsBootableFloppyDevice.new
157
159
  else
158
160
  raise "failed to create boot device because \"#{boot_device}\" is unknown"
159
161
  end
@@ -161,17 +163,11 @@ module Fog
161
163
  boot_order
162
164
  end
163
165
 
164
- def get_disk_device_key(index)
166
+ def get_disk_device_key(controller_key, unit_number)
167
+ # controller key is based on 1000 + controller bus
165
168
  # disk key is based on 2000 + the SCSI ID + the controller bus * 16
166
- # the scsi host adapter appears as SCSI ID 7, so we have to skip that
167
- # host adapter key is based on 1000 + bus id
168
- # fog assumes that there is only a single scsi controller, see device_change()
169
- if (index > 6) then
170
- _index = index + 1
171
- else
172
- _index = index
173
- end
174
- 2000 + _index
169
+ controller_bus = controller_key - 1000
170
+ 2000 + (controller_bus * 16) + unit_number
175
171
  end
176
172
 
177
173
  def create_nic_backing nic, attributes
@@ -204,9 +200,9 @@ module Fog
204
200
  }
205
201
  end
206
202
 
207
- def create_controller options=nil
208
- options=if options
209
- controller_default_options.merge(Hash[options.map{|k,v| [k.to_sym,v] }])
203
+ def create_controller(controller=nil, index = 0)
204
+ options=if controller
205
+ controller_default_options.merge(controller.attributes)
210
206
  else
211
207
  controller_default_options
212
208
  end
@@ -218,15 +214,15 @@ module Fog
218
214
  {
219
215
  :operation => options[:operation],
220
216
  :device => controller_class.new({
221
- :key => options[:key],
222
- :busNumber => options[:bus_id],
217
+ :key => options[:key] || (1000 + index),
218
+ :busNumber => options[:bus_id] || index,
223
219
  :sharedBus => controller_get_shared_from_options(options),
224
220
  })
225
221
  }
226
222
  end
227
223
 
228
224
  def controller_default_options
229
- {:operation => "add", :type => RbVmomi::VIM.VirtualLsiLogicController.class, :key => 1000, :bus_id => 0, :shared => false }
225
+ {:operation => :add, :type => RbVmomi::VIM.VirtualLsiLogicController.class, :shared => false }
230
226
  end
231
227
 
232
228
  def controller_get_shared_from_options options
@@ -241,30 +237,28 @@ module Fog
241
237
  end
242
238
  end
243
239
 
244
- def create_disk disk, index = 0, operation = :add, controller_key = 1000, storage_pod = nil
245
- if (index > 6) then
246
- _index = index + 1
247
- else
248
- _index = index
249
- end
240
+ def create_disk(disk, operation = :add, storage_pod = nil)
250
241
  # If we deploy the vm on a storage pod, datastore has to be an empty string
251
242
  if storage_pod
252
243
  datastore = ''
253
244
  else
254
245
  datastore = "[#{disk.datastore}]"
255
246
  end
247
+
248
+ disk.set_unit_number
249
+
256
250
  payload = {
257
251
  :operation => operation,
258
252
  :fileOperation => operation == :add ? :create : :destroy,
259
253
  :device => RbVmomi::VIM.VirtualDisk(
260
- :key => disk.key || _index,
254
+ :key => -1,
261
255
  :backing => RbVmomi::VIM.VirtualDiskFlatVer2BackingInfo(
262
256
  :fileName => datastore,
263
257
  :diskMode => disk.mode.to_sym,
264
258
  :thinProvisioned => disk.thin
265
259
  ),
266
- :controllerKey => controller_key,
267
- :unitNumber => _index,
260
+ :controllerKey => disk.controller_key,
261
+ :unitNumber => disk.unit_number,
268
262
  :capacityInKB => disk.size
269
263
  )
270
264
  }
@@ -0,0 +1,24 @@
1
+ module Fog
2
+ module Compute
3
+ class Vsphere
4
+ class Real
5
+ def list_vm_scsi_controllers(vm_id)
6
+ list_vm_scsi_controllers_raw(vm_id).map do |raw_controller|
7
+ Fog::Compute::Vsphere::SCSIController.new(raw_controller)
8
+ end
9
+ end
10
+
11
+ def list_vm_scsi_controllers_raw(vm_id)
12
+ get_vm_ref(vm_id).config.hardware.device.grep(RbVmomi::VIM::VirtualSCSIController).map do |ctrl|
13
+ {
14
+ :type => ctrl.class.to_s,
15
+ :shared_bus => ctrl.sharedBus.to_s,
16
+ :unit_number => ctrl.scsiCtlrUnitNumber,
17
+ :key => ctrl.key,
18
+ }
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -38,7 +38,8 @@ module Fog
38
38
  :size => vol.capacityInKB,
39
39
  :name => vol.deviceInfo.label,
40
40
  :key => vol.key,
41
- :unit_number => vol.unitNumber
41
+ :unit_number => vol.unitNumber,
42
+ :controller_key => vol.controllerKey
42
43
  }
43
44
  end
44
45
  end
@@ -1,5 +1,5 @@
1
1
  module Fog
2
2
  module Vsphere
3
- VERSION = '1.3.0'
3
+ VERSION = '1.4.0'
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fog-vsphere
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - J.R. Garcia
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-10-17 00:00:00.000000000 Z
11
+ date: 2016-10-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fog-core
@@ -228,6 +228,7 @@ files:
228
228
  - lib/fog/vsphere/requests/compute/list_vm_cdroms.rb
229
229
  - lib/fog/vsphere/requests/compute/list_vm_customvalues.rb
230
230
  - lib/fog/vsphere/requests/compute/list_vm_interfaces.rb
231
+ - lib/fog/vsphere/requests/compute/list_vm_scsi_controllers.rb
231
232
  - lib/fog/vsphere/requests/compute/list_vm_snapshots.rb
232
233
  - lib/fog/vsphere/requests/compute/list_vm_volumes.rb
233
234
  - lib/fog/vsphere/requests/compute/modify_vm_cdrom.rb