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))
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
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 = {
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",
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"):
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):
"""
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"],
"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")
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")):
# 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 = {
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)
"vnf": [],
"image": [],
"flavor": [],
+ "action_id": nslcmop_id
}
desc = await self.RO.deploy(nsr_id, target)
action_id = desc["action_id"]
# 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"
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):
: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
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:
# 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,
# '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:
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)
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
# 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"]
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": []
})
"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"
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:
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:
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