class Chef::Knife::VsphereVmClone

VsphereVmClone extends the BaseVspherecommand

Attributes

host_descriptor[RW]
server_name[RW]

Public Instance Methods

all_the_hosts() click to toggle source
# File lib/chef/knife/vsphere_vm_clone.rb, line 476
def all_the_hosts
  hosts = traverse_folders_for_computeresources(datacenter.hostFolder)
  all_hosts = []
  hosts.each do |host|
    if host.is_a? RbVmomi::VIM::ClusterComputeResource
      all_hosts.concat(host.host)
    else
      all_hosts.push host
    end
  end
  all_hosts
end
create_delta_disk(src_vm) click to toggle source
# File lib/chef/knife/vsphere_vm_clone.rb, line 423
def create_delta_disk(src_vm)
  disks = src_vm.config.hardware.device.grep(RbVmomi::VIM::VirtualDisk)
  disks.select { |disk| disk.backing.parent.nil? }.each do |disk|
    spec = {
      deviceChange: [
        {
          operation: :remove,
          device: disk,
        },
        {
          operation: :add,
          fileOperation: :create,
          device: disk.dup.tap do |new_disk|
            new_disk.backing = new_disk.backing.dup
            new_disk.backing.fileName = "[#{disk.backing.datastore.name}]"
            new_disk.backing.parent = disk.backing
          end,
        },
      ],
    }
    src_vm.ReconfigVM_Task(spec: spec).wait_for_completion
  end
end
customization_plugin() click to toggle source

Loads the customization plugin if one was specified @return [KnifeVspherePlugin] the loaded and initialized plugin or nil

# File lib/chef/knife/vsphere_vm_clone.rb, line 698
def customization_plugin
  if @customization_plugin.nil?
    cplugin_path = get_config(:customization_plugin)
    if cplugin_path
      if File.exist? cplugin_path
        require cplugin_path
      else
        abort "Customization plugin could not be found at #{cplugin_path}"
      end

      if Object.const_defined? "KnifeVspherePlugin"
        @customization_plugin = Object.const_get("KnifeVspherePlugin").new
        cplugin_data = get_config(:customization_plugin_data)
        if cplugin_data
          if @customization_plugin.respond_to?(:data=)
            @customization_plugin.data = cplugin_data
          else
            abort "Customization plugin has no :data= accessor to receive the --cplugin-data argument. Define both or neither."
          end
        end
      else
        abort "KnifeVspherePlugin class is not defined in #{cplugin_path}"
      end
    end
  end

  @customization_plugin
end
find_available_hosts() click to toggle source
# File lib/chef/knife/vsphere_vm_clone.rb, line 447
def find_available_hosts
  hosts = traverse_folders_for_computeresources(datacenter.hostFolder)
  fatal_exit("No ComputeResource found - Use --resource-pool to specify a resource pool or a cluster") if hosts.empty?
  hosts.reject!(&:nil?)
  hosts.reject! { |host| host.host.all? { |h| h.runtime.inMaintenanceMode } }
  fatal_exit "All hosts in maintenance mode!" if hosts.empty?
  if get_config(:datastore)
    hosts.reject! { |host| !host.datastore.include?(find_datastore(get_config(:datastore))) }
  end

  fatal_exit "No hosts have the requested Datastore available! #{get_config(:datastore)}" if hosts.empty?

  if get_config(:datastorecluster)
    hosts.reject! { |host| !host.datastore.include?(find_datastorecluster(get_config(:datastorecluster))) }
  end

  fatal_exit "No hosts have the requested DatastoreCluster available! #{get_config(:datastorecluster)}" if hosts.empty?

  if get_config(:customization_vlan)
    vlan_list = get_config(:customization_vlan).split(",")
    vlan_list.each do |network|
      hosts.reject! { |host| !host.network.include?(find_network(network)) }
    end
  end

  fatal_exit "No hosts have the requested Network available! #{get_config(:customization_vlan)}" if hosts.empty?
  hosts
end
find_customization(name) click to toggle source

Retrieves a CustomizationSpecItem that matches the supplied name @param name [String] name of customization @return [RbVmomi::VIM::CustomizationSpecItem]

# File lib/chef/knife/vsphere_vm_clone.rb, line 730
def find_customization(name)
  csm = vim_connection.serviceContent.customizationSpecManager
  csm.GetCustomizationSpec(name: name)
