kitchen-vcenter 2.4.0 → 2.5.2

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