class VCenterDriver::Datastore
Class Datastore
Attributes
Public Class Methods
Source
# File lib/datastore.rb, line 831 def self.detach_and_destroy(disk, vm, disk_id, prev_ds_ref, vi_client) # it's not a CDROM (CLONE=NO) is_cd = !(disk['CLONE'].nil? || disk['CLONE'] == 'YES') begin # Detach disk if possible (VM is reconfigured) # and gather vCenter info # Needed for poweroff machines too ds_ref, img_path = vm.detach_disk(disk) return if is_cd # Disk could't be detached, use OpenNebula info if !(ds_ref && img_path && !img_path.empty?) img_path = vm.disk_real_path(disk, disk_id) ds_ref = prev_ds_ref end # If disk was already detached we have no way to remove it ds = VCenterDriver::Datastore.new_from_ref(ds_ref, vi_client) search_params = ds.get_search_params(ds['name'], File.dirname(img_path), File.basename(img_path)) # Perform search task and return results search_task = ds['browser'] .SearchDatastoreSubFolders_Task(search_params) search_task.wait_for_completion ds.delete_virtual_disk(img_path) img_dir = File.dirname(img_path) ds.rm_directory(img_dir) if ds.dir_empty?(img_dir) rescue StandardError => e if !e.message.start_with?('FileNotFound') raise e.message # Ignore FileNotFound end end end
detach disk from vCenter vm if possible, destroy the disk on FS
Source
# File lib/datastore.rb, line 370 def initialize(item, vi_client = nil) check_item(item, RbVmomi::VIM::Datastore) @vi_client = vi_client @item = item @one_item = {} super() end
Calls superclass method
Source
# File lib/datastore.rb, line 826 def self.new_from_ref(ref, vi_client) new(RbVmomi::VIM::Datastore.new(vi_client.vim, ref), vi_client) end
This is never cached
Public Instance Methods
Source
# File lib/datastore.rb, line 685 def all_images images = {} imid = -1 ds_id = nil ds_name = self['name'] # We need OpenNebula Images and Datastores pools ipool = VCenterDriver::VIHelper .one_pool(OpenNebula::ImagePool, false) if ipool.respond_to?(:message) raise "Could not get OpenNebula ImagePool: #{pool.message}" end dpool = VCenterDriver::VIHelper .one_pool(OpenNebula::DatastorePool, false) if dpool.respond_to?(:message) raise "Could not get OpenNebula DatastorePool: #{pool.message}" end ds_id = @one_item['ID'] begin # Create Search Spec search_params = get_search_params(ds_name) # Perform search task and return results search_task = self['browser'] .SearchDatastoreSubFolders_Task(search_params) search_task.wait_for_completion # Loop through search results search_task.info.result.each do |result| # Remove [datastore] from file path folderpath = '' size = result.folderPath.size if result.folderPath[-1] != ']' if result.folderPath[-1] != '/' result.folderPath[size] = '/' end folderpath = result .folderPath.sub(/^\[#{ds_name}\] /, '') end # Loop through images in result.file result.file.each do |image| image_path = '' # Skip not relevant files next unless %w[FloppyImageFileInfo IsoImageFileInfo VmDiskFileInfo].include? image.class.to_s # Get image path and name image_path << folderpath << image.path image_name = File.basename(image.path) .reverse.sub('kdmv.', '').reverse # Get image's type if image.class.to_s == 'VmDiskFileInfo' image_type = 'OS' else image_type = 'CDROM' end # Get image's size image_size = image.capacityKb / 1024 rescue nil image_size ||= image.fileSize / 1024 / 1024 rescue nil # Assign image prefix if known or assign default prefix controller = image.controllerType rescue nil if controller if controller == 'VirtualIDEController' disk_prefix = 'hd' else disk_prefix = 'sd' end else # Get default value for disks that # are not attached to any controller disk_prefix = VCenterDriver::VIHelper .get_default( 'IMAGE/TEMPLATE/DEV_PREFIX' ) end # Generate a crypto hash # this hash is used to avoid name collisions key = "#{image_name}#{ds_name}#{image_path}" import_name = VCenterDriver::VIHelper .one_name( OpenNebula::ImagePool, image_name, key, ipool ) # Set template one_image = "NAME=\"#{import_name}\"\n" one_image << "PATH=\"vcenter://#{image_path}\"\n" one_image << "PERSISTENT=\"NO\"\n" one_image << "TYPE=\"#{image_type}\"\n" unless CONFIG[:delete_images] one_image << "VCENTER_IMPORTED=\"YES\"\n" end one_image << "DEV_PREFIX=\"#{disk_prefix}\"\n" # Check image hasn't already been imported image_found = VCenterDriver::VIHelper .find_image_by( 'SOURCE', OpenNebula::ImagePool, image_path, ds_id, ipool ) next if image_found # Add template to image array images[import_name] = { :import_id => imid+=1, :name => import_name, :ref => import_name, :path => image_path, :size => image_size.to_s, :type => image.class.to_s, :dsid => ds_id, :one => one_image } end end rescue StandardError => e raise "Could not find images. \ Reason: #{e.message}/#{e.backtrace}" end vname = @vi_client.vc_name || '' { vname => images } end
Source
# File lib/datastore.rb, line 414 def copy_virtual_disk(src_path, target_ds, target_path, new_size = nil) source_ds_name = self['name'] target_ds_name = target_ds['name'] leading_dirs = target_path.split('/')[0..-2] if !leading_dirs.empty? if source_ds_name == target_ds_name create_directory(leading_dirs.join('/')) else target_ds.create_directory(leading_dirs.join('/')) end end copy_params = { :sourceName => "[#{source_ds_name}] #{src_path}", :sourceDatacenter => obtain_dc.item } if File.extname(src_path) == '.vmdk' copy_params[:destName] = "[#{target_ds_name}] #{target_path}" obtain_vdm.CopyVirtualDisk_Task(copy_params).wait_for_completion if new_size resize_spec = { :name => "[#{target_ds_name}] #{target_path}", :datacenter => target_ds.obtain_dc.item, :newCapacityKb => new_size, :eagerZero => false } obtain_vdm.ExtendVirtualDisk_Task( resize_spec ).wait_for_completion end else copy_params[:destinationName] = "[#{target_ds_name}] #{target_path}" obtain_fm.CopyDatastoreFile_Task( copy_params ).wait_for_completion end target_path end
Copy a VirtualDisk
Source
# File lib/datastore.rb, line 603 def dc_path dc = obtain_dc p = dc.item.parent path = [dc.item.name] while p.instance_of? RbVmomi::VIM::Folder path.unshift(p.name) p = p.parent end path.delete_at(0) # The first folder is the root "Datacenters" path.join('/') end
Source
# File lib/datastore.rb, line 396 def delete_file(img_name) ds_name = self['name'] begin obtain_fm.DeleteDatastoreFile_Task( :name => "[#{ds_name}] #{img_name}", :datacenter => obtain_dc.item ).wait_for_completion rescue StandardError => e # Ignore if file not found if !e.message.start_with?('ManagedObjectNotFound') && !e.message.start_with?('FileNotFound') raise e end end end
Source
# File lib/datastore.rb, line 379 def delete_virtual_disk(img_name) ds_name = self['name'] begin obtain_vdm.DeleteVirtualDisk_Task( :name => "[#{ds_name}] #{img_name}", :datacenter => obtain_dc.item ).wait_for_completion rescue StandardError => e # Ignore if file not found if !e.message.start_with?('ManagedObjectNotFound') && !e.message.start_with?('FileNotFound') raise e end end end
Source
# File lib/datastore.rb, line 644 def descriptor?(remote_path) url = generate_file_url(remote_path) rout, wout = IO.pipe pid = spawn(CURLBIN, '-I', '-k', '--noproxy', '*', '-f', '-b', self['_connection.cookie'], url, :out => wout, :err => '/dev/null') Process.waitpid(pid, 0) raise 'read image header failed' unless $?.success? # rubocop:disable Style/SpecialGlobalVars wout.close size = rout.readlines.select do |l| l.downcase.start_with?('content-length') end[0].downcase.sub('content-length: ', '') rout.close size.chomp.to_i < 4096 # If <4k, then is a descriptor end
Source
# File lib/datastore.rb, line 503 def dir_empty?(path) ds_name = self['name'] spec = RbVmomi::VIM::HostDatastoreBrowserSearchSpec.new search_params = { 'datastorePath' => "[#{ds_name}] #{path}", 'searchSpec' => spec } begin search_task = self['browser'] .SearchDatastoreSubFolders_Task(search_params) search_task.wait_for_completion !search_task.info.result.nil? && search_task.info.result.length == 1 && search_task.info.result.first.file.empty? rescue StandardError false end end
Source
# File lib/datastore.rb, line 529 def download_file(source_path, target_path) @item.download(source_path, target_path) end
Source
# File lib/datastore.rb, line 633 def download_to_stdout(remote_path) url = generate_file_url(remote_path) pid = spawn(CURLBIN, '-k', '--noproxy', '*', '-f', '-b', self['_connection.cookie'], url) Process.waitpid(pid, 0) raise 'download failed' unless $?.success? # rubocop:disable Style/SpecialGlobalVars end
Source
# File lib/datastore.rb, line 615 def generate_file_url(path) if self['_connection.http.use_ssl?'] protocol = 'https://' else protocol = 'http://' end hostname = self['_connection.http.address'] port = self['_connection.http.port'] dcpath = dc_path url_path = "folder/#{path}?dcPath=#{dcpath}&dsName=#{self['name']}" # This creates the vcenter file URL # for uploading or downloading files # e.g: url = "#{protocol}#{hostname}:#{port}/#{url_path}" URI.escape(url) # rubocop:disable Lint/UriEscapeUnescape end
Source
# File lib/datastore.rb, line 570 def get_search_params(ds_name, img_path = nil, img_name = nil) spec = RbVmomi::VIM::HostDatastoreBrowserSearchSpec.new vmdisk_query = RbVmomi::VIM::VmDiskFileQuery.new vmdisk_query.details = RbVmomi::VIM::VmDiskFileQueryFlags( :diskType => true, :capacityKb => true, :hardwareVersion => true, :controllerType => true ) spec.query = [vmdisk_query, RbVmomi::VIM::IsoImageFileQuery.new] spec.details = RbVmomi::VIM::FileQueryFlags( :fileOwner => true, :fileSize => true, :fileType => true, :modification => true ) if img_name.nil? spec.matchPattern = [] else spec.matchPattern = [img_name] end datastore_path = "[#{ds_name}]" datastore_path << " #{img_path}" unless img_path.nil? { 'datastorePath' => datastore_path, 'searchSpec' => spec } end
Source
# File lib/datastore.rb, line 666 def get_text_file(remote_path) url = generate_file_url(remote_path) rout, wout = IO.pipe pid = spawn CURLBIN, '-k', '--noproxy', '*', '-f', '-b', self['_connection.cookie'], url, :out => wout, :err => '/dev/null' Process.waitpid(pid, 0) raise 'get text file failed' unless $?.success? # rubocop:disable Style/SpecialGlobalVars wout.close output = rout.readlines rout.close output end
Source
# File lib/datastore.rb, line 459 def move_virtual_disk(disk, dest_path, dest_dsid, vi_client = nil) vi_client ||= @vi_client target_ds = VCenterDriver::VIHelper.one_item( OpenNebula::Datastore, dest_dsid, false ) target_ds_ref = target_ds['TEMPLATE/VCENTER_DS_REF'] target_ds_vc = VCenterDriver::Datastore .new_from_ref( target_ds_ref, vi_client ) dest_name = target_ds_vc['name'] target_ds_vc.create_directory(File.dirname(dest_path)) dpath_ds = "[#{dest_name}] #{dest_path}" orig_path = "[#{self['name']}] #{disk.path}" move_params = { :sourceName => orig_path, :sourceDatacenter => obtain_dc.item, :destName => dpath_ds, :force => true } obtain_vdm.MoveVirtualDisk_Task(move_params).wait_for_completion end
Source
# File lib/datastore.rb, line 490 def rm_directory(directory) ds_name = self['name'] rm_directory_params = { :name => "[#{ds_name}] #{directory}", :datacenter => obtain_dc.item } obtain_fm.DeleteDatastoreFile_Task( rm_directory_params ).wait_for_completion end
Source
# File lib/datastore.rb, line 534 def stat(img_str) ds_name = self['name'] img_path = File.dirname img_str img_name = File.basename img_str # Create Search Spec search_params = get_search_params(ds_name, img_path, img_name) # Perform search task and return results begin search_task = self['browser'] .SearchDatastoreSubFolders_Task(search_params) search_task.wait_for_completion # Try to get vmdk capacity as seen by VM size = search_task .info.result[0].file[0].capacityKb / 1024 rescue nil # Try to get file size size ||= search_task .info .result[0].file[0].fileSize / 1024 / 1024 rescue nil raise 'Could not get file size or capacity' if size.nil? size rescue StandardError => e message = "Could not find file. Reason: \"#{e.message}\"." if VCenterDriver::CONFIG[:debug_information] message += ' ' + e.backtrace.to_s end raise message end end
Get file size for image handling
Source
# File lib/datastore.rb, line 525 def upload_file(source_path, target_path) @item.upload(target_path, source_path) end