예제 #1
0
    def _handle_InstallationFinishedEvent(self, event):
        """
    Get information from NFFG installation process.

    :param event: event object info
    :type event: :any:`InstallationFinishedEvent`
    :return: None
    """
        if not InstantiationFinishedEvent.is_error(event.result):
            self.log.info(
                "NF-FG(%s) instantiation has been finished successfully "
                "with result: %s!" % (event.id, event.result))
        else:
            self.log.error(
                "NF-FG(%s) instantiation has been finished with error "
                "result: %s!" % (event.id, event.result))
            if InstantiationFinishedEvent.is_deploy_error(event.result):
                if CONFIG.get_trial_and_error(layer=LAYER_NAME):
                    log.info(
                        "TRIAL_AND_ERROR is enabled! Reschedule for mapping..."
                    )
                    self.__proceed_trial_and_error(
                        original_request_id=event.id)
                    return
                else:
                    log.debug("TRIAL_AND_ERROR is disabled! Proceeding...")
        if not event.is_pending(event.result):
            self.__process_mapping_result(nffg_id=event.id,
                                          fail=event.is_error(event.result))
        self.raiseEventNoErrors(InstantiationFinishedEvent,
                                id=event.id,
                                result=event.result)
예제 #2
0
    def __manage_neo4j_service(self):
        """
    Manage neo4j service.

    :return: None
    """
        if not CONFIG.get_manage_neo4j_service():
            log.debug("Skip Neo4j service management...")
            return
        log.debug("Detected Neo4j service name: %s" % self.service_name)
        if check_service_status(self.service_name):
            log.debug("%s service is already running..." % self.service_name)
            return
        log.info("Starting service: %s..." % self.service_name)
        ret = run_cmd('sudo service %s start' % self.service_name)
        if "failed" in ret:
            log.error("Neo4j service initiation status: %s" % ret)
            return
        log.log(VERBOSE, "Neo4j service initiation status: %s" % ret)
        # Check if the service has been started - only 5 try
        if port_tester(host=self.DB_HOST,
                       port=self.DB_PORT,
                       interval=1,
                       period=10,
                       log=log):
            log.debug("Neo4j service has been verified!")
        else:
            log.error("Neo4j service has not started correctly!")
예제 #3
0
파일: ros_API.py 프로젝트: hsnlab/fero
 def initialize(self):
     """
 .. seealso::
   :func:`AbstractAPI.initialize() <escape.util.api.AbstractAPI.initialize>`
 """
     log.debug("Initializing Resource Orchestration Sublayer...")
     self.resource_orchestrator = ResourceOrchestrator(self)
     if self._nffg_file:
         try:
             service_request = self._read_data_from_file(self._nffg_file)
             service_request = NFFG.parse(service_request)
             self.__proceed_instantiation(nffg=service_request)
         except (ValueError, IOError, TypeError) as e:
             log.error("Can't load service request from file because of: " +
                       str(e))
         else:
             log.info("Graph representation is loaded successfully!")
     # Initiate ROS REST-API if needed
     if self._agent or self._rosapi:
         self._initiate_ros_api()
     # Initiate Cf-Or REST-API if needed
     if self._cfor:
         self._initiate_cfor_api()
     log.info("Resource Orchestration Sublayer has been initialized!")
     if self._agent:
         log.warning(
             "In AGENT mode Service Layer is not going to be initialized!")
예제 #4
0
    def __process_mapping_result(self, nffg_id, fail):
        """
    Perform common tasks after the mapping alg has run and deploy is performed.

    :param nffg_id: deployed NFFG id
    :type nffg_id: str or int
    :param fail: mark the deploy step was failed
    :type fail: bool
    :return: None
    """
        self.log.debug("Cache request status...")
        req_status = self.api_mgr.request_cache.get_request_by_nffg_id(nffg_id)
        if req_status is None:
            self.log.debug("Request status is missing for NFFG: %s! "
                           "Skip result processing..." % nffg_id)
            return
        self.log.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:
                self.log.debug("No callback was defined!")
            else:
                self.log.debug(
                    "Callback: %s has invoked with return value: %s" %
                    (req_status.get_callback(), ret))
        RequestScheduler().set_orchestration_finished(id=nffg_id)
