The Real and Mock classes share the same method because #list_virtual_machines will be properly mocked for us
# File lib/fog/vsphere/compute.rb, line 111 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
# File lib/fog/vsphere/requests/compute/current_time.rb, line 6 def current_time current_time = @connection.serviceInstance.CurrentTime { 'current_time' => current_time } end
# File lib/fog/vsphere/requests/compute/datacenters.rb, line 5 def datacenters @datacenters ||= datacenters_reload # Hide the values which are the RbVmomi instances @datacenters.keys end
# 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. if options['instance_uuid'] then list_all_virtual_machines_by_instance_uuid(options) elsif options['folder'] then list_all_virtual_machines_in_folder(options) else list_all_virtual_machines end end
# File lib/fog/vsphere/requests/compute/vm_clone.rb, line 33 def vm_clone(options = {}) # Option handling options = vm_clone_check_options(options) notfound = lambda { raise Fog::Compute::Vsphere::NotFound, "Could not find VM template" } # Find the template in the folder. This is more efficient than # searching ALL VM's looking for the template. # Tap gets rid of the leading empty string and "Datacenters" element # and returns the array. path_elements = options['path'].split('/').tap { |ary| ary.shift 2 } # The DC name itself. template_dc = path_elements.shift # If the first path element contains "vm" this denotes the vmFolder # and needs to be shifted out path_elements.shift if path_elements[0] == 'vm' # The template name. The remaining elements are the folders in the # datacenter. template_name = path_elements.pop # Make sure @datacenters is populated. We need the instances from the Hash keys. self.datacenters # Get the datacenter managed object from the hash dc = @datacenters[template_dc] # Get the VM Folder (Group) efficiently vm_folder = dc.vmFolder # Walk the tree resetting the folder pointer as we go folder = path_elements.inject(vm_folder) do |current_folder, sub_folder_name| # 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_folder = current_folder.find(sub_folder_name, RbVmomi::VIM::Folder) raise ArgumentError, "Could not descend into #{sub_folder_name}. Please check your path." unless sub_folder sub_folder end # Now find the template itself using the efficient find method vm_mob_ref = folder.find(template_name, RbVmomi::VIM::VirtualMachine) # Now find _a_ resource pool to use for the clone # (REVISIT: We need to support cloning into a specific RP) if ( 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 else # 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 resource_pool = vm_mob_ref.resourcePool 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(:pool => resource_pool, :diskMoveType => :moveChildMostDiskBacking) else relocation_spec = RbVmomi::VIM.VirtualMachineRelocateSpec(:pool => resource_pool, :transform => options['transform'] || 'sparse') end # And the clone specification clone_spec = RbVmomi::VIM.VirtualMachineCloneSpec(:location => relocation_spec, :powerOn => options['power_on'] || true, :template => false) task = vm_mob_ref.CloneVM_Task(:folder => vm_mob_ref.parent, :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, 'vm_attributes' => new_vm ? convert_vm_mob_ref_to_attr_hash(new_vm) : {}, 'task_ref' => task._ref } end
# 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
# File lib/fog/vsphere/requests/compute/vm_create.rb, line 29 def vm_create(options = {}) # Option handling options = vm_create_check_options(options) path_elements = options['path'].split('/').tap { |ary| ary.shift 2 } dc_name = path_elements.shift vm_cfg = { :name => options['name'], :guestId => options['guest_id'] ? options['guest_id'] : 'otherGuest', :files => { :vmPathName => "[#{options['datastore']}]" }, :numCPUs => options['num_cpus'] ? options['num_cpus'] : 1 , :memoryMB => options['memory'] ? options['memory'] : 512, :memoryHotAddEnabled => options['memory_hot_add_enabled'] ? options['memory_hot_add_enabled'] : 0, :cpuHotAddEnabled => options['cpu_hot_add_enabled'] ? options['cpu_hot_add_enabled'] : 0, :deviceChange => options['device_array'].class == Array ? options['device_array'] : nil, :extraConfig => options['extra_config'].class == Array ? options['extra_config'] : nil, } self.datacenters dc = @datacenters[dc_name] vm_folder = dc.vmFolder folder = path_elements.inject(vm_folder) do |current_folder, sub_folder_name| sub_folder = current_folder.find(sub_folder_name, RbVmomi::VIM::Folder) raise ArgumentError, "Could not descend into #{sub_folder_name}. Please check your path." unless sub_folder sub_folder end clusters = dc.hostFolder.children build_cluster='' clusters.each { |my_cluster| if "#{my_cluster.name}" == "#{options['cluster']}" build_cluster=my_cluster end } resource_pool = build_cluster.resourcePool task=folder.CreateVM_Task(:config => vm_cfg, :pool => resource_pool) if options['wait'] then new_vm = task.wait_for_completion else tries = 0 new_vm = begin 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 { 'vm_ref' => new_vm ? new_vm._ref : nil, 'vm_attributes' => new_vm ? convert_vm_mob_ref_to_attr_hash(new_vm) : {}, 'task_ref' => task._ref } end
# 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' # 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.Destroy_Task task.wait_for_completion { 'task_state' => task.info.state } end
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 =~ %r^RemoteDisplay\.vnc\.(\w+)$/ [$1.to_sym, config.value] end end.compact] end
# 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
# 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
# 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
# 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.ShutdownGuest { 'task_state' => "running", 'reboot_type' => 'reboot_guest' } end end
# 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
# 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' 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 => RbVmomi::VIM.VirtualMachineConfigSpec(options['hardware_spec'])) task.wait_for_completion { 'task_state' => task.info.state } end
# 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