knife-vsphere 2.0.5 → 2.1.0

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
  SHA1:
3
- metadata.gz: eb16b64d53791bd6e96ba472a5567de9c8f16cf2
4
- data.tar.gz: 6da5cf9fe415bba0e43e48ecf6b70e084152dde1
3
+ metadata.gz: 28d327261e11658b4d6f926e93b136a1c4979e55
4
+ data.tar.gz: 4c0499b076d8197ccdbd44f9aba9834989e65743
5
5
  SHA512:
6
- metadata.gz: 29a121097a149a4f65a477e25e81a8a5050f30211a34819453bd9ee40f919b5173c6fd42f96ffc23804c5530e1ec79a18f8453eac427e3146d4b6db654fd586c
7
- data.tar.gz: 54c0d812429c81c78961c7e3cdda47c713fa175e53304289831c1fb8105f5132a7bcdb7a57e4648519d53daae996812c556c2b944c3c7ea6d7e7b72726d2b069
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, config[:folder]) || fatal_exit("Could not find #{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
- src_folder = find_folder(get_config(:folder)) || dc.vmFolder
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 #{config[:source_vm]} to new VM #{vmname}"
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 = find_in_folder(dest_folder, RbVmomi::VIM::VirtualMachine, vmname) ||
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] || config[:vmname]
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 'rbvmomi'
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
- $stdout.sync = true # smoother output from print
112
+ option :short_path,
113
+ long: '--short-path',
114
+ description: 'Show the VM\'s enclosing folder name'
115
115
 
116
- # Find the given pool or compute resource
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
- poolname = config[:pool]
137
- if poolname.nil?
138
- show_usage
139
- fatal_exit('You must specify a resource pool or cluster name (see knife vsphere pool list)')
140
- end
141
-
142
- abort '--ips has been removed. Please use --networks' if get_config(:ips)
143
-
144
- vim_connection
145
- dc = datacenter
146
- folder = dc.hostFolder
147
- pool = if get_config(:poolpath)
148
- find_pool(poolname) || abort("Pool #{poolname} not found")
149
- else
150
- traverse_folders_for_pool_clustercompute(folder, poolname) || abort("Pool #{poolname} not found")
151
- end
152
- vm_list = if pool.class == RbVmomi::VIM::ResourcePool
153
- pool.vm
154
- else
155
- pool.resourcePool.vm
156
- end
157
-
158
- return if vm_list.nil?
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
- thisvm['name'] = vm.name
201
- if get_config(:hostname)
202
- thisvm['hostname'] = vm.guest.hostName
203
- end
204
- if get_config(:host_name)
205
- # TODO: Why vm.summary.runtime vs vm.runtime?
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
- if get_config(:ip)
223
- thisvm['ip'] = vm.guest.ipAddress
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(:networks)
227
- ipregex = /^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/
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
- { 'name' => net.network,
232
- 'ip' => firstip.ipAddress,
233
- 'prefix' => firstip.prefixLength
234
- }
235
- end
236
- end
171
+ thisvm
172
+ end
173
+ ui.output(output.compact)
174
+ end
237
175
 
238
- if get_config(:os)
239
- thisvm['os'] = vm.guest.guestFullName
240
- end
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
- if get_config(:ram)
243
- thisvm['ram'] = vm.summary.config.memorySizeMB
244
- end
193
+ def matched_vms
194
+ get_all_vm_objects(properties: @properties).select { |vm| match_vm? vm }
195
+ end
245
196
 
246
- if get_config(:cpu_hot_add_enabled)
247
- thisvm['cpu_hot_add_enabled'] = vm.config.cpuHotAddEnabled
248
- end
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
- if get_config(:memory_hot_add_enabled)
251
- thisvm['memory_hot_add_enabled'] = vm.config.memoryHotAddEnabled
252
- end
205
+ def match_name?(name)
206
+ !get_config(:matchname) || name.include?(get_config(:matchname))
207
+ end
253
208
 
254
- if get_config(:cpu)
255
- thisvm['cpu'] = vm.summary.config.numCpu
256
- end
209
+ def match_tools?(tools)
210
+ !get_config(:matchtools) || tools == get_config(:matchtools)
211
+ end
257
212
 
258
- if get_config(:alarms)
259
- thisvm['alarms'] = vm.summary.overallStatus
260
- end
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
- if get_config(:tools)
263
- thisvm['tools'] = vm.guest.toolsStatus
264
- end
219
+ def match_ip?(ip)
220
+ ip ||= 'NOTANIP'
221
+ !get_config(:matchip) || ip.include?(get_config(:matchip))
222
+ end
265
223
 
266
- if get_config(:os_disk)
267
- thisvm['disks'] = vm.guest.disk.map do |disk|
268
- { 'name' => disk.diskPath,
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
- if get_config(:esx_disk)
276
- # TODO: https://www.vmware.com/support/developer/converter-sdk/conv55_apireference/vim.VirtualMachine.html#field_detail says this is deprecated
277
- thisvm['esx_disks'] = vm.layout.disk.map(&:diskFile)
278
- end
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
- if get_config(:snapshots)
281
- thisvm['snapshots'] = if vm.snapshot
282
- vm.snapshot.rootSnapshotList.map(&:name)
283
- else
284
- []
285
- end
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
- ui.output(output.compact)
246
+
247
+ path.join '/'
290
248
  end
291
249
  end
@@ -42,8 +42,6 @@ class Chef::Knife::VsphereVmWaitSysprep < Chef::Knife::BaseVsphereCommand
42
42
  fatal_exit('You must specify a virtual machine name')
43
43
  end
44
44
 
45
- config[:vmname] = vmname
46
-
47
45
  sleep_time = get_config(:sleep).to_i
48
46
  sleep_timeout = get_config(:timeout).to_i
49
47
 
@@ -1,5 +1,5 @@
1
1
  # The main knife-vsphere module.
2
2
  module KnifeVsphere
3
3
  # The version of this gem.
4
- VERSION = '2.0.5'
4
+ VERSION = '2.1.0'
5
5
  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.5
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-22 00:00:00.000000000 Z
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.14
240
+ rubygems_version: 2.6.11
241
241
  signing_key:
242
242
  specification_version: 4
243
243
  summary: vSphere Support for Knife