예제 #5
0
    def __process_info_result(self, status, fail):
        """
    Perform common tasks after an Info request was processed and responses were
    collected.

    :param status: deploy status
    :type status: :any:`DomainRequestStatus`
    :param fail: mark the Info step was failed
    :type fail: bool
    :return: None
    """
        self.log.debug("Cache collected 'info' request status...")
        req_status = self.api_mgr.request_cache.get_request(
            message_id=status.id)
        if req_status is None:
            self.log.debug("Request status is missing: %s! "
                           "Skip result processing..." % status.id)
            return
        self.log.debug("Process collected info result...")
        if fail:
            self.api_mgr.request_cache.set_error_result(id=status.id)
            body = None
        else:
            self.api_mgr.request_cache.set_success_result(id=status.id)
            body = status.data[0]
            body = body.xml() if isinstance(body, Info) else str(body)
        log.info("Set request status: %s for message: %s" %
                 (req_status.status, req_status.message_id))
        log.log(VERBOSE, "Collected Info data:\n%s" % body)
        ret = self.api_mgr.invoke_callback(message_id=status.id, body=body)
        if ret is None:
            self.log.debug("No callback was defined!")
        else:
            self.log.info("Callback: %s has invoked with return value: %s" %
                          (req_status.get_callback(), ret))
예제 #6
0
 def timer_decorator(func, *args, **kwargs):
     start = time.time()
     try:
         result = func(*args, **kwargs)
     finally:
         delta = time.time() - start
         log.info("Mapping algorithm finished in %.3f seconds!" % delta)
     return result
예제 #7
0
    def shutdown(self, event):
        """
    .. seealso::
      :func:`AbstractAPI.shutdown() <escape.util.api.AbstractAPI.shutdown>`

    :param event: event object
    """
        log.info("Resource Orchestration Sublayer is going down...")
        self.orchestrator.finalize()
예제 #8
0
파일: ros_API.py 프로젝트: hsnlab/fero
 def __init__(self, standalone=False, **kwargs):
     """
 .. seealso::
   :func:`AbstractAPI.__init__() <escape.util.api.AbstractAPI.__init__>`
 """
     log.info("Starting Resource Orchestration Sublayer...")
     # Mandatory super() call
     self.resource_orchestrator = None
     super(ResourceOrchestrationAPI, self).__init__(standalone, **kwargs)
예제 #9
0
    def finalize(self):
        """
    Finalize function for the class.

    :return: None
    """
        if CONFIG.get_manage_neo4j_service():
            log.info("Stopping %s service..." % self.service_name)
            ret = run_cmd('sudo service %s stop' % self.service_name)
            log.log(VERBOSE, "Neo4j service shutdown status: %s" % ret)
예제 #10
0
 def cprofiler_decorator(func, *args, **kwargs):
     profiler = cProfile.Profile(builtins=False, subcalls=False)
     try:
         profiler.enable()
         result = func(*args, **kwargs)
     finally:
         profiler.disable()
         profiler.create_stats()
         stat = pstats.Stats(profiler)
         log.info("Mapping algorithm finished with %d function calls "
                  "(%d primitive calls) in %.3f seconds!" %
                  (stat.total_calls, stat.prim_calls, stat.total_tt))
     return result
예제 #11
0
    def _initiate_ros_api(self):
        """
    Initialize and setup REST API in a different thread.

    If agent_mod is set rewrite the received NFFG domain from REMOTE to
    INTERNAL.

    :return: None
    """
        rest_api = self.get_dependent_component('REST-API')
        rest_api.register_component(component=self)
        if self._agent:
            log.info("REST-API is set in AGENT mode")
예제 #12
0
파일: ros_API.py 프로젝트: hsnlab/fero
    def shutdown(self, event):
        """
    .. seealso::
      :func:`AbstractAPI.shutdown() <escape.util.api.AbstractAPI.shutdown>`

    :param event: event object
    """
        log.info("Resource Orchestration Sublayer is going down...")
        if self._agent or self._rosapi:
            log.debug("REST-API: %s is shutting down..." % self.ros_api.api_id)
            # self.ros_api.stop()
        if self._cfor:
            log.debug("REST-API: %s is shutting down..." %
                      self.cfor_api.api_id)
예제 #13
0
    def timer_decorator(func, *args, **kwargs):
        """
    Decorator function to measure the runtime of given function.

    :param func: profiled function
    :type func: callable
    :return: return value of given function
    """
        start = time.time()
        try:
            result = func(*args, **kwargs)
        finally:
            delta = time.time() - start
            log.info("Mapping algorithm finished in %.3f seconds!" % delta)
        return result
예제 #14
0
 def __init__(self, standalone=False, **kwargs):
     """
 .. seealso::
   :func:`AbstractAPI.__init__() <escape.util.api.AbstractAPI.__init__>`
 """
     log.info("Starting Resource Orchestration Sublayer...")
     # Mandatory super() call
     self.orchestrator = None
     """:type: ResourceOrchestrator"""
     self.api_mgr = RESTAPIManager(
         unique_bb_id=False,
         unique_nf_id=CONFIG.ensure_unique_vnf_id(),
         logger=log)
     self.log = log.getChild('API')
     super(ResourceOrchestrationAPI, self).__init__(standalone, **kwargs)
