From: tierno Date: Fri, 16 Feb 2018 13:34:33 +0000 (+0100) Subject: Features 5648 5650 5651 X-Git-Tag: v4.0.0~39 X-Git-Url: https://osm.etsi.org/gitweb/?p=osm%2FRO.git;a=commitdiff_plain;h=41a6981cd96a7e4ae15e881bc868873fbfaa3937 Features 5648 5650 5651 Change-Id: I3542587777f124badf75aa4285d9fad5e25a1a0a Signed-off-by: tierno --- diff --git a/openmanod b/openmanod index c273f81a..5b68ce47 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.52-r562" +__version__ = "0.5.53-r563" version_date = "Mar 2018" database_version = 28 # expected database schema version diff --git a/osm_ro/nfvo.py b/osm_ro/nfvo.py index bf32c245..b94d13b4 100644 --- a/osm_ro/nfvo.py +++ b/osm_ro/nfvo.py @@ -838,6 +838,8 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor): db_interfaces = [] db_images = [] db_flavors = [] + db_ip_profiles_index = 0 + db_ip_profiles = [] uuid_list = [] vnfd_uuid_list = [] vnfd_catalog_descriptor = vnf_descriptor.get("vnfd:vnfd-catalog") @@ -869,6 +871,27 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor): if vnfd_descriptor["id"] == str(vnfd["id"]): break + # table ip_profiles (ip-profiles) + ip_profile_name2db_table_index = {} + for ip_profile in vnfd.get("ip-profiles").itervalues(): + db_ip_profile = { + "ip_version": str(ip_profile["ip-profile-params"].get("ip-version", "ipv4")), + "subnet_address": str(ip_profile["ip-profile-params"].get("subnet-address")), + "gateway_address": str(ip_profile["ip-profile-params"].get("gateway-address")), + "dhcp_enabled": str(ip_profile["ip-profile-params"]["dhcp-params"].get("enabled", True)), + "dhcp_start_address": str(ip_profile["ip-profile-params"]["dhcp-params"].get("start-address")), + "dhcp_count": str(ip_profile["ip-profile-params"]["dhcp-params"].get("count")), + } + dns_list = [] + for dns in ip_profile["ip-profile-params"]["dns-server"].itervalues(): + dns_list.append(str(dns.get("address"))) + db_ip_profile["dns_address"] = ";".join(dns_list) + if ip_profile["ip-profile-params"].get('security-group'): + db_ip_profile["security_group"] = ip_profile["ip-profile-params"]['security-group'] + ip_profile_name2db_table_index[str(ip_profile["name"])] = db_ip_profiles_index + db_ip_profiles_index += 1 + db_ip_profiles.append(db_ip_profile) + # table nets (internal-vld) net_id2uuid = {} # for mapping interface with network for vld in vnfd.get("internal-vld").itervalues(): @@ -883,6 +906,22 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor): } net_id2uuid[vld.get("id")] = net_uuid db_nets.append(db_net) + # ip-profile, link db_ip_profile with db_sce_net + if vld.get("ip-profile-ref"): + ip_profile_name = vld.get("ip-profile-ref") + if ip_profile_name not in ip_profile_name2db_table_index: + raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{}]':'vld[{}]':'ip-profile-ref':" + "'{}'. Reference to a non-existing 'ip_profiles'".format( + str(vnfd["id"]), str(vld["id"]), str(vld["ip-profile-ref"])), + HTTP_Bad_Request) + db_ip_profiles[ip_profile_name2db_table_index[ip_profile_name]]["net_id"] = net_uuid + else: #check no ip-address has been defined + for icp in vld.get("internal-connection-point"): + if icp.get("ip-address"): + raise NfvoException("Error at 'vnfd[{}]':'vld[{}]':'internal-connection-point[{}]' " + "contains an ip-address but no ip-profile has been defined at VLD".format( + str(vnfd["id"]), str(vld["id"]), str(icp["id"])), + HTTP_Bad_Request) # connection points vaiable declaration cp_name2iface_uuid = {} @@ -893,6 +932,10 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor): vdu_id2uuid = {} vdu_id2db_table_index = {} for vdu in vnfd.get("vdu").itervalues(): + + for vdu_descriptor in vnfd_descriptor["vdu"]: + if vdu_descriptor["id"] == str(vdu["id"]): + break vm_uuid = str(uuid4()) uuid_list.append(vm_uuid) vdu_id = get_str(vdu, "id", 255) @@ -1043,27 +1086,43 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor): HTTP_Bad_Request) elif iface.get("internal-connection-point-ref"): try: + for icp_descriptor in vdu_descriptor["internal-connection-point"]: + if icp_descriptor["id"] == str(iface.get("internal-connection-point-ref")): + break + else: + raise KeyError("does not exist at vdu:internal-connection-point") + icp = None + icp_vld = None for vld in vnfd.get("internal-vld").itervalues(): for cp in vld.get("internal-connection-point").itervalues(): if cp.get("id-ref") == iface.get("internal-connection-point-ref"): - db_interface["net_id"] = net_id2uuid[vld.get("id")] - for cp_descriptor in vnfd_descriptor["connection-point"]: - if cp_descriptor["name"] == db_interface["internal_name"]: - break - if str(cp_descriptor.get("port-security-enabled")).lower() == "false": - db_interface["port_security"] = 0 - elif str(cp_descriptor.get("port-security-enabled")).lower() == "true": - db_interface["port_security"] = 1 - break - except KeyError: + if icp: + raise KeyError("is referenced by more than one 'internal-vld'") + icp = cp + icp_vld = vld + if not icp: + raise KeyError("is not referenced by any 'internal-vld'") + + db_interface["net_id"] = net_id2uuid[icp_vld.get("id")] + if str(icp_descriptor.get("port-security-enabled")).lower() == "false": + db_interface["port_security"] = 0 + elif str(icp_descriptor.get("port-security-enabled")).lower() == "true": + db_interface["port_security"] = 1 + if icp.get("ip-address"): + if not icp_vld.get("ip-profile-ref"): + raise NfvoException + db_interface["ip_address"] = str(icp.get("ip-address")) + except KeyError as e: raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'vdu[{vdu}]':" - "'interface[{iface}]':'internal-connection-point-ref':'{cp}' is not" - " referenced by any internal-vld".format( + "'interface[{iface}]':'internal-connection-point-ref':'{cp}'" + " {msg}".format( vnf=vnfd_id, vdu=vdu_id, iface=iface["name"], - cp=iface.get("internal-connection-point-ref")), + cp=iface.get("internal-connection-point-ref"), msg=str(e)), HTTP_Bad_Request) if iface.get("position") is not None: db_interface["created_at"] = int(iface.get("position")) - 1000 + if iface.get("mac-address"): + db_interface["mac"] = str(iface.get("mac-address")) db_interfaces.append(db_interface) # table flavors @@ -1189,14 +1248,13 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor): if mgmt_access: db_vnf["mgmt_access"] = yaml.safe_dump(mgmt_access, default_flow_style=True, width=256) - - db_vnfs.append(db_vnf) db_tables=[ {"vnfs": db_vnfs}, {"nets": db_nets}, {"images": db_images}, {"flavors": db_flavors}, + {"ip_profiles": db_ip_profiles}, {"vms": db_vms}, {"interfaces": db_interfaces}, ] @@ -2255,12 +2313,15 @@ def new_nsd_v3(mydb, tenant_id, nsd_descriptor): db_sce_net["type"] = "data" sce_interface_uuid = str(uuid4()) uuid_list.append(sce_net_uuid) + iface_ip_address = None + if iface.get("ip-address"): + iface_ip_address = str(iface.get("ip-address")) db_sce_interface = { "uuid": sce_interface_uuid, "sce_vnf_id": vnf_index2scevnf_uuid[vnf_index], "sce_net_id": sce_net_uuid, "interface_id": interface_uuid, - # "ip_address": #TODO + "ip_address": iface_ip_address, } db_sce_interfaces.append(db_sce_interface) if not db_sce_net["type"]: @@ -2929,7 +2990,7 @@ def create_instance(mydb, tenant_id, instance_dict): # 0.2 merge instance information into scenario # Ideally, the operation should be as simple as: update(scenarioDict,instance_dict) # However, this is not possible yet. - for net_name, net_instance_desc in instance_dict.get("networks",{}).iteritems(): + for net_name, net_instance_desc in instance_dict.get("networks", {}).iteritems(): for scenario_net in scenarioDict['nets']: if net_name == scenario_net["name"]: if 'ip-profile' in net_instance_desc: @@ -2950,13 +3011,13 @@ def create_instance(mydb, tenant_id, instance_dict): scenario_net['ip_profile'] = ipprofile_db else: update(scenario_net['ip_profile'], ipprofile_db) - for interface in net_instance_desc.get('interfaces', () ): + for interface in net_instance_desc.get('interfaces', ()): if 'ip_address' in interface: for vnf in scenarioDict['vnfs']: if interface['vnf'] == vnf['name']: for vnf_interface in vnf['interfaces']: if interface['vnf_interface'] == vnf_interface['external_name']: - vnf_interface['ip_address']=interface['ip_address'] + vnf_interface['ip_address'] = interface['ip_address'] # logger.debug(">>>>>>>> Merged dictionary") # logger.debug("Creating instance scenario-dict MERGED:\n%s", @@ -3230,50 +3291,53 @@ def create_instance(mydb, tenant_id, instance_dict): db_vm_ifaces = [] for iface in vm['interfaces']: netDict = {} - if iface['type']=="data": + if iface['type'] == "data": netDict['type'] = iface['model'] - elif "model" in iface and iface["model"]!=None: - netDict['model']=iface['model'] + elif "model" in iface and iface["model"] != None: + netDict['model'] = iface['model'] # TODO in future, remove this because mac_address will not be set, and the type of PV,VF # is obtained from iterface table model # discover type of interface looking at flavor - for numa in flavor_dict.get('extended',{}).get('numas',[]): - for flavor_iface in numa.get('interfaces',[]): + for numa in flavor_dict.get('extended', {}).get('numas', []): + for flavor_iface in numa.get('interfaces', []): if flavor_iface.get('name') == iface['internal_name']: if flavor_iface['dedicated'] == 'yes': - netDict['type']="PF" #passthrough + netDict['type'] = "PF" # passthrough elif flavor_iface['dedicated'] == 'no': - netDict['type']="VF" #siov + netDict['type'] = "VF" # siov elif flavor_iface['dedicated'] == 'yes:sriov': - netDict['type']="VFnotShared" #sriov but only one sriov on the PF + netDict['type'] = "VFnotShared" # sriov but only one sriov on the PF netDict["mac_address"] = flavor_iface.get("mac_address") - break; + break netDict["use"]=iface['type'] - if netDict["use"]=="data" and not netDict.get("type"): - #print "netDict", netDict - #print "iface", iface - e_text = "Cannot determine the interface type PF or VF of VNF '%s' VM '%s' iface '%s'" %(sce_vnf['name'], vm['name'], iface['internal_name']) - if flavor_dict.get('extended')==None: + if netDict["use"] == "data" and not netDict.get("type"): + # print "netDict", netDict + # print "iface", iface + e_text = "Cannot determine the interface type PF or VF of VNF '{}' VM '{}' iface '{}'".fromat( + sce_vnf['name'], vm['name'], iface['internal_name']) + if flavor_dict.get('extended') == None: raise NfvoException(e_text + "After database migration some information is not available. \ Try to delete and create the scenarios and VNFs again", HTTP_Conflict) else: raise NfvoException(e_text, HTTP_Internal_Server_Error) - if netDict["use"]=="mgmt" or netDict["use"]=="bridge": + if netDict["use"] == "mgmt" or netDict["use"] == "bridge": netDict["type"]="virtual" - if "vpci" in iface and iface["vpci"] is not None: + if iface.get("vpci"): netDict['vpci'] = iface['vpci'] - if "mac" in iface and iface["mac"] is not None: + if iface.get("mac"): netDict['mac_address'] = iface['mac'] - if "port-security" in iface and iface["port-security"] is not None: + if iface.get("ip_address"): + netDict['ip_address'] = iface['ip_address'] + if iface.get("port-security") is not None: netDict['port_security'] = iface['port-security'] - if "floating-ip" in iface and iface["floating-ip"] is not None: + if iface.get("floating-ip") is not None: netDict['floating_ip'] = iface['floating-ip'] netDict['name'] = iface['internal_name'] if iface['net_id'] is None: for vnf_iface in sce_vnf["interfaces"]: # print iface # print vnf_iface - if vnf_iface['interface_id']==iface['uuid']: + if vnf_iface['interface_id'] == iface['uuid']: netDict['net_id'] = "TASK-{}".format(net2task_id['scenario'][ vnf_iface['sce_net_id'] ][datacenter_id]) instance_net_id = sce_net2instance[ vnf_iface['sce_net_id'] ][datacenter_id] task_depends_on.append(net2task_id['scenario'][ vnf_iface['sce_net_id'] ][datacenter_id]) @@ -3294,6 +3358,7 @@ def create_instance(mydb, tenant_id, instance_dict): # 'vim_interface_id': , 'type': 'external' if iface['external_name'] is not None else 'internal', 'ip_address': iface.get('ip_address'), + 'mac_address': iface.get('mac'), 'floating_ip': int(iface.get('floating-ip', False)), 'port_security': int(iface.get('port-security', True)) } @@ -3327,8 +3392,8 @@ def create_instance(mydb, tenant_id, instance_dict): for net in myVMDict['networks']: if "vim_id" in net: for iface in vm['interfaces']: - if net["name"]==iface["internal_name"]: - iface["vim_id"]=net["vim_id"] + if net["name"] == iface["internal_name"]: + iface["vim_id"] = net["vim_id"] break vm_uuid = str(uuid4()) uuid_list.append(vm_uuid) diff --git a/osm_ro/nfvo_db.py b/osm_ro/nfvo_db.py index 87e3f1e1..055699e4 100644 --- a/osm_ro/nfvo_db.py +++ b/osm_ro/nfvo_db.py @@ -598,14 +598,14 @@ class nfvo_db(db_base.db_base): vnf['mgmt_access'] = yaml.load(mgmt_access_dict[0]['mgmt_access']) else: vnf['mgmt_access'] = None - #sce_interfaces + # sce_interfaces cmd = "SELECT scei.uuid,scei.sce_net_id,scei.interface_id,i.external_name,scei.ip_address"\ " FROM sce_interfaces as scei join interfaces as i on scei.interface_id=i.uuid"\ " WHERE scei.sce_vnf_id='{}' ORDER BY scei.created_at".format(vnf['uuid']) self.logger.debug(cmd) self.cur.execute(cmd) vnf['interfaces'] = self.cur.fetchall() - #vms + # vms cmd = "SELECT vms.uuid as uuid, flavor_id, image_id, vms.name as name," \ " vms.description as description, vms.boot_data as boot_data, count," \ " vms.availability_zone as availability_zone" \ @@ -643,9 +643,14 @@ class nfvo_db(db_base.db_base): self.logger.debug(cmd) self.cur.execute(cmd) vm['interfaces'] = self.cur.fetchall() - for index in range(0,len(vm['interfaces'])): - vm['interfaces'][index]['port-security'] = vm['interfaces'][index].pop("port_security") - vm['interfaces'][index]['floating-ip'] = vm['interfaces'][index].pop("floating_ip") + for iface in vm['interfaces']: + iface['port-security'] = iface.pop("port_security") + iface['floating-ip'] = iface.pop("floating_ip") + for sce_interface in vnf["interfaces"]: + if sce_interface["interface_id"] == iface["uuid"]: + if sce_interface["ip_address"]: + iface["ip_address"] = sce_interface["ip_address"] + break #nets every net of a vms cmd = "SELECT uuid,name,type,description FROM nets WHERE vnf_id='{}'".format(vnf['vnf_id']) self.logger.debug(cmd) diff --git a/osm_ro/openmano_schemas.py b/osm_ro/openmano_schemas.py index 9e15ac53..34d3ba48 100644 --- a/osm_ro/openmano_schemas.py +++ b/osm_ro/openmano_schemas.py @@ -101,9 +101,9 @@ config_schema = { "http_console_host": nameshort_schema, "http_console_ports": { "type": "array", - "items": {"OneOf" : [ + "items": {"OneOf": [ port_schema, - {"type":"object", "properties":{"from": port_schema, "to": port_schema}, "required": ["from","to"]} + {"type": "object", "properties": {"from": port_schema, "to": port_schema}, "required": ["from", "to"]} ]} }, "log_level": log_level_schema, @@ -300,22 +300,22 @@ datacenter_associate_schema={ } dhcp_schema = { - "title":"DHCP schema", + "title": "DHCP schema", "$schema": "http://json-schema.org/draft-04/schema#", - "type":"object", + "type": "object", "properties":{ "enabled": {"type": "boolean"}, - "start-address": ip_schema, - "count": integer1_schema + "start-address": {"OneOf": [{"type": "null"}, ip_schema]}, + "count": integer0_schema }, "required": ["enabled", "start-address", "count"], } ip_profile_schema = { - "title":"IP profile schema", + "title": "IP profile schema", "$schema": "http://json-schema.org/draft-04/schema#", - "type":"object", - "properties":{ + "type": "object", + "properties": { "ip-version": {"type": "string", "enum": ["IPv4","IPv6"]}, "subnet-address": ip_prefix_schema, "gateway-address": ip_schema, diff --git a/osm_ro/vimconn.py b/osm_ro/vimconn.py index bdfcb150..fd8f9be0 100644 --- a/osm_ro/vimconn.py +++ b/osm_ro/vimconn.py @@ -321,15 +321,14 @@ class vimconnector(): 'bridge': overlay isolated network 'data': underlay E-LAN network for Passthrough and SRIOV interfaces 'ptp': underlay E-LINE network for Passthrough and SRIOV interfaces. - 'ip_profile': is a dict containing the IP parameters of the network (Currently only IPv4 is implemented) - 'ip-version': can be one of ["IPv4","IPv6"] - 'subnet-address': ip_prefix_schema, that is X.X.X.X/Y - 'gateway-address': (Optional) ip_schema, that is X.X.X.X - 'dns-address': (Optional) ip_schema, - 'dhcp': (Optional) dict containing - 'enabled': {"type": "boolean"}, - 'start-address': ip_schema, first IP to grant - 'count': number of IPs to grant. + 'ip_profile': is a dict containing the IP parameters of the network + 'ip_version': can be "IPv4" or "IPv6" (Currently only IPv4 is implemented) + 'subnet_address': ip_prefix_schema, that is X.X.X.X/Y + 'gateway_address': (Optional) ip_schema, that is X.X.X.X + 'dns_address': (Optional) comma separated list of ip_schema, e.g. X.X.X.X[,X,X,X,X] + 'dhcp_enabled': True or False + 'dhcp_start_address': ip_schema, first IP to grant + 'dhcp_count': number of IPs to grant. 'shared': if this network can be seen/use by other tenants/organization 'vlan': in case of a data or ptp net_type, the intended vlan tag to be used for the network Returns the network identifier on success or raises and exception on failure @@ -483,6 +482,7 @@ class vimconnector(): 'vpci': (optional) virtual vPCI address to assign at the VM. Can be ignored depending on VIM capabilities 'model': (optional and only have sense for type==virtual) interface model: virtio, e2000, ... 'mac_address': (optional) mac address to assign to this interface + 'ip_address': (optional) IP address to assign to this interface #TODO: CHECK if an optional 'vlan' parameter is needed for VIMs when type if VF and net_id is not provided, the VLAN tag to be used. In case net_id is provided, the internal network vlan is used for tagging VF 'type': (mandatory) can be one of: diff --git a/osm_ro/vimconn_openstack.py b/osm_ro/vimconn_openstack.py index fd16f544..734f7a30 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"] diff --git a/osm_ro/vimconn_openvim.py b/osm_ro/vimconn_openvim.py index b34fdf0a..417092f1 100644 --- a/osm_ro/vimconn_openvim.py +++ b/osm_ro/vimconn_openvim.py @@ -850,6 +850,8 @@ class vimconnector(vimconn.vimconnector): net_dict["model"] = net["model"] if net.get("mac_address"): net_dict["mac_address"] = net["mac_address"] + if net.get("ip_address"): + net_dict["ip_address"] = net["ip_address"] virtio_net_list.append(net_dict) payload_dict={ "name": name[:64], "description": description, @@ -952,7 +954,7 @@ class vimconnector(vimconn.vimconnector): vm={} #print "VIMConnector refresh_tenant_vms and nets: Getting tenant VM instance information from VIM" try: - url = self.url+'/'+self.tenant+'/servers/'+ vm_id + url = self.url + '/' + self.tenant + '/servers/' + vm_id self.logger.info("Getting vm GET %s", url) vim_response = requests.get(url, headers = self.headers_req) self._check_http_request_response(vim_response) @@ -969,7 +971,7 @@ class vimconnector(vimconn.vimconnector): #get interfaces info try: management_ip = False - url2 = self.url+'/ports?device_id='+ quote(vm_id) + url2 = self.url + '/ports?device_id=' + quote(vm_id) self.logger.info("Getting PORTS GET %s", url2) vim_response2 = requests.get(url2, headers = self.headers_req) self._check_http_request_response(vim_response2) @@ -978,7 +980,7 @@ class vimconnector(vimconn.vimconnector): vm["interfaces"]=[] for port in client_data.get("ports"): interface={} - interface['vim_info'] = yaml.safe_dump(port) + interface['vim_info'] = yaml.safe_dump(port) interface["mac_address"] = port.get("mac_address") interface["vim_net_id"] = port.get("network_id") interface["vim_interface_id"] = port["id"] diff --git a/test/RO_tests/v3_2vdu_set_ip_mac/scenario_2vdu_set_ip_mac.yaml b/test/RO_tests/v3_2vdu_set_ip_mac/scenario_2vdu_set_ip_mac.yaml new file mode 100644 index 00000000..4dfc5b08 --- /dev/null +++ b/test/RO_tests/v3_2vdu_set_ip_mac/scenario_2vdu_set_ip_mac.yaml @@ -0,0 +1,83 @@ +nsd:nsd-catalog: + nsd: + - id: test_2vdu_nsd + name: test_2vdu_nsd_name + short-name: test_2vdu_nsd_sname + description: 2 vnfs, eatch one with 3 cirros vdu + vendor: OSM + version: '1.0' + + # Place the logo as png in icons directory and provide the name here + logo: osm_2x.png + + # Specify the VNFDs that are part of this NSD + constituent-vnfd: + # The member-vnf-index needs to be unique, starting from 1 + # vnfd-id-ref is the id of the VNFD + # Multiple constituent VNFDs can be specified + - member-vnf-index: 1 + vnfd-id-ref: test_2vdu + - member-vnf-index: 2 + vnfd-id-ref: test_2vdu2 + + ip-profiles: + - description: Inter VNF Link + ip-profile-params: + gateway-address: 10.31.31.254 + ip-version: ipv4 + subnet-address: 10.31.31.0/24 + dns-server: + - address: 8.8.8.8 + - address: 8.8.8.9 + dhcp-params: + count: 200 + start-address: 10.31.31.20 + name: ipprofileA + - description: IP profile that disables dhcp server + ip-profile-params: + dhcp-params: + enabled: 'false' + ip-version: ipv4 + name: no_dhcp + + vld: + # Networks for the VNFs + - id: vld1 + name: mgmt + short-name: vld1-sname + type: ELAN + vnfd-connection-point-ref: + - member-vnf-index-ref: 1 + vnfd-id-ref: test_2vdu + vnfd-connection-point-ref: eth0 + - member-vnf-index-ref: 2 + vnfd-id-ref: test_2vdu2 + vnfd-connection-point-ref: eth0 + + - id: vld2 + name: vld2-name + short-name: vld2-sname + type: ELAN + ip-profile-ref: ipprofileA + vnfd-connection-point-ref: + - member-vnf-index-ref: 1 + vnfd-id-ref: test_2vdu + vnfd-connection-point-ref: eth1 + ip-address: 10.31.31.4 + - member-vnf-index-ref: 2 + vnfd-id-ref: test_2vdu2 + vnfd-connection-point-ref: eth1 + ip-address: 10.31.31.5 + + - id: vld3 + name: vld3-name + short-name: vld3-sname + type: ELAN + ip-profile-ref: no_dhcp + vnfd-connection-point-ref: + - member-vnf-index-ref: 1 + vnfd-id-ref: test_2vdu + vnfd-connection-point-ref: eth4 + - member-vnf-index-ref: 2 + vnfd-id-ref: test_2vdu2 + vnfd-connection-point-ref: eth4 diff --git a/test/RO_tests/v3_2vdu_set_ip_mac/vnfd_2vdu_set_ip_mac.yaml b/test/RO_tests/v3_2vdu_set_ip_mac/vnfd_2vdu_set_ip_mac.yaml new file mode 100644 index 00000000..b6be27c1 --- /dev/null +++ b/test/RO_tests/v3_2vdu_set_ip_mac/vnfd_2vdu_set_ip_mac.yaml @@ -0,0 +1,93 @@ +vnfd-catalog: + vnfd: + - connection-point: + - name: eth0 + type: VPORT + - name: eth1 + type: VPORT + - name: eth4 + type: VPORT + description: VNF with internal VLD and set IP and mac + id: test_2vdu + name: test_2vdu_name + short-name: test_2vdu_sname + mgmt-interface: + cp: eth0 + internal-vld: + - description: Internal VL + id: net_internal + name: net_internal_name + short-name: net_internal_sname + type: ELAN + internal-connection-point: + - id-ref: eth2 + ip-address: 10.10.133.4 + - id-ref: eth3 + ip-address: 10.10.133.5 + ip-profile-ref: ip-profile1 + ip-profiles: + - description: Inter VNF Link + ip-profile-params: + gateway-address: 10.10.133.1 + ip-version: ipv4 + subnet-address: 10.10.133.0/24 + dhcp-params: + count: 200 + start-address: 10.10.133.20 + name: ip-profile1 + vdu: + - id: VM1 + name: VM1-name + image: US1604 + interface: + - name: iface11 + type: EXTERNAL + virtual-interface: + type: VIRTIO + external-connection-point-ref: eth0 + mac-address: "52:33:44:55:66:77" + - name: iface12 + type: INTERNAL + virtual-interface: + type: VIRTIO + internal-connection-point-ref: eth2 + mac-address: "52:33:44:55:66:78" + - name: iface13 + type: EXTERNAL + virtual-interface: + type: VIRTIO + external-connection-point-ref: eth4 + internal-connection-point: + - name: eth2-icp + id: eth2 + type: VPORT + vm-flavor: + memory-mb: '2048' + storage-gb: '8' + vcpu-count: '1' + - id: VM2 + image: US1604 + name: VM2-name + interface: + - name: iface21 + type: EXTERNAL + virtual-interface: + type: VIRTIO + external-connection-point-ref: eth1 + mac-address: 52:33:44:55:66:79 + - name: iface22 + type: INTERNAL + virtual-interface: + type: VIRTIO + internal-connection-point-ref: eth3 + mac-address: 52:33:44:55:66:80 + internal-connection-point: + - name: eth3-icp + id: eth3 + type: VPORT + vm-flavor: + memory-mb: '2048' + storage-gb: '8' + vcpu-count: '1' + vendor: ROtest + version: '1.0' diff --git a/test/RO_tests/v3_2vdu_set_ip_mac/vnfd_2vdu_set_ip_mac2.yaml b/test/RO_tests/v3_2vdu_set_ip_mac/vnfd_2vdu_set_ip_mac2.yaml new file mode 100644 index 00000000..fe200bfc --- /dev/null +++ b/test/RO_tests/v3_2vdu_set_ip_mac/vnfd_2vdu_set_ip_mac2.yaml @@ -0,0 +1,93 @@ +vnfd-catalog: + vnfd: + - connection-point: + - name: eth0 + type: VPORT + - name: eth1 + type: VPORT + - name: eth4 + type: VPORT + description: VNF with internal VLD and set IP and mac + id: test_2vdu2 + name: test_2vdu2_name + short-name: test_2vdu2_sname + mgmt-interface: + cp: eth0 + internal-vld: + - description: Internal VL + id: net_internal + name: net_internal_name + short-name: net_internal_sname + type: ELAN + internal-connection-point: + - id-ref: eth2 + ip-address: 10.10.133.4 + - id-ref: eth3 + ip-address: 10.10.133.5 + ip-profile-ref: ip-profile1 + ip-profiles: + - description: Inter VNF Link + ip-profile-params: + gateway-address: 10.10.133.1 + ip-version: ipv4 + subnet-address: 10.10.133.0/24 + dhcp-params: + count: 200 + start-address: 10.10.133.20 + name: ip-profile1 + vdu: + - id: VM1 + name: VM1-name + image: US1604 + interface: + - name: iface11 + type: EXTERNAL + virtual-interface: + type: VIRTIO + external-connection-point-ref: eth0 + mac-address: "52:33:44:55:66:81" + - name: iface12 + type: INTERNAL + virtual-interface: + type: VIRTIO + internal-connection-point-ref: eth2 + mac-address: "52:33:44:55:66:82" + - name: iface13 + type: EXTERNAL + virtual-interface: + type: VIRTIO + external-connection-point-ref: eth4 + internal-connection-point: + - name: eth2-icp + id: eth2 + type: VPORT + vm-flavor: + memory-mb: '2048' + storage-gb: '8' + vcpu-count: '1' + - id: VM2 + image: US1604 + name: VM2-name + interface: + - name: iface21 + type: EXTERNAL + virtual-interface: + type: VIRTIO + external-connection-point-ref: eth1 + mac-address: 52:33:44:55:66:83 + - name: iface22 + type: INTERNAL + virtual-interface: + type: VIRTIO + internal-connection-point-ref: eth3 + mac-address: 52:33:44:55:66:84 + internal-connection-point: + - name: eth3-icp + id: eth3 + type: VPORT + vm-flavor: + memory-mb: '2048' + storage-gb: '8' + vcpu-count: '1' + vendor: ROtest + version: '1.0'