From: tierno Date: Mon, 19 Oct 2020 16:38:59 +0000 (+0000) Subject: Feature 7184 New Generation RO enhancemnt X-Git-Tag: release-v9.0-start~11 X-Git-Url: https://osm.etsi.org/gitweb/?a=commitdiff_plain;h=refs%2Fchanges%2F85%2F9885%2F12;p=osm%2FLCM.git Feature 7184 New Generation RO enhancemnt - Adding ssh-key injection - Adding parameter instantiation to NG-RO - Removing for NG-RO vim creation and edition - Autodetect if it is old RO or new generatio RO - Provide cloud init text for new generatio RO - scaling for new generation RO - Adding sdn creation info at new generation RO Change-Id: I322c2a8989b58e89ad981926f11cfdd3e630b75a Signed-off-by: tierno --- diff --git a/osm_lcm/lcm.py b/osm_lcm/lcm.py index eaf2558..73bd7b4 100644 --- a/osm_lcm/lcm.py +++ b/osm_lcm/lcm.py @@ -94,13 +94,14 @@ class Lcm: "loglevel": config["RO"].get("loglevel", "ERROR"), } if not self.config["ro_config"]["uri"]: - if not self.config["ro_config"]["ng"]: - self.config["ro_config"]["uri"] = "http://{}:{}/openmano".format(config["RO"]["host"], - config["RO"]["port"]) - else: - self.config["ro_config"]["uri"] = "http://{}:{}/ro".format(config["RO"]["host"], config["RO"]["port"]) + self.config["ro_config"]["uri"] = "http://{}:{}/".format(config["RO"]["host"], config["RO"]["port"]) + elif "/ro" in self.config["ro_config"]["uri"][-4:] or "/openmano" in self.config["ro_config"]["uri"][-10:]: + # uri ends with '/ro', '/ro/', '/openmano', '/openmano/' + index = self.config["ro_config"]["uri"][-1].rfind("/") + self.config["ro_config"]["uri"] = self.config["ro_config"]["uri"][index+1] self.loop = loop or asyncio.get_event_loop() + self.ns = self.netslice = self.vim = self.wim = self.sdn = self.k8scluster = self.k8srepo = None # logging log_format_simple = "%(asctime)s %(levelname)s %(name)s %(filename)s:%(lineno)s %(message)s" @@ -200,31 +201,32 @@ class Lcm: config["tsdb"]["driver"])) else: self.prometheus = None - self.ns = ns.NsLcm(self.db, self.msg, self.fs, self.lcm_tasks, self.config, self.loop, self.prometheus) - self.netslice = netslice.NetsliceLcm(self.db, self.msg, self.fs, self.lcm_tasks, self.config, self.loop, - self.ns) - self.vim = vim_sdn.VimLcm(self.db, self.msg, self.fs, self.lcm_tasks, self.config, self.loop) - self.wim = vim_sdn.WimLcm(self.db, self.msg, self.fs, self.lcm_tasks, self.config, self.loop) - self.sdn = vim_sdn.SdnLcm(self.db, self.msg, self.fs, self.lcm_tasks, self.config, self.loop) - self.k8scluster = vim_sdn.K8sClusterLcm(self.db, self.msg, self.fs, self.lcm_tasks, self.config, self.loop) - self.k8srepo = vim_sdn.K8sRepoLcm(self.db, self.msg, self.fs, self.lcm_tasks, self.config, self.loop) async def check_RO_version(self): tries = 14 last_error = None while True: + ro_uri = self.config["ro_config"]["uri"] try: - if self.config["ro_config"].get("ng"): + # try new RO, if fail old RO + try: + self.config["ro_config"]["uri"] = ro_uri + "ro" ro_server = NgRoClient(self.loop, **self.config["ro_config"]) - else: + ro_version = await ro_server.get_version() + self.config["ro_config"]["ng"] = True + except Exception: + self.config["ro_config"]["uri"] = ro_uri + "openmano" ro_server = ROClient(self.loop, **self.config["ro_config"]) - ro_version = await ro_server.get_version() + ro_version = await ro_server.get_version() + self.config["ro_config"]["ng"] = False if versiontuple(ro_version) < versiontuple(min_RO_version): raise LcmException("Not compatible osm/RO version '{}'. Needed '{}' or higher".format( ro_version, min_RO_version)) - self.logger.info("Connected to RO version {}".format(ro_version)) + self.logger.info("Connected to RO version {} new-generation version {}". + format(ro_version, self.config["ro_config"]["ng"])) return except (ROClientException, NgRoException) as e: + self.config["ro_config"]["uri"] = ro_uri tries -= 1 error_text = "Error while connecting to RO on {}: {}".format(self.config["ro_config"]["uri"], e) if tries <= 0: @@ -421,8 +423,9 @@ class Lcm: elif topic == "vim_account": vim_id = params["_id"] if command in ("create", "created"): - task = asyncio.ensure_future(self.vim.create(params, order_id)) - self.lcm_tasks.register("vim_account", vim_id, order_id, "vim_create", task) + if not self.config["ro_config"].get("ng"): + task = asyncio.ensure_future(self.vim.create(params, order_id)) + self.lcm_tasks.register("vim_account", vim_id, order_id, "vim_create", task) return elif command == "delete" or command == "deleted": self.lcm_tasks.cancel(topic, vim_id) @@ -434,16 +437,18 @@ class Lcm: sys.stdout.flush() return elif command in ("edit", "edited"): - task = asyncio.ensure_future(self.vim.edit(params, order_id)) - self.lcm_tasks.register("vim_account", vim_id, order_id, "vim_edit", task) + if not self.config["ro_config"].get("ng"): + task = asyncio.ensure_future(self.vim.edit(params, order_id)) + self.lcm_tasks.register("vim_account", vim_id, order_id, "vim_edit", task) return elif command == "deleted": return # TODO cleaning of task just in case should be done elif topic == "wim_account": wim_id = params["_id"] if command in ("create", "created"): - task = asyncio.ensure_future(self.wim.create(params, order_id)) - self.lcm_tasks.register("wim_account", wim_id, order_id, "wim_create", task) + if not self.config["ro_config"].get("ng"): + task = asyncio.ensure_future(self.wim.create(params, order_id)) + self.lcm_tasks.register("wim_account", wim_id, order_id, "wim_create", task) return elif command == "delete" or command == "deleted": self.lcm_tasks.cancel(topic, wim_id) @@ -463,8 +468,9 @@ class Lcm: elif topic == "sdn": _sdn_id = params["_id"] if command in ("create", "created"): - task = asyncio.ensure_future(self.sdn.create(params, order_id)) - self.lcm_tasks.register("sdn", _sdn_id, order_id, "sdn_create", task) + if not self.config["ro_config"].get("ng"): + task = asyncio.ensure_future(self.sdn.create(params, order_id)) + self.lcm_tasks.register("sdn", _sdn_id, order_id, "sdn_create", task) return elif command == "delete" or command == "deleted": self.lcm_tasks.cancel(topic, _sdn_id) @@ -515,6 +521,15 @@ class Lcm: # check RO version self.loop.run_until_complete(self.check_RO_version()) + self.ns = ns.NsLcm(self.db, self.msg, self.fs, self.lcm_tasks, self.config, self.loop, self.prometheus) + self.netslice = netslice.NetsliceLcm(self.db, self.msg, self.fs, self.lcm_tasks, self.config, self.loop, + self.ns) + self.vim = vim_sdn.VimLcm(self.db, self.msg, self.fs, self.lcm_tasks, self.config, self.loop) + self.wim = vim_sdn.WimLcm(self.db, self.msg, self.fs, self.lcm_tasks, self.config, self.loop) + self.sdn = vim_sdn.SdnLcm(self.db, self.msg, self.fs, self.lcm_tasks, self.config, self.loop) + self.k8scluster = vim_sdn.K8sClusterLcm(self.db, self.msg, self.fs, self.lcm_tasks, self.config, self.loop) + self.k8srepo = vim_sdn.K8sRepoLcm(self.db, self.msg, self.fs, self.lcm_tasks, self.config, self.loop) + # configure tsdb prometheus if self.prometheus: self.loop.run_until_complete(self.prometheus.start()) diff --git a/osm_lcm/ns.py b/osm_lcm/ns.py index 198def1..2478310 100644 --- a/osm_lcm/ns.py +++ b/osm_lcm/ns.py @@ -158,6 +158,26 @@ class NsLcm(LcmBase): else: self.RO = ROclient.ROClient(self.loop, **self.ro_config) + @staticmethod + def increment_ip_mac(ip_mac, vm_index=1): + if not isinstance(ip_mac, str): + return ip_mac + try: + # try with ipv4 look for last dot + i = ip_mac.rfind(".") + if i > 0: + i += 1 + return "{}{}".format(ip_mac[:i], int(ip_mac[i:]) + vm_index) + # try with ipv6 or mac look for last colon. Operate in hex + i = ip_mac.rfind(":") + if i > 0: + i += 1 + # format in hex, len can be 2 for mac or 4 for ipv6 + return ("{}{:0" + str(len(ip_mac) - i) + "x}").format(ip_mac[:i], int(ip_mac[i:], 16) + vm_index) + except Exception: + pass + return None + def _on_update_ro_db(self, nsrs_id, ro_descriptor): # self.logger.debug('_on_update_ro_db(nsrs_id={}'.format(nsrs_id)) @@ -353,6 +373,24 @@ class NsLcm(LcmBase): vdu.pop("cloud-init", None) return vnfd_RO + @staticmethod + def ip_profile_2_RO(ip_profile): + RO_ip_profile = deepcopy(ip_profile) + if "dns-server" in RO_ip_profile: + if isinstance(RO_ip_profile["dns-server"], list): + RO_ip_profile["dns-address"] = [] + for ds in RO_ip_profile.pop("dns-server"): + RO_ip_profile["dns-address"].append(ds['address']) + else: + RO_ip_profile["dns-address"] = RO_ip_profile.pop("dns-server") + if RO_ip_profile.get("ip-version") == "ipv4": + RO_ip_profile["ip-version"] = "IPv4" + if RO_ip_profile.get("ip-version") == "ipv6": + RO_ip_profile["ip-version"] = "IPv6" + if "dhcp-params" in RO_ip_profile: + RO_ip_profile["dhcp"] = RO_ip_profile.pop("dhcp-params") + return RO_ip_profile + def _ns_params_2_RO(self, ns_params, nsd, vnfd_dict, db_vnfrs, n2vc_key_list): """ Creates a RO ns descriptor from OSM ns_instantiate params @@ -394,23 +432,6 @@ class NsLcm(LcmBase): else: return wim_account - def ip_profile_2_RO(ip_profile): - RO_ip_profile = deepcopy((ip_profile)) - if "dns-server" in RO_ip_profile: - if isinstance(RO_ip_profile["dns-server"], list): - RO_ip_profile["dns-address"] = [] - for ds in RO_ip_profile.pop("dns-server"): - RO_ip_profile["dns-address"].append(ds['address']) - else: - RO_ip_profile["dns-address"] = RO_ip_profile.pop("dns-server") - if RO_ip_profile.get("ip-version") == "ipv4": - RO_ip_profile["ip-version"] = "IPv4" - if RO_ip_profile.get("ip-version") == "ipv6": - RO_ip_profile["ip-version"] = "IPv6" - if "dhcp-params" in RO_ip_profile: - RO_ip_profile["dhcp"] = RO_ip_profile.pop("dhcp-params") - return RO_ip_profile - if not ns_params: return None RO_ns_params = { @@ -533,7 +554,7 @@ class NsLcm(LcmBase): if internal_vld_params.get("ip-profile"): populate_dict(RO_ns_params, ("vnfs", vnf_params["member-vnf-index"], "networks", internal_vld_params["name"], "ip-profile"), - ip_profile_2_RO(internal_vld_params["ip-profile"])) + self.ip_profile_2_RO(internal_vld_params["ip-profile"])) if internal_vld_params.get("provider-network"): populate_dict(RO_ns_params, ("vnfs", vnf_params["member-vnf-index"], "networks", @@ -570,7 +591,7 @@ class NsLcm(LcmBase): for vld_params in get_iterable(ns_params, "vld"): if "ip-profile" in vld_params: populate_dict(RO_ns_params, ("networks", vld_params["name"], "ip-profile"), - ip_profile_2_RO(vld_params["ip-profile"])) + self.ip_profile_2_RO(vld_params["ip-profile"])) if vld_params.get("provider-network"): @@ -649,54 +670,53 @@ class NsLcm(LcmBase): cp_params["mac-address"]) return RO_ns_params - def scale_vnfr(self, db_vnfr, vdu_create=None, vdu_delete=None): - # make a copy to do not change - vdu_create = copy(vdu_create) - vdu_delete = copy(vdu_delete) - - vdurs = db_vnfr.get("vdur") - if vdurs is None: - vdurs = [] - vdu_index = len(vdurs) - while vdu_index: - vdu_index -= 1 - vdur = vdurs[vdu_index] - if vdur.get("pdu-type"): - continue - vdu_id_ref = vdur["vdu-id-ref"] - if vdu_create and vdu_create.get(vdu_id_ref): - vdur_copy = deepcopy(vdur) - vdur_copy["status"] = "BUILD" - vdur_copy["status-detailed"] = None - vdur_copy["ip_address"]: None - for iface in vdur_copy["interfaces"]: - iface["ip-address"] = None - iface["mac-address"] = None - iface.pop("mgmt_vnf", None) # only first vdu can be managment of vnf # TODO ALF - for index in range(0, vdu_create[vdu_id_ref]): + def scale_vnfr(self, db_vnfr, vdu_create=None, vdu_delete=None, mark_delete=False): + + db_vdu_push_list = [] + db_update = {"_admin.modified": time()} + if vdu_create: + for vdu_id, vdu_count in vdu_create.items(): + vdur = next((vdur for vdur in reversed(db_vnfr["vdur"]) if vdur["vdu-id-ref"] == vdu_id), None) + if not vdur: + raise LcmException("Error scaling OUT VNFR for {}. There is not any existing vnfr. Scaled to 0?". + format(vdu_id)) + + for count in range(vdu_count): + vdur_copy = deepcopy(vdur) + vdur_copy["status"] = "BUILD" + vdur_copy["status-detailed"] = None + vdur_copy["ip-address"]: None vdur_copy["_id"] = str(uuid4()) - vdur_copy["count-index"] += 1 - vdurs.insert(vdu_index+1+index, vdur_copy) - self.logger.debug("scale out, adding vdu={}".format(vdur_copy)) - vdur_copy = deepcopy(vdur_copy) - - del vdu_create[vdu_id_ref] - if vdu_delete and vdu_delete.get(vdu_id_ref): - del vdurs[vdu_index] - vdu_delete[vdu_id_ref] -= 1 - if not vdu_delete[vdu_id_ref]: - del vdu_delete[vdu_id_ref] - # check all operations are done - if vdu_create or vdu_delete: - raise LcmException("Error scaling OUT VNFR for {}. There is not any existing vnfr. Scaled to 0?".format( - vdu_create)) + vdur_copy["count-index"] += count + 1 + vdur_copy["id"] = "{}-{}".format(vdur_copy["vdu-id-ref"], vdur_copy["count-index"]) + vdur_copy.pop("vim_info", None) + for iface in vdur_copy["interfaces"]: + if iface.get("fixed-ip"): + iface["ip-address"] = self.increment_ip_mac(iface["ip-address"], count+1) + else: + iface.pop("ip-address", None) + if iface.get("fixed-mac"): + iface["mac-address"] = self.increment_ip_mac(iface["mac-address"], count+1) + else: + iface.pop("mac-address", None) + iface.pop("mgmt_vnf", None) # only first vdu can be managment of vnf + db_vdu_push_list.append(vdur_copy) + # self.logger.debug("scale out, adding vdu={}".format(vdur_copy)) if vdu_delete: - raise LcmException("Error scaling IN VNFR for {}. There is not any existing vnfr. Scaled to 0?".format( - vdu_delete)) - - vnfr_update = {"vdur": vdurs} - db_vnfr["vdur"] = vdurs - self.update_db_2("vnfrs", db_vnfr["_id"], vnfr_update) + for vdu_id, vdu_count in vdu_delete.items(): + if mark_delete: + indexes_to_delete = [iv[0] for iv in enumerate(db_vnfr["vdur"]) if iv[1]["vdu-id-ref"] == vdu_id] + db_update.update({"vdur.{}.status".format(i): "DELETING" for i in indexes_to_delete[-vdu_count:]}) + else: + # it must be deleted one by one because common.db does not allow otherwise + vdus_to_delete = [v for v in reversed(db_vnfr["vdur"]) if v["vdu-id-ref"] == vdu_id] + for vdu in vdus_to_delete[:vdu_count]: + self.db.set_one("vnfrs", {"_id": db_vnfr["_id"]}, None, pull={"vdur": {"_id": vdu["_id"]}}) + db_push = {"vdur": db_vdu_push_list} if db_vdu_push_list else None + self.db.set_one("vnfrs", {"_id": db_vnfr["_id"]}, db_update, push_list=db_push) + # modify passed dictionary db_vnfr + db_vnfr_ = self.db.get_one("vnfrs", {"_id": db_vnfr["_id"]}) + db_vnfr["vdur"] = db_vnfr_["vdur"] def ns_update_nsr(self, ns_update_nsr, db_nsr, nsr_desc_RO): """ @@ -870,6 +890,38 @@ class NsLcm(LcmBase): async def _instantiate_ng_ro(self, logging_text, nsr_id, nsd, db_nsr, db_nslcmop, db_vnfrs, db_vnfds_ref, n2vc_key_list, stage, start_deploy, timeout_ns_deploy): + + db_vims = {} + + def get_vim_account(vim_account_id): + nonlocal db_vims + if vim_account_id in db_vims: + return db_vims[vim_account_id] + db_vim = self.db.get_one("vim_accounts", {"_id": vim_account_id}) + db_vims[vim_account_id] = db_vim + return db_vim + + # modify target_vld info with instantiation parameters + def parse_vld_instantiation_params(target_vim, target_vld, vld_params, target_sdn): + if vld_params.get("ip-profile"): + target_vld["vim_info"][target_vim]["ip_profile"] = vld_params["ip-profile"] + if vld_params.get("provider-network"): + target_vld["vim_info"][target_vim]["provider_network"] = vld_params["provider-network"] + if "sdn-ports" in vld_params["provider-network"] and target_sdn: + target_vld["vim_info"][target_sdn]["sdn-ports"] = vld_params["provider-network"]["sdn-ports"] + if vld_params.get("wimAccountId"): + target_wim = "wim:{}".format(vld_params["wimAccountId"]) + target_vld["vim_info"][target_wim] = {} + for param in ("vim-network-name", "vim-network-id"): + if vld_params.get(param): + if isinstance(vld_params[param], dict): + pass + # for vim_account, vim_net in vld_params[param].items(): + # TODO populate vim_info RO_vld_sites.append({ + else: # isinstance str + target_vld["vim_info"][target_vim][param.replace("-", "_")] = vld_params[param] + # TODO if vld_params.get("ns-net"): + nslcmop_id = db_nslcmop["_id"] target = { "name": db_nsr["name"], @@ -878,13 +930,20 @@ class NsLcm(LcmBase): "image": deepcopy(db_nsr["image"]), "flavor": deepcopy(db_nsr["flavor"]), "action_id": nslcmop_id, + "cloud_init_content": {}, } for image in target["image"]: - image["vim_info"] = [] + image["vim_info"] = {} for flavor in target["flavor"]: - flavor["vim_info"] = [] + flavor["vim_info"] = {} - ns_params = db_nslcmop.get("operationParams") + if db_nslcmop.get("lcmOperationType") != "instantiate": + # get parameters of instantiation: + db_nslcmop_instantiate = self.db.get_list("nslcmops", {"nsInstanceId": db_nslcmop["nsInstanceId"], + "lcmOperationType": "instantiate"})[-1] + ns_params = db_nslcmop_instantiate.get("operationParams") + else: + ns_params = db_nslcmop.get("operationParams") ssh_keys = [] if ns_params.get("ssh_keys"): ssh_keys += ns_params.get("ssh_keys") @@ -892,36 +951,91 @@ class NsLcm(LcmBase): ssh_keys += n2vc_key_list cp2target = {} - for vld_index, vld in enumerate(nsd.get("vld")): - target_vld = {"id": vld["id"], - "name": vld["name"], - "mgmt-network": vld.get("mgmt-network", False), - "type": vld.get("type"), - "vim_info": [{"vim-network-name": vld.get("vim-network-name"), - "vim_account_id": ns_params["vimAccountId"]}], - } - for cp in vld["vnfd-connection-point-ref"]: + for vld_index, vld in enumerate(db_nsr.get("vld")): + target_vim = "vim:{}".format(ns_params["vimAccountId"]) + target_vld = { + "id": vld["id"], + "name": vld["name"], + "mgmt-network": vld.get("mgmt-network", False), + "type": vld.get("type"), + "vim_info": { + target_vim: {"vim-network-name": vld.get("vim-network-name")} + } + } + # check if this network needs SDN assist + target_sdn = None + if vld.get("pci-interfaces"): + db_vim = get_vim_account(ns_params["vimAccountId"]) + sdnc_id = db_vim["config"].get("sdn-controller") + if sdnc_id: + sdn_vld = "nsrs:{}:vld.{}".format(nsr_id, vld["id"]) + target_sdn = "sdn:{}".format(sdnc_id) + target_vld["vim_info"][target_sdn] = { + "sdn": True, "target_vim": target_vim, "vlds": [sdn_vld], "type": vld.get("type")} + + nsd_vld = next(v for v in nsd["vld"] if v["id"] == vld["id"]) + for cp in nsd_vld["vnfd-connection-point-ref"]: cp2target["member_vnf:{}.{}".format(cp["member-vnf-index-ref"], cp["vnfd-connection-point-ref"])] = \ "nsrs:{}:vld.{}".format(nsr_id, vld_index) + + # check at nsd descriptor, if there is an ip-profile + vld_params = {} + if nsd_vld.get("ip-profile-ref"): + ip_profile = next(ipp for ipp in nsd["ip-profiles"] if ipp["name"] == nsd_vld["ip-profile-ref"]) + vld_params["ip-profile"] = ip_profile["ip-profile-params"] + # update vld_params with instantiation params + vld_instantiation_params = next((v for v in get_iterable(ns_params, "vld") + if v["name"] in (vld["name"], vld["id"])), None) + if vld_instantiation_params: + vld_params.update(vld_instantiation_params) + parse_vld_instantiation_params(target_vim, target_vld, vld_params, target_sdn) target["ns"]["vld"].append(target_vld) for vnfr in db_vnfrs.values(): vnfd = db_vnfds_ref[vnfr["vnfd-ref"]] + vnf_params = next((v for v in get_iterable(ns_params, "vnf") + if v["member-vnf-index"] == vnfr["member-vnf-index-ref"]), None) target_vnf = deepcopy(vnfr) + target_vim = "vim:{}".format(vnfr["vim-account-id"]) for vld in target_vnf.get("vld", ()): - # check if connected to a ns.vld + # check if connected to a ns.vld, to fill target' vnf_cp = next((cp for cp in vnfd.get("connection-point", ()) if cp.get("internal-vld-ref") == vld["id"]), None) if vnf_cp: ns_cp = "member_vnf:{}.{}".format(vnfr["member-vnf-index-ref"], vnf_cp["id"]) if cp2target.get(ns_cp): vld["target"] = cp2target[ns_cp] - vld["vim_info"] = [{"vim-network-name": vld.get("vim-network-name"), - "vim_account_id": vnfr["vim-account-id"]}] - + vld["vim_info"] = {target_vim: {"vim-network-name": vld.get("vim-network-name")}} + # check if this network needs SDN assist + target_sdn = None + if vld.get("pci-interfaces"): + db_vim = get_vim_account(vnfr["vim-account-id"]) + sdnc_id = db_vim["config"].get("sdn-controller") + if sdnc_id: + sdn_vld = "vnfrs:{}:vld.{}".format(target_vnf["_id"], vld["id"]) + target_sdn = "sdn:{}".format(sdnc_id) + vld["vim_info"][target_sdn] = { + "sdn": True, "target_vim": target_vim, "vlds": [sdn_vld], "type": vld.get("type")} + + # check at vnfd descriptor, if there is an ip-profile + vld_params = {} + vnfd_vld = next(v for v in vnfd["internal-vld"] if v["id"] == vld["id"]) + if vnfd_vld.get("ip-profile-ref"): + ip_profile = next(ipp for ipp in vnfd["ip-profiles"] if ipp["name"] == vnfd_vld["ip-profile-ref"]) + vld_params["ip-profile"] = ip_profile["ip-profile-params"] + # update vld_params with instantiation params + if vnf_params: + vld_instantiation_params = next((v for v in get_iterable(vnf_params, "internal-vld") + if v["name"] == vld["id"]), None) + if vld_instantiation_params: + vld_params.update(vld_instantiation_params) + parse_vld_instantiation_params(target_vim, vld, vld_params, target_sdn) + + vdur_list = [] for vdur in target_vnf.get("vdur", ()): - vdur["vim_info"] = [{"vim_account_id": vnfr["vim-account-id"]}] + if vdur.get("status") == "DELETING" or vdur.get("pdu-type"): + continue # This vdu must not be created + vdur["vim_info"] = {target_vim: {}} vdud_index, vdud = next(k for k in enumerate(vnfd["vdu"]) if k[1]["id"] == vdur["vdu-id-ref"]) - # vdur["additionalParams"] = vnfr.get("additionalParamsForVnf") # TODO additional params for VDU if ssh_keys: if deep_get(vdud, ("vdu-configuration", "config-access", "ssh-access", "required")): @@ -935,26 +1049,43 @@ class NsLcm(LcmBase): # cloud-init if vdud.get("cloud-init-file"): vdur["cloud-init"] = "{}:file:{}".format(vnfd["_id"], vdud.get("cloud-init-file")) + # read file and put content at target.cloul_init_content. Avoid ng_ro to use shared package system + if vdur["cloud-init"] not in target["cloud_init_content"]: + base_folder = vnfd["_admin"]["storage"] + cloud_init_file = "{}/{}/cloud_init/{}".format(base_folder["folder"], base_folder["pkg-dir"], + vdud.get("cloud-init-file")) + with self.fs.file_open(cloud_init_file, "r") as ci_file: + target["cloud_init_content"][vdur["cloud-init"]] = ci_file.read() elif vdud.get("cloud-init"): vdur["cloud-init"] = "{}:vdu:{}".format(vnfd["_id"], vdud_index) + # put content at target.cloul_init_content. Avoid ng_ro read vnfd descriptor + target["cloud_init_content"][vdur["cloud-init"]] = vdud["cloud-init"] + vdur["additionalParams"] = vdur.get("additionalParams") or {} + deploy_params_vdu = self._format_additional_params(vdur.get("additionalParams") or {}) + deploy_params_vdu["OSM"] = self._get_osm_params(vnfr, vdur["vdu-id-ref"], vdur["count-index"]) + vdur["additionalParams"] = deploy_params_vdu # flavor ns_flavor = target["flavor"][int(vdur["ns-flavor-id"])] - if not next((vi for vi in ns_flavor["vim_info"] if - vi and vi.get("vim_account_id") == vnfr["vim-account-id"]), None): - ns_flavor["vim_info"].append({"vim_account_id": vnfr["vim-account-id"]}) + if target_vim not in ns_flavor["vim_info"]: + ns_flavor["vim_info"][target_vim] = {} # image ns_image = target["image"][int(vdur["ns-image-id"])] - if not next((vi for vi in ns_image["vim_info"] if - vi and vi.get("vim_account_id") == vnfr["vim-account-id"]), None): - ns_image["vim_info"].append({"vim_account_id": vnfr["vim-account-id"]}) - - vdur["vim_info"] = [{"vim_account_id": vnfr["vim-account-id"]}] + if target_vim not in ns_image["vim_info"]: + ns_image["vim_info"][target_vim] = {} + + vdur["vim_info"] = {target_vim: {}} + # instantiation parameters + # if vnf_params: + # vdu_instantiation_params = next((v for v in get_iterable(vnf_params, "vdu") if v["id"] == + # vdud["id"]), None) + vdur_list.append(vdur) + target_vnf["vdur"] = vdur_list target["vnf"].append(target_vnf) desc = await self.RO.deploy(nsr_id, target) action_id = desc["action_id"] - await self._wait_ng_ro(self, nsr_id, action_id, nslcmop_id, start_deploy, timeout_ns_deploy, stage) + await self._wait_ng_ro(nsr_id, action_id, nslcmop_id, start_deploy, timeout_ns_deploy, stage) # Updating NSR db_nsr_update = { @@ -967,21 +1098,24 @@ class NsLcm(LcmBase): self.logger.debug(logging_text + "ns deployed at RO. RO_id={}".format(action_id)) return - async def _wait_ng_ro(self, nsr_id, action_id, nslcmop_id, start_time, timeout, stage): + async def _wait_ng_ro(self, nsr_id, action_id, nslcmop_id=None, start_time=None, timeout=600, stage=None): detailed_status_old = None db_nsr_update = {} + start_time = start_time or time() while time() <= start_time + timeout: desc_status = await self.RO.status(nsr_id, action_id) if desc_status["status"] == "FAILED": raise NgRoException(desc_status["details"]) elif desc_status["status"] == "BUILD": - stage[2] = "VIM: ({})".format(desc_status["details"]) + if stage: + stage[2] = "VIM: ({})".format(desc_status["details"]) elif desc_status["status"] == "DONE": - stage[2] = "Deployed at VIM" + if stage: + stage[2] = "Deployed at VIM" break else: assert False, "ROclient.check_ns_status returns unknown {}".format(desc_status["status"]) - if stage[2] != detailed_status_old: + if stage and nslcmop_id and stage[2] != detailed_status_old: detailed_status_old = stage[2] db_nsr_update["detailed-status"] = " ".join(stage) self.update_db_2("nsrs", nsr_id, db_nsr_update) @@ -1001,6 +1135,7 @@ class NsLcm(LcmBase): "vnf": [], "image": [], "flavor": [], + "action_id": nslcmop_id } desc = await self.RO.deploy(nsr_id, target) action_id = desc["action_id"] @@ -1010,7 +1145,7 @@ class NsLcm(LcmBase): # wait until done delete_timeout = 20 * 60 # 20 minutes - await self._wait_ng_ro(self, nsr_id, action_id, nslcmop_id, start_deploy, delete_timeout, stage) + await self._wait_ng_ro(nsr_id, action_id, nslcmop_id, start_deploy, delete_timeout, stage) db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED" @@ -1277,9 +1412,12 @@ class NsLcm(LcmBase): self._write_op_status(nslcmop_id, stage) # await self._on_update_n2vc_db("nsrs", {"_id": nsr_id}, "_admin.deployed", db_nsr_update) # self.logger.debug(logging_text + "Deployed at VIM") - except (ROclient.ROClientException, LcmException, DbException, NgRoException) as e: + except Exception as e: stage[2] = "ERROR deploying at VIM" self.set_vnfr_at_error(db_vnfrs, str(e)) + self.logger.error("Error deploying at VIM {}".format(e), + exc_info=not isinstance(e, (ROclient.ROClientException, LcmException, DbException, + NgRoException))) raise async def wait_kdu_up(self, logging_text, nsr_id, vnfr_id, kdu_name): @@ -1323,7 +1461,7 @@ class NsLcm(LcmBase): :return: IP address """ - # self.logger.debug(logging_text + "Starting wait_vm_up_insert_key_ro") + self.logger.debug(logging_text + "Starting wait_vm_up_insert_key_ro") ro_nsr_id = None ip_address = None nb_tries = 0 @@ -1358,13 +1496,17 @@ class NsLcm(LcmBase): if not vdur: raise LcmException("Not found vnfr_id={}, vdu_id={}, vdu_index={}".format(vnfr_id, vdu_id, vdu_index)) - - if vdur.get("pdu-type") or vdur.get("status") == "ACTIVE": + # New generation RO stores information at "vim_info" + ng_ro_status = None + if vdur.get("vim_info"): + target_vim = next(t for t in vdur["vim_info"]) # there should be only one key + ng_ro_status = vdur["vim_info"][target_vim].get("vim_status") + if vdur.get("pdu-type") or vdur.get("status") == "ACTIVE" or ng_ro_status == "ACTIVE": ip_address = vdur.get("ip-address") if not ip_address: continue target_vdu_id = vdur["vdu-id-ref"] - elif vdur.get("status") == "ERROR": + elif vdur.get("status") == "ERROR" or vdur["vim_info"][target_vim].get("vim_status") == "ERROR": raise LcmException("Cannot inject ssh-key because target VM is in error state") if not target_vdu_id: @@ -1372,25 +1514,28 @@ class NsLcm(LcmBase): # inject public key into machine if pub_key and user: - # wait until NS is deployed at RO - if not ro_nsr_id: - db_nsrs = self.db.get_one("nsrs", {"_id": nsr_id}) - ro_nsr_id = deep_get(db_nsrs, ("_admin", "deployed", "RO", "nsr_id")) - if not ro_nsr_id: - continue - - # self.logger.debug(logging_text + "Inserting RO key") + self.logger.debug(logging_text + "Inserting RO key") if vdur.get("pdu-type"): self.logger.error(logging_text + "Cannot inject ssh-ky to a PDU") return ip_address try: ro_vm_id = "{}-{}".format(db_vnfr["member-vnf-index-ref"], target_vdu_id) # TODO add vdu_index if self.ng_ro: + self.logger.debug(logging_text + "ALF lanzando orden") target = {"action": "inject_ssh_key", "key": pub_key, "user": user, - "vnf": [{"_id": vnfr_id, "vdur": [{"id": vdu_id}]}], + "vnf": [{"_id": vnfr_id, "vdur": [{"id": vdur["id"]}]}], } - await self.RO.deploy(nsr_id, target) + desc = await self.RO.deploy(nsr_id, target) + action_id = desc["action_id"] + await self._wait_ng_ro(nsr_id, action_id, timeout=600) + break else: + # wait until NS is deployed at RO + if not ro_nsr_id: + db_nsrs = self.db.get_one("nsrs", {"_id": nsr_id}) + ro_nsr_id = deep_get(db_nsrs, ("_admin", "deployed", "RO", "nsr_id")) + if not ro_nsr_id: + continue result_dict = await self.RO.create_action( item="ns", item_id_name=ro_nsr_id, @@ -2944,7 +3089,7 @@ class NsLcm(LcmBase): # 'detailed-status' : status message # 'operationType': may be any type, in the case of scaling: 'PRE-SCALE' | 'POST-SCALE' # Status and operation type are currently only used for 'scale', but NOT for 'terminate' sub-operations. - def _add_suboperation(self, db_nslcmop, vnf_index, vdu_id, vdu_count_index, vdu_name, primitive, + def _add_suboperation(self, db_nslcmop, vnf_index, vdu_id, vdu_count_index, vdu_name, primitive, mapped_primitive_params, operationState=None, detailed_status=None, operationType=None, RO_nsr_id=None, RO_scaling_info=None): if not db_nslcmop: @@ -3546,11 +3691,11 @@ class NsLcm(LcmBase): error_list.append(created_tasks_info[task]) error_detail_list.append(new_error) if isinstance(exc, (str, DbException, N2VCException, ROclient.ROClientException, LcmException, - K8sException)): + K8sException, NgRoException)): self.logger.error(logging_text + new_error) else: exc_traceback = "".join(traceback.format_exception(None, exc, exc.__traceback__)) - self.logger.error(logging_text + created_tasks_info[task] + exc_traceback) + self.logger.error(logging_text + created_tasks_info[task] + " " + exc_traceback) else: self.logger.debug(logging_text + created_tasks_info[task] + ": Done") stage[1] = "{}/{}.".format(num_done, num_tasks) @@ -3939,6 +4084,8 @@ class NsLcm(LcmBase): return logging_text = "Task ns={} scale={} ".format(nsr_id, nslcmop_id) + stage = ['', '', ''] + # ^ stage, step, VIM progress self.logger.debug(logging_text + "Enter") # get all needed from database db_nsr = None @@ -3985,7 +4132,7 @@ class NsLcm(LcmBase): # vdu_name = db_nslcmop["operationParams"].get("vdu_name") ####### - RO_nsr_id = nsr_deployed["RO"]["nsr_id"] + RO_nsr_id = nsr_deployed["RO"].get("nsr_id") vnf_index = db_nslcmop["operationParams"]["scaleVnfData"]["scaleByStepData"]["member-vnf-index"] scaling_group = db_nslcmop["operationParams"]["scaleVnfData"]["scaleByStepData"]["scaling-group-descriptor"] scaling_type = db_nslcmop["operationParams"]["scaleVnfData"]["scaleVnfType"] @@ -4083,14 +4230,13 @@ class NsLcm(LcmBase): vdu_scaling_info["vdu-delete"][vdu_scale_info["vdu-id-ref"]] = vdu_scale_info.get("count", 1) # update VDU_SCALING_INFO with the VDUs to delete ip_addresses - vdu_create = vdu_scaling_info.get("vdu-create") vdu_delete = copy(vdu_scaling_info.get("vdu-delete")) if vdu_scaling_info["scaling_direction"] == "IN": for vdur in reversed(db_vnfr["vdur"]): if vdu_delete.get(vdur["vdu-id-ref"]): vdu_delete[vdur["vdu-id-ref"]] -= 1 vdu_scaling_info["vdu"].append({ - "name": vdur["name"], + "name": vdur.get("name") or vdur.get("vdu-name"), "vdu_id": vdur["vdu-id-ref"], "interface": [] }) @@ -4100,7 +4246,7 @@ class NsLcm(LcmBase): "ip_address": interface["ip-address"], "mac_address": interface.get("mac-address"), }) - vdu_delete = vdu_scaling_info.pop("vdu-delete") + # vdu_delete = vdu_scaling_info.pop("vdu-delete") # PRE-SCALE BEGIN step = "Executing pre-scale vnf-config-primitive" @@ -4177,120 +4323,19 @@ class NsLcm(LcmBase): scale_process = None # PRE-SCALE END + db_nsr_update["_admin.scaling-group.{}.nb-scale-op".format(admin_scale_index)] = nb_scale_op + db_nsr_update["_admin.scaling-group.{}.time".format(admin_scale_index)] = time() + # SCALE RO - BEGIN - # Should this block be skipped if 'RO_nsr_id' == None ? - # if (RO_nsr_id and RO_scaling_info): if RO_scaling_info: scale_process = "RO" - # Scale RO retry check: Check if this sub-operation has been executed before - op_index = self._check_or_add_scale_suboperation( - db_nslcmop, vnf_index, None, None, 'SCALE-RO', RO_nsr_id, RO_scaling_info) - if op_index == self.SUBOPERATION_STATUS_SKIP: - # Skip sub-operation - result = 'COMPLETED' - result_detail = 'Done' - self.logger.debug(logging_text + "Skipped sub-operation RO, result {} {}".format( - result, result_detail)) + if self.ro_config.get("ng"): + await self._scale_ng_ro(logging_text, db_nsr, db_nslcmop, db_vnfr, vdu_scaling_info, stage) else: - if op_index == self.SUBOPERATION_STATUS_NEW: - # New sub-operation: Get index of this sub-operation - op_index = len(db_nslcmop.get('_admin', {}).get('operations')) - 1 - self.logger.debug(logging_text + "New sub-operation RO") - else: - # retry: Get registered params for this existing sub-operation - op = db_nslcmop.get('_admin', {}).get('operations', [])[op_index] - RO_nsr_id = op.get('RO_nsr_id') - RO_scaling_info = op.get('RO_scaling_info') - self.logger.debug(logging_text + "Sub-operation RO retry for primitive {}".format( - vnf_config_primitive)) - - RO_desc = await self.RO.create_action("ns", RO_nsr_id, {"vdu-scaling": RO_scaling_info}) - db_nsr_update["_admin.scaling-group.{}.nb-scale-op".format(admin_scale_index)] = nb_scale_op - db_nsr_update["_admin.scaling-group.{}.time".format(admin_scale_index)] = time() - # wait until ready - RO_nslcmop_id = RO_desc["instance_action_id"] - db_nslcmop_update["_admin.deploy.RO"] = RO_nslcmop_id - - RO_task_done = False - step = detailed_status = "Waiting for VIM to scale. RO_task_id={}.".format(RO_nslcmop_id) - detailed_status_old = None - self.logger.debug(logging_text + step) - - deployment_timeout = 1 * 3600 # One hour - while deployment_timeout > 0: - if not RO_task_done: - desc = await self.RO.show("ns", item_id_name=RO_nsr_id, extra_item="action", - extra_item_id=RO_nslcmop_id) - - # deploymentStatus - self._on_update_ro_db(nsrs_id=nsr_id, ro_descriptor=desc) - - ns_status, ns_status_info = self.RO.check_action_status(desc) - if ns_status == "ERROR": - raise ROclient.ROClientException(ns_status_info) - elif ns_status == "BUILD": - detailed_status = step + "; {}".format(ns_status_info) - elif ns_status == "ACTIVE": - RO_task_done = True - self.scale_vnfr(db_vnfr, vdu_create=vdu_create, vdu_delete=vdu_delete) - step = detailed_status = "Waiting ns ready at RO. RO_id={}".format(RO_nsr_id) - self.logger.debug(logging_text + step) - else: - assert False, "ROclient.check_action_status returns unknown {}".format(ns_status) - else: - desc = await self.RO.show("ns", RO_nsr_id) - ns_status, ns_status_info = self.RO.check_ns_status(desc) - # deploymentStatus - self._on_update_ro_db(nsrs_id=nsr_id, ro_descriptor=desc) - - if ns_status == "ERROR": - raise ROclient.ROClientException(ns_status_info) - elif ns_status == "BUILD": - detailed_status = step + "; {}".format(ns_status_info) - elif ns_status == "ACTIVE": - step = detailed_status = \ - "Waiting for management IP address reported by the VIM. Updating VNFRs" - try: - # nsr_deployed["nsr_ip"] = RO.get_ns_vnf_info(desc) - self.ns_update_vnfr({db_vnfr["member-vnf-index-ref"]: db_vnfr}, desc) - break - except LcmExceptionNoMgmtIP: - pass - else: - assert False, "ROclient.check_ns_status returns unknown {}".format(ns_status) - if detailed_status != detailed_status_old: - self._update_suboperation_status( - db_nslcmop, op_index, 'COMPLETED', detailed_status) - detailed_status_old = db_nslcmop_update["detailed-status"] = detailed_status - self.update_db_2("nslcmops", nslcmop_id, db_nslcmop_update) - - await asyncio.sleep(5, loop=self.loop) - deployment_timeout -= 5 - if deployment_timeout <= 0: - self._update_suboperation_status( - db_nslcmop, nslcmop_id, op_index, 'FAILED', "Timeout when waiting for ns to get ready") - raise ROclient.ROClientException("Timeout waiting ns to be ready") - - # update VDU_SCALING_INFO with the obtained ip_addresses - if vdu_scaling_info["scaling_direction"] == "OUT": - for vdur in reversed(db_vnfr["vdur"]): - if vdu_scaling_info["vdu-create"].get(vdur["vdu-id-ref"]): - vdu_scaling_info["vdu-create"][vdur["vdu-id-ref"]] -= 1 - vdu_scaling_info["vdu"].append({ - "name": vdur["name"], - "vdu_id": vdur["vdu-id-ref"], - "interface": [] - }) - for interface in vdur["interfaces"]: - vdu_scaling_info["vdu"][-1]["interface"].append({ - "name": interface["name"], - "ip_address": interface["ip-address"], - "mac_address": interface.get("mac-address"), - }) - del vdu_scaling_info["vdu-create"] - - self._update_suboperation_status(db_nslcmop, op_index, 'COMPLETED', 'Done') - # SCALE RO - END + await self._RO_scale(logging_text, RO_nsr_id, RO_scaling_info, db_nslcmop, db_vnfr, + db_nslcmop_update, vdu_scaling_info) + vdu_scaling_info.pop("vdu-create", None) + vdu_scaling_info.pop("vdu-delete", None) scale_process = None if db_nsr_update: @@ -4376,7 +4421,7 @@ class NsLcm(LcmBase): else old_operational_status db_nsr_update["config-status"] = old_config_status return - except (ROclient.ROClientException, DbException, LcmException) as e: + except (ROclient.ROClientException, DbException, LcmException, NgRoException) as e: self.logger.error(logging_text + "Exit Exception {}".format(e)) exc = e except asyncio.CancelledError: @@ -4440,6 +4485,148 @@ class NsLcm(LcmBase): self.logger.debug(logging_text + "Exit") self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_scale") + async def _scale_ng_ro(self, logging_text, db_nsr, db_nslcmop, db_vnfr, vdu_scaling_info, stage): + nsr_id = db_nslcmop["nsInstanceId"] + db_nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]}) + db_vnfrs = {} + + # read from db: vnfd's for every vnf + db_vnfds = {} # every vnfd data indexed by vnf id + db_vnfds_ref = {} # every vnfd data indexed by vnfd id + db_vnfds = {} + + # for each vnf in ns, read vnfd + for vnfr in self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id}): + db_vnfrs[vnfr["member-vnf-index-ref"]] = vnfr + vnfd_id = vnfr["vnfd-id"] # vnfd uuid for this vnf + vnfd_ref = vnfr["vnfd-ref"] # vnfd name for this vnf + # if we haven't this vnfd, read it from db + if vnfd_id not in db_vnfds: + # read from db + vnfd = self.db.get_one("vnfds", {"_id": vnfd_id}) + db_vnfds_ref[vnfd_ref] = vnfd # vnfd's indexed by name + db_vnfds[vnfd_id] = vnfd # vnfd's indexed by id + n2vc_key = self.n2vc.get_public_key() + n2vc_key_list = [n2vc_key] + self.scale_vnfr(db_vnfr, vdu_scaling_info.get("vdu-create"), vdu_scaling_info.get("vdu-delete"), + mark_delete=True) + # db_vnfr has been updated, update db_vnfrs to use it + db_vnfrs[db_vnfr["member-vnf-index-ref"]] = db_vnfr + await self._instantiate_ng_ro(logging_text, nsr_id, db_nsd, db_nsr, db_nslcmop, db_vnfrs, + db_vnfds_ref, n2vc_key_list, stage=stage, start_deploy=time(), + timeout_ns_deploy=self.timeout_ns_deploy) + if vdu_scaling_info.get("vdu-delete"): + self.scale_vnfr(db_vnfr, None, vdu_scaling_info["vdu-delete"], mark_delete=False) + + async def _RO_scale(self, logging_text, RO_nsr_id, RO_scaling_info, db_nslcmop, db_vnfr, db_nslcmop_update, + vdu_scaling_info): + nslcmop_id = db_nslcmop["_id"] + nsr_id = db_nslcmop["nsInstanceId"] + vdu_create = vdu_scaling_info.get("vdu-create") + vdu_delete = vdu_scaling_info.get("vdu-delete") + # Scale RO retry check: Check if this sub-operation has been executed before + op_index = self._check_or_add_scale_suboperation( + db_nslcmop, db_vnfr["member-vnf-index-ref"], None, None, 'SCALE-RO', RO_nsr_id, RO_scaling_info) + if op_index == self.SUBOPERATION_STATUS_SKIP: + # Skip sub-operation + result = 'COMPLETED' + result_detail = 'Done' + self.logger.debug(logging_text + "Skipped sub-operation RO, result {} {}".format(result, result_detail)) + else: + if op_index == self.SUBOPERATION_STATUS_NEW: + # New sub-operation: Get index of this sub-operation + op_index = len(db_nslcmop.get('_admin', {}).get('operations')) - 1 + self.logger.debug(logging_text + "New sub-operation RO") + else: + # retry: Get registered params for this existing sub-operation + op = db_nslcmop.get('_admin', {}).get('operations', [])[op_index] + RO_nsr_id = op.get('RO_nsr_id') + RO_scaling_info = op.get('RO_scaling_info') + self.logger.debug(logging_text + "Sub-operation RO retry") + + RO_desc = await self.RO.create_action("ns", RO_nsr_id, {"vdu-scaling": RO_scaling_info}) + # wait until ready + RO_nslcmop_id = RO_desc["instance_action_id"] + db_nslcmop_update["_admin.deploy.RO"] = RO_nslcmop_id + + RO_task_done = False + step = detailed_status = "Waiting for VIM to scale. RO_task_id={}.".format(RO_nslcmop_id) + detailed_status_old = None + self.logger.debug(logging_text + step) + + deployment_timeout = 1 * 3600 # One hour + while deployment_timeout > 0: + if not RO_task_done: + desc = await self.RO.show("ns", item_id_name=RO_nsr_id, extra_item="action", + extra_item_id=RO_nslcmop_id) + + # deploymentStatus + self._on_update_ro_db(nsrs_id=nsr_id, ro_descriptor=desc) + + ns_status, ns_status_info = self.RO.check_action_status(desc) + if ns_status == "ERROR": + raise ROclient.ROClientException(ns_status_info) + elif ns_status == "BUILD": + detailed_status = step + "; {}".format(ns_status_info) + elif ns_status == "ACTIVE": + RO_task_done = True + self.scale_vnfr(db_vnfr, vdu_create=vdu_create, vdu_delete=vdu_delete) + step = detailed_status = "Waiting ns ready at RO. RO_id={}".format(RO_nsr_id) + self.logger.debug(logging_text + step) + else: + assert False, "ROclient.check_action_status returns unknown {}".format(ns_status) + else: + desc = await self.RO.show("ns", RO_nsr_id) + ns_status, ns_status_info = self.RO.check_ns_status(desc) + # deploymentStatus + self._on_update_ro_db(nsrs_id=nsr_id, ro_descriptor=desc) + + if ns_status == "ERROR": + raise ROclient.ROClientException(ns_status_info) + elif ns_status == "BUILD": + detailed_status = step + "; {}".format(ns_status_info) + elif ns_status == "ACTIVE": + step = detailed_status = \ + "Waiting for management IP address reported by the VIM. Updating VNFRs" + try: + # nsr_deployed["nsr_ip"] = RO.get_ns_vnf_info(desc) + self.ns_update_vnfr({db_vnfr["member-vnf-index-ref"]: db_vnfr}, desc) + break + except LcmExceptionNoMgmtIP: + pass + else: + assert False, "ROclient.check_ns_status returns unknown {}".format(ns_status) + if detailed_status != detailed_status_old: + self._update_suboperation_status( + db_nslcmop, op_index, 'COMPLETED', detailed_status) + detailed_status_old = db_nslcmop_update["detailed-status"] = detailed_status + self.update_db_2("nslcmops", nslcmop_id, db_nslcmop_update) + + await asyncio.sleep(5, loop=self.loop) + deployment_timeout -= 5 + if deployment_timeout <= 0: + self._update_suboperation_status( + db_nslcmop, nslcmop_id, op_index, 'FAILED', "Timeout when waiting for ns to get ready") + raise ROclient.ROClientException("Timeout waiting ns to be ready") + + # update VDU_SCALING_INFO with the obtained ip_addresses + if vdu_scaling_info["scaling_direction"] == "OUT": + for vdur in reversed(db_vnfr["vdur"]): + if vdu_scaling_info["vdu-create"].get(vdur["vdu-id-ref"]): + vdu_scaling_info["vdu-create"][vdur["vdu-id-ref"]] -= 1 + vdu_scaling_info["vdu"].append({ + "name": vdur["name"] or vdur.get("vdu-name"), + "vdu_id": vdur["vdu-id-ref"], + "interface": [] + }) + for interface in vdur["interfaces"]: + vdu_scaling_info["vdu"][-1]["interface"].append({ + "name": interface["name"], + "ip_address": interface["ip-address"], + "mac_address": interface.get("mac-address"), + }) + self._update_suboperation_status(db_nslcmop, op_index, 'COMPLETED', 'Done') + async def add_prometheus_metrics(self, ee_id, artifact_path, ee_config_descriptor, vnfr_id, nsr_id, target_ip): if not self.prometheus: return diff --git a/osm_lcm/vim_sdn.py b/osm_lcm/vim_sdn.py index 7c774d2..a44aa9b 100644 --- a/osm_lcm/vim_sdn.py +++ b/osm_lcm/vim_sdn.py @@ -142,7 +142,6 @@ class VimLcm(LcmBase): operation_state = 'COMPLETED' operation_details = 'Done' - # await asyncio.sleep(15) # TODO remove. This is for test self.logger.debug(logging_text + "Exit Ok VIM account created at RO_vim_account_id={}".format(desc["uuid"])) return @@ -228,7 +227,7 @@ class VimLcm(LcmBase): vim_RO.pop("vim_password", None) if RO_sdn_id: vim_RO["config"]["sdn-controller"] = RO_sdn_id - # TODO make a deep update of sdn-port-mapping + # TODO make a deep update of sdn-port-mapping if vim_RO: await RO.edit("vim", RO_vim_id, descriptor=vim_RO) @@ -319,31 +318,31 @@ class VimLcm(LcmBase): try: # wait for any previous tasks in process await self.lcm_tasks.waitfor_related_HA('vim', 'delete', op_id) - - db_vim = self.db.get_one("vim_accounts", {"_id": vim_id}) - if db_vim.get("_admin") and db_vim["_admin"].get("deployed") and db_vim["_admin"]["deployed"].get("RO"): - RO_vim_id = db_vim["_admin"]["deployed"]["RO"] - RO = ROclient.ROClient(self.loop, **self.ro_config) - step = "Detaching vim from RO tenant" - try: - await RO.detach("vim_account", RO_vim_id) - except ROclient.ROClientException as e: - if e.http_code == 404: # not found - self.logger.debug(logging_text + "RO_vim_id={} already detached".format(RO_vim_id)) - else: - raise - - step = "Deleting vim from RO" - try: - await RO.delete("vim", RO_vim_id) - except ROclient.ROClientException as e: - if e.http_code == 404: # not found - self.logger.debug(logging_text + "RO_vim_id={} already deleted".format(RO_vim_id)) - else: - raise - else: - # nothing to delete - self.logger.error(logging_text + "Nothing to remove at RO") + if not self.ro_config.get("ng"): + db_vim = self.db.get_one("vim_accounts", {"_id": vim_id}) + if db_vim.get("_admin") and db_vim["_admin"].get("deployed") and db_vim["_admin"]["deployed"].get("RO"): + RO_vim_id = db_vim["_admin"]["deployed"]["RO"] + RO = ROclient.ROClient(self.loop, **self.ro_config) + step = "Detaching vim from RO tenant" + try: + await RO.detach("vim_account", RO_vim_id) + except ROclient.ROClientException as e: + if e.http_code == 404: # not found + self.logger.debug(logging_text + "RO_vim_id={} already detached".format(RO_vim_id)) + else: + raise + + step = "Deleting vim from RO" + try: + await RO.delete("vim", RO_vim_id) + except ROclient.ROClientException as e: + if e.http_code == 404: # not found + self.logger.debug(logging_text + "RO_vim_id={} already deleted".format(RO_vim_id)) + else: + raise + else: + # nothing to delete + self.logger.debug(logging_text + "Nothing to remove at RO") self.db.del_one("vim_accounts", {"_id": vim_id}) db_vim = None self.logger.debug(logging_text + "Exit Ok")