예제 #15
0
파일: ros_API.py 프로젝트: hsnlab/fero
    def _initiate_ros_api(self):
        """
    Initialize and setup REST API in a different thread.

    If agent_mod is set rewrite the received NFFG domain from REMOTE to
    INTERNAL.

    :return: None
    """
        # set bounded layer name here to avoid circular dependency problem
        handler = CONFIG.get_ros_agent_class()
        handler.bounded_layer = self._core_name
        params = CONFIG.get_ros_agent_params()
        # can override from global config
        if 'prefix' in params:
            handler.prefix = params['prefix']
        if 'unify_interface' in params:
            handler.virtualizer_format_enabled = params['unify_interface']
        if 'diff' in params:
            handler.DEFAULT_DIFF = bool(params['diff'])
        address = (params.get('address'), params.get('port'))
        # Virtualizer ID of the Sl-Or interface
        self.ros_api = RESTServer(handler, *address)
        self.ros_api.api_id = handler.LOGGER_NAME = "Sl-Or"
        # Virtualizer type for Sl-Or API
        self.ros_api.virtualizer_type = CONFIG.get_api_virtualizer(
            layer_name=LAYER_NAME, api_name=self.ros_api.api_id)
        handler.log.info("Init REST-API for %s on %s:%s!" %
                         (self.ros_api.api_id, address[0], address[1]))
        self.ros_api.start()
        handler.log.debug(
            "Enforced configuration for %s: virtualizer type: %s, interface: %s, "
            "diff: %s" % (self.ros_api.api_id, self.ros_api.virtualizer_type,
                          "UNIFY" if handler.virtualizer_format_enabled else
                          "Internal-NFFG", handler.DEFAULT_DIFF))
        if self._agent:
            log.info("REST-API is set in AGENT mode")
예제 #16
0
  def __initialize (self):
    """
    Initialize NFIB with test data.
    """
    log.info("Initializing NF database with NFs and decompositions...")
    # start clean - all the existing info is removed from the DB
    self.removeGraphDB()
    # add new high-level NF to the DB, all the information related to the NF
    # should be given as a dict
    self.addNode({'label': 'NF', 'node_id': 'forwarder', 'type': 'NA'})
    self.addNode({'label': 'NF', 'node_id': 'compressor', 'type': 'NA'})
    self.addNode({'label': 'NF', 'node_id': 'decompressor', 'type': 'NA'})

    log.debug(
      "%s: high-level NFs were added to the DB" % self.__class__.__name__)

    # generate a  decomposition for a high-level forwarder NF (in form of
    # networkx)
    G1 = networkx.DiGraph()
    G1.add_path(['SAP1', 'simpleForwarder', 'SAP2'])

    # create node properties
    for n in G1.nodes():
      properties = {'node_id': n}

      if 'SAP' in n:
        properties['label'] = 'SAP'
        properties['type'] = 'NA'
      else:
        properties['label'] = 'NF'
        properties['type'] = 'click'
        properties['cpu'] = 10
        properties['mem'] = 100
        properties['storage'] = 100
      G1.node[n]['properties'] = properties

    # create edge properties
    properties = {'BW': 100, 'src_port': 1, 'dst_port': 1}
    G1.edge['SAP1']['simpleForwarder']['properties'] = properties

    properties1 = {'BW': 100, 'src_port': 2, 'dst_port': 2}
    G1.edge['simpleForwarder']['SAP2']['properties'] = properties1

    # generate a decomposition for a high-level compressor NF (in form of
    # networkx)
    G2 = networkx.DiGraph()
    G2.add_path(['SAP3', 'headerCompressor', 'SAP4'])

    # create node properties
    for n in G2.nodes():
      properties = {'node_id': n}
      if 'SAP' in n:
        properties['label'] = 'SAP'
        properties['type'] = 'NA'
      else:
        properties['label'] = 'NF'
        properties['type'] = 'click'
        properties['cpu'] = 20
        properties['mem'] = 200
        properties['storage'] = 200
      G2.node[n]['properties'] = properties

    # create edge properties 
    properties3 = {'BW': 200, 'src_port': 1, 'dst_port': 1}
    G2.edge['SAP3']['headerCompressor']['properties'] = properties3

    properties4 = {'BW': 200, 'src_port': 2, 'dst_port': 2}
    G2.edge['headerCompressor']['SAP4']['properties'] = properties4

    # generate a decomposition for a high-level decompressor NF (in form of
    # networkx)
    G3 = networkx.DiGraph()
    G3.add_path(['SAP5', 'headerDecompressor', 'SAP6'])

    # create node properties
    for n in G3.nodes():
      properties = {'node_id': n}
      if 'SAP' in n:
        properties['label'] = 'SAP'
        properties['type'] = 'NA'
      else:
        properties['label'] = 'NF'
        properties['type'] = 'click'
        properties['cpu'] = 30
        properties['mem'] = 300
        properties['storage'] = 300
      G3.node[n]['properties'] = properties

    # create edge properties
    properties5 = {'BW': 300, 'src_port': 1, 'dst_port': 1}
    G3.edge['SAP5']['headerDecompressor']['properties'] = properties5

    properties6 = {'BW': 300, 'src_port': 2, 'dst_port': 2}
    G3.edge['headerDecompressor']['SAP6']['properties'] = properties6

    # required elementary NFs should be added first to the DB
    self.addClickNF({'label': 'NF', 'node_id': 'Queue', 'type:': 'click'})
    self.addClickNF({'label': 'NF', 'node_id': 'Classifier', 'type': 'click'})
    self.addClickNF({'label': 'NF', 'node_id': 'Counter', 'type': 'click'})
    self.addClickNF({'label': 'NF', 'node_id': 'RFC2507Comp', 'type': 'click'})
    self.addClickNF(
      {'label': 'NF', 'node_id': 'RFC2507Decomp', 'type': 'click'})

    # the NF decompositions are added to the DB
    self.addDecomp('forwarder', 'G1', G1)
    self.addDecomp('compressor', 'G2', G2)
    self.addDecomp('decompressor', 'G3', G3)

    log.debug(
      "%s: NF decompositions were added to the DB" % self.__class__.__name__)
