Class: Fog::Compute::Vsphere::Real

Inherits:
Object
  • Object
show all
Includes:
Shared
Defined in:
lib/fog/vsphere/compute.rb,
lib/fog/vsphere/requests/compute/vm_clone.rb,
lib/fog/vsphere/requests/compute/create_vm.rb,
lib/fog/vsphere/requests/compute/vm_reboot.rb,
lib/fog/vsphere/requests/compute/get_folder.rb,
lib/fog/vsphere/requests/compute/vm_destroy.rb,
lib/fog/vsphere/requests/compute/vm_migrate.rb,
lib/fog/vsphere/requests/compute/get_cluster.rb,
lib/fog/vsphere/requests/compute/get_network.rb,
lib/fog/vsphere/requests/compute/vm_power_on.rb,
lib/fog/vsphere/requests/compute/current_time.rb,
lib/fog/vsphere/requests/compute/get_template.rb,
lib/fog/vsphere/requests/compute/list_folders.rb,
lib/fog/vsphere/requests/compute/vm_power_off.rb,
lib/fog/vsphere/requests/compute/create_folder.rb,
lib/fog/vsphere/requests/compute/get_datastore.rb,
lib/fog/vsphere/requests/compute/list_clusters.rb,
lib/fog/vsphere/requests/compute/list_networks.rb,
lib/fog/vsphere/requests/compute/vm_config_vnc.rb,
lib/fog/vsphere/requests/compute/get_datacenter.rb,
lib/fog/vsphere/requests/compute/list_templates.rb,
lib/fog/vsphere/requests/compute/get_server_type.rb,
lib/fog/vsphere/requests/compute/list_datastores.rb,
lib/fog/vsphere/requests/compute/list_vm_volumes.rb,
lib/fog/vsphere/requests/compute/list_datacenters.rb,
lib/fog/vsphere/requests/compute/vm_reconfig_cpus.rb,
lib/fog/vsphere/requests/compute/get_resource_pool.rb,
lib/fog/vsphere/requests/compute/list_customfields.rb,
lib/fog/vsphere/requests/compute/list_server_types.rb,
lib/fog/vsphere/requests/compute/get_interface_type.rb,
lib/fog/vsphere/requests/compute/list_vm_interfaces.rb,
lib/fog/vsphere/requests/compute/vm_reconfig_memory.rb,
lib/fog/vsphere/requests/compute/get_virtual_machine.rb,
lib/fog/vsphere/requests/compute/list_resource_pools.rb,
lib/fog/vsphere/requests/compute/modify_vm_interface.rb,
lib/fog/vsphere/requests/compute/list_interface_types.rb,
lib/fog/vsphere/requests/compute/list_vm_customvalues.rb,
lib/fog/vsphere/requests/compute/vm_reconfig_hardware.rb,
lib/fog/vsphere/requests/compute/list_virtual_machines.rb

Instance Attribute Summary

Attributes included from Shared

#vsphere_is_vcenter, #vsphere_rev, #vsphere_server, #vsphere_username

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Real

Returns a new instance of Real.



334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
# File 'lib/fog/vsphere/compute.rb', line 334

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_expected_pubkey_hash = options[:vsphere_expected_pubkey_hash]
  @vsphere_must_reauthenticate = false

  @connection = nil
  # 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
      break
    rescue OpenSSL::SSL::SSLError
      raise if bad_cert
      bad_cert = true
    end
  end

  if bad_cert then
    validate_ssl_connection
  end

  # Negotiate the API revision
  if not options[:vsphere_rev]
    rev = @connection.serviceContent.about.apiVersion
    @connection.rev = [ rev, ENV['FOG_VSPHERE_REV'] || '4.1' ].min
  end

  @vsphere_is_vcenter = @connection.serviceContent.about.apiType == "VirtualCenter"
  @vsphere_rev = @connection.rev

  authenticate
end

Instance Method Details

#add_vm_interface(vmid, options = {}) ⇒ Object

