from osm_common.dbbase import DbException
from osm_common.fsbase import FsException
-from n2vc.vnf import N2VC, N2VCPrimitiveExecutionFailed, NetworkServiceDoesNotExist
+from n2vc.vnf import N2VC, N2VCPrimitiveExecutionFailed, NetworkServiceDoesNotExist, PrimitiveDoesNotExist
from copy import copy, deepcopy
from http import HTTPStatus
raise LcmException("ns_update_vnfr: Not found member_vnf_index={} at RO info".format(vnf_index))
async def instantiate(self, nsr_id, nslcmop_id):
+
+ # Try to lock HA task here
+ task_is_locked_by_me = self.lcm_tasks.lock_HA('ns', 'nslcmops', nslcmop_id)
+ if not task_is_locked_by_me:
+ return
+
logging_text = "Task ns={} instantiate={} ".format(nsr_id, nslcmop_id)
self.logger.debug(logging_text + "Enter")
# get all needed from database
n2vc_key_list = [] # list of public keys to be injected as authorized to VMs
exc = None
try:
+ # wait for any previous tasks in process
+ await self.lcm_tasks.waitfor_related_HA('ns', 'nslcmops', nslcmop_id)
+
step = "Getting nslcmop={} from db".format(nslcmop_id)
db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
step = "Getting nsr={} from db".format(nsr_id)
nsd = db_nsr["nsd"]
nsr_name = db_nsr["name"] # TODO short-name??
- # look if previous tasks in process
- task_name, task_dependency = self.lcm_tasks.lookfor_related("ns", nsr_id, nslcmop_id)
- if task_dependency:
- step = db_nslcmop_update["detailed-status"] = \
- "Waiting for related tasks to be completed: {}".format(task_name)
- self.logger.debug(logging_text + step)
- self.update_db_2("nslcmops", nslcmop_id, db_nslcmop_update)
- _, pending = await asyncio.wait(task_dependency, timeout=3600)
- if pending:
- raise LcmException("Timeout waiting related tasks to be completed")
-
step = "Getting vnfrs from db"
db_vnfrs_list = self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id})
db_vnfds_ref = {}
.format(vca_deployed["member-vnf-index"],
vca_deployed["vdu_id"])
self.logger.debug(logging_text + step)
- primitive_id = await self.n2vc.ExecutePrimitive(
- vca_deployed["model"],
- vca_deployed["application"],
- "get-ssh-public-key",
- None,
- )
- vca_deployed["step"] = db_nsr_update[database_entry + "step"] = "get-ssh-public-key"
- vca_deployed["primitive_id"] = db_nsr_update[database_entry + "primitive_id"] =\
- primitive_id
- db_nsr_update[database_entry + "operational-status"] =\
- vca_deployed["operational-status"]
+ try:
+ primitive_id = await self.n2vc.ExecutePrimitive(
+ vca_deployed["model"],
+ vca_deployed["application"],
+ "get-ssh-public-key",
+ None,
+ )
+ vca_deployed["step"] = db_nsr_update[database_entry + "step"] = "get-ssh-public-key"
+ vca_deployed["primitive_id"] = db_nsr_update[database_entry + "primitive_id"] =\
+ primitive_id
+ db_nsr_update[database_entry + "operational-status"] =\
+ vca_deployed["operational-status"]
+ except PrimitiveDoesNotExist:
+ ssh_public_key = None
+ vca_deployed["step"] = db_nsr_update[database_entry + "step"] =\
+ "ssh-public-key-obtained"
+ vca_deployed["ssh-public-key"] = db_nsr_update[database_entry + "ssh-public-key"] =\
+ ssh_public_key
+ step = "charm ssh-public-key for member_vnf_index={} vdu_id={} not needed".format(
+ vca_deployed["member-vnf-index"], vca_deployed["vdu_id"])
+ self.logger.debug(logging_text + step)
+
elif vca_deployed["step"] in ("get-ssh-public-key", "retry-get-ssh-public-key"):
primitive_id = vca_deployed["primitive_id"]
primitive_status = await self.n2vc.GetPrimitiveStatus(vca_deployed["model"],
for vdu_index, vdu in enumerate(get_iterable(vnfd, 'vdu')):
if vdu["id"] == vdu_id:
initial_config_primitive_list = vdu['vdu-configuration'].get(
- 'initial-config-primitive', ())
- break
+ 'initial-config-primitive', [])
+ break
else:
raise LcmException("Not found vdu_id={} at vnfd:vdu".format(vdu_id))
vdur = db_vnfrs[vnf_index]["vdur"][vdu_index]
add_params["rw_mgmt_ip"] = vdur["ip-address"]
else:
add_params["rw_mgmt_ip"] = db_vnfrs[vnf_index]["ip-address"]
- initial_config_primitive_list = vnfd["vnf-configuration"].get('initial-config-primitive', ())
+ initial_config_primitive_list = vnfd["vnf-configuration"].get('initial-config-primitive', [])
else:
if db_nsr.get("additionalParamsForNs"):
add_params = db_nsr["additionalParamsForNs"].copy()
if isinstance(v, str) and v.startswith("!!yaml "):
add_params[k] = yaml.safe_load(v[7:])
add_params["rw_mgmt_ip"] = None
+ initial_config_primitive_list = nsd["ns-configuration"].get('initial-config-primitive', [])
# add primitive verify-ssh-credentials to the list after config only when is a vnf or vdu charm
initial_config_primitive_list = initial_config_primitive_list.copy()
- if initial_config_primitive_list and vnf_index:
- initial_config_primitive_list.insert(1, {"name": "verify-ssh-credentials", "paramter": []})
+ if initial_config_primitive_list and vnf_index and vca_deployed.get("ssh-public-key"):
+ initial_config_primitive_list.insert(1, {"name": "verify-ssh-credentials", "parameter": []})
for initial_config_primitive in initial_config_primitive_list:
+ primitive_params_ = self._map_primitive_params(initial_config_primitive, {}, add_params)
+ self.logger.debug(logging_text + step + " primitive '{}' params '{}'"
+ .format(initial_config_primitive["name"], primitive_params_))
primitive_result, primitive_detail = await self._ns_execute_primitive(
db_nsr["_admin"]["deployed"], vnf_index, vdu_id, vdu_name, vdu_count_index,
initial_config_primitive["name"],
- self._map_primitive_params(initial_config_primitive, {}, add_params))
+ primitive_params_,
+ retries=10 if initial_config_primitive["name"] == "verify-ssh-credentials" else 0,
+ retries_interval=30)
if primitive_result != "COMPLETED":
- raise LcmException("charm error executing primitive {} for member_vnf_index={} vdu_id={}: '{}'"
+ raise LcmException("charm error executing primitive {} for member_vnf_index={} vdu_id={}: '{}'"
.format(initial_config_primitive["name"], vca_deployed["member-vnf-index"],
vca_deployed["vdu_id"], primitive_detail))
# waiting all charms are ok
configuration_failed = False
if number_to_configure:
+ step = "Waiting all charms are active"
old_status = "configuring: init: {}".format(number_to_configure)
db_nsr_update["config-status"] = old_status
db_nsr_update["detailed-status"] = old_status
else:
return False
- # Get a numerically sorted list of the sequences for this VNFD's terminate action
- def _get_terminate_config_primitive_seq_list(self, vnfd):
+ @staticmethod
+ def _get_terminate_config_primitive_seq_list(vnfd):
+ """ Get a numerically sorted list of the sequences for this VNFD's terminate action """
# No need to check for existing primitive twice, already done before
vnf_config = vnfd.get("vnf-configuration")
seq_list = vnf_config.get("terminate-config-primitive")
}
return nslcmop
- # Create a primitive with params from VNFD
- # - Called from terminate() before deleting instance
- # - Calls action() to execute the primitive
+ def _get_terminate_primitive_params(self, seq, vnf_index):
+ primitive = seq.get('name')
+ primitive_params = {}
+ params = {
+ "member_vnf_index": vnf_index,
+ "primitive": primitive,
+ "primitive_params": primitive_params,
+ }
+ desc_params = {}
+ return self._map_primitive_params(seq, params, desc_params)
+
+ def _add_suboperation(self, db_nslcmop, nslcmop_id, vnf_index, vdu_id, vdu_count_index,
+ vdu_name, primitive, mapped_primitive_params):
+ # Create the "_admin.operations" array, or append operation if array already exists
+ key_admin = '_admin'
+ key_operations = 'operations'
+ db_nslcmop_update = {}
+ db_nslcmop_admin = db_nslcmop.get(key_admin, {})
+ op_list = db_nslcmop_admin.get(key_operations)
+ new_op = {'member_vnf_index': vnf_index,
+ 'vdu_id': vdu_id,
+ 'vdu_count_index': vdu_count_index,
+ 'primitive': primitive,
+ 'primitive_params': mapped_primitive_params}
+ if db_nslcmop_admin:
+ if not op_list:
+ # First operation, create key 'operations' with current operation as first list element
+ db_nslcmop_admin.update({key_operations: [new_op]})
+ op_list = db_nslcmop_admin.get(key_operations)
+ else:
+ # Not first operation, append operation to existing list
+ op_list.append(new_op)
+
+ db_nslcmop_update['_admin.operations'] = op_list
+ self.update_db_2("nslcmops", nslcmop_id, db_nslcmop_update)
+
async def _terminate_action(self, db_nslcmop, nslcmop_id, nsr_id):
+ """ Create a primitive with params from VNFD
+ Called from terminate() before deleting instance
+ Calls action() to execute the primitive """
logging_text = "Task ns={} _terminate_action={} ".format(nsr_id, nslcmop_id)
- db_vnfds = {}
db_vnfrs_list = self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id})
+ db_vnfds = {}
# Loop over VNFRs
for vnfr in db_vnfrs_list:
vnfd_id = vnfr["vnfd-id"]
# Get the primitive's sorted sequence list
seq_list = self._get_terminate_config_primitive_seq_list(vnfd)
for seq in seq_list:
- # For each sequence in list, call terminate action
+ # For each sequence in list, get primitive and call _ns_execute_primitive()
step = "Calling terminate action for vnf_member_index={} primitive={}".format(
vnf_index, seq.get("name"))
self.logger.debug(logging_text + step)
- # Create the primitive for each sequence
- operation = "action"
- # primitive, i.e. "primitive": "touch"
+ # Create the primitive for each sequence, i.e. "primitive": "touch"
primitive = seq.get('name')
- primitive_params = {}
- params = {
- "member_vnf_index": vnf_index,
- "primitive": primitive,
- "primitive_params": primitive_params,
- }
- nslcmop_primitive = self._create_nslcmop(nsr_id, operation, params)
- # Get a copy of db_nslcmop 'admin' part
- db_nslcmop_action = {"_admin": deepcopy(db_nslcmop["_admin"])}
- # Update db_nslcmop with the primitive data
- db_nslcmop_action.update(nslcmop_primitive)
- # Create a new db entry for the created primitive, returns the new ID.
- # (The ID is normally obtained from Kafka.)
- nslcmop_terminate_action_id = self.db.create(
- "nslcmops", db_nslcmop_action)
- # Execute the primitive
- nslcmop_operation_state, nslcmop_operation_state_detail = await self.action(
- nsr_id, nslcmop_terminate_action_id)
+ mapped_primitive_params = self._get_terminate_primitive_params(seq, vnf_index)
+ # The following 3 parameters are currently set to None for 'terminate':
+ # vdu_id, vdu_count_index, vdu_name
+ vdu_id = db_nslcmop["operationParams"].get("vdu_id")
+ vdu_count_index = db_nslcmop["operationParams"].get("vdu_count_index")
+ vdu_name = db_nslcmop["operationParams"].get("vdu_name")
+ # Add suboperation
+ self._add_suboperation(db_nslcmop,
+ nslcmop_id,
+ vnf_index,
+ vdu_id,
+ vdu_count_index,
+ vdu_name,
+ primitive,
+ mapped_primitive_params)
+ # Suboperations: Call _ns_execute_primitive() instead of action()
+ db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
+ nsr_deployed = db_nsr["_admin"]["deployed"]
+ result, result_detail = await self._ns_execute_primitive(
+ nsr_deployed, vnf_index, vdu_id, vdu_name, vdu_count_index, primitive,
+ mapped_primitive_params)
+
+ # nslcmop_operation_state, nslcmop_operation_state_detail = await self.action(
+ # nsr_id, nslcmop_terminate_action_id)
# Launch Exception if action() returns other than ['COMPLETED', 'PARTIALLY_COMPLETED']
- nslcmop_operation_states_ok = ['COMPLETED', 'PARTIALLY_COMPLETED']
- if nslcmop_operation_state not in nslcmop_operation_states_ok:
+ result_ok = ['COMPLETED', 'PARTIALLY_COMPLETED']
+ if result not in result_ok:
raise LcmException(
"terminate_primitive_action for vnf_member_index={}",
" primitive={} fails with error {}".format(
- vnf_index, seq.get("name"), nslcmop_operation_state_detail))
+ vnf_index, seq.get("name"), result_detail))
async def terminate(self, nsr_id, nslcmop_id):
+
+ # Try to lock HA task here
+ task_is_locked_by_me = self.lcm_tasks.lock_HA('ns', 'nslcmops', nslcmop_id)
+ if not task_is_locked_by_me:
+ return
+
logging_text = "Task ns={} terminate={} ".format(nsr_id, nslcmop_id)
self.logger.debug(logging_text + "Enter")
db_nsr = None
nslcmop_operation_state = None
autoremove = False # autoremove after terminated
try:
+ # wait for any previous tasks in process
+ await self.lcm_tasks.waitfor_related_HA("ns", 'nslcmops', nslcmop_id)
+
step = "Getting nslcmop={} from db".format(nslcmop_id)
db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
step = "Getting nsr={} from db".format(nsr_id)
return calculated_params
async def _ns_execute_primitive(self, db_deployed, member_vnf_index, vdu_id, vdu_name, vdu_count_index,
- primitive, primitive_params):
+ primitive, primitive_params, retries=0, retries_interval=30):
start_primitive_time = time()
try:
for vca_deployed in db_deployed["VCA"]:
await self.n2vc.login()
if primitive == "config":
primitive_params = {"params": primitive_params}
- primitive_id = await self.n2vc.ExecutePrimitive(
- model_name,
- application_name,
- primitive,
- callback,
- *callback_args,
- **primitive_params
- )
- while time() - start_primitive_time < self.timeout_primitive:
- primitive_result_ = await self.n2vc.GetPrimitiveStatus(model_name, primitive_id)
- if primitive_result_ in ("completed", "failed"):
- primitive_result = "COMPLETED" if primitive_result_ == "completed" else "FAILED"
- detailed_result = await self.n2vc.GetPrimitiveOutput(model_name, primitive_id)
- break
- elif primitive_result_ is None and primitive == "config":
- primitive_result = "COMPLETED"
- detailed_result = None
+ while retries >= 0:
+ primitive_id = await self.n2vc.ExecutePrimitive(
+ model_name,
+ application_name,
+ primitive,
+ callback,
+ *callback_args,
+ **primitive_params
+ )
+ while time() - start_primitive_time < self.timeout_primitive:
+ primitive_result_ = await self.n2vc.GetPrimitiveStatus(model_name, primitive_id)
+ if primitive_result_ in ("completed", "failed"):
+ primitive_result = "COMPLETED" if primitive_result_ == "completed" else "FAILED"
+ detailed_result = await self.n2vc.GetPrimitiveOutput(model_name, primitive_id)
+ break
+ elif primitive_result_ is None and primitive == "config":
+ primitive_result = "COMPLETED"
+ detailed_result = None
+ break
+ else: # ("running", "pending", None):
+ pass
+ await asyncio.sleep(5)
+ else:
+ raise LcmException("timeout after {} seconds".format(self.timeout_primitive))
+ if primitive_result == "COMPLETED":
break
- else: # ("running", "pending", None):
- pass
- await asyncio.sleep(5)
- else:
- raise LcmException("timeout after {} seconds".format(self.timeout_primitive))
+ retries -= 1
+ if retries >= 0:
+ await asyncio.sleep(retries_interval)
+
return primitive_result, detailed_result
except (N2VCPrimitiveExecutionFailed, LcmException) as e:
return "FAILED", str(e)
async def action(self, nsr_id, nslcmop_id):
+
+ # Try to lock HA task here
+ task_is_locked_by_me = self.lcm_tasks.lock_HA('ns', 'nslcmops', nslcmop_id)
+ if not task_is_locked_by_me:
+ return
+
logging_text = "Task ns={} action={} ".format(nsr_id, nslcmop_id)
self.logger.debug(logging_text + "Enter")
# get all needed from database
nslcmop_operation_state_detail = None
exc = None
try:
+ # wait for any previous tasks in process
+ await self.lcm_tasks.waitfor_related_HA('ns', 'nslcmops', nslcmop_id)
+
step = "Getting information from database"
db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
step = "Getting nsd from database"
db_nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
- # look if previous tasks in process
- task_name, task_dependency = self.lcm_tasks.lookfor_related("ns", nsr_id, nslcmop_id)
- if task_dependency:
- step = db_nslcmop_update["detailed-status"] = \
- "Waiting for related tasks to be completed: {}".format(task_name)
- self.logger.debug(logging_text + step)
- self.update_db_2("nslcmops", nslcmop_id, db_nslcmop_update)
- _, pending = await asyncio.wait(task_dependency, timeout=3600)
- if pending:
- raise LcmException("Timeout waiting related tasks to be completed")
-
# for backward compatibility
if nsr_deployed and isinstance(nsr_deployed.get("VCA"), dict):
nsr_deployed["VCA"] = list(nsr_deployed["VCA"].values())
return nslcmop_operation_state, nslcmop_operation_state_detail
async def scale(self, nsr_id, nslcmop_id):
+
+ # Try to lock HA task here
+ task_is_locked_by_me = self.lcm_tasks.lock_HA('ns', 'nslcmops', nslcmop_id)
+ if not task_is_locked_by_me:
+ return
+
logging_text = "Task ns={} scale={} ".format(nsr_id, nslcmop_id)
self.logger.debug(logging_text + "Enter")
# get all needed from database
old_config_status = ""
vnfr_scaled = False
try:
- # look if previous tasks in process
- task_name, task_dependency = self.lcm_tasks.lookfor_related("ns", nsr_id, nslcmop_id)
- if task_dependency:
- step = db_nslcmop_update["detailed-status"] = \
- "Waiting for related tasks to be completed: {}".format(task_name)
- self.logger.debug(logging_text + step)
- self.update_db_2("nslcmops", nslcmop_id, db_nslcmop_update)
- _, pending = await asyncio.wait(task_dependency, timeout=3600)
- if pending:
- raise LcmException("Timeout waiting related tasks to be completed")
+ # wait for any previous tasks in process
+ await self.lcm_tasks.waitfor_related_HA('ns', 'nslcmops', nslcmop_id)
step = "Getting nslcmop from database"
self.logger.debug(step + " after having waited for previous tasks to be completed")
raise LcmException("reached the limit of {} (max-instance-count) "
"scaling-out operations for the "
"scaling-group-descriptor '{}'".format(nb_scale_op, scaling_group))
-
+
nb_scale_op += 1
vdu_scaling_info["scaling_direction"] = "OUT"
vdu_scaling_info["vdu-create"] = {}