예제 #17
0
    def __proceed_instantiation(self, nffg, resource_nffg):
        """
    Helper function to instantiate the NFFG mapping from different source.

    :param nffg: pre-mapped service request
    :type nffg: :class:`NFFG`
    :return: None
    """
        self.log.info("Invoke instantiation on %s with NF-FG: %s" %
                      (self.__class__.__name__, nffg.name))
        stats.add_measurement_start_entry(type=stats.TYPE_ORCHESTRATION,
                                          info=LAYER_NAME)
        # Get shown topology view
        if resource_nffg is None:
            log.error("Missing resource for difference calculation!")
            return
        log.debug("Got resource view for difference calculation: %s" %
                  resource_nffg)
        self.log.debug("Store received NFFG request info...")
        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)
            self.log.debug("Request is stored with id: %s" % msg_id)
        else:
            self.log.debug("No request info detected.")
        # Check if mapping mode is set globally in CONFIG
        mapper_params = CONFIG.get_mapping_config(layer=LAYER_NAME)
        if 'mode' in mapper_params and mapper_params['mode'] is not None:
            mapping_mode = mapper_params['mode']
            log.info("Detected mapping mode from configuration: %s" %
                     mapping_mode)
        elif nffg.mode is not None:
            mapping_mode = nffg.mode
            log.info("Detected mapping mode from NFFG: %s" % mapping_mode)
        else:
            mapping_mode = None
            log.info("No mapping mode was defined explicitly!")
        if not CONFIG.get_mapping_enabled(layer=LAYER_NAME):
            log.warning("Mapping is disabled! Skip difference calculation...")
        elif nffg.status == NFFG.MAP_STATUS_SKIPPED:
            log.debug("Detected NFFG map status: %s! "
                      "Skip difference calculation and "
                      "proceed with original request..." % nffg.status)
        elif mapping_mode != NFFG.MODE_REMAP:
            # Calculated ADD-DELETE difference
            log.debug("Calculate ADD - DELETE difference with mapping mode...")
            # Recreate SG-hops for diff calc.
            log.debug("Recreate SG hops for difference calculation...")
            NFFGToolBox.recreate_all_sghops(nffg=nffg)
            NFFGToolBox.recreate_all_sghops(nffg=resource_nffg)
            log.log(VERBOSE, "New NFFG:\n%s" % nffg.dump())
            log.log(VERBOSE, "Resource NFFG:\n%s" % resource_nffg.dump())
            # Calculate difference
            add_nffg, del_nffg = NFFGToolBox.generate_difference_of_nffgs(
                old=resource_nffg, new=nffg, ignore_infras=True)
            log.log(VERBOSE, "Calculated ADD NFFG:\n%s" % add_nffg.dump())
            log.log(VERBOSE, "Calculated DEL NFFG:\n%s" % del_nffg.dump())
            if not add_nffg.is_bare() and del_nffg.is_bare():
                nffg = add_nffg
                log.info("DEL NFFG is bare! Calculated mapping mode: %s" %
                         nffg.mode)
            elif add_nffg.is_bare() and not del_nffg.is_bare():
                nffg = del_nffg
                log.info("ADD NFFG is bare! Calculated mapping mode: %s" %
                         nffg.mode)
            elif not add_nffg.is_bare() and not del_nffg.is_bare():
                log.warning("Both ADD / DEL mode is not supported currently")
                self.__process_mapping_result(nffg_id=nffg.id, fail=True)
                stats.add_measurement_end_entry(type=stats.TYPE_ORCHESTRATION,
                                                info=LAYER_NAME + "-FAILED")
                self.raiseEventNoErrors(
                    InstantiationFinishedEvent,
                    id=nffg.id,
                    result=InstantiationFinishedEvent.ABORTED)
                return
            else:
                log.debug("Difference calculation resulted empty subNFFGs!")
                log.warning(
                    "No change has been detected in request! Skip mapping...")
                self.log.debug("Invoked instantiation on %s is finished!" %
                               self.__class__.__name__)
                self.__process_mapping_result(nffg_id=nffg.id, fail=False)
                stats.add_measurement_end_entry(type=stats.TYPE_ORCHESTRATION,
                                                info=LAYER_NAME + "-SKIPPED")
                return
        else:
            log.debug(
                "Mode: %s detected from config! Skip difference calculation..."
                % mapping_mode)
        try:
            if CONFIG.get_mapping_enabled(layer=LAYER_NAME):
                # Initiate request mapping
                mapped_nffg = self.orchestrator.instantiate_nffg(nffg=nffg)
            else:
                log.warning("Mapping is disabled! Skip instantiation step...")
                mapped_nffg = nffg
                mapped_nffg.status = NFFG.MAP_STATUS_SKIPPED
                log.debug("Mark NFFG status: %s!" % mapped_nffg.status)
            # Rewrite REMAP mode for backward compatibility
            if mapped_nffg is not None and mapping_mode == NFFG.MODE_REMAP:
                mapped_nffg.mode = mapping_mode
                log.debug("Rewrite mapping mode: %s into mapped NFFG..." %
                          mapped_nffg.mode)
            else:
                log.debug("Skip mapping mode rewriting! Mode remained: %s" %
                          mapping_mode)
                self.log.debug("Invoked instantiate_nffg on %s is finished!" %
                               self.__class__.__name__)
            # If mapping is not threaded and finished with OK
            if mapped_nffg is not None and not self.orchestrator.mapper.threaded:
                self._proceed_to_install_NFFG(mapped_nffg=mapped_nffg,
                                              original_request=nffg)
            else:
                log.warning(
                    "Something went wrong in service request instantiation: "
                    "mapped service request is missing!")
                self.__process_mapping_result(nffg_id=nffg.id, fail=True)
                stats.add_measurement_end_entry(type=stats.TYPE_ORCHESTRATION,
                                                info=LAYER_NAME + "-FAILED")
                self.raiseEventNoErrors(
                    InstantiationFinishedEvent,
                    id=nffg.id,
                    result=InstantiationFinishedEvent.MAPPING_ERROR)
        except ProcessorError as e:
            self.__process_mapping_result(nffg_id=nffg.id, fail=True)
            stats.add_measurement_end_entry(type=stats.TYPE_ORCHESTRATION,
                                            info=LAYER_NAME + "-DENIED")
            self.raiseEventNoErrors(
                InstantiationFinishedEvent,
                id=nffg.id,
                result=InstantiationFinishedEvent.REFUSED_BY_VERIFICATION,
                error=e)