Raises:

  • (ArgumentError)


6
7
8
9
10
11
# File 'lib/fog/vsphere/requests/compute/modify_vm_interface.rb', line 6

def add_vm_interface(vmid, options = {})
  raise ArgumentError, "instance id is a required parameter" unless vmid

  interface=get_interface_from_options(vmid, options)
  vm_reconfig_hardware('instance_uuid' => vmid, 'hardware_spec' => {'deviceChange'=>[create_interface(interface)]})
end

#create_folder(datacenter, path, name) ⇒ Object

Raises:

  • (ArgumentError)


5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 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" }.collect { |a| a.first.name }.join("/").sub(/^\/?Datacenters\/#{datacenter}\/vm\/?/, '')
  rescue => e
    raise e, "failed to create folder: #{e}"
  end
end

#create_vm(attributes = { }) ⇒ Object



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/fog/vsphere/requests/compute/create_vm.rb', line 5

def create_vm attributes = { }
  # build up vm configuration

  vm_cfg        = {
    :name         => attributes[:name],
    :guestId      => attributes[:guest_id],
    :files        => { :vmPathName => vm_path_name(attributes) },
    :numCPUs      => attributes[:cpus],
    :memoryMB     => attributes[:memory_mb],
    :deviceChange => device_change(attributes),
    :extraConfig  => extra_config(attributes),
  }
  resource_pool = if attributes[:resource_pool]
                    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])
  vm            = vmFolder.CreateVM_Task(:config => vm_cfg, :pool => resource_pool).wait_for_completion
  vm.config.instanceUuid
rescue => e
  raise e, "failed to create vm: #{e}"
end

#current_timeObject



6
7
8
9
# File 'lib/fog/vsphere/requests/compute/current_time.rb', line 6

def current_time
  current_time = @connection.serviceInstance.CurrentTime
  { 'current_time' => current_time }
end

#destroy_vm_interface(vmid, options = {}) ⇒ Object

Raises:

  • (ArgumentError)


13
14
15
16
17
18
# File 'lib/fog/vsphere/requests/compute/modify_vm_interface.rb', line 13

def destroy_vm_interface(vmid, options = {})
  raise ArgumentError, "instance id is a required parameter" unless vmid

  interface=get_vm_interface(vmid, options)
  vm_reconfig_hardware('instance_uuid' => vmid, 'hardware_spec' => {'deviceChange'=>[create_interface(interface, interface.key, :remove)]})
end

#get_cluster(name, datacenter_name) ⇒ Object



5
6
7
8
9
# 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::Compute::Vsphere::NotFound) unless cluster
  cluster_attributes(cluster, datacenter_name)
end

#get_datacenter(name) ⇒ Object



5
6
7
8
9
# File 'lib/fog/vsphere/requests/compute/get_datacenter.rb', line 5

def get_datacenter name
  dc = find_raw_datacenter(name)
  raise(Fog::Compute::Vsphere::NotFound) unless dc
  {:name => dc.name, :status => dc.overallStatus}
end

#get_datastore(name, datacenter_name) ⇒ Object



5
6
7
8
9
# File 'lib/fog/vsphere/requests/compute/get_datastore.rb', line 5

def get_datastore(name, datacenter_name)
  datastore = get_raw_datastore(name, datacenter_name)
  raise(Fog::Compute::Vsphere::NotFound) unless datastore
  datastore_attributes(datastore, datacenter_name)
end

#get_folder(path, datacenter_name, type = nil) ⇒ Object



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 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.
  case type
    when 'vm', :vm
      # if you're a vm then grab the VM.
      folder = get_raw_vmfolder(path, datacenter_name)
      raise(Fog::Compute::Vsphere::NotFound) unless folder
      folder_attributes(folder, datacenter_name)
    when 'network', :network
      raise "not implemented"
    when 'datastore', :datastore
      raise "not implemented"
    else
      raise ArgumentError, "#{type} is unknown"
  end
end

