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