fog-vsphere 1.3.0 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
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