X-Git-Url: https://osm.etsi.org/gitweb/?a=blobdiff_plain;f=osm_ro%2Fnfvo.py;h=bd9d3689f173df9330822865e4fc88cc6e14bb31;hb=refs%2Fchanges%2F76%2F5676%2F3;hp=e5d13eba12cab7d2a4ae75cff6e386bed42b5db8;hpb=3fcfdb7674436861d6ab0740972573293b9a355f;p=osm%2FRO.git diff --git a/osm_ro/nfvo.py b/osm_ro/nfvo.py index e5d13eba..bd9d3689 100644 --- a/osm_ro/nfvo.py +++ b/osm_ro/nfvo.py @@ -38,6 +38,7 @@ import console_proxy_thread as cli import vimconn import logging import collections +import math from uuid import uuid4 from db_base import db_base_Exception @@ -852,9 +853,10 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor): vnf_uuid = str(uuid4()) uuid_list.append(vnf_uuid) vnfd_uuid_list.append(vnf_uuid) + vnfd_id = get_str(vnfd, "id", 255) db_vnf = { "uuid": vnf_uuid, - "osm_id": get_str(vnfd, "id", 255), + "osm_id": vnfd_id, "name": get_str(vnfd, "name", 255), "description": get_str(vnfd, "description", 255), "tenant_id": tenant_id, @@ -888,9 +890,10 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor): for vdu in vnfd.get("vdu").itervalues(): vm_uuid = str(uuid4()) uuid_list.append(vm_uuid) + vdu_id = get_str(vdu, "id", 255) db_vm = { "uuid": vm_uuid, - "osm_id": get_str(vdu, "id", 255), + "osm_id": vdu_id, "name": get_str(vdu, "name", 255), "description": get_str(vdu, "description", 255), "vnf_id": vnf_uuid, @@ -937,74 +940,6 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor): device["image checksum"] = str(volume["image-checksum"]) devices.append(device) - # table flavors - db_flavor = { - "name": get_str(vdu, "name", 250) + "-flv", - "vcpus": int(vdu["vm-flavor"].get("vcpu-count", 1)), - "ram": int(vdu["vm-flavor"].get("memory-mb", 1)), - "disk": int(vdu["vm-flavor"].get("storage-gb", 1)), - } - # EPA TODO revise - extended = {} - numa = {} - if devices: - extended["devices"] = devices - if vdu.get("guest-epa"): # TODO or dedicated_int: - epa_vcpu_set = False - if vdu["guest-epa"].get("numa-node-policy"): # TODO or dedicated_int: - numa_node_policy = vdu["guest-epa"].get("numa-node-policy") - if numa_node_policy.get("node"): - numa_node = numa_node_policy["node"]['0'] - if numa_node.get("num-cores"): - numa["cores"] = numa_node["num-cores"] - epa_vcpu_set = True - if numa_node.get("paired-threads"): - if numa_node["paired-threads"].get("num-paired-threads"): - numa["paired-threads"] = int(numa_node["paired-threads"]["num-paired-threads"]) - epa_vcpu_set = True - if len(numa_node["paired-threads"].get("paired-thread-ids")): - numa["paired-threads-id"] = [] - for pair in numa_node["paired-threads"]["paired-thread-ids"].itervalues(): - numa["paired-threads-id"].append( - (str(pair["thread-a"]), str(pair["thread-b"])) - ) - if numa_node.get("num-threads"): - numa["threads"] = int(numa_node["num-threads"]) - epa_vcpu_set = True - if numa_node.get("memory-mb"): - numa["memory"] = max(int(numa_node["memory-mb"] / 1024), 1) - if vdu["guest-epa"].get("mempage-size"): - if vdu["guest-epa"]["mempage-size"] != "SMALL": - numa["memory"] = max(int(db_flavor["ram"] / 1024), 1) - if vdu["guest-epa"].get("cpu-pinning-policy") and not epa_vcpu_set: - if vdu["guest-epa"]["cpu-pinning-policy"] == "DEDICATED": - if vdu["guest-epa"].get("cpu-thread-pinning-policy") and \ - vdu["guest-epa"]["cpu-thread-pinning-policy"] != "PREFER": - numa["cores"] = max(db_flavor["vcpus"], 1) - else: - numa["threads"] = max(db_flavor["vcpus"], 1) - if numa: - extended["numas"] = [numa] - if extended: - extended_text = yaml.safe_dump(extended, default_flow_style=True, width=256) - db_flavor["extended"] = extended_text - # look if flavor exist - - temp_flavor_dict = {'disk': db_flavor.get('disk', 1), - 'ram': db_flavor.get('ram'), - 'vcpus': db_flavor.get('vcpus'), - 'extended': db_flavor.get('extended') - } - existing_flavors = mydb.get_rows(FROM="flavors", WHERE=temp_flavor_dict) - if existing_flavors: - flavor_uuid = existing_flavors[0]["uuid"] - else: - flavor_uuid = str(uuid4()) - uuid_list.append(flavor_uuid) - db_flavor["uuid"] = flavor_uuid - db_flavors.append(db_flavor) - db_vm["flavor_id"] = flavor_uuid - # cloud-init boot_data = {} if vdu.get("cloud-init"): @@ -1032,11 +967,14 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor): db_vms_index += 1 # table interfaces (internal/external interfaces) + flavor_epa_interfaces = [] cp_name2iface_uuid = {} cp_name2vm_uuid = {} cp_name2db_interface = {} + vdu_id2cp_name = {} # stored only when one external connection point is presented at this VDU # for iface in chain(vdu.get("internal-interface").itervalues(), vdu.get("external-interface").itervalues()): for iface in vdu.get("interface").itervalues(): + flavor_epa_interface = {} iface_uuid = str(uuid4()) uuid_list.append(iface_uuid) db_interface = { @@ -1044,12 +982,15 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor): "internal_name": get_str(iface, "name", 255), "vm_id": vm_uuid, } + flavor_epa_interface["name"] = db_interface["internal_name"] if iface.get("virtual-interface").get("vpci"): db_interface["vpci"] = get_str(iface.get("virtual-interface"), "vpci", 12) + flavor_epa_interface["vpci"] = db_interface["vpci"] if iface.get("virtual-interface").get("bandwidth"): bps = int(iface.get("virtual-interface").get("bandwidth")) - db_interface["bw"] = bps/1000 + db_interface["bw"] = int(math.ceil(bps/1000000.0)) + flavor_epa_interface["bandwidth"] = "{} Mbps".format(db_interface["bw"]) if iface.get("virtual-interface").get("type") == "OM-MGMT": db_interface["type"] = "mgmt" @@ -1059,11 +1000,13 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor): elif iface.get("virtual-interface").get("type") in ("SR-IOV", "PCI-PASSTHROUGH"): db_interface["type"] = "data" db_interface["model"] = get_str(iface.get("virtual-interface"), "type", 12) + flavor_epa_interface["dedicated"] = "no" if iface["virtual-interface"]["type"] == "SR-IOV" \ + else "yes" + flavor_epa_interfaces.append(flavor_epa_interface) else: raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{}]':'vdu[{}]':'interface':'virtual" "-interface':'type':'{}'. Interface type is not supported".format( - str(vnfd["id"])[:255], str(vdu["id"])[:255], - iface.get("virtual-interface").get("type")), + vnfd_id, vdu_id, iface.get("virtual-interface").get("type")), HTTP_Bad_Request) if iface.get("external-connection-point-ref"): @@ -1076,6 +1019,15 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor): for cp_descriptor in vnfd_descriptor["connection-point"]: if cp_descriptor["name"] == db_interface["external_name"]: break + else: + raise KeyError() + + if vdu_id in vdu_id2cp_name: + vdu_id2cp_name[vdu_id] = None # more than two connecdtion point for this VDU + else: + vdu_id2cp_name[vdu_id] = db_interface["external_name"] + + # port security 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": @@ -1084,7 +1036,7 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor): raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'vdu[{vdu}]':" "'interface[{iface}]':'vnfd-connection-point-ref':'{cp}' is not present" " at connection-point".format( - vnf=vnfd["id"], vdu=vdu["id"], iface=iface["name"], + vnf=vnfd_id, vdu=vdu_id, iface=iface["name"], cp=iface.get("vnfd-connection-point-ref")), HTTP_Bad_Request) elif iface.get("internal-connection-point-ref"): @@ -1105,13 +1057,82 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor): raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'vdu[{vdu}]':" "'interface[{iface}]':'vdu-internal-connection-point-ref':'{cp}' is not" " referenced by any internal-vld".format( - vnf=vnfd["id"], vdu=vdu["id"], iface=iface["name"], + vnf=vnfd_id, vdu=vdu_id, iface=iface["name"], cp=iface.get("vdu-internal-connection-point-ref")), HTTP_Bad_Request) if iface.get("position") is not None: db_interface["created_at"] = int(iface.get("position")) - 1000 db_interfaces.append(db_interface) + # table flavors + db_flavor = { + "name": get_str(vdu, "name", 250) + "-flv", + "vcpus": int(vdu["vm-flavor"].get("vcpu-count", 1)), + "ram": int(vdu["vm-flavor"].get("memory-mb", 1)), + "disk": int(vdu["vm-flavor"].get("storage-gb", 1)), + } + # EPA TODO revise + extended = {} + numa = {} + if devices: + extended["devices"] = devices + if flavor_epa_interfaces: + numa["interfaces"] = flavor_epa_interfaces + if vdu.get("guest-epa"): # TODO or dedicated_int: + epa_vcpu_set = False + if vdu["guest-epa"].get("numa-node-policy"): # TODO or dedicated_int: + numa_node_policy = vdu["guest-epa"].get("numa-node-policy") + if numa_node_policy.get("node"): + numa_node = numa_node_policy["node"]['0'] + if numa_node.get("num-cores"): + numa["cores"] = numa_node["num-cores"] + epa_vcpu_set = True + if numa_node.get("paired-threads"): + if numa_node["paired-threads"].get("num-paired-threads"): + numa["paired-threads"] = int(numa_node["paired-threads"]["num-paired-threads"]) + epa_vcpu_set = True + if len(numa_node["paired-threads"].get("paired-thread-ids")): + numa["paired-threads-id"] = [] + for pair in numa_node["paired-threads"]["paired-thread-ids"].itervalues(): + numa["paired-threads-id"].append( + (str(pair["thread-a"]), str(pair["thread-b"])) + ) + if numa_node.get("num-threads"): + numa["threads"] = int(numa_node["num-threads"]) + epa_vcpu_set = True + if numa_node.get("memory-mb"): + numa["memory"] = max(int(numa_node["memory-mb"] / 1024), 1) + if vdu["guest-epa"].get("mempage-size"): + if vdu["guest-epa"]["mempage-size"] != "SMALL": + numa["memory"] = max(int(db_flavor["ram"] / 1024), 1) + if vdu["guest-epa"].get("cpu-pinning-policy") and not epa_vcpu_set: + if vdu["guest-epa"]["cpu-pinning-policy"] == "DEDICATED": + if vdu["guest-epa"].get("cpu-thread-pinning-policy") and \ + vdu["guest-epa"]["cpu-thread-pinning-policy"] != "PREFER": + numa["cores"] = max(db_flavor["vcpus"], 1) + else: + numa["threads"] = max(db_flavor["vcpus"], 1) + if numa: + extended["numas"] = [numa] + if extended: + extended_text = yaml.safe_dump(extended, default_flow_style=True, width=256) + db_flavor["extended"] = extended_text + # look if flavor exist + temp_flavor_dict = {'disk': db_flavor.get('disk', 1), + 'ram': db_flavor.get('ram'), + 'vcpus': db_flavor.get('vcpus'), + 'extended': db_flavor.get('extended') + } + existing_flavors = mydb.get_rows(FROM="flavors", WHERE=temp_flavor_dict) + if existing_flavors: + flavor_uuid = existing_flavors[0]["uuid"] + else: + flavor_uuid = str(uuid4()) + uuid_list.append(flavor_uuid) + db_flavor["uuid"] = flavor_uuid + db_flavors.append(db_flavor) + db_vm["flavor_id"] = flavor_uuid + # VNF affinity and antiaffinity for pg in vnfd.get("placement-groups").itervalues(): pg_name = get_str(pg, "name", 255) @@ -1120,7 +1141,7 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor): if vdu_id not in vdu_id2db_table_index: raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'placement-groups[{pg}]':" "'member-vdus':'{vdu}'. Reference to a non-existing vdu".format( - vnf=vnfd["id"], pg=pg_name, vdu=vdu_id), + vnf=vnfd_id, pg=pg_name, vdu=vdu_id), HTTP_Bad_Request) db_vms[vdu_id2db_table_index[vdu_id]]["availability_zone"] = pg_name # TODO consider the case of isolation and not colocation @@ -1129,19 +1150,24 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor): # VNF mgmt configuration mgmt_access = {} if vnfd["mgmt-interface"].get("vdu-id"): - if vnfd["mgmt-interface"]["vdu-id"] not in vdu_id2uuid: + mgmt_vdu_id = get_str(vnfd["mgmt-interface"], "vdu-id", 255) + if mgmt_vdu_id not in vdu_id2uuid: raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'mgmt-interface':'vdu-id':" "'{vdu}'. Reference to a non-existing vdu".format( - vnf=vnfd["id"], vdu=vnfd["mgmt-interface"]["vdu-id"]), + vnf=vnfd_id, vdu=mgmt_vdu_id), HTTP_Bad_Request) mgmt_access["vm_id"] = vdu_id2uuid[vnfd["mgmt-interface"]["vdu-id"]] + # if only one cp is defined by this VDU, mark this interface as of type "mgmt" + if vdu_id2cp_name.get(mgmt_vdu_id): + cp_name2db_interface[vdu_id2cp_name[mgmt_vdu_id]]["type"] = "mgmt" + if vnfd["mgmt-interface"].get("ip-address"): mgmt_access["ip-address"] = str(vnfd["mgmt-interface"].get("ip-address")) if vnfd["mgmt-interface"].get("cp"): if vnfd["mgmt-interface"]["cp"] not in cp_name2iface_uuid: raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'mgmt-interface':'cp':'{cp}'. " "Reference to a non-existing connection-point".format( - vnf=vnfd["id"], cp=vnfd["mgmt-interface"]["cp"]), + vnf=vnfd_id, cp=vnfd["mgmt-interface"]["cp"]), HTTP_Bad_Request) mgmt_access["vm_id"] = cp_name2vm_uuid[vnfd["mgmt-interface"]["cp"]] mgmt_access["interface_id"] = cp_name2iface_uuid[vnfd["mgmt-interface"]["cp"]] @@ -2173,7 +2199,8 @@ def new_nsd_v3(mydb, tenant_id, nsd_descriptor): elif vld.get("provider-network").get("overlay-type") == "VLAN": db_sce_net["type"] = "data" else: - db_sce_net["type"] = "bridge" + # later on it will be fixed to bridge or data depending on the type of interfaces attached to it + db_sce_net["type"] = None db_sce_nets.append(db_sce_net) # ip-profile, link db_ip_profile with db_sce_net @@ -2197,7 +2224,7 @@ def new_nsd_v3(mydb, tenant_id, nsd_descriptor): str(nsd["id"]), str(vld["id"]), str(iface["member-vnf-index-ref"])), HTTP_Bad_Request) - existing_ifaces = mydb.get_rows(SELECT=('i.uuid as uuid',), + existing_ifaces = mydb.get_rows(SELECT=('i.uuid as uuid', 'i.type as iface_type'), FROM="interfaces as i join vms on i.vm_id=vms.uuid", WHERE={'vnf_id': vnf_index2vnf_uuid[vnf_index], 'external_name': get_str(iface, "vnfd-connection-point-ref", @@ -2210,6 +2237,8 @@ def new_nsd_v3(mydb, tenant_id, nsd_descriptor): str(iface.get("vnfd-id-ref"))[:255]), HTTP_Bad_Request) interface_uuid = existing_ifaces[0]["uuid"] + if existing_ifaces[0]["iface_type"] == "data" and not db_sce_net["type"]: + db_sce_net["type"] = "data" sce_interface_uuid = str(uuid4()) uuid_list.append(sce_net_uuid) db_sce_interface = { @@ -2220,6 +2249,8 @@ def new_nsd_v3(mydb, tenant_id, nsd_descriptor): # "ip_address": #TODO } db_sce_interfaces.append(db_sce_interface) + if not db_sce_net["type"]: + db_sce_net["type"] = "bridge" db_tables = [ {"scenarios": db_scenarios},