end
find_host(host_name) click to toggle source
# File lib/chef/knife/vsphere_vm_clone.rb, line 489
def find_host(host_name)
  host = all_the_hosts.find { |host| host.name == host_name }
  raise "Can't find #{host_name}. I found #{all_the_hosts.map(&:name)}" unless host

  host
end
generate_adapter_map(ip = nil, gw = nil, mac = nil) click to toggle source

Generates a CustomizationAdapterMapping (currently only single IPv4 address) object @param ip [String] Any static IP address to use, or “dhcp” for DHCP @param gw [String] If static, the gateway for the interface, otherwise network address + 1 will be used @return [RbVmomi::VIM::CustomizationIPSettings]

# File lib/chef/knife/vsphere_vm_clone.rb, line 739
def generate_adapter_map(ip = nil, gw = nil, mac = nil)
  settings = RbVmomi::VIM.CustomizationIPSettings

  if ip.nil? || ip.casecmp("dhcp") == 0
    settings.ip = RbVmomi::VIM::CustomizationDhcpIpGenerator.new
  else
    cidr_ip = NetAddr::CIDR.create(ip)
    settings.ip = RbVmomi::VIM::CustomizationFixedIp(ipAddress: cidr_ip.ip)
    settings.subnetMask = cidr_ip.netmask_ext

    # TODO: want to confirm gw/ip are in same subnet?
    # Only set gateway on first IP.
    if config[:customization_ips].split(",").first == ip
      if gw.nil?
        settings.gateway = [cidr_ip.network(Objectify: true).next_ip]
      else
        gw_cidr = NetAddr::CIDR.create(gw)
        settings.gateway = [gw_cidr.ip]
      end
    end
  end

  adapter_map = RbVmomi::VIM.CustomizationAdapterMapping
  adapter_map.macAddress = mac if !mac.nil? && (mac != AUTO_MAC)
  adapter_map.adapter = settings
  adapter_map
end
generate_clone_spec(src_config) click to toggle source

Builds a CloneSpec

