コード例 #1
0
 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!")
コード例 #2
0
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)
コード例 #3
0
ファイル: cas_API.py プロジェクト: walexzzy/escape
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)
コード例 #4
0
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)