except asyncio.TimeoutError:
raise NgRoException("Timeout", http_code=504)
+ async def operate(self, nsr_id, target, operation_type):
+ """
+ Performs start/stop/rebuil of VNFs
+ :param nsr_id: NS Instance Id
+ :param target: payload data for migrate operation
+ :param operation_type: start/stop/rebuil of VNFs
+ :return: dictionary with the information or raises NgRoException on Error
+ """
+ try:
+ if isinstance(target, str):
+ target = self._parse_yaml(target)
+ payload_req = yaml.safe_dump(target)
+
+ url = "{}/ns/v1/{operation_type}/{nsr_id}".format(
+ self.endpoint_url, operation_type=operation_type, nsr_id=nsr_id
+ )
+ async with aiohttp.ClientSession(loop=self.loop) as session:
+ self.logger.debug("NG-RO POST %s %s", url, payload_req)
+ # timeout = aiohttp.ClientTimeout(total=self.timeout_large)
+ async with session.post(
+ url, headers=self.headers_req, data=payload_req
+ ) as response:
+ response_text = await response.read()
+ self.logger.debug(
+ "POST {} [{}] {}".format(
+ url, response.status, response_text[:100]
+ )
+ )
+ if response.status >= 300:
+ raise NgRoException(response_text, http_code=response.status)
+ return self._parse_yaml(response_text, response=True)
+ except (aiohttp.ClientOSError, aiohttp.ClientError) as e:
+ raise NgRoException(e, http_code=504)
+ except asyncio.TimeoutError:
+ raise NgRoException("Timeout", http_code=504)
+
async def status(self, nsr_id, action_id):
try:
url = "{}/ns/v1/deploy/{nsr_id}/{action_id}".format(
10 * 60
) # timeout for some progress in a primitive execution
timeout_migrate = 1800 # default global timeout for migrating vnfs
-
+ timeout_operate = 1800 # default global timeout for migrating vnfs
SUBOPERATION_STATUS_NOT_FOUND = -1
SUBOPERATION_STATUS_NEW = -2
SUBOPERATION_STATUS_SKIP = -3
)
)
+ elif update_type == "OPERATE_VNF":
+ vnf_id = db_nslcmop["operationParams"]["operateVnfData"]["vnfInstanceId"]
+ operation_type = db_nslcmop["operationParams"]["operateVnfData"]["changeStateTo"]
+ additional_param = db_nslcmop["operationParams"]["operateVnfData"]["additionalParam"]
+ (result, detailed_status) = await self.rebuild_start_stop(
+ nsr_id, nslcmop_id, vnf_id, additional_param, operation_type
+ )
+ if result == "FAILED":
+ nslcmop_operation_state = result
+ error_description_nslcmop = detailed_status
+ db_nslcmop_update["detailed-status"] = detailed_status
+ if not nslcmop_operation_state:
+ nslcmop_operation_state = "COMPLETED"
+ self.logger.debug(
+ logging_text
+ + " task Done with result {} {}".format(
+ nslcmop_operation_state, detailed_status
+ )
+ )
+
# If nslcmop_operation_state is None, so any operation is not failed.
# All operations are executed in overall.
if not nslcmop_operation_state:
job["vnfr_id"] = vnfr_id
return job_list
+ async def rebuild_start_stop(self, nsr_id, nslcmop_id, vnf_id, additional_param, operation_type):
+ logging_text = "Task ns={} {}={} ".format(nsr_id, operation_type, nslcmop_id)
+ self.logger.info(logging_text + "Enter")
+ stage = ["Preparing the environment", ""]
+ # database nsrs record
+ db_nsr_update = {}
+ vdu_vim_name = None
+ vim_vm_id = None
+ # in case of error, indicates what part of scale was failed to put nsr at error status
+ start_deploy = time()
+ try:
+ db_vnfr = self.db.get_one("vnfrs", {"_id": vnf_id})
+ vim_account_id = db_vnfr.get("vim-account-id")
+ vim_info_key = "vim:" + vim_account_id
+ vdur = find_in_list(
+ db_vnfr["vdur"], lambda vdu: vdu["count-index"] == additional_param["count-index"]
+ )
+ if vdur:
+ vdu_vim_name = vdur["name"]
+ vim_vm_id = vdur["vim_info"][vim_info_key]["vim_id"]
+ target_vim, _ = next(k_v for k_v in vdur["vim_info"].items())
+ self.logger.info("vdu_vim_name >> {} ".format(vdu_vim_name))
+ # wait for any previous tasks in process
+ stage[1] = "Waiting for previous operations to terminate"
+ self.logger.info(stage[1])
+ await self.lcm_tasks.waitfor_related_HA('ns', 'nslcmops', nslcmop_id)
+
+ stage[1] = "Reading from database."
+ self.logger.info(stage[1])
+ self._write_ns_status(
+ nsr_id=nsr_id,
+ ns_state=None,
+ current_operation=operation_type.upper(),
+ current_operation_id=nslcmop_id
+ )
+ self._write_op_status(op_id=nslcmop_id, stage=stage, queuePosition=0)
+
+ # read from db: ns
+ stage[1] = "Getting nsr={} from db.".format(nsr_id)
+ db_nsr_update["operational-status"] = operation_type
+ self.update_db_2("nsrs", nsr_id, db_nsr_update)
+ # Payload for RO
+ desc = {
+ operation_type: {
+ "vim_vm_id": vim_vm_id,
+ "vnf_id": vnf_id,
+ "vdu_index": additional_param["count-index"],
+ "vdu_id": vdur["id"],
+ "target_vim": target_vim,
+ "vim_account_id": vim_account_id
+ }
+ }
+ stage[1] = "Sending rebuild request to RO... {}".format(desc)
+ self._write_op_status(op_id=nslcmop_id, stage=stage, queuePosition=0)
+ self.logger.info("ro nsr id: {}".format(nsr_id))
+ result_dict = await self.RO.operate(nsr_id, desc, operation_type)
+ self.logger.info("response from RO: {}".format(result_dict))
+ action_id = result_dict["action_id"]
+ await self._wait_ng_ro(
+ nsr_id, action_id, nslcmop_id, start_deploy, self.timeout_operate
+ )
+ return "COMPLETED", "Done"
+ except (ROclient.ROClientException, DbException, LcmException) as e:
+ self.logger.error("Exit Exception {}".format(e))
+ exc = e
+ except asyncio.CancelledError:
+ self.logger.error("Cancelled Exception while '{}'".format(stage))
+ exc = "Operation was cancelled"
+ except Exception as e:
+ exc = traceback.format_exc()
+ self.logger.critical("Exit Exception {} {}".format(type(e).__name__, e), exc_info=True)
+ return "FAILED", "Error in operate VNF {}".format(exc)
+
def get_vca_cloud_and_credentials(self, vim_account_id: str) -> (str, str):
"""
Get VCA Cloud and VCA Cloud Credentials for the VIM account
operationState: FAILED
startTime: 1566823354.414689
statusEnteredTime: 1566824534.5112448
+
+- _id: 1bd4b60a-e15d-49e5-b75e-2b3224f15dda
+ id: 1bd4b60a-e15d-49e5-b75e-2b3224f15dda
+ operationState: COMPLETED
+ queuePosition: 0
+ stage: ''
+ errorMessage: ''
+ detailedStatus:
+ statusEnteredTime: 1652349205.9499352
+ nsInstanceId: 52f0b3ac-1574-481f-a48f-528fc02912f7
+ lcmOperationType: update
+ startTime: 1652349205.7415159
+ isAutomaticInvocation: false
+ operationParams:
+ updateType: OPERATE_VNF
+ operateVnfData:
+ vnfInstanceId: a6df8aa0-1271-4dfc-85a5-e0484fea303f
+ changeStateTo: start
+ additionalParam:
+ run-day1: false
+ vdu-id: mgmtVM
+ count-index: 0
+ lcmOperationType: update
+ nsInstanceId: 52f0b3ac-1574-481f-a48f-528fc02912f7
+ isCancelPending: false
+ links:
+ self: "/osm/nslcm/v1/ns_lcm_op_occs/1bd4b60a-e15d-49e5-b75e-2b3224f15dda"
+ nsInstance: "/osm/nslcm/v1/ns_instances/52f0b3ac-1574-481f-a48f-528fc02912f7"
+ _admin:
+ created: 1652349205.7415788
+ modified: 1652349205.9499364
+ projects_read:
+ - e38990e1-6724-4292-ab6f-2ecc109f9af4
+ projects_write:
+ - e38990e1-6724-4292-ab6f-2ecc109f9af4
+ worker: fbf6b5aa99e2
+ detailed-status: Done
+
+- _id: 6eace44b-2ef4-4de5-b15f-63f2e8898bfb
+ id: 6eace44b-2ef4-4de5-b15f-63f2e8898bfb
+ operationState: Error
+ queuePosition: 0
+ stage: ''
+ errorMessage: ''
+ detailedStatus:
+ statusEnteredTime: 1652349205.9499352
+ nsInstanceId: 52f0b3ac-1574-481f-a48f-528fc02912f7
+ lcmOperationType: update
+ startTime: 1652349205.7415159
+ isAutomaticInvocation: false
+ operationParams:
+ updateType: OPERATE_VNF
+ operateVnfData:
+ vnfInstanceId: a6df8aa0-1271-4dfc-85a5-e0484fea303f
+ changeStateTo: stop
+ additionalParam:
+ run-day1: false
+ vdu-id: mgmtVM
+ count-index: 0
+ lcmOperationType: update
+ nsInstanceId: 52f0b3ac-1574-481f-a48f-528fc02912f7
+ isCancelPending: false
+ links:
+ self: "/osm/nslcm/v1/ns_lcm_op_occs/1bd4b60a-e15d-49e5-b75e-2b3224f15dda"
+ nsInstance: "/osm/nslcm/v1/ns_instances/52f0b3ac-1574-481f-a48f-528fc02912f7"
+ _admin:
+ created: 1652349205.7415788
+ modified: 1652349205.9499364
+ projects_read:
+ - e38990e1-6724-4292-ab6f-2ecc109f9af4
+ projects_write:
+ - e38990e1-6724-4292-ab6f-2ecc109f9af4
+ worker: fbf6b5aa99e2
+ detailed-status: Done
+
"""
db_nsrs_text = """
vim-account-id: 74337dcb-ef54-41e7-bd2d-8c0d7fcd326f
vnfd-id: d96b1cdf-5ad6-49f7-bf65-907ada989293
vnfd-ref: native-kdu_knf
+
+- _id: a6df8aa0-1271-4dfc-85a5-e0484fea303f
+ id: a6df8aa0-1271-4dfc-85a5-e0484fea303f
+ nsr-id-ref: 52f0b3ac-1574-481f-a48f-528fc02912f7
+ member-vnf-index-ref: '1'
+ additionalParamsForVnf:
+ created-time: 1652105830.965044
+ vnfd-ref: ha_proxy_charm-vnf
+ vnfd-id: 8b42078a-9d42-4def-8b5d-7dd0f041d078
+ vim-account-id: dff4014e-bb5e-441a-a28d-6dd5d86c7175
+ vca-id:
+ vdur:
+ - _id: 392e010d-3a39-4516-acc0-76993c19691f
+ alt-image-ids:
+ - '1'
+ - '2'
+ - '3'
+ cloud-init: 8b42078a-9d42-4def-8b5d-7dd0f041d078:file:cloud-config.txt
+ count-index: 0
+ id: 392e010d-3a39-4516-acc0-76993c19691f
+ internal-connection-point:
+ - connection-point-id: mgmtVM-eth0-int
+ id: mgmtVM-eth0-int
+ name: mgmtVM-eth0-int
+ - connection-point-id: dataVM-xe0-int
+ id: dataVM-xe0-int
+ name: dataVM-xe0-int
+ ip-address: 10.45.28.134
+ ns-flavor-id: '0'
+ ns-image-id: '0'
+ ssh-access-required: true
+ vdu-id-ref: mgmtVM
+ vdu-name: mgmtVM
+ vim_info:
+ vim:05357241-1a01-416f-9e02-af20f65f51cd:
+ vim_id: 1f8c18e3-b3aa-484c-a211-e88d6654f24a
+ vim_status: ACTIVE
+ vim_name: test_ns_ch-1-mgmtVM-0
+ status: ACTIVE
+ vim-id: 1f8c18e3-b3aa-484c-a211-e88d6654f24a
+ name: test_ns_ch-1-mgmtVM-0
+ vim_details:
+ vim_id: 1f8c18e3-b3aa-484c-a211-e88d6654f24a
+ vim_status: DONE
+ vim_message:
+ ip-address: 10.45.28.134
+ _admin:
+ created: 1652105830.9652078
+ modified: 1652105830.9652078
+ projects_read:
+ - e38990e1-6724-4292-ab6f-2ecc109f9af4
+ projects_write:
+ - e38990e1-6724-4292-ab6f-2ecc109f9af4
+ nsState: INSTANTIATED
+ vdu:
+ status: DONE
+ vim-id: 1f8c18e3-b3aa-484c-a211-e88d6654f24a
"""
db_nslcmops_scale_text = """
"vnf": "88d90b0c-faff-4b9f-bccd-017f33985984",
"removeVnf": "a639fac7-e0bb-4225-8ecb-c1f8efcc125f",
},
+ "TEST-OP-VNF": {
+ "ns": "f48163a6-c807-47bc-9682-f72caef5af85",
+ "nslcmops": "1bd4b60a-e15d-49e5-b75e-2b3224f15dda",
+ "nslcmops1": "6eace44b-2ef4-4de5-b15f-63f2e8898bfb",
+ "vnfrs": "a6df8aa0-1271-4dfc-85a5-e0484fea303f",
+ },
}
# await self.test_instantiate()
# # this will check that the initial-congig-primitive 'not_to_be_called' is not called
+ @asynctest.fail_on(active_handles=True)
+ async def test_start_stop_rebuild_pass(self):
+ nsr_id = descriptors.test_ids["TEST-OP-VNF"]["ns"]
+ nslcmop_id = descriptors.test_ids["TEST-OP-VNF"]["nslcmops"]
+ vnf_id = descriptors.test_ids["TEST-OP-VNF"]["vnfrs"]
+ additional_param = {"count-index": "0"}
+ operation_type = "start"
+ await self.my_ns.rebuild_start_stop(
+ nsr_id, nslcmop_id, vnf_id, additional_param, operation_type
+ )
+ expected_value = "COMPLETED"
+ return_value = self.db.get_one("nslcmops", {"_id": nslcmop_id}).get(
+ "operationState"
+ )
+ self.assertEqual(return_value, expected_value)
+
+ @asynctest.fail_on(active_handles=True)
+ async def test_start_stop_rebuild_fail(self):
+ nsr_id = descriptors.test_ids["TEST-OP-VNF"]["ns"]
+ nslcmop_id = descriptors.test_ids["TEST-OP-VNF"]["nslcmops1"]
+ vnf_id = descriptors.test_ids["TEST-OP-VNF"]["vnfrs"]
+ additional_param = {"count-index": "0"}
+ operation_type = "stop"
+ await self.my_ns.rebuild_start_stop(
+ nsr_id, nslcmop_id, vnf_id, additional_param, operation_type
+ )
+ expected_value = "Error"
+ return_value = self.db.get_one("nslcmops", {"_id": nslcmop_id}).get(
+ "operationState"
+ )
+ self.assertEqual(return_value, expected_value)
+
# Test scale() and related methods
@asynctest.fail_on(active_handles=True) # all async tasks must be completed
async def test_scale(self):