# File lib/chef/knife/vsphere_vm_clone.rb, line 497
def generate_clone_spec(src_config)
  rspec = RbVmomi::VIM.VirtualMachineRelocateSpec

  case
  when get_config(:host)
    rspec.host = find_host(get_config(:host))
    hosts = find_available_hosts
    rspec.pool = hosts.first.resourcePool
  when get_config(:resource_pool)
    rspec.pool = find_pool(get_config(:resource_pool))
  else
    hosts = find_available_hosts
    rspec.pool = hosts.first.resourcePool
  end

  rspec.diskMoveType = :moveChildMostDiskBacking if get_config(:linked_clone)

  if get_config(:datastore)
    rspec.datastore = find_datastore(get_config(:datastore))
  end

  if get_config(:datastorecluster)
    dsc = find_datastorecluster(get_config(:datastorecluster))

    dsc.childEntity.each do |store|
      if rspec.datastore.nil? || rspec.datastore.summary[:freeSpace] < store.summary[:freeSpace]
        rspec.datastore = store
      end
    end
  end

  rspec.transform = :sparse if get_config(:thin_provision)

  is_template = !get_config(:mark_as_template).nil?
  clone_spec = RbVmomi::VIM.VirtualMachineCloneSpec(location: rspec, powerOn: false, template: is_template)

  clone_spec.config = RbVmomi::VIM.VirtualMachineConfigSpec(deviceChange: [])

  if get_config(:annotation)
    clone_spec.config.annotation = get_config(:annotation)
  end

  if get_config(:customization_cpucount)
    clone_spec.config.numCPUs = get_config(:customization_cpucount)
  end

  if get_config(:customization_corespersocket)
    clone_spec.config.numCoresPerSocket = get_config(:customization_corespersocket)
  end

  if get_config(:customization_memory)
    clone_spec.config.memoryMB = Integer(get_config(:customization_memory)) * 1024
  end

  if get_config(:customization_memory_reservation)
    clone_spec.config.memoryAllocation = RbVmomi::VIM.ResourceAllocationInfo reservation: Integer(Float(get_config(:customization_memory_reservation)) * 1024)
  end

  mac_list = if get_config(:customization_macs) == AUTO_MAC
               [AUTO_MAC] * get_config(:customization_ips).split(",").length
             else
               get_config(:customization_macs).split(",")
             end

  if get_config(:customization_sw_uuid)
    unless get_config(:customization_vlan)
      abort("Must specify VLANs with --cvlan when specifying switch UUIDs with --sw-uuids")
    end
    swuuid_list = if get_config(:customization_sw_uuid) == "auto"
                    ["auto"] * get_config(:customization_ips).split(",").length
                  else
                    get_config(:customization_sw_uuid).split(",").map { |swuuid| swuuid.gsub(/((\w+\s+){7})(\w+)\s+(.+)/, '\1\3-\4') }
                  end
  end

  if get_config(:customization_vlan)
    vlan_list = get_config(:customization_vlan).split(",")
    sw_uuid   = get_config(:customization_sw_uuid)
    networks  = vlan_list.map { |vlan| find_network(vlan, sw_uuid) }

    cards = src_config.hardware.device.grep(RbVmomi::VIM::VirtualEthernetCard)

    networks.each_with_index do |network, index|
      card = cards[index] || abort("Can't find source network card to customize for vlan #{vlan_list[index]}")
      begin
        if get_config(:customization_sw_uuid) && (swuuid_list[index] != "auto")
          switch_port = RbVmomi::VIM.DistributedVirtualSwitchPortConnection(
            switchUuid: swuuid_list[index], portgroupKey: network.key
          )
        else
          switch_port = RbVmomi::VIM.DistributedVirtualSwitchPortConnection(
            switchUuid: network.config.distributedVirtualSwitch.uuid, portgroupKey: network.key
          )
        end
        card.backing.port = switch_port
      rescue
        # not connected to a distibuted switch?
        card.backing = RbVmomi::VIM::VirtualEthernetCardNetworkBackingInfo(network: network, deviceName: network.name)
      end
      card.macAddress = mac_list[index] if get_config(:customization_macs) && mac_list[index] != AUTO_MAC
      dev_spec = RbVmomi::VIM.VirtualDeviceConfigSpec(device: card, operation: "edit")
      clone_spec.config.deviceChange.push dev_spec
    end
  end

  cust_spec = if get_config(:customization_spec)
                csi = find_customization(get_config(:customization_spec)) ||
                  fatal_exit("failed to find customization specification named #{get_config(:customization_spec)}")

                csi.spec
              else
                global_ipset = RbVmomi::VIM.CustomizationGlobalIPSettings
                identity_settings = RbVmomi::VIM.CustomizationIdentitySettings
                RbVmomi::VIM.CustomizationSpec(globalIPSettings: global_ipset, identity: identity_settings)
              end

  if get_config(:disable_customization)
    clone_spec.customization = get_config(:customization_spec) ? cust_spec : nil
    return clone_spec
  end

  if get_config(:customization_dns_ips)
    cust_spec.globalIPSettings.dnsServerList = get_config(:customization_dns_ips).split(",")
  end

  if get_config(:customization_dns_suffixes)
    cust_spec.globalIPSettings.dnsSuffixList = get_config(:customization_dns_suffixes).split(",")
  end

  if config[:customization_ips] != NO_IPS
    cust_spec.nicSettingMap = config[:customization_ips].split(",").map.with_index { |cust_ip, index|
      generate_adapter_map(cust_ip, get_config(:customization_gw), mac_list[index])
    }
  end

  # TODO: why does the domain matter?
  use_ident = config[:customization_hostname] || get_config(:customization_domain) || cust_spec.identity.props.empty?

  # TODO: How could we not take this? Only if the identity were empty, but that's statically defined as empty above
  if use_ident
    hostname = config[:customization_hostname] || vmname

    if windows?(src_config)
      # We should get here with the customizations set, either by a plugin or a --cspec
      fatal_exit "Windows clones need a customization identity. Try passing a --cspec or making a --cplugin" if cust_spec.identity.props.empty?

      identification = identification_for_spec(cust_spec)

      if cust_spec.identity.licenseFilePrintData
        license_file_print_data = RbVmomi::VIM.CustomizationLicenseFilePrintData(
          autoMode: cust_spec.identity.licenseFilePrintData.autoMode
        )
      end # optional param

      user_data = RbVmomi::VIM.CustomizationUserData(
        fullName: cust_spec.identity.userData.fullName,
        orgName: cust_spec.identity.userData.orgName,
        productId: cust_spec.identity.userData.productId,
        computerName: RbVmomi::VIM.CustomizationFixedName(name: hostname)
      )

      gui_unattended = RbVmomi::VIM.CustomizationGuiUnattended(
        autoLogon: cust_spec.identity.guiUnattended.autoLogon,
        autoLogonCount: cust_spec.identity.guiUnattended.autoLogonCount,
        password: RbVmomi::VIM.CustomizationPassword(
          plainText: cust_spec.identity.guiUnattended.password.plainText,
          value: cust_spec.identity.guiUnattended.password.value
        ),
        timeZone: cust_spec.identity.guiUnattended.timeZone
      )
      runonce = RbVmomi::VIM.CustomizationGuiRunOnce(
        commandList: ["cust_spec.identity.guiUnattended.commandList"]
      )
      ident = RbVmomi::VIM.CustomizationSysprep
      ident.guiRunOnce = runonce
      ident.guiUnattended = gui_unattended
      ident.identification = identification
      ident.licenseFilePrintData = license_file_print_data
      ident.userData = user_data
      cust_spec.identity = ident
    elsif linux?(src_config)
      ident = RbVmomi::VIM.CustomizationLinuxPrep
      ident.hostName = RbVmomi::VIM.CustomizationFixedName(name: hostname)

      ident.domain = (get_config(:customization_domain) || "")
      cust_spec.identity = ident
    else
      ui.error("Customization only supports Linux and Windows currently.")
      exit 1
    end
  end
  clone_spec.customization = cust_spec

  if customization_plugin && customization_plugin.respond_to?(:customize_clone_spec)
    clone_spec = customization_plugin.customize_clone_spec(src_config, clone_spec)
  end
  clone_spec