예제 #18
0
    def map(cls, graph, resource, persistent=None, pre_state=None):
        """
    Default mapping algorithm of ESCAPEv2.

    :param graph: Network Function forwarding Graph
    :type graph: :class:`NFFG`
    :param resource: global virtual resource info
    :type resource: :class:`NFFG`
    :param persistent: use persistent state object
    :type persistent: object
    :param pre_state: use mapping state for continued mapping
    :type pre_state: :class:`MappingState`
    :return: mapped Network Function Forwarding Graph
    :rtype: :class:`NFFG`
    """
        log.info("Invoke mapping algorithm: %s - request: %s resource: %s, "
                 "previous state: %s" %
                 (cls.__name__, graph, resource, pre_state))
        if graph is None:
            log.error("Missing request NFFG! Abort mapping process...")
            return
        if resource is None:
            log.error("Missing resource NFFG! Abort mapping process...")
            return
        try:
            # Run pre-mapping step to resolve target-less flowrules
            cls._resolve_external_ports(graph, resource)
            # Copy mapping config
            mapper_params = CONFIG.get_mapping_config(
                layer=cls.LAYER_NAME).copy()
            mapper_params['persistent'] = persistent
            if 'mode' in mapper_params and mapper_params['mode']:
                log.debug("Setup mapping mode from configuration: %s" %
                          mapper_params['mode'])
            elif graph.mode:
                mapper_params['mode'] = graph.mode
                log.debug("Setup mapping mode based on request: %s" %
                          mapper_params['mode'])
            if CONFIG.get_trial_and_error(layer=cls.LAYER_NAME):
                log.info("Use 'trial and error' approach for mapping")
                mapper_params['return_mapping_state'] = True
                mapper_params['mapping_state'] = pre_state
            mapping_result = cls.call_mapping_algorithm(
                request=graph.copy(),
                topology=resource.copy(),
                **mapper_params)
            if isinstance(mapping_result, tuple or list):
                mapped_nffg = mapping_result[0]
            else:
                mapped_nffg = mapping_result
            # Set mapped NFFG id for original SG request tracking
            log.debug("Move request metadata into mapping result...")
            mapped_nffg.id = graph.id
            mapped_nffg.name = "%s-%s-mapped" % (graph.name, cls.LAYER_NAME)
            # Explicitly copy metadata
            mapped_nffg.metadata = graph.metadata.copy()
            # Explicit copy of SAP data
            for sap in graph.saps:
                if sap.id in mapped_nffg:
                    mapped_nffg[sap.id].metadata = graph[
                        sap.id].metadata.copy()
            log.info("Mapping algorithm: %s is finished on NF-FG: %s" %
                     (cls.__name__, mapped_nffg))
            return mapping_result
        except MappingException as e:
            log.error(
                "Mapping algorithm unable to map given request! Cause:\n%s" %
                e.msg)
            log.error("Mapping algorithm on %s is aborted!" % graph)
            return
        except BadInputException as e:
            log.error("Mapping algorithm refuse given input! Cause:\n%s" %
                      e.msg)
            log.error("Mapping algorithm on %s is aborted!" % graph)
            return
        except InternalAlgorithmException as e:
            log.critical(
                "Mapping algorithm fails due to internal error! Cause:\n%s" %
                e.msg)
            log.error("Mapping algorithm on %s is aborted!" % graph)
            return
        except Exception:
            log.exception("Got unexpected error during mapping process!")
