From: tierno Date: Sat, 14 Oct 2017 11:27:03 +0000 (+0200) Subject: bug 331 Ensure neutron port is deleted upon vm creation failed X-Git-Tag: v3.0.2~7 X-Git-Url: https://osm.etsi.org/gitweb/?p=osm%2FRO.git;a=commitdiff_plain;h=98e909c77827a222ad5658554dee51ecffbdaff0 bug 331 Ensure neutron port is deleted upon vm creation failed Change-Id: I9fd63a5fd09495ba02b46c55337d2da68fcae7b5 Signed-off-by: tierno --- diff --git a/openmanod b/openmanod index 14dba03f..14f07779 100755 --- a/openmanod +++ b/openmanod @@ -48,7 +48,7 @@ import osm_ro __author__ = "Alfonso Tierno, Gerardo Garcia, Pablo Montes" __date__ = "$26-aug-2014 11:09:29$" -__version__ = "0.5.38-r548" +__version__ = "0.5.39-r549" version_date = "Nov 2017" database_version = 27 # expected database schema version diff --git a/osm_ro/nfvo.py b/osm_ro/nfvo.py index c864be3b..69c4ac36 100644 --- a/osm_ro/nfvo.py +++ b/osm_ro/nfvo.py @@ -2409,7 +2409,7 @@ def start_scenario(mydb, tenant_id, scenario_id, instance_scenario_name, instanc else: av_index = None - vm_id = myvim.new_vminstance(myVMDict['name'], myVMDict['description'], myVMDict.get('start', None), + vm_id, _ = myvim.new_vminstance(myVMDict['name'], myVMDict['description'], myVMDict.get('start', None), myVMDict['imageRef'], myVMDict['flavorRef'], myVMDict['networks'], availability_zone_index=av_index, availability_zone_list=vnf_availability_zones) diff --git a/osm_ro/vim_thread.py b/osm_ro/vim_thread.py index 22a882ed..2c30fb90 100644 --- a/osm_ro/vim_thread.py +++ b/osm_ro/vim_thread.py @@ -43,6 +43,7 @@ The task content are (M: stored at memory, D: stored at database): iface_id: uuid of intance_interfaces sdn_port_id: sdn_net_id: + created_items: dictionary with extra elements created that need to be deleted. e.g. ports, volumes,... created: False if the VIM element is not created by other actions, and it should not be deleted vim_status: VIM status of the element. Stored also at database in the instance_XXX M depends: dict with task_index(from depends_on) to task class @@ -533,6 +534,10 @@ class vim_thread(threading.Thread): task["extra"]["sdn_vim_id"] = to_supersede["extra"]["sdn_vim_id"] if to_supersede["extra"].get("interfaces"): task["extra"]["interfaces"] = to_supersede["extra"]["interfaces"] + if to_supersede["extra"].get("created_items"): + if not task["extra"].get("created_items"): + task["extra"]["created_items"] = {} + task["extra"]["created_items"].update(to_supersede["extra"]["created_items"]) # Mark task as SUPERSEDED. # If task is in self.pending_tasks, it will be removed and database will be update # If task is in self.refresh_tasks, it will be removed @@ -649,7 +654,7 @@ class vim_thread(threading.Thread): "Cannot create VM because depends on a network not created or found: " + str(task_net["error_msg"])) net["net_id"] = network_id - vim_vm_id = self.vim.new_vminstance(*params) + vim_vm_id, created_items = self.vim.new_vminstance(*params) # fill task_interfaces. Look for snd_net_id at database for each interface task_interfaces = {} @@ -669,6 +674,7 @@ class vim_thread(threading.Thread): task["vim_interfaces"] = {} task["extra"]["interfaces"] = task_interfaces task["extra"]["created"] = True + task["extra"]["created_items"] = created_items task["error_msg"] = None task["status"] = "DONE" task["vim_id"] = vim_vm_id @@ -698,7 +704,7 @@ class vim_thread(threading.Thread): iface["sdn_port_id"], vm_vim_id) + str(e), exc_info=True) # TODO Set error_msg at instance_nets - self.vim.delete_vminstance(vm_vim_id) + self.vim.delete_vminstance(vm_vim_id, task["extra"].get("created_items")) task["status"] = "DONE" task["error_msg"] = None return True, None @@ -713,6 +719,13 @@ class vim_thread(threading.Thread): return False, None def _get_net_internal(self, task, filter_param): + """ + Common code for get_net and new_net. It looks for a network on VIM with the filter_params + :param task: task for this find or find-or-create action + :param filter_param: parameters to send to the vimconnector + :return: a dict with the content to update the instance_nets database table. Raises an exception on error, or + when network is not found or found more than one + """ vim_nets = self.vim.get_network_list(filter_param) if not vim_nets: raise VimThreadExceptionNotFound("Network not found with this criteria: '{}'".format(filter)) diff --git a/osm_ro/vimconn.py b/osm_ro/vimconn.py index 1fbce190..1f609867 100644 --- a/osm_ro/vimconn.py +++ b/osm_ro/vimconn.py @@ -519,7 +519,11 @@ class vimconnector(): availability_zone_index: Index of availability_zone_list to use for this this VM. None if not AV required availability_zone_list: list of availability zones given by user in the VNFD descriptor. Ignore if availability_zone_index is None - Returns the instance identifier or raises an exception on error + Returns a tuple with the instance identifier and created_items or raises an exception on error + created_items can be None or a dictionary where this method can include key-values that will be passed to + the method delete_vminstance and action_vminstance. Can be used to store created ports, volumes, etc. + Format is vimconnector dependent, but do not use nested dictionaries and a value of None should be the same + as not present. """ raise vimconnNotImplemented( "Should have implemented this" ) @@ -527,9 +531,14 @@ class vimconnector(): """Returns the VM instance information from VIM""" raise vimconnNotImplemented( "Should have implemented this" ) - def delete_vminstance(self, vm_id): - """Removes a VM instance from VIM - Returns the instance identifier""" + def delete_vminstance(self, vm_id, created_items=None): + """ + Removes a VM instance from VIM and each associate elements + :param vm_id: VIM identifier of the VM, provided by method new_vminstance + :param created_items: dictionary with extra items to be deleted. provided by method new_vminstance and/or method + action_vminstance + :return: None or the same vm_id. Raises an exception on fail + """ raise vimconnNotImplemented( "Should have implemented this" ) def refresh_vms_status(self, vm_list): @@ -560,9 +569,18 @@ class vimconnector(): """ raise vimconnNotImplemented( "Should have implemented this" ) - def action_vminstance(self, vm_id, action_dict): - """Send and action over a VM instance from VIM - Returns the vm_id if the action was successfully sent to the VIM""" + def action_vminstance(self, vm_id, action_dict, created_items={}): + """ + Send and action over a VM instance. Returns created_items if the action was successfully sent to the VIM. + created_items is a dictionary with items that + :param vm_id: VIM identifier of the VM, provided by method new_vminstance + :param action_dict: dictionary with the action to perform + :param created_items: provided by method new_vminstance is a dictionary with key-values that will be passed to + the method delete_vminstance. Can be used to store created ports, volumes, etc. Format is vimconnector + dependent, but do not use nested dictionaries and a value of None should be the same as not present. This + method can modify this value + :return: None, or a console dict + """ raise vimconnNotImplemented( "Should have implemented this" ) def get_vminstance_console(self, vm_id, console_type="vnc"): diff --git a/osm_ro/vimconn_aws.py b/osm_ro/vimconn_aws.py index 3ccef44a..0e1f5739 100644 --- a/osm_ro/vimconn_aws.py +++ b/osm_ro/vimconn_aws.py @@ -634,7 +634,11 @@ class vimconnector(vimconn.vimconnector): disk_list': (optional) list with additional disks to the VM. Each item is a dict with: image_id': (optional). VIM id of an existing image. If not provided an empty disk must be mounted size': (mandatory) string with the size of the disk in GB - Returns: instance identifier or raises an exception on error + Returns a tuple with the instance identifier and created_items or raises an exception on error + created_items can be None or a dictionary where this method can include key-values that will be passed to + the method delete_vminstance and action_vminstance. Can be used to store created ports, volumes, etc. + Format is vimconnector dependent, but do not use nested dictionaries and a value of None should be the same + as not present. """ self.logger.debug("Creating a new VM instance") @@ -682,7 +686,7 @@ class vimconnector(vimconn.vimconnector): net_list[index]['vim_id'] = reservation.instances[0].interfaces[index].id instance = reservation.instances[0] - return instance.id + return instance.id, None except Exception as e: self.format_vimconn_exception(e) @@ -696,7 +700,7 @@ class vimconnector(vimconn.vimconnector): except Exception as e: self.format_vimconn_exception(e) - def delete_vminstance(self, vm_id): + def delete_vminstance(self, vm_id, created_items=None): """Removes a VM instance from VIM Returns the instance identifier""" @@ -772,7 +776,7 @@ class vimconnector(vimconn.vimconnector): self.logger.error("Exception getting vm status: %s", str(e), exc_info=True) self.format_vimconn_exception(e) - def action_vminstance(self, vm_id, action_dict): + def action_vminstance(self, vm_id, action_dict, created_items={}): """Send and action over a VM instance from VIM Returns the vm_id if the action was successfully sent to the VIM""" @@ -787,6 +791,6 @@ class vimconnector(vimconn.vimconnector): self.conn.terminate_instances(vm_id) elif "reboot" in action_dict: self.conn.reboot_instances(vm_id) - return vm_id + return None except Exception as e: self.format_vimconn_exception(e) diff --git a/osm_ro/vimconn_openstack.py b/osm_ro/vimconn_openstack.py index e90497a6..24033da7 100644 --- a/osm_ro/vimconn_openstack.py +++ b/osm_ro/vimconn_openstack.py @@ -936,7 +936,7 @@ class vimconnector(vimconn.vimconnector): def new_vminstance(self, name, description, start, image_id, flavor_id, net_list, cloud_config=None, disk_list=None, availability_zone_index=None, availability_zone_list=None): - '''Adds a VM instance to VIM + """Adds a VM instance to VIM Params: start: indicates if VM must start or boot in pause mode. Ignored image_id,flavor_id: iamge and flavor uuid @@ -971,20 +971,25 @@ class vimconnector(vimconn.vimconnector): availability_zone_list: list of availability zones given by user in the VNFD descriptor. Ignore if availability_zone_index is None #TODO ip, security groups - Returns the instance identifier - ''' + Returns a tuple with the instance identifier and created_items or raises an exception on error + created_items can be None or a dictionary where this method can include key-values that will be passed to + the method delete_vminstance and action_vminstance. Can be used to store created ports, volumes, etc. + Format is vimconnector dependent, but do not use nested dictionaries and a value of None should be the same + as not present. + """ self.logger.debug("new_vminstance input: image='%s' flavor='%s' nics='%s'",image_id, flavor_id,str(net_list)) try: server = None - metadata={} - net_list_vim=[] - external_network=[] # list of external networks to be connected to instance, later on used to create floating_ip + created_items = {} + metadata = {} + net_list_vim = [] + external_network = [] # list of external networks to be connected to instance, later on used to create floating_ip no_secured_ports = [] # List of port-is with port-security disabled self._reload_connection() - metadata_vpci={} # For a specific neutron plugin + metadata_vpci = {} # For a specific neutron plugin block_device_mapping = None for net in net_list: - if not net.get("net_id"): #skip non connected iface + if not net.get("net_id"): # skip non connected iface continue port_dict={ @@ -1024,6 +1029,7 @@ class vimconnector(vimconn.vimconnector): if net.get("mac_address"): port_dict["mac_address"]=net["mac_address"] new_port = self.neutron.create_port({"port": port_dict }) + created_items[("port", str(new_port["port"]["id"]))] = True net["mac_adress"] = new_port["port"]["mac_address"] net["vim_id"] = new_port["port"]["id"] # if try to use a network without subnetwork, it will return a emtpy list @@ -1064,10 +1070,10 @@ class vimconnector(vimconn.vimconnector): security_groups = self.config.get('security_groups') if type(security_groups) is str: security_groups = ( security_groups, ) - #cloud config + # cloud config config_drive, userdata = self._create_user_data(cloud_config) - #Create additional volumes in case these are present in disk_list + # Create additional volumes in case these are present in disk_list base_disk_index = ord('b') if disk_list != None: block_device_mapping = {} @@ -1078,10 +1084,11 @@ class vimconnector(vimconn.vimconnector): else: volume = self.cinder.volumes.create(size=disk['size'], name=name + '_vd' + chr(base_disk_index)) + created_items[("volume", str(volume.id))] = True block_device_mapping['_vd' + chr(base_disk_index)] = volume.id base_disk_index += 1 - #wait until volumes are with status available + # wait until volumes are with status available keep_waiting = True elapsed_time = 0 while keep_waiting and elapsed_time < volume_timeout: @@ -1093,17 +1100,8 @@ class vimconnector(vimconn.vimconnector): time.sleep(1) elapsed_time += 1 - #if we exceeded the timeout rollback + # if we exceeded the timeout rollback if elapsed_time >= volume_timeout: - #delete the volumes we just created - for volume_id in block_device_mapping.itervalues(): - self.cinder.volumes.delete(volume_id) - - #delete ports we just created - for net_item in net_list_vim: - if 'port-id' in net_item: - self.neutron.delete_port(net_item['port-id']) - raise vimconn.vimconnException('Timeout creating volumes for instance ' + name, http_code=vimconn.HTTP_Request_Timeout) # get availability Zone @@ -1130,23 +1128,21 @@ class vimconnector(vimconn.vimconnector): for port_id in no_secured_ports: try: self.neutron.update_port(port_id, {"port": {"port_security_enabled": False, "security_groups": None} }) - except Exception as e: self.logger.error("It was not possible to disable port security for port {}".format(port_id)) - self.delete_vminstance(server.id) raise - #print "DONE :-)", server - pool_id = None - floating_ips = self.neutron.list_floatingips().get("floatingips", ()) + # print "DONE :-)", server + pool_id = None if external_network: + floating_ips = self.neutron.list_floatingips().get("floatingips", ()) self.__wait_for_vm(server.id, 'ACTIVE') for floating_network in external_network: try: assigned = False - while(assigned == False): + while not assigned: if floating_ips: ip = floating_ips.pop(0) if not ip.get("port_id", False) and ip.get('tenant_id') == server.tenant_id: @@ -1190,7 +1186,7 @@ class vimconnector(vimconn.vimconnector): continue raise - return server.id + return server.id, created_items # except nvExceptions.NotFound as e: # error_value=-vimconn.HTTP_Not_Found # error_text= "vm instance %s not found" % vm_id @@ -1198,19 +1194,13 @@ class vimconnector(vimconn.vimconnector): # raise vimconn.vimconnException(type(e).__name__ + ": "+ str(e), http_code=vimconn.HTTP_Bad_Request) except Exception as e: - # delete the volumes we just created - if block_device_mapping: - for volume_id in block_device_mapping.itervalues(): - self.cinder.volumes.delete(volume_id) - - # Delete the VM - if server != None: - self.delete_vminstance(server.id) - else: - # delete ports we just created - for net_item in net_list_vim: - if 'port-id' in net_item: - self.neutron.delete_port(net_item['port-id']) + server_id = None + if server: + server_id = server.id + try: + self.delete_vminstance(server_id, created_items) + except Exception as e2: + self.logger.error("new_vminstance rollback fail {}".format(e2)) self._format_exception(e) @@ -1276,50 +1266,57 @@ class vimconnector(vimconn.vimconnector): except (nvExceptions.NotFound, ksExceptions.ClientException, nvExceptions.ClientException, nvExceptions.BadRequest, ConnectionError) as e: self._format_exception(e) - def delete_vminstance(self, vm_id): + def delete_vminstance(self, vm_id, created_items=None): '''Removes a VM instance from VIM. Returns the old identifier ''' #print "osconnector: Getting VM from VIM" + if created_items == None: + created_items = {} try: self._reload_connection() - #delete VM ports attached to this networks before the virtual machine - ports = self.neutron.list_ports(device_id=vm_id) - for p in ports['ports']: + # delete VM ports attached to this networks before the virtual machine + for k, v in created_items.items(): + if not v: # skip already deleted + continue try: - self.neutron.delete_port(p["id"]) + if k[0] == "port": + self.neutron.delete_port(k[1]) except Exception as e: self.logger.error("Error deleting port: " + type(e).__name__ + ": "+ str(e)) - #commented because detaching the volumes makes the servers.delete not work properly ?!? - #dettach volumes attached - server = self.nova.servers.get(vm_id) - volumes_attached_dict = server._info['os-extended-volumes:volumes_attached'] - #for volume in volumes_attached_dict: - # self.cinder.volumes.detach(volume['id']) + # #commented because detaching the volumes makes the servers.delete not work properly ?!? + # #dettach volumes attached + # server = self.nova.servers.get(vm_id) + # volumes_attached_dict = server._info['os-extended-volumes:volumes_attached'] #volume['id'] + # #for volume in volumes_attached_dict: + # # self.cinder.volumes.detach(volume['id']) - self.nova.servers.delete(vm_id) + if vm_id: + self.nova.servers.delete(vm_id) - #delete volumes. - #Although having detached them should have them in active status - #we ensure in this loop + # delete volumes. Although having detached, they should have in active status before deleting + # we ensure in this loop keep_waiting = True elapsed_time = 0 while keep_waiting and elapsed_time < volume_timeout: keep_waiting = False - for volume in volumes_attached_dict: - if self.cinder.volumes.get(volume['id']).status != 'available': - keep_waiting = True - else: - self.cinder.volumes.delete(volume['id']) + for k, v in created_items.items(): + if not v: # skip already deleted + continue + try: + if k[0] == "volume": + if self.cinder.volumes.get(k[1]).status != 'available': + keep_waiting = True + else: + self.cinder.volumes.delete(k[1]) + except Exception as e: + self.logger.error("Error deleting volume: " + type(e).__name__ + ": " + str(e)) if keep_waiting: time.sleep(1) elapsed_time += 1 - - return vm_id + return None except (nvExceptions.NotFound, ksExceptions.ClientException, nvExceptions.ClientException, ConnectionError) as e: self._format_exception(e) - #TODO insert exception vimconn.HTTP_Unauthorized - #if reaching here is because an exception def refresh_vms_status(self, vm_list): '''Get the status of the virtual machines and their interfaces/ports @@ -1423,9 +1420,9 @@ class vimconnector(vimconn.vimconnector): vm_dict[vm_id] = vm return vm_dict - def action_vminstance(self, vm_id, action_dict): + def action_vminstance(self, vm_id, action_dict, created_items={}): '''Send and action over a VM instance from VIM - Returns the vm_id if the action was successfully sent to the VIM''' + Returns None or the console dict if the action was successfully sent to the VIM''' self.logger.debug("Action over VM '%s': %s", vm_id, str(action_dict)) try: self._reload_connection() @@ -1492,7 +1489,7 @@ class vimconnector(vimconn.vimconnector): except Exception as e: raise vimconn.vimconnException("Unexpected response from VIM " + str(console_dict)) - return vm_id + return None except (ksExceptions.ClientException, nvExceptions.ClientException, nvExceptions.NotFound, ConnectionError) as e: self._format_exception(e) #TODO insert exception vimconn.HTTP_Unauthorized diff --git a/osm_ro/vimconn_openvim.py b/osm_ro/vimconn_openvim.py index 135cfc6c..b45edf64 100644 --- a/osm_ro/vimconn_openvim.py +++ b/osm_ro/vimconn_openvim.py @@ -800,7 +800,11 @@ class vimconnector(vimconn.vimconnector): type: 'virtual', 'PF', 'VF', 'VFnotShared' vim_id: filled/added by this function #TODO ip, security groups - Returns the instance identifier + Returns a tuple with the instance identifier and created_items or raises an exception on error + created_items can be None or a dictionary where this method can include key-values that will be passed to + the method delete_vminstance and action_vminstance. Can be used to store created ports, volumes, etc. + Format is vimconnector dependent, but do not use nested dictionaries and a value of None should be the same + as not present. ''' self.logger.debug("new_vminstance input: image='%s' flavor='%s' nics='%s'", image_id, flavor_id, str(net_list)) try: @@ -873,7 +877,7 @@ class vimconnector(vimconn.vimconnector): # return result, error_text break - return vminstance_id + return vminstance_id, None except (requests.exceptions.RequestException, js_e.ValidationError) as e: self._format_request_exception(e) @@ -897,7 +901,7 @@ class vimconnector(vimconn.vimconnector): except (requests.exceptions.RequestException, js_e.ValidationError) as e: self._format_request_exception(e) - def delete_vminstance(self, vm_id): + def delete_vminstance(self, vm_id, created_items=None): '''Removes a VM instance from VIM, returns the deleted vm_id''' try: self._get_my_tenant() @@ -1026,7 +1030,7 @@ class vimconnector(vimconn.vimconnector): net_dict[net_id] = net return net_dict - def action_vminstance(self, vm_id, action_dict): + def action_vminstance(self, vm_id, action_dict, created_items={}): '''Send and action over a VM instance from VIM''' '''Returns the status''' try: @@ -1037,7 +1041,7 @@ class vimconnector(vimconn.vimconnector): self.logger.info("Action over VM instance POST %s", url) vim_response = requests.post(url, headers = self.headers_req, data=json.dumps(action_dict) ) self._check_http_request_response(vim_response) - return vm_id + return None except (requests.exceptions.RequestException, js_e.ValidationError) as e: self._format_request_exception(e) diff --git a/osm_ro/vimconn_vmware.py b/osm_ro/vimconn_vmware.py index 82d6a697..f99ef653 100644 --- a/osm_ro/vimconn_vmware.py +++ b/osm_ro/vimconn_vmware.py @@ -1420,7 +1420,11 @@ class vimconnector(vimconn.vimconnector): availability_zone_index: Index of availability_zone_list to use for this this VM. None if not AV required availability_zone_list: list of availability zones given by user in the VNFD descriptor. Ignore if availability_zone_index is None - Returns the instance identifier or raises an exception on error + Returns a tuple with the instance identifier and created_items or raises an exception on error + created_items can be None or a dictionary where this method can include key-values that will be passed to + the method delete_vminstance and action_vminstance. Can be used to store created ports, volumes, etc. + Format is vimconnector dependent, but do not use nested dictionaries and a value of None should be the same + as not present. """ self.logger.info("Creating new instance for entry {}".format(name)) self.logger.debug("desc {} boot {} image_id: {} flavor_id: {} net_list: {} cloud_config {} disk_list {}".format( @@ -1767,7 +1771,7 @@ class vimconnector(vimconn.vimconnector): wait_time +=INTERVAL_TIME if vapp_uuid is not None: - return vapp_uuid + return vapp_uuid, None else: raise vimconn.vimconnUnexpectedResponse("new_vminstance(): Failed create new vm instance {}".format(name)) @@ -1825,7 +1829,7 @@ class vimconnector(vimconn.vimconnector): return vm_dict - def delete_vminstance(self, vm__vim_uuid): + def delete_vminstance(self, vm__vim_uuid, created_items=None): """Method poweroff and remove VM instance from vcloud director network. Args: @@ -2129,7 +2133,7 @@ class vimconnector(vimconn.vimconnector): self.logger.debug("ParseError in response from NSX Manager {}".format(Err.message), exc_info=True) - def action_vminstance(self, vm__vim_uuid=None, action_dict=None): + def action_vminstance(self, vm__vim_uuid=None, action_dict=None, created_items={}): """Send and action over a VM instance from VIM Returns the vm_id if the action was successfully sent to the VIM""" @@ -2139,7 +2143,7 @@ class vimconnector(vimconn.vimconnector): vdc = self.get_vdc_details() if vdc is None: - return -1, "Failed to get a reference of VDC for a tenant {}".format(self.tenant_name) + raise vimconn.vimconnException("Failed to get a reference of VDC for a tenant {}".format(self.tenant_name)) vapp_name = self.get_namebyvappid(vdc, vm__vim_uuid) if vapp_name is None: @@ -2191,7 +2195,7 @@ class vimconnector(vimconn.vimconnector): reboot_task = the_vapp.reboot() else: raise vimconn.vimconnException("action_vminstance: Invalid action {} or action is None.".format(action_dict)) - return vm__vim_uuid + return None except Exception as exp : self.logger.debug("action_vminstance: Failed with Exception {}".format(exp)) raise vimconn.vimconnException("action_vminstance: Failed with Exception {}".format(exp)) diff --git a/osm_ro/vmwarecli.py b/osm_ro/vmwarecli.py index 4583a651..80fe3949 100755 --- a/osm_ro/vmwarecli.py +++ b/osm_ro/vmwarecli.py @@ -554,7 +554,7 @@ def boot_image(vim=None, image_name=None, vm_name=None): return None print (" Booting {} image id {} ".format(vm_name, vim_catalog)) - vm_uuid = vim.new_vminstance(name=vm_name, image_id=vim_catalog) + vm_uuid, _ = vim.new_vminstance(name=vm_name, image_id=vim_catalog) if vm_uuid is not None and validate_uuid4(vm_uuid): print("Image booted and vm uuid {}".format(vm_uuid)) vapp_dict = vim.get_vapp(vdc_name=namespace.vcdvdc, vapp_name=vm_uuid, isuuid=True) diff --git a/osm_ro/vmwarerecli.py b/osm_ro/vmwarerecli.py index acd4240b..b2f1752f 100755 --- a/osm_ro/vmwarerecli.py +++ b/osm_ro/vmwarerecli.py @@ -553,7 +553,7 @@ def boot_image(vim=None, image_name=None, vm_name=None): return None print (" Booting {} image id {} ".format(vm_name, vim_catalog)) - vm_uuid = vim.new_vminstance(name=vm_name, image_id=vim_catalog) + vm_uuid, _ = vim.new_vminstance(name=vm_name, image_id=vim_catalog) if vm_uuid is not None and validate_uuid4(vm_uuid): print("Image booted and vm uuid {}".format(vm_uuid)) vapp_dict = vim.get_vapp(vdc_name=namespace.vcdvdc, vapp_name=vm_uuid, isuuid=True) diff --git a/test/test_RO.py b/test/test_RO.py index 0e7a5e6b..26848922 100755 --- a/test/test_RO.py +++ b/test/test_RO.py @@ -1005,7 +1005,7 @@ class test_vimconn_new_vminstance(test_base): net_list = [{'use': self.__class__.net_type, 'name': name, 'floating_ip': False, 'vpci': vpci, 'port_security': True, 'type': 'virtual', 'net_id': self.__class__.network_id}] - self.__class__.instance_id = test_config["vim_conn"].new_vminstance(name='Test1_vm', image_id=self.__class__.image_id, flavor_id=flavor_id, net_list=net_list) + self.__class__.instance_id, _ = test_config["vim_conn"].new_vminstance(name='Test1_vm', image_id=self.__class__.image_id, flavor_id=flavor_id, net_list=net_list) self.assertEqual(type(self.__class__.instance_id),str) @@ -1024,7 +1024,7 @@ class test_vimconn_new_vminstance(test_base): net_list = [{'use': self.__class__.net_type, 'name': name, 'floating_ip': False, 'port_security': True, 'model': model_name, 'type': 'virtual', 'net_id': self.__class__.network_id}] - instance_id = test_config["vim_conn"].new_vminstance(name='Test1_vm', image_id=self.__class__.image_id, + instance_id, _ = test_config["vim_conn"].new_vminstance(name='Test1_vm', image_id=self.__class__.image_id, flavor_id=flavor_id, net_list=net_list) self.assertEqual(type(instance_id),str) @@ -1048,7 +1048,7 @@ class test_vimconn_new_vminstance(test_base): net_list = [{'use': net_use, 'name': name, 'floating_ip': False, 'port_security': True, 'type': 'virtual', 'net_id': self.__class__.network_id}] - instance_id = test_config["vim_conn"].new_vminstance(name='Test1_vm', image_id=self.__class__.image_id, + instance_id, _ = test_config["vim_conn"].new_vminstance(name='Test1_vm', image_id=self.__class__.image_id, flavor_id=flavor_id, net_list=net_list) self.assertEqual(type(instance_id),str) @@ -1072,7 +1072,7 @@ class test_vimconn_new_vminstance(test_base): net_list = [{'use': self.__class__.net_type, 'name': name, 'floating_ip': False, 'port_security': True, 'type': _type, 'net_id': self.__class__.network_id}] - instance_id = test_config["vim_conn"].new_vminstance(name='Test1_vm', image_id=self.__class__.image_id, + instance_id, _ = test_config["vim_conn"].new_vminstance(name='Test1_vm', image_id=self.__class__.image_id, flavor_id=flavor_id, net_list=net_list) self.assertEqual(type(instance_id),str) @@ -1102,7 +1102,7 @@ class test_vimconn_new_vminstance(test_base): net_list = [{'use': self.__class__.net_type, 'name': name, 'floating_ip': False, 'port_security': True, 'type': 'virtual', 'net_id': self.__class__.network_id}] - instance_id = test_config["vim_conn"].new_vminstance(name='Cloud_vm', image_id=self.__class__.image_id, + instance_id, _ = test_config["vim_conn"].new_vminstance(name='Cloud_vm', image_id=self.__class__.image_id, flavor_id=flavor_id, net_list=net_list, cloud_config=cloud_data) @@ -1128,7 +1128,7 @@ class test_vimconn_new_vminstance(test_base): net_list = [{'use': self.__class__.net_type, 'name': name, 'floating_ip': False, 'port_security': True, 'type': 'virtual', 'net_id': self.__class__.network_id}] - instance_id = test_config["vim_conn"].new_vminstance(name='VM_test1', image_id=self.__class__.image_id, + instance_id, _ = test_config["vim_conn"].new_vminstance(name='VM_test1', image_id=self.__class__.image_id, flavor_id=flavor_id, net_list=net_list, disk_list=device_data)