end
guest_address(vm) click to toggle source
# File lib/chef/knife/vsphere_vm_clone.rb, line 384
def guest_address(vm)
  puts "Waiting for network interfaces to become available..."
  sleep 2 while vm.guest.net.empty? || !vm.guest.ipAddress
  ui.info "Found address #{vm.guest.ipAddress}" if log_verbose?
  config[:fqdn] = if config[:bootstrap_ipv4]
                    ipv4_address(vm)
                  elsif config[:fqdn]
                    get_config(:fqdn)
                  else
                    # Use the first IP which is not a link-local address.
                    # This is the closest thing to vm.guest.ipAddress but
                    # allows specifying a NIC.
                    vm.guest.net[bootstrap_nic_index].ipConfig.ipAddress.detect do |addr|
                      addr.origin != "linklayer"
                    end.ipAddress
                  end
end
ipv4_address(vm) click to toggle source
# File lib/chef/knife/vsphere_vm_clone.rb, line 370
def ipv4_address(vm)
  puts "Waiting for a valid IPv4 address..."
  # Multiple reboots occur during guest customization in which a link-local
  # address is assigned. As such, we need to wait until a routable IP address
  # becomes available. This is most commonly an issue with Windows instances.
  sleep 2 while vm_is_waiting_for_ip?(vm)
  vm.guest.net[bootstrap_nic_index].ipAddress.detect { |addr| IPAddr.new(addr).ipv4? }
end
plugin_create_instance!() click to toggle source

Create the server that we will bootstrap, if necessary

Plugins that subclass bootstrap, e.g. knife-ec2, can use this method to call out to an API to build an instance of the server we wish to bootstrap

@return [TrueClass] If instance successfully created, or exits