예제 #19
0
파일: ros_mapping.py 프로젝트: hsnlab/fero
    def _perform_mapping(self, input_graph, resource_view):
        """
    Orchestrate mapping of given NF-FG on given global resource.

    :param input_graph: Network Function Forwarding Graph
    :type input_graph: :any:`NFFG`
    :param resource_view: global resource view
    :type resource_view: :any:`DomainVirtualizer`
    :return: mapped Network Function Forwarding Graph
    :rtype: :any:`NFFG`
    """
        if input_graph is None:
            log.error(
                "Missing mapping request information! Abort mapping process!")
            return None
        log.debug("Request %s to launch orchestration on NF-FG: %s with View: "
                  "%s" % (self.__class__.__name__, input_graph, resource_view))
        # Steps before mapping (optional)
        log.debug("Request global resource info...")
        virt_resource = resource_view.get_resource_info()
        if virt_resource is None:
            log.error("Missing resource information! Abort mapping process!")
            return None
        # log a warning if resource is empty --> possibly mapping will be failed
        if virt_resource.is_empty():
            log.warning("Resource information is empty!")
        # Log verbose resource view if it is exist
        log.log(
            VERBOSE,
            "Orchestration Layer resource graph:\n%s" % virt_resource.dump())
        # Check if the mapping algorithm is enabled
        if not CONFIG.get_mapping_enabled(LAYER_NAME):
            log.warning("Mapping algorithm in Layer: %s is disabled! "
                        "Skip mapping step and return service request "
                        "to lower layer..." % LAYER_NAME)
            # virt_resource.id = input_graph.id
            # return virt_resource
            # Send request forward (probably to Remote ESCAPE)
            return input_graph
        # Run actual mapping algorithm
        if self._threaded:
            # Schedule a microtask which run mapping algorithm in a Python thread
            log.info("Schedule mapping algorithm: %s in a worker thread" %
                     self.strategy.__name__)
            call_as_coop_task(self._start_mapping,
                              graph=input_graph,
                              resource=virt_resource)
            log.info("NF-FG: %s orchestration is finished by %s" %
                     (input_graph, self.__class__.__name__))
            # Return with None
            return None
        else:
            mapped_nffg = self.strategy.map(graph=input_graph,
                                            resource=virt_resource)
            if mapped_nffg is None:
                log.error(
                    "Mapping process is failed! Abort orchestration process.")
            else:
                # Steps after mapping (optional)
                log.info(
                    "NF-FG: %s orchestration is finished by %s successfully!" %
                    (input_graph, self.__class__.__name__))
            return mapped_nffg