#get_interface_type(id, servertype, datacenter, filter = {}) ⇒ Object



5
6
7
8
9
10
11
# 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::Compute::Vsphere::NotFound) unless interfacetype
   interfacetype
end

#get_network(name, datacenter_name) ⇒ Object



5
6
7
8
9
# 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::Compute::Vsphere::NotFound) unless network
  network_attributes(network, datacenter_name)
end

#get_resource_pool(name, cluster_name, datacenter_name) ⇒ Object



5
6
7
8
9
# 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::Compute::Vsphere::NotFound) unless resource_pool
  resource_pool_attributes(resource_pool, cluster_name, datacenter_name)
end

#get_server_type(id, datacenter, filter = {}) ⇒ Object



5
6
7
8
9
# 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::Compute::Vsphere::NotFound) unless server_type
  server_type_attributes(server_type, datacenter)           
end

#get_template(id, datacenter_name = nil) ⇒ Object



5
6
7
# 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) ⇒ Object



5
6
7
# File 'lib/fog/vsphere/requests/compute/get_virtual_machine.rb', line 5

def get_virtual_machine(id, datacenter_name = nil)
  convert_vm_mob_ref_to_attr_hash(get_vm_ref(id, datacenter_name))
end

#get_vm_interface(vm_id, options = {}) ⇒ Object

Raises:

  • (ArgumentError)


46
47
48
49
50
51
52
53
54
55
56
# File 'lib/fog/vsphere/requests/compute/list_vm_interfaces.rb', line 46

def get_vm_interface(vm_id, options={})
  raise ArgumentError, "instance id is a required parameter" unless vm_id
  if options.is_a? Fog::Compute::Vsphere::Interface
    options
  else
    raise ArgumentError, "Either key or name is a required parameter. options: #{options}" unless options.has_key? :key or options.has_key? :mac or options.has_key? :name
    list_vm_interfaces(vm_id).find do | nic |
      (options.has_key? :key and nic[:key]==options[:key].to_i) or (options.has_key? :mac and nic[:mac]==options[:mac]) or (options.has_key? :name and nic[:name]==options[:name])
    end
  end
end

#interface_type_attributes(nic, servertype, datacenter) ⇒ Object



13
14
15
16
17
18
19
20
21
# File 'lib/fog/vsphere/requests/compute/list_interface_types.rb', line 13

def interface_type_attributes(nic, servertype, datacenter)
  {
    :id => nic,
    :name => nic,
    :datacenter => datacenter,
    :servertype => servertype,
#            :class => Fog.class_from_string(nic)
  }
end

#list_clusters(filters = { }) ⇒ Object



5
6
7
8
9
10
11
# File 'lib/fog/vsphere/requests/compute/list_clusters.rb', line 5

def list_clusters(filters = { })
  datacenter_name = filters[:datacenter]

  raw_clusters(datacenter_name).map do |cluster|
    cluster_attributes(cluster, datacenter_name)
  end
end

#list_customfieldsObject



5
6
7
8
9
10
11
12
13
# 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 = {}) ⇒ Object



6
7
8
9
10
11
12
13
14
# File 'lib/fog/vsphere/requests/compute/list_datacenters.rb', line 6

def list_datacenters filters = {}
  raw_datacenters.map do |dc|
    {
      :id => managed_obj_id(dc),
      :name => dc.name,
      :status => dc.overallStatus
    }
  end
end

#list_datastores(filters = { }) ⇒ Object



5
6
7
8
9
10
11
12
13
# File 'lib/fog/vsphere/requests/compute/list_datastores.rb', line 5

def list_datastores(filters = { })
  datacenter_name = filters[:datacenter]
  # default to show all datastores
  only_active = filters[:accessible] || false
  raw_datastores(datacenter_name).map do |datastore|
    next if only_active and !datastore.summary.accessible
    datastore_attributes(datastore, datacenter_name)
  end.compact
end

#list_folders(filters = { }) ⇒ Object

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


