kitchen-vcenter 2.4.0 → 2.5.2

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
  SHA256:
3
- metadata.gz: 45583a32d2c2ccf32d21491735bbe862c1cc85990ea89bc773a06086a117fc17
4
- data.tar.gz: 872abb17f6fd2caf8bbe14f05c31fbe9c402bb065a3c6b010bc8136a944dc525
3
+ metadata.gz: 69eea65c20662c0ec15d88d55d4871d57978427d2b1ebb86977236f5e955f407
4
+ data.tar.gz: e07a74cb3f693286e7721bf40346fb4f9cd8b6f2cf720292d5c07ced71982956
5
5
  SHA512:
6
- metadata.gz: d523aa9288f11454ef5bffd91be68132e3ed34028566af46ddbc85daeb707e05245604477234077a836fbce5e108a1f528b89f65d01653ba62e43ddd94b18747
7
- data.tar.gz: c5ee31885c9a12eb0cd9d7e28d2dbb99e0257a897912054ca566aad2cef05f52301ebc65a1e61b588fbbcdf0587982aadfc29e1e72addfa29f2ae9c51a589b8d
6
+ metadata.gz: b576ba091634bb15c78ea248a6aa5bd7c2e69f6c682cf3b03472cf02389d844e9f8c974fe8435f47792f1608db9480f55df5fafe95293e2df98580071187b0d7
7
+ data.tar.gz: 86d97a406cb9e7ec156baa0af3743aea8ade5591efda376ce7dd58044113a9f4ab1fa9ee2645544a4de6362c55938f795aa6627e131e9f5b92677d4536e460c9
@@ -20,5 +20,5 @@
20
20
  # The main kitchen-vcenter module
21
21
  module KitchenVcenter
22
22
  # The version of this version of test-kitchen we assume enterprises want.
23
- VERSION = "2.4.0"
23
+ VERSION = "2.5.2"
24
24
  end
@@ -85,10 +85,6 @@ module Kitchen
85
85
  save_and_validate_parameters
86
86
  connect
87
87
 
88
- # Using the clone class, create a machine for TK
89
- # Find the identifier for the targethost to pass to rbvmomi
90
- config[:targethost] = get_host(config[:targethost])
91
-
92
88
  # Use the root resource pool of a specified cluster, if any
93
89
  if config[:cluster].nil?
94
90
  # Find the first resource pool on any cluster
@@ -110,6 +106,7 @@ module Kitchen
110
106
  end
111
107
 
112
108
  raise format("Pool %s not found on cluster %s", config[:resource_pool], config[:cluster]) if found_pool.nil?
109
+
113
110
  config[:resource_pool] = found_pool
114
111
  end
115
112
  end
@@ -117,6 +114,14 @@ module Kitchen
117
114
  # Check that the datacenter exists
118
115
  datacenter_exists?(config[:datacenter])
119
116
 
117
+ # Get datacenter and cluster information
118
+ datacenter = get_datacenter(config[:datacenter])
119
+ cluster_id = get_cluster_id(config[:cluster])
120
+
121
+ # Using the clone class, create a machine for TK
122
+ # Find the identifier for the targethost to pass to rbvmomi
123
+ config[:targethost] = get_host(config[:targethost], datacenter, cluster_id)
124
+
120
125
  # Check if network exists, if to be changed
121
126
  network_exists?(config[:network_name]) unless config[:network_name].nil?
122
127
 
@@ -193,6 +198,7 @@ module Kitchen
193
198
  # Error out on undefined tags
194
199
  invalid = config[:tags] - valid_tags.keys
195
200
  raise format("Specified tag(s) %s not valid", invalid.join(",")) unless invalid.empty?
201
+
196
202
  tag_service = VSphereAutomation::CIS::TaggingTagAssociationApi.new(api_client)
197
203
  tag_ids = config[:tags].map { |name| valid_tags[name] }
198
204
 
@@ -298,19 +304,18 @@ module Kitchen
298
304
  # Validates the host name of the server you can connect to
299
305
  #
300
306
  # @param [name] name is the name of the host
301
- def get_host(name)
307
+ def get_host(name, datacenter, cluster = nil)
302
308
  # create a host object to work with
303
309
  host_api = VSphereAutomation::VCenter::HostApi.new(api_client)
304
310
 
