+def get_str(obj, field, length):
+ """
+ Obtain the str value,
+ :param obj:
+ :param length:
+ :return:
+ """
+ value = obj.get(field)
+ if value is not None:
+ value = str(value)[:length]
+ return value
+
+def _lookfor_or_create_image(db_image, mydb, descriptor):
+ """
+ fill image content at db_image dictionary. Check if the image with this image and checksum exist
+ :param db_image: dictionary to insert data
+ :param mydb: database connector
+ :param descriptor: yang descriptor
+ :return: uuid if the image exist at DB, or None if a new image must be created with the data filled at db_image
+ """
+
+ db_image["name"] = get_str(descriptor, "image", 255)
+ db_image["checksum"] = get_str(descriptor, "image-checksum", 32)
+ if not db_image["checksum"]: # Ensure that if empty string, None is stored
+ db_image["checksum"] = None
+ if db_image["name"].startswith("/"):
+ db_image["location"] = db_image["name"]
+ existing_images = mydb.get_rows(FROM="images", WHERE={'location': db_image["location"]})
+ else:
+ db_image["universal_name"] = db_image["name"]
+ existing_images = mydb.get_rows(FROM="images", WHERE={'universal_name': db_image['universal_name'],
+ 'checksum': db_image['checksum']})
+ if existing_images:
+ return existing_images[0]["uuid"]
+ else:
+ image_uuid = str(uuid4())
+ db_image["uuid"] = image_uuid
+ return None
+
+def new_vnfd_v3(mydb, tenant_id, vnf_descriptor):
+ """
+ Parses an OSM IM vnfd_catalog and insert at DB
+ :param mydb:
+ :param tenant_id:
+ :param vnf_descriptor:
+ :return: The list of cretated vnf ids
+ """
+ try:
+ myvnfd = vnfd_catalog.vnfd()
+ pybindJSONDecoder.load_ietf_json(vnf_descriptor, None, None, obj=myvnfd)
+ db_vnfs = []
+ db_nets = []
+ db_vms = []
+ db_vms_index = 0
+ db_interfaces = []
+ db_images = []
+ db_flavors = []
+ uuid_list = []
+ vnfd_uuid_list = []
+ for rift_vnfd in myvnfd.vnfd_catalog.vnfd.itervalues():
+ vnfd = rift_vnfd.get()
+
+ # table vnf
+ vnf_uuid = str(uuid4())
+ uuid_list.append(vnf_uuid)
+ vnfd_uuid_list.append(vnf_uuid)
+ db_vnf = {
+ "uuid": vnf_uuid,
+ "osm_id": get_str(vnfd, "id", 255),
+ "name": get_str(vnfd, "name", 255),
+ "description": get_str(vnfd, "description", 255),
+ "tenant_id": tenant_id,
+ "vendor": get_str(vnfd, "vendor", 255),
+ "short_name": get_str(vnfd, "short-name", 255),
+ "descriptor": str(vnf_descriptor)[:60000]
+ }
+
+ # table nets (internal-vld)
+ net_id2uuid = {} # for mapping interface with network
+ for vld in vnfd.get("internal-vld").itervalues():
+ net_uuid = str(uuid4())
+ uuid_list.append(net_uuid)
+ db_net = {
+ "name": get_str(vld, "name", 255),
+ "vnf_id": vnf_uuid,
+ "uuid": net_uuid,
+ "description": get_str(vld, "description", 255),
+ "type": "bridge", # TODO adjust depending on connection point type
+ }
+ net_id2uuid[vld.get("id")] = net_uuid
+ db_nets.append(db_net)
+
+ # table vms (vdus)
+ vdu_id2uuid = {}
+ vdu_id2db_table_index = {}
+ for vdu in vnfd.get("vdu").itervalues():
+ vm_uuid = str(uuid4())
+ uuid_list.append(vm_uuid)
+ db_vm = {
+ "uuid": vm_uuid,
+ "osm_id": get_str(vdu, "id", 255),
+ "name": get_str(vdu, "name", 255),
+ "description": get_str(vdu, "description", 255),
+ "vnf_id": vnf_uuid,
+ }
+ vdu_id2uuid[db_vm["osm_id"]] = vm_uuid
+ vdu_id2db_table_index[db_vm["osm_id"]] = db_vms_index
+ if vdu.get("count"):
+ db_vm["count"] = int(vdu["count"])
+
+ # table image
+ image_present = False
+ if vdu.get("image"):
+ image_present = True
+ db_image = {}
+ image_uuid = _lookfor_or_create_image(db_image, mydb, vdu)
+ if not image_uuid:
+ image_uuid = db_image["uuid"]
+ db_images.append(db_image)
+ db_vm["image_id"] = image_uuid
+
+ # volumes
+ devices = []
+ if vdu.get("volumes"):
+ for volume_key in sorted(vdu["volumes"]):
+ volume = vdu["volumes"][volume_key]
+ if not image_present:
+ # Convert the first volume to vnfc.image
+ image_present = True
+ db_image = {}
+ image_uuid = _lookfor_or_create_image(db_image, mydb, volume)
+ if not image_uuid:
+ image_uuid = db_image["uuid"]
+ db_images.append(db_image)
+ db_vm["image_id"] = image_uuid
+ else:
+ # Add Openmano devices
+ device = {}
+ device["type"] = str(volume.get("device-type"))
+ if volume.get("size"):
+ device["size"] = int(volume["size"])
+ if volume.get("image"):
+ device["image name"] = str(volume["image"])
+ if volume.get("image-checksum"):
+ 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"] = numa_node["paired-threads"]["num-paired-threads"]
+ epa_vcpu_set = True
+ if len(numa_node["paired-threads"].get("paired-thread-ids")) > 0:
+ 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"] = 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"):
+ boot_data["user-data"] = vdu["cloud-init"]
+ elif vdu.get("cloud-init-file"):
+ # TODO Where this file content is present???
+ # boot_data["user-data"] = rift_vnfd.files[vdu["cloud-init-file"]]
+ boot_data["user-data"] = str(vdu["cloud-init-file"])
+
+ if vdu.get("supplemental-boot-data"):
+ if vdu["supplemental-boot-data"].get('boot-data-drive'):
+ boot_data['boot-data-drive'] = True
+ if vdu["supplemental-boot-data"].get('config-file'):
+ om_cfgfile_list = list()
+ for custom_config_file in vdu["supplemental-boot-data"]['config-file'].itervalues():
+ # TODO Where this file content is present???
+ cfg_source = str(custom_config_file["source"])
+ om_cfgfile_list.append({"dest": custom_config_file["dest"],
+ "content": cfg_source})
+ boot_data['config-files'] = om_cfgfile_list
+ if boot_data:
+ db_vm["boot_data"] = boot_data
+
+ db_vms.append(db_vm)
+ db_vms_index += 1
+
+ # table interfaces (internal/external interfaces)
+ cp_name2iface_uuid = {}
+ cp_name2vm_uuid = {}
+ for iface in chain(vdu.get("internal-interface").itervalues(), vdu.get("external-interface").itervalues()):
+ iface_uuid = str(uuid4())
+ uuid_list.append(iface_uuid)
+ db_interface = {
+ "uuid": iface_uuid,
+ "internal_name": get_str(iface, "name", 255),
+ "vm_id": vm_uuid,
+ }
+ if iface.get("virtual-interface").get("vpci"):
+ db_interface["vpci"] = get_str(iface.get("virtual-interface"), "vpci", 12)
+
+ if iface.get("virtual-interface").get("bandwidth"):
+ bps = int(iface.get("virtual-interface").get("bandwidth"))
+ db_interface["bw"] = bps/1000
+
+ if iface.get("virtual-interface").get("type") == "OM-MGMT":
+ db_interface["type"] = "mgmt"
+ elif iface.get("virtual-interface").get("type") in ("VIRTIO", "E1000"):
+ db_interface["type"] = "bridge"
+ db_interface["model"] = get_str(iface.get("virtual-interface"), "type", 12)
+ 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)
+ else:
+ raise ValueError("Interface type {} not supported".format(iface.get("virtual-interface").get("type")))
+
+ if iface.get("vnfd-connection-point-ref"):
+ try:
+ cp = vnfd.get("connection-point")[iface.get("vnfd-connection-point-ref")]
+ db_interface["external_name"] = get_str(cp, "name", 255)
+ cp_name2iface_uuid[db_interface["external_name"]] = iface_uuid
+ cp_name2vm_uuid[db_interface["external_name"]] = vm_uuid
+ # TODO add port-security-enable
+ # if cp.get("port-security-enabled") == False:
+ # elif cp.get("port-security-enabled") == True:
+ except KeyError:
+ raise KeyError(
+ "Error wrong reference at vnfd['{vnf}'] vdu['{vdu}']:internal-interface['{iface}']:"
+ "vnfd-connection-point-ref '{cp}' is not present at connection-point".format(
+ vnf=vnfd["id"], vdu=vdu["id"], iface=iface["name"],
+ cp=iface.get("vnfd-connection-point-ref"))
+ )
+ elif iface.get("vdu-internal-connection-point-ref"):
+ try:
+ for vld in vnfd.get("internal-vld").itervalues():
+ for cp in vld.get("internal-connection-point").itervalues():
+ if cp.get("id-ref") == iface.get("vdu-internal-connection-point-ref"):
+ db_interface["net_id"] = net_id2uuid[vld.get("id")]
+ break
+ except KeyError:
+ raise KeyError(
+ "Error at vnfd['{vnf}'] vdu['{vdu}']:internal-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"],
+ cp=iface.get("vdu-internal-connection-point-ref"))
+ )
+
+ db_interfaces.append(db_interface)
+
+ # VNF affinity and antiaffinity
+ for pg in vnfd.get("placement-groups").itervalues():
+ pg_name = get_str(pg, "name", 255)
+ for vdu in pg.get("member-vdus").itervalues():
+ vdu_id = get_str(vdu, "member-vdu-ref", 255)
+ if vdu_id not in vdu_id2db_table_index:
+ raise KeyError(
+ "Error at 'vnfd'['{vnf}']:'placement-groups'['{pg}']:'member-vdus':'{vdu}' references a non existing vdu".format(
+ vnf=vnfd["id"], pg=pg_name, vdu=vdu_id))
+ db_vms[vdu_id2db_table_index[vdu_id]]["availability_zone"] = pg_name
+ # TODO consider the case of isolation and not colocation
+ # if pg.get("strategy") == "ISOLATION":
+
+ # VNF mgmt configuration
+ mgmt_access = {}
+ if vnfd["mgmt-interface"].get("vdu-id"):
+ if vnfd["mgmt-interface"]["vdu-id"] not in vdu_id2uuid:
+ raise KeyError(
+ "Error at vnfd['{vnf}']:'mgmt-interface':'vdu-id':{vdu} reference a non existing vdu".format(
+ vnf=vnfd["id"], vdu=vnfd["mgmt-interface"]["vdu-id"]))
+ mgmt_access["vm_id"] = vdu_id2uuid[vnfd["mgmt-interface"]["vdu-id"]]
+ 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 KeyError(
+ "Error at vnfd['{vnf}']:'mgmt-interface':'cp':{cp} reference a non existing connection-point".
+ format(vnf=vnfd["id"], cp=vnfd["mgmt-interface"]["cp"]))
+ mgmt_access["vm_id"] = cp_name2vm_uuid[vnfd["mgmt-interface"]["cp"]]
+ mgmt_access["interface_id"] = cp_name2iface_uuid[vnfd["mgmt-interface"]["cp"]]
+ default_user = get_str(vnfd.get("vnf-configuration").get("config-access", {}).get("ssh-access", {}),
+ "default-user", 64)
+ if default_user:
+ mgmt_access["default_user"] = default_user
+ 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},
+ {"vms": db_vms},
+ {"interfaces": db_interfaces},
+ ]
+
+ logger.debug("create_vnf Deployment done vnfDict: %s",
+ yaml.safe_dump(db_tables, indent=4, default_flow_style=False) )
+ mydb.new_rows(db_tables, uuid_list)
+ return vnfd_uuid_list
+ except Exception as e:
+ logger.error("Exception {}".format(e))
+ raise # NfvoException("Exception {}".format(e), HTTP_Bad_Request)
+
+