23
24
25
26
27
28
29
# File 'lib/fog/vsphere/requests/compute/list_folders.rb', line 23

def list_folders(filters = { })
  path            = filters[:path] || filters['path'] || ''
  datacenter_name = filters[:datacenter]
  get_raw_vmfolders(path, datacenter_name).map do |folder|
    folder_attributes(folder, datacenter_name)
  end
end

#list_interface_types(filters = {}) ⇒ Object



5
6
7
8
9
10
11
12
# 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.has_key?(:id) and filters[:id] != nictype
    interface_type_attributes(nictype, servertype_name, datacenter_name)
  end.compact
end

#list_networks(filters = { }) ⇒ Object



5
6
7
8
9
10
11
12
13
# File 'lib/fog/vsphere/requests/compute/list_networks.rb', line 5

def list_networks(filters = { })
  datacenter_name = filters[:datacenter]
  # default to show all networks
  only_active = filters[:accessible] || false
  raw_networks(datacenter_name).map do |network|
    next if only_active and !network.summary.accessible
    network_attributes(network, datacenter_name)
  end.compact
end

#list_resource_pools(filters = { }) ⇒ Object



5
6
7
8
9
10
11
12
# 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_server_types(filters = {}) ⇒ Object



5
6
7
8
9
10
11
12
13
14
15
16
# 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
  else
    nil
  end
  #select{ | guestdesc | guestdesc.select{ | k, v | filter.has_key?(k) and filter[k] == v }==filter }
end

#list_templates(options = { }) ⇒ Object



5
6
7
8
9
10
11
12
# File 'lib/fog/vsphere/requests/compute/list_templates.rb', line 5

def list_templates(options = { })
  options[:folder] ||= options['folder']
  if options[:folder] then
    list_all_templates_in_folder(options[:folder], options[:datacenter])
  else
    list_all_templates(options)
  end
end

#list_virtual_machines(options = { }) ⇒ Object



5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 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'] then
    [get_virtual_machine(options['instance_uuid'])]
  elsif options[:folder] && options[:datacenter] then
    list_all_virtual_machines_in_folder(options[:folder], options[:datacenter])
  else
    list_all_virtual_machines(options)
  end
end

#list_vm_customvalues(vm_id) ⇒ Object



5
6
7
8
9
10
11
12
13
# 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) ⇒ Object

> 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,



31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/fog/vsphere/requests/compute/list_vm_interfaces.rb', line 31

def list_vm_interfaces(vm_id)
  get_vm_ref(vm_id).config.hardware.device.grep(RbVmomi::VIM::VirtualEthernetCard).map do |nic|
    {
      :name    => nic.deviceInfo.label,
      :mac     => nic.macAddress,
      :network => nic.backing.respond_to?("network") ? nic.backing.network.name : nic.backing.port.portgroupKey,
      :status  => nic.connectable.status,
      :summary => nic.deviceInfo.summary,
      :type    => nic.class,
      :key     => nic.key,
    }
  end

end

#list_vm_volumes(vm_id) ⇒ Object

[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

)]



30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/fog/vsphere/requests/compute/list_vm_volumes.rb', line 30

def list_vm_volumes(vm_id)
  get_vm_ref(vm_id).disks.map do |vol|
    {
      :id => vol.backing.uuid,
      :thin => vol.backing.thinProvisioned,
      :mode => vol.backing.diskMode,
      :filename => vol.backing.fileName,
      :datastore => (vol.backing.datastore.name rescue(nil)),
      :size => vol.capacityInKB,
      :name => vol.deviceInfo.label
    }
  end
end

#raw_clusters(datacenter) ⇒ Object



13
14
15
# File 'lib/fog/vsphere/requests/compute/list_clusters.rb', line 13

def raw_clusters(datacenter)
  find_raw_datacenter(datacenter).hostFolder.childEntity.grep(RbVmomi::VIM::ClusterComputeResource)
end

#raw_datastores(datacenter_name) ⇒ Object



15
16
17
# File 'lib/fog/vsphere/requests/compute/list_datastores.rb', line 15