305
- if name.nil?
306
- hosts = host_api.list.value
307
- else
308
- hosts = host_api.list({ filter_names: name }).value
309
- end
311
+ hosts = host_api.list({ filter_names: name,
312
+ filter_datacenters: datacenter,
313
+ filter_clusters: cluster,
314
+ filter_connection_states: ["CONNECTED"] }).value
310
315
 
311
316
  raise format("Unable to find target host: %s", name) if hosts.empty?
312
317
 
313
- hosts.first
318
+ hosts.sample
314
319
  end
315
320
 
316
321
  # Gets the folder you want to create the VM
@@ -318,10 +323,12 @@ module Kitchen
318
323
  # @param [name] name is the name of the folder
319
324
  def get_folder(name)
320
325
  folder_api = VSphereAutomation::VCenter::FolderApi.new(api_client)
321
- folders = folder_api.list({ filter_names: name }).value
326
+ folders = folder_api.list({ filter_names: name, filter_type: "VIRTUAL_MACHINE" }).value
322
327
 
323
328
  raise format("Unable to find folder: %s", name) if folders.empty?
324
329
 
330
+ raise format("%s returned too many folders", name) if folders.length > 1
331
+
325
332
  folders.first.folder
326
333
  end
327
334
 
@@ -335,22 +342,48 @@ module Kitchen
335
342
  vms.first
336
343
  end
337
344
 
338
- # Gets the info of the cluster
345
+ # Gets the info of the datacenter
346
+ #
347
+ # @param [name] name is the name of the Datacenter
348
+ def get_datacenter(name)
349
+ dc_api = VSphereAutomation::VCenter::DatacenterApi.new(api_client)
350
+ dcs = dc_api.list({ filter_names: name }).value
351
+
352
+ raise format("Unable to find data center: %s", name) if dcs.empty?
353
+
354
+ raise format("%s returned too many data centers", name) if dcs.length > 1
355
+
356
+ dcs.first.datacenter
357
+ end
358
+
359
+ # Gets the ID of the cluster
339
360
  #
340
361
  # @param [name] name is the name of the Cluster
341
- def get_cluster(name)
362
+ def get_cluster_id(name)
363
+ return nil if name.nil?
364
+
342
365
  cluster_api = VSphereAutomation::VCenter::ClusterApi.new(api_client)
343
366
  clusters = cluster_api.list({ filter_names: name }).value
344
367
 
345
368
  raise format("Unable to find Cluster: %s", name) if clusters.empty?
346
369
 
347
- cluster_id = clusters.first.cluster
370
+ raise format("%s returned too many clusters", name) if clusters.length > 1
371
+
372
+ clusters.first.cluster
373
+ end
374
+
375
+ # Gets the info of the cluster
376
+ #
377
+ # @param [name] name is the name of the Cluster
378
+ def get_cluster(name)
379
+ cluster_id = get_cluster_id(name)
348
380
 
349
381
  host_api = VSphereAutomation::VCenter::HostApi.new(api_client)
350
382
  hosts = host_api.list({ filter_clusters: cluster_id, connection_states: "CONNECTED" }).value
351
383
 
352
384
  raise format("Unable to find active host in cluster %s", name) if hosts.empty?
353
385
 
386
+ cluster_api = VSphereAutomation::VCenter::ClusterApi.new(api_client)
354
387
  cluster_api.get(cluster_id).value
355
388
  end
356
389
 
@@ -375,14 +408,14 @@ module Kitchen
375
408
 
376
409
  # Remove default pool for first pass (<= 1.2.1 behaviour to pick first user-defined pool found)
377
410
  resource_pools = rp_api.list.value.delete_if { |pool| pool.name == "Resources" }
378
- debug("Search of all resource pools found: " + resource_pools.map { |pool| pool.name }.to_s)
411
+ debug("Search of all resource pools found: " + resource_pools.map(&:name).to_s)
379
412
 
380
413
  # Revert to default pool, if no user-defined pool found (> 1.2.1 behaviour)
381
414
  # (This one might not be found under some circumstances by the statement above)
382
415
  return get_resource_pool("Resources") if resource_pools.empty?
383
416
  else
384
417
  resource_pools = rp_api.list({ filter_names: name }).value
385
- debug("Search for resource pools found: " + resource_pools.map { |pool| pool.name }.to_s)
418
+ debug("Search for resource pools found: " + resource_pools.map(&:name).to_s)
386
419
  end
