class Fog::Vsphere::Compute::Real

rubocop:disable ClassLength

Public Class Methods

new(options = {}) click to toggle source
# File lib/fog/vsphere/compute.rb, line 592
def initialize(options = {})
  require 'rbvmomi'
  @vsphere_username = options[:vsphere_username]
  @vsphere_password = options[:vsphere_password]
  @vsphere_server   = options[:vsphere_server]
  @vsphere_port     = options[:vsphere_port] || 443
  @vsphere_path     = options[:vsphere_path] || '/sdk'
  @vsphere_ns       = options[:vsphere_ns] || 'urn:vim25'
  @vsphere_rev      = options[:vsphere_rev] || '4.0'
  @vsphere_ssl      = options[:vsphere_ssl] || true
  @vsphere_debug    = options[:vsphere_debug] || false
  @vsphere_expected_pubkey_hash = options[:vsphere_expected_pubkey_hash]
  @vsphere_must_reauthenticate = false
  @vsphere_is_vcenter = nil
  @connection = nil
  connect
  negotiate_revision(options[:vsphere_rev])
  authenticate
end

Public Instance Methods

add_vm_cdrom(cdrom) click to toggle source
# File lib/fog/vsphere/requests/compute/modify_vm_cdrom.rb, line 5
def add_vm_cdrom(cdrom)
  vm_reconfig_hardware('instance_uuid' => cdrom.server.instance_uuid, 'hardware_spec' => { 'deviceChange' => [create_cdrom(cdrom, cdrom.unit_number, :add)] })
end
add_vm_controller(controller) click to toggle source
# File lib/fog/vsphere/requests/compute/modify_vm_controller.rb, line 5
def add_vm_controller(controller)
  vm_reconfig_hardware('instance_uuid' => controller.server_id, 'hardware_spec' => { 'deviceChange' => [create_controller(controller)] })
end
add_vm_interface(vmid, options = {}) click to toggle source
# File lib/fog/vsphere/requests/compute/modify_vm_interface.rb, line 5
def add_vm_interface(vmid, options = {})
  raise ArgumentError, 'instance id is a required parameter' unless vmid

  interface = get_interface_from_options(vmid, options.merge(server_id: vmid))
  vm_reconfig_hardware('instance_uuid' => vmid, 'hardware_spec' => { 'deviceChange' => [create_interface(interface, 0, :add, options)] })
end
add_vm_volume(volume) click to toggle source
# File lib/fog/vsphere/requests/compute/modify_vm_volume.rb, line 5
def add_vm_volume(volume)
  vm_reconfig_hardware('instance_uuid' => volume.server_id, 'hardware_spec' => { 'deviceChange' => [create_disk(volume, :add)] })
end
cloudinit_to_customspec(user_data) click to toggle source
# File lib/fog/vsphere/requests/compute/cloudinit_to_customspec.rb, line 5
def cloudinit_to_customspec(user_data)
  raise ArgumentError, "user_data can't be nil" if user_data.nil?
  custom_spec = { 'customization_spec' => {} }
  user_data = YAML.safe_load(user_data)
  # https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.Specification.html
  # encryptionKey expects an array
  # globalIPSettings expects a hash, REQUIRED
  # identity expects an hash, REQUIRED
  # nicSettingMap expects an array
  # options expects an hash
  # extraConfig expects a hash

  custom_spec['encryptionKey']    = user_data['encryptionKey'] if user_data.key?('encryptionKey')
  custom_spec['globalIPSettings'] = user_data['globalIPSettings'] if user_data.key?('globalIPSettings')
  custom_spec['identity']         = user_data['identity'] if user_data.key?('identity')
  custom_spec['identity']         = { 'Sysprep' => { 'guiRunOnce' => { 'commandList' => user_data['runcmd'] } } } if user_data.key?('runcmd') && !user_data.key?('identity')
  custom_spec['nicSettingMap']    = user_data['nicSettingMap'] if user_data.key?('nicSettingMap')
  custom_spec['options']          = user_data['options'] if user_data.key?('options')
  custom_spec['extraConfig']      = user_data['extraConfig'] if user_data.key?('extraConfig')

  # for backwards compatability
  # hostname expects a string, REQUIRED
  # netmask expects a string
  # dns expects an array
  # gateway expects an array
  # domain expects a string, REQUIRED
  # domainsuffixlist expects an array, REQUIRED
  # timezone expects a string, for example Europe/Copenhagen, REQUIRED
  custom_spec['hostname']                    =  user_data['hostname'] if user_data.key?('hostname')
  custom_spec['ipsettings']                  =  { 'ip' => user_data['ip'] } if user_data.key?('ip')
  custom_spec['ipsettings']['subnetMask']    =  user_data['netmask'] if user_data.key?('netmask')
  custom_spec['ipsettings']['dnsServerList'] =  user_data['dns'] if user_data.key?('dns')
  custom_spec['ipsettings']['gateway']       =  user_data['gateway'] if user_data.key?('gateway')
  custom_spec['domain']                      =  user_data['domain'] if user_data.key?('domain')
  custom_spec['dnsSuffixList']               =  user_data['domainsuffixlist'] if user_data.key?('domainsuffixlist')
  custom_spec['time_zone']                   =  user_data['timezone'] if user_data.key?('timezone')
  custom_spec
end
connection() click to toggle source
# File lib/fog/vsphere/compute.rb, line 612
def connection
  if @connection.nil? || @connection.serviceContent.sessionManager.currentSession.nil?
    Fog::Logger.debug('Reconnecting to vSphere.')
    @connection = nil
    reload
  end
  @connection
