+ def _look_for_pdu(self, session, rollback, vnfr, vim_account, vnfr_update, vnfr_update_rollback):
+ """
+ Look for a free PDU in the catalog matching vdur type and interfaces. Fills vnfr.vdur with the interface
+ (ip_address, ...) information.
+ Modifies PDU _admin.usageState to 'IN_USE'
+
+ :param session: client session information
+ :param rollback: list with the database modifications to rollback if needed
+ :param vnfr: vnfr to be updated. It is modified with pdu interface info if pdu is found
+ :param vim_account: vim_account where this vnfr should be deployed
+ :param vnfr_update: dictionary filled by this method with changes to be done at database vnfr
+ :param vnfr_update_rollback: dictionary filled by this method with original content of vnfr in case a rollback
+ of the changed vnfr is needed
+
+ :return: List of PDU interfaces that are connected to an existing VIM network. Each item contains:
+ "vim-network-name": used at VIM
+ "name": interface name
+ "vnf-vld-id": internal VNFD vld where this interface is connected, or
+ "ns-vld-id": NSD vld where this interface is connected.
+ NOTE: One, and only one between 'vnf-vld-id' and 'ns-vld-id' contains a value. The other will be None
+ """
+
+ ifaces_forcing_vim_network = []
+ for vdur_index, vdur in enumerate(get_iterable(vnfr.get("vdur"))):
+ if not vdur.get("pdu-type"):
+ continue
+ pdu_type = vdur.get("pdu-type")
+ pdu_filter = self._get_project_filter(session, write=True, show_all=True)
+ pdu_filter["vim_accounts"] = vim_account
+ pdu_filter["type"] = pdu_type
+ pdu_filter["_admin.operationalState"] = "ENABLED"
+ pdu_filter["_admin.usageState"] = "NOT_IN_USE"
+ # TODO feature 1417: "shared": True,
+
+ available_pdus = self.db.get_list("pdus", pdu_filter)
+ for pdu in available_pdus:
+ # step 1 check if this pdu contains needed interfaces:
+ match_interfaces = True
+ for vdur_interface in vdur["interfaces"]:
+ for pdu_interface in pdu["interfaces"]:
+ if pdu_interface["name"] == vdur_interface["name"]:
+ # TODO feature 1417: match per mgmt type
+ break
+ else: # no interface found for name
+ match_interfaces = False
+ break
+ if match_interfaces:
+ break
+ else:
+ raise EngineException(
+ "No PDU of type={} at vim_account={} found for member_vnf_index={}, vdu={} matching interface "
+ "names".format(pdu_type, vim_account, vnfr["member-vnf-index-ref"], vdur["vdu-id-ref"]))
+
+ # step 2. Update pdu
+ rollback_pdu = {
+ "_admin.usageState": pdu["_admin"]["usageState"],
+ "_admin.usage.vnfr_id": None,
+ "_admin.usage.nsr_id": None,
+ "_admin.usage.vdur": None,
+ }
+ self.db.set_one("pdus", {"_id": pdu["_id"]},
+ {"_admin.usageState": "IN_USE",
+ "_admin.usage.vnfr_id": vnfr["_id"],
+ "_admin.usage.nsr_id": vnfr["nsr-id-ref"],
+ "_admin.usage.vdur": vdur["vdu-id-ref"]}
+ )
+ rollback.append({"topic": "pdus", "_id": pdu["_id"], "operation": "set", "content": rollback_pdu})
+
+ # step 3. Fill vnfr info by filling vdur
+ vdu_text = "vdur.{}".format(vdur_index)
+ vnfr_update_rollback[vdu_text + ".pdu-id"] = None
+ vnfr_update[vdu_text + ".pdu-id"] = pdu["_id"]
+ for iface_index, vdur_interface in enumerate(vdur["interfaces"]):
+ for pdu_interface in pdu["interfaces"]:
+ if pdu_interface["name"] == vdur_interface["name"]:
+ iface_text = vdu_text + ".interfaces.{}".format(iface_index)
+ for k, v in pdu_interface.items():
+ if k in ("ip-address", "mac-address"): # TODO: switch-xxxxx must be inserted
+ vnfr_update[iface_text + ".{}".format(k)] = v
+ vnfr_update_rollback[iface_text + ".{}".format(k)] = vdur_interface.get(v)
+ if pdu_interface.get("ip-address"):
+ if vdur_interface.get("mgmt-interface"):
+ vnfr_update_rollback[vdu_text + ".ip-address"] = vdur.get("ip-address")
+ vnfr_update[vdu_text + ".ip-address"] = pdu_interface["ip-address"]
+ if vdur_interface.get("mgmt-vnf"):
+ vnfr_update_rollback["ip-address"] = vnfr.get("ip-address")
+ vnfr_update["ip-address"] = pdu_interface["ip-address"]
+ if pdu_interface.get("vim-network-name"): # or pdu_interface.get("vim-network-id"):
+ ifaces_forcing_vim_network.append({
+ # "vim-network-id": pdu_interface.get("vim-network-id"),
+ "vim-network-name": pdu_interface.get("vim-network-name"),
+ "name": vdur_interface.get("vnf-vld-id") or vdur_interface.get("ns-vld-id"),
+ "vnf-vld-id": vdur_interface.get("vnf-vld-id"),
+ "ns-vld-id": vdur_interface.get("ns-vld-id")})
+ break
+
+ return ifaces_forcing_vim_network
+
+ def _update_vnfrs(self, session, rollback, nsr, indata):
+ vnfrs = None
+ # get vnfr
+ nsr_id = nsr["_id"]
+ vnfrs = self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id})
+
+ for vnfr in vnfrs:
+ vnfr_update = {}
+ vnfr_update_rollback = {}
+ member_vnf_index = vnfr["member-vnf-index-ref"]
+ # update vim-account-id
+
+ vim_account = indata["vimAccountId"]
+ # check instantiate parameters
+ for vnf_inst_params in get_iterable(indata.get("vnf")):
+ if vnf_inst_params["member-vnf-index"] != member_vnf_index:
+ continue
+ if vnf_inst_params.get("vimAccountId"):
+ vim_account = vnf_inst_params.get("vimAccountId")
+
+ vnfr_update["vim-account-id"] = vim_account
+ vnfr_update_rollback["vim-account-id"] = vnfr.get("vim-account-id")
+
+ # get pdu
+ ifaces_forcing_vim_network = self._look_for_pdu(session, rollback, vnfr, vim_account, vnfr_update,
+ vnfr_update_rollback)
+
+ # updata database vnfr
+ self.db.set_one("vnfrs", {"_id": vnfr["_id"]}, vnfr_update)
+ rollback.append({"topic": "vnfrs", "_id": vnfr["_id"], "operation": "set", "content": vnfr_update_rollback})
+
+ # Update indada in case pdu forces to use a concrete vim-network-name
+ # TODO check if user has already insert a vim-network-name and raises an error
+ if not ifaces_forcing_vim_network:
+ continue
+ for iface_info in ifaces_forcing_vim_network:
+ if iface_info.get("ns-vld-id"):
+ if "vld" not in indata:
+ indata["vld"] = []
+ indata["vld"].append({key: iface_info[key] for key in
+ ("name", "vim-network-name", "vim-network-id") if iface_info.get(key)})
+
+ elif iface_info.get("vnf-vld-id"):
+ if "vnf" not in indata:
+ indata["vnf"] = []
+ indata["vnf"].append({
+ "member-vnf-index": member_vnf_index,
+ "internal-vld": [{key: iface_info[key] for key in
+ ("name", "vim-network-name", "vim-network-id") if iface_info.get(key)}]
+ })
+
+ @staticmethod
+ def _create_nslcmop(nsr_id, operation, params):
+ """
+ Creates a ns-lcm-opp content to be stored at database.
+ :param nsr_id: internal id of the instance
+ :param operation: instantiate, terminate, scale, action, ...
+ :param params: user parameters for the operation
+ :return: dictionary following SOL005 format
+ """