예제 #20
0
    def _perform_mapping(self, input_graph, resource_view, continued=False):
        """
    Orchestrate mapping of given NF-FG on given global resource.

    :param input_graph: Network Function Forwarding Graph
    :type input_graph: :class:`NFFG`
    :param resource_view: global resource view
    :type resource_view: :any:`DomainVirtualizer`
    :return: mapped Network Function Forwarding Graph
    :rtype: :class:`NFFG`
    """
        if input_graph is None:
            log.error(
                "Missing mapping request information! Abort mapping process!")
            return None
        log.debug(
            "Request %s to launch orchestration on NF-FG: %s with View: "
            "%s, continued remap: %s" %
            (self.__class__.__name__, input_graph, resource_view, continued))
        # Steps before mapping (optional)
        log.debug("Request global resource info...")
        virt_resource = resource_view.get_resource_info()
        if virt_resource is None:
            log.error("Missing resource information! Abort mapping process!")
            return None
        # log a warning if resource is empty --> possibly mapping will be failed
        if virt_resource.is_empty():
            log.warning("Resource information is empty!")
        # Log verbose resource view if it is exist
        log.log(
            VERBOSE,
            "Orchestration Layer resource graph:\n%s" % virt_resource.dump())
        # Check if the mapping algorithm is enabled
        if not CONFIG.get_mapping_enabled(LAYER_NAME):
            log.warning("Mapping algorithm in Layer: %s is disabled! "
                        "Skip mapping step and return service request "
                        "to lower layer..." % LAYER_NAME)
            # virt_resource.id = input_graph.id
            # return virt_resource
            # Send request forward (probably to Remote ESCAPE)
            input_graph.status = NFFG.MAP_STATUS_SKIPPED
            log.debug("Mark NFFG status: %s!" % input_graph.status)
            return input_graph
        # Run actual mapping algorithm
        if self._threaded:
            # Schedule a microtask which run mapping algorithm in a Python thread
            log.info("Schedule mapping algorithm: %s in a worker thread" %
                     self.strategy.__name__)
            call_as_coop_task(self._start_mapping,
                              graph=input_graph,
                              resource=virt_resource)
            log.info("NF-FG: %s orchestration is finished by %s" %
                     (input_graph, self.__class__.__name__))
            # Return with None
            return None
        else:
            state = self.last_mapping_state if continued else None
            mapping_result = self.strategy.map(
                graph=input_graph,
                resource=virt_resource,
                persistent=self.persistent_state,
                pre_state=state)
            if isinstance(mapping_result, tuple or list):
                if len(mapping_result) == 2:
                    mapped_nffg = mapping_result[0]
                    self.persistent_state = mapping_result[1]
                    log.debug("Cache returned persistent state: %s" %
                              self.persistent_state)
                elif len(mapping_result) == 3:
                    mapped_nffg = mapping_result[0]
                    self.persistent_state = mapping_result[1]
                    log.debug("Cache returned persistent state: %s" %
                              self.persistent_state)
                    self.last_mapping_state = mapping_result[2]
                    log.debug("Cache returned mapping state: %s" %
                              self.last_mapping_state)
                else:
                    log.error("Mapping result is invalid: %s" %
                              repr(mapping_result))
                    mapped_nffg = None
            else:
                mapped_nffg = mapping_result
            # Check error result
            if mapped_nffg is None:
                log.error(
                    "Mapping process is failed! Abort orchestration process.")
            else:
                # Steps after mapping (optional)
                log.info(
                    "NF-FG: %s orchestration is finished by %s successfully!" %
                    (input_graph, self.__class__.__name__))
            log.debug("Last mapping state: %s" % self.last_mapping_state)
            if self.last_mapping_state:
                log.debug("Mapping iteration: %s" %
                          self.last_mapping_state.get_number_of_trials()
                          if self.last_mapping_state else None)
            return mapped_nffg
