def __init__(self, module): super(VMwareHostDatastore, self).__init__(module) # NOTE: The below parameter is deprecated starting from Ansible v2.11 self.datacenter_name = module.params['datacenter_name'] self.datastore_name = module.params['datastore_name'] self.datastore_type = module.params['datastore_type'] self.nfs_server = module.params['nfs_server'] self.nfs_path = module.params['nfs_path'] self.nfs_ro = module.params['nfs_ro'] self.vmfs_device_name = module.params['vmfs_device_name'] self.vmfs_version = module.params['vmfs_version'] self.esxi_hostname = module.params['esxi_hostname'] self.state = module.params['state'] if self.is_vcenter(): if not self.esxi_hostname: self.module.fail_json( msg="esxi_hostname is mandatory with a vcenter") self.esxi = self.find_hostsystem_by_name(self.esxi_hostname) if self.esxi is None: self.module.fail_json(msg="Failed to find ESXi hostname %s" % self.esxi_hostname) else: self.esxi = find_obj(self.content, [vim.HostSystem], None)
def execute(self): result = dict(changed=False) obj = find_obj(self.content, [vim.HostSystem], self.esxi_hostname) if (obj): for pg in obj.config.network.portgroup: if (isinstance(pg, vim.host.PortGroup) and pg.spec.name == self.pg_name): portgroup_spec = pg.spec portgroup_spec.policy.security.allowPromiscuous = self.promiscuous_mode portgroup_spec.policy.security.forgedTransmits = self.forged_transmits portgroup_spec.policy.security.macChanges = self.mac_address_changes try: obj.configManager.networkSystem.UpdatePortGroup( self.pg_name, portgroup_spec) except: self.module.fail_json( msg="Failed to portgroup security update %s." % self.pg_name) result['changed'] = True self.module.exit_json(**result) else: self.module.fail_json(msg="%s not found" % self.pg_name) else: self.module.fail_json(msg="%s not found." % self.esxi_hostname)
def __init__(self, module): super(VMwareHostDatastore, self).__init__(module) self.datacenter_name = module.params['datacenter_name'] self.datastore_name = module.params['datastore_name'] self.esxi_hostname = module.params['esxi_hostname'] self.esxi_hostname = module.params['esxi_hostname'] self.vmfs_device_name = module.params['vmfs_device_name'] self.folder_name = module.params['folder_name'] self.esxi = self.find_hostsystem_by_name(self.esxi_hostname) if self.esxi is None: self.module.fail_json(msg="Failed to find ESXi hostname %s." % self.esxi_hostname) if self.folder_name: self.folder = find_obj(self.content, [vim.Folder], self.folder_name, first=True) if self.folder is None: self.module.fail_json( msg= "Failed to find storage folder '%s'. Make sure the folder exists, " "or remove module parameter folder_name." % self.folder_name) self.check_datastore_host_state()
def get_object(self): # find_obj doesn't include rootFolder if self.params['object_type'] == 'Folder' and self.params[ 'object_name'] == 'rootFolder': self.current_obj = self.content.rootFolder return try: object_type = getattr(vim, self.params['object_type']) except AttributeError: self.module.fail_json(msg="Object type %s is not valid." % self.params['object_type']) self.current_obj = find_obj( content=self.content, vimtype=[getattr(vim, self.params['object_type'])], name=self.params['object_name']) if self.current_obj is None: self.module.fail_json( msg="Specified object %s of type %s was not found." % (self.params['object_name'], self.params['object_type'])) if self.params['object_type'] == 'DistributedVirtualSwitch': msg = "You are applying permissions to a Distributed vSwitch. " \ "This will probably fail, since Distributed vSwitches inherits permissions " \ "from the datacenter or a folder level. " \ "Define permissions on the datacenter or the folder containing the switch." self.module.warn(msg)
def all_facts(content): host = find_obj(content, [vim.HostSystem], None) ansible_facts = {} ansible_facts.update(get_cpu_facts(host)) ansible_facts.update(get_memory_facts(host)) ansible_facts.update(get_datastore_facts(host)) ansible_facts.update(get_network_facts(host)) ansible_facts.update(get_system_facts(host)) return ansible_facts
def find_obj(self, content, types, name, confine_to_datacenter=True): """ Wrapper around find_obj to set datacenter context """ result = find_obj(content, types, name) if result and confine_to_datacenter: if self.get_parent_datacenter(result).name != self.dc_name: result = None objects = self.get_all_objs(content, types, confine_to_datacenter=True) for obj in objects: if name is None or obj.name == name: return obj return result
def __init__(self, module): super(VmwareHostSnmp, self).__init__(module) if self.is_vcenter(): self.module.fail_json( msg="You have to connect directly to the ESXi host. " "It's not possible to configure SNMP through a vCenter connection." ) else: self.host = find_obj(self.content, [vim.HostSystem], None) if self.host is None: self.module.fail_json(msg="Failed to find host system.")
def sanitize_params(self): ''' this method is used to verify user provided parameters ''' self.vm_obj = self.get_vm() if self.vm_obj is None: vm_id = self.vm_uuid or self.vm_name or self.moid self.module.fail_json( msg="Failed to find the VM/template with %s" % vm_id) # connect to destination VC self.destination_content = connect_to_api( self.module, hostname=self.destination_vcenter, username=self.destination_vcenter_username, password=self.destination_vcenter_password, port=self.destination_vcenter_port, validate_certs=self.destination_vcenter_validate_certs) # Check if vm name already exists in the destination VC vm = find_vm_by_name(content=self.destination_content, vm_name=self.params['destination_vm_name']) if vm: self.module.exit_json( changed=False, msg="A VM with the given name already exists") datastore_name = self.params['destination_datastore'] datastore_cluster = find_obj(self.destination_content, [vim.StoragePod], datastore_name) if datastore_cluster: # If user specified datastore cluster so get recommended datastore datastore_name = self.get_recommended_datastore( datastore_cluster_obj=datastore_cluster) # Check if get_recommended_datastore or user specified datastore exists or not self.destination_datastore = find_datastore_by_name( content=self.destination_content, datastore_name=datastore_name) if self.destination_datastore is None: self.module.fail_json(msg="Destination datastore not found.") self.destination_host = find_hostsystem_by_name( content=self.destination_content, hostname=self.params['destination_host']) if self.destination_host is None: self.module.fail_json(msg="Destination host not found.") if self.params['destination_resource_pool']: self.destination_resource_pool = find_resource_pool_by_name( content=self.destination_content, resource_pool_name=self.params['destination_resource_pool']) else: self.destination_resource_pool = self.destination_host.parent.resourcePool
def __init__(self, module): super(VMwareHostFactManager, self).__init__(module) esxi_host_name = self.params.get('esxi_hostname', None) if self.is_vcenter(): if esxi_host_name is None: self.module.fail_json(msg="Connected to a vCenter system without specifying esxi_hostname") self.host = self.get_all_host_objs(esxi_host_name=esxi_host_name) if len(self.host) > 1: self.module.fail_json(msg="esxi_hostname matched multiple hosts") self.host = self.host[0] else: self.host = find_obj(self.content, [vim.HostSystem], None) if self.host is None: self.module.fail_json(msg="Failed to find host system.")
def get_object(self): try: object_type = getattr(vim, self.params['object_type']) except AttributeError: self.module.fail_json(msg="Object type %s is not valid." % self.params['object_type']) self.current_obj = find_obj( content=self.content, vimtype=[getattr(vim, self.params['object_type'])], name=self.params['object_name']) if self.current_obj is None: self.module.fail_json( msg="Specified object %s of type %s was not found." % (self.params['object_name'], self.params['object_type']))
def get_object(self): # find_obj doesn't include rootFolder if self.params['object_type'] == 'Folder' and self.params['object_name'] == 'rootFolder': self.current_obj = self.content.rootFolder return try: object_type = getattr(vim, self.params['object_type']) except AttributeError: self.module.fail_json(msg="Object type %s is not valid." % self.params['object_type']) self.current_obj = find_obj(content=self.content, vimtype=[getattr(vim, self.params['object_type'])], name=self.params['object_name']) if self.current_obj is None: self.module.fail_json( msg="Specified object %s of type %s was not found." % (self.params['object_name'], self.params['object_type']) )
def ensure_disks(self, vm_obj=None): """ Manage internal state of virtual machine disks Args: vm_obj: Managed object of virtual machine """ # Set vm object self.vm = vm_obj # Sanitize user input disk_data = self.sanitize_disk_inputs() # Create stateful information about SCSI devices current_scsi_info = dict() results = dict(changed=False, disk_data=None, disk_changes=dict()) # Deal with SCSI Controller for device in vm_obj.config.hardware.device: if isinstance(device, tuple(self.scsi_device_type.values())): # Found SCSI device if device.busNumber not in current_scsi_info: device_bus_number = 1000 + device.busNumber current_scsi_info[device_bus_number] = dict(disks=dict()) scsi_changed = False for disk in disk_data: scsi_controller = disk['scsi_controller'] + 1000 if scsi_controller not in current_scsi_info and disk[ 'state'] == 'present': scsi_ctl = self.create_scsi_controller(disk['scsi_type'], disk['scsi_controller']) current_scsi_info[scsi_controller] = dict(disks=dict()) self.config_spec.deviceChange.append(scsi_ctl) scsi_changed = True if scsi_changed: self.reconfigure_vm(self.config_spec, 'SCSI Controller') self.config_spec = vim.vm.ConfigSpec() self.config_spec.deviceChange = [] # Deal with Disks for device in vm_obj.config.hardware.device: if isinstance(device, vim.vm.device.VirtualDisk): # Found Virtual Disk device if device.controllerKey not in current_scsi_info: current_scsi_info[device.controllerKey] = dict( disks=dict()) current_scsi_info[device.controllerKey]['disks'][ device.unitNumber] = device vm_name = self.vm.name disk_change_list = [] for disk in disk_data: disk_change = False scsi_controller = disk[ 'scsi_controller'] + 1000 # VMware auto assign 1000 + SCSI Controller if disk['disk_unit_number'] not in current_scsi_info[ scsi_controller]['disks'] and disk['state'] == 'present': # Add new disk disk_spec = self.create_scsi_disk(scsi_controller, disk['disk_unit_number'], disk['disk_mode'], disk['filename']) if disk['filename'] is None: disk_spec.device.capacityInKB = disk['size'] if disk['disk_type'] == 'thin': disk_spec.device.backing.thinProvisioned = True elif disk['disk_type'] == 'eagerzeroedthick': disk_spec.device.backing.eagerlyScrub = True # get Storage DRS recommended datastore from the datastore cluster if disk['datastore_cluster'] is not None: datastore_name = self.get_recommended_datastore( datastore_cluster_obj=disk['datastore_cluster'], disk_spec_obj=disk_spec) disk['datastore'] = find_obj(self.content, [vim.Datastore], datastore_name) if disk['filename'] is None: disk_spec.device.backing.fileName = "[%s] %s/%s_%s_%s.vmdk" % ( disk['datastore'].name, vm_name, vm_name, str(scsi_controller), str(disk['disk_unit_number'])) else: disk_spec.device.backing.fileName = disk['filename'] disk_spec.device.backing.datastore = disk['datastore'] disk_spec = self.get_ioandshares_diskconfig(disk_spec, disk) self.config_spec.deviceChange.append(disk_spec) disk_change = True current_scsi_info[scsi_controller]['disks'][ disk['disk_unit_number']] = disk_spec.device results['disk_changes'][disk['disk_index']] = "Disk created." elif disk['disk_unit_number'] in current_scsi_info[ scsi_controller]['disks']: if disk['state'] == 'present': disk_spec = vim.vm.device.VirtualDeviceSpec() # set the operation to edit so that it knows to keep other settings disk_spec.device = current_scsi_info[scsi_controller][ 'disks'][disk['disk_unit_number']] # Edit and no resizing allowed if disk['size'] < disk_spec.device.capacityInKB: self.module.fail_json( msg= "Given disk size at disk index [%s] is smaller than found (%d < %d)." "Reducing disks is not allowed." % (disk['disk_index'], disk['size'], disk_spec.device.capacityInKB)) if disk['size'] != disk_spec.device.capacityInKB: disk_spec.operation = vim.vm.device.VirtualDeviceSpec.Operation.edit disk_spec = self.get_ioandshares_diskconfig( disk_spec, disk) disk_spec.device.capacityInKB = disk['size'] self.config_spec.deviceChange.append(disk_spec) disk_change = True results['disk_changes'][ disk['disk_index']] = "Disk size increased." else: results['disk_changes'][ disk['disk_index']] = "Disk already exists." elif disk['state'] == 'absent': # Disk already exists, deleting disk_spec = vim.vm.device.VirtualDeviceSpec() disk_spec.operation = vim.vm.device.VirtualDeviceSpec.Operation.remove if disk['destroy'] is True: disk_spec.fileOperation = vim.vm.device.VirtualDeviceSpec.FileOperation.destroy disk_spec.device = current_scsi_info[scsi_controller][ 'disks'][disk['disk_unit_number']] self.config_spec.deviceChange.append(disk_spec) disk_change = True results['disk_changes'][ disk['disk_index']] = "Disk deleted." if disk_change: # Adding multiple disks in a single attempt raises weird errors # So adding single disk at a time. self.reconfigure_vm(self.config_spec, 'disks') self.config_spec = vim.vm.ConfigSpec() self.config_spec.deviceChange = [] disk_change_list.append(disk_change) if any(disk_change_list): results['changed'] = True results['disk_data'] = self.gather_disk_facts(vm_obj=self.vm) self.module.exit_json(**results)
def get_cluster(self, cluster): if cluster not in self.clusters: self.clusters[cluster] = find_obj(self.content, [vim.ClusterComputeResource], cluster) return self.clusters[cluster]
def sanitize_disk_inputs(self): """ Check correctness of disk input provided by user Returns: A list of dictionary containing disk information """ disks_data = list() if not self.desired_disks: self.module.exit_json(changed=False, msg="No disks provided for virtual" " machine '%s' for management." % self.vm.name) for disk_index, disk in enumerate(self.desired_disks): # Initialize default value for disk current_disk = dict(disk_index=disk_index, state='present', datastore=None, autoselect_datastore=True, disk_unit_number=0, scsi_controller=0) # Check state if 'state' in disk: if disk['state'] not in ['absent', 'present']: self.module.fail_json(msg="Invalid state provided '%s' for disk index [%s]." " State can be either - 'absent', 'present'" % (disk['state'], disk_index)) else: current_disk['state'] = disk['state'] if current_disk['state'] == 'present': # Select datastore or datastore cluster if 'datastore' in disk: if 'autoselect_datastore' in disk: self.module.fail_json(msg="Please specify either 'datastore' " "or 'autoselect_datastore' for disk index [%s]" % disk_index) # Check if given value is datastore or datastore cluster datastore_name = disk['datastore'] datastore_cluster = find_obj(self.content, [vim.StoragePod], datastore_name) if datastore_cluster: # If user specified datastore cluster so get recommended datastore datastore_name = self.get_recommended_datastore(datastore_cluster_obj=datastore_cluster) # Check if get_recommended_datastore or user specified datastore exists or not datastore = find_obj(self.content, [vim.Datastore], datastore_name) if datastore is None: self.module.fail_json(msg="Failed to find datastore named '%s' " "in given configuration." % disk['datastore']) current_disk['datastore'] = datastore current_disk['autoselect_datastore'] = False elif 'autoselect_datastore' in disk: # Find datastore which fits requirement datastores = get_all_objs(self.content, [vim.Datastore]) if not datastores: self.module.fail_json(msg="Failed to gather information about" " available datastores in given datacenter.") datastore = None datastore_freespace = 0 for ds in datastores: if ds.summary.freeSpace > datastore_freespace: # If datastore field is provided, filter destination datastores datastore = ds datastore_freespace = ds.summary.freeSpace current_disk['datastore'] = datastore if 'datastore' not in disk and 'autoselect_datastore' not in disk: self.module.fail_json(msg="Either 'datastore' or 'autoselect_datastore' is" " required parameter while creating disk for " "disk index [%s]." % disk_index) if [x for x in disk.keys() if x.startswith('size_') or x == 'size']: # size, size_tb, size_gb, size_mb, size_kb disk_size_parse_failed = False if 'size' in disk: size_regex = re.compile(r'(\d+(?:\.\d+)?)([tgmkTGMK][bB])') disk_size_m = size_regex.match(disk['size']) if disk_size_m: expected = disk_size_m.group(1) unit = disk_size_m.group(2) else: disk_size_parse_failed = True try: if re.match(r'\d+\.\d+', expected): # We found float value in string, let's typecast it expected = float(expected) else: # We found int value in string, let's typecast it expected = int(expected) except (TypeError, ValueError, NameError): disk_size_parse_failed = True else: # Even multiple size_ parameter provided by user, # consider first value only param = [x for x in disk.keys() if x.startswith('size_')][0] unit = param.split('_')[-1] disk_size = disk[param] if isinstance(disk_size, (float, int)): disk_size = str(disk_size) try: if re.match(r'\d+\.\d+', disk_size): # We found float value in string, let's typecast it expected = float(disk_size) else: # We found int value in string, let's typecast it expected = int(disk_size) except (TypeError, ValueError, NameError): disk_size_parse_failed = True if disk_size_parse_failed: # Common failure self.module.fail_json(msg="Failed to parse disk size for disk index [%s]," " please review value provided" " using documentation." % disk_index) disk_units = dict(tb=3, gb=2, mb=1, kb=0) unit = unit.lower() if unit in disk_units: current_disk['size'] = expected * (1024 ** disk_units[unit]) else: self.module.fail_json(msg="%s is not a supported unit for disk size for disk index [%s]." " Supported units are ['%s']." % (unit, disk_index, "', '".join(disk_units.keys()))) else: # No size found but disk, fail self.module.fail_json(msg="No size, size_kb, size_mb, size_gb or size_tb" " attribute found into disk index [%s] configuration." % disk_index) # Check SCSI controller key if 'scsi_controller' in disk: try: temp_disk_controller = int(disk['scsi_controller']) except ValueError: self.module.fail_json(msg="Invalid SCSI controller ID '%s' specified" " at index [%s]" % (disk['scsi_controller'], disk_index)) if temp_disk_controller not in range(0, 4): # Only 4 SCSI controllers are allowed per VM self.module.fail_json(msg="Invalid SCSI controller ID specified [%s]," " please specify value between 0 to 3 only." % temp_disk_controller) current_disk['scsi_controller'] = temp_disk_controller else: self.module.fail_json(msg="Please specify 'scsi_controller' under disk parameter" " at index [%s], which is required while creating disk." % disk_index) # Check for disk unit number if 'unit_number' in disk: try: temp_disk_unit_number = int(disk['unit_number']) except ValueError: self.module.fail_json(msg="Invalid Disk unit number ID '%s'" " specified at index [%s]" % (disk['unit_number'], disk_index)) if temp_disk_unit_number not in range(0, 16): self.module.fail_json(msg="Invalid Disk unit number ID specified for disk [%s] at index [%s]," " please specify value between 0 to 15" " only (excluding 7)." % (temp_disk_unit_number, disk_index)) if temp_disk_unit_number == 7: self.module.fail_json(msg="Invalid Disk unit number ID specified for disk at index [%s]," " please specify value other than 7 as it is reserved" "for SCSI Controller" % disk_index) current_disk['disk_unit_number'] = temp_disk_unit_number else: self.module.fail_json(msg="Please specify 'unit_number' under disk parameter" " at index [%s], which is required while creating disk." % disk_index) # Type of Disk disk_type = disk.get('type', 'thick').lower() if disk_type not in ['thin', 'thick', 'eagerzeroedthick']: self.module.fail_json(msg="Invalid 'disk_type' specified for disk index [%s]. Please specify" " 'disk_type' value from ['thin', 'thick', 'eagerzeroedthick']." % disk_index) current_disk['disk_type'] = disk_type # SCSI Controller Type scsi_contrl_type = disk.get('scsi_type', 'paravirtual').lower() if scsi_contrl_type not in self.scsi_device_type.keys(): self.module.fail_json(msg="Invalid 'scsi_type' specified for disk index [%s]. Please specify" " 'scsi_type' value from ['%s']" % (disk_index, "', '".join(self.scsi_device_type.keys()))) current_disk['scsi_type'] = scsi_contrl_type disks_data.append(current_disk) return disks_data
def __init__(self, module): super(VMwareHostFactManager, self).__init__(module) self.host = find_obj(self.content, [vim.HostSystem], None) if self.host is None: self.module.fail_json(msg="Failed to find host system.")
def download(self): ovf_files = [] result = dict(changed=False) # Thread class. class downloadThread(threading.Thread): def __init__(self): threading.Thread.__init__(self) def run(self): url = self.deviceUrl.url if (re.search(r"\*", url)): url = url.replace("*", self.host) file_name = url.split("/").pop() save_path = os.path.join(self.path, file_name) headers = { "Content-Type": "application/x-vnd.vmware-streamVmdk" } r = requests.get(url, headers=headers, stream=True, verify=self.ssl_verify) if (r.status_code == 200): total_byte = 0 with open(save_path, "wb") as f: for chunk in r.iter_content(chunk_size=2048): if (chunk): f.write(chunk) f.flush() total_byte += len(chunk) ovf_file = vim.OvfManager.OvfFile() ovf_file.deviceId = self.deviceUrl.key ovf_file.path = self.deviceUrl.targetId ovf_file.size = total_byte ovf_files.append(ovf_file) # Check exist of directory path. if (not (os.path.isdir(self.path))): self.module.fail_json(msg="%s not found" % self.path) # Get VirtualMachine obj. obj = find_obj(self.content, [vim.VirtualMachine], self.name) if (obj == None): self.module.fail_json(msg="%s not found" % self.name) # Export ovf. lease = obj.ExportVm() while True: if (lease.state == vim.HttpNfcLease.State.ready): break elif (lease.state == vim.HttpNfcLease.State.error): self.module.fail_json(msg="ovf export state error") time.sleep(1) threads = [] for deviceUrl in lease.info.deviceUrl: if (deviceUrl.targetId): t = downloadThread() t.host = self.module.params["hostname"] t.ssl_verify = self.module.params["validate_certs"] t.path = self.path t.deviceUrl = deviceUrl t.start() threads.append(t) # Check Threads. while True: if (threads): for t in threads: if (not (t.is_alive())): lease.HttpNfcLeaseProgress(percent=int(100 / len(threads))) threads.remove(t) else: time.sleep(1) else: break # Create of ovf file. ovf_manager = self.content.ovfManager ovf_parameters = vim.OvfManager.CreateDescriptorParams() ovf_parameters.name = obj.name ovf_parameters.ovfFiles = ovf_files vm_descriptor_result = ovf_manager.CreateDescriptor(obj=obj, cdp=ovf_parameters) save_path = os.path.join(self.path, "%s.ovf" % obj.name) with open(save_path, "w") as f: f.writelines(vm_descriptor_result.ovfDescriptor) # ovf download finish. lease.HttpNfcLeaseComplete() self.module.exit_json(**result)
def deploy(self): result = dict(changed=False) # Thread class class deployThread(threading.Thread): def __init__(self): threading.Thread.__init__(self) def run(self): url = self.deviceUrl.url if (re.search(r"\*", url)): url = url.replace("*", self.host) file_path = os.path.join(self.path, self.targetId) headers = { "Content-Type": "application/x-vnd.vmware-streamVmdk" } requests.post(url, headers=headers, data=open(file_path, 'rb'), verify=self.ssl_verify) # Check exist of directory path. if (not (os.path.isdir(self.path))): self.module.fail_json(msg="%s not found" % self.path) # Search of Managed Objects. datastore = find_obj(self.content, [vim.Datastore], self.datastore) if (datastore == None): self.module.fail_json(msg="%s not found" % self.datastore) folder = self.content.searchIndex.FindByInventoryPath( "/%s/%s" % (self.datacenter, self.folder)) if (folder == None): self.module.fail_json( msg= "/%s/%s not found. There is no datacenter or folder, or both." % (self.datacenter, self.folder)) if (self.resource_pool): resource_pool = find_obj(self.content, [vim.ResourcePool], self.resource_pool) if (resource_pool == None): self.module.fail_json(msg="%s not found" % self.resource_pool) elif (self.compute_resource): compute_resource = find_obj(self.content, [vim.ComputeResource], self.compute_resource) if (compute_resource == None): self.module.fail_json(msg="%s not found" % self.compute_resource) resource_pool = compute_resource.resourcePool else: self.module.fail_json( msg="Please specify resource_pool or compute_resource") # Get file list related to ovf. files = os.listdir(self.path) # Read ovf file. ovf_file_path = os.path.join( self.path, list(filter(lambda x: re.match(r".*\.ovf$", x), files))[0]) if (os.path.isfile(ovf_file_path)): with open(ovf_file_path, "r") as f: ovf_file = xmltodict.parse(f.read()) del ovf_file['Envelope']['VirtualSystem'][ 'VirtualHardwareSection']['System'][ 'vssd:VirtualSystemType'] ovf_file = xmltodict.unparse(ovf_file) else: self.module.fail_json(msg="%s not found" % ovf_file_path) # Import ovf. spec_params = vim.OvfManager.CreateImportSpecParams() spec_params.entityName = self.name spec_params.diskProvisioning = self.disk_type ovf_manager = self.content.ovfManager ovf_import_spec = ovf_manager.CreateImportSpec(ovf_file, resource_pool, datastore, spec_params) lease = resource_pool.ImportVApp(ovf_import_spec.importSpec, folder) while True: if (lease.state == vim.HttpNfcLease.State.ready): break elif (lease.state == vim.HttpNfcLease.State.error): self.module.fail_json(msg="ovf import state error") time.sleep(1) threads = [] for deviceUrl in lease.info.deviceUrl: if (deviceUrl.targetId): t = deployThread() t.host = self.module.params["hostname"] t.ssl_verify = self.module.params["validate_certs"] t.path = self.path t.deviceUrl = deviceUrl t.targetId = deviceUrl.targetId t.start() threads.append(t) # Check Threads. while True: if (threads): for t in threads: if (not (t.is_alive())): lease.HttpNfcLeaseProgress(percent=int(100 / len(threads))) threads.remove(t) else: time.sleep(1) else: break lease.HttpNfcLeaseComplete() self.module.exit_json(**result)