task = asyncio.ensure_future(self.ns.migrate(nsr_id, nslcmop_id))
self.lcm_tasks.register("ns", nsr_id, nslcmop_id, "ns_migrate", task)
return
+ elif command == "verticalscale":
+ nslcmop = params
+ nslcmop_id = nslcmop["_id"]
+ nsr_id = nslcmop["nsInstanceId"]
+ task = asyncio.ensure_future(self.ns.vertical_scale(nsr_id, nslcmop_id))
+ self.logger.debug("nsr_id,nslcmop_id,task {},{},{}".format(nsr_id, nslcmop_id, task))
+ self.lcm_tasks.register("ns", nsr_id, nslcmop_id, "ns_verticalscale", task)
+ self.logger.debug("LCM task registered {},{},{} ".format(nsr_id, nslcmop_id, task))
+ return
elif command == "show":
nsr_id = params
try:
"actioned",
"updated",
"migrated",
+ "verticalscaled",
): # "scaled-cooldown-time"
return
except asyncio.TimeoutError:
raise NgRoException("Timeout", http_code=504)
+ async def vertical_scale(self, nsr_id, target):
+ """
+ Performs migration of VNFs
+ :param nsr_id: NS Instance Id
+ :param target: payload data for migrate operation
+ :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/verticalscale/{nsr_id}".format(self.endpoint_url, nsr_id=nsr_id)
+ async with aiohttp.ClientSession(loop=self.loop) as session:
+ self.logger.debug("NG-RO POST %s %s", url, payload_req)
+ 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)
+
@staticmethod
def _parse_yaml(descriptor, response=False):
try:
) # 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
+ timeout_verticalscale = 1800 # default global timeout for Vertical Sclaing
SUBOPERATION_STATUS_NOT_FOUND = -1
SUBOPERATION_STATUS_NEW = -2
SUBOPERATION_STATUS_SKIP = -3
await asyncio.sleep(15, loop=self.loop)
else: # timeout_ns_deploy
raise NgRoException("Timeout waiting ns to deploy")
+
+ async def vertical_scale(self, nsr_id, nslcmop_id):
+ """
+ Vertical Scale the VDUs in a NS
+
+ :param: nsr_id: NS Instance ID
+ :param: nslcmop_id: nslcmop ID of migrate
+
+ """
+ # 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={} vertical scale ".format(nsr_id)
+ self.logger.debug(logging_text + "Enter")
+ # get all needed from database
+ db_nslcmop = None
+ db_nslcmop_update = {}
+ nslcmop_operation_state = None
+ db_nsr_update = {}
+ target = {}
+ exc = None
+ # in case of error, indicates what part of scale was failed to put nsr at error status
+ start_deploy = time()
+
+ try:
+ # wait for any previous tasks in process
+ step = "Waiting for previous operations to terminate"
+ await self.lcm_tasks.waitfor_related_HA('ns', 'nslcmops', nslcmop_id)
+
+ self._write_ns_status(
+ nsr_id=nsr_id,
+ ns_state=None,
+ current_operation="VerticalScale",
+ current_operation_id=nslcmop_id
+ )
+ step = "Getting nslcmop from database"
+ self.logger.debug(step + " after having waited for previous tasks to be completed")
+ db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
+ operationParams = db_nslcmop.get("operationParams")
+ target = {}
+ target.update(operationParams)
+ desc = await self.RO.vertical_scale(nsr_id, target)
+ self.logger.debug("RO return > {}".format(desc))
+ action_id = desc["action_id"]
+ await self._wait_ng_ro(
+ nsr_id, action_id, nslcmop_id, start_deploy, self.timeout_verticalscale
+ )
+ 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(step))
+ 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)
+ finally:
+ self._write_ns_status(
+ nsr_id=nsr_id,
+ ns_state=None,
+ current_operation="IDLE",
+ current_operation_id=None,
+ )
+ if exc:
+ db_nslcmop_update[
+ "detailed-status"
+ ] = "FAILED {}: {}".format(step, exc)
+ nslcmop_operation_state = "FAILED"
+ else:
+ nslcmop_operation_state = "COMPLETED"
+ db_nslcmop_update["detailed-status"] = "Done"
+ db_nsr_update["detailed-status"] = "Done"
+
+ self._write_op_status(
+ op_id=nslcmop_id,
+ stage="",
+ error_message="",
+ operation_state=nslcmop_operation_state,
+ other_update=db_nslcmop_update,
+ )
+ if nslcmop_operation_state:
+ try:
+ msg = {
+ "nsr_id": nsr_id,
+ "nslcmop_id": nslcmop_id,
+ "operationState": nslcmop_operation_state,
+ }
+ await self.msg.aiowrite("ns", "verticalscaled", msg, loop=self.loop)
+ except Exception as e:
+ self.logger.error(
+ logging_text + "kafka_write notification Exception {}".format(e)
+ )
+ self.logger.debug(logging_text + "Exit")
+ self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_verticalscale")
worker: fbf6b5aa99e2
detailed-status: Done
+- _admin:
+ created: 1566823354.4148262
+ modified: 1566823354.4148262
+ projects_read:
+ - 25b5aebf-3da1-49ed-99de-1d2b4a86d6e4
+ projects_write:
+ - 25b5aebf-3da1-49ed-99de-1d2b4a86d6e4
+ worker: 86434c2948e2
+ _id: 8b838aa8-53a3-4955-80bd-fbba6a7957ed
+ detailed-status: 'FAILED executing proxy charm initial primitives for member_vnf_index=1
+ vdu_id=None: charm error executing primitive verify-ssh-credentials for member_vnf_index=1
+ vdu_id=None: ''timeout after 600 seconds'''
+ id: 8b838aa8-53a3-4955-80bd-fbba6a7957ed
+ isAutomaticInvocation: false
+ isCancelPending: false
+ lcmOperationType: scale
+ links:
+ nsInstance: /osm/nslcm/v1/ns_instances/f48163a6-c807-47bc-9682-f72caef5af85
+ self: /osm/nslcm/v1/ns_lcm_op_occs/8b838aa8-53a3-4955-80bd-fbba6a7957ed
+ nsInstanceId: f48163a6-c807-47bc-9682-f72caef5af85
+ operationParams:
+ additionalParamsForVnf:
+ - additionalParams:
+ touch_filename: /home/ubuntu/first-touch-1
+ touch_filename2: /home/ubuntu/second-touch-1
+ member-vnf-index: '1'
+ lcmOperationType: instantiate
+ nsDescription: default description
+ nsInstanceId: f48163a6-c807-47bc-9682-f72caef5af85
+ nsName: ALF
+ nsdId: 8c2f8b95-bb1b-47ee-8001-36dc090678da
+ vimAccountId: ea958ba5-4e58-4405-bf42-6e3be15d4c3a
+ operationState: FAILED
+ startTime: 1566823354.414689
+ statusEnteredTime: 1566824534.5112448
+
+- _admin:
+ created: 1566823354.4148262
+ modified: 1566823354.4148262
+ projects_read:
+ - 25b5aebf-3da1-49ed-99de-1d2b4a86d6e4
+ projects_write:
+ - 25b5aebf-3da1-49ed-99de-1d2b4a86d6e4
+ worker: 86434c2948e2
+ _id: a21af1d4-7f1a-4f7b-b666-222315113a62
+ detailed-status: 'FAILED executing proxy charm initial primitives for member_vnf_index=1
+ vdu_id=None: charm error executing primitive verify-ssh-credentials for member_vnf_index=1
+ vdu_id=None: ''timeout after 600 seconds'''
+ id: a21af1d4-7f1a-4f7b-b666-222315113a62
+ isAutomaticInvocation: false
+ isCancelPending: false
+ lcmOperationType: scale
+ links:
+ nsInstance: /osm/nslcm/v1/ns_instances/f48163a6-c807-47bc-9682-f72caef5af85
+ self: /osm/nslcm/v1/ns_lcm_op_occs/a21af1d4-7f1a-4f7b-b666-222315113a62
+ nsInstanceId: f48163a6-c807-47bc-9682-f72caef5af85
+ operationParams:
+ additionalParamsForVnf:
+ - additionalParams:
+ touch_filename: /home/ubuntu/first-touch-1
+ touch_filename2: /home/ubuntu/second-touch-1
+ member-vnf-index: '1'
+ lcmOperationType: instantiate
+ nsDescription: default description
+ nsInstanceId: f48163a6-c807-47bc-9682-f72caef5af85
+ nsName: ALF
+ nsdId: 8c2f8b95-bb1b-47ee-8001-36dc090678da
+ vimAccountId: ea958ba5-4e58-4405-bf42-6e3be15d4c3a
+ operationState: COMPLETED
+ startTime: 1566823354.414689
+ statusEnteredTime: 1566824534.5112448
"""
db_nsrs_text = """
"nslcmops1": "6eace44b-2ef4-4de5-b15f-63f2e8898bfb",
"vnfrs": "a6df8aa0-1271-4dfc-85a5-e0484fea303f",
},
+ "TEST-V-SCALE": {
+ "ns": "f48163a6-c807-47bc-9682-f72caef5af85",
+ "instantiate-1": "8b838aa8-53a3-4955-80bd-fbba6a7957ed",
+ "instantiate": "a21af1d4-7f1a-4f7b-b666-222315113a62",
+ },
}
self.db.get_one("vnfrs", {"_id": vnf_instance_id})
self.assertTrue("database exception Not found entry with filter" in str(context.exception))
+ # test vertical scale executes sucessfully
+ # @patch("osm_lcm.ng_ro.status.response")
+ @asynctest.fail_on(active_handles=True)
+ async def test_vertical_scaling(self):
+ nsr_id = descriptors.test_ids["TEST-V-SCALE"]["ns"]
+ nslcmop_id = descriptors.test_ids["TEST-V-SCALE"]["instantiate"]
+
+ # calling the vertical scale fucntion
+ # self.my_ns.RO.status = asynctest.CoroutineMock(self.my_ns.RO.status, side_effect=self._ro_status("update"))
+ mock_wait_ng_ro = asynctest.CoroutineMock()
+ with patch("osm_lcm.ns.NsLcm._wait_ng_ro", mock_wait_ng_ro):
+ await self.my_ns.vertical_scale(nsr_id, nslcmop_id)
+ return_value = self.db.get_one("nslcmops", {"_id": nslcmop_id}).get(
+ "operationState"
+ )
+ expected_value = "COMPLETED"
+ self.assertEqual(return_value, expected_value)
+
+ # test vertical scale executes fail
+ @asynctest.fail_on(active_handles=True)
+ async def test_vertical_scaling_fail(self):
+ # get th nsr nad nslcmops id from descriptors
+ nsr_id = descriptors.test_ids["TEST-V-SCALE"]["ns"]
+ nslcmop_id = descriptors.test_ids["TEST-V-SCALE"]["instantiate-1"]
+
+ # calling the vertical scale fucntion
+ await self.my_ns.vertical_scale(nsr_id, nslcmop_id)
+ return_value = self.db.get_one("nslcmops", {"_id": nslcmop_id}).get(
+ "operationState"
+ )
+ expected_value = "FAILED"
+ self.assertEqual(return_value, expected_value)
+
# async def test_instantiate_pdu(self):
# nsr_id = descriptors.test_ids["TEST-A"]["ns"]
# nslcmop_id = descriptors.test_ids["TEST-A"]["instantiate"]