예제 #21
0
  def instantiate_nffg (self, nffg):
    """
    Main API function for NF-FG instantiation.

    :param nffg: NFFG instance
    :type nffg: :any:`NFFG`
    :return: mapped NFFG instance
    :rtype: :any:`NFFG`
    """

    log.debug("Invoke %s to instantiate given NF-FG" % self.__class__.__name__)
    # Store newly created NF-FG
    self.nffgManager.save(nffg)
    # Get Domain Virtualizer to acquire global domain view
    global_view = self.virtualizerManager.dov
    # Notify remote visualizer about resource view of this layer if it's needed
    notify_remote_visualizer(data=global_view.get_resource_info(),
                             id=LAYER_NAME)
    # Log verbose mapping request
    log.log(VERBOSE, "Orchestration Layer request graph:\n%s" % nffg.dump())
    # Start Orchestrator layer mapping
    print nffg.dump()
    if global_view is not None:
      if isinstance(global_view, AbstractVirtualizer):
        # If the request is a bare NFFG, it is probably an empty topo for domain
        # deletion --> skip mapping to avoid BadInputException and forward
        # topo to adaptation layer
        if nffg.is_bare():
          log.warning("No valid service request (VNFs/Flowrules/SGhops) has "
                      "been detected in SG request! Skip orchestration in "
                      "layer: %s and proceed with the bare %s..." %
                      (LAYER_NAME, nffg))
          if nffg.is_virtualized():
            if nffg.is_SBB():
              log.debug("Request is a bare SingleBiSBiS representation!")
            else:
              log.warning(
                "Detected virtualized representation with multiple BiSBiS "
                "nodes! Currently this type of virtualization is nut fully"
                "supported!")
          else:
            log.debug("Detected full view representation!")
          # Return with the original request
          return nffg
        else:
          log.info("Request check: detected valid content!")
        try:
          # Run Nf-FG mapping orchestration
          log.debug("Starting request preprocession...")
          log.info(int(round(time.time() * 1000)))
          self.preprocess_nffg(nffg)
          log.debug("Preprocession ended, start mapping")
          log.info(int(round(time.time() * 1000)))
          mapped_nffg = self.mapper.orchestrate(nffg, global_view)
          log.debug("NF-FG instantiation is finished by %s" %
                    self.__class__.__name__)
          log.info(int(round(time.time() * 1000)))
          return mapped_nffg
        except ProcessorError as e:
          log.warning("Mapping pre/post processing was unsuccessful! "
                      "Cause: %s" % e)
      else:
        log.warning("Global view is not subclass of AbstractVirtualizer!")
    else:
      log.warning("Global view is not acquired correctly!")
    log.error("Abort orchestration process!")
예제 #22
0
    def instantiate_nffg(self, nffg, continued_request_id=None):
        """
    Main API function for NF-FG instantiation.

    :param nffg: NFFG instance
    :type nffg: :class:`NFFG`
    :param continued_request_id: use explicit request id if request is
      continued after a trial and error (default: False)
    :type continued_request_id: str or None
    :return: mapped NFFG instance
    :rtype: :class:`NFFG`
    """
        log.debug("Invoke %s to instantiate given NF-FG" %
                  self.__class__.__name__)
        if not continued_request_id:
            # Store newly created NF-FG
            self.nffgManager.save(nffg)
        else:
            # Use the original NFFG requested for getting the original request
            nffg = self.nffgManager.get(nffg_id=continued_request_id)
            log.info("Using original request for remapping: %s" % nffg)
        # Get Domain Virtualizer to acquire global domain view
        global_view = self.virtualizerManager.dov
        # Notify remote visualizer about resource view of this layer if it's needed
        # notify_remote_visualizer(data=global_view.get_resource_info(),
        #                          id=LAYER_NAME)
        # Log verbose mapping request
        log.log(VERBOSE,
                "Orchestration Layer request graph:\n%s" % nffg.dump())
        # Start Orchestrator layer mapping
        if global_view is not None:
            # If the request is a bare NFFG, it is probably an empty topo for domain
            # deletion --> skip mapping to avoid BadInputException and forward
            # topo to adaptation layer
            if not continued_request_id:
                if nffg.is_bare():
                    log.warning(
                        "No valid service request (VNFs/Flowrules/SGhops) has "
                        "been detected in SG request! Skip orchestration in "
                        "layer: %s and proceed with the bare %s..." %
                        (LAYER_NAME, nffg))
                    if nffg.is_virtualized():
                        if nffg.is_SBB():
                            log.debug(
                                "Request is a bare SingleBiSBiS representation!"
                            )
                        else:
                            log.warning(
                                "Detected virtualized representation with multiple BiSBiS "
                                "nodes! Currently this type of virtualization is nut fully "
                                "supported!")
                    else:
                        log.debug("Detected full view representation!")
                    # Return with the original request
                    return nffg
                else:
                    log.info("Request check: detected valid NFFG content!")
            try:
                # Run NF-FG mapping orchestration
                mapped_nffg = self.mapper.orchestrate(
                    input_graph=nffg,
                    resource_view=global_view,
                    continued=bool(continued_request_id))
                log.debug("NF-FG instantiation is finished by %s" %
                          self.__class__.__name__)
                return mapped_nffg
            except ProcessorError as e:
                log.warning("Mapping pre/post processing was unsuccessful! "
                            "Cause: %s" % e)
                # Propagate the ProcessError to API layer
                raise
        else:
            log.warning("Global view is not acquired correctly!")
        log.error("Abort orchestration process!")