387
420
 
388
421
  raise format("Unable to find Resource Pool: %s", name) if resource_pools.empty?
@@ -58,6 +58,7 @@ class Support
58
58
  return
59
59
  end
60
60
  break if (Time.new - start) >= timeout
61
+
61
62
  sleep interval
62
63
  end
63
64
 
@@ -178,7 +179,7 @@ class Support
178
179
  RbVmomi::VIM.VirtualDeviceConfigSpec(
179
180
  operation: RbVmomi::VIM::VirtualDeviceConfigSpecOperation("edit"),
180
181
  device: network_device
181
- )
182
+ ),
182
183
  ]
183
184
  )
184
185
 
@@ -212,7 +213,7 @@ class Support
212
213
  return [
213
214
  "/sbin/modprobe -r vmxnet3",
214
215
  "/sbin/modprobe vmxnet3",
215
- "/sbin/dhclient"
216
+ "/sbin/dhclient",
216
217
  ]
217
218
  when :windows
218
219
  return [
@@ -229,7 +230,7 @@ class Support
229
230
  case options[:vm_os].downcase.to_sym
230
231
  when :linux
231
232
  [
232
- "/usr/bin/vmware-toolbox-cmd info update network"
233
+ "/usr/bin/vmware-toolbox-cmd info update network",
233
234
  ]
234
235
  when :windows
235
236
  [
@@ -292,12 +293,89 @@ class Support
292
293
  true
293
294
  end
294
295
 
296
+ def check_add_disk_config(disk_config)
297
+ valid_types = %w{thin flat flat_lazy flat_eager}
298
+
299
+ unless valid_types.include? disk_config[:type].to_s
300
+ message = format("Unknown disk type in add_disks: %s. Allowed: %s",
301
+ disk_config[:type].to_s,
302
+ valid_types.join(", "))
303
+
304
+ raise Support::CloneError.new(message)
305
+ end
306
+ end
307
+
295
308
  def reconfigure_guest
296
309
  Kitchen.logger.info "Waiting for reconfiguration to finish"
297
310
 
298
- # Pass contents of the customization option/Hash through to allow full customization
311
+ # Pass some contents right through
299
312
  # https://pubs.vmware.com/vsphere-6-5/index.jsp?topic=%2Fcom.vmware.wssdk.smssdk.doc%2Fvim.vm.ConfigSpec.html
300
- config_spec = RbVmomi::VIM.VirtualMachineConfigSpec(options[:customize])
313
+ config = options[:customize].select { |key, _| %i{annotation memoryMB numCPUs}.include? key }
314
+
315
+ add_disks = options[:customize]&.fetch(:add_disks, nil)
316
+ unless add_disks.nil?
317
+ config[:deviceChange] = []
318
+
319
+ # Will create a stem like "default-ubuntu-12345678/default-ubuntu-12345678"
320
+ filename_base = vm.disks.first.backing.fileName.gsub(/(-[0-9]+)?.vmdk/, "")
321
+
322
+ # Storage Controller and ID mapping
323
+ controller = vm.config.hardware.device.select { |device| device.is_a? RbVmomi::VIM::VirtualSCSIController }.first
324
+
325
+ add_disks.each_with_index do |disk_config, idx|
326
+ # Default to Thin Provisioning and 10GB disk size
327
+ disk_config[:type] ||= :thin
328
+ disk_config[:size_mb] ||= 10240
329
+
330
+ check_add_disk_config(disk_config)
331
+
332
+ disk_spec = RbVmomi::VIM.VirtualDeviceConfigSpec(
333
+ fileOperation: "create",
334
+ operation: RbVmomi::VIM::VirtualDeviceConfigSpecOperation("add"),
335
+ device: RbVmomi::VIM.VirtualDisk(
336
+ backing: RbVmomi::VIM.VirtualDiskFlatVer2BackingInfo(
337
+ thinProvisioned: true,
338
+ diskMode: "persistent",
339
+ fileName: format("%s_disk%03d.vmdk", filename_base, idx + 1),
340
+ datastore: vm.disks.first.backing.datastore
341
+ ),
342
+ deviceInfo: RbVmomi::VIM::Description(
343
+ label: format("Additional disk %d", idx + 1),
344
+ summary: format("%d MB", disk_config[:size_mb])
345
+ )
346
+ )
347
+ )
348
+
349
+ # capacityInKB is marked a deprecated in 6.7 but still a required parameter
350
+ disk_spec.device.capacityInBytes = disk_config[:size_mb] * 1024**2
351
+ disk_spec.device.capacityInKB = disk_config[:size_mb] * 1024
352
+
353
+ disk_spec.device.controllerKey = controller.key
354
+
355
+ highest_id = vm.disks.map(&:unitNumber).sort.last
356
+ next_id = highest_id + idx + 1
357
+
358
+ # Avoid the SCSI controller ID
359
+ next_id += 1 if next_id == controller.scsiCtlrUnitNumber
360
+
361
+ # Theoretically could add another SCSI controller, but there are limits to what kitchen should support
362
+ if next_id > 14
363
+ raise Support::CloneError.new(format("Ran out of SCSI IDs while trying to assign new disk %d", idx + 1))
364
+ end
365
+
366
+ disk_spec.device.unitNumber = next_id
367
+
368
+ device_keys = vm.config.hardware.device.map(&:key).sort
369
+ disk_spec.device.key = device_keys.last + (idx + 1) * 1000
370
+
371
+ disk_spec.device.backing.eagerlyScrub = true if disk_config[:type].to_s == "flat_eager"
372
+ disk_spec.device.backing.thinProvisioned = false if disk_config[:type].to_s =~ /^flat/
373
+
374
+ config[:deviceChange] << disk_spec
375
+ end
376
+ end
377
+
378
+ config_spec = RbVmomi::VIM.VirtualMachineConfigSpec(config)
301
379
 
302
380
  task = vm.ReconfigVM_Task(spec: config_spec)
303
381
  task.wait_for_completion
@@ -386,7 +464,7 @@ class Support
386
464
  RbVmomi::VIM.VirtualDeviceConfigSpec(
387
465
  operation: RbVmomi::VIM::VirtualDeviceConfigSpecOperation("edit"),
388
466
  device: network_device
389
- )
467
+ ),
390
468
  ]
