knife-vsphere 2.0.5 → 2.1.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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 28d327261e11658b4d6f926e93b136a1c4979e55
|
4
|
+
data.tar.gz: 4c0499b076d8197ccdbd44f9aba9834989e65743
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dfdd72ab2858dc5ae00bc8e688c737562a68eb65e52a34e004629a7d7b40a1acb3776dc061c16cfc6699b788ea2f9c66c222af7608b8f3f174cee4fc0de775c1
|
7
|
+
data.tar.gz: 11f6c48d15e56559a0b6181d9e6506ae0c7d77ad9eec8f70dacbfaf4ab4103d31d18c8551c8a0c468097573c1e1fc4dcad753cded01d84a86a898b94e46a8e26
|
@@ -64,7 +64,7 @@ class Chef::Knife::VsphereVmCdrom < Chef::Knife::BaseVsphereCommand
|
|
64
64
|
fatal_exit 'You must specify the name and path of an ISO with --iso' if get_config(:attach) && !get_config(:iso)
|
65
65
|
fatal_exit 'You must specify the datastore containing the ISO with --datastore' if get_config(:attach) && !get_config(:datastore)
|
66
66
|
|
67
|
-
vm = get_vm_by_name(vmname,
|
67
|
+
vm = get_vm_by_name(vmname, get_config(:folder)) || fatal_exit("Could not find #{vmname}")
|
68
68
|
|
69
69
|
cdrom_obj = vm.config.hardware.device.find { |hw| hw.class == RbVmomi::VIM::VirtualCdrom }
|
70
70
|
fatal_exit 'Could not find a cd drive' unless cdrom_obj
|
@@ -8,12 +8,12 @@
|
|
8
8
|
|
9
9
|
require 'chef/knife'
|
10
10
|
require 'chef/knife/base_vsphere_command'
|
11
|
-
require 'rbvmomi'
|
12
|
-
require 'netaddr'
|
13
|
-
require 'securerandom'
|
14
|
-
require 'chef/knife/winrm_base'
|
15
11
|
require 'chef/knife/customization_helper'
|
12
|
+
require 'chef/knife/search_helper'
|
13
|
+
require 'chef/knife/winrm_base'
|
16
14
|
require 'ipaddr'
|
15
|
+
require 'netaddr'
|
16
|
+
require 'securerandom'
|
17
17
|
|
18
18
|
# VsphereVmClone extends the BaseVspherecommand
|
19
19
|
class Chef::Knife::VsphereVmClone < Chef::Knife::BaseVsphereCommand
|
@@ -28,6 +28,7 @@ class Chef::Knife::VsphereVmClone < Chef::Knife::BaseVsphereCommand
|
|
28
28
|
|
29
29
|
include Chef::Knife::WinrmBase
|
30
30
|
include CustomizationHelper
|
31
|
+
include SearchHelper
|
31
32
|
deps do
|
32
33
|
require 'chef/json_compat'
|
33
34
|
require 'chef/knife/bootstrap'
|
@@ -351,17 +352,13 @@ class Chef::Knife::VsphereVmClone < Chef::Knife::BaseVsphereCommand
|
|
351
352
|
end
|
352
353
|
|
353
354
|
config[:chef_node_name] = vmname unless get_config(:chef_node_name)
|
354
|
-
config[:vmname] = vmname
|
355
355
|
|
356
356
|
vim = vim_connection
|
357
357
|
vim.serviceContent.virtualDiskManager
|
358
358
|
|
359
359
|
dc = datacenter
|
360
360
|
|
361
|
-
|
362
|
-
|
363
|
-
src_vm = find_in_folder(src_folder, RbVmomi::VIM::VirtualMachine, config[:source_vm]) ||
|
364
|
-
abort('VM/Template not found')
|
361
|
+
src_vm = get_vm_by_name(get_config(:source_vm), get_config(:folder)) || fatal_exit("Could not find template #{vmname}")
|
365
362
|
|
366
363
|
create_delta_disk(src_vm) if get_config(:linked_clone)
|
367
364
|
|
@@ -372,7 +369,7 @@ class Chef::Knife::VsphereVmClone < Chef::Knife::BaseVsphereCommand
|
|
372
369
|
dest_folder = cust_folder.nil? ? src_vm.vmFolder : find_folder(cust_folder)
|
373
370
|
|
374
371
|
task = src_vm.CloneVM_Task(folder: dest_folder, name: vmname, spec: clone_spec)
|
375
|
-
puts "Cloning template #{
|
372
|
+
puts "Cloning template #{get_config(:source_vm)} to new VM #{vmname}"
|
376
373
|
|
377
374
|
pp clone_spec if log_verbose?
|
378
375
|
|
@@ -398,8 +395,7 @@ class Chef::Knife::VsphereVmClone < Chef::Knife::BaseVsphereCommand
|
|
398
395
|
|
399
396
|
return if get_config(:mark_as_template)
|
400
397
|
if get_config(:power) || get_config(:bootstrap)
|
401
|
-
vm =
|
402
|
-
fatal_exit("VM #{vmname} not found")
|
398
|
+
vm = get_vm_by_name(vmname, cust_folder) || fatal_exit("VM #{vmname} not found")
|
403
399
|
begin
|
404
400
|
vm.PowerOnVM_Task.wait_for_completion
|
405
401
|
rescue RbVmomi::Fault => e
|
@@ -704,7 +700,7 @@ class Chef::Knife::VsphereVmClone < Chef::Knife::BaseVsphereCommand
|
|
704
700
|
|
705
701
|
# TODO: How could we not take this? Only if the identity were empty, but that's statically defined as empty above
|
706
702
|
if use_ident
|
707
|
-
hostname = config[:customization_hostname] ||
|
703
|
+
hostname = config[:customization_hostname] || vmname
|
708
704
|
|
709
705
|
if windows?(src_config)
|
710
706
|
# We should get here with the customizations set, either by a plugin or a --cspec
|
@@ -1,24 +1,26 @@
|
|
1
|
-
#
|
2
1
|
# Author:: Raducu Deaconu (<rhadoo_io@yahoo.com>)
|
3
2
|
# License:: Apache License, Version 2.0
|
4
3
|
#
|
5
4
|
|
6
5
|
require 'chef/knife'
|
7
6
|
require 'chef/knife/base_vsphere_command'
|
8
|
-
require '
|
9
|
-
require 'netaddr'
|
7
|
+
require 'chef/knife/search_helper'
|
10
8
|
|
11
9
|
# find vms belonging to pool that match criteria, display specified fields
|
12
10
|
class Chef::Knife::VsphereVmFind < Chef::Knife::BaseVsphereCommand
|
11
|
+
include SearchHelper
|
13
12
|
banner 'knife vsphere vm find'
|
14
13
|
|
14
|
+
VMFOLDER = 'vm'.freeze
|
15
|
+
|
15
16
|
common_options
|
16
17
|
|
18
|
+
# Deprecating
|
17
19
|
option :pool,
|
18
20
|
long: '--pool pool',
|
19
21
|
short: '-h',
|
20
22
|
description: 'Target pool'
|
21
|
-
|
23
|
+
# Deprecating
|
22
24
|
option :poolpath,
|
23
25
|
long: '--pool-path',
|
24
26
|
description: 'Pool is full-path'
|
@@ -55,10 +57,6 @@ class Chef::Knife::VsphereVmFind < Chef::Knife::BaseVsphereCommand
|
|
55
57
|
long: '--ip',
|
56
58
|
description: 'Show primary ip'
|
57
59
|
|
58
|
-
option :ips,
|
59
|
-
long: '--ips',
|
60
|
-
description: 'Show all ips, with networks - DEPRECATED use --networks'
|
61
|
-
|
62
60
|
option :networks,
|
63
61
|
long: '--networks',
|
64
62
|
description: 'Show all networks with their IPs'
|
@@ -83,6 +81,10 @@ class Chef::Knife::VsphereVmFind < Chef::Knife::BaseVsphereCommand
|
|
83
81
|
long: '--match-name VMNAME',
|
84
82
|
description: 'match name'
|
85
83
|
|
84
|
+
option :matchtools,
|
85
|
+
long: '--match-tools TOOLSSTATE',
|
86
|
+
description: 'match tools state'
|
87
|
+
|
86
88
|
option :hostname,
|
87
89
|
long: '--hostname',
|
88
90
|
description: 'show hostname of the guest'
|
@@ -103,189 +105,145 @@ class Chef::Knife::VsphereVmFind < Chef::Knife::BaseVsphereCommand
|
|
103
105
|
long: '--tools',
|
104
106
|
description: 'show tools status'
|
105
107
|
|
106
|
-
option :matchtools,
|
107
|
-
long: '--match-tools TOOLSSTATE',
|
108
|
-
description: 'match tools state'
|
109
|
-
|
110
108
|
option :full_path,
|
111
109
|
long: '--full-path',
|
112
|
-
description: 'Show full path'
|
110
|
+
description: 'Show full folder path to the VM'
|
113
111
|
|
114
|
-
|
112
|
+
option :short_path,
|
113
|
+
long: '--short-path',
|
114
|
+
description: 'Show the VM\'s enclosing folder name'
|
115
115
|
|
116
|
-
|
117
|
-
# @param folder [RbVmomi::VIM::Folder] the folder from which to start the search, most likely dc.hostFolder
|
118
|
-
# @param objectname [String] name of the object (pool or cluster/compute) to find
|
119
|
-
# @return [RbVmomi::VIM::ClusterComputeResource, RbVmomi::VIM::ComputeResource, RbVmomi::VIM::ResourcePool]
|
120
|
-
def traverse_folders_for_pool_clustercompute(folder, objectname)
|
121
|
-
children = find_all_in_folder(folder, RbVmomi::VIM::ManagedObject)
|
122
|
-
children.each do |child|
|
123
|
-
next unless child.class == RbVmomi::VIM::ClusterComputeResource || child.class == RbVmomi::VIM::ComputeResource || child.class == RbVmomi::VIM::ResourcePool
|
124
|
-
if child.name == objectname
|
125
|
-
return child
|
126
|
-
elsif child.class == RbVmomi::VIM::Folder || child.class == RbVmomi::VIM::ComputeResource || child.class == RbVmomi::VIM::ClusterComputeResource || child.class == RbVmomi::VIM::ResourcePool
|
127
|
-
pool = traverse_folders_for_pool_clustercompute(child, objectname)
|
128
|
-
end
|
129
|
-
return pool if pool
|
130
|
-
end
|
131
|
-
false
|
132
|
-
end
|
116
|
+
$stdout.sync = true # smoother output from print
|
133
117
|
|
134
118
|
# Main entry point to the command
|
135
119
|
def run
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
output = vm_list.map do |vm|
|
161
|
-
thisvm = {}
|
162
|
-
if get_config(:matchname)
|
163
|
-
next unless vm.name.include? config[:matchname]
|
164
|
-
end
|
165
|
-
|
166
|
-
if get_config(:matchtools)
|
167
|
-
next unless vm.guest.toolsStatus == config[:matchtools]
|
168
|
-
end
|
169
|
-
|
170
|
-
power_state = vm.runtime.powerState
|
171
|
-
|
172
|
-
thisvm['state'] = case power_state
|
173
|
-
when PS_ON
|
174
|
-
'on'
|
175
|
-
when PS_OFF
|
176
|
-
'off'
|
177
|
-
when PS_SUSPENDED
|
178
|
-
'suspended'
|
179
|
-
end
|
180
|
-
|
181
|
-
|
182
|
-
next if get_config(:soff) && (power_state == PS_ON)
|
183
|
-
|
184
|
-
next if get_config(:son) && (power_state == PS_OFF)
|
185
|
-
|
186
|
-
if get_config(:matchip)
|
187
|
-
if !vm.guest.ipAddress.nil? && vm.guest.ipAddress != ''
|
188
|
-
next unless vm.guest.ipAddress.include? config[:matchip]
|
189
|
-
else
|
190
|
-
next
|
191
|
-
end
|
192
|
-
end
|
193
|
-
|
194
|
-
unless vm.guest.guestFullName.nil?
|
195
|
-
if get_config(:matchos)
|
196
|
-
next unless vm.guest.guestFullName.include? config[:matchos]
|
120
|
+
property_map('name' => 'name')
|
121
|
+
property_map('runtime.powerState' => 'state') { |value| state_to_english(value) }
|
122
|
+
|
123
|
+
property_map('config.cpuHotAddEnabled' => 'cpu_hot_add_enabled') if get_config(:cpu_hot_add_enabled)
|
124
|
+
property_map('config.memoryHotAddEnabled' => 'memory_hot_add_enabled') if get_config(:memory_hot_add_enabled)
|
125
|
+
property_map('guest.guestFullName' => 'os') if get_config(:matchos) || get_config(:os)
|
126
|
+
property_map('guest.hostName' => 'hostname') if get_config(:hostname)
|
127
|
+
property_map('guest.ipAddress' => 'ip') if get_config(:matchip) || get_config(:ip)
|
128
|
+
property_map('guest.toolsStatus' => 'tools') if get_config(:matchtools) || get_config(:tools)
|
129
|
+
property_map('summary.config.memorySizeMB' => 'ram') if get_config(:ram)
|
130
|
+
property_map('summary.config.numCpu' => 'cpu') if get_config(:cpu)
|
131
|
+
property_map('summary.overallStatus' => 'alarms') if get_config(:alarms)
|
132
|
+
property_map('summary.runtime.host' => 'host_name', &:name) if get_config(:host_name)
|
133
|
+
|
134
|
+
# TODO: https://www.vmware.com/support/developer/converter-sdk/conv55_apireference/vim.VirtualMachine.html#field_detail says this is deprecated
|
135
|
+
property_map('layout.disk' => 'esx_disk') { |disks| disks.map(&:diskFile) } if get_config(:esx_disk)
|
136
|
+
property_map('snapshot.rootSnapshotList' => 'snapshots') { |snapshots| Array(snapshots).map(&:name) } if get_config(:snapshots)
|
137
|
+
|
138
|
+
if get_config(:networks)
|
139
|
+
property_map('guest.net' => 'networks') do |nets|
|
140
|
+
ipregex = /^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/
|
141
|
+
nets.map do |net|
|
142
|
+
firstip = net.ipConfig.ipAddress.first { |i| i.ipAddress[ipregex] }
|
143
|
+
{ 'name' => net.network, 'ip' => firstip.ipAddress, 'prefix' => firstip.prefixLength }
|
197
144
|
end
|
198
145
|
end
|
146
|
+
end
|
199
147
|
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
thisvm['host_name'] = vm.summary.runtime.host.name
|
207
|
-
end
|
208
|
-
|
209
|
-
if get_config(:full_path)
|
210
|
-
fullpath = ''
|
211
|
-
iterator = vm
|
212
|
-
|
213
|
-
while iterator = iterator.parent
|
214
|
-
break if iterator.name == 'vm'
|
215
|
-
fullpath = fullpath.empty? ? iterator.name : "#{iterator.name}/#{fullpath}"
|
148
|
+
if get_config(:os_disk)
|
149
|
+
property_map('guest.disk' => 'disks') do |disks|
|
150
|
+
disks.map do |disk|
|
151
|
+
{ 'name' => disk.diskPath,
|
152
|
+
'capacity' => disk.capacity / 1024 / 1024,
|
153
|
+
'free' => disk.freeSpace / 1024 / 1024 }
|
216
154
|
end
|
217
|
-
thisvm['folder'] = fullpath
|
218
|
-
else
|
219
|
-
thisvm['folder'] = vm.parent.name
|
220
155
|
end
|
156
|
+
end
|
221
157
|
|
222
|
-
|
223
|
-
|
158
|
+
output = matched_vms.map do |vm|
|
159
|
+
thisvm = {}
|
160
|
+
@output_pairs.each do |property, out_key|
|
161
|
+
thisvm[out_key] = if @blocks[out_key]
|
162
|
+
@blocks[out_key].call(vm[property])
|
163
|
+
else
|
164
|
+
vm[property]
|
165
|
+
end
|
224
166
|
end
|
225
167
|
|
226
|
-
if get_config(:
|
227
|
-
|
228
|
-
thisvm['networks'] = vm.guest.net.map do |net|
|
229
|
-
firstip = net.ipConfig.ipAddress.first { |i| i.ipAddress[ipregex] }
|
168
|
+
thisvm['folder'] = full_path_to(vm) if get_config(:full_path)
|
169
|
+
thisvm['folder'] = vm.obj.parent.name if get_config(:short_path)
|
230
170
|
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
end
|
236
|
-
end
|
171
|
+
thisvm
|
172
|
+
end
|
173
|
+
ui.output(output.compact)
|
174
|
+
end
|
237
175
|
|
238
|
-
|
239
|
-
|
240
|
-
|
176
|
+
private
|
177
|
+
|
178
|
+
# property_map sets up the things we'll ask from vmware, and how they'll be displayed
|
179
|
+
# If it's passed a Hash then we'll request the key from vmware and the output will appear
|
180
|
+
# in the item specified by key.
|
181
|
+
# If you pass a block, then the result from vsphere will be passed to the block and that value used instead
|
182
|
+
def property_map(property_pair, &block)
|
183
|
+
@properties ||= []
|
184
|
+
@output_pairs ||= {}
|
185
|
+
@blocks ||= {}
|
186
|
+
|
187
|
+
(prop, out_key) = property_pair.first
|
188
|
+
@properties << prop
|
189
|
+
@output_pairs[prop] = out_key
|
190
|
+
@blocks[out_key] = block if block
|
191
|
+
end
|
241
192
|
|
242
|
-
|
243
|
-
|
244
|
-
|
193
|
+
def matched_vms
|
194
|
+
get_all_vm_objects(properties: @properties).select { |vm| match_vm? vm }
|
195
|
+
end
|
245
196
|
|
246
|
-
|
247
|
-
|
248
|
-
|
197
|
+
def match_vm?(vm)
|
198
|
+
match_name?(vm['name']) &&
|
199
|
+
match_tools?(vm['guest.toolsStatus']) &&
|
200
|
+
match_power_state?(vm['runtime.powerState']) &&
|
201
|
+
match_ip?(vm['guest.ipAddress']) &&
|
202
|
+
match_os?(vm['guest.guestFullName'])
|
203
|
+
end
|
249
204
|
|
250
|
-
|
251
|
-
|
252
|
-
|
205
|
+
def match_name?(name)
|
206
|
+
!get_config(:matchname) || name.include?(get_config(:matchname))
|
207
|
+
end
|
253
208
|
|
254
|
-
|
255
|
-
|
256
|
-
|
209
|
+
def match_tools?(tools)
|
210
|
+
!get_config(:matchtools) || tools == get_config(:matchtools)
|
211
|
+
end
|
257
212
|
|
258
|
-
|
259
|
-
|
260
|
-
|
213
|
+
def match_power_state?(power_state)
|
214
|
+
!(get_config(:son) || get_config(:soff)) ||
|
215
|
+
get_config(:son) && power_state == PS_ON ||
|
216
|
+
get_config(:soff) && power_state == PS_OFF
|
217
|
+
end
|
261
218
|
|
262
|
-
|
263
|
-
|
264
|
-
|
219
|
+
def match_ip?(ip)
|
220
|
+
ip ||= 'NOTANIP'
|
221
|
+
!get_config(:matchip) || ip.include?(get_config(:matchip))
|
222
|
+
end
|
265
223
|
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
'capacity' => disk.capacity / 1024 / 1024,
|
270
|
-
'free' => disk.freeSpace / 1024 / 1024
|
271
|
-
}
|
272
|
-
end
|
273
|
-
end
|
224
|
+
def match_os?(os)
|
225
|
+
!get_config(:matchos) || (os && os.include?(get_config(:matchos)))
|
226
|
+
end
|
274
227
|
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
228
|
+
def state_to_english(power_state)
|
229
|
+
case power_state
|
230
|
+
when PS_ON
|
231
|
+
'on'
|
232
|
+
when PS_OFF
|
233
|
+
'off'
|
234
|
+
when PS_SUSPENDED
|
235
|
+
'suspended'
|
236
|
+
end
|
237
|
+
end
|
279
238
|
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
end
|
287
|
-
thisvm
|
239
|
+
def full_path_to(vm)
|
240
|
+
path = []
|
241
|
+
iterator = vm.obj
|
242
|
+
while (iterator = iterator.parent)
|
243
|
+
break if iterator.name == VMFOLDER
|
244
|
+
path.unshift iterator.name
|
288
245
|
end
|
289
|
-
|
246
|
+
|
247
|
+
path.join '/'
|
290
248
|
end
|
291
249
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: knife-vsphere
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ezra Pagel
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-03-
|
11
|
+
date: 2018-03-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: knife-windows
|
@@ -237,7 +237,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
237
237
|
version: '0'
|
238
238
|
requirements: []
|
239
239
|
rubyforge_project:
|
240
|
-
rubygems_version: 2.6.
|
240
|
+
rubygems_version: 2.6.11
|
241
241
|
signing_key:
|
242
242
|
specification_version: 4
|
243
243
|
summary: vSphere Support for Knife
|