diff --git a/lib/chef/knife/search_helper.rb b/lib/chef/knife/search_helper.rb new file mode 100644 index 00000000..970fed21 --- /dev/null +++ b/lib/chef/knife/search_helper.rb @@ -0,0 +1,41 @@ +# Some helpers for faster searching of the inventory +module SearchHelper + # Retrieves all the VM objects and returns their ObjectContents + # Note that since it's a ObjectContent coming back, the individual + # object's [] will return only the properties you asked for + # and `#obj` will return the actual object (but make a call to the server) + # param [Array] properties to retrieve + # @return [Array] + def get_all_vm_objects(properties = ['name']) + pc = vim_connection.serviceInstance.content.propertyCollector + viewmgr = vim_connection.serviceInstance.content.viewManager + root_folder = vim_connection.serviceInstance.content.rootFolder + vmview = viewmgr.CreateContainerView(container: root_folder, + type: ['VirtualMachine'], + recursive: true) + + filter_spec = RbVmomi::VIM.PropertyFilterSpec( + objectSet: [ + obj: vmview, + skip: true, + selectSet: [ + RbVmomi::VIM.TraversalSpec( + name: 'traverseEntities', + type: 'ContainerView', + path: 'view', + skip: false + ) + ] + ], + propSet: [ + { type: 'VirtualMachine', pathSet: properties } + ] + ) + pc.RetrieveProperties(specSet: [filter_spec]) + end + + def get_vm_by_name(vmname) + vm = get_all_vm_objects.detect { |r| r['name'] == vmname } + vm ? vm.obj : nil + end +end diff --git a/lib/chef/knife/vsphere_vm_config.rb b/lib/chef/knife/vsphere_vm_config.rb index 981e4edc..7cbae964 100644 --- a/lib/chef/knife/vsphere_vm_config.rb +++ b/lib/chef/knife/vsphere_vm_config.rb @@ -3,11 +3,11 @@ require 'chef/knife' require 'chef/knife/base_vsphere_command' -require 'rbvmomi' -require 'netaddr' +require 'chef/knife/search_helper' # VsphereVMconfig extends the BaseVspherecommand class Chef::Knife::VsphereVmConfig < Chef::Knife::BaseVsphereCommand + include SearchHelper banner "knife vsphere vm config VMNAME PROPERTY VALUE. See \"http://pubs.vmware.com/vi3/sdk/ReferenceGuide/vim.vm.ConfigSpec.html\" for allowed ATTRIBUTE values (any property of type xs:string is supported)." @@ -39,10 +39,7 @@ def run vim_connection - dc = datacenter - folder = find_folder(get_config(:folder)) || dc.vmFolder - - vm = traverse_folders_for_vm(folder, vmname) || abort("VM #{vmname} not found") + vm = get_vm_by_name(vmname) || fatal_exit("Could not find #{vmname}") properties = {} properties[property_name] = property_value diff --git a/lib/chef/knife/vsphere_vm_disk_list.rb b/lib/chef/knife/vsphere_vm_disk_list.rb index e03b456f..312ad5be 100644 --- a/lib/chef/knife/vsphere_vm_disk_list.rb +++ b/lib/chef/knife/vsphere_vm_disk_list.rb @@ -1,9 +1,12 @@ require 'chef/knife' require 'chef/knife/base_vsphere_command' +require 'chef/knife/search_helper' # List the disks attached to a VM # VsphereVmdisklist extends the BaseVspherecommand class Chef::Knife::VsphereVmDiskList < Chef::Knife::BaseVsphereCommand + include SearchHelper + banner 'knife vsphere vm disk list VMNAME' common_options @@ -18,9 +21,7 @@ def run fatal_exit 'You must specify a virtual machine name' end - vim_connection - vm = get_vm(vmname) - fatal_exit "Could not find #{vmname}" unless vm + vm = get_vm_by_name(vmname) || fatal_exit("Could not find #{vmname}") disks = vm.config.hardware.device.select do |device| device.is_a? RbVmomi::VIM::VirtualDisk diff --git a/lib/chef/knife/vsphere_vm_property_set.rb b/lib/chef/knife/vsphere_vm_property_set.rb index 56fd63c1..7baf97a5 100644 --- a/lib/chef/knife/vsphere_vm_property_set.rb +++ b/lib/chef/knife/vsphere_vm_property_set.rb @@ -3,11 +3,11 @@ require 'chef/knife' require 'chef/knife/base_vsphere_command' -require 'rbvmomi' -require 'netaddr' +require 'chef/knife/search_helper' # VsphereVMPropertySet extends Basevspherecommand class Chef::Knife::VsphereVmPropertySet < Chef::Knife::BaseVsphereCommand + include SearchHelper banner 'knife vsphere vm property set VMNAME PROPERTY VALUE. Sets a vApp Property on VMNAME.' common_options @@ -42,9 +42,8 @@ def run vim_connection dc = datacenter - folder = find_folder(get_config(:folder)) || dc.vmFolder - vm = find_in_folder(folder, RbVmomi::VIM::VirtualMachine, vmname) || abort("VM #{vmname} not found") + vm = get_vm_by_name(vmname) || fatal_exit("Could not find #{vmname}") if vm.config.vAppConfig && vm.config.vAppConfig.property existing_property = vm.config.vAppConfig.property.find { |p| p.props[:id] == property_name.to_s } diff --git a/lib/chef/knife/vsphere_vm_snapshot.rb b/lib/chef/knife/vsphere_vm_snapshot.rb index 97a37fd8..115980f5 100644 --- a/lib/chef/knife/vsphere_vm_snapshot.rb +++ b/lib/chef/knife/vsphere_vm_snapshot.rb @@ -4,11 +4,11 @@ require 'chef/knife' require 'chef/knife/base_vsphere_command' -require 'rbvmomi' -require 'netaddr' +require 'chef/knife/search_helper' # Manage snapshots of a virtual machine class Chef::Knife::VsphereVmSnapshot < Chef::Knife::BaseVsphereCommand + include SearchHelper banner 'knife vsphere vm snapshot VMNAME (options)' common_options @@ -44,7 +44,7 @@ class Chef::Knife::VsphereVmSnapshot < Chef::Knife::BaseVsphereCommand description: 'Indicates whether to wait for creation/removal to complete', boolean: false - option :find, + option :find, # imma deprecate this long: '--find', description: 'Finds the virtual machine by searching all folders' @@ -77,14 +77,7 @@ def run vim_connection - vm = if get_config(:find) - puts "No folder entered, searching for #{vmname}" - src_folder = find_folder(get_config(:folder)) - traverse_folders_for_vm(src_folder, vmname) - else - base_folder = find_folder get_config(:folder) - find_in_folder(base_folder, RbVmomi::VIM::VirtualMachine, vmname) || abort("VM #{vmname} not found") - end + vm = get_vm_by_name(vmname) || fatal_exit("Could not find #{vmname}") if vm.snapshot snapshot_list = vm.snapshot.rootSnapshotList diff --git a/lib/chef/knife/vsphere_vm_state.rb b/lib/chef/knife/vsphere_vm_state.rb index e39d602e..52d52fb6 100644 --- a/lib/chef/knife/vsphere_vm_state.rb +++ b/lib/chef/knife/vsphere_vm_state.rb @@ -5,12 +5,12 @@ require 'chef/knife' require 'chef/knife/base_vsphere_command' -require 'rbvmomi' -require 'netaddr' +require 'chef/knife/search_helper' # Manage power state of a virtual machine # VsphereVmState extends the BaseVspherecommand class Chef::Knife::VsphereVmState < Chef::Knife::BaseVsphereCommand + include SearchHelper # The Different power states that vSphere reports POWER_STATES = { PS_ON => 'powered on', @@ -56,18 +56,7 @@ def run vim_connection - if get_config(:recursive) - vms = get_vms(vmname) - if vms.length > 1 - abort "More than one VM with name #{vmname} found:\n" + vms.map { |vm| get_path_to_object(vm) }.join("\n") - end - abort "VM #{vmname} not found" if vms.length == 0 - vm = vms[0] - else - base_folder = find_folder(get_config(:folder)) - - vm = find_in_folder(base_folder, RbVmomi::VIM::VirtualMachine, vmname) || abort("VM #{vmname} not found") - end + vm = get_vm_by_name(vmname) || fatal_exit("Could not find #{vmname}") state = vm.runtime.powerState