class Chef::Knife::BaseVsphereCommand
Main knife vsphere that more or less everything in this gem is built off of
Public Class Methods
common_options()
click to toggle source
# File lib/chef/knife/helpers/base_vsphere_command.rb, line 34 def self.common_options option :vsphere_user, short: "-u USERNAME", long: "--vsuser USERNAME", description: "The username for vsphere" option :vsphere_pass, short: "-p PASSWORD", long: "--vspass PASSWORD", description: "The password for vsphere" option :vsphere_host, long: "--vshost HOST", description: "The vsphere host" option :vsphere_dc, short: "-D DATACENTER", long: "--vsdc DATACENTER", description: "The Datacenter for vsphere" option :vsphere_path, long: "--vspath SOAP_PATH", description: "The vsphere SOAP endpoint path", default: "/sdk" option :vsphere_port, long: "--vsport PORT", description: "The VI SDK port number to use", default: "443" option :vsphere_nossl, long: "--vsnossl", description: "Disable SSL connectivity" option :vsphere_insecure, long: "--vsinsecure", description: "Disable SSL certificate verification" option :folder, short: "-f FOLDER", long: "--folder FOLDER", description: "The folder to get VMs from", default: "" option :proxy_host, long: "--proxyhost PROXY_HOSTNAME", description: "Proxy hostname" option :proxy_port, long: "--proxyport PROXY_PORT", description: "Proxy port" end
Public Instance Methods
choose_datastore(dstores, size)
click to toggle source
# File lib/chef/knife/helpers/base_vsphere_command.rb, line 249 def choose_datastore(dstores, size) vmdk_size_b = size.to_i * 1024 * 1024 * 1024 candidates = [] dstores.each do |store| avail = number_to_human_size(store.summary[:freeSpace]) cap = number_to_human_size(store.summary[:capacity]) puts "#{ui.color("Datastore", :cyan)}: #{store.name} (#{avail}(#{store.summary[:freeSpace]}) / #{cap})" # vm's can span multiple datastores, so instead of grabbing the first one # let's find the first datastore with the available space on a LUN the vm # is already using, or use a specified LUN (if given) next unless (store.summary[:freeSpace] - vmdk_size_b) > 0 # also let's not use more than 90% of total space to save room for snapshots. cap_remains = 100 * ((store.summary[:freeSpace].to_f - vmdk_size_b.to_f) / store.summary[:capacity].to_f) candidates.push(store) if cap_remains.to_i > 10 end if candidates.length > 0 vmdk_datastore = candidates[0] else puts "Insufficient space on all LUNs designated or assigned to the virtual machine. Please specify a new target." vmdk_datastore = nil end vmdk_datastore end
conn_opts()
click to toggle source
# File lib/chef/knife/helpers/base_vsphere_command.rb, line 106 def conn_opts { host: get_config(:vsphere_host), path: get_config(:vsphere_path), port: get_config(:vsphere_port), use_ssl: !get_config(:vsphere_nossl), user: get_config(:vsphere_user), password: password, insecure: get_config(:vsphere_insecure), proxyHost: get_config(:proxy_host), proxyPort: get_config(:proxy_port), } end
datacenter()
click to toggle source
# File lib/chef/knife/helpers/base_vsphere_command.rb, line 174 def datacenter dcname = get_config(:vsphere_dc) traverse_folders_for_dc(vim_connection.rootFolder, dcname) || abort("datacenter not found") end
fatal_exit(msg)
click to toggle source
# File lib/chef/knife/helpers/base_vsphere_command.rb, line 365 def fatal_exit(msg) ui.fatal(msg) exit 1 end
find_all_in_folder(folder, type)
click to toggle source
# File lib/chef/knife/helpers/base_vsphere_command.rb, line 334 def find_all_in_folder(folder, type) if folder.instance_of?(RbVmomi::VIM::ClusterComputeResource) || folder.instance_of?(RbVmomi::VIM::ComputeResource) folder = folder.resourcePool end if folder.instance_of?(RbVmomi::VIM::ResourcePool) folder.resourcePool.grep(type) elsif folder.instance_of?(RbVmomi::VIM::Folder) folder.childEntity.grep(type) else puts "Unknown type #{folder.class}, not enumerating" nil end end
find_datastore(dsName)
click to toggle source
# File lib/chef/knife/helpers/base_vsphere_command.rb, line 288 def find_datastore(dsName) dc = datacenter base_entity = dc.datastore base_entity.find { |f| f.info.name == dsName } || abort("no such datastore #{dsName}") end
find_datastorecluster(dsName, folder = nil)
click to toggle source
# File lib/chef/knife/helpers/base_vsphere_command.rb, line 294 def find_datastorecluster(dsName, folder = nil) unless folder dc = datacenter folder = dc.datastoreFolder end folder.childEntity.each do |child| if child.class.to_s == "Folder" ds = find_datastorecluster(dsName, child) return ds if ds elsif child.class.to_s == "StoragePod" && child.name == dsName return child end end nil end
find_datastores_regex(regex)
click to toggle source
# File lib/chef/knife/helpers/base_vsphere_command.rb, line 277 def find_datastores_regex(regex) stores = [] puts "Looking for all datastores that match /#{regex}/" dc = datacenter base_entity = dc.datastore base_entity.each do |ds| stores.push ds if ds.name =~ /#{regex}/ end stores end
find_device(vm, deviceName)
click to toggle source
# File lib/chef/knife/helpers/base_vsphere_command.rb, line 327 def find_device(vm, deviceName) vm.config.hardware.device.each do |device| return device if device.deviceInfo.label == deviceName end nil end
find_folder(folderName)
click to toggle source
# File lib/chef/knife/helpers/base_vsphere_command.rb, line 179 def find_folder(folderName) dc = datacenter base_entity = dc.vmFolder entity_array = folderName.split("/") entity_array.each do |entityArrItem| if entityArrItem != "" base_entity = base_entity.childEntity.grep(RbVmomi::VIM::Folder).find { |f| f.name == entityArrItem } || abort("no such folder #{folderName} while looking for #{entityArrItem}") end end base_entity end
find_in_folder(folder, type, name)
click to toggle source
# File lib/chef/knife/helpers/base_vsphere_command.rb, line 361 def find_in_folder(folder, type, name) folder.childEntity.grep(type).find { |o| o.name == name } end
find_network(networkName, dvswitch = nil)
click to toggle source
# File lib/chef/knife/helpers/base_vsphere_command.rb, line 192 def find_network(networkName, dvswitch = nil) dc = datacenter base_entity = dc.network networks = base_entity.select { |f| f.name == networkName } abort("no such network #{networkName}") if networks.empty? if dvswitch && dvswitch != "auto" return networks.find do |f| next unless f.respond_to?(:config) sw = f.config.distributedVirtualSwitch sw.uuid == dvswitch || sw.name == dvswitch end end networks.first end
find_pool(poolName)
click to toggle source
# File lib/chef/knife/helpers/base_vsphere_command.rb, line 224 def find_pool(poolName) dc = datacenter base_entity = dc.hostFolder entity_array = poolName.split("/") entity_array.each do |entityArrItem| next if entityArrItem == "" if base_entity.is_a? RbVmomi::VIM::Folder base_entity = base_entity.childEntity.find { |f| f.name == entityArrItem } || abort("no such pool #{poolName} while looking for #{entityArrItem}") elsif base_entity.is_a?(RbVmomi::VIM::ClusterComputeResource) || base_entity.is_a?(RbVmomi::VIM::ComputeResource) base_entity = base_entity.resourcePool.resourcePool.find { |f| f.name == entityArrItem } || abort("no such pool #{poolName} while looking for #{entityArrItem}") elsif base_entity.is_a? RbVmomi::VIM::ResourcePool base_entity = base_entity.resourcePool.find { |f| f.name == entityArrItem } || abort("no such pool #{poolName} while looking for #{entityArrItem}") else abort "Unexpected Object type encountered #{base_entity.type} while finding resourcePool" end end base_entity = base_entity.resourcePool if !base_entity.is_a?(RbVmomi::VIM::ResourcePool) && base_entity.respond_to?(:resourcePool) base_entity end
find_pool_folder(folderName)
click to toggle source
# File lib/chef/knife/helpers/base_vsphere_command.rb, line 211 def find_pool_folder(folderName) dc = datacenter base_entity = dc.hostFolder entity_array = folderName.split("/") entity_array.each do |entityArrItem| if entityArrItem != "" base_entity = base_entity.childEntity.grep(RbVmomi::VIM::ManagedObject).find { |f| f.name == entityArrItem } || abort("no such folder #{folderName} while looking for #{entityArrItem}") end end base_entity end
find_pools_and_clusters(folder, poolname = nil)
click to toggle source
# File lib/chef/knife/helpers/base_vsphere_command.rb, line 167 def find_pools_and_clusters(folder, poolname = nil) pools = traverse_folders_for_pools(folder) clusters = traverse_folders_for_computeresources(folder) cluster_pool = clusters + pools poolname.nil? ? cluster_pool : cluster_pool.select { |p| p.name == poolname } end
get_config(key)
click to toggle source
# File lib/chef/knife/helpers/base_vsphere_command.rb, line 87 def get_config(key) key = key.to_sym rval = config[key].nil? ? Chef::Config[:knife][key] : config[key] Chef::Log.debug("value for config item #{key}: #{rval}") rval end
get_password_from_stdin()
click to toggle source
# File lib/chef/knife/helpers/base_vsphere_command.rb, line 124 def get_password_from_stdin @password ||= ui.ask("Enter your password: ") { |q| q.echo(false) } end
get_path_to_object(object)
click to toggle source
# File lib/chef/knife/helpers/base_vsphere_command.rb, line 348 def get_path_to_object(object) if object.is_a?(RbVmomi::VIM:: ManagedEntity) if object.parent.is_a?(RbVmomi::VIM:: ManagedEntity) get_path_to_object(object.parent) + "/" + object.parent.name else "" end else puts "Unknown type #{object.class}, not enumerating" nil end end
linux?(config)
click to toggle source
# File lib/chef/knife/helpers/base_vsphere_command.rb, line 408 def linux?(config) gid = config.guestId.downcase # This makes the assumption that if it isn't mac or windows it's linux # See https://www.vmware.com/support/developer/vc-sdk/visdk25pubs/ReferenceGuide/vim.vm.GuestOsDescriptor.GuestOsIdentifier.html for values is_linux_bool = !gid.include?("windows") && !gid.include?("darwin") Chef::Log.debug("Identified os as linux.") if is_linux_bool is_linux_bool end
number_to_human_size(number)
click to toggle source
# File lib/chef/knife/helpers/base_vsphere_command.rb, line 310 def number_to_human_size(number) number = number.to_f storage_units_fmt = %w{byte kB MB GB TB} base = 1024 if number.to_i < base unit = storage_units_fmt[0] else max_exp = storage_units_fmt.size - 1 exponent = (Math.log(number) / Math.log(base)).to_i # Convert to base exponent = max_exp if exponent > max_exp # we need this to avoid overflow for the highest unit number /= base**exponent unit = storage_units_fmt[exponent] end format("%0.2f %s", number, unit) end
password()
click to toggle source
# File lib/chef/knife/helpers/base_vsphere_command.rb, line 94 def password if !get_config(:vsphere_pass) # Password is not in the config file - grab it # from the command line get_password_from_stdin elsif get_config(:vsphere_pass).start_with?("base64:") Base64.decode64(get_config(:vsphere_pass)[7..-1]).chomp else get_config(:vsphere_pass) end end
tcp_test_port(hostname, port)
click to toggle source
# File lib/chef/knife/helpers/base_vsphere_command.rb, line 379 def tcp_test_port(hostname, port) tcp_socket = TCPSocket.new(hostname, port) readable = IO.select([tcp_socket], nil, nil, 5) if readable Chef::Log.debug("sshd accepting connections on #{hostname}, banner is #{tcp_socket.gets}") if port == 22 true else false end rescue Errno::ETIMEDOUT false rescue Errno::EPERM false rescue Errno::ECONNREFUSED sleep 2 false rescue Errno::EHOSTUNREACH, Errno::ENETUNREACH sleep 2 false ensure tcp_socket && tcp_socket.close end
tcp_test_port_vm(vm, port)
click to toggle source
# File lib/chef/knife/helpers/base_vsphere_command.rb, line 370 def tcp_test_port_vm(vm, port) ip = vm.guest.ipAddress if ip.nil? sleep 2 return false end tcp_test_port(ip, port) end
traverse_folders_for_computeresources(folder)
click to toggle source
# File lib/chef/knife/helpers/base_vsphere_command.rb, line 141 def traverse_folders_for_computeresources(folder) retval = [] children = folder.children.find_all children.each do |child| if child.class == RbVmomi::VIM::ComputeResource || child.class == RbVmomi::VIM::ClusterComputeResource retval << child elsif child.class == RbVmomi::VIM::Folder retval.concat(traverse_folders_for_computeresources(child)) end end retval end
traverse_folders_for_dc(folder, dcname)
click to toggle source
# File lib/chef/knife/helpers/base_vsphere_command.rb, line 154 def traverse_folders_for_dc(folder, dcname) children = folder.children.find_all children.each do |child| if child.class == RbVmomi::VIM::Datacenter && child.name == dcname return child elsif child.class == RbVmomi::VIM::Folder dc = traverse_folders_for_dc(child, dcname) return dc if dc end end false end
traverse_folders_for_pools(folder)
click to toggle source
# File lib/chef/knife/helpers/base_vsphere_command.rb, line 128 def traverse_folders_for_pools(folder) retval = [] children = folder.children.find_all children.each do |child| if child.class == RbVmomi::VIM::ResourcePool retval << child elsif child.class == RbVmomi::VIM::Folder retval.concat(traverse_folders_for_pools(child)) end end retval end
vim_connection()
click to toggle source
# File lib/chef/knife/helpers/base_vsphere_command.rb, line 120 def vim_connection config[:vim] ||= RbVmomi::VIM.connect conn_opts end
windows?(config)
click to toggle source
# File lib/chef/knife/helpers/base_vsphere_command.rb, line 402 def windows?(config) is_win_bool = config.guestId.downcase.include?("windows") Chef::Log.debug("Identified os as windows.") if is_win_bool is_win_bool end