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)) 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.debug("Overall installation result: %s" % result) self.raiseEventNoErrors(InstallationFinishedEvent, id=id, result=result)
def _detect_topology(self): """ Check the undetected topology is up or not. If the domain is confirmed and detected, the ``internal_topo`` attribute will be updated with the new topology. .. warning:: No :any:`DomainChangedEvent` will be raised internally if the domain is confirmed! :return: detected or not :rtype: bool """ if self.topoAdapter.check_domain_reachable(): log.info(">>> %s domain confirmed!" % self.domain_name) self._detected = True log.info("Requesting resource information from %s domain..." % self.domain_name) topo_nffg = self.topoAdapter.get_topology_resource() if topo_nffg: log.debug("Save detected topology: %s..." % topo_nffg) # Update the received new topo self.internal_topo = topo_nffg else: log.warning("Resource info is missing!") return self._detected
def __roll_next_revision(self): if self.__revision is None: self.__revision = self.REVISION_SEED else: self.__revision += 1 log.debug("New topology revision: %s" % self.__revision) return self.__revision
def __init__(self, base_url, prefix="", auth=None, **kwargs): """ Init. :param base_url: base URL without the prefix path :type base_url: str :param prefix: prefix :type prefix: str :param auth: optional authentications :type auth: str :param kwargs: optional params: :type kwargs: dict :return: None """ super(AbstractRESTAdapter, self).__init__() if not base_url: return if base_url.endswith('/'): self._base_url = urlparse.urljoin(base_url, prefix + "/") else: self._base_url = urlparse.urljoin(base_url + '/', prefix + "/") self.auth = auth # Store the last request self._response = None if 'timeout' in kwargs: self.CONNECTION_TIMEOUT = kwargs['timeout'] log.debug("Setup explicit timeout for REST responses: %ss" % self.CONNECTION_TIMEOUT) # Suppress low level logging self.__suppress_requests_logging()
def set_domain_as_global_view(self, domain, nffg): """ Set the copy of given NFFG as the global view of DoV. Add the specific :attr:`DoV` id and generated name to the global view. :param nffg: NFFG instance intended to use as the global view :type nffg: :class:`NFFG` :param domain: name of the merging domain :type domain: str :return: updated Dov :rtype: :class:`NFFG` """ log.debug("Set domain: %s as the global view!" % domain) if not self.__global_nffg.is_empty(): log.warning( "Global view is not empty! Current state will be lost!") self.__global_nffg = nffg.copy() self.__global_nffg.id = DoV self.__global_nffg.name = DoV log.debug("DoV stat:\n%s" % self.__global_nffg.get_stat()) # Raise event for observing Virtualizers about topology change self.raiseEventNoErrors(DoVChangedEvent, cause=DoVChangedEvent.TYPE.UPDATE) return self.__global_nffg
def url(self): if self.__callback: log.debug("Using explicit URL for callback: %s" % self.__callback) return self.__callback else: log.debug("Using generated callback URL...") return "http://%s:%s/callback" % self.server_address
def _acquire_resource(self): """ Compute and return with the Single BiS-BiS view based on the global view. :return: single BiSBiS representation of the global view :rtype: :class:`NFFG` """ dov = self.global_view.get_resource_info() if dov.is_empty(): # DoV is not initialized yet! Probably only just remote Mgrs has been # enabled! return with the default empty DoV log.warning( "Requested global resource view is empty! Return the default empty " "topology!") return dov else: if str(self.sbb_id).startswith('$'): if str(self.sbb_id)[1:] in os.environ: self.sbb_id = os.environ.get(str(self.sbb_id)[1:]) log.debug("Detected SBB id from environment variable: %s" % self.sbb_id) # Generate the Single BiSBiS representation sbb = NFFGToolBox.generate_SBB_representation(nffg=dov, sbb_id=self.sbb_id, log=log) log.log(VERBOSE, "Generated SBB:\n%s" % sbb.dump()) return sbb
def remerge_domain_in_dov(self, domain, nffg): """ Update the existing domain in the merged Global view with explicit domain remove and re-add. :param nffg: changed infrastructure info :type nffg: :class:`NFFG` :param domain: name of the merging domain :type domain: str :return: updated Dov :rtype: :class:`NFFG` """ NFFGToolBox.remove_domain(base=self.__global_nffg, domain=domain, log=log) # log.log(VERBOSE, "Reduced Dov:\n%s" % self.__global_nffg.dump()) NFFGToolBox.merge_new_domain(base=self.__global_nffg, nffg=nffg, log=log) log.debug("DoV stat:\n%s" % self.__global_nffg.get_stat()) log.log(VERBOSE, "Re-merged DoV:\n%s" % self.__global_nffg.dump()) if self.__global_nffg.is_empty(): log.warning( "No Node had been remained after updating the domain part: " "%s! DoV is empty!" % domain) # Raise event for observing Virtualizers about topology change self.raiseEventNoErrors(DoVChangedEvent, cause=DoVChangedEvent.TYPE.CHANGE) return self.__global_nffg
def __init__(self, address=DEFAULT_SERVER_ADDRESS, port=DEFAULT_PORT, timeout=DEFAULT_WAIT_TIMEOUT, **kwargs): """ Init. :param address: callback address :type address: str :param port: listening port :type port: int :param timeout: used timeout value for callbacks :type timeout: float """ Thread.__init__(self, name="%s(%s:%s)" % (self.__class__.__name__, address, port)) HTTPServer.__init__(self, (address, port), CallbackHandler, bind_and_activate=False) self.wait_timeout = float(timeout) self.__register = {} self.__domain_proxy = {} self.daemon = True self.__blocking_mutex = threading.Event() log.debug("Init %s" % self.__class__.__name__)
def register_and_block_wait(self, cb_id, type, req_id=None, data=None, timeout=None): """ Register for a callback and block-wait until callback is received. :param cb_id: callback ID :type cb_id: str :param type: callback type :type type: str :param req_id: original request ID (optional) :type req_id: str or int :param data: optional callback data (optional) :type data: object :param timeout: explicit timeout value (optional) :type timeout: float :return: registered callback object :rtype: :class:`Callback` """ cb = self.subscribe_callback(hook=None, cb_id=cb_id, type=type, req_id=req_id, domain=None, data=data, timeout=timeout) _timeout = timeout if timeout is not None else self.wait_timeout + 1 log.debug("Waiting for callback result...") self.__blocking_mutex.wait(timeout=_timeout) self.__blocking_mutex.clear() return self.unsubscribe_callback(cb_id=cb.callback_id, domain=None)
def add_domain(self, domain, nffg): """ Update the global view data with the specific domain info. :param domain: domain name :type domain: str :param nffg: infrastructure info collected from the domain :type nffg: :any:`NFFG` :return: None """ # If the domain is not tracked if domain not in self.__tracked_domains: if not nffg: log.warning("Got empty data. Skip domain addition...") return log.info("Append %s domain to DoV..." % domain) # If DoV is empty if not self.__dov.is_empty(): # Merge domain topo into global view self.__dov.merge_new_domain_into_dov(nffg=nffg) else: # No other domain detected, set NFFG as the whole Global view log.debug( "DoV is empty! Add new domain: %s as the global view!" % domain) self.__dov.set_domain_as_global_view(domain=domain, nffg=nffg) # Add detected domain to cached domains self.__tracked_domains.add(domain) else: log.error( "New domain: %s has already tracked: %s! Abort adding..." % (domain, self.__tracked_domains))
def __filter_external_domains(nffg): """ Filter out domains detected by external DomainManagers. :param nffg: filtered NFFG :return: :class:`NFFG` """ log.debug("Filtering domains detected from external DomainManagers...") # Get External DomainManager names ext_mgr = CONFIG.get_external_managers() # Copy NFFG filtered_nffg = nffg.copy() # Remove the detected domains by External DomainManagers for ext in ext_mgr: # Get all the domains domains = NFFGToolBox.detect_domains(nffg=filtered_nffg) # Get domains detected and initiated by the External DomainManager ext_domains = [d for d in domains if ext in d] # Remove collected domains from NFFG for domain in ext_domains: log.debug( "Remove domain: %s originated from external DomainManager: %s" % (domain, ext)) NFFGToolBox.remove_domain(base=filtered_nffg, domain=domain, log=log) filtered_nffg.name += "-filtered" return filtered_nffg
def __init__(self, layer_API, with_infr=False): """ Initialize Controller adapter. For domain components the ControllerAdapter checks the CONFIG first. :param layer_API: layer API instance :type layer_API: :any:`ControllerAdaptationAPI` :param with_infr: using emulated infrastructure (default: False) :type with_infr: bool """ log.debug("Init ControllerAdapter - with IL: %s" % with_infr) super(ControllerAdapter, self).__init__() # Set a weak reference to avoid circular dependencies self._layer_API = weakref.proxy(layer_API) self._with_infr = with_infr # Set virtualizer-related components self.DoVManager = GlobalResourceManager() self.domains = ComponentConfigurator(self) try: if with_infr: # Init internal domain manager if Infrastructure Layer is started self.domains.load_local_domain_mgr() # Init default domain managers self.domains.load_default_mgrs() except (ImportError, AttributeError, ConfigurationError) as e: from escape.util.misc import quit_with_error quit_with_error( msg="Shutting down ESCAPEv2 due to an unexpected error!", logger=log, exception=e) # Here every domainManager is up and running # Notify the remote visualizer about collected data if it's needed notify_remote_visualizer(data=self.DoVManager.dov.get_resource_info(), id=LAYER_NAME)
def __init__(self): """ Init. """ super(GlobalResourceManager, self).__init__() log.debug("Init DomainResourceManager") self.__dov = DomainVirtualizer(self) # Domain Virtualizer self.__tracked_domains = set() # Cache for detected and stored domains self._remerge = CONFIG.use_remerge_update_strategy()
def __init__(self): """ Initialize virtualizer manager. :return: None """ super(VirtualizerManager, self).__init__() log.debug("Init %s" % self.__class__.__name__) self._virtualizers = dict()
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
def finit(self): """ Finish the remained connections and release the reserved resources. Called by the DomainManager. :return: None """ log.debug("Finit ESCAPEAdapter name: %s, type: %s" % (self.name, self.type))
def setup_timer(self, timeout, hook, **kwargs): if not timeout: log.debug("Timeout disabled for request callback: %s" % self.request_id) return if not self.__timer: log.debug("Setup timeout: %s for callback: %s" % (timeout, self.callback_id)) self.__timer = Timer(timeout, hook, kwargs=kwargs) self.__timer.start() else: log.warning("Callback timer has already been set up!")
def run(self): try: log.debug("Start %s for domain: %s on %s:%s" % (self.__class__.__name__, self.domain_name, self.server_address[0], self.server_address[1])) self.serve_forever() except KeyboardInterrupt: raise except Exception as e: log.error("Got exception in %s: %s" % (self.__class__.__name__, e)) finally: self.server_close()
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 set_global_view(self, nffg): """ Replace the global view with the given topology. :param nffg: new global topology :type nffg: :any:`NFFG` :return: None """ log.debug("Update the whole Global view (DoV) with the NFFG: %s..." % nffg) self.dov.update_full_global_view(nffg=nffg) self.__tracked_domains.clear() self.__tracked_domains.update(NFFGToolBox.detect_domains(nffg))
def _handle_DoVChangedEvent(self, event): """ Handle :any:`DomainChangedEvent` raised by the observer :any:`DomainVirtualizer`. :param event: event object :type event: :any:`DomainChangedEvent` :return: None """ log.debug("Received DoVChanged notification for %s! Cause: %s" % (self, DoVChangedEvent.TYPE.reversed[event.cause])) # Topology is changed, set dirty flag self._dirty = True
def unsubscribe_callback(self, cb_id): """ :param cb_id: :return: :rtype: Callback """ log.debug("Unregister callback for response: %s from domain: %s" % (cb_id, self.domain_name)) cb = self.__register.pop(cb_id, None) if cb: cb.stop_timer() return cb
def get_resource_info(self): """ Hides object's mechanism and return with a resource info. :return: resource info :rtype: :class:`NFFG` """ # If topology has not changed -> return with cached resource if self.__dirty is False: log.debug( "DoV is unchanged (revision: %s)! Return cached NFFG..." % self.__revision) else: if self.__dirty is None: log.debug("Virtual view is uninitialized! " "Requesting resource NFFG...") self.__roll_next_revision() else: log.debug( "DoV has been changed! Requesting new resource NFFG...") # If Virtualizer dirty resource info is changed since last request or has # never queried yet -> acquire resource info with template method # Acquire and cache new resource self.__cache = self._acquire_resource() log.debug("Clear dirty flag...") # Clear dirty flag self.__dirty = False return self.__cache
def __init__(self, global_view, id): """ Init. :param global_view: virtualizer instance represents the global view :type global_view: :any:`DomainVirtualizer` :param id: id of the assigned entity :type: id: str """ log.debug("Initiate default SingleBiSBiS <Virtual View>") super(SingleBiSBiSVirtualizer, self).__init__(id=id, global_view=global_view, type=self.SINGLE_VIRTUALIZER)
def __init__(self, global_view, id): """ Init. :param global_view: virtualizer instance represents the global view :type global_view: :any:`DomainVirtualizer` :param id: id of the assigned entity :type: id: str """ log.debug("Initiate unfiltered/global <Virtual View>") super(GlobalViewVirtualizer, self).__init__(id=id, global_view=global_view, type=self.GLOBAL_VIRTUALIZER)
def __init__(self, global_view, id, **kwargs): """ Init. :param global_view: virtualizer instance represents the global view :type global_view: :any:`DomainVirtualizer` :param id: id of the assigned entity :type: id: str :param kwargs: optional parameters for Virtualizer :type kwargs: dict :return: None """ log.debug("Initiate only-local SingleBiSBiS <Virtual View>") super(LocalSingleBiSBiSVirtualizer, self).__init__(id=id, global_view=global_view, type=self.TYPE)
def wait_for_callback(self, cb): """ Register an existing callback object for block-wait. :param cb: callback object :type cb: :class:`Callback` :return: original callback object :rtype cb: :class:`Callback` """ _timeout = cb.get_timer_timeout() + 1.0 log.debug("Waiting for callback result...") self.__blocking_mutex.wait(timeout=_timeout) self.__blocking_mutex.clear() return self.unsubscribe_callback(cb_id=cb.callback_id, domain=cb.domain)
def pre_sanity_check(cls, args, kwargs): """ Implements the the sanity check before virtualizer's sanity check is called. :param args: original nameless arguments :type args: tuple :param kwargs: original named arguments :type kwargs: dict :return: None """ virtualizer = args[0] nffg = args[1] # TODO - implement log.debug("PolicyEnforcement: sanity_check NFFG(%s) <--> %s [OK]" % (nffg, repr.repr(virtualizer)))
def get_resource_info(self): """ Return with the unfiltered global view. :return: Virtual resource info :rtype: :any:`NFFG` """ # Leave the dirty mechanism operational self._dirty = False log.debug( "No filtering in Virtualizer: %s. Return full global resource..." % self.type) # Currently we NOT filter the global view just propagate to other layers # and entities intact return self.global_view.get_resource_info()