# File lib/chef/knife/vsphere_vm_clone.rb, line 274
def plugin_create_instance!
  config[:chef_node_name] = vmname unless get_config(:chef_node_name)

  vim = vim_connection
  vim.serviceContent.virtualDiskManager

  dc = datacenter

  src_vm = get_vm_by_name(get_config(:source_vm), get_config(:folder)) || fatal_exit("Could not find template #{get_config(:source_vm)}")

  create_delta_disk(src_vm) if get_config(:linked_clone)

  clone_spec = generate_clone_spec(src_vm.config)

  cust_folder = config[:dest_folder] || get_config(:folder)

  dest_folder = cust_folder.nil? ? src_vm.vmFolder : find_folder(cust_folder)

  task = src_vm.CloneVM_Task(folder: dest_folder, name: vmname, spec: clone_spec)
  puts "Cloning template #{get_config(:source_vm)} to new VM #{vmname}"

  pp clone_spec if log_verbose?

  begin
    task.wait_for_completion
  rescue RbVmomi::Fault => e
    fault = e.fault
    if fault.class == RbVmomi::VIM::NicSettingMismatch
      abort "There is a mismatch in the number of NICs on the template (#{fault.numberOfNicsInVM}) and what you've passed on the command line with --cips (#{fault.numberOfNicsInSpec}). The VM has been cloned but not customized."
    elsif fault.class == RbVmomi::VIM::DuplicateName
      ui.info "VM already exists, proceeding to bootstrap"
    else
      raise e
    end
  end

  puts "Finished creating virtual machine #{vmname}"

  if customization_plugin && customization_plugin.respond_to?(:reconfig_vm)
    target_vm = find_in_folder(dest_folder, RbVmomi::VIM::VirtualMachine, vmname) || abort("VM could not be found in #{dest_folder}")
    customization_plugin.reconfig_vm(target_vm)
  end

  return if get_config(:mark_as_template)

  if get_config(:power) || get_config(:bootstrap)
    vm = get_vm_by_name(vmname, cust_folder) || fatal_exit("VM #{vmname} not found")
    begin
      vm.PowerOnVM_Task.wait_for_completion
    rescue RbVmomi::Fault => e
      raise e unless e.fault.class == RbVmomi::VIM::InvalidPowerState # Ignore if it's already turned on
    end
    puts "Powered on virtual machine #{vmname}"
  end
  return unless get_config(:bootstrap)

  protocol = get_config(:bootstrap_protocol)
  if windows?(src_vm.config)
    protocol ||= "winrm"
    connect_port ||= 5985
    unless config[:disable_customization]
      # Wait for customization to complete
      puts "Waiting for customization to complete..."
      CustomizationHelper.wait_for_sysprep(vm, vim, Integer(get_config(:sysprep_timeout)), 10)
      puts "Customization Complete"
    end
    connect_host = guest_address(vm)
    self.server_name = connect_host
    Chef::Log.debug("Connect Host for winrm Bootstrap: #{connect_host}")
    wait_for_access(connect_host, connect_port, protocol)
  else
    connect_host = guest_address(vm)
    self.server_name = connect_host
    connect_port ||= 22
    Chef::Log.debug("Connect Host for SSH Bootstrap: #{connect_host}")
    protocol ||= "ssh"
    wait_for_access(connect_host, connect_port, protocol)
  end
end
plugin_finalize() click to toggle source

Perform any teardown or cleanup necessary by the plugin

Plugins that subclass bootstrap, e.g. knife-ec2, can use this method to display a message or perform any cleanup

@return [void]

# File lib/chef/knife/vsphere_vm_clone.rb, line 366
def plugin_finalize; end
plugin_setup!() click to toggle source

Perform any setup necessary by the plugin

Plugins that subclass bootstrap, e.g. knife-ec2, can use this method to create connection objects

@return [TrueClass] If instance successfully created, or exits

# File lib/chef/knife/vsphere_vm_clone.rb, line 359
def plugin_setup!; end
plugin_validate_options!() click to toggle source

@return [TrueClass] If options are valid or exits

# File lib/chef/knife/vsphere_vm_clone.rb, line 248
def plugin_validate_options!
  unless using_supplied_hostname? ^ using_random_hostname?
    show_usage
    fatal_exit("You must specify a virtual machine name OR use --random-vmname")
  end

  abort "--template or knife[:source_vm] must be specified" unless config[:source_vm]

  if get_config(:datastore) && get_config(:datastorecluster)
    abort "Please select either datastore or datastorecluster"
  end

  if get_config(:customization_macs) != AUTO_MAC && get_config(:customization_ips) == NO_IPS
    abort('Must specify IP numbers with --cips when specifying MAC addresses with --cmacs, can use "dhcp" as placeholder')
  end
end
run() click to toggle source
# File lib/chef/knife/vsphere_vm_clone.rb, line 217
def run
  check_license

  plugin_setup!
  validate_name_args!
  validate_protocol!
  validate_first_boot_attributes!
  validate_winrm_transport_opts!
  validate_policy_options!
  plugin_validate_options!

  winrm_warn_no_ssl_verification
  warn_on_short_session_timeout

  plugin_create_instance!

  return unless get_config(:bootstrap)

  $stdout.sync = true
  connect!
  register_client

  content = render_template
  bootstrap_path = upload_bootstrap(content)
  perform_bootstrap(bootstrap_path)
  plugin_finalize
ensure
  connection.del_file!(bootstrap_path) if connection && bootstrap_path
end
tcp_test_ssh(hostname, connection_port) { || ... } click to toggle source
# File lib/chef/knife/vsphere_vm_clone.rb, line 767
def tcp_test_ssh(hostname, connection_port)
  tcp_socket = TCPSocket.new(hostname, connection_port)
  readable = IO.select([tcp_socket], nil, nil, 5)
  if readable
    ssh_banner = tcp_socket.gets
    if ssh_banner.nil? || ssh_banner.empty?
      false
    else
      Chef::Log.debug("sshd accepting connections on #{hostname}, banner is #{ssh_banner}")
      yield
      true
    end
  else
    false
  end
