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 +4 -4
- data/lib/kitchen-vcenter/version.rb +1 -1
- data/lib/kitchen/driver/vcenter.rb +50 -17
- data/lib/support/clone_vm.rb +88 -8
- data/lib/support/guest_operations.rb +1 -0
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 69eea65c20662c0ec15d88d55d4871d57978427d2b1ebb86977236f5e955f407
|
|
4
|
+
data.tar.gz: e07a74cb3f693286e7721bf40346fb4f9cd8b6f2cf720292d5c07ced71982956
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b576ba091634bb15c78ea248a6aa5bd7c2e69f6c682cf3b03472cf02389d844e9f8c974fe8435f47792f1608db9480f55df5fafe95293e2df98580071187b0d7
|
|
7
|
+
data.tar.gz: 86d97a406cb9e7ec156baa0af3743aea8ade5591efda376ce7dd58044113a9f4ab1fa9ee2645544a4de6362c55938f795aa6627e131e9f5b92677d4536e460c9
|
|
@@ -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
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
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.
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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?
|
data/lib/support/clone_vm.rb
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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
|
|
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,
|
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
|
+
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-
|
|
11
|
+
date: 2019-09-16 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rbvmomi
|