def raw_datastores(datacenter_name)
  find_raw_datacenter(datacenter_name).datastore
end

#raw_networks(datacenter_name) ⇒ Object



15
16
17
# File 'lib/fog/vsphere/requests/compute/list_networks.rb', line 15

def raw_networks(datacenter_name)
  find_raw_datacenter(datacenter_name).network
end

#raw_server_types(datacenter_name, filter = {}) ⇒ Object



18
19
20
21
22
23
24
# File 'lib/fog/vsphere/requests/compute/list_server_types.rb', line 18

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

#update_vm_interface(vmid, options = {}) ⇒ Object

Raises:

  • (ArgumentError)


20
21
22
23
24
25
# File 'lib/fog/vsphere/requests/compute/modify_vm_interface.rb', line 20

def update_vm_interface(vmid, options = {})
  raise ArgumentError, "instance id is a required parameter" unless vmid

  interface=get_vm_interface(vmid, options)
  vm_reconfig_hardware('instance_uuid' => vmid, 'hardware_spec' => {'deviceChange'=>[create_interface(interface, interface.key, :edit)]})          
end

#vm_clone(options = {}) ⇒ Object

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)
      
    • ‘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

    • ‘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. Static IP Settings not configured. 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’



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
# File 'lib/fog/vsphere/requests/compute/vm_clone.rb', line 71

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']

  # Default wait enabled
  options['wait'] = true

  # 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 = get_raw_vmfolder(options['dest_folder'], options['datacenter']) if options.has_key?('dest_folder')
  dest_folder ||= vm_mob_ref.parent

  # Options['resource_pool']<~Array>
  # Now find _a_ resource pool to use for the clone if one is not specified
  if ( options.has_key?('resource_pool') && options['resource_pool'].is_a?(Array) && options['resource_pool'].length == 2 )
    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 ( 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
  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['datastore']<~String>
  # Grab the datastore object if option is set
  datastore_obj = get_raw_datastore(options['datastore'], options['datacenter']) if options.has_key?('datastore')
  # confirm nil if nil or option is not set
  datastore_obj ||= nil
  virtual_machine_config_spec = RbVmomi::VIM::VirtualMachineConfigSpec()

  # Options['network']
  # Build up the config spec
  if ( options.has_key?('network_label') )
    #network_obj = datacenter_obj.networkFolder.find(options['network_label'])
    config_spec_operation = RbVmomi::VIM::VirtualDeviceConfigSpecOperation('edit')
    nic_backing_info = RbVmomi::VIM::VirtualEthernetCardNetworkBackingInfo(:deviceName => options['network_label'])
      #:deviceName => "Network adapter 1",
      #:network => network_obj)
    connectable = RbVmomi::VIM::VirtualDeviceConnectInfo(
      :allowGuestControl => true,
      :connected => true,
      :startConnected => true)
    device = RbVmomi::VIM::VirtualE1000(
      :backing => nic_backing_info,
      :deviceInfo => RbVmomi::VIM::Description(:label => "Network adapter 1", :summary => options['network_label']),
      :key => options['network_adapter_device_key'],
      :connectable => connectable)
    device_spec = RbVmomi::VIM::VirtualDeviceConfigSpec(
      :operation => config_spec_operation,
      :device => device)
    virtual_machine_config_spec.deviceChange = [device_spec]
  end
  # 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
  virtual_machine_config_spec.numCPUs = options['numCPUs'] if  ( options.has_key?('numCPUs') )
  virtual_machine_config_spec.memoryMB = options['memoryMB'] if ( options.has_key?('memoryMB') )
  # Options['customization_spec']
  # Build up all the crappy tiered objects like the perl method
  # Collect your variables ifset (writing at 11pm revist me)
  # * domain <~String> - *REQUIRED* - Sets the server's domain for customization
  # * 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
  if ( options.has_key?('customization_spec') )
    cust_options = options['customization_spec']
    if cust_options.has_key?("ipsettings")
      raise ArgumentError, "ip and subnetMask is required for static ip" unless cust_options["ipsettings"].has_key?("ip") and
                                                                                cust_options["ipsettings"].has_key?("subnetMask")
    end
    raise ArgumentError, "domain is required" unless cust_options.has_key?("domain")
    cust_domain = cust_options['domain']
    cust_ip_settings = RbVmomi::VIM::CustomizationIPSettings.new(cust_options["ipsettings"]) if cust_options.has_key?("ipsettings")
    cust_ip_settings.ip = RbVmomi::VIM::CustomizationFixedIp("ipAddress" => cust_options["ipsettings"]["ip"]) if cust_options.has_key?("ipsettings")
    cust_ip_settings ||= RbVmomi::VIM::CustomizationIPSettings.new("ip" => RbVmomi::VIM::CustomizationDhcpIpGenerator.new())
    cust_ip_settings.dnsDomain = cust_domain
    cust_global_ip_settings = RbVmomi::VIM::CustomizationGlobalIPSettings.new
    cust_global_ip_settings.dnsServerList = cust_ip_settings.dnsServerList
    cust_global_ip_settings.dnsSuffixList = [cust_domain]
    cust_hostname = RbVmomi::VIM::CustomizationFixedName.new(:name => cust_options['hostname']) if cust_options.has_key?('hostname')
    cust_hostname ||= RbVmomi::VIM::CustomizationFixedName.new(:name => options['name'])
    cust_hwclockutc = cust_options['hw_clock_utc']
    cust_timezone = cust_options['time_zone']
    # Start Building objects
    # Build the CustomizationLinuxPrep Object
    cust_prep = RbVmomi::VIM::CustomizationLinuxPrep.new(
      :domain => cust_domain,
      :hostName => cust_hostname,
      :hwClockUTC => cust_hwclockutc,
      :timeZone => cust_timezone)
    # Build the Custom Adapter Mapping Supports only one eth right now
    cust_adapter_mapping = [RbVmomi::VIM::CustomizationAdapterMapping.new("adapter" => cust_ip_settings)]
    # Build the customization Spec
    customization_spec = RbVmomi::VIM::CustomizationSpec.new(
      :identity => cust_prep,
      :globalIPSettings => cust_global_ip_settings,
      :nicSettingMap => cust_adapter_mapping)
  end
  customization_spec ||= nil

  # FIXME: pad this out with the rest of the useful things in VirtualMachineConfigSpec
  # http://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/vim.vm.ConfigSpec.html
  if options.has_key?('memoryMB') || options.has_key?('numCPUs')
    virtual_machine_config_spec = {
      :memoryMB => options['memoryMB'],
      :numCPUs  => options['numCPUs']
    }
  end

  relocation_spec=nil
  if ( options['linked_clone'] )
    # 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{|disk_backing|
              disk_backing.backing = disk_backing.backing.dup;
              disk_backing.backing.fileName = "[#{disk.backing.datastore.name}]";
              disk_backing.backing.parent = disk.backing
            }
          },
        ]
      }
      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,
                                                              :diskMoveType => :moveChildMostDiskBacking)
  else
    relocation_spec = RbVmomi::VIM.VirtualMachineRelocateSpec(:datastore => datastore_obj,
                                                              :pool => resource_pool,
                                                              :transform => options['transform'] || 'sparse')
  end
  # And the clone specification
  clone_spec = RbVmomi::VIM.VirtualMachineCloneSpec(:location => relocation_spec,
                                                    :config => virtual_machine_config_spec,
                                                    :customization => customization_spec,
                                                    :powerOn  => options.has_key?('power_on') ? options['power_on'] : true,
                                                    :template => false)

  # Perform the actual Clone Task
  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['wait'] then
    # 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
    tries = 0
    new_vm = begin
      # Try and find the new VM (folder.find is quite efficient)
      folder.find(options['name'], RbVmomi::VIM::VirtualMachine) or raise Fog::Vsphere::Errors::NotFound
    rescue Fog::Vsphere::Errors::NotFound
      tries += 1
      if tries <= 10 then
        sleep 15
        retry
      end
      nil
    end
  end

  # Return hash
  {
    'vm_ref'        => new_vm ? new_vm._ref : nil,
    'new_vm'        => new_vm ? get_virtual_machine("#{options['dest_folder']}/#{options['name']}", options['datacenter']) : nil,
    'task_ref'      => task._ref
  }
