X-Git-Url: https://osm.etsi.org/gitweb/?a=blobdiff_plain;f=osm_ro%2Fvimconn_openstack.py;h=55f910b4499672655b6c46203ee4c887bcef6ab1;hb=a6eff0a68fb60108545b81215f9551097f4bfd40;hp=fd16f544d2cc721d32ea8054af3dac72d55f169e;hpb=69b590eb0469efa021bada0d2bf867bbdff27a10;p=osm%2FRO.git diff --git a/osm_ro/vimconn_openstack.py b/osm_ro/vimconn_openstack.py index fd16f544..55f910b4 100644 --- a/osm_ro/vimconn_openstack.py +++ b/osm_ro/vimconn_openstack.py @@ -353,7 +353,7 @@ class vimconnector(vimconn.vimconnector): elif isinstance(exception, nvExceptions.Conflict): raise vimconn.vimconnConflictException(type(exception).__name__ + ": " + str(exception)) elif isinstance(exception, vimconn.vimconnException): - raise + raise exception else: # () self.logger.error("General Exception " + str(exception), exc_info=True) raise vimconn.vimconnConnectionException(type(exception).__name__ + ": " + str(exception)) @@ -443,7 +443,7 @@ class vimconnector(vimconn.vimconnector): #create subnetwork, even if there is no profile if not ip_profile: ip_profile = {} - if 'subnet_address' not in ip_profile: + if not ip_profile.get('subnet_address'): #Fake subnet is required subnet_rand = random.randint(0, 255) ip_profile['subnet_address'] = "192.168.{}.0/24".format(subnet_rand) @@ -455,16 +455,18 @@ class vimconnector(vimconn.vimconnector): "cidr": ip_profile['subnet_address'] } # Gateway should be set to None if not needed. Otherwise openstack assigns one by default - subnet['gateway_ip'] = ip_profile.get('gateway_address') + if ip_profile.get('gateway_address'): + subnet['gateway_ip'] = ip_profile.get('gateway_address') if ip_profile.get('dns_address'): subnet['dns_nameservers'] = ip_profile['dns_address'].split(";") if 'dhcp_enabled' in ip_profile: - subnet['enable_dhcp'] = False if ip_profile['dhcp_enabled']=="false" else True - if 'dhcp_start_address' in ip_profile: + subnet['enable_dhcp'] = False if \ + ip_profile['dhcp_enabled']=="false" or ip_profile['dhcp_enabled']==False else True + if ip_profile.get('dhcp_start_address'): subnet['allocation_pools'] = [] subnet['allocation_pools'].append(dict()) subnet['allocation_pools'][0]['start'] = ip_profile['dhcp_start_address'] - if 'dhcp_count' in ip_profile: + if ip_profile.get('dhcp_count'): #parts = ip_profile['dhcp_start_address'].split('.') #ip_int = (int(parts[0]) << 24) + (int(parts[1]) << 16) + (int(parts[2]) << 8) + int(parts[3]) ip_int = int(netaddr.IPAddress(ip_profile['dhcp_start_address'])) @@ -474,7 +476,7 @@ class vimconnector(vimconn.vimconnector): #self.logger.debug(">>>>>>>>>>>>>>>>>> Subnet: %s", str(subnet)) self.neutron.create_subnet({"subnet": subnet} ) return new_net["network"]["id"] - except (neExceptions.ConnectionFailed, ksExceptions.ClientException, neExceptions.NeutronException, ConnectionError) as e: + except Exception as e: if new_net: self.neutron.delete_network(new_net['network']['id']) self._format_exception(e) @@ -953,20 +955,20 @@ class vimconnector(vimconn.vimconnector): type: 'virtual', 'PCI-PASSTHROUGH'('PF'), 'SR-IOV'('VF'), 'VFnotShared' vim_id: filled/added by this function floating_ip: True/False (or it can be None) - 'cloud_config': (optional) dictionary with: - 'key-pairs': (optional) list of strings with the public key to be inserted to the default user - 'users': (optional) list of users to be inserted, each item is a dict with: - 'name': (mandatory) user name, - 'key-pairs': (optional) list of strings with the public key to be inserted to the user - 'user-data': (optional) string is a text script to be passed directly to cloud-init - 'config-files': (optional). List of files to be transferred. Each item is a dict with: - 'dest': (mandatory) string with the destination absolute path - 'encoding': (optional, by default text). Can be one of: - 'b64', 'base64', 'gz', 'gz+b64', 'gz+base64', 'gzip+b64', 'gzip+base64' - 'content' (mandatory): string with the content of the file - 'permissions': (optional) string with file permissions, typically octal notation '0644' - 'owner': (optional) file owner, string with the format 'owner:group' - 'boot-data-drive': boolean to indicate if user-data must be passed using a boot drive (hard disk) + 'cloud_config': (optional) dictionary with: + 'key-pairs': (optional) list of strings with the public key to be inserted to the default user + 'users': (optional) list of users to be inserted, each item is a dict with: + 'name': (mandatory) user name, + 'key-pairs': (optional) list of strings with the public key to be inserted to the user + 'user-data': (optional) string is a text script to be passed directly to cloud-init + 'config-files': (optional). List of files to be transferred. Each item is a dict with: + 'dest': (mandatory) string with the destination absolute path + 'encoding': (optional, by default text). Can be one of: + 'b64', 'base64', 'gz', 'gz+b64', 'gz+base64', 'gzip+b64', 'gzip+base64' + 'content' (mandatory): string with the content of the file + 'permissions': (optional) string with file permissions, typically octal notation '0644' + 'owner': (optional) file owner, string with the format 'owner:group' + 'boot-data-drive': boolean to indicate if user-data must be passed using a boot drive (hard disk) '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 @@ -1033,6 +1035,9 @@ class vimconnector(vimconn.vimconnector): port_dict["name"]=name if net.get("mac_address"): port_dict["mac_address"]=net["mac_address"] + if net.get("ip_address"): + port_dict["fixed_ips"] = [{'ip_address': net["ip_address"]}] + # TODO add 'subnet_id': 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"] @@ -1055,6 +1060,7 @@ class vimconnector(vimconn.vimconnector): elif net['use'] == 'mgmt' and self.config.get('use_floating_ip'): net['exit_on_floating_ip_error'] = False external_network.append(net) + net['floating_ip'] = self.config.get('use_floating_ip') # If port security is disabled when the port has not yet been attached to the VM, then all vm traffic is dropped. # As a workaround we wait until the VM is active and then disable the port-security @@ -1126,6 +1132,7 @@ class vimconnector(vimconn.vimconnector): block_device_mapping=block_device_mapping ) # , description=description) + vm_start_time = time.time() # Previously mentioned workaround to wait until the VM is active and then disable the port-security if no_secured_ports: self.__wait_for_vm(server.id, 'ACTIVE') @@ -1142,49 +1149,61 @@ class vimconnector(vimconn.vimconnector): 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 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: - free_floating_ip = ip.get("floating_ip_address") - try: - fix_ip = floating_network.get('ip') - server.add_floating_ip(free_floating_ip, fix_ip) - assigned = True - except Exception as e: - raise vimconn.vimconnException(type(e).__name__ + ": Cannot create floating_ip "+ str(e), http_code=vimconn.HTTP_Conflict) + if ip.get("port_id", False) or ip.get('tenant_id') != server.tenant_id: + continue + if isinstance(floating_network['floating_ip'], str): + if ip.get("floating_network_id") != floating_network['floating_ip']: + continue + free_floating_ip = ip.get("floating_ip_address") else: - #Find the external network - external_nets = list() - for net in self.neutron.list_networks()['networks']: - if net['router:external']: - external_nets.append(net) - - if len(external_nets) == 0: - raise vimconn.vimconnException("Cannot create floating_ip automatically since no external " - "network is present", - http_code=vimconn.HTTP_Conflict) - if len(external_nets) > 1: - raise vimconn.vimconnException("Cannot create floating_ip automatically since multiple " - "external networks are present", - http_code=vimconn.HTTP_Conflict) - - pool_id = external_nets[0].get('id') + if isinstance(floating_network['floating_ip'], str): + pool_id = floating_network['floating_ip'] + else: + #Find the external network + external_nets = list() + for net in self.neutron.list_networks()['networks']: + if net['router:external']: + external_nets.append(net) + + if len(external_nets) == 0: + raise vimconn.vimconnException("Cannot create floating_ip automatically since no external " + "network is present", + http_code=vimconn.HTTP_Conflict) + if len(external_nets) > 1: + raise vimconn.vimconnException("Cannot create floating_ip automatically since multiple " + "external networks are present", + http_code=vimconn.HTTP_Conflict) + + pool_id = external_nets[0].get('id') param = {'floatingip': {'floating_network_id': pool_id, 'tenant_id': server.tenant_id}} try: #self.logger.debug("Creating floating IP") new_floating_ip = self.neutron.create_floatingip(param) free_floating_ip = new_floating_ip['floatingip']['floating_ip_address'] - fix_ip = floating_network.get('ip') + except Exception as e: + raise vimconn.vimconnException(type(e).__name__ + ": Cannot create new floating_ip " + + str(e), http_code=vimconn.HTTP_Conflict) + + fix_ip = floating_network.get('ip') + while not assigned: + try: server.add_floating_ip(free_floating_ip, fix_ip) - assigned=True + assigned = True except Exception as e: - raise vimconn.vimconnException(type(e).__name__ + ": Cannot assign floating_ip "+ str(e), http_code=vimconn.HTTP_Conflict) + vm_status = self.nova.servers.get(server.id).status + if vm_status != 'ACTIVE' and vm_status != 'ERROR': + if time.time() - vm_start_time < server_timeout: + time.sleep(5) + continue + raise vimconn.vimconnException(type(e).__name__ + ": Cannot create floating_ip "+ str(e), + http_code=vimconn.HTTP_Conflict) + except Exception as e: if not floating_network['exit_on_floating_ip_error']: self.logger.warn("Cannot create floating_ip. %s", str(e)) @@ -1593,8 +1612,7 @@ class vimconnector(vimconn.vimconnector): error_text= type(e).__name__ + ": "+ (str(e) if len(e.args)==0 else str(e.args[0])) #TODO insert exception vimconn.HTTP_Unauthorized #if reaching here is because an exception - if self.debug: - self.logger.debug("new_user " + error_text) + self.logger.debug("new_user " + error_text) return error_value, error_text def delete_user(self, user_id): @@ -1617,8 +1635,7 @@ class vimconnector(vimconn.vimconnector): error_text= type(e).__name__ + ": "+ (str(e) if len(e.args)==0 else str(e.args[0])) #TODO insert exception vimconn.HTTP_Unauthorized #if reaching here is because an exception - if self.debug: - print("delete_tenant " + error_text) + self.logger.debug("delete_tenant " + error_text) return error_value, error_text def get_hosts_info(self): @@ -1641,8 +1658,7 @@ class vimconnector(vimconn.vimconnector): error_text= type(e).__name__ + ": "+ (str(e) if len(e.args)==0 else str(e.args[0])) #TODO insert exception vimconn.HTTP_Unauthorized #if reaching here is because an exception - if self.debug: - print("get_hosts_info " + error_text) + self.logger.debug("get_hosts_info " + error_text) return error_value, error_text def get_hosts(self, vim_tenant): @@ -1670,8 +1686,7 @@ class vimconnector(vimconn.vimconnector): error_text= type(e).__name__ + ": "+ (str(e) if len(e.args)==0 else str(e.args[0])) #TODO insert exception vimconn.HTTP_Unauthorized #if reaching here is because an exception - if self.debug: - print("get_hosts " + error_text) + self.logger.debug("get_hosts " + error_text) return error_value, error_text def new_classification(self, name, ctype, definition): @@ -1827,9 +1842,9 @@ class vimconnector(vimconn.vimconnector): try: new_sf = None self._reload_connection() - correlation = None - if sfc_encap: - correlation = 'nsh' + # correlation = None + # if sfc_encap: + # correlation = 'nsh' for instance in sfis: sfi = self.get_sfi(instance) if sfi.get('sfc_encap') != sfc_encap: