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