end

#vm_config_vnc(options = { }) ⇒ Object

Raises:

  • (ArgumentError)


5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 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.has_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 = {}) ⇒ Object

Raises:

  • (ArgumentError)


6
7
8
9
10
11
12
13
# File 'lib/fog/vsphere/requests/compute/vm_destroy.rb', line 6

def vm_destroy(options = {})
  raise ArgumentError, "instance_uuid is a required parameter" unless options.has_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_get_vnc(uuid) ⇒ Object

return a hash of VNC attributes required to view the console



22
23
24
25
26
27
28
29
30
31
# 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+)$/
      [$1.to_sym, config.value]
    end
  end.compact]
end

#vm_migrate(options = {}) ⇒ Object

Raises:

  • (ArgumentError)


6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# File 'lib/fog/vsphere/requests/compute/vm_migrate.rb', line 6

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.has_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.kind_of? RbVmomi::VIM::VirtualMachine
    raise Fog::Vsphere::Errors::NotFound,
      "Could not find VirtualMachine with instance uuid #{options['instance_uuid']}"
  end
  task = vm_mob_ref.MigrateVM_Task(:pool => options['pool'], :host => options['host'], :priority => "#{priority}", :state => options['state'] )
  task.wait_for_completion
  { 'task_state' => task.info.state }