rescue SocketError, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ENETUNREACH, IOError
  Chef::Log.debug("ssh failed to connect: #{hostname}")
  sleep 2
  false
rescue Errno::EPERM, Errno::ETIMEDOUT
  Chef::Log.debug("ssh timed out: #{hostname}")
  false
rescue Errno::ECONNRESET
  Chef::Log.debug("ssh reset its connection: #{hostname}")
  sleep 2
  false
ensure
  tcp_socket && tcp_socket.close
end
tcp_test_winrm(hostname, port) { || ... } click to toggle source
# File lib/chef/knife/vsphere_vm_clone.rb, line 797
def tcp_test_winrm(hostname, port)
  tcp_socket = TCPSocket.new(hostname, port)
  yield
  true
rescue SocketError
  sleep 2
  false
rescue Errno::ETIMEDOUT
  false
rescue Errno::EPERM
  false
rescue Errno::ECONNREFUSED
  sleep 2
  false
rescue Errno::EHOSTUNREACH
  sleep 2
  false
rescue Errno::ENETUNREACH
  sleep 2
  false
ensure
  tcp_socket && tcp_socket.close
end
validate_name_args!() click to toggle source
# File lib/chef/knife/vsphere_vm_clone.rb, line 368
def validate_name_args!; end
vm_is_waiting_for_ip?(vm) click to toggle source
# File lib/chef/knife/vsphere_vm_clone.rb, line 379
def vm_is_waiting_for_ip?(vm)
  first_ip_address = vm.guest.net[bootstrap_nic_index].ipConfig.ipAddress.detect { |addr| IPAddr.new(addr.ipAddress).ipv4? }
  first_ip_address.nil? || first_ip_address.origin == ORIGIN_IS_REAL_NIC
end
wait_for_access(connect_host, connect_port, protocol) click to toggle source
# File lib/chef/knife/vsphere_vm_clone.rb, line 402
def wait_for_access(connect_host, connect_port, protocol)
  if winrm?
    if get_config(:winrm_ssl) && get_config(:connection_port) == "5985"
      config[:connection_port] = "5986"
    end
    connect_port = get_config(:connection_port)
    print "\n#{ui.color("Waiting for winrm access to become available on #{connect_host}:#{connect_port}", :magenta)}"
    print(".") until tcp_test_winrm(connect_host, connect_port) do
      sleep 10
      puts("done")
    end
  else
    print "\n#{ui.color("Waiting for sshd access to become available on #{connect_host}:#{connect_port}", :magenta)}"
    print(".") until tcp_test_ssh(connect_host, connect_port) do
      sleep 10
      puts("done")
    end
  end
  connect_port
end

Private Instance Methods

bootstrap_nic_index() click to toggle source
# File lib/chef/knife/vsphere_vm_clone.rb, line 843
def bootstrap_nic_index
  Integer(get_config(:bootstrap_nic))
end
identification_for_spec(cust_spec) click to toggle source
# File lib/chef/knife/vsphere_vm_clone.rb, line 847
def identification_for_spec(cust_spec)
  # If --cdomain matches what is in --cspec then use identification from the --cspec, else use --cdomain
  case domain = get_config(:customization_domain)
  when nil?
    # Fall back to original behavior of using joinWorkgroup from the --cspec
    RbVmomi::VIM.CustomizationIdentification(
      joinWorkgroup: cust_spec.identity.identification.joinWorkgroup
    )
  when cust_spec.identity.identification.joinDomain
    cust_spec.identity.identification
  else
    RbVmomi::VIM.CustomizationIdentification(
      joinDomain: domain
    )
  end
end
random_hostname() click to toggle source
# File lib/chef/knife/vsphere_vm_clone.rb, line 839
def random_hostname
  @random_hostname ||= config[:random_vmname_prefix] + SecureRandom.hex(4)
end
supplied_hostname() click to toggle source
# File lib/chef/knife/vsphere_vm_clone.rb, line 835
def supplied_hostname
  @name_args[0]
end
using_random_hostname?() click to toggle source
# File lib/chef/knife/vsphere_vm_clone.rb, line 827
def using_random_hostname?
  config[:random_vmname]
end
using_supplied_hostname?() click to toggle source
# File lib/chef/knife/vsphere_vm_clone.rb, line 831
def using_supplied_hostname?
  !supplied_hostname.nil?
end
vmname() click to toggle source
# File lib/chef/knife/vsphere_vm_clone.rb, line 823
def vmname
  supplied_hostname || random_hostname
end