From 555e0964f7d530267e65c80f83dfc12e4346905f Mon Sep 17 00:00:00 2001 From: Sean Walberg Date: Thu, 15 Mar 2018 14:26:53 -0400 Subject: [PATCH] Improve the speed of finding an individual VM This PR makes use of the [ContainerView](https://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/vim.view.ViewManager.html) to retrieve a cut down list of servers from which the desired object can be found, after which the object itself can be downloaded. Previously, we'd download each VM (about 3.5K and several round trips to the server) to find the VM we want. From ``` sean~/play/knife-vsphere (find_speed %)$ time knife vsphere vm disk list myserver 0 Hard disk 1 nosnapshots_ds4 64.00 GiB real 1m56.153s user 0m9.536s sys 0m1.713s ``` to ``` sean~/play/knife-vsphere (find_speed *%)$ time be knife vsphere vm disk list myserver /Users/sean/.gem/ruby/2.4.1/gems/builder-3.2.2/lib/builder/xchar.rb:111: warning: constant ::Fixnum is deprecated 0 Hard disk 1 nosnapshots_ds4 64.00 GiB real 0m2.929s user 0m1.038s sys 0m0.236s ``` This'll have to be retrofitted to the other commands, which we can do over time. See https://github.com/vmware/rbvmomi/issues/117 for some more context --- lib/chef/knife/search_helper.rb | 41 ++++++++++++++++++++++++++ lib/chef/knife/vsphere_vm_disk_list.rb | 7 +++-- 2 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 lib/chef/knife/search_helper.rb 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_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