end

#vm_power_off(options = {}) ⇒ Object

Raises:

  • (ArgumentError)


6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# File 'lib/fog/vsphere/requests/compute/vm_power_off.rb', line 6

def vm_power_off(options = {})
  options = { 'force' => false }.merge(options)
  raise ArgumentError, "instance_uuid is a required parameter" unless options.has_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'] then
    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 = {}) ⇒ Object

Raises:

  • (ArgumentError)


6
7
8
9
10
11
12
13
14
15
16
# File 'lib/fog/vsphere/requests/compute/vm_power_on.rb', line 6

def vm_power_on(options = {})
  raise ArgumentError, "instance_uuid is a required parameter" unless options.has_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 = {}) ⇒ Object

Raises:

  • (ArgumentError)


6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# File 'lib/fog/vsphere/requests/compute/vm_reboot.rb', line 6

def vm_reboot(options = {})
  options = { 'force' => false }.merge(options)
  raise ArgumentError, "instance_uuid is a required parameter" unless options.has_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'] then
    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_cpus(options = {}) ⇒ Object

Raises:

  • (ArgumentError)


5
6
7
8
9
10
# 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.has_key? 'cpus'
  raise ArgumentError, "instance_uuid is a required parameter" unless options.has_key? 'instance_uuid'
  hardware_spec={'numCPUs' => options['cpus']}
  vm_reconfig_hardware('instance_uuid' => options['instance_uuid'], 'hardware_spec' => hardware_spec )
end

#vm_reconfig_hardware(options = {}) ⇒ Object

Raises:

  • (ArgumentError)


5
6
7
8
9
10
11
12
# 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.has_key? 'hardware_spec'
  raise ArgumentError, "instance_uuid is a required parameter" unless options.has_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 = {}) ⇒ Object

Raises:

  • (ArgumentError)


5
6
7
8
9
10
# 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.has_key? 'memory'
  raise ArgumentError, "instance_uuid is a required parameter" unless options.has_key? 'instance_uuid'
  hardware_spec={'memoryMB' => options['memory']}
  vm_reconfig_hardware('instance_uuid' => options['instance_uuid'], 'hardware_spec' => hardware_spec )
end