end
create_folder(datacenter, path, name) click to toggle source
# File lib/fog/vsphere/requests/compute/create_folder.rb, line 5
def create_folder(datacenter, path, name)
  # Path cannot be nil but it can be an empty string
  raise ArgumentError, 'Path cannot be nil' if path.nil?

  parent_folder = get_raw_vmfolder(path, datacenter)
  begin
    new_folder = parent_folder.CreateFolder(name: name)
    # output is cleaned up to return the new path
    # new path will be path/name, example: "Production/Pool1"
    new_folder.path.reject { |a| a.first.class == 'Folder' }.map { |a| a.first.name }.join('/').sub(/^\/?Datacenters\/#{datacenter}\/vm\/?/, '')
  end
end
create_group(attributes = {}) click to toggle source
# File lib/fog/vsphere/requests/compute/create_group.rb, line 5
def create_group(attributes = {})
  cluster = get_raw_cluster(attributes[:cluster], attributes[:datacenter])
  group = cluster.configurationEx.group.find { |n| n[:name] == attributes[:name] }
  if group
    raise ArgumentError, "Group #{attributes[:name]} already exists!"
  end
  spec = get_group_spec attributes
  cluster_spec = RbVmomi::VIM.ClusterConfigSpecEx(groupSpec: [
                                                    RbVmomi::VIM.ClusterGroupSpec(
                                                      operation: RbVmomi::VIM.ArrayUpdateOperation('add'),
                                                      info: spec
                                                    )
                                                  ])
  cluster.ReconfigureComputeResource_Task(spec: cluster_spec, modify: true).wait_for_completion
  group = cluster.configurationEx.group.find { |n| n[:name] == attributes[:name] }
  if group
    return group[:name]
  else
    raise Fog::Vsphere::Errors::ServiceError, "Unknown error creating group #{attributes[:name]}"
  end
end
create_rule(attributes = {}) click to toggle source
# File lib/fog/vsphere/requests/compute/create_rule.rb, line 5
def create_rule(attributes = {})
  cluster = get_raw_cluster(attributes[:cluster], attributes[:datacenter])
  rule = cluster.configurationEx.rule.find { |n| n[:name] == attributes[:name] }
  if rule
    raise ArgumentError, "Rule #{attributes[:name]} already exists!"
  end
  spec = get_rule_spec attributes
  # Now, attach it to the cluster
  cluster_spec = RbVmomi::VIM.ClusterConfigSpecEx(rulesSpec: [
                                                    RbVmomi::VIM.ClusterRuleSpec(
                                                      operation: RbVmomi::VIM.ArrayUpdateOperation('add'),
                                                      info: spec
                                                    )
                                                  ])
  ret = cluster.ReconfigureComputeResource_Task(spec: cluster_spec, modify: true).wait_for_completion
  rule = cluster.configurationEx.rule.find { |n| n[:name] == attributes[:name] }
  if rule
    return rule[:key]
  else
    raise Fog::Vsphere::Errors::ServiceError, "Unknown error creating rule #{attributes[:name]}"
  end
end
create_vm(attributes = {}) click to toggle source
# File lib/fog/vsphere/requests/compute/create_vm.rb, line 5
def create_vm(attributes = {})
  # build up vm configuration

  vm_cfg = {
    name: attributes[:name],
    annotation: attributes[:annotation],
    guestId: attributes[:guest_id],
    version: attributes[:hardware_version],
    files: { vmPathName: vm_path_name(attributes) },
    numCPUs: attributes[:cpus],
    numCoresPerSocket: attributes[:corespersocket],
    memoryMB: attributes[:memory_mb],
    deviceChange: device_change(attributes),
    extraConfig: extra_config(attributes)
  }
  vm_cfg[:cpuHotAddEnabled] = attributes[:cpuHotAddEnabled] if attributes.key?(:cpuHotAddEnabled)
  vm_cfg[:memoryHotAddEnabled] = attributes[:memoryHotAddEnabled] if attributes.key?(:memoryHotAddEnabled)
  vm_cfg[:firmware] = attributes[:firmware] if attributes.key?(:firmware)
  vm_cfg[:bootOptions] = boot_options(attributes, vm_cfg) if attributes.key?(:boot_order) || attributes.key?(:boot_retry)
  resource_pool = if attributes[:resource_pool] && attributes[:resource_pool] != 'Resources'
                    get_raw_resource_pool(attributes[:resource_pool], attributes[:cluster], attributes[:datacenter])
                  else
                    get_raw_cluster(attributes[:cluster], attributes[:datacenter]).resourcePool
                  end
  vmFolder      = get_raw_vmfolder(attributes[:path], attributes[:datacenter])
  host = if attributes.key?(:host)
           get_raw_host(attributes[:host], attributes[:cluster], attributes[:datacenter])
         end
  # if any volume has a storage_pod set, we deploy the vm on a storage pod instead of the defined datastores
  pod = get_storage_pod_from_volumes(attributes)
  vm = if pod
         create_vm_on_storage_pod(pod, vm_cfg, vmFolder, resource_pool, attributes[:datacenter], host)
       else
         create_vm_on_datastore(vm_cfg, vmFolder, resource_pool, host)
       end
  vm.config.instanceUuid
end
current_time() click to toggle source
# File lib/fog/vsphere/requests/compute/current_time.rb, line 5
def current_time
  current_time = connection.serviceInstance.CurrentTime
  { 'current_time' => current_time }
end
destroy_group(attributes = {}) click to toggle source
# File lib/fog/vsphere/requests/compute/destroy_group.rb, line 5
def destroy_group(attributes = {})
  cluster = get_raw_cluster(attributes[:cluster], attributes[:datacenter])
  group   = cluster.configurationEx.group.find { |g| g.name == attributes[:name] }
  raise Fog::Vsphere::Error::NotFound, "group #{attributes[:name]} not found" unless group
  delete_spec = RbVmomi::VIM.ClusterConfigSpecEx(groupSpec: [
                                                   RbVmomi::VIM.ClusterGroupSpec(
                                                     operation: RbVmomi::VIM.ArrayUpdateOperation('remove'),
                                                     removeKey: group.name
                                                   )
                                                 ])
  cluster.ReconfigureComputeResource_Task(spec: delete_spec, modify: true).wait_for_completion
end
destroy_rule(attributes = {}) click to toggle source
# File lib/fog/vsphere/requests/compute/destroy_rule.rb, line 5
def destroy_rule(attributes = {})
  cluster = get_raw_cluster(attributes[:cluster], attributes[:datacenter])
  rule    = cluster.configurationEx.rule.find { |rule| rule.key == attributes[:key] }
  raise Fog::Vsphere::Error::NotFound, "rule #{attributes[:key]} not found" unless rule
  delete_spec = RbVmomi::VIM.ClusterConfigSpecEx(rulesSpec: [
                                                   RbVmomi::VIM.ClusterRuleSpec(
                                                     operation: RbVmomi::VIM.ArrayUpdateOperation('remove'),
                                                     removeKey: rule.key
                                                   )
                                                 ])
  cluster.ReconfigureComputeResource_Task(spec: delete_spec, modify: true).wait_for_completion
end
destroy_vm_cdrom(cdrom) click to toggle source
# File lib/fog/vsphere/requests/compute/modify_vm_cdrom.rb, line 9
def destroy_vm_cdrom(cdrom)
  vm_reconfig_hardware('instance_uuid' => cdrom.server.instance_uuid, 'hardware_spec' => { 'deviceChange' => [create_cdrom(cdrom, cdrom.unit_number, :remove)] })
end
destroy_vm_interface(vmid, options = {}) click to toggle source
# File lib/fog/vsphere/requests/compute/modify_vm_interface.rb, line 12
def destroy_vm_interface(vmid, options = {})
  raise ArgumentError, 'instance id is a required parameter' unless vmid

  interface = get_interface_from_options(vmid, options.merge(server_id: vmid))
  vm_reconfig_hardware('instance_uuid' => vmid, 'hardware_spec' => { 'deviceChange' => [create_interface(interface, interface.key, :remove, options)] })
end
destroy_vm_volume(volume) click to toggle source
# File lib/fog/vsphere/requests/compute/modify_vm_volume.rb, line 13
def destroy_vm_volume(volume)
  vm_reconfig_hardware('instance_uuid' => volume.server_id, 'hardware_spec' => {
                         'deviceChange' => [create_disk(volume, :remove, file_operation: :destroy)]
                       })
end
folder_destroy(path, datacenter_name) click to toggle source
# File lib/fog/vsphere/requests/compute/folder_destroy.rb, line 5
def folder_destroy(path, datacenter_name)
  folder = get_raw_vmfolder(path, datacenter_name)
  raise Fog::Vsphere::Errors::NotFound, "No such folder #{path}" unless folder
  raise Fog::Vsphere::Errors::ServiceError, "Folder #{path} is not empty" unless folder.childEntity.empty?

  task = folder.Destroy_Task
  task.wait_for_completion
  { 'task_state' => task.info.state }
end
get_cluster(name, datacenter_name) click to toggle source
# File lib/fog/vsphere/requests/compute/get_cluster.rb, line 5
def get_cluster(name, datacenter_name)
  cluster = get_raw_cluster(name, datacenter_name)
  raise(Fog::Vsphere::Compute::NotFound) unless cluster
  cluster_attributes(cluster, datacenter_name)
end
get_compute_resource(name, datacenter_name) click to toggle source
# File lib/fog/vsphere/requests/compute/get_compute_resource.rb, line 5
def get_compute_resource(name, datacenter_name)
  compute_resource = get_raw_compute_resource(name, datacenter_name)
  raise(Fog::Vsphere::Compute::NotFound) unless compute_resource
  compute_resource_attributes(compute_resource, datacenter_name)
end
get_datacenter(name) click to toggle source
# File lib/fog/vsphere/requests/compute/get_datacenter.rb, line 5
def get_datacenter(name)
  dc = find_raw_datacenter(name)
  raise(Fog::Vsphere::Compute::NotFound) unless dc
  { name: dc.name, status: dc.overallStatus, path: raw_getpathmo(dc) }
end
get_datastore(name, datacenter_name) click to toggle source
# File lib/fog/vsphere/requests/compute/get_datastore.rb, line 5
def get_datastore(name, datacenter_name)
  datastore = list_datastores(datacenter: datacenter_name).detect { |ds| ds[:name] == name }
  raise(Fog::Vsphere::Compute::NotFound) unless datastore
  datastore
end
get_folder(path, datacenter_name, type = nil) click to toggle source
# File lib/fog/vsphere/requests/compute/get_folder.rb, line 5
def get_folder(path, datacenter_name, type = nil)
  type ||= 'vm'
  # Cycle through all types of folders.
  folder = get_raw_folder(path, datacenter_name, type)
  raise(Fog::Vsphere::Compute::NotFound) unless folder
  folder_attributes(folder, datacenter_name)
end
get_host(name, cluster_name, datacenter_name) click to toggle source
# File lib/fog/vsphere/requests/compute/get_host.rb, line 5
def get_host(name, cluster_name, datacenter_name)
  get_raw_host(name, cluster_name, datacenter_name)
end
get_interface_type(id, servertype, datacenter, _filter = {}) click to toggle source
# File lib/fog/vsphere/requests/compute/get_interface_type.rb, line 5
def get_interface_type(id, servertype, datacenter, _filter = {})
  interfacetype = list_interface_types(filters = { id: id,
                                                   datacenter: datacenter,
                                                   servertype: servertype.id }).first
  raise(Fog::Vsphere::Compute::NotFound) unless interfacetype
  interfacetype
end
get_network(name, datacenter_name) click to toggle source
# File lib/fog/vsphere/requests/compute/get_network.rb, line 5
def get_network(name, datacenter_name)
  network = get_raw_network(name, datacenter_name)
  raise(Fog::Vsphere::Compute::NotFound) unless network
  network_attributes(network, datacenter_name)
end
get_raw_interface(vm_id, options = {}) click to toggle source
# File lib/fog/vsphere/requests/compute/list_vm_interfaces.rb, line 44
def get_raw_interface(vm_id, options = {})
  raise ArgumentError, 'instance id is a required parameter' unless vm_id

  if options.is_a? Fog::Vsphere::Compute::Interface
    options

  else
    raise ArgumentError, "Either key or name is a required parameter. options: #{options}" unless options.key?(:key) || options.key?(:mac) || options.key?(:name)
    raise ArgumentError, "'datacenter' is a required parameter in options: #{options}" unless options.key?(:datacenter)

    get_raw_interfaces(vm_id, options[:datacenter]).find do |nic|
      (options.key?(:key) && (nic.key == options[:key].to_i)) ||
        (options.key?(:mac) && (nic.macAddress == options[:mac])) ||
        (options.key?(:name) && (nic.deviceInfo.label == options[:name]))
    end
  end
end
get_raw_interfaces(vm_id, datacenter = nil) click to toggle source
# File lib/fog/vsphere/requests/compute/list_vm_interfaces.rb, line 40
def get_raw_interfaces(vm_id, datacenter = nil)
  get_vm_ref(vm_id, datacenter).config.hardware.device.grep(RbVmomi::VIM::VirtualEthernetCard)
end
get_resource_pool(name, cluster_name, datacenter_name) click to toggle source
# File lib/fog/vsphere/requests/compute/get_resource_pool.rb, line 5
def get_resource_pool(name, cluster_name, datacenter_name)
  resource_pool = get_raw_resource_pool(name, cluster_name, datacenter_name)
  raise(Fog::Vsphere::Compute::NotFound) unless resource_pool
  resource_pool_attributes(resource_pool, cluster_name, datacenter_name)
end
get_server_type(id, datacenter, _filter = {}) click to toggle source
# File lib/fog/vsphere/requests/compute/get_server_type.rb, line 5
def get_server_type(id, datacenter, _filter = {})
  server_type = get_raw_server_type(id, datacenter)
  raise(Fog::Vsphere::Compute::NotFound) unless server_type
  server_type_attributes(server_type, datacenter)
end
get_storage_pod(name, datacenter_name) click to toggle source
# File lib/fog/vsphere/requests/compute/get_storage_pod.rb, line 5
def get_storage_pod(name, datacenter_name)
  storage_pod = list_storage_pods(datacenter: datacenter_name).detect { |pod| pod[:name] == name }
  raise(Fog::Vsphere::Compute::NotFound) unless storage_pod
  storage_pod
end
get_template(id, datacenter_name = nil) click to toggle source
# File lib/fog/vsphere/requests/compute/get_template.rb, line 5
def get_template(id, datacenter_name = nil)
  convert_vm_mob_ref_to_attr_hash(get_vm_ref(id, datacenter_name))
end
get_virtual_machine(id, datacenter_name = nil, folder = nil, recursive = false) click to toggle source
# File lib/fog/vsphere/requests/compute/get_virtual_machine.rb, line 5
def get_virtual_machine(id, datacenter_name = nil, folder = nil, recursive = false)
  # The larger the VM list the longer it will take if not searching based on UUID.
  convert_vm_mob_ref_to_attr_hash(get_vm_ref(id, datacenter_name, folder, recursive))
end
get_vm_cluster(vm_mob_ref) click to toggle source
# File lib/fog/vsphere/requests/compute/vm_relocate.rb, line 81
def get_vm_cluster(vm_mob_ref)
  parent = vm_mob_ref.runtime.host.parent
  until parent.is_a?(RbVmomi::VIM::ClusterComputeResource)
    if vm_mob_ref.respond_to?(:parent)
      parent = parent.parent
    else
      return
    end
  end
  parent.name
end
get_vm_datacenter(vm_mob_ref) click to toggle source
# File lib/fog/vsphere/requests/compute/vm_relocate.rb, line 69
def get_vm_datacenter(vm_mob_ref)
  parent = vm_mob_ref.parent
  until parent.is_a?(RbVmomi::VIM::Datacenter)
    if vm_mob_ref.respond_to?(:parent)
      parent = parent.parent
    else
      return
    end
  end
  parent.name
end
get_vm_first_scsi_controller(vm_id) click to toggle source
# File lib/fog/vsphere/requests/compute/get_vm_first_scsi_controller.rb, line 6
def get_vm_first_scsi_controller(vm_id)
  Fog::Vsphere::Compute::SCSIController.new(get_vm_first_scsi_controller_raw(vm_id))
end
get_vm_first_scsi_controller_raw(vm_id) click to toggle source
# File lib/fog/vsphere/requests/compute/get_vm_first_scsi_controller.rb, line 10
def get_vm_first_scsi_controller_raw(vm_id)
  ctrl = get_vm_ref(vm_id).config.hardware.device.grep(RbVmomi::VIM::VirtualSCSIController).select { |ctrl| ctrl.key == 1000 }.first
  {
    type: ctrl.class.to_s,
    shared_bus: ctrl.sharedBus.to_s,
    unit_number: ctrl.scsiCtlrUnitNumber,
    key: ctrl.key
  }
end
get_vm_interface(vm_id, options = {}) click to toggle source
# File lib/fog/vsphere/requests/compute/list_vm_interfaces.rb, line 35
def get_vm_interface(vm_id, options = {})
  raw = get_raw_interface(vm_id, options)
  raw_to_hash(raw) if raw
end
host_finish_maintenance(name, cluster_name, datacenter_name, timeout = 0) click to toggle source
# File lib/fog/vsphere/requests/compute/host_finish_maintenance.rb, line 5
def host_finish_maintenance(name, cluster_name, datacenter_name, timeout = 0)
  host_ref = get_host(name, cluster_name, datacenter_name)
  task = host_ref.ExitMaintenanceMode_Task(timeout: timeout)
  task.wait_for_completion
  { 'task_state' => task.info.state }
end
host_shutdown(name, cluster_name, datacenter_name, force = false) click to toggle source
# File lib/fog/vsphere/requests/compute/host_shutdown.rb, line 5
def host_shutdown(name, cluster_name, datacenter_name, force = false)
  host_ref = get_host(name, cluster_name, datacenter_name)
  task = host_ref.ShutdownHost_Task(force: force)
  task.wait_for_completion
  { 'task_state' => task.info.state }
end
host_start_maintenance(name, cluster_name, datacenter_name, timeout = 0, evacuate_powered_off_vms = false) click to toggle source
# File lib/fog/vsphere/requests/compute/host_start_maintenance.rb, line 5
def host_start_maintenance(name, cluster_name, datacenter_name, timeout = 0, evacuate_powered_off_vms = false)
  host_ref = get_host(name, cluster_name, datacenter_name)
  task = host_ref.EnterMaintenanceMode_Task(timeout: timeout, evacuatePoweredOffVms: evacuate_powered_off_vms)
  task.wait_for_completion
  { 'task_state' => task.info.state }
end
interface_type_attributes(nic, servertype, datacenter) click to toggle source
# File lib/fog/vsphere/requests/compute/list_interface_types.rb, line 14
def interface_type_attributes(nic, servertype, datacenter)
  {
    id: nic,
    name: nic,
    datacenter: datacenter,
    servertype: servertype
  }
end
list_child_snapshots(snapshot, opts = {}) click to toggle source
# File lib/fog/vsphere/requests/compute/list_child_snapshots.rb, line 5
def list_child_snapshots(snapshot, opts = {})
  normalized_snapshot = Hash === snapshot ?
    Snapshot.new(snapshot.update(service: self)) : snapshot

  child_snapshots = normalized_snapshot.tree_node.childSnapshotList.map do |snap|
    item = child_snapshot_info(snap, normalized_snapshot)
    [
      item,
      opts[:recursive] ? list_child_snapshots(item, opts) : nil
    ]
  end

  child_snapshots.flatten.compact
end
list_clusters(filters = {}) click to toggle source
# File lib/fog/vsphere/requests/compute/list_clusters.rb, line 5
def list_clusters(filters = {})
  datacenter_name = filters[:datacenter] if filters.key? :datacenter
  if datacenter_name.nil?
    list_datacenters.map { |dc| list_clusters(datacenter: dc[:name]) }.flatten
  else
    raw_clusters(datacenter_name).map do |cluster|
      cluster_attributes(cluster, datacenter_name)
    end.compact
  end
end
list_compute_resources(filters = {}) click to toggle source
# File lib/fog/vsphere/requests/compute/list_compute_resources.rb, line 5
def list_compute_resources(filters = {})
  datacenter_name = filters[:datacenter]
  # default to show all compute_resources
  only_active = filters[:effective] || false
  compute_resources = raw_compute_resources datacenter_name

  compute_resources.map do |compute_resource|
    next if compute_resource.instance_of? RbVmomi::VIM::Folder
    summary = compute_resource.summary
    next if only_active && (summary.numEffectiveHosts == 0)
    compute_resource_attributes(compute_resource, datacenter_name)
  end.compact
end
list_customfields() click to toggle source
# File lib/fog/vsphere/requests/compute/list_customfields.rb, line 5
def list_customfields
  connection.serviceContent.customFieldsManager.field.map do |customfield|
    {
      key: customfield.key.to_i,
      name: customfield.name,
      type: customfield.type
    }
  end
end
list_datacenters(_filters = {}) click to toggle source
# File lib/fog/vsphere/requests/compute/list_datacenters.rb, line 5
def list_datacenters(_filters = {})
  raw_datacenters.map do |dc|
    {
      id: managed_obj_id(dc),
      name: dc.name,
      path: raw_getpathmo(dc),
      status: dc.overallStatus
    }
  end
end
list_datastores(filters = {}) click to toggle source
# File lib/fog/vsphere/requests/compute/list_datastores.rb, line 5
def list_datastores(filters = {})
  datacenter_name = filters[:datacenter]
  cluster_name = filters.fetch(:cluster, nil)
  # default to show all datastores
  only_active = filters[:accessible] || false

  dc = find_raw_datacenter(datacenter_name)

  datastores = if cluster_name
                 cluster = get_raw_cluster(cluster_name, dc)
                 property_collector_results(datastore_cluster_filter_spec(cluster))
               else
                 property_collector_results(datastore_filter_spec(dc))
               end

  datastores.map do |datastore|
    next if only_active && !datastore['summary.accessible']
    map_attrs_to_hash(datastore, datastore_attribute_mapping).merge(
      datacenter: datacenter_name,
      id: managed_obj_id(datastore.obj)
    )
  end.compact
end
list_folders(filters = {}) click to toggle source

Grabs all sub folders within a given path folder.

Parameters

  • filters<~Hash>:

    • :datacenter<~String> - REQUIRED Your datacenter where you're looking for folders. Example: 'my-datacenter-name' (passed if you are using the models/collections)

      eg: vspconn.datacenters.first.vm_folders('mypath')
    • :path<~String> - Your path where you're looking for more folders, if return = none you will get an error. If you don't define it will look in the main datacenter folder for any folders in that datacenter.

Example Usage Testing Only:

vspconn = Fog::Compute[:vsphere]
mydc = vspconn.datacenters.first
folders = mydc.vm_folders
# File lib/fog/vsphere/requests/compute/list_folders.rb, line 23
def list_folders(filters = {})
  path            = filters[:path] || filters['path'] || ''
  datacenter_name = filters[:datacenter]

  # if we don't need to display folders for a specific path
  # we can easily use a property collector to get the
  # data in an efficient manner from vsphere
  # otherwise we use a much slower implementation
  unless path.nil? || path.empty?
    return get_raw_vmfolders(path, datacenter_name).map do |folder|
      folder_attributes(folder, datacenter_name)
    end
  end

  root_folder = connection.serviceContent.rootFolder

  results = property_collector_results(folder_filter_spec(root_folder))

  folder_inventory = generate_folder_inventory(results)

  folders = results.select { |result| result.obj.is_a?(RbVmomi::VIM::Folder) && result['childType'].include?('VirtualMachine') }

  folders.map do |folder|
    folder_id = managed_obj_id(folder.obj)
    parent_id = folder['parent']._ref if folder['parent']
    path = lookup_folder_path(folder_inventory, folder_id)
    next unless path.include?(datacenter_name) # skip folders from another datacenter
    map_attrs_to_hash(folder, folder_attribute_mapping).merge(
      datacenter: datacenter_name,
      parent: lookup_folder_name(folder_inventory, parent_id),
      path: path.join('/'),
      type: folder_type(folder['childType']),
      id: folder_id
    )
  end.compact
end
list_groups(filters = {}) click to toggle source
# File lib/fog/vsphere/requests/compute/list_groups.rb, line 5
def list_groups(filters = {})
  cluster = get_raw_cluster(filters[:cluster], filters[:datacenter])
  cluster.configurationEx.group.map { |g| group_attributes g, filters }
end
list_hosts(filters = {}) click to toggle source
# File lib/fog/vsphere/requests/compute/list_hosts.rb, line 6
def list_hosts(filters = {})
  cluster = get_raw_cluster(filters[:cluster], filters[:datacenter])

  results = property_collector_results(host_system_filter_spec(cluster))

  results.map do |host|
    hsh = map_attrs_to_hash(host, host_system_attribute_mapping)
    hsh.merge(
      datacenter: filters[:datacenter],
      cluster: filters[:cluster],
      ipaddress: (begin
                    host['config.network.vnic'].first.spec.ip.ipAddress
                  rescue
                    nil
                  end),
      ipaddress6: (begin
                     host['config.network.vnic'].first.spec.ip.ipV6Config.ipV6Address.first.ipAddress
                   rescue
                     nil
                   end),
      vm_ids: proc {
        host['vm'].map do |vm|
          begin
                                   vm.config.instanceUuid
                                 rescue
                                   nil
                                 end
        end
      }
    )
  end
end
list_interface_types(filters = {}) click to toggle source
# File lib/fog/vsphere/requests/compute/list_interface_types.rb, line 5
def list_interface_types(filters = {})
  datacenter_name = filters[:datacenter]
  servertype_name = filters[:servertype]
  get_raw_server_type(servertype_name, datacenter_name)[:supportedEthernetCard].map do |nictype|
    next if filters.key?(:id) && (filters[:id] != nictype)
    interface_type_attributes(nictype, servertype_name, datacenter_name)
  end.compact
end
list_networks(filters = {}) click to toggle source
# File lib/fog/vsphere/requests/compute/list_networks.rb, line 5
def list_networks(filters = {})
  datacenter_name = filters[:datacenter]
  cluster_name = filters.fetch(:cluster, nil)
  # default to show all networks
  only_active = filters[:accessible] || false

  dc = find_raw_datacenter(datacenter_name)

  results = property_collector_results(network_filter_spec(dc))

  dvswitches = results.select { |result| result.obj.is_a?(RbVmomi::VIM::DistributedVirtualSwitch) }.each_with_object({}) do |dvswitch, obj|
    obj[dvswitch.obj._ref] = dvswitch['summary.name']
  end

  if cluster_name
    cluster = get_raw_cluster(cluster_name, datacenter_name)
    cluster_networks = cluster.network.map(&:_ref)
  end

  results.select { |result| result.obj.is_a?(RbVmomi::VIM::DistributedVirtualPortgroup) || result.obj.is_a?(RbVmomi::VIM::Network) }.map do |network|
    next if cluster_name && !cluster_networks.include?(network.obj._ref)
    next if only_active && !network['summary.accessible']
    if network.obj.is_a?(RbVmomi::VIM::DistributedVirtualPortgroup)
      map_attrs_to_hash(network, network_dvportgroup_attribute_mapping).merge(
        vlanid: raw_network_vlan(network['config.defaultPortConfig']),
        virtualswitch: dvswitches[network['config.distributedVirtualSwitch']._ref]
      )
    else
      map_attrs_to_hash(network, network_attribute_mapping).merge(
        id: managed_obj_id(network.obj)
      )
    end.merge(
      datacenter: datacenter_name,
      _ref: network.obj._ref
    )
  end.compact
end
list_processes(vm_id, opts) click to toggle source
# File lib/fog/vsphere/requests/compute/list_processes.rb, line 5
def list_processes(vm_id, opts)
  vm = get_vm_ref(vm_id)

  auth = RbVmomi::VIM::NamePasswordAuthentication(
    username: opts[:user],
    password: opts[:password],
    interactiveSession: false
  )

  p_manager = connection.serviceContent.guestOperationsManager.processManager
  processes = p_manager.ListProcessesInGuest(vm: vm, auth: auth)
  processes.map do |pi|
    Process.new(
      cmd_line: pi.cmdLine,
      end_time: pi.endTime,
      exit_code: pi.exitCode,
      name: pi.name,
      owner: pi.owner,
      pid: pi.pid,
      start_time: pi.startTime
    )
  end
end
list_resource_pools(filters = {}) click to toggle source
# File lib/fog/vsphere/requests/compute/list_resource_pools.rb, line 5
def list_resource_pools(filters = {})
  datacenter_name = filters[:datacenter]
  cluster_name    = filters[:cluster]
  cluster         = get_raw_cluster(cluster_name, datacenter_name)
  list_raw_resource_pools(cluster).map do |resource_pool|
    resource_pool_attributes(resource_pool, cluster_name, datacenter_name)
  end
end
list_rules(filters = {}) click to toggle source
# File lib/fog/vsphere/requests/compute/list_rules.rb, line 5
def list_rules(filters = {})
  cluster = get_raw_cluster(filters[:cluster], filters[:datacenter])
  cluster.configurationEx.rule.map { |r| rule_attributes r, filters }
end
list_server_types(filters = {}) click to toggle source
# File lib/fog/vsphere/requests/compute/list_server_types.rb, line 5
def list_server_types(filters = {})
  datacenter_name = filters[:datacenter]
  servertypes = raw_server_types(datacenter_name)
  if servertypes
    servertypes.map do |servertype|
      server_type_attributes(servertype, datacenter_name)
    end.compact
  end
  # select{ | guestdesc | guestdesc.select{ | k, v | filter.has_key?(k) and filter[k] == v }==filter }
end
list_storage_pods(filters = {}) click to toggle source
# File lib/fog/vsphere/requests/compute/list_storage_pods.rb, line 5
def list_storage_pods(filters = {})
  datacenter_name = filters[:datacenter]

  dc = find_raw_datacenter(datacenter_name)

  storage_pods = property_collector_results(storage_pod_filter_spec(dc))

  storage_pods.map do |storage_pod|
    map_attrs_to_hash(storage_pod, storage_pod_attribute_mapping).merge(
      datacenter: datacenter_name,
      id: managed_obj_id(storage_pod.obj)
    )
  end
end
list_templates(options = {}) click to toggle source
# File lib/fog/vsphere/requests/compute/list_templates.rb, line 5
def list_templates(options = {})
  options[:folder] ||= options['folder']
  if options[:folder]
    list_all_templates_in_folder(options[:folder], options[:datacenter])
  else
    list_all_templates(options)
  end
end
list_virtual_machines(options = {}) click to toggle source
# File lib/fog/vsphere/requests/compute/list_virtual_machines.rb, line 5
def list_virtual_machines(options = {})
  # Listing all VM's can be quite slow and expensive.  Try and optimize
  # based on the available options we have.  These conditions are in
  # ascending order of time to complete for large deployments.

  options[:folder] ||= options['folder']
  if options['instance_uuid']
    [get_virtual_machine(options['instance_uuid'])]
  elsif options[:folder] && options[:datacenter]
    list_all_virtual_machines_in_folder(options[:folder], options[:datacenter], options[:recursive])
  else
    list_all_virtual_machines(options)
  end
end
list_vm_cdroms(vm_id) click to toggle source
# File lib/fog/vsphere/requests/compute/list_vm_cdroms.rb, line 6
def list_vm_cdroms(vm_id)
  get_vm_ref(vm_id).config.hardware.device.select { |hw| hw.class == RbVmomi::VIM::VirtualCdrom }.map do |cdrom|
    {
      filename: (begin
                      cdrom.backing.fileName
                    rescue
                      (nil)
                    end),
      name: cdrom.deviceInfo.label,
      key: cdrom.key,
      controller_key: cdrom.controllerKey,
      unit_number: cdrom.unitNumber,
      start_connected: cdrom.connectable.startConnected,
      allow_guest_control: cdrom.connectable.allowGuestControl,
      connected: cdrom.connectable.connected,
      instance_uuid: vm_id
    }
  end
end
list_vm_customvalues(vm_id) click to toggle source
# File lib/fog/vsphere/requests/compute/list_vm_customvalues.rb, line 5
def list_vm_customvalues(vm_id)
  get_vm_ref(vm_id).summary.customValue.map do |customvalue|
    {
      key: customvalue.key.to_i,
      value: customvalue.value
    }
  end
end
list_vm_interfaces(vm_id, datacenter = nil) click to toggle source

> VirtualE1000(

addressType: “assigned”, backing: VirtualEthernetCardNetworkBackingInfo(

deviceName: "VM Network",
dynamicProperty: [],
network: Network("network-163"),
useAutoDetect: false

), connectable: VirtualDeviceConnectInfo(

allowGuestControl: true,
connected: true,
dynamicProperty: [],
startConnected: true,
status: "ok"

), controllerKey: 100, deviceInfo: Description(

dynamicProperty: [],
label: "Network adapter 1",
summary: "VM Network"

), dynamicProperty: [], key: 4000, macAddress: “00:50:56:a9:00:28”, unitNumber: 7,

# File lib/fog/vsphere/requests/compute/list_vm_interfaces.rb, line 31
def list_vm_interfaces(vm_id, datacenter = nil)
  get_raw_interfaces(vm_id, datacenter).map { |nic| raw_to_hash nic }
end
list_vm_scsi_controllers(vm_id) click to toggle source
# File lib/fog/vsphere/requests/compute/list_vm_scsi_controllers.rb, line 5
def list_vm_scsi_controllers(vm_id)
  list_vm_scsi_controllers_raw(vm_id).map do |raw_controller|
    Fog::Vsphere::Compute::SCSIController.new(raw_controller)
  end
end
list_vm_scsi_controllers_raw(vm_id) click to toggle source
# File lib/fog/vsphere/requests/compute/list_vm_scsi_controllers.rb, line 11
def list_vm_scsi_controllers_raw(vm_id)
  get_vm_ref(vm_id).config.hardware.device.grep(RbVmomi::VIM::VirtualSCSIController).map do |ctrl|
    {
      type: ctrl.class.to_s,
      shared_bus: ctrl.sharedBus.to_s,
      unit_number: ctrl.scsiCtlrUnitNumber,
      key: ctrl.key
    }
  end
end
list_vm_snapshots(vm_id, opts = {}) click to toggle source
# File lib/fog/vsphere/requests/compute/list_vm_snapshots.rb, line 5
def list_vm_snapshots(vm_id, opts = {})
  vm_snapshot_info = get_vm_ref(vm_id).snapshot

  return [] unless vm_snapshot_info

  root_snapshots = vm_snapshot_info.rootSnapshotList.map do |snap|
    item = snapshot_info(snap, vm_id)
    [
      item,
      opts[:recursive] ? list_child_snapshots(item, opts) : nil
    ]
  end

  root_snapshots.flatten.compact
end
list_vm_volumes(vm_id) click to toggle source

[VirtualDisk(

backing: VirtualDiskFlatVer2BackingInfo(
  contentId: "a172d19487e878e17d6b16ff2505d7eb",
  datastore: Datastore("datastore-162"),
  diskMode: "persistent",
  dynamicProperty: [],
  fileName: "[Storage1] rhel6-mfojtik/rhel6-mfojtik.vmdk",
  split: false,
  thinProvisioned: true,
  uuid: "6000C29c-a47d-4cd9-5249-c371de775f06",
  writeThrough: false
),
capacityInKB: 8388608,
controllerKey: 1000,
deviceInfo: Description(
  dynamicProperty: [],
  label: "Hard disk 1",
  summary: "8,388,608 KB"
),
dynamicProperty: [],
key: 2001,
shares: SharesInfo( dynamicProperty: [], level: "normal", shares: 1000 ),
unitNumber: 1

)]

# File lib/fog/vsphere/requests/compute/list_vm_volumes.rb, line 31
def list_vm_volumes(vm_id)
  get_vm_ref(vm_id).disks.map do |vol|
    {
      id: vol.backing.uuid,
      thin: (begin
                  vol.backing.thinProvisioned
                rescue
                  (nil)
                end),
      mode: vol.backing.diskMode,
      filename: vol.backing.fileName,
      datastore: (begin
                       vol.backing.datastore.name
                     rescue
                       (nil)
                     end),
      size: vol.capacityInKB,
      name: vol.deviceInfo.label,
      key: vol.key,
      unit_number: vol.unitNumber,
      controller_key: vol.controllerKey
    }
  end
end
modify_template_nics_simple_spec(network_label, nic_type, network_adapter_device_key, datacenter) click to toggle source

Build up the network config spec for simple case: simple case: apply just the network_label, nic_type and network_adapter_device_key

# File lib/fog/vsphere/requests/compute/vm_clone.rb, line 724
def modify_template_nics_simple_spec(network_label, nic_type, network_adapter_device_key, datacenter)
  config_spec_operation = RbVmomi::VIM::VirtualDeviceConfigSpecOperation('edit')
  # Get the portgroup and handle it from there.
  network = get_raw_network(network_label, datacenter)
  nic_backing_info = if network.is_a? RbVmomi::VIM::DistributedVirtualPortgroup
                       # Create the NIC backing for the distributed virtual portgroup
                       RbVmomi::VIM::VirtualEthernetCardDistributedVirtualPortBackingInfo(
                         port: RbVmomi::VIM::DistributedVirtualSwitchPortConnection(
                           portgroupKey: network.key,
                           switchUuid: network.config.distributedVirtualSwitch.uuid
                         )
                       )
                     else
                       # Otherwise it's a non distributed port group
                       RbVmomi::VIM::VirtualEthernetCardNetworkBackingInfo(deviceName: network_label)
                     end
  connectable = RbVmomi::VIM::VirtualDeviceConnectInfo(
    allowGuestControl: true,
    connected: true,
    startConnected: true
  )
  device = RbVmomi::VIM.public_send nic_type.to_s,
                                    backing: nic_backing_info,
                                    deviceInfo: RbVmomi::VIM::Description(label: 'Network adapter 1', summary: network_label),
                                    key: network_adapter_device_key,
                                    connectable: connectable
  device_spec = RbVmomi::VIM::VirtualDeviceConfigSpec(
    operation: config_spec_operation,
    device: device
  )
  device_spec
end
modify_template_nics_specs(vm_mob_ref, nics, datacenter) click to toggle source
# File lib/fog/vsphere/requests/compute/vm_clone.rb, line 757
def modify_template_nics_specs(vm_mob_ref, nics, datacenter)
  specs = []
  template_nics = vm_mob_ref.config.hardware.device.grep(RbVmomi::VIM::VirtualEthernetCard)
  modified_nics = nics.take(template_nics.size)
  new_nics      = nics.drop(template_nics.size)

  template_nics.zip(modified_nics).each do |template_nic, new_nic|
    if new_nic
      backing = create_nic_backing(new_nic, datacenter: datacenter)
      template_nic.backing = backing
      template_nic.addressType = 'generated'
      template_nic.macAddress = nil
      connectable = RbVmomi::VIM::VirtualDeviceConnectInfo(
        allowGuestControl: true,
        connected: true,
        startConnected: true
      )
      template_nic.connectable = connectable
      specs << {
        operation: :edit,
        device: template_nic
      }
    else
      interface = Fog::Vsphere::Compute::Interface.new(raw_to_hash(template_nic))
      specs << create_interface(interface, interface.key, :remove, datacenter: datacenter)
    end
  end

  new_nics.each do |interface|
    specs << create_interface(interface, 0, :add, datacenter: datacenter)
  end

  specs
end
modify_template_volumes_specs(vm_mob_ref, volumes) click to toggle source
# File lib/fog/vsphere/requests/compute/vm_clone.rb, line 792
def modify_template_volumes_specs(vm_mob_ref, volumes)
  template_volumes = vm_mob_ref.config.hardware.device.grep(RbVmomi::VIM::VirtualDisk)
  modified_volumes = volumes.take(template_volumes.size)
  new_volumes      = volumes.drop(template_volumes.size)

  specs = []
  template_volumes.zip(modified_volumes).each do |template_volume, new_volume|
    if new_volume
      # updated the attribtues on the existing volume
      # it's not allowed to reduce the size of the volume when cloning
      if new_volume.size > template_volume.capacityInKB
        template_volume.capacityInKB = new_volume.size
      end
      template_volume.backing.diskMode = new_volume.mode
      template_volume.backing.thinProvisioned = new_volume.thin
      specs << { operation: :edit, device: template_volume }
    else
      specs << { operation: :remove,
                 fileOperation: :destroy,
                 device: template_volume }
    end
  end
  new_volumes.map { |volume| volume.unit_number = volumes.index(volume) < 7 ? volumes.index(volume) : volumes.index(volume) + 1 }
  specs.concat(new_volumes.map { |volume| create_disk(volume) })
  specs
end
raw_clusters(datacenter) click to toggle source
# File lib/fog/vsphere/requests/compute/list_clusters.rb, line 16
def raw_clusters(datacenter)
  folder ||= find_raw_datacenter(datacenter).hostFolder
  @raw_clusters = get_raw_clusters_from_folder(folder)
end
raw_compute_resources(datacenter_name) click to toggle source
# File lib/fog/vsphere/requests/compute/list_compute_resources.rb, line 19
def raw_compute_resources(datacenter_name)
  find_raw_datacenter(datacenter_name).find_compute_resource('').children
end
raw_server_types(datacenter_name, _filter = {}) click to toggle source
# File lib/fog/vsphere/requests/compute/list_server_types.rb, line 16
def raw_server_types(datacenter_name, _filter = {})
  datacenter = find_raw_datacenter(datacenter_name)
  environmentBrowser = datacenter.hostFolder.childEntity.grep(RbVmomi::VIM::ComputeResource).first.environmentBrowser
  if environmentBrowser
    environmentBrowser.QueryConfigOption[:guestOSDescriptor]
  end
end
reload() click to toggle source
# File lib/fog/vsphere/compute.rb, line 621
def reload
  connect
  # Check if the negotiation was ever run
  negotiate if @vsphere_is_vcenter.nil?
  authenticate
end
relocate_template_volumes_specs(vm_mob_ref, volumes, datacenter) click to toggle source
# File lib/fog/vsphere/requests/compute/vm_clone.rb, line 819
def relocate_template_volumes_specs(vm_mob_ref, volumes, datacenter)
  template_volumes = vm_mob_ref.config.hardware.device.grep(RbVmomi::VIM::VirtualDisk)
  modified_volumes = volumes.take(template_volumes.size)

  specs = []
  template_volumes.zip(modified_volumes).each do |template_volume, new_volume|
    if new_volume && new_volume.datastore && new_volume.datastore != template_volume.backing.datastore.name
      specs << { diskId: template_volume.key, datastore: get_raw_datastore(new_volume.datastore, datacenter) }
    end
  end
  specs
end
remove_vm_volume(volume) click to toggle source
# File lib/fog/vsphere/requests/compute/modify_vm_volume.rb, line 9
def remove_vm_volume(volume)
  vm_reconfig_hardware('instance_uuid' => volume.server_id, 'hardware_spec' => { 'deviceChange' => [create_disk(volume, :remove)] })
end
revert_to_snapshot(snapshot) click to toggle source
# File lib/fog/vsphere/requests/compute/revert_to_snapshot.rb, line 5
def revert_to_snapshot(snapshot)
  unless Snapshot === snapshot
    raise ArgumentError, 'snapshot is a required parameter'
  end

  task = snapshot.mo_ref.RevertToSnapshot_Task
  task.wait_for_completion

  {
    'state' => task.info.state
  }
end
set_vm_customvalue(vm_id, key, value) click to toggle source
# File lib/fog/vsphere/requests/compute/set_vm_customvalue.rb, line 5
def set_vm_customvalue(vm_id, key, value)
  vm_ref = get_vm_ref(vm_id)
  vm_ref.setCustomValue(key: key, value: value)
end
update_vm(server) click to toggle source
# File lib/fog/vsphere/requests/compute/update_vm.rb, line 5
def update_vm(server)
  attributes = server.attributes
  datacenter = attributes[:datacenter]
  vm_mob_ref = get_vm_ref(attributes[:instance_uuid], datacenter)

  device_change = []
  spec = {}

  # Name
  spec[:name] = attributes[:name]

  # CPUs
  spec[:numCPUs] = attributes[:cpus]
  spec[:numCoresPerSocket] = attributes[:corespersocket]

  # Memory
  spec[:memoryMB] = attributes[:memory_mb]

  # Volumes
  device_change.concat(update_vm_volumes_specs(vm_mob_ref, server.volumes))

  # Networks
  device_change.concat(update_vm_interfaces_specs(vm_mob_ref, server.interfaces, datacenter))

  spec[:deviceChange] = device_change unless device_change.empty?

  vm_reconfig_hardware('instance_uuid' => attributes[:instance_uuid], 'hardware_spec' => spec) unless spec.empty?
end
update_vm_interface(vmid, options = {}) click to toggle source
# File lib/fog/vsphere/requests/compute/modify_vm_interface.rb, line 19
def update_vm_interface(vmid, options = {})
  raise ArgumentError, 'instance id is a required parameter' unless vmid
  raise ArgumentError, "'datacenter' is a required key in options: #{options}" unless options.key?(:datacenter)

  datacenter_name = options[:datacenter]

  interface = get_interface_from_options(vmid, options)
  raw_interface = get_raw_interface(vmid, key: interface.key, datacenter: datacenter_name)

  if options[:network]
    interface.network = options[:network]
    backing = create_nic_backing(interface, datacenter: datacenter_name)
    raw_interface.backing = backing
  end

  apply_options_to_raw_interface(raw_interface, options)

  spec = {
    operation: :edit,
    device: raw_interface
  }

  vm_reconfig_hardware('instance_uuid' => vmid, 'hardware_spec' => { 'deviceChange' => [spec] })
end
upload_iso(options = {}) click to toggle source
# File lib/fog/vsphere/requests/compute/upload_iso.rb, line 19
def upload_iso(options = {})
  options = upload_iso_check_options(options)
  datastore = get_raw_datastore(options['datastore'], options['datacenter'])
  datacenter = get_raw_datacenter(options['datacenter'])
  filename = options['filename'] || File.basename(options['local_path'])
  unless datastore.exists? options['upload_directory'] + '/'
    connection.serviceContent.fileManager.MakeDirectory name: "[#{options['datastore']}] #{options['upload_directory']}",
                                                        datacenter: datacenter,
                                                        createParentDirectories: false
  end
  datastore.upload options['upload_directory'] + '/' + filename, options['local_path']
  datastore.exists? options['upload_directory'] + '/' + filename
end
upload_iso_check_options(options) click to toggle source
# File lib/fog/vsphere/requests/compute/upload_iso.rb, line 5
def upload_iso_check_options(options)
  default_options = {
    'upload_directory' => 'isos'
  }
  options = default_options.merge(options)
  required_options = %w[datacenter datastore local_path]
  required_options.each do |param|
    raise ArgumentError, "#{required_options.join(', ')} are required" unless options.key? param
  end
  raise Fog::Vsphere::Compute::NotFound, "Datacenter #{options['datacenter']} Doesn't Exist!" unless get_datacenter(options['datacenter'])
  raise Fog::Vsphere::Compute::NotFound, "Datastore #{options['datastore']} Doesn't Exist!" unless get_raw_datastore(options['datastore'], options['datacenter'])
  options
end
vm_acquire_ticket(options = {}) click to toggle source
# File lib/fog/vsphere/requests/compute/vm_acquire_ticket.rb, line 5
def vm_acquire_ticket(options = {})
  raise ArgumentError, 'instance_uuid is a required parameter' unless options.key?('instance_uuid')
  ticket_type = options['ticket_type'] || 'webmks'

  vm_mob_ref = get_vm_ref(options['instance_uuid'])

  ticket = vm_mob_ref.AcquireTicket(ticketType: ticket_type)
  {
    'ticket' => ticket.ticket,
    'host' => ticket.host,
    'port' => ticket.port,
    'ssl_thumbprint' => ticket.sslThumbprint
  }
end
vm_clone(options = {}) click to toggle source

Clones a VM from a template or existing machine on your vSphere Server.

Parameters

  • options<~Hash>:

    • 'datacenter'<~String> - REQUIRED Datacenter name your cloning in. Make sure this datacenter exists, should if you're using the clone function in server.rb model.

    • 'template_path'<~String> - REQUIRED The path to the machine you want to clone FROM. Relative to Datacenter (Example: “FolderNameHere/VMNameHere”)

    • 'name'<~String> - REQUIRED The VMName of the Destination

    • 'dest_folder'<~String> - Destination Folder of where 'name' will be placed on your cluster. Relative Path to Datacenter E.G. “FolderPlaceHere/anotherSub Folder/onemore”

    • 'power_on'<~Boolean> - Whether to power on machine after clone. Defaults to true.

    • 'wait'<~Boolean> - Whether the method should wait for the virtual machine to finish cloning before returning information from vSphere. Broken right now as you cannot return a model of a serer that isn't finished cloning. Defaults to True

    • 'resource_pool'<~Array> - The resource pool on your datacenter cluster you want to use. Only works with clusters within same same datacenter as where you're cloning from. Datacenter grabbed from template_path option. Example: ['cluster_name_here','resource_pool_name_here']

    • 'datastore'<~String> - The datastore you'd like to use.

      (datacenterObj.datastoreFolder.find('name') in API)
    • 'storage_pod'<~String> - The storage pod / datastore cluster you'd like to use.

    • 'transform'<~String> - Not documented - see www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/vim.vm.RelocateSpec.html

    • 'numCPUs'<~Integer> - the number of Virtual CPUs of the Destination VM

    • 'numCoresPerSocket'<~Integer> - the number of cores per socket of the Destination VM

    • 'memoryMB'<~Integer> - the size of memory of the Destination VM in MB

    • customization_spec<~Hash>: Options are marked as required if you use this customization_spec. As defined pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.Specification.html

      • encryptionKey <~array of bytes> Used to encrypt/decrypt password

      • globalIPSettings expects a hash, REQUIRED

      • identity expects a hash, REQUIRED - either LinuxPrep, Sysprep or SysprepText

      • nicSettingMap expects an array

      • options expects a hash

      • All options can be parsed using a yaml template with cloudinit_to_customspec.rb

      OLD Values still supported: This only support cloning and setting DHCP on the first interface

      • 'domain'<~String> - REQUIRED This is put into /etc/resolve.conf (we hope)

      • 'hostname'<~String> - Hostname of the Guest Os - default is options

      • 'hw_utc_clock'<~Boolean> - REQUIRED Is hardware clock UTC? Default true

      • 'time_zone'<~String> - REQUIRED Only valid linux options are valid - example: 'America/Denver'

      • 'interfaces' <~Array> - interfaces object to apply to

        the template when cloning: overrides the
        network_label, network_adapter_device_key and nic_type attributes
      • 'volumes' <~Array> - volumes object to apply to

        the template when cloning: this allows to resize the
        existing disks as well as add or remove them. The
        resizing is applied only when the size is bigger then the
        in size in the template

rubocop:disable Metrics/MethodLength

# File lib/fog/vsphere/requests/compute/vm_clone.rb, line 100
def vm_clone(options = {})
  # Option handling
  options = vm_clone_check_options(options)

  # Added for people still using options['path']
  template_path = options['path'] || options['template_path']

  # Options['template_path']<~String>
  # Added for people still using options['path']
  template_path = options['path'] || options['template_path']
  # Now find the template itself using the efficient find method
  vm_mob_ref = get_vm_ref(template_path, options['datacenter'])

  # Options['dest_folder']<~String>
  # Grab the destination folder object if it exists else use cloned mach
  dest_folder_path = options.fetch('dest_folder', '/') # default to root path ({dc_name}/vm/)
  dest_folder = get_raw_vmfolder(dest_folder_path, options['datacenter'])

  # Options['resource_pool']<~Array>
  # Now find _a_ resource pool to use for the clone if one is not specified
  if options.key?('resource_pool') && options['resource_pool'].is_a?(Array) && options['resource_pool'].length == 2 && options['resource_pool'][1] != 'Resources'
    cluster_name = options['resource_pool'][0]
    pool_name = options['resource_pool'][1]
    resource_pool = get_raw_resource_pool(pool_name, cluster_name, options['datacenter'])
  elsif options.key?('resource_pool') && options['resource_pool'].is_a?(Array) && options['resource_pool'].length == 2 && options['resource_pool'][1] == 'Resources'
    cluster_name = options['resource_pool'][0]
    resource_pool = get_raw_resource_pool(nil, cluster_name, options['datacenter'])
  elsif vm_mob_ref.resourcePool.nil?
    # If the template is really a template then there is no associated resource pool,
    # so we need to find one using the template's parent host or cluster
    esx_host = vm_mob_ref.collect!('runtime.host')['runtime.host']
    # The parent of the ESX host itself is a ComputeResource which has a resourcePool
    resource_pool = esx_host.parent.resourcePool
    cluster_name = nil
  end
  # If the vm given did return a valid resource pool, default to using it for the clone.
  # Even if specific pools aren't implemented in this environment, we will still get back
  # at least the cluster or host we can pass on to the clone task
  # This catches if resource_pool option is set but comes back nil and if resourcePool is
  # already set.
  resource_pool ||= vm_mob_ref.resourcePool.nil? ? esx_host.parent.resourcePool : vm_mob_ref.resourcePool

  # Options['host']<~String>
  # The target host for the virtual machine. Optional.
  host = if options.key?('host') && !options['host'].empty? && !cluster_name.nil?
           get_raw_host(options['host'], cluster_name, options['datacenter'])
         end

  # Options['datastore']<~String>
  # Grab the datastore object if option is set
  datastore_obj = get_raw_datastore(options['datastore'], options['datacenter']) if options.key?('datastore')
  # confirm nil if nil or option is not set
  datastore_obj ||= nil
  virtual_machine_config_spec = RbVmomi::VIM::VirtualMachineConfigSpec()

  device_change = []
  # fully futured interfaces api: replace the current nics
  # with the new based on the specification
  if options.key?('interfaces')
    if options.key?('network_label')
      raise ArgumentError, "interfaces option can't be specified together with network_label"
    end
    device_change.concat(modify_template_nics_specs(vm_mob_ref, options['interfaces'], options['datacenter']))
  elsif options.key?('network_label')
    device_change << modify_template_nics_simple_spec(options['network_label'], options['nic_type'], options['network_adapter_device_key'], options['datacenter'])
  end
  if disks = options['volumes']
    device_change.concat(modify_template_volumes_specs(vm_mob_ref, options['volumes']))
  end
  virtual_machine_config_spec.deviceChange = device_change if device_change.any?
  # Options['numCPUs'] or Options['memoryMB']
  # Build up the specification for Hardware, for more details see ____________
  # https://github.com/rlane/rbvmomi/blob/master/test/test_serialization.rb
  # http://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/vim.vm.ConfigSpec.html
  # FIXME: pad this out with the rest of the useful things in VirtualMachineConfigSpec
  virtual_machine_config_spec.numCPUs = options['numCPUs'] if options.key?('numCPUs')
  virtual_machine_config_spec.numCoresPerSocket = options['numCoresPerSocket'] if options.key?('numCoresPerSocket')
  virtual_machine_config_spec.memoryMB = options['memoryMB'] if options.key?('memoryMB')
  virtual_machine_config_spec.cpuHotAddEnabled = options['cpuHotAddEnabled'] if options.key?('cpuHotAddEnabled')
  virtual_machine_config_spec.memoryHotAddEnabled = options['memoryHotAddEnabled'] if options.key?('memoryHotAddEnabled')
  virtual_machine_config_spec.firmware = options['firmware'] if options.key?('firmware')
  virtual_machine_config_spec.extraConfig = extra_config(extra_config: options['extraConfig']) if options.key?('extraConfig')
  if @vsphere_rev.to_f >= 5 && options.key?('boot_order')
    boot_order = options['boot_order'].flat_map do |boot_device|
      case boot_device.to_sym
      when :network
        interfaces = device_change.select do |change|
          %i[edit add].include?(change[:operation]) &&
            change[:device].class <= RbVmomi::VIM::VirtualEthernetCard
        end.map { |change| change[:device] }
        interfaces.map do |interface|
          RbVmomi::VIM::VirtualMachineBootOptionsBootableEthernetDevice.new(
            deviceKey: interface.key
          )
        end
      when :disk
        disks = device_change.select do |change|
          %i[edit add].include?(change[:operation]) &&
            change[:device].is_a?(RbVmomi::VIM::VirtualDisk)
        end.map { |change| change[:device] }
        disks.map do |disk|
          RbVmomi::VIM::VirtualMachineBootOptionsBootableDiskDevice.new(
            deviceKey: disk.key
          )
        end
      when :cdrom
        RbVmomi::VIM::VirtualMachineBootOptionsBootableCdromDevice.new
      when :floppy
        RbVmomi::VIM::VirtualMachineBootOptionsBootableFloppyDevice.new
      end
    end
    virtual_machine_config_spec.bootOptions = { bootOrder: boot_order }
  end
  # Options['customization_spec']
  # OLD Options still supported
  # * domain <~String> - *REQUIRED* - Sets the server's domain for customization
  # * dnsSuffixList <~Array> - Optional - Sets the dns search paths in resolv - Example: ["dev.example.com", "example.com"]
  # * time_zone <~String> - Required - Only valid linux options are valid - example: 'America/Denver'
  # * ipsettings <~Hash> - Optional - If not set defaults to dhcp
  #  * ip <~String> - *REQUIRED* Sets the ip address of the VM - Example: 10.0.0.10
  #  * dnsServerList <~Array> - Optional - Sets the nameservers in resolv - Example: ["10.0.0.2", "10.0.0.3"]
  #  * gateway <~Array> - Optional - Sets the gateway for the interface - Example: ["10.0.0.1"]
  #  * subnetMask <~String> - *REQUIRED* - Set the netmask of the interface - Example: "255.255.255.0"
  #    For other ip settings options see http://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/vim.vm.customization.IPSettings.html
  #
  #  Implement complete customization spec as per https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.Specification.html
  #   * encryptionKey <~Array> - Optional, encryption key used to encypt any encrypted passwords
  #   https://pubs.vmware.com/vsphere-51/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.GlobalIPSettings.html
  #   * globalIPSettings <~Hash> - REQUIRED
  #   *   dnsServerList <~Array> - Optional, list of dns servers - Example: ["10.0.0.2", "10.0.0.3"]
  #   *   dnsSuffixList <~Array> - Optional, List of name resolution suffixes - Example: ["dev.example.com", "example.com"]
  #   * identity <~Hash> - REQUIRED, Network identity and settings, similar to Microsoft's Sysprep tool. This is a Sysprep, LinuxPrep, or SysprepText object
  #   *   Sysprep <~Hash> - Optional, representation of a Windows sysprep.inf answer file.
  #   *     guiRunOnce: <~Hash> -Optional, representation of the sysprep GuiRunOnce key
  #   *       commandList: <~Array> - REQUIRED, list of commands to run at first user logon, after guest customization. - Example: ["c:\sysprep\runaftersysprep.cmd", "c:\sysprep\installpuppet.ps1"]
  #   *     guiUnattended: <~Hash> - REQUIRED, representation of the sysprep GuiUnattended key
  #   *       autoLogin: boolean - REQUIRED, Flag to determine whether or not the machine automatically logs on as Administrator.
  #   *       autoLogonCount: int - REQUIRED, specifies the number of times the machine should automatically log on as Administrator
  #   *       password: <~Hash> - REQUIRED, new administrator password for the machine
  #   *         plainText: boolean - REQUIRED, specify whether or not the password is in plain text, rather than encrypted
  #   *         value: <~String> - REQUIRED, password string
  #   *       timeZone: <~int> - REQUIRED, (see here for values https://msdn.microsoft.com/en-us/library/ms912391(v=winembedded.11).aspx)
  #   *     identification: <~Hash> - REQUIRED, representation of the sysprep Identification key
  #   *       domainAdmin: <~String> - Optional, domain user account used for authentication if the virtual machine is joining a domain
  #   *       domainAdminPassword: <~Hash> - Optional, password for the domain user account used for authentication
  #   *         plainText: boolean - REQUIRED, specify whether or not the password is in plain text, rather than encrypted
  #   *         value: <~String> - REQUIRED, password string
  #   *       joinDomain: <~String> - Optional, The domain that the virtual machine should join. If this value is supplied, then domainAdmin and domainAdminPassword must also be supplied
  #   *       joinWorkgroup: <~String> - Optional, The workgroup that the virtual machine should join.
  #   *     licenseFilePrintData: <~Hash> - Optional, representation of the sysprep LicenseFilePrintData key
  #   *       autoMode: <~String> - REQUIRED, Server licensing mode. Two strings are supported: 'perSeat' or 'perServer'
  #   *       autoUsers: <~Int> - Optional, This key is valid only if AutoMode = PerServer. The integer value indicates the number of client licenses
  #   *     userData: <~Hash> - REQUIRED, representation of the sysprep UserData key
  #   *       computerName: <~String> - REQUIRED, The computer name of the (Windows) virtual machine. Will be truncates to 15 characters
  #   *       fullName: <~String> - REQUIRED, User's full name
  #   *       orgName: <~String> - REQUIRED, User's organization
  #   *       productId: <~String> - REQUIRED, serial number for os, ignored if using volume licensed instance
  #   *   LinuxPrep: <~Hash> - Optional, contains machine-wide settings (note the uppercase P)
  #   *     domain: <~String> - REQUIRED, The fully qualified domain name.
  #   *     hostName: <~String> - REQUIRED, the network host name
  #   *     hwClockUTC: <~Boolean> - Optional, Specifies whether the hardware clock is in UTC or local time
  #   *     timeZone: <~String> - Optional, Case sensistive timezone, valid values can be found at https://pubs.vmware.com/vsphere-51/topic/com.vmware.wssdk.apiref.doc/timezone.html
  #   *   SysprepText: <~Hash> - Optional, alternate way to specify the sysprep.inf answer file.
  #   *     value: <~String> - REQUIRED, Text for the sysprep.inf answer file.
  #   * nicSettingMap: <~Array> - Optional, IP settings that are specific to a particular virtual network adapter
  #   *   Each item in array:
  #   *   adapter: <~Hash> - REQUIRED, IP settings for the associated virtual network adapter
  #   *     dnsDomain: <~String> - Optional, DNS domain suffix for adapter
  #   *     dnsServerList: <~Array> - Optional, list of dns server ip addresses - Example: ["10.0.0.2", "10.0.0.3"]
  #   *     gateway: <~Array> - Optional, list of gateways - Example: ["10.0.0.2", "10.0.0.3"]
  #   *     ip: <~String> - Optional, but required if static IP
  #   *     ipV6Spec: <~Hash> - Optional, IPv^ settings
  #   *       ipAddress: <~String> - Optional, but required if setting static IP
  #   *       gateway: <~Array> - Optional, list of ipv6 gateways
  #   *     netBIOS: <~String> - Optional, NetBIOS settings, if supplied must be one of: disableNetBIOS','enableNetBIOS','enableNetBIOSViaDhcp'
  #   *     primaryWINS: <~String> - Optional, IP address of primary WINS server
  #   *     secondaryWINS: <~String> - Optional, IP address of secondary WINS server
  #   *     subnetMask: <~String> - Optional, subnet mask for adapter
  #   *   macAddress: <~String> - Optional, MAC address of adapter being customized. This cannot be set by the client
  #   * options: <~Hash> Optional operations, currently only win options have any value
  #   *   changeSID: <~Boolean> - REQUIRED, The customization process should modify the machine's security identifier
  #   *   deleteAccounts: <~Boolean> - REQUIRED, If deleteAccounts is true, then all user accounts are removed from the system
  #   *   reboot: <~String> - Optional, (defaults to reboot), Action to be taken after running sysprep, must be one of: 'noreboot', 'reboot', 'shutdown'
  #
  if options.key?('customization_spec')
    custom_spec = options['customization_spec']

    # backwards compatablity
    if custom_spec.key?('domain')
      # doing this means the old options quash any new ones passed as well... might not be the best way to do it?
      # any 'old' options overwrite the following:
      #   - custom_spec['identity']['LinuxPrep']
      #   - custom_spec['globalIPSettings['['dnsServerList']
      #   - custom_spec['globalIPSettings']['dnsSuffixList']
      #   - custom_spec['nicSettingMap'][0]['adapter']['ip']
      #   - custom_spec['nicSettingMap'][0]['adapter']['gateway']
      #   - custom_spec['nicSettingMap'][0]['adapter']['subnetMask']
      #   - custom_spec['nicSettingMap'][0]['adapter']['dnsDomain']
      #   - custom_spec['nicSettingMap'][0]['adapter']['dnsServerList']
      #
      # we can assume old parameters being passed
      cust_hostname = custom_spec['hostname'] || options['name']
      custom_spec['identity'] = {} unless custom_spec.key?('identity')
      custom_spec['identity']['LinuxPrep'] = { 'domain' => custom_spec['domain'], 'hostName' => cust_hostname, 'timeZone' => custom_spec['time_zone'] }

      if custom_spec.key?('ipsettings')
        custom_spec['globalIPSettings'] = {} unless custom_spec.key?('globalIPSettings')
        custom_spec['globalIPSettings']['dnsServerList'] = custom_spec['ipsettings']['dnsServerList'] if custom_spec['ipsettings'].key?('dnsServerList')
        custom_spec['globalIPSettings']['dnsSuffixList'] = custom_spec['dnsSuffixList'] || [custom_spec['domain']] if custom_spec['dnsSuffixList'] || custom_spec['domain']
        if custom_spec['ipsettings'].key?('ip') || custom_spec['ipsettings'].key?('gateway') || custom_spec['ipsettings'].key?('subnetMask') || custom_spec['ipsettings'].key?('domain') || custom_spec['ipsettings'].key?('dnsServerList')
          if custom_spec['ipsettings'].key?('ip') && !custom_spec['ipsettings'].key?('subnetMask')
            raise ArgumentError, 'subnetMask is required for static ip'
          end
          custom_spec['nicSettingMap'] = [] unless custom_spec.key?('nicSettingMap')
          custom_spec['nicSettingMap'][0] = {} if custom_spec['nicSettingMap'].empty?
          custom_spec['nicSettingMap'][0]['adapter'] = {} unless custom_spec['nicSettingMap'][0].key?('adapter')
          custom_spec['nicSettingMap'][0]['adapter']['ip'] = custom_spec['ipsettings']['ip'] if custom_spec['ipsettings'].key?('ip')
          custom_spec['nicSettingMap'][0]['adapter']['gateway'] = custom_spec['ipsettings']['gateway'] if custom_spec['ipsettings'].key?('gateway')
          custom_spec['nicSettingMap'][0]['adapter']['subnetMask'] = custom_spec['ipsettings']['subnetMask'] if custom_spec['ipsettings'].key?('subnetMask')
          custom_spec['nicSettingMap'][0]['adapter']['dnsDomain'] = custom_spec['ipsettings']['domain'] if custom_spec['ipsettings'].key?('domain')
          custom_spec['nicSettingMap'][0]['adapter']['dnsServerList'] = custom_spec['ipsettings']['dnsServerList'] if custom_spec['ipsettings'].key?('dnsServerList')
        end
      end
    end
    ### End of backwards compatability

    ## requirements check here ##
    raise ArgumentError, 'globalIPSettings are required when using Customization Spec' unless custom_spec.key?('globalIPSettings')
    raise ArgumentError, 'identity is required when using Customization Spec' unless custom_spec.key?('identity')

    # encryptionKey
    custom_encryptionKey = custom_spec['encryptionKey'] if custom_spec.key?('encryptionKey')
    custom_encryptionKey ||= nil

    # globalIPSettings
    # https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.GlobalIPSettings.html
    custom_globalIPSettings = RbVmomi::VIM::CustomizationGlobalIPSettings.new
    custom_globalIPSettings.dnsServerList = custom_spec['globalIPSettings']['dnsServerList'] if custom_spec['globalIPSettings'].key?('dnsServerList')
    custom_globalIPSettings.dnsSuffixList = custom_spec['globalIPSettings']['dnsSuffixList'] if custom_spec['globalIPSettings'].key?('dnsSuffixList')

    # identity
    # https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.IdentitySettings.html
    # Accepts the 3 supported CustomizationIdentitySettings Types:
    # 1. CustomizationLinuxPrep (LinuxPrep) - note the uppercase P
    # 2. CustomizationSysprep (Sysprep)
    # 3. CustomizationSysprepText (SysprepText)
    # At least one of these is required
    #
    identity = custom_spec['identity']
    if identity.key?('LinuxPrep')
      # https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.LinuxPrep.html
      # Fields:
      #   * domain: string **REQUIRED**
      #   * hostName: string (CustomizationName)  **REQUIRED** Will use options['name'] if not provided.
      #   * hwClockUTC: boolean
      #   * timeZone: string (https://pubs.vmware.com/vsphere-55/topic/com.vmware.wssdk.apiref.doc/timezone.html)
      raise ArgumentError, 'domain is required when using LinuxPrep identity' unless identity['LinuxPrep'].key?('domain')
      custom_identity = RbVmomi::VIM::CustomizationLinuxPrep(domain: identity['LinuxPrep']['domain'])
      cust_hostname = RbVmomi::VIM::CustomizationFixedName(name: identity['LinuxPrep']['hostName']) if identity['LinuxPrep'].key?('hostName')
      cust_hostname ||= RbVmomi::VIM::CustomizationFixedName(name: options['name'])
      custom_identity.hostName = cust_hostname
      custom_identity.hwClockUTC = identity['LinuxPrep']['hwClockUTC'] if identity['LinuxPrep'].key?('hwClockUTC')
      custom_identity.timeZone = identity['LinuxPrep']['timeZone'] if identity['LinuxPrep'].key?('timeZone')
    elsif identity.key?('Sysprep')
      # https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.Sysprep.html
      # Fields:
      #   * guiRunOnce: CustomizationGuiRunOnce
      #   * guiUnattended: CustomizationGuiUnattended  **REQUIRED**
      #   * identification: CustomizationIdentification  **REQUIRED**
      #   * licenseFilePrintData: CustomizationLicenseFilePrintData
      #   * userData: CustomizationUserData **REQUIRED**
      #
      raise ArgumentError, 'guiUnattended is required when using Sysprep identity' unless identity['Sysprep'].key?('guiUnattended')
      raise ArgumentError, 'identification is required when using Sysprep identity' unless identity['Sysprep'].key?('identification')
      raise ArgumentError, 'userData is required when using Sysprep identity' unless identity['Sysprep'].key?('userData')
      if identity['Sysprep']['guiRunOnce']
        # https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.GuiRunOnce.html
        # Fields:
        #  * commandList: array of string **REQUIRED***
        #
        raise ArgumentError, 'commandList is required when using Sysprep identity and guiRunOnce' unless identity['Sysprep']['guiRunOnce'].key?('commandList')
        cust_guirunonce = RbVmomi::VIM.CustomizationGuiRunOnce(commandList: identity['Sysprep']['guiRunOnce']['commandList'])
      end
      # https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.GuiUnattended.html
      # Fields:
      #   * autoLogin: boolean **REQUIRED**
      #   * autoLogonCount: int **REQUIRED**
      #   * timeZone: int (see here for values https://msdn.microsoft.com/en-us/library/ms912391(v=winembedded.11).aspx) **REQUIRED**
      #   * password: CustomizationPassword
      raise ArgumentError, 'guiUnattended->autoLogon is required when using Sysprep identity' unless identity['Sysprep']['guiUnattended'].key?('autoLogon')
      raise ArgumentError, 'guiUnattended->autoLogonCount is required when using Sysprep identity' unless identity['Sysprep']['guiUnattended'].key?('autoLogonCount')
      raise ArgumentError, 'guiUnattended->timeZone is required when using Sysprep identity' unless identity['Sysprep']['guiUnattended'].key?('timeZone')
      custom_guiUnattended = RbVmomi::VIM.CustomizationGuiUnattended(
        autoLogon: identity['Sysprep']['guiUnattended']['autoLogon'],
        autoLogonCount: identity['Sysprep']['guiUnattended']['autoLogonCount'],
        timeZone: identity['Sysprep']['guiUnattended']['timeZone']
      )
      if identity['Sysprep']['guiUnattended']['password']
        # https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.Password.html
        # Fields:
        #   * plainText: boolean  **REQUIRED**
        #   * value: string  **REQUIRED**
        raise ArgumentError, 'guiUnattended->password->plainText is required when using Sysprep identity and guiUnattended -> password' unless identity['Sysprep']['guiUnattended']['password'].key?('plainText')
        raise ArgumentError, 'guiUnattended->password->value is required when using Sysprep identity and guiUnattended -> password' unless identity['Sysprep']['guiUnattended']['password'].key?('value')
        custom_guiUnattended.password = RbVmomi::VIM.CustomizationPassword(
          plainText: identity['Sysprep']['guiUnattended']['password']['plainText'],
          value: identity['Sysprep']['guiUnattended']['password']['value']
        )
      end
      # https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.Identification.html
      # Fields:
      #   * domainAdmin: string
      #   * domainAdminPassword: CustomizationPassword
      #   * joinDomain: string *If supplied domainAdmin and domainAdminPassword must be set
      #   * joinWorkgroup: string *If supplied, joinDomain, domainAdmin and domainAdminPassword will be ignored
      custom_identification = RbVmomi::VIM.CustomizationIdentification()
      if identity['Sysprep']['identification'].key?('joinWorkgroup')
        custom_identification.joinWorkgroup = identity['Sysprep']['identification']['joinWorkgroup']
      elsif identity['Sysprep']['identification'].key?('joinDomain')
        raise ArgumentError, 'identification->domainAdmin is required when using Sysprep identity and identification -> joinDomain' unless identity['Sysprep']['identification'].key?('domainAdmin')
        raise ArgumentError, 'identification->domainAdminPassword is required when using Sysprep identity and identification -> joinDomain' unless identity['Sysprep']['identification'].key?('domainAdmin')
        raise ArgumentError, 'identification->domainAdminPassword->plainText is required when using Sysprep identity and identification -> joinDomain' unless identity['Sysprep']['identification']['domainAdminPassword'].key?('plainText')
        raise ArgumentError, 'identification->domainAdminPassword->value is required when using Sysprep identity and identification -> joinDomain' unless identity['Sysprep']['identification']['domainAdminPassword'].key?('value')
        custom_identification.joinDomain = identity['Sysprep']['identification']['joinDomain']
        custom_identification.domainAdmin = identity['Sysprep']['identification']['domainAdmin']
        # https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.Password.html
        # Fields:
        #   * plainText: boolean **REQUIRED**
        #   * value: string **REQUIRED**
        custom_identification.domainAdminPassword = RbVmomi::VIM.CustomizationPassword(
          plainText: identity['Sysprep']['identification']['domainAdminPassword']['plainText'],
          value: identity['Sysprep']['identification']['domainAdminPassword']['value']
        )
      else
        raise ArgumentError, "No valid Indentification found, valid values are 'joinWorkgroup' and 'joinDomain'"
      end
      if identity['Sysprep'].key?('licenseFilePrintData')
        # https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.LicenseFilePrintData.html
        # Fields:
        #   * autoMode: string (CustomizationLicenseDataMode) ** REQUIRED **, valid strings are: 'perSeat' or 'perServer'
        #   * autoUsers: int (valid only if AutoMode = PerServer)
        raise ArgumentError, 'licenseFilePrintData->autoMode is required when using Sysprep identity and licenseFilePrintData' unless identity['Sysprep']['licenseFilePrintData'].key?('autoMode')
        raise ArgumentError, "Unsupported autoMode, supported modes are : 'perSeat' or 'perServer'" unless %w[perSeat perServer].include? identity['Sysprep']['licenseFilePrintData']['autoMode']
        custom_licenseFilePrintData = RbVmomi::VIM.CustomizationLicenseFilePrintData(
          autoMode: RbVmomi::VIM.CustomizationLicenseDataMode(identity['Sysprep']['licenseFilePrintData']['autoMode'])
        )
        if identity['Sysprep']['licenseFilePrintData'].key?('autoUsers')
          custom_licenseFilePrintData.autoUsers = identity['Sysprep']['licenseFilePrintData']['autoUsers'] if identity['Sysprep']['licenseFilePrintData']['autoMode'] == 'PerServer'
        end
      end
      # https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.UserData.html
      # Fields:
      #   * computerName: string (CustomizationFixedName)  **REQUIRED**
      #   * fullName: string **REQUIRED**
      #   * orgName: string **REQUIRED**
      #   * productID: string **REQUIRED**
      raise ArgumentError, 'userData->computerName is required when using Sysprep identity' unless identity['Sysprep']['userData'].key?('computerName')
      raise ArgumentError, 'userData->fullName is required when using Sysprep identity' unless identity['Sysprep']['userData'].key?('fullName')
      raise ArgumentError, 'userData->orgName is required when using Sysprep identity' unless identity['Sysprep']['userData'].key?('orgName')
      raise ArgumentError, 'userData->productId is required when using Sysprep identity' unless identity['Sysprep']['userData'].key?('productId')
      custom_userData = RbVmomi::VIM.CustomizationUserData(
        fullName: identity['Sysprep']['userData']['fullName'],
        orgName: identity['Sysprep']['userData']['orgName'],
        productId: identity['Sysprep']['userData']['productId'],
        computerName: RbVmomi::VIM.CustomizationFixedName(name: identity['Sysprep']['userData']['computerName'])
      )

      custom_identity = RbVmomi::VIM::CustomizationSysprep(
        guiUnattended: custom_guiUnattended,
        identification: custom_identification,
        userData: custom_userData
      )
      custom_identity.guiRunOnce = cust_guirunonce if defined?(cust_guirunonce)
      custom_identity.licenseFilePrintData = custom_licenseFilePrintData if defined?(custom_licenseFilePrintData)
    elsif identity.key?('SysprepText')
      # https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.SysprepText.html
      # Fields:
      #   * value: string **REQUIRED**
      raise ArgumentError, 'SysprepText -> value is required when using SysprepText identity' unless identity['SysprepText'].key?('value')
      custom_identity = RbVmomi::VIM::CustomizationSysprepText(value: identity['SysprepText']['value'])
    else
      raise ArgumentError, 'At least one of the following valid identities must be supplied: LinuxPrep, Sysprep, SysprepText'
    end

    if custom_spec.key?('nicSettingMap')
      # custom_spec['nicSettingMap'] is an array of adapater mappings:
      # custom_spec['nicSettingMap'][0]['macAddress']
      # custom_spec['nicSettingMap'][0]['adapter']['ip']
      # https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.AdapterMapping.html
      # Fields:
      #   * adapter: CustomizationIPSettings **REQUIRED**
      #   * macAddress: string
      raise ArgumentError, 'At least one nicSettingMap is required when using nicSettingMap' if custom_spec['nicSettingMap'].empty?
      raise ArgumentError, 'Adapter is required when using nicSettingMap' unless custom_spec['nicSettingMap'][0].key?('adapter')

      custom_nicSettingMap = []
      # need to go through array here for each apapter
      custom_spec['nicSettingMap'].each do |nic|
        # https://pubs.vmware.com/vsphere-55/index.jsp?topic=%2Fcom.vmware.wssdk.apiref.doc%2Fvim.vm.customization.IPSettings.html
        # Fields:
        #   * dnsDomain: string
        #   * gateway: array of string
        #   * ip: CustomizationIpGenerator (string) **REQUIRED IF Assigning Static IP***
        #   * ipV6Spec: CustomizationIPSettingsIpV6AddressSpec
        #   * netBIOS: CustomizationNetBIOSMode (string)
        #   * primaryWINS: string
        #   * secondaryWINS: string
        #   * subnetMask: string - Required if assigning static IP
        if nic['adapter'].key?('ip')
          raise ArgumentError, 'SubnetMask is required when assigning static IP when using nicSettingMap -> Adapter' unless nic['adapter'].key?('subnetMask')
          custom_ip = RbVmomi::VIM.CustomizationFixedIp(ipAddress: nic['adapter']['ip'])
        else
          custom_ip = RbVmomi::VIM::CustomizationDhcpIpGenerator.new
        end
        custom_adapter = RbVmomi::VIM.CustomizationIPSettings(ip: custom_ip)
        custom_adapter.dnsDomain = nic['adapter']['dnsDomain'] if nic['adapter'].key?('dnsDomain')
        custom_adapter.dnsServerList = nic['adapter']['dnsServerList'] if nic['adapter'].key?('dnsServerList')
        custom_adapter.gateway = nic['adapter']['gateway'] if nic['adapter'].key?('gateway')
        if nic['adapter'].key?('ipV6Spec')
          # https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.IPSettings.IpV6AddressSpec.html
          # Fields:
          #   * gateway: array of string
          #   * ip: CustomizationIpV6Generator[] **Required if setting static IP **
          if nic['adapter']['ipV6Spec'].key?('ipAddress')
            raise ArgumentError, 'SubnetMask is required when assigning static IPv6 when using nicSettingMap -> Adapter -> ipV6Spec' unless nic['adapter']['ipV6Spec'].key?('subnetMask')
            # https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.FixedIpV6.html
            #   * ipAddress: string **REQUIRED**
            #   * subnetMask: int **REQUIRED**
            custom_ipv6 = RbVmomi::VIM.CustomizationFixedIpV6(
              ipAddress: nic['adapter']['ipV6Spec']['ipAddress'],
              subnetMask: nic['adapter']['ipV6Spec']['subnetMask']
            )
          else
            custom_ipv6 = RbVmomi::VIM::CustomizationDhcpIpV6Generator.new
          end
          custom_ipv6Spec = RbVmomi::VIM.CustomizationIPSettingsIpV6AddressSpec(ip: custom_ipv6)
          custom_ipv6Spec.gateway = nic['adapter']['ipV6Spec']['gateway'] if nic['adapter']['ipV6Spec'].key?('gateway')
          custom_adapter.ipV6Spec = custom_ipv6Spec
        end
        if nic['adapter'].key?('netBIOS')
          # https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.IPSettings.NetBIOSMode.html
          # Fields:
          #   netBIOS: string matching: 'disableNetBIOS','enableNetBIOS' or 'enableNetBIOSViaDhcp' ** REQUIRED **
          #
          raise ArgumentError, "Unsupported NetBIOSMode, supported modes are : 'disableNetBIOS','enableNetBIOS' or 'enableNetBIOSViaDhcp'" unless %w[disableNetBIOS enableNetBIOS enableNetBIOSViaDhcp].include? nic['adapter']['netBIOS']
          custom_adapter.netBIOS = RbVmomi::VIM.CustomizationNetBIOSMode(nic['adapter']['netBIOS'])
        end
        custom_adapter.primaryWINS = nic['adapter']['primaryWINS'] if nic['adapter'].key?('primaryWINS')
        custom_adapter.secondaryWINS = nic['adapter']['secondaryWINS'] if nic['adapter'].key?('secondaryWINS')
        custom_adapter.subnetMask = nic['adapter']['subnetMask'] if nic['adapter'].key?('subnetMask')

        custom_adapter_mapping = RbVmomi::VIM::CustomizationAdapterMapping(adapter: custom_adapter)
        custom_adapter_mapping.macAddress = nic['macAddress'] if nic.key?('macAddress')

        # build the adapters array
        custom_nicSettingMap << custom_adapter_mapping
      end
    end

    if custom_spec.key?('options')
      # https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.Options.html
      # this currently doesn't have any Linux options, just windows
      # Fields:
      #   * changeSID: boolean **REQUIRED**
      #   * deleteAccounts: boolean **REQUIRED** **note deleteAccounts is deprecated as of VI API 2.5 so can be ignored
      #   * reboot: CustomizationSysprepRebootOption: (string) one of following 'noreboot', reboot' or 'shutdown' (defaults to reboot)
      raise ArgumentError, 'changeSID id required when using Windows Options' unless custom_spec['options'].key?('changeSID')
      raise ArgumentError, 'deleteAccounts id required when using Windows Options' unless custom_spec['options'].key?('deleteAccounts')
      custom_options = RbVmomi::VIM::CustomizationWinOptions(
        changeSID: custom_spec['options']['changeSID'],
        deleteAccounts: custom_spec['options']['deleteAccounts']
      )
      if custom_spec['options'].key?('reboot')
        raise ArgumentError, "Unsupported reboot option, supported options are : 'noreboot', 'reboot' or 'shutdown'" unless %w[noreboot reboot shutdown].include? custom_spec['options']['reboot']
        custom_options.reboot = RBVmomi::VIM.CustomizationSysprepRebootOption(custom_spec['options']['reboot'])
      end
    end
    custom_options ||= nil

    # https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.Specification.html
    customization_spec = RbVmomi::VIM::CustomizationSpec(
      globalIPSettings: custom_globalIPSettings,
      identity: custom_identity
    )
    customization_spec.encryptionKey = custom_encryptionKey if defined?(custom_encryptionKey)
    customization_spec.nicSettingMap = custom_nicSettingMap if defined?(custom_nicSettingMap)
    customization_spec.options = custom_options if defined?(custom_options)

  end
  customization_spec ||= nil

  relocation_spec = nil
  if options['linked_clone']
    # Storage DRS does not support vSphere linked clones.
    # http://www.vmware.com/files/pdf/techpaper/vsphere-storage-drs-interoperability.pdf
    raise ArgumentError, 'linked clones are not supported on storage pods' unless options.key?('storage_pod')
    # cribbed heavily from the rbvmomi clone_vm.rb
    # this chunk of code reconfigures the disk of the clone source to be read only,
    # and then creates a delta disk on top of that, this is required by the API in order to create
    # linked clondes
    disks = vm_mob_ref.config.hardware.device.select do |vm_device|
      vm_device.class == RbVmomi::VIM::VirtualDisk
    end
    disks.select { |vm_device| vm_device.backing.parent.nil? }.each do |disk|
      disk_spec = {
        deviceChange: [
          {
            operation: :remove,
            device: disk
          },
          {
            operation: :add,
            fileOperation: :create,
            device: disk.dup.tap do |disk_backing|
              disk_backing.backing = disk_backing.backing.dup
              disk_backing.backing.fileName = "[#{disk.backing.datastore.name}]"
              disk_backing.backing.parent = disk.backing
            end
          }
        ]
      }
      vm_mob_ref.ReconfigVM_Task(spec: disk_spec).wait_for_completion
    end
    # Next, create a Relocation Spec instance
    relocation_spec = RbVmomi::VIM.VirtualMachineRelocateSpec(datastore: datastore_obj,
                                                              pool: resource_pool,
                                                              host: host,
                                                              diskMoveType: :moveChildMostDiskBacking)
  else
    relocation_spec = RbVmomi::VIM.VirtualMachineRelocateSpec(pool: resource_pool,
                                                              host: host,
                                                              transform: options['transform'] || 'sparse')
    unless options.key?('storage_pod') && datastore_obj.nil?
      relocation_spec[:datastore] = datastore_obj
    end
  end
  # relocate templates is not supported by fog-vsphere when vm is cloned on a storage pod
  unless options.key?('storage_pod')
    unless options['volumes'].blank?
      relocation_spec[:disk] = relocate_template_volumes_specs(vm_mob_ref, options['volumes'], options['datacenter'])
    end
  end
  # And the clone specification
  clone_spec = RbVmomi::VIM.VirtualMachineCloneSpec(location: relocation_spec,
                                                    config: virtual_machine_config_spec,
                                                    customization: customization_spec,
                                                    powerOn: options.key?('power_on') ? options['power_on'] : true,
                                                    template: options.key?('template') ? options['template'] : false)

  # Perform the actual Clone Task
  # Clone VM on a storage pod
  if options.key?('storage_pod') && !options['storage_pod'].nil?
    raise ArgumentError, 'need to use at least vsphere revision 5.0 or greater to use storage pods' unless @vsphere_rev.to_f >= 5
    pod_spec = RbVmomi::VIM::StorageDrsPodSelectionSpec.new(
      storagePod: get_raw_storage_pod(options['storage_pod'], options['datacenter'])
    )
    storage_spec = RbVmomi::VIM::StoragePlacementSpec.new(
      type: 'clone',
      folder: dest_folder,
      resourcePool: resource_pool,
      podSelectionSpec: pod_spec,
      cloneSpec: clone_spec,
      cloneName: options['name'],
      vm: vm_mob_ref
    )
    srm = connection.serviceContent.storageResourceManager
    result = srm.RecommendDatastores(storageSpec: storage_spec)

    # if result array contains recommendation, we can apply it
    if key = result.recommendations.first.key
      task = srm.ApplyStorageDrsRecommendation_Task(key: [key])
      if options.fetch('wait', true)
        result = task.wait_for_completion
        new_vm = result.vm
      else
        new_vm = nil
        Fog.wait_for(150, 15) do
          begin
            (new_vm = dest_folder.find(options['name'], RbVmomi::VIM::VirtualMachine)) || raise(Fog::Vsphere::Errors::NotFound)
          rescue Fog::Vsphere::Errors::NotFound
            new_vm = nil
          end
        end
        raise Fog::Vsphere::Errors::NotFound unless new_vm
      end
    end
  else
    task = vm_mob_ref.CloneVM_Task(folder: dest_folder,
                                   name: options['name'],
                                   spec: clone_spec)
    # Waiting for the VM to complete allows us to get the VirtulMachine
    # object of the new machine when it's done.  It is HIGHLY recommended
    # to set 'wait' => true if your app wants to wait.  Otherwise, you're
    # going to have to reload the server model over and over which
    # generates a lot of time consuming API calls to vmware.
    if options.fetch('wait', true)
      # REVISIT: It would be awesome to call a block passed to this
      # request to notify the application how far along in the process we
      # are.  I'm thinking of updating a progress bar, etc...
      new_vm = task.wait_for_completion
    else
      new_vm = nil
      Fog.wait_for(150, 15) do
        begin
          (new_vm = dest_folder.find(options['name'], RbVmomi::VIM::VirtualMachine)) || raise(Fog::Vsphere::Errors::NotFound)
        rescue Fog::Vsphere::Errors::NotFound
          new_vm = nil
        end
      end
      raise Fog::Vsphere::Errors::NotFound unless new_vm
    end
  end

  # Return hash
  {
    'vm_ref'        => new_vm ? new_vm._ref : nil,
    'new_vm'        => new_vm ? convert_vm_mob_ref_to_attr_hash(new_vm) : nil,
    'task_ref'      => task._ref
  }
end
vm_config_vnc(options = {}) click to toggle source
# File lib/fog/vsphere/requests/compute/vm_config_vnc.rb, line 5
def vm_config_vnc(options = {})
  raise ArgumentError, 'instance_uuid is a required parameter' unless options.key? 'instance_uuid'

  search_filter = { :uuid => options['instance_uuid'], 'vmSearch' => true, 'instanceUuid' => true }
  vm_mob_ref    = connection.searchIndex.FindAllByUuid(search_filter).first
  task          = vm_mob_ref.ReconfigVM_Task(spec: {
                                               extraConfig: [
                                                 { key: 'RemoteDisplay.vnc.enabled',  value: options[:enabled] ? 'true' : 'false' },
                                                 { key: 'RemoteDisplay.vnc.password', value: options[:password].to_s },
                                                 { key: 'RemoteDisplay.vnc.port',     value: options[:port].to_s || '5910' }
                                               ]
                                             })
  task.wait_for_completion
  { 'task_state' => task.info.state }
end
vm_destroy(options = {}) click to toggle source
# File lib/fog/vsphere/requests/compute/vm_destroy.rb, line 5
def vm_destroy(options = {})
  raise ArgumentError, 'instance_uuid is a required parameter' unless options.key? 'instance_uuid'

  vm_mob_ref = get_vm_ref(options['instance_uuid'])
  task = vm_mob_ref.Destroy_Task
  task.wait_for_completion
  { 'task_state' => task.info.state }
end
vm_execute(options = {}) click to toggle source

NOTE: you must be using vsphere_rev 5.0 or greater to use this functionality e.g. Fog::Compute.new(provider: “vsphere”, vsphere_rev: “5.5”, etc)

  • options<~Hash>:

    • 'instance_uuid'<~String> - REQUIRED the instance uuid you would like to operate on

    • 'command'<~String> REQUIRED the command to execute

    • 'args'<~String> arguments to pass the command

    • 'working_dir'<~String> path to the working directory

    • 'user'<~String> REQUIRED the ssh username you would like to login as

    • 'password'<~String> REQUIRED the ssh password for the user you would like to log in as

# File lib/fog/vsphere/requests/compute/vm_execute.rb, line 14
def vm_execute(options = {})
  raise ArgumentError, 'instance_uuid is a required parameter' unless options.key? 'instance_uuid'
  raise ArgumentError, 'command is a required parameter' unless options.key? 'command'
  raise ArgumentError, 'user is a required parameter' unless options.key? 'user'
  raise ArgumentError, 'password is a required parameter' unless options.key? 'password'

  search_filter = { :uuid => options['instance_uuid'], 'vmSearch' => true, 'instanceUuid' => true }
  vm_mob_ref = connection.searchIndex.FindAllByUuid(search_filter).first

  auth = RbVmomi::VIM::NamePasswordAuthentication(interactiveSession: false,
                                                  username: options['user'],
                                                  password: options['password'])

  spec = RbVmomi::VIM::GuestProgramSpec(programPath: options['command'],
                                        arguments: options['args'],
                                        workingDirectory: options['working_dir'])

  gom = connection.serviceContent.guestOperationsManager
  gom.processManager.StartProgramInGuest(vm: vm_mob_ref, auth: auth, spec: spec)
end
vm_get_vnc(uuid) click to toggle source

return a hash of VNC attributes required to view the console

# File lib/fog/vsphere/requests/compute/vm_config_vnc.rb, line 22
def vm_get_vnc(uuid)
  search_filter = { :uuid => uuid, 'vmSearch' => true, 'instanceUuid' => true }
  vm = connection.searchIndex.FindAllByUuid(search_filter).first
  Hash[vm.config.extraConfig.map do |config|
    if config.key =~ /^RemoteDisplay\.vnc\.(\w+)$/
      [Regexp.last_match(1).to_sym, config.value]
    end
  end.compact]
end
vm_migrate(options = {}) click to toggle source
# File lib/fog/vsphere/requests/compute/vm_migrate.rb, line 5
def vm_migrate(options = {})
  # priority is the only required option, and it has a sane default option.
  priority = options['priority'].nil? ? 'defaultPriority' : options['priority']
  raise ArgumentError, 'instance_uuid is a required parameter' unless options.key? 'instance_uuid'

  # Find the VM Object
  search_filter = { :uuid => options['instance_uuid'], 'vmSearch' => true, 'instanceUuid' => true }
  vm_mob_ref = connection.searchIndex.FindAllByUuid(search_filter).first

  unless vm_mob_ref.is_a? RbVmomi::VIM::VirtualMachine
    raise Fog::Vsphere::Errors::NotFound,
          "Could not find VirtualMachine with instance uuid #{options['instance_uuid']}"
  end
  options['host'] = get_raw_host(options['host'], options['cluster'], options['datacenter']) if options['host']
  task_options = { pool: options['pool'], host: options['host'], state: options['state'] }
  if options['check']
    checker = connection.serviceContent.vmProvisioningChecker
    task = checker.CheckMigrate_Task(task_options.merge(vm: vm_mob_ref))
    task.wait_for_completion
    { 'error' => task.info.result[0].error, 'warning' => task.info.result[0].warning }
  else
    task = vm_mob_ref.MigrateVM_Task(task_options.merge(priority: priority.to_s))
    task.wait_for_completion
    { 'task_state' => task.info.state }
  end
end
vm_power_off(options = {}) click to toggle source
# File lib/fog/vsphere/requests/compute/vm_power_off.rb, line 5
def vm_power_off(options = {})
  options = { 'force' => false }.merge(options)
  raise ArgumentError, 'instance_uuid is a required parameter' unless options.key? 'instance_uuid'

  search_filter = { :uuid => options['instance_uuid'], 'vmSearch' => true, 'instanceUuid' => true }
  vm_mob_ref = connection.searchIndex.FindAllByUuid(search_filter).first

  if options['force']
    task = vm_mob_ref.PowerOffVM_Task
    task.wait_for_completion
    { 'task_state' => task.info.result, 'power_off_type' => 'cut_power' }
  else
    vm_mob_ref.ShutdownGuest
    {
      'task_state'     => 'running',
      'power_off_type' => 'shutdown_guest'
    }
  end
end
vm_power_on(options = {}) click to toggle source
# File lib/fog/vsphere/requests/compute/vm_power_on.rb, line 5
def vm_power_on(options = {})
  raise ArgumentError, 'instance_uuid is a required parameter' unless options.key? 'instance_uuid'

  search_filter = { :uuid => options['instance_uuid'], 'vmSearch' => true, 'instanceUuid' => true }
  vm_mob_ref = connection.searchIndex.FindAllByUuid(search_filter).first

  task = vm_mob_ref.PowerOnVM_Task
  task.wait_for_completion
  # 'success', 'running', 'queued', 'error'
  { 'task_state' => task.info.state }
end
vm_reboot(options = {}) click to toggle source
# File lib/fog/vsphere/requests/compute/vm_reboot.rb, line 5
def vm_reboot(options = {})
  options = { 'force' => false }.merge(options)
  raise ArgumentError, 'instance_uuid is a required parameter' unless options.key? 'instance_uuid'

  search_filter = { :uuid => options['instance_uuid'], 'vmSearch' => true, 'instanceUuid' => true }
  vm_mob_ref = connection.searchIndex.FindAllByUuid(search_filter).first

  if options['force']
    task = vm_mob_ref.ResetVM_Task
    task.wait_for_completion
    { 'task_state' => task.info.result, 'reboot_type' => 'reset_power' }
  else
    vm_mob_ref.RebootGuest
    { 'task_state' => 'running', 'reboot_type' => 'reboot_guest' }
  end
end
vm_reconfig_cdrom(options = {}) click to toggle source
# File lib/fog/vsphere/requests/compute/vm_reconfig_cdrom.rb, line 5
def vm_reconfig_cdrom(options = {})
  raise ArgumentError, 'instance_uuid is a required parameter' unless options.key? 'instance_uuid'
  # Attach iso / disattach
  if options.key?('iso')
    raise ArgumentError, 'datastore is a required parameter' unless options.key? 'datastore'
    backing = RbVmomi::VIM::VirtualCdromIsoBackingInfo(
      fileName: "[#{options['datastore']}] #{options['iso']}"
    )
  else
    backing = RbVmomi::VIM::VirtualCdromRemoteAtapiBackingInfo(deviceName: '')
  end
  cdrom_obj = get_vm_ref(options['instance_uuid']).config.hardware.device.grep(RbVmomi::VIM::VirtualCdrom).first
  hardware_spec = {
    deviceChange: [{
      operation: :edit,
      device: RbVmomi::VIM::VirtualCdrom(
        backing: backing,
        key: cdrom_obj.key,
        controllerKey: cdrom_obj.controllerKey,
        connectable: RbVmomi::VIM::VirtualDeviceConnectInfo(
          startConnected: options['start_connected'] || false,
          connected: options['connected'] || false,
          allowGuestControl: options['allow_guest_control'] || true
        )
      )
    }]
  }
  vm_reconfig_hardware('instance_uuid' => options['instance_uuid'], 'hardware_spec' => hardware_spec)
end
vm_reconfig_cpus(options = {}) click to toggle source
# File lib/fog/vsphere/requests/compute/vm_reconfig_cpus.rb, line 5
def vm_reconfig_cpus(options = {})
  raise ArgumentError, 'cpus is a required parameter' unless options.key? 'cpus'
  raise ArgumentError, 'instance_uuid is a required parameter' unless options.key? 'instance_uuid'
  hardware_spec = { 'numCPUs' => options['cpus'], 'numCoresPerSocket' => options['corespersocket'] }
  vm_reconfig_hardware('instance_uuid' => options['instance_uuid'], 'hardware_spec' => hardware_spec)
end
vm_reconfig_hardware(options = {}) click to toggle source
# File lib/fog/vsphere/requests/compute/vm_reconfig_hardware.rb, line 5
def vm_reconfig_hardware(options = {})
  raise ArgumentError, 'hardware_spec is a required parameter' unless options.key? 'hardware_spec'
  raise ArgumentError, 'instance_uuid is a required parameter' unless options.key? 'instance_uuid'
  vm_mob_ref = get_vm_ref(options['instance_uuid'])
  task = vm_mob_ref.ReconfigVM_Task(spec: RbVmomi::VIM.VirtualMachineConfigSpec(options['hardware_spec']))
  task.wait_for_completion
  { 'task_state' => task.info.state }
end
vm_reconfig_memory(options = {}) click to toggle source
# File lib/fog/vsphere/requests/compute/vm_reconfig_memory.rb, line 5
def vm_reconfig_memory(options = {})
  raise ArgumentError, 'memory is a required parameter' unless options.key? 'memory'
  raise ArgumentError, 'instance_uuid is a required parameter' unless options.key? 'instance_uuid'
  hardware_spec = { 'memoryMB' => options['memory'] }
  vm_reconfig_hardware('instance_uuid' => options['instance_uuid'], 'hardware_spec' => hardware_spec)
end
vm_reconfig_volumes(options = {}) click to toggle source
# File lib/fog/vsphere/requests/compute/vm_reconfig_volumes.rb, line 5
def vm_reconfig_volumes(options = {})
  raise ArgumentError, 'instance_uuid is a required parameter' unless options.key? 'instance_uuid'
  raise ArgumentError, 'volumes is a required parameter' unless options.key? 'volumes'
  hardware_spec = {
    deviceChange: []
  }
  options['volumes'].each do |volume|
    hardware_spec[:deviceChange].push(create_disk(volume, :edit, filename: volume.filename))
  end
  vm_reconfig_hardware('instance_uuid' => options['instance_uuid'], 'hardware_spec' => hardware_spec)
end
vm_relocate(options = {}) click to toggle source

Relocates a VM to different host or datastore.

Parameters

  • options<~Hash>:

    • 'instance_uuid'<~String> - REQUIRED VM to relocate

    • 'host'<~String> - name of host which will run the VM.

    • 'cluster'<~String> - name of cluster where host is.

      Only works with clusters within same datacenter as
      where vm is running. Defaults to vm's host's cluster.
    • 'datacenter'<~String> - name of datacenter where host is.

      It must be same datacenter as where vm is running.
      Defaults to vm's datacenter.
    • 'datastore'<~String> - name of datastore where VM will

      be located.
    • 'pool'<~String> - name of pool which the VM should be

      attached.
    • 'disks'<~Array> - disks to relocate. Each disk is a

      hash with diskId wich is key attribute of volume,
      and datastore to relocate to. diskBackingInfo can be provided,
      with type FlatVer2 or SeSparse
      Example: [{
        'diskId' => 2000,
        'datastore' => 'datastore_name',
        'diskBackingInfo' => {'type' => 'FlatVer2', ...}
      }]
# File lib/fog/vsphere/requests/compute/vm_relocate.rb, line 30
def vm_relocate(options = {})
  raise ArgumentError, 'instance_uuid is a required parameter' unless options.key? 'instance_uuid'

  # Find the VM Object
  search_filter = { :uuid => options['instance_uuid'], 'vmSearch' => true, 'instanceUuid' => true }
  vm_mob_ref = connection.searchIndex.FindAllByUuid(search_filter).first

  unless vm_mob_ref.is_a? RbVmomi::VIM::VirtualMachine
    raise Fog::Vsphere::Errors::NotFound,
          "Could not find VirtualMachine with instance uuid #{options['instance_uuid']}"
  end
  datacenter = options['datacenter'] || get_vm_datacenter(vm_mob_ref)
  cluster_name = options['cluster'] || get_vm_cluster(vm_mob_ref)

  options['host'] = get_raw_host(options['host'], cluster_name, datacenter) if options['host']
  options['datastore'] = get_raw_datastore(options['datastore'], datacenter) if options.key?('datastore')

  if options['disks']
    options['disks'] = options['disks'].map do |disk|
      disk['datastore'] = get_raw_datastore(disk['datastore'], datacenter)
      if disk['diskBackingInfo'] && disk['diskBackingInfo']['type']
        backing_type = "VirtualDisk#{disk['diskBackingInfo'].delete('type')}BackingInfo"
        disk['diskBackingInfo'] = RbVmomi::VIM.send(backing_type, disk['diskBackingInfo'])
      end
      RbVmomi::VIM::VirtualMachineRelocateSpecDiskLocator(disk)
    end
  end

  spec = RbVmomi::VIM::VirtualMachineRelocateSpec(
    datastore: options['datastore'],
    pool: options['pool'],
    host: options['host'],
    disk: options['disks']
  )
  task = vm_mob_ref.RelocateVM_Task(spec: spec, priority: options['priority'])
  task.wait_for_completion
  { 'task_state' => task.info.state }
end
vm_remove_snapshot(vm_id, snapshot_id, remove_children = false) click to toggle source
# File lib/fog/vsphere/requests/compute/vm_remove_snapshot.rb, line 5
def vm_remove_snapshot(vm_id, snapshot_id, remove_children = false)
  vm = servers.get(vm_id)
  snapshot = vm.snapshots.get(snapshot_id).mo_ref
  task = snapshot.RemoveSnapshot_Task(removeChildren: remove_children)

  task.wait_for_completion

  {
    'task_state' => task.info.state,
    'was_cancelled' => task.info.cancelled
  }
end
vm_rename(options = {}) click to toggle source
# File lib/fog/vsphere/requests/compute/vm_rename.rb, line 5
def vm_rename(options = {})
  raise ArgumentError, 'name is a required parameter' unless options.key? 'name'
  raise ArgumentError, 'instance_uuid is a required parameter' unless options.key? 'instance_uuid'
  vm_mob_ref = get_vm_ref(options['instance_uuid'])
  task = vm_mob_ref.Rename_Task(newName: options['name'])
  task.wait_for_completion
  { 'task_state' => task.info.state }
end
vm_revert_snapshot(vm_id, snapshot_id) click to toggle source
# File lib/fog/vsphere/requests/compute/vm_revert_snapshot.rb, line 5
def vm_revert_snapshot(vm_id, snapshot_id)
  vm = servers.get(vm_id)
  snapshot = vm.snapshots.get(snapshot_id).mo_ref
  task = snapshot.RevertToSnapshot_Task

  task.wait_for_completion

  {
    'task_state' => task.info.state,
    'was_cancelled' => task.info.cancelled
  }
end
vm_suspend(options = {}) click to toggle source
# File lib/fog/vsphere/requests/compute/vm_suspend.rb, line 5
def vm_suspend(options = {})
  raise(ArgumentError, 'instance_uuid is a required parameter') unless options.key?('instance_uuid')
  options = { 'force' => false }.merge(options)

  search_filter = { :uuid => options['instance_uuid'], 'vmSearch' => true, 'instanceUuid' => true }
  vm = connection.searchIndex.FindAllByUuid(search_filter).first

  if options['force']
    suspend_forcefully(vm)
  else
    suspend_gracefully(vm)
  end
end
vm_take_snapshot(options = {}) click to toggle source
# File lib/fog/vsphere/requests/compute/vm_take_snapshot.rb, line 5
def vm_take_snapshot(options = {})
  raise ArgumentError, 'instance_uuid is a required parameter' unless options.key? 'instance_uuid'
  raise ArgumentError, 'name is a required parameter' unless options.key? 'name'
  vm = get_vm_ref(options['instance_uuid'])
  task = vm.CreateSnapshot_Task(
    name: options['name'],
    description: options['description'] || '',
    memory: options['memory'] || true,
    quiesce: options['quiesce'] || false
  )

  task.wait_for_completion

  {
    'task_state' => task.info.state,
    'was_cancelled' => task.info.cancelled
  }
end

Protected Instance Methods

child_folders(folder) click to toggle source
# File lib/fog/vsphere/requests/compute/list_folders.rb, line 155
def child_folders(folder)
  [folder, folder.childEntity.grep(RbVmomi::VIM::Folder).map(&method(:child_folders)).flatten]
end
child_snapshot_info(snap_tree, parent_snap) click to toggle source
# File lib/fog/vsphere/requests/compute/list_child_snapshots.rb, line 22
def child_snapshot_info(snap_tree, parent_snap)
  {
    name: snap_tree.name,
    quiesced: snap_tree.quiesced,
    description: snap_tree.description,
    create_time: snap_tree.createTime,
    power_state: snap_tree.state,
    ref: snap_tree.snapshot._ref,
    mo_ref: snap_tree.snapshot,
    tree_node: snap_tree,
    snapshot_name_chain:               "#{parent_snap.snapshot_name_chain}/#{snap_tree.name}",
    ref_chain:               "#{parent_snap.ref_chain}/#{snap_tree.snapshot._ref}",
    server_id: parent_snap.server_id
  }
end
cluster_attributes(cluster, datacenter_name) click to toggle source
# File lib/fog/vsphere/requests/compute/list_clusters.rb, line 33
def cluster_attributes(cluster, datacenter_name)
  {
    id: managed_obj_id(cluster),
    name: cluster.name,
    full_path: cluster_path(cluster, datacenter_name),
    num_host: cluster.summary.numHosts,
    num_cpu_cores: cluster.summary.numCpuCores,
    overall_status: cluster.summary.overallStatus,
    datacenter: datacenter_name || parent_attribute(cluster.path, :datacenter)[1]
  }
end
cluster_path(cluster, datacenter_name) click to toggle source
# File lib/fog/vsphere/requests/compute/list_clusters.rb, line 45
def cluster_path(cluster, datacenter_name)
  datacenter = find_raw_datacenter(datacenter_name)
  cluster.pretty_path.gsub(%r{(^#{Regexp.escape(datacenter_name)}|#{Regexp.escape(datacenter.hostFolder.name)})\/}, '')
end
compute_resource_attributes(compute_resource, _datacenter) click to toggle source
# File lib/fog/vsphere/requests/compute/list_compute_resources.rb, line 25
def compute_resource_attributes(compute_resource, _datacenter)
  overall_usage = compute_resource.host.inject(overallCpuUsage: 0, overallMemoryUsage: 0) do |sum, host|
    {
      overallCpuUsage: sum[:overallCpuUsage] + (host.summary.quickStats.overallCpuUsage || 0),
      overallMemoryUsage: sum[:overallMemoryUsage] + (host.summary.quickStats.overallMemoryUsage || 0)
    }
  end
  {
    id: managed_obj_id(compute_resource),
    name: compute_resource.name,
    totalCpu: compute_resource.summary.totalCpu,
    totalMemory: compute_resource.summary.totalMemory,
    numCpuCores: compute_resource.summary.numCpuCores,
    numCpuThreads: compute_resource.summary.numCpuThreads,
    effectiveCpu: compute_resource.summary.effectiveCpu,
    effectiveMemory: compute_resource.summary.effectiveMemory,
    numHosts: compute_resource.summary.numHosts,
    numEffectiveHosts: compute_resource.summary.numEffectiveHosts,
    overallStatus: compute_resource.summary.overallStatus,
    overallCpuUsage: overall_usage[:overallCpuUsage],
    overallMemoryUsage: overall_usage[:overallMemoryUsage],
    effective: compute_resource.summary.numEffectiveHosts > 0,
    isSingleHost: compute_resource.summary.numHosts == 1
  }
end
compute_resource_datastore_traversal_spec() click to toggle source
# File lib/fog/vsphere/requests/compute/list_datastores.rb, line 63
def compute_resource_datastore_traversal_spec
  RbVmomi::VIM.TraversalSpec(
    name: 'computeResourceDatastoreTraversalSpec',
    type: 'ComputeResource',
    path: 'datastore',
    skip: false
  )
end
compute_resource_host_traversal_spec() click to toggle source
# File lib/fog/vsphere/requests/compute/list_hosts.rb, line 52
def compute_resource_host_traversal_spec
  RbVmomi::VIM.TraversalSpec(
    name: 'computeResourceHostTraversalSpec',
    type: 'ComputeResource',
    path: 'host',
    skip: false
  )
end
datacenter_to_vm_folder_traversal_spec() click to toggle source
# File lib/fog/vsphere/requests/compute/list_folders.rb, line 92
def datacenter_to_vm_folder_traversal_spec
  RbVmomi::VIM.TraversalSpec(
    name: 'DatacenterToVmFolderTraversalSpec',
    type: 'Datacenter',
    path: 'vmFolder',
    skip: false,
    selectSet: [
      RbVmomi::VIM.SelectionSpec(name: 'dcFolderTraversalSpec')
    ]
  )
end
datastore_attribute_mapping() click to toggle source
# File lib/fog/vsphere/requests/compute/list_datastores.rb, line 72
def datastore_attribute_mapping
  {
    name: 'summary.name',
    accessible: 'summary.accessible',
    type: 'summary.type',
    freespace: 'summary.freeSpace',
    capacity: 'summary.capacity',
    uncommitted: 'summary.uncommitted'
  }
end
datastore_cluster_filter_spec(obj) click to toggle source
# File lib/fog/vsphere/requests/compute/list_datastores.rb, line 44
def datastore_cluster_filter_spec(obj)
  RbVmomi::VIM.PropertyFilterSpec(
    objectSet: [
      obj: obj,
      skip: true,
      selectSet: [
        compute_resource_datastore_traversal_spec
      ]
    ],
    propSet: datastore_filter_prop_set
  )
end
datastore_filter_prop_set() click to toggle source
# File lib/fog/vsphere/requests/compute/list_datastores.rb, line 57
def datastore_filter_prop_set
  [
    { type: 'Datastore', pathSet: datastore_attribute_mapping.values }
  ]
end
datastore_filter_spec(obj) click to toggle source
# File lib/fog/vsphere/requests/compute/list_datastores.rb, line 31
def datastore_filter_spec(obj)
  RbVmomi::VIM.PropertyFilterSpec(
    objectSet: [
      obj: obj.datastoreFolder,
      skip: true,
      selectSet: [
        folder_traversal_spec
      ]
    ],
    propSet: datastore_filter_prop_set
  )
end
dc_folder_traversal_spec() click to toggle source
# File lib/fog/vsphere/requests/compute/list_folders.rb, line 79
def dc_folder_traversal_spec
  RbVmomi::VIM.TraversalSpec(
    name: 'dcFolderTraversalSpec',
    type: 'Folder',
    path: 'childEntity',
    skip: false,
    selectSet: [
      RbVmomi::VIM.SelectionSpec(name: 'dcFolderTraversalSpec'),
      RbVmomi::VIM.SelectionSpec(name: 'DatacenterToVmFolderTraversalSpec')
    ]
  )
end
find_datacenters(name = nil) click to toggle source
# File lib/fog/vsphere/requests/compute/list_datacenters.rb, line 41
def find_datacenters(name = nil)
  name ? [find_raw_datacenter(name)] : raw_datacenters
end
find_raw_datacenter(name) click to toggle source
# File lib/fog/vsphere/requests/compute/get_datacenter.rb, line 13
def find_raw_datacenter(name)
  raw_datacenters.find { |d| d.name == name } || get_raw_datacenter(name)
end
folder_attribute_mapping() click to toggle source
# File lib/fog/vsphere/requests/compute/list_folders.rb, line 128
def folder_attribute_mapping
  {
    name: 'name'
  }
end
folder_attributes(folder, datacenter_name) click to toggle source
# File lib/fog/vsphere/requests/compute/get_folder.rb, line 52
def folder_attributes(folder, datacenter_name)
  {
    id: managed_obj_id(folder),
    name: folder.name,
    parent: folder.parent.name,
    datacenter: datacenter_name,
    type: folder_type(folder.childType),
    path: folder_path(folder)
  }
end
folder_filter_spec(root_folder) click to toggle source
# File lib/fog/vsphere/requests/compute/list_folders.rb, line 62
def folder_filter_spec(root_folder)
  RbVmomi::VIM.PropertyFilterSpec(
    objectSet: [
      obj: root_folder,
      skip: false,
      selectSet: [
        dc_folder_traversal_spec,
        datacenter_to_vm_folder_traversal_spec
      ]
    ],
    propSet: [
      { type: 'Folder', pathSet: folder_attribute_mapping.values + %w[parent childType] },
      { type: 'Datacenter', pathSet: %w[name parent] }
    ]
  )
end
folder_path(folder) click to toggle source
# File lib/fog/vsphere/requests/compute/get_folder.rb, line 63
def folder_path(folder)
  '/' + folder.path.map(&:last).join('/')
end
folder_traversal_spec() click to toggle source
# File lib/fog/vsphere/requests/compute/list_networks.rb, line 58
def folder_traversal_spec
  RbVmomi::VIM.TraversalSpec(
    name: 'FolderTraversalSpec',
    type: 'Folder',
    path: 'childEntity',
    skip: false,
    selectSet: [
      RbVmomi::VIM.SelectionSpec(name: 'FolderTraversalSpec')
    ]
  )
end
folder_type(types) click to toggle source
# File lib/fog/vsphere/requests/compute/get_folder.rb, line 67
def folder_type(types)
  return :vm        if types.include?('VirtualMachine')
  return :network   if types.include?('Network')
  return :datastore if types.include?('Datastore')
  return :host      if types.include?('ComputeResource')
end
generate_folder_inventory(folders) click to toggle source
# File lib/fog/vsphere/requests/compute/list_folders.rb, line 134
def generate_folder_inventory(folders)
  folder_inventory = folders.each_with_object({}) do |folder, inventory|
    parent = if folder['parent'].nil?
               nil
             else
               folder['parent']._ref
             end
    inventory[folder.obj._ref] = {
      name: folder['name'],
      parent: parent
    }
  end
  set_folder_paths(folder_inventory)
  folder_inventory
end
get_raw_cluster(name, datacenter_name_or_obj) click to toggle source
# File lib/fog/vsphere/requests/compute/get_cluster.rb, line 13
def get_raw_cluster(name, datacenter_name_or_obj)
  dc = if datacenter_name_or_obj.is_a?(String)
         find_raw_datacenter(datacenter_name_or_obj)
       else
         datacenter_name_or_obj
       end
  dc.find_compute_resource(name)
end
get_raw_clusters_from_folder(folder) click to toggle source
# File lib/fog/vsphere/requests/compute/list_clusters.rb, line 23
def get_raw_clusters_from_folder(folder)
  folder.childEntity.map do |child_entity|
    if child_entity.is_a? RbVmomi::VIM::ComputeResource
      child_entity
    elsif child_entity.is_a? RbVmomi::VIM::Folder
      get_raw_clusters_from_folder(child_entity)
    end
  end.flatten
end
get_raw_compute_resource(name, datacenter_name) click to toggle source
# File lib/fog/vsphere/requests/compute/get_compute_resource.rb, line 13
def get_raw_compute_resource(name, datacenter_name)
  find_raw_datacenter(datacenter_name).find_compute_resource(name)
end
get_raw_datacenter(path) click to toggle source

@note RbVmomi takes path instead of name as argument to find datacenter

# File lib/fog/vsphere/requests/compute/get_datacenter.rb, line 18
def get_raw_datacenter(path)
  connection.serviceInstance.find_datacenter(path)
end
get_raw_datacenters_from_folder(folder = nil) click to toggle source
# File lib/fog/vsphere/requests/compute/list_datacenters.rb, line 31
def get_raw_datacenters_from_folder(folder = nil)
  folder.childEntity.map do |childE|
    if childE.is_a? RbVmomi::VIM::Datacenter
      childE
    elsif childE.is_a? RbVmomi::VIM::Folder
      get_raw_datacenters_from_folder childE
    end
  end.flatten
end
get_raw_datastore(name, datacenter_name) click to toggle source
# File lib/fog/vsphere/requests/compute/get_datastore.rb, line 13
def get_raw_datastore(name, datacenter_name)
  get_raw_datastores(datacenter_name).detect { |ds| ds.name == name }
end
get_raw_datastores(datacenter_name) click to toggle source
# File lib/fog/vsphere/requests/compute/get_datastore.rb, line 17
def get_raw_datastores(datacenter_name)
  list_container_view(datacenter_name, 'Datastore', :datastoreFolder)
end
get_raw_folder(path, datacenter_name_or_obj, type) click to toggle source
# File lib/fog/vsphere/requests/compute/get_folder.rb, line 15
def get_raw_folder(path, datacenter_name_or_obj, type)
  # The required path syntax - 'topfolder/subfolder

  # Clean up path to be relative since we're providing datacenter name
  dc = if datacenter_name_or_obj.is_a?(String)
         find_raw_datacenter(datacenter_name_or_obj)
       else
         datacenter_name_or_obj
       end

  valid_types = %w[vm network datastore host]
  raise ArgumentError, "#{type} is unknown" if type.nil? || type.empty?
  raise "Invalid type (#{type}). Must be one of #{valid_types.join(', ')} " unless valid_types.include?(type.to_s)
  meth = "#{type}Folder"
  dc_root_folder = dc.send(meth)

  # Filter the root path for this datacenter not to be used."
  dc_root_folder_path = dc_root_folder.path.map { |_, name| name }.join('/')
  paths = path.sub(/^\/?#{Regexp.quote(dc_root_folder_path)}\/?/, '').split('/')

  return dc_root_folder if paths.empty?
  # Walk the tree resetting the folder pointer as we go
  paths.reduce(dc_root_folder) do |last_returned_folder, sub_folder|
    # JJM VIM::Folder#find appears to be quite efficient as it uses the
    # searchIndex It certainly appears to be faster than
    # VIM::Folder#inventory since that returns _all_ managed objects of
    # a certain type _and_ their properties.
    sub = last_returned_folder.find(sub_folder, RbVmomi::VIM::Folder)
    raise Fog::Vsphere::Compute::NotFound, "Could not descend into #{sub_folder}.  Please check your path. #{path}" unless sub
    sub
  end
end
get_raw_host(name, cluster_name, datacenter_name) click to toggle source
# File lib/fog/vsphere/requests/compute/get_host.rb, line 11
def get_raw_host(name, cluster_name, datacenter_name)
  cluster = get_raw_cluster(cluster_name, datacenter_name)
  cluster.host.find { |host| host.name == name } ||
    raise(Fog::Vsphere::Compute::NotFound, "no such host #{name}")
end
get_raw_network(name, datacenter_name, distributedswitch = nil) click to toggle source
# File lib/fog/vsphere/requests/compute/get_network.rb, line 13
def get_raw_network(name, datacenter_name, distributedswitch = nil)
  finder = choose_finder(name, distributedswitch)
  get_all_raw_networks(datacenter_name).find { |n| finder.call(n) }
end
get_raw_resource_pool(name, cluster_name, datacenter_name) click to toggle source
# File lib/fog/vsphere/requests/compute/get_resource_pool.rb, line 13
def get_raw_resource_pool(name, cluster_name, datacenter_name)
  dc      = find_raw_datacenter(datacenter_name)
  cluster = dc.find_compute_resource(cluster_name)
  name.nil? ? cluster.resourcePool : cluster.resourcePool.traverse(name)
end
get_raw_server_type(id, datacenter, _filter = {}) click to toggle source
# File lib/fog/vsphere/requests/compute/get_server_type.rb, line 13
def get_raw_server_type(id, datacenter, _filter = {})
  types = raw_server_types(datacenter)
  raise(Fog::Vsphere::Compute::NotFound) unless types
  types = types.select { |servertype| servertype.id == id }.first
  raise(Fog::Vsphere::Compute::NotFound) unless types
  types
end
get_raw_storage_pod(name, datacenter_name) click to toggle source
# File lib/fog/vsphere/requests/compute/get_storage_pod.rb, line 13
def get_raw_storage_pod(name, datacenter_name)
  raw_storage_pods(datacenter_name).detect { |pod| pod.name == name }
end
get_raw_vmfolder(path, datacenter_name) click to toggle source
# File lib/fog/vsphere/requests/compute/get_folder.rb, line 48
def get_raw_vmfolder(path, datacenter_name)
  get_raw_folder(path, datacenter_name, 'vm')
end
get_raw_vmfolders(path, datacenter_name) click to toggle source
# File lib/fog/vsphere/requests/compute/list_folders.rb, line 150
def get_raw_vmfolders(path, datacenter_name)
  folder = get_raw_vmfolder(path, datacenter_name)
  child_folders(folder).flatten.compact
end
get_vm_by_name(name, dc, folder, recursive) click to toggle source
# File lib/fog/vsphere/requests/compute/get_virtual_machine.rb, line 31
def get_vm_by_name(name, dc, folder, recursive)
  vms = if folder
          # This returns an Enumerator, which when called with .find will
          # search only until it finds the VM we're looking for
          raw_list_all_virtual_machines_in_folder(folder, dc, recursive)
        else
          raw_list_all_virtual_machines(dc)
        end

  if name.include?('/')
    folder = File.dirname(name)
    basename = File.basename(name)
    vms.find do |v|
      begin
        v['name'] == basename && v.parent.pretty_path.include?(folder)
      rescue RbVmomi::VIM::ManagedObjectNotFound
        false
      end
    end
  else
    vms.find do |v|
      begin
        v['name'] == name
      rescue RbVmomi::VIM::ManagedObjectNotFound
        false
      end
    end
  end
end
get_vm_ref(id, dc = nil, folder = nil, recursive = false) click to toggle source
# File lib/fog/vsphere/requests/compute/get_virtual_machine.rb, line 12
def get_vm_ref(id, dc = nil, folder = nil, recursive = false)
  raw_datacenter = find_raw_datacenter(dc) if dc
  vm = case is_uuid?(id)
         # UUID based
       when true
         params = { uuid: id, vmSearch: true, instanceUuid: true }
         params[:datacenter] = raw_datacenter if dc
         connection.searchIndex.FindByUuid(params)
       else
         # try to find based on VM name
         if dc
           get_vm_by_name(id, dc, folder, recursive)
         else
           raw_datacenters.map { |d| get_vm_by_name(id, d['name'], folder, recursive) }.compact.first
         end
       end
  vm ? vm : raise(Fog::Vsphere::Compute::NotFound, "#{id} was not found")
end
group_attributes(group, filters) click to toggle source
# File lib/fog/vsphere/requests/compute/list_groups.rb, line 12
def group_attributes(group, filters)
  attributes = {}
  attributes[:datacenter] = filters[:datacenter]
  attributes[:cluster] = filters[:cluster]
  attributes[:name] = group[:name]
  attributes[:type] = group.class
  if group.class.to_s == 'ClusterVmGroup' then attributes[:vm_ids] = group[:vm].map { |vm| vm.config.instanceUuid } end
  if group.class.to_s == 'ClusterHostGroup' then attributes[:hosts] = group[:host].map(&:name) end
  attributes
end
host_system_attribute_mapping() click to toggle source
# File lib/fog/vsphere/requests/compute/list_hosts.rb, line 75
def host_system_attribute_mapping
  {
    name:            'name',
    cpu_cores:       'hardware.cpuInfo.numCpuCores',
    cpu_sockets:     'hardware.cpuInfo.numCpuPackages',
    cpu_threads:     'hardware.cpuInfo.numCpuThreads',
    cpu_hz:          'hardware.cpuInfo.hz',
    memory:          'hardware.memorySize',
    uuid:            'hardware.systemInfo.uuid',
    model:           'hardware.systemInfo.model',
    vendor:          'hardware.systemInfo.vendor',
    product_name:    'summary.config.product.name',
    product_version: 'summary.config.product.version',
    hostname:        'config.network.dnsConfig.hostName',
    domainname:      'config.network.dnsConfig.domainName'
  }
end
host_system_filter_spec(obj) click to toggle source
# File lib/fog/vsphere/requests/compute/list_hosts.rb, line 61
def host_system_filter_spec(obj)
  RbVmomi::VIM.PropertyFilterSpec(
    objectSet: [
      obj: obj,
      selectSet: [
        compute_resource_host_traversal_spec
      ]
    ],
    propSet: [
      { type: 'HostSystem', pathSet: host_system_attribute_mapping.values + ['config.network.vnic', 'vm'] }
    ]
  )
end
list_raw_resource_pools(cluster) click to toggle source

root ResourcePool + Children if they exists

# File lib/fog/vsphere/requests/compute/list_resource_pools.rb, line 17
def list_raw_resource_pools(cluster)
  pools = []
  traverse_raw_resource_pools(pools, cluster.resourcePool)
  pools.uniq
end
lookup_folder_name(inventory, folder_id) click to toggle source
# File lib/fog/vsphere/requests/compute/list_folders.rb, line 104
def lookup_folder_name(inventory, folder_id)
  folder = inventory[folder_id]
  return '' unless folder
  folder[:name]
end
lookup_folder_path(inventory, folder_id) click to toggle source
# File lib/fog/vsphere/requests/compute/list_folders.rb, line 110
def lookup_folder_path(inventory, folder_id)
  folder = inventory[folder_id]
  return '' unless folder
  folder[:path]
end
lookup_parent_folders(folder_inventory, ref) click to toggle source
# File lib/fog/vsphere/requests/compute/list_folders.rb, line 122
def lookup_parent_folders(folder_inventory, ref)
  return [] unless folder_inventory[ref]
  return [folder_inventory[ref][:name]] if folder_inventory[ref][:parent].nil?
  [folder_inventory[ref][:name], lookup_parent_folders(folder_inventory, folder_inventory[ref][:parent])].flatten
end
map_attrs_to_hash(obj, attribute_mapping) click to toggle source
# File lib/fog/vsphere/requests/compute/list_hosts.rb, line 41
def map_attrs_to_hash(obj, attribute_mapping)
  attribute_mapping.each_with_object({}) do |(k, v), hsh|
    hsh[k] = obj[v]
  end
end
network_attribute_mapping() click to toggle source
# File lib/fog/vsphere/requests/compute/list_networks.rb, line 45
def network_attribute_mapping
  {
    name: 'name',
    accessible: 'summary.accessible'
  }
end
network_dvportgroup_attribute_mapping() click to toggle source
# File lib/fog/vsphere/requests/compute/list_networks.rb, line 52
def network_dvportgroup_attribute_mapping
  network_attribute_mapping.merge(
    id: 'config.key'
  )
end
network_filter_spec(obj) click to toggle source
# File lib/fog/vsphere/requests/compute/list_networks.rb, line 70
def network_filter_spec(obj)
  RbVmomi::VIM.PropertyFilterSpec(
    objectSet: [
      obj: obj.networkFolder,
      skip: true,
      selectSet: [
        folder_traversal_spec
      ]
    ],
    propSet: [
      { type: 'DistributedVirtualSwitch', pathSet: ['summary.name'] },
      { type: 'Network', pathSet: network_attribute_mapping.values },
      { type: 'DistributedVirtualPortgroup', pathSet: network_dvportgroup_attribute_mapping.values + ['config.defaultPortConfig', 'config.distributedVirtualSwitch'] }
    ]
  )
end
property_collector_results(filter_spec) click to toggle source
# File lib/fog/vsphere/requests/compute/list_hosts.rb, line 47
def property_collector_results(filter_spec)
  property_collector = connection.serviceContent.propertyCollector
  property_collector.RetrieveProperties(specSet: [filter_spec])
end
raw_datacenters(folder = nil) click to toggle source
# File lib/fog/vsphere/requests/compute/list_datacenters.rb, line 26
def raw_datacenters(folder = nil)
  folder ||= connection.rootFolder
  @raw_datacenters ||= get_raw_datacenters_from_folder folder
end
raw_getpathmo(mo) click to toggle source
# File lib/fog/vsphere/requests/compute/list_datacenters.rb, line 18
def raw_getpathmo(mo)
  if mo.parent.nil? || (mo.parent.name == connection.rootFolder.name)
    [mo.name]
  else
    [raw_getpathmo(mo.parent), mo.name].flatten
  end
end
raw_storage_pods(datacenter_name) click to toggle source
# File lib/fog/vsphere/requests/compute/get_storage_pod.rb, line 17
def raw_storage_pods(datacenter_name)
  list_container_view(datacenter_name, 'StoragePod')
end
resource_pool_attributes(resource_pool, cluster, datacenter) click to toggle source
# File lib/fog/vsphere/requests/compute/list_resource_pools.rb, line 38
def resource_pool_attributes(resource_pool, cluster, datacenter)
  name = folder_path(resource_pool).gsub(/^.*Resources(\/|)/, '')
  name = 'Resources' if name.empty?
  {
    id: managed_obj_id(resource_pool),
    name: name,
    configured_memory_mb: resource_pool.summary.configuredMemoryMB,
    overall_status: resource_pool.overallStatus,
    cluster: cluster,
    datacenter: datacenter
  }
end
rule_attributes(rule, filters) click to toggle source
# File lib/fog/vsphere/requests/compute/list_rules.rb, line 12
def rule_attributes(rule, filters)
  attributes = {}
  attributes[:datacenter] = filters[:datacenter]
  attributes[:cluster] = filters[:cluster]
  attributes[:key] = rule[:key]
  attributes[:name] = rule[:name]
  attributes[:enabled] = rule[:enabled]
  attributes[:type] = rule.class
  if rule.class.to_s == 'ClusterAntiAffinityRuleSpec' || rule.class.to_s == 'ClusterAffinityRuleSpec'
    attributes[:vm_ids] = rule[:vm].map { |vm| vm.config.instanceUuid }
  elsif rule.class.to_s == 'ClusterVmHostRuleInfo'
    attributes[:mandatory] = rule[:mandatory]
    attributes[:vmGroupName] = rule[:vmGroupName]
    attributes[:affineHostGroupName] = rule[:affineHostGroupName]
  end
  attributes
end
server_type_attributes(servertype, datacenter) click to toggle source
# File lib/fog/vsphere/requests/compute/list_server_types.rb, line 26
def server_type_attributes(servertype, datacenter)
  {
    id: servertype.id,
    name: servertype.id,
    family: servertype.family,
    fullname: servertype.fullName,
    datacenter: datacenter
  }
end
set_folder_paths(folder_inventory) click to toggle source
# File lib/fog/vsphere/requests/compute/list_folders.rb, line 116
def set_folder_paths(folder_inventory) # rubocop:disable Naming/AccessorMethodName
  folder_inventory.each do |ref, props|
    props[:path] = ['', lookup_parent_folders(folder_inventory, ref).reverse].flatten
  end
end
snapshot_info(snap_tree, vm_id) click to toggle source
# File lib/fog/vsphere/requests/compute/list_vm_snapshots.rb, line 23
def snapshot_info(snap_tree, vm_id)
  {
    name: snap_tree.name,
    quiesced: snap_tree.quiesced,
    description: snap_tree.description,
    create_time: snap_tree.createTime,
    power_state: snap_tree.state,
    ref: snap_tree.snapshot._ref,
    mo_ref: snap_tree.snapshot,
    tree_node: snap_tree,
    ref_chain: "#{vm_id}/#{snap_tree.snapshot._ref}",
    snapshot_name_chain: "#{vm_id}/#{snap_tree.name}",
    server_id: vm_id
  }
end
storage_pod_attribute_mapping() click to toggle source
# File lib/fog/vsphere/requests/compute/list_storage_pods.rb, line 41
def storage_pod_attribute_mapping
  {
    name: 'name',
    freespace: 'summary.freeSpace',
    capacity: 'summary.capacity'
  }
end
storage_pod_filter_prop_set() click to toggle source
# File lib/fog/vsphere/requests/compute/list_storage_pods.rb, line 35
def storage_pod_filter_prop_set
  [
    { type: 'StoragePod', pathSet: storage_pod_attribute_mapping.values }
  ]
end
storage_pod_filter_spec(obj) click to toggle source
# File lib/fog/vsphere/requests/compute/list_storage_pods.rb, line 22
def storage_pod_filter_spec(obj)
  RbVmomi::VIM.PropertyFilterSpec(
    objectSet: [
      obj: obj.datastoreFolder,
      skip: true,
      selectSet: [
        folder_traversal_spec
      ]
    ],
    propSet: storage_pod_filter_prop_set
  )
end
traverse_raw_resource_pools(pools, rp) click to toggle source
# File lib/fog/vsphere/requests/compute/list_resource_pools.rb, line 23
def traverse_raw_resource_pools(pools, rp)
  if rp
    if rp.respond_to? :resourcePool
      traverse_raw_resource_pools(pools, rp.resourcePool)
    end
    if rp.respond_to? :each
      rp.each do |resourcePool|
        traverse_raw_resource_pools(pools, resourcePool)
      end
    else
      pools << rp
    end
  end
end

Private Instance Methods

apply_options_to_raw_interface(raw_interface, options) click to toggle source
# File lib/fog/vsphere/requests/compute/modify_vm_interface.rb, line 62
def apply_options_to_raw_interface(raw_interface, options)
  if options[:connectable]
    options[:connectable].each do |key, value|
      raw_interface.connectable.send("#{key}=", value)
    end
  end
  raw_interface
end
authenticate() click to toggle source
# File lib/fog/vsphere/compute.rb, line 687
def authenticate
  @connection.serviceContent.sessionManager.Login userName: @vsphere_username,
                                                  password: @vsphere_password
rescue RbVmomi::VIM::InvalidLogin => e
  raise Fog::Vsphere::Errors::ServiceError, e.message
end
boot_options(attributes, vm_cfg) click to toggle source
# File lib/fog/vsphere/requests/compute/create_vm.rb, line 112
def boot_options(attributes, vm_cfg)
  # NOTE: you must be using vsphere_rev 5.0 or greater to set boot_order
  # e.g. Fog::Compute.new(provider: "vsphere", vsphere_rev: "5.5", etc)
  options = {}
  if (@vsphere_rev.to_f >= 5) && attributes[:boot_order]
    options[:bootOrder] = boot_order(attributes, vm_cfg)
  end

  # Set attributes[:boot_retry] to a delay in miliseconds to enable boot retries
  if attributes[:boot_retry]
    options[:bootRetryEnabled] = true
    options[:bootRetryDelay]   = attributes[:boot_retry]
  end

  options.empty? ? nil : RbVmomi::VIM::VirtualMachineBootOptions.new(options)
end
boot_order(attributes, vm_cfg) click to toggle source
# File lib/fog/vsphere/requests/compute/create_vm.rb, line 129
def boot_order(attributes, vm_cfg)
  # attributes[:boot_order] may be an array like this ['network', 'disk']
  # stating, that we want to prefer network boots over disk boots
  boot_order = []
  attributes[:boot_order].each do |boot_device|
    case boot_device
    when 'network'
      if nics = attributes[:interfaces]
        # key is based on 4000 + the interface index
        # we allow booting from all network interfaces, the first interface has the highest priority
        nics.each do |nic|
          boot_order << RbVmomi::VIM::VirtualMachineBootOptionsBootableEthernetDevice.new(
            deviceKey: 4000 + nics.index(nic)
          )
        end
      end
    when 'disk'
      disks = vm_cfg[:deviceChange].map { |dev| dev[:device] }.select { |dev| dev.is_a? RbVmomi::VIM::VirtualDisk }
      disks.each do |disk|
        # we allow booting from all harddisks, the first disk has the highest priority
        boot_order << RbVmomi::VIM::VirtualMachineBootOptionsBootableDiskDevice.new(
          deviceKey: disk.key
        )
      end
    when 'cdrom'
      boot_order << RbVmomi::VIM::VirtualMachineBootOptionsBootableCdromDevice.new
    when 'floppy'
      boot_order << RbVmomi::VIM::VirtualMachineBootOptionsBootableFloppyDevice.new
    else
      raise "failed to create boot device because \"#{boot_device}\" is unknown"
    end
  end
  boot_order
end
connect() click to toggle source
# File lib/fog/vsphere/compute.rb, line 641
def connect
  # This is a state variable to allow digest validation of the SSL cert
  bad_cert = false
  loop do
    begin
      @connection = RbVmomi::VIM.new host: @vsphere_server,
                                     port: @vsphere_port,
                                     path: @vsphere_path,
                                     ns: @vsphere_ns,
                                     rev: @vsphere_rev,
                                     ssl: @vsphere_ssl,
                                     insecure: bad_cert,
                                     debug: @vsphere_debug

      # Create a shadow class to change the behaviour of @connection.obj2xml
      # so that xsd:any types are converted to xsd:int (and not xsd:long).
      #
      # This is a known issue with RbVmomi.
      #
      # See https://communities.vmware.com/message/2505334 for discussion
      # and https://github.com/rlane/rbvmomi/pull/30 for an unmerged
      # pull request that fixes it in RbVmomi.
      #
      class <<@connection
        def obj2xml(xml, name, type, is_array, o, attrs = {})
          case o
          when Integer
            attrs['xsi:type'] = 'xsd:int' if type(type) == RbVmomi::BasicTypes::AnyType
            xml.tag! name, o.to_s, attrs
            xml
          else
            super xml, name, type, is_array, o, attrs
          end
        end
      end

      break
    rescue OpenSSL::SSL::SSLError
      raise if bad_cert
      bad_cert = true
    end
  end

  validate_ssl_connection if bad_cert
end
controller_default_options() click to toggle source
# File lib/fog/vsphere/requests/compute/create_vm.rb, line 219
def controller_default_options
  { operation: :add, type: RbVmomi::VIM.VirtualLsiLogicController.class, shared: false }
end
controller_get_shared_from_options(options) click to toggle source
# File lib/fog/vsphere/requests/compute/create_vm.rb, line 223
def controller_get_shared_from_options(options)
  if (options.key?(:shared) && (options[:shared] == false)) || (!options.key? :shared)
    :noSharing
  elsif options[:shared] == true
    :virtualSharing
  elsif options[:shared].is_a? String
    options[:shared]
  else
    :noSharing
  end
end
create_cdrom(cdrom, index = 0, operation = :add, controller_key = 200) click to toggle source
# File lib/fog/vsphere/requests/compute/create_vm.rb, line 270
def create_cdrom(cdrom, index = 0, operation = :add, controller_key = 200)
  {
    operation: operation,
    device: RbVmomi::VIM.VirtualCdrom(
      key: cdrom.key || index,
      backing: RbVmomi::VIM::VirtualCdromRemoteAtapiBackingInfo(deviceName: ''),
      controllerKey: controller_key,
      connectable: RbVmomi::VIM::VirtualDeviceConnectInfo(
        startConnected: false,
        connected: false,
        allowGuestControl: true
      )
    )
  }
end
create_controller(controller = nil, index = 0) click to toggle source
# File lib/fog/vsphere/requests/compute/create_vm.rb, line 200
def create_controller(controller = nil, index = 0)
  options = if controller
              controller_default_options.merge(controller.attributes)
            else
              controller_default_options
          end
  controller_class = if options[:type].is_a? String
                       Fog::Vsphere.class_from_string options[:type], 'RbVmomi::VIM'
                     else
                       options[:type]
                   end
  {
    operation: options[:operation],
    device: controller_class.new(key: options[:key] || (1000 + index),
                                 busNumber: options[:bus_id] || index,
                                 sharedBus: controller_get_shared_from_options(options))
  }
end
create_disk(disk, operation = :add, options = {}) click to toggle source
# File lib/fog/vsphere/requests/compute/create_vm.rb, line 235
def create_disk(disk, operation = :add, options = {})
  # If we deploy the vm on a storage pod, datastore has to be an empty string
  datastore = if options[:storage_pod]
                ''
              else
                "[#{disk.datastore}]"
              end

  disk.set_unit_number
  disk.set_key

  payload = {
    operation: operation,
    device: RbVmomi::VIM.VirtualDisk(
      key: disk.key,
      backing: RbVmomi::VIM.VirtualDiskFlatVer2BackingInfo(
        fileName: options[:filename] || datastore,
        diskMode: disk.mode.to_sym,
        thinProvisioned: disk.thin
      ),
      controllerKey: disk.controller_key,
      unitNumber: disk.unit_number,
      capacityInKB: disk.size
    )
  }
  file_operation = options[:file_operation] || (:create if operation == :add)
  payload[:fileOperation] = file_operation if file_operation

  if operation == :add && disk.thin == 'false' && disk.eager_zero == 'true'
    payload[:device][:backing][:eagerlyScrub] = disk.eager_zero
  end

  payload
end
create_interface(nic, index = 0, operation = :add, attributes = {}) click to toggle source
# File lib/fog/vsphere/requests/compute/create_vm.rb, line 185
def create_interface(nic, index = 0, operation = :add, attributes = {})
  {
    operation: operation,
    device: nic.type.new(
      key: index,
      deviceInfo:                 {
        label: nic.name,
        summary: nic.summary
      },
      backing: create_nic_backing(nic, attributes),
      addressType: 'generated'
    )
  }
end
create_nic_backing(nic, attributes) click to toggle source
# File lib/fog/vsphere/requests/compute/create_vm.rb, line 164
def create_nic_backing(nic, attributes)
  raw_network = get_raw_network(nic.network, attributes[:datacenter], if nic.virtualswitch then nic.virtualswitch end)

  if raw_network.is_a? RbVmomi::VIM::DistributedVirtualPortgroup
    RbVmomi::VIM.VirtualEthernetCardDistributedVirtualPortBackingInfo(
      port: RbVmomi::VIM.DistributedVirtualSwitchPortConnection(
        portgroupKey: raw_network.key,
        switchUuid: raw_network.config.distributedVirtualSwitch.uuid
      )
    )
  elsif raw_network.is_a? RbVmomi::VIM::OpaqueNetwork
    RbVmomi::VIM.VirtualEthernetCardOpaqueNetworkBackingInfo(
      opaqueNetworkType: raw_network.summary.opaqueNetworkType,
      opaqueNetworkId: raw_network.summary.opaqueNetworkId
    )

  else
    RbVmomi::VIM.VirtualEthernetCardNetworkBackingInfo(deviceName: nic.network)
  end
end
create_vm_on_datastore(vm_cfg, vmFolder, resource_pool, host = nil) click to toggle source
# File lib/fog/vsphere/requests/compute/create_vm.rb, line 45
def create_vm_on_datastore(vm_cfg, vmFolder, resource_pool, host = nil)
  vm = vmFolder.CreateVM_Task(config: vm_cfg, pool: resource_pool, host: host).wait_for_completion
end
create_vm_on_storage_pod(storage_pod, vm_cfg, vmFolder, resource_pool, datacenter, host = nil) click to toggle source
# File lib/fog/vsphere/requests/compute/create_vm.rb, line 49
def create_vm_on_storage_pod(storage_pod, vm_cfg, vmFolder, resource_pool, datacenter, host = nil)
  pod_spec = RbVmomi::VIM::StorageDrsPodSelectionSpec.new(
    storagePod: get_raw_storage_pod(storage_pod, datacenter)
  )
  storage_spec = RbVmomi::VIM::StoragePlacementSpec.new(
    type: 'create',
    folder: vmFolder,
    resourcePool: resource_pool,
    podSelectionSpec: pod_spec,
    configSpec: vm_cfg,
    host: host
  )
  srm = connection.serviceContent.storageResourceManager
  result = srm.RecommendDatastores(storageSpec: storage_spec)

  # if result array contains recommendation, we can apply it
  if key = result.recommendations.first.key
    result = srm.ApplyStorageDrsRecommendation_Task(key: [key]).wait_for_completion
    vm = result.vm
  else
    raise 'Could not create vm on storage pod, did not get a storage recommendation'
  end
  vm
end
device_change(attributes) click to toggle source
# File lib/fog/vsphere/requests/compute/create_vm.rb, line 92
def device_change(attributes)
  devices = []
  if (nics = attributes[:interfaces])
    devices << nics.map { |nic| create_interface(nic, nics.index(nic), :add, attributes) }
  end

  if (scsi_controllers = (attributes[:scsi_controllers] || attributes['scsi_controller']))
    devices << scsi_controllers.each_with_index.map { |controller, index| create_controller(controller, index) }
  end

  if (disks = attributes[:volumes])
    devices << disks.map { |disk| create_disk(disk, :add, storage_pod: get_storage_pod_from_volumes(attributes)) }
  end

  if (cdroms = attributes[:cdroms])
    devices << cdroms.map { |cdrom| create_cdrom(cdrom, cdroms.index(cdrom)) }
  end
  devices.flatten
end
extra_config(attributes) click to toggle source
# File lib/fog/vsphere/requests/compute/create_vm.rb, line 286
def extra_config(attributes)
  extra_config = attributes[:extra_config] || { 'bios.bootOrder' => 'ethernet0' }
  extra_config.map { |k, v| { key: k, value: v.to_s } }
end
folder_enumerator(raw_folder, recursive) click to toggle source

An enumerator for a folder. Enumerates all the VMs in the folder, recursively if passed recursive=true

# File lib/fog/vsphere/requests/compute/list_virtual_machines.rb, line 36
def folder_enumerator(raw_folder, recursive)
  Enumerator.new do |yielder|
    raw_folder.children.each do |child|
      case child
      when RbVmomi::VIM::Folder
        folder_enumerator(child, true).each { |item| yielder.yield item } if recursive
      when RbVmomi::VIM::VirtualMachine
        yielder.yield child
      end
    end
  end
end
get_folder_path(folder, root = nil) click to toggle source
# File lib/fog/vsphere/requests/compute/list_virtual_machines.rb, line 68
def get_folder_path(folder, root = nil)
  return if !folder.methods.include?('parent') || (folder == root)
  "#{get_folder_path(folder.parent)}/#{folder.name}"
end
get_group_spec(attributes = {}) click to toggle source
# File lib/fog/vsphere/requests/compute/create_group.rb, line 29
def get_group_spec(attributes = {})
  if attributes[:type].to_s == 'ClusterVmGroup'
    vms = attributes[:vm_ids].to_a.map { |id| get_vm_ref(id, attributes[:datacenter]) }
    attributes[:type].new(
      name: attributes[:name],
      vm: vms
    )
  elsif attributes[:type].to_s == 'ClusterHostGroup'
    attributes[:type].new(
      name: attributes[:name],
      host: attributes[:host_refs]
    )
  end
end
get_interface_from_options(vmid, options) click to toggle source
# File lib/fog/vsphere/requests/compute/modify_vm_interface.rb, line 46
def get_interface_from_options(vmid, options)
  if options && options[:interface]
    options[:interface]

  elsif options[:key] && (options[:key] > 0)
    oldattributes = get_vm_interface(vmid, options)
    Fog::Vsphere::Compute::Interface.new(oldattributes.merge(options))

  elsif options[:type] && options[:network]
    Fog::Vsphere::Compute::Interface.new options

  else
    raise ArgumentError, 'interface is a required parameter or pass options with type and network'
  end
end
get_rule_spec(attributes = {}) click to toggle source
# File lib/fog/vsphere/requests/compute/create_rule.rb, line 30
def get_rule_spec(attributes = {})
  if attributes[:type].to_s == 'ClusterAntiAffinityRuleSpec' || attributes[:type].to_s == 'ClusterAffinityRuleSpec'
    vms = attributes[:vm_ids].to_a.map { |id| get_vm_ref(id, attributes[:datacenter]) }
    attributes[:type].new(
      name: attributes[:name],
      enabled: attributes[:enabled],
      vm: vms
    )
  elsif attributes[:type].to_s == 'ClusterVmHostRuleInfo'
    attributes[:type].new(
      name: attributes[:name],
      enabled: attributes[:enabled],
      mandatory: attributes[:mandatory],
      vmGroupName: attributes[:vmGroupName],
      affineHostGroupName: attributes[:affineHostGroupName]
    )
  end
end
get_storage_pod_from_volumes(attributes) click to toggle source

check if a storage pool is set on any of the volumes and return the first result found or nil return early if vsphere revision is lower than 5 as this is not supported

# File lib/fog/vsphere/requests/compute/create_vm.rb, line 76
def get_storage_pod_from_volumes(attributes)
  return unless @vsphere_rev.to_f >= 5
  volume = attributes[:volumes].detect { |volume| !(volume.storage_pod.nil? || volume.storage_pod.empty?) }
  volume.storage_pod if volume
end
list_all_templates(options = {}) click to toggle source
# File lib/fog/vsphere/requests/compute/list_templates.rb, line 26
def list_all_templates(options = {})
  datacenters = find_datacenters(options[:datacenter])

  vms = datacenters.map do |dc|
    list_container_view(dc, 'VirtualMachine', :vmFolder)
  end.flatten
  # remove all virtual machines that are not templates
  vms.delete_if { |v| v.config.nil? || !v.config.template }

  vms.map(&method(:convert_vm_mob_ref_to_attr_hash))
end
list_all_templates_in_folder(path, datacenter_name) click to toggle source
# File lib/fog/vsphere/requests/compute/list_templates.rb, line 16
def list_all_templates_in_folder(path, datacenter_name)
  folder = get_raw_vmfolder(path, datacenter_name)

  vms = folder.children.grep(RbVmomi::VIM::VirtualMachine)
  # remove all virtual machines that are not template
  vms.delete_if { |v| v.config.nil? || !v.config.template }

  vms.map(&method(:convert_vm_mob_ref_to_attr_hash))
end
list_all_virtual_machines(options = {}) click to toggle source
# File lib/fog/vsphere/requests/compute/list_virtual_machines.rb, line 49
def list_all_virtual_machines(options = {})
  raw_vms = raw_list_all_virtual_machines(options[:datacenter])
  vms = convert_vm_view_to_attr_hash(raw_vms)

  # remove all template based virtual machines
  vms.delete_if { |v| v['template'] }
  vms
end
list_all_virtual_machines_in_folder(path, datacenter_name, recursive) click to toggle source
# File lib/fog/vsphere/requests/compute/list_virtual_machines.rb, line 22
def list_all_virtual_machines_in_folder(path, datacenter_name, recursive)
  vms = raw_list_all_virtual_machines_in_folder(path, datacenter_name, recursive).to_a
  # remove all template based virtual machines
  vms.delete_if { |v| v.config.nil? || v.config.template }
  vms.map(&method(:convert_vm_mob_ref_to_attr_hash))
end
list_container_view(datacenter_obj_or_name, type, container_object = nil) click to toggle source
# File lib/fog/vsphere/compute.rb, line 704
def list_container_view(datacenter_obj_or_name, type, container_object = nil)
  dc = if datacenter_obj_or_name.is_a?(String)
         find_raw_datacenter(datacenter_obj_or_name)
       else
         datacenter_obj_or_name
       end

  container = if container_object
                dc.public_send(container_object)
              else
                dc
              end

  container_view = connection.serviceContent.viewManager.CreateContainerView(
    container: dc,
    type: [type],
    recursive: true
  )

  result = container_view.view
  container_view.DestroyView
  result
end
negotiate_revision(revision = nil) click to toggle source
# File lib/fog/vsphere/compute.rb, line 630
def negotiate_revision(revision = nil)
  # Negotiate the API revision
  unless revision
    rev = @connection.serviceContent.about.apiVersion
    @connection.rev = [rev, ENV['FOG_VSPHERE_REV'] || '4.1'].max
  end

  @vsphere_is_vcenter = @connection.serviceContent.about.apiType == 'VirtualCenter'
  @vsphere_rev = @connection.rev
end
nic_backing_different?(one, two) click to toggle source
# File lib/fog/vsphere/requests/compute/update_vm.rb, line 92
def nic_backing_different?(one, two)
  return true if one.class != two.class

  return true if one.is_a?(RbVmomi::VIM::VirtualEthernetCardDistributedVirtualPortBackingInfo) && (one.port.portgroupKey != two.port.portgroupKey || one.port.switchUuid != two.port.switchUuid)

  return true if one.is_a?(RbVmomi::VIM::VirtualEthernetCardNetworkBackingInfo) && one.deviceName != two.deviceName && one.deviceType != twp.device

  false
end
raw_list_all_virtual_machines(datacenter_name = nil) click to toggle source
# File lib/fog/vsphere/requests/compute/list_virtual_machines.rb, line 58
def raw_list_all_virtual_machines(datacenter_name = nil)
  ## Moved this to its own function since trying to get a list of all virtual machines
  ## to parse for a find function took way too long. The raw list returned will make it
  ## much faster to interact for some functions.
  datacenters = find_datacenters(datacenter_name)
  datacenters.map do |dc|
    list_container_view(dc, 'VirtualMachine', :vmFolder)
  end.flatten
end
raw_list_all_virtual_machines_in_folder(path, datacenter_name, recursive) click to toggle source
# File lib/fog/vsphere/requests/compute/list_virtual_machines.rb, line 29
def raw_list_all_virtual_machines_in_folder(path, datacenter_name, recursive)
  folder = get_raw_vmfolder(path, datacenter_name)
  folder_enumerator(folder, recursive)
end
raw_network_vlan(network) click to toggle source
# File lib/fog/vsphere/requests/compute/list_networks.rb, line 89
def raw_network_vlan(network)
  case network
  when RbVmomi::VIM::VMwareDVSPortSetting
    raw_network_vlan_id(network.vlan)
  end
end
raw_network_vlan_id(vlan) click to toggle source
# File lib/fog/vsphere/requests/compute/list_networks.rb, line 96
def raw_network_vlan_id(vlan)
  case vlan
  when RbVmomi::VIM::VmwareDistributedVirtualSwitchVlanIdSpec
    vlan.vlanId
  end
end
raw_to_hash(nic) click to toggle source

rubocop:disable Style/ConditionalAssignment

# File lib/fog/vsphere/requests/compute/list_vm_interfaces.rb, line 65
def raw_to_hash(nic)
  if nic.backing.respond_to?(:network)
    network = nic.backing.network.name
  elsif nic.backing.respond_to?(:port)
    network = nic.backing.port.portgroupKey
  else
    network = nil
  end
  {
    name: nic.deviceInfo.label,
    mac: nic.macAddress,
    network: network,
    status: nic.connectable.status,
    connected: nic.connectable.connected,
    summary: nic.deviceInfo.summary,
    type: nic.class,
    key: nic.key
  }
end
suspend_forcefully(vm) click to toggle source
# File lib/fog/vsphere/requests/compute/vm_suspend.rb, line 21
def suspend_forcefully(vm)
  task = vm.SuspendVM_Task
  task.wait_for_completion
  {
    'task_state'   => task.info.result,
    'suspend_type' => 'suspend'
  }
end
suspend_gracefully(vm) click to toggle source
# File lib/fog/vsphere/requests/compute/vm_suspend.rb, line 30
def suspend_gracefully(vm)
  vm.StandbyGuest
  {
    'task_state'   => 'running',
    'suspend_type' => 'standby_guest'
  }
end
update_vm_interfaces_specs(vm_mob_ref, fog_interfaces, datacenter) click to toggle source
# File lib/fog/vsphere/requests/compute/update_vm.rb, line 36
def update_vm_interfaces_specs(vm_mob_ref, fog_interfaces, datacenter)
  vm_nics = vm_mob_ref.config.hardware.device.grep(RbVmomi::VIM::VirtualEthernetCard)
  modified_nics = fog_interfaces.to_a.take(vm_nics.size)
  new_nics = fog_interfaces.to_a.drop(vm_nics.size)

  specs = []
  vm_nics.zip(modified_nics).each do |vm_nic, fog_nic|
    if fog_nic
      # Update the attributes on the existing nic
      backing = create_nic_backing(fog_nic, datacenter: datacenter)

      if nic_backing_different?(vm_nic.backing, backing)
        vm_nic.backing = backing
        specs << { operation: :edit, device: vm_nic }
      end
    else
      specs << {
        operation: :remove,
        device: vm_nic
      }
    end
  end

  specs.concat(new_nics.map { |nic| create_interface(nic, 0, :add, datacenter: datacenter) }) if new_nics.any?

  specs
end
update_vm_volumes_specs(vm_mob_ref, volumes) click to toggle source
# File lib/fog/vsphere/requests/compute/update_vm.rb, line 64
def update_vm_volumes_specs(vm_mob_ref, volumes)
  vm_volumes = vm_mob_ref.config.hardware.device.grep(RbVmomi::VIM::VirtualDisk)
  modified_volumes = volumes.to_a.take(vm_volumes.size)
  new_volumes = volumes.to_a.drop(vm_volumes.size)

  specs = []
  vm_volumes.zip(modified_volumes).each do |vm_volume, fog_volume|
    if fog_volume
      update_volume_attributes(vm_volume, fog_volume)

      specs << { operation: :edit, device: vm_volume }
      next
    end

    specs << { operation: :remove, fileOperation: :destroy, device: vm_volume }
  end

  specs.concat(new_volumes.map { |volume| create_disk(volume) }) if new_volumes.any?

  specs
end
update_volume_attributes(vm_volume, fog_volume) click to toggle source
# File lib/fog/vsphere/requests/compute/update_vm.rb, line 86
def update_volume_attributes(vm_volume, fog_volume)
  vm_volume.capacityInKB = fog_volume.size
  vm_volume.backing.diskMode = fog_volume.mode
  vm_volume.backing.thinProvisioned = fog_volume.thin
end
validate_ssl_connection() click to toggle source

Verify a SSL certificate based on the hashed public key

# File lib/fog/vsphere/compute.rb, line 695
def validate_ssl_connection
  pubkey = @connection.http.peer_cert.public_key
  pubkey_hash = Digest::SHA2.hexdigest(pubkey.to_s)
  expected_pubkey_hash = @vsphere_expected_pubkey_hash
  if pubkey_hash != expected_pubkey_hash
    raise Fog::Vsphere::Errors::SecurityError, "The remote system presented a public key with hash #{pubkey_hash} but we're expecting a hash of #{expected_pubkey_hash || '<unset>'}.  If you are sure the remote system is authentic set vsphere_expected_pubkey_hash: <the hash printed in this message> in ~/.fog"
  end
end
vm_path_name(attributes) click to toggle source

this methods defines where the vm config files would be located, by default we prefer to keep it at the same place the (first) vmdk is located if we deploy the vm on a storage pool, we have to return an empty string

# File lib/fog/vsphere/requests/compute/create_vm.rb, line 85
def vm_path_name(attributes)
  return '' if get_storage_pod_from_volumes(attributes)
  datastore = attributes[:volumes].first.datastore unless attributes[:volumes].empty?
  datastore ||= 'datastore1'
  "[#{datastore}]"
end