391
469
  end
392
470
 
@@ -397,15 +475,17 @@ class Support
397
475
  if instant_clone?
398
476
  vcenter_data = vim.serviceInstance.content.about
399
477
  raise Support::CloneError.new("Instant clones only supported with vCenter 6.7 or higher") unless vcenter_data.version.to_f >= 6.7
478
+
400
479
  Kitchen.logger.debug format("Detected %s", vcenter_data.fullName)
401
480
 
402
481
  resources = dc.hostFolder.children
403
- hosts = resources.select { |resource| resource.class.to_s =~ /ComputeResource$/ }.map { |c| c.host }.flatten
482
+ hosts = resources.select { |resource| resource.class.to_s =~ /ComputeResource$/ }.map(&:host).flatten
404
483
  targethost = hosts.select { |host| host.summary.config.name == options[:targethost].name }.first
405
484
  raise Support::CloneError.new("No matching ComputeResource found in host folder") if targethost.nil?
406
485
 
407
486
  esx_data = targethost.summary.config.product
408
487
  raise Support::CloneError.new("Instant clones only supported with ESX 6.7 or higher") unless esx_data.version.to_f >= 6.7
488
+
409
489
  Kitchen.logger.debug format("Detected %s", esx_data.fullName)
410
490
 
411
491
  # Other tools check for VMWare Tools status, but that will be toolsNotRunning on frozen VMs
@@ -431,7 +511,7 @@ class Support
431
511
  RbVmomi::VIM.VirtualDeviceConfigSpec(
432
512
  operation: RbVmomi::VIM::VirtualDeviceConfigSpecOperation("edit"),
433
513
  device: network_device
434
- )
514
+ ),
435
515
  ]
436
516
 
437
517
  clone_spec = RbVmomi::VIM.VirtualMachineInstantCloneSpec(location: relocate_spec,
@@ -47,6 +47,7 @@ class Support
47
47
  loop do
48
48
  return unless process_is_running(pid)
49
49
  break if (Time.new - start) >= timeout
50
+
50
51
  sleep interval
51
52
  end
52
53
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kitchen-vcenter
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.0
4
+ version: 2.5.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chef Software
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-06-18 00:00:00.000000000 Z
11
+ date: 2019-09-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rbvmomi