def initialize (self): """ .. seealso:: :func:`AbstractAPI.initialize() <escape.util.api.AbstractAPI.initialize>` """ log.debug("Initializing Controller Adaptation Sublayer...") self.controller_adapter = ControllerAdapter(self, with_infr=self._with_infr) if self._mapped_nffg: try: mapped_request = self._read_data_from_file(self._mapped_nffg) mapped_request = NFFG.parse(mapped_request) self.__proceed_installation(mapped_nffg=mapped_request) except (ValueError, IOError, TypeError) as e: log.error("Can't load service request from file because of: " + str(e)) else: log.debug("Graph representation is loaded successfully!") log.info("Controller Adaptation Sublayer has been initialized!")
class ControllerAdaptationAPI(AbstractAPI): """ Entry point for Controller Adaptation Sublayer (CAS). Maintain the contact with other UNIFY layers. Implement the Or - Ca reference point. """ # Define specific name for core object i.e. pox.core.<_core_name> _core_name = LAYER_NAME # Events raised by this class _eventMixin_events = {GlobalResInfoEvent, InstallationFinishedEvent, DeployNFFGEvent, InfoRequestFinishedEvent} # Dependencies # None def __init__ (self, standalone=False, **kwargs): """ .. seealso:: :func:`AbstractAPI.__init__() <escape.util.api.AbstractAPI.__init__>` """ log.info("Starting Controller Adaptation Sublayer...") # Set Infrastructure as a dependency if kwargs['with_infr']: log.debug("Set Infrastructure Layer as a dependency") self.dependencies = self.dependencies + (INFR_LAYER_NAME,) # Mandatory super() call self.controller_adapter = None super(ControllerAdaptationAPI, self).__init__(standalone, **kwargs) def initialize (self): """ .. seealso:: :func:`AbstractAPI.initialize() <escape.util.api.AbstractAPI.initialize>` """ log.debug("Initializing Controller Adaptation Sublayer...") self.controller_adapter = ControllerAdapter(self, with_infr=self._with_infr) if self._mapped_nffg: try: mapped_request = self._read_data_from_file(self._mapped_nffg) mapped_request = NFFG.parse(mapped_request) self.__proceed_installation(mapped_nffg=mapped_request) except (ValueError, IOError, TypeError) as e: log.error("Can't load service request from file because of: " + str(e)) quit_with_error(msg=str(e), logger=log) else: log.debug("Graph representation is loaded successfully!") log.info("Controller Adaptation Sublayer has been initialized!") def shutdown (self, event): """ .. seealso:: :func:`AbstractAPI.shutdown() <escape.util.api.AbstractAPI.shutdown>` :param event: event object :type: :class:`pox.lib.revent.revent.Event` :return: None """ log.info("Controller Adaptation Sublayer is going down...") self.controller_adapter.shutdown() ############################################################################## # UNIFY Or - Ca API functions starts here ############################################################################## def _handle_InstallNFFGEvent (self, event): """ Install mapped NF-FG (UNIFY Or - Ca API). :param event: event object contains mapped NF-FG :type event: :any:`InstallNFFGEvent` :return: None """ log.getChild('API').info("Received mapped NF-FG: %s from %s Layer" % ( event.mapped_nffg, str(event.source._core_name).title())) self.__proceed_installation(mapped_nffg=event.mapped_nffg, original_request=event.original_request) @schedule_as_coop_task def __proceed_installation (self, mapped_nffg, original_request=None): """ Helper function to instantiate the NFFG mapping from different source. :param mapped_nffg: pre-mapped service request :type mapped_nffg: :class:`NFFG` :return: None """ log.getChild('API').info("Invoke install_nffg on %s with NF-FG: %s " % ( self.__class__.__name__, mapped_nffg)) stats.add_measurement_start_entry(type=stats.TYPE_DEPLOY, info=LAYER_NAME) try: deploy_status = self.controller_adapter.install_nffg(mapped_nffg, original_request) except Exception: log.error("Something went wrong during NFFG installation!") self.raiseEventNoErrors(InstallationFinishedEvent, result=InstallationFinishedEvent.DEPLOY_ERROR) raise log.getChild('API').debug("Invoked install_nffg on %s is finished!" % self.__class__.__name__) if not deploy_status.still_pending: id = mapped_nffg.id result = InstallationFinishedEvent.get_result_from_status(deploy_status) log.info("Overall installation result: %s" % result) self.raiseEventNoErrors(InstallationFinishedEvent, id=id, result=result) @schedule_as_coop_task def _handle_CollectMonitoringDataEvent (self, event): """ :param event: :return: """ log.getChild('API').info("Received recursive monitoring request from %s " "Layer" % event.source._core_name.title()) try: status = self.controller_adapter.propagate_info_requests(id=event.id, info=event.info) except Exception: log.exception("Something went wrong during info request processing!") self.raiseEventNoErrors(InfoRequestFinishedEvent, result=InfoRequestFinishedEvent.ERROR) return log.getChild('API').debug("Invoked 'info' on %s is finished!" % self.__class__.__name__) if not status.still_pending: result = InfoRequestFinishedEvent.get_result_from_status(status) self.raiseEventNoErrors(InfoRequestFinishedEvent, result=result, status=status) ############################################################################## # UNIFY ( Ca - ) Co - Rm API functions starts here ############################################################################## def _handle_GetGlobalResInfoEvent (self, event): """ Generate global resource info and send back to ROS. :param event: event object :type event: :any:`GetGlobalResInfoEvent` :return: None """ log.getChild('API').debug( "Received DoV request from %s layer" % str( event.source._core_name).title()) # Currently global view is a reference to the DoV to keep ESCAPE fast dov = self.controller_adapter.DoVManager.dov log.getChild('API').debug("Sending back DoV: %s..." % dov) self.raiseEventNoErrors(GlobalResInfoEvent, dov)
class ControllerAdaptationAPI(AbstractAPI): """ Entry point for Controller Adaptation Sublayer (CAS). Maintain the contact with other UNIFY layers. Implement the Or - Ca reference point. """ # Define specific name for core object i.e. pox.core.<_core_name> _core_name = LAYER_NAME # Events raised by this class _eventMixin_events = { GlobalResInfoEvent, InstallationFinishedEvent, DeployNFFGEvent, InfoRequestFinishedEvent } # Dependencies dependencies = ('REST-API', ) def __init__(self, standalone=False, **kwargs): """ .. seealso:: :func:`AbstractAPI.__init__() <escape.util.api.AbstractAPI.__init__>` """ log.info("Starting Controller Adaptation Sublayer...") # Set Infrastructure as a dependency if kwargs['with_infr']: log.debug("Set Infrastructure Layer as a dependency") self.dependencies = self.dependencies + (INFR_LAYER_NAME, ) # Mandatory super() call self.controller_adapter = None self.api_mgr = RESTAPIManager(unique_bb_id=False, unique_nf_id=True, logger=log) super(ControllerAdaptationAPI, self).__init__(standalone, **kwargs) def initialize(self): """ .. seealso:: :func:`AbstractAPI.initialize() <escape.util.api.AbstractAPI.initialize>` """ log.debug("Initializing Controller Adaptation Sublayer...") self.controller_adapter = ControllerAdapter(self, with_infr=self._with_infr) if self._mapped_nffg: try: mapped_request = self._read_data_from_file(self._mapped_nffg) mapped_request = NFFG.parse(mapped_request) self.__proceed_installation(mapped_nffg=mapped_request) except (ValueError, IOError, TypeError) as e: log.error("Can't load service request from file because of: " + str(e)) quit_with_error(msg=str(e), logger=log) else: log.debug("Graph representation is loaded successfully!") if self._dovapi: self._initialize_dov_api() log.info("Controller Adaptation Sublayer has been initialized!") def shutdown(self, event): """ .. seealso:: :func:`AbstractAPI.shutdown() <escape.util.api.AbstractAPI.shutdown>` :param event: event object :type: :class:`pox.lib.revent.revent.Event` :return: None """ log.info("Controller Adaptation Sublayer is going down...") self.controller_adapter.shutdown() def _initialize_dov_api(self): rest_api = self.get_dependent_component('REST-API') rest_api.register_component(component=self) dov = self.controller_adapter.DoVManager.dov self.dov_api_view = GlobalViewVirtualizer(id=self._core_name, global_view=dov) log.debug("Created default Virtualizer View for DOV-API: %s" % self.dov_api_view) return ############################################################################## # UNIFY Or - Ca API functions starts here ############################################################################## def _handle_InstallNFFGEvent(self, event): """ Install mapped NF-FG (UNIFY Or - Ca API). :param event: event object contains mapped NF-FG :type event: :any:`InstallNFFGEvent` :return: None """ log.getChild('API').info( "Received mapped NF-FG: %s from %s Layer" % (event.mapped_nffg, str(event.source._core_name).title())) self.__proceed_installation(mapped_nffg=event.mapped_nffg, original_request=event.original_request) @schedule_as_coop_task def __proceed_installation(self, mapped_nffg, original_request=None, direct_deploy=False): """ Helper function to instantiate the NFFG mapping from different source. :param mapped_nffg: pre-mapped service request :type mapped_nffg: :class:`NFFG` :return: None """ log.getChild('API').info("Invoke install_nffg on %s with NF-FG: %s " % (self.__class__.__name__, mapped_nffg)) stats.add_measurement_start_entry(type=stats.TYPE_DEPLOY, info=LAYER_NAME) try: deploy_status = self.controller_adapter.install_nffg( mapped_nffg=mapped_nffg, original_request=original_request, direct_deploy=direct_deploy) except Exception as e: log.error("Something went wrong during NFFG installation: %s" % e) self._process_mapping_result(nffg_id=mapped_nffg.id, fail=True) self.raiseEventNoErrors( InstallationFinishedEvent, id=mapped_nffg.id, result=InstallationFinishedEvent.DEPLOY_ERROR) return log.getChild('API').debug("Invoked install_nffg on %s is finished!" % self.__class__.__name__) if deploy_status is None: log.error("Deploy status is missing!") self._process_mapping_result(nffg_id=mapped_nffg.id, fail=True) self.raiseEventNoErrors( InstallationFinishedEvent, id=mapped_nffg.id, result=InstallationFinishedEvent.DEPLOY_ERROR) elif not deploy_status.still_pending: result = InstallationFinishedEvent.get_result_from_status( deploy_status) log.info("Overall installation result: %s" % result) is_fail = InstallationFinishedEvent.is_error(result) self._process_mapping_result(nffg_id=mapped_nffg.id, fail=is_fail) self.raiseEventNoErrors(InstallationFinishedEvent, id=mapped_nffg.id, result=result) elif deploy_status.standby: if self._dovapi: RequestScheduler().set_orchestration_standby() def _process_mapping_result(self, nffg_id, fail): """ :param nffg_id: :param fail: :return: """ log.getChild('API').debug("Cache request status...") req_status = self.api_mgr.request_cache.get_request_by_nffg_id(nffg_id) if req_status is None: log.getChild('API').debug( "Request status is missing for NFFG: %s! " "Skip result processing..." % nffg_id) return log.getChild('API').debug("Process mapping result...") message_id = req_status.message_id if message_id is not None: if fail: self.api_mgr.request_cache.set_error_result(id=message_id) else: self.api_mgr.request_cache.set_success_result(id=message_id) log.info("Set request status: %s for message: %s" % (req_status.status, req_status.message_id)) ret = self.api_mgr.invoke_callback(message_id=message_id) if ret is None: log.getChild('API').debug("No callback was defined!") else: log.getChild('API').debug( "Callback: %s has invoked with return value: %s" % (req_status.get_callback(), ret)) RequestScheduler().set_orchestration_finished(id=nffg_id) @schedule_as_coop_task def _handle_CollectMonitoringDataEvent(self, event): """ Propagate Info request to the domain. :param event: event object :type event: :class:`CollectMonitoringDataEvent` :return: None """ log.getChild('API').info( "Received recursive monitoring request from %s " "Layer" % event.source._core_name.title()) try: status = self.controller_adapter.propagate_info_requests( id=event.id, info=event.info) except Exception: log.exception( "Something went wrong during info request processing!") self.raiseEventNoErrors(InfoRequestFinishedEvent, result=InfoRequestFinishedEvent.ERROR) return log.getChild('API').debug("Invoked 'info' on %s is finished!" % self.__class__.__name__) if not status.still_pending: result = InfoRequestFinishedEvent.get_result_from_status(status) self.raiseEventNoErrors(InfoRequestFinishedEvent, result=result, status=status) ############################################################################## # UNIFY ( Ca - ) Co - Rm API functions starts here ############################################################################## def _handle_GetGlobalResInfoEvent(self, event): """ Generate global resource info and send back to ROS. :param event: event object :type event: :class:`GetGlobalResInfoEvent` :return: None """ log.getChild('API').debug("Received DoV request from %s layer" % str(event.source._core_name).title()) # Currently global view is a reference to the DoV to keep ESCAPE fast dov = self.controller_adapter.DoVManager.dov log.getChild('API').debug("Sending back DoV: %s..." % dov) self.raiseEventNoErrors(GlobalResInfoEvent, dov) ############################################################################## # Agent API functions starts here ############################################################################## def rest_api_get_config(self): """ Implementation of REST-API RPC: get-config. Return with the global resource as an :class:`NFFG` if it has been changed otherwise return with False. :return: global resource view (DoV) :rtype: :class:`NFFG` or False """ # return self.controller_adapter.DoVManager.dov.get_resource_info() log.getChild('[DOV-API]').debug("Requesting Virtualizer for DoV-API") if self.dov_api_view is not None: # Check the topology is initialized if self.dov_api_view.revision is None: log.getChild('[DOV-API]').debug( "DoV has not initialized yet! " "Force to get default topology...") else: # Check if the resource is changed if self.api_mgr.topology_revision == self.dov_api_view.revision: # If resource has not been changed return False # This causes to response with the cached topology log.debug( "Global resource has not changed (revision: %s)! " % self.dov_api_view.revision) log.debug("Send topology from cache...") if self.api_mgr.last_response is None: log.error("Cached topology is missing!") return else: return self.api_mgr.last_response else: log.getChild('[DOV-API]').debug( "Response cache is outdated " "(new revision: %s)!" % self.dov_api_view.revision) res = self.dov_api_view.get_resource_info() self.api_mgr.topology_revision = self.dov_api_view.revision log.debug("Updated revision number: %s" % self.api_mgr.topology_revision) if CONFIG.get_rest_api_config(self._core_name)['unify_interface']: log.info("Convert internal NFFG to Virtualizer...") res = self.api_mgr.converter.dump_to_Virtualizer(nffg=res) log.debug("Cache acquired topology...") self.api_mgr.last_response = res return res else: log.error("Virtualizer(id=%s) assigned to DoV-API is not found!" % self._core_name) # noinspection PyUnusedLocal def rest_api_edit_config(self, id, data, params=None): """ Implement edit-config call for CAS layer. Receive edit-config request from external component and directly forward data for deployment. :param params: request params :type params: dict :return: None """ log.getChild('[DOV-API]').info( "Invoke instantiation on %s with NF-FG: " "%s " % (self.__class__.__name__, id)) if CONFIG.get_rest_api_config(self._core_name)['unify_interface']: log.debug("Virtualizer format enabled! Start conversion step...") if CONFIG.get_rest_api_config(self._core_name)['diff']: log.debug("Diff format enabled! Start patching step...") if self.api_mgr.last_response is None: log.info( "Missing cached Virtualizer! Acquiring topology now..." ) self.rest_api_get_config() stats.add_measurement_start_entry(type=stats.TYPE_PROCESSING, info="RECREATE-FULL-REQUEST") log.info("Patching cached topology with received diff...") full_req = self.api_mgr.last_response.yang_copy() full_req.patch(source=data) stats.add_measurement_end_entry(type=stats.TYPE_PROCESSING, info="RECREATE-FULL-REQUEST") else: full_req = data log.info("Converting full request data...") stats.add_measurement_start_entry(type=stats.TYPE_CONVERSION, info="VIRTUALIZER-->NFFG") nffg = self.api_mgr.converter.parse_from_Virtualizer( vdata=full_req) stats.add_measurement_end_entry(type=stats.TYPE_CONVERSION, info="VIRTUALIZER-->NFFG") else: nffg = data log.debug("Set NFFG id: %s" % id) if nffg.service_id is None: nffg.service_id = nffg.id nffg.id = id if params: nffg.add_metadata(name="params", value=params) log.info("Proceeding request: %s to instantiation..." % id) if CONFIG.get_vnfm_enabled(): deploy_status = self.controller_adapter.status_mgr.get_last_status( ) if deploy_status is None: log.warning( "Received direct DoV rewrite request from external " "component without any preliminary deploy request!") else: if deploy_status.id != nffg.id: log.error( "Received direct deploy request id: %s is different from " "service request under deploy: %s" % (nffg.id, deploy_status.id)) return else: self.controller_adapter.cancel_vnfm_timer() log.getChild('API').debug("Store received DoV request...") msg_id = self.api_mgr.request_cache.cache_request_by_nffg(nffg=nffg) if msg_id is not None: self.api_mgr.request_cache.set_in_progress(id=msg_id) log.getChild('API').debug("Request is stored with id: %s" % msg_id) else: log.getChild('API').warning("No request info detected.") self.__proceed_installation(mapped_nffg=nffg, direct_deploy=True)
class ControllerAdaptationAPI(AbstractAPI): """ Entry point for Controller Adaptation Sublayer (CAS). Maintain the contact with other UNIFY layers. Implement the Or - Ca reference point. """ # Define specific name for core object i.e. pox.core.<_core_name> _core_name = LAYER_NAME # Events raised by this class _eventMixin_events = {GlobalResInfoEvent, InstallationFinishedEvent, DeployNFFGEvent} # Dependencies # None def __init__ (self, standalone=False, **kwargs): """ .. seealso:: :func:`AbstractAPI.__init__() <escape.util.api.AbstractAPI.__init__>` """ log.info("Starting Controller Adaptation Sublayer...") # Set Infrastructure as a dependency if kwargs['with_infr']: log.debug("Set Infrastructure Layer as a dependency") self.dependencies = self.dependencies + (INFR_LAYER_NAME,) # Mandatory super() call self.controller_adapter = None super(ControllerAdaptationAPI, self).__init__(standalone, **kwargs) def initialize (self): """ .. seealso:: :func:`AbstractAPI.initialize() <escape.util.api.AbstractAPI.initialize>` """ log.debug("Initializing Controller Adaptation Sublayer...") self.controller_adapter = ControllerAdapter(self, with_infr=self._with_infr) if self._mapped_nffg: try: mapped_request = self._read_data_from_file(self._mapped_nffg) mapped_request = NFFG.parse(mapped_request) self.__proceed_installation(mapped_nffg=mapped_request) except (ValueError, IOError, TypeError) as e: log.error("Can't load service request from file because of: " + str(e)) else: log.debug("Graph representation is loaded successfully!") log.info("Controller Adaptation Sublayer has been initialized!") def shutdown (self, event): """ .. seealso:: :func:`AbstractAPI.shutdown() <escape.util.api.AbstractAPI.shutdown>` :param event: event object """ log.info("Controller Adaptation Sublayer is going down...") self.controller_adapter.shutdown() ############################################################################## # UNIFY Or - Ca API functions starts here ############################################################################## def _handle_InstallNFFGEvent (self, event): """ Install mapped NF-FG (UNIFY Or - Ca API). :param event: event object contains mapped NF-FG :type event: :any:`InstallNFFGEvent` :return: None """ log.getChild('API').info("Received mapped NF-FG: %s from %s Layer" % ( event.mapped_nffg, str(event.source._core_name).title())) self.__proceed_installation(mapped_nffg=event.mapped_nffg) @schedule_as_coop_task def __proceed_installation (self, mapped_nffg): """ Helper function to instantiate the NFFG mapping from different source. :param mapped_nffg: pre-mapped service request :type mapped_nffg: :any:`NFFG` :return: None """ log.getChild('API').info("Invoke install_nffg on %s with NF-FG: %s " % ( self.__class__.__name__, mapped_nffg)) log.info(int(round(time.time() * 1000))) try: install_result = self.controller_adapter.install_nffg(mapped_nffg) except Exception as e: log.error("Something went wrong during NFFG installation!") self.raiseEventNoErrors(InstallationFinishedEvent, result=False, error=e) raise log.getChild('API').debug("Invoked install_nffg on %s is finished" % self.__class__.__name__) log.info(int(round(time.time() * 1000))) self.raiseEventNoErrors(InstallationFinishedEvent, id=mapped_nffg.id, result=install_result) ############################################################################## # UNIFY ( Ca - ) Co - Rm API functions starts here ############################################################################## def _handle_GetGlobalResInfoEvent (self, event): """ Generate global resource info and send back to ROS. :param event: event object :type event: :any:`GetGlobalResInfoEvent` :return: None """ log.getChild('API').debug( "Received DoV request from %s layer" % str( event.source._core_name).title()) # Currently global view is a reference to the DoV to keep ESCAPE fast dov = self.controller_adapter.DoVManager.dov log.getChild('API').debug( "Sending back DoV: %s..." % dov) self.raiseEventNoErrors(GlobalResInfoEvent, dov) def _handle_DeployEvent (self, event): """ Receive processed NF-FG from domain adapter(s) and forward to Infrastructure :param event: event object :type event: :any:`DeployNFFGEvent` :return: None """ # Sending NF-FG to Infrastructure layer as an Event # Exceptions in event handlers are caught by default in a non-blocking way log.getChild('API').info( "Processed NF-FG has been sent to Infrastructure...") # XXX - probably will not be supported in the future self.raiseEventNoErrors(DeployNFFGEvent, event.nffg_part) def _handle_DeploymentFinishedEvent (self, event): """ Receive successful NF-FG deployment event and propagate upwards :param event: event object :type event: :any:`DeploymentFinishedEvent` :return: None """ if event.success: log.getChild('API').info( "NF-FG installation has been finished successfully!") else: log.getChild('API').error( "NF-FG installation has been finished with error!") self.raiseEventNoErrors(InstallationFinishedEvent, event.success)