예제 #1
0
    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
예제 #2
0
    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
예제 #3
0
    def clean_domain_from_dov(self, domain):
        """
    Clean domain by removing initiated NFs and flowrules related to BiSBiS
    nodes of the given domain

    :param domain: domain name
    :type domain: str
    :return: updated Dov
    :rtype: :class:`NFFG`
    """
        if self.__global_nffg.is_empty():
            log.debug("DoV is empty! Skip cleanup domain: %s" % domain)
            return self.__global_nffg
        if self.__global_nffg.is_bare():
            log.debug("No initiated service has been detected in DoV! "
                      "Skip cleanup domain: %s" % domain)
            return self.__global_nffg
        NFFGToolBox.clear_domain(base=self.__global_nffg,
                                 domain=domain,
                                 log=log)
        log.debug("DoV stat:\n%s" % self.__global_nffg.get_stat())
        log.log(VERBOSE, "Cleaned Dov:\n%s" % self.__global_nffg.dump())
        self.raiseEventNoErrors(DoVChangedEvent,
                                cause=DoVChangedEvent.TYPE.CHANGE)
        return self.__global_nffg
예제 #4
0
파일: domain.py 프로젝트: ustcldf/escape-1
    def send_quietly(self,
                     method,
                     url=None,
                     body=None,
                     timeout=None,
                     **kwargs):
        """
    Send REST request with handling exceptions and logging only in VERBOSE mode.

    :param method: HTTP method
    :type method: str
    :param url: valid URL or relevant part follows ``self.base_url``
    :type url: str
    :param body: request body
    :type body: :class:`NFFG` or dict or bytes or str
    :param timeout: optional timeout param can be given also here
    :type timeout: int
    :raises: :any:`requests.Timeout`
    :return: raw response data
    :rtype: str
    """
        try:
            if timeout is not None:
                kwargs['timeout'] = timeout
            return self.send_request(method, url, body, **kwargs)
        except Timeout:
            log.log(
                VERBOSE,
                "Remote agent(adapter: %s, url: %s) reached timeout limit!" %
                (self.name, self._base_url))
            return None
        except ConnectionError:
            log.log(
                VERBOSE,
                "Remote agent(adapter: %s, url: %s) is not reachable!" %
                (self.name, self._base_url))
            return None
        except HTTPError as e:
            log.log(
                VERBOSE,
                "Remote agent(adapter: %s, url: %s) responded with an error: %s"
                % (self.name, self._base_url, e.message))
            return None
        except RequestException as e:
            log.log(VERBOSE, "Got unexpected exception: %s" % e)
            return None
        except KeyboardInterrupt:
            log.log(
                VERBOSE, "Request to remote agent(adapter: %s, url: %s) is "
                "interrupted by user!" % (self.name, self._base_url))
            return None
예제 #5
0
    def remove_deployed_elements(self):
        """
    Remove all the NFs, flowrules and dynamic ports from DoV.

    :return: updated Dov
    :rtype: :class:`NFFG`
    """
        if self.__global_nffg.is_empty():
            log.debug("DoV is empty! Skip DoV cleanup")
            return self.__global_nffg
        NFFGToolBox.remove_deployed_services(nffg=self.__global_nffg, log=log)
        log.debug("DoV stat:\n%s" % self.__global_nffg.get_stat())
        log.log(VERBOSE, "Cleared Dov:\n%s" % self.__global_nffg.dump())
        self.raiseEventNoErrors(DoVChangedEvent,
                                cause=DoVChangedEvent.TYPE.CHANGE)
        return self.__global_nffg
예제 #6
0
    def remove_domain_from_dov(self, domain):
        """
    Remove the nodes and edges with the given from Global view.

    :param domain: domain name
    :type domain: str
    :return: updated Dov
    :rtype: :any:`NFFG`
    """
        NFFGToolBox.remove_domain(base=self.__global_nffg,
                                  domain=domain,
                                  log=log)
        if self.__global_nffg.is_empty():
            log.warning(
                "No Node had been remained after updating the domain part: "
                "%s! DoV is empty!" % domain)
        log.log(VERBOSE, "Reduced Dov:\n%s" % self.__global_nffg.dump())
        # Raise event for observing Virtualizers about topology change
        self.raiseEventNoErrors(DoVChangedEvent,
                                cause=DoVChangedEvent.TYPE.REDUCE)
        return self.__global_nffg
예제 #7
0
    def merge_new_domain_into_dov(self, nffg):
        """
    Add a newly detected domain to DoV.

    Based on the feature: escape.util.nffg.NFFGToolBox#merge_domains

    :param nffg: NFFG object need to be merged into DoV
    :type nffg: :any:`NFFG`
    :return: updated Dov
    :rtype: :any:`NFFG`
    """
        # Using general merging function from NFFGToolBox and return the updated
        # NFFG
        NFFGToolBox.merge_new_domain(base=self.__global_nffg,
                                     nffg=nffg,
                                     log=log)
        # Raise event for observing Virtualizers about topology change
        log.log(VERBOSE, "Merged Dov:\n%s" % self.__global_nffg.dump())
        self.raiseEventNoErrors(DoVChangedEvent,
                                cause=DoVChangedEvent.TYPE.EXTEND)
        return self.__global_nffg
예제 #8
0
    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:
            filtered_dov = self.__filter_external_domains(nffg=dov)
            # Generate the Single BiSBiS representation
            sbb = NFFGToolBox.generate_SBB_representation(nffg=filtered_dov,
                                                          log=log)
            log.log(VERBOSE, "Generated SBB:\n%s" % sbb.dump())
            return sbb
예제 #9
0
    def update_domain_status_in_dov(self, domain, nffg):
        """
    Set status of initiated NFs and flowrules related to BiSBiS nodes of the
    given domain.

    :param domain: domain name
    :type domain: str
    :param nffg: changed infrastructure info
    :type nffg: :class:`NFFG`
    :return: updated Dov
    :rtype: :class:`NFFG`
    """
        if self.__global_nffg.is_empty():
            log.debug("DoV is empty! Skip cleanup domain: %s" % domain)
            return self.__global_nffg
        NFFGToolBox.update_status_info(nffg=nffg, status=NFFG.STATUS_DEPLOY)
        NFFGToolBox.update_nffg_by_status(base=self.__global_nffg,
                                          updated=nffg,
                                          log=log)
        log.log(VERBOSE, "Updated Dov:\n%s" % self.__global_nffg.dump())
        self.raiseEventNoErrors(DoVChangedEvent,
                                cause=DoVChangedEvent.TYPE.CHANGE)
        return self.__global_nffg
예제 #10
0
    def update_domain_in_dov(self, domain, nffg):
        """
    Update the existing domain in the merged Global view.

    :param nffg: NFFG object need to be updated with
    :type nffg: :any:`NFFG`
    :param domain: name of the merging domain
    :type domain: str
    :return: updated Dov
    :rtype: :any:`NFFG`
    """
        NFFGToolBox.update_domain(base=self.__global_nffg,
                                  updated=nffg,
                                  log=log)
        if self.__global_nffg.is_empty():
            log.warning(
                "No Node had been remained after updating the domain part: "
                "%s! DoV is empty!" % domain)
        log.log(VERBOSE, "Updated DoV:\n%s" % self.__global_nffg.dump())
        # Raise event for observing Virtualizers about topology change
        self.raiseEventNoErrors(DoVChangedEvent,
                                cause=DoVChangedEvent.TYPE.CHANGE)
        return self.__global_nffg
예제 #11
0
파일: domain.py 프로젝트: ustcldf/escape-1
    def install_flowrule(self, id, match, action):
        """
    Install a flowrule in an OpenFlow switch.

    :param id: ID of the infra element stored in the NFFG
    :type id: str
    :param match: match part of the rule (keys: in_port, vlan_id)
    :type match: dict
    :param action: action part of the rule (keys: out, vlan_push, vlan_pop)
    :type action: dict
    :return: None
    """
        conn = self.openflow.getConnection(dpid=self.infra_to_dpid[id])
        if not conn:
            log.warning(
                "Missing connection for node element: %s! Skip flowrule "
                "installation..." % id)
            return
        msg = of.ofp_flow_mod()
        msg.match.in_port = match['in_port']
        if 'vlan_id' in match:
            try:
                vlan_id = int(match['vlan_id'])
            except ValueError:
                log.warning(
                    "VLAN_ID: %s in match field is not a valid number! "
                    "Skip flowrule installation..." % match['vlan_id'])
                return
            msg.match.dl_vlan = vlan_id
        # Append explicit matching parameters to OF flowrule
        if 'flowclass' in match:
            for ovs_match_entry in match['flowclass'].split(','):
                kv = ovs_match_entry.split('=')
                # kv = [field, value] ~ ['dl_src', '00:0A:E4:25:6B:B6']
                # msg.match.dl_src = "00:00:00:00:00:01"
                if kv[0] in ('dl_src', 'dl_dst'):
                    setattr(msg.match, kv[0], EthAddr(kv[1]))
                elif kv[0] in ('in_port', 'dl_vlan', 'dl_type', 'ip_proto',
                               'nw_proto', 'nw_tos', 'nw_ttl', 'tp_src',
                               'tp_dst'):
                    setattr(msg.match, kv[0], int(kv[1], 0))
                elif kv[0] in ('nw_src', 'nw_dst'):
                    setattr(msg.match, kv[0], IPAddr(kv[1]))
                else:
                    setattr(msg.match, kv[0], kv[1])
        if 'vlan_push' in action:
            try:
                vlan_push = int(action['vlan_push'])
            except ValueError:
                log.warning(
                    "VLAN_PUSH: %s in action field is not a valid number! "
                    "Skip flowrule installation..." % action['vlan_push'])
                return
            msg.actions.append(of.ofp_action_vlan_vid(vlan_vid=vlan_push))
            # msg.actions.append(of.ofp_action_vlan_vid())
        out = action['out']
        # If out is in the detected saps --> always remove the VLAN tags
        if 'vlan_pop' in action:
            msg.actions.append(of.ofp_action_strip_vlan())
        else:
            try:
                # If next node is a SAP we need to setup the MAC addresses and
                # strip VLAN from the frame explicitly
                if out in self.saps[id]:
                    msg.actions.append(of.ofp_action_strip_vlan())
            except KeyError:
                pass
        try:
            if out in self.saps[id]:
                dl_dst = self.saps[id][str(out)]['dl_dst']
                dl_src = self.saps[id][str(out)]['dl_src']
                msg.actions.append(
                    of.ofp_action_dl_addr.set_dst(EthAddr(dl_dst)))
                msg.actions.append(
                    of.ofp_action_dl_addr.set_src(EthAddr(dl_src)))
        except KeyError:
            pass
        try:
            out_port = int(action['out'])
        except ValueError:
            log.warning(
                "Output port: %s is not a valid port in flowrule action: %s! "
                "Skip flowrule installation..." % (action['out'], action))
            return
        msg.actions.append(of.ofp_action_output(port=out_port))
        log.debug("Install flow entry into INFRA: %s on connection: %s ..." %
                  (id, conn))
        conn.send(msg)
        log.log(VERBOSE, "Sent raw OpenFlow flowrule:\n%s" % msg)
예제 #12
0
    def install_nffg(self, mapped_nffg):
        """
    Start NF-FG installation.

    Process given :any:`NFFG`, slice information self.__global_nffg on
    domains and invoke DomainManagers to install domain specific parts.

    :param mapped_nffg: mapped NF-FG instance which need to be installed
    :type mapped_nffg: NFFG
    :return: mapping result
    :rtype: bool
    """
        log.debug("Invoke %s to install NF-FG(%s)" %
                  (self.__class__.__name__, mapped_nffg.name))
        # # Notify remote visualizer about the deployable NFFG if it's needed
        # notify_remote_visualizer(data=mapped_nffg, id=LAYER_NAME)
        slices = NFFGToolBox.split_into_domains(nffg=mapped_nffg, log=log)
        if slices is None:
            log.warning("Given mapped NFFG: %s can not be sliced! "
                        "Skip domain notification steps" % mapped_nffg)
            return
        log.debug("Notify initiated domains: %s" %
                  [d for d in self.domains.initiated])
        # TODO - abstract/inter-domain tag rewrite
        # NFFGToolBox.rewrite_interdomain_tags(slices)
        mapping_result = True
        for domain, part in slices:
            log.debug(
                "Recreate missing TAG matching fields in domain part: %s..." %
                domain)
            # Temporarily rewrite/recreate TAGs here
            NFFGToolBox.recreate_match_TAGs(nffg=part, log=log)
            # Get Domain Manager
            domain_mgr = self.domains.get_component_by_domain(
                domain_name=domain)
            if domain_mgr is None:
                log.warning(
                    "No DomainManager has been initialized for domain: %s! "
                    "Skip install domain part..." % domain)
                continue
            log.log(VERBOSE,
                    "Splitted domain: %s part:\n%s" % (domain, part.dump()))
            log.info("Delegate splitted part: %s to %s" % (part, domain_mgr))
            # Rebind requirement link fragments as e2e reqs
            part = NFFGToolBox.rebind_e2e_req_links(nffg=part, log=log)
            # Check if need to reset domain before install
            if CONFIG.reset_domains_before_install():
                log.debug("Reset %s domain before deploying mapped NFFG..." %
                          domain_mgr.domain_name)
                domain_mgr.clear_domain()
            # Invoke DomainAdapter's install
            res = domain_mgr.install_nffg(part)
            # Update the DoV based on the mapping result covering some corner case
            if not res:
                log.error("Installation of %s in %s was unsuccessful!" %
                          (part, domain))
            # Note result according to others before
            mapping_result = mapping_result and res
            # If installation of the domain was performed without error
            if not res:
                log.warning("Skip DoV update with domain: %s! Cause: "
                            "Domain installation was unsuccessful!" % domain)
                continue
            # If the domain manager does not poll the domain update here
            # else polling takes care of domain updating
            if isinstance(domain_mgr,
                          AbstractRemoteDomainManager) and domain_mgr._poll:
                log.info("Skip explicit DoV update for domain: %s. "
                         "Cause: polling enabled!" % domain)
                continue
            # If the internalDM is the only initiated mgr, we can override the
            # whole DoV
            if domain_mgr.IS_LOCAL_MANAGER:
                if mapped_nffg.is_SBB():
                    # If the request was a cleanup request, we can simply clean the DOV
                    if mapped_nffg.is_bare():
                        log.debug(
                            "Detected cleanup topology (no NF/Flowrule/SG_hop)! Clean DoV..."
                        )
                        self.DoVManager.clean_domain(domain=domain)
                    # If the reset contains some VNF, cannot clean or override
                    else:
                        log.warning(
                            "Detected SingleBiSBiS topology! Local domain has been already "
                            "cleared, skip DoV update...")
                # If the the topology was a GLOBAL view, just override the whole DoV
                elif not mapped_nffg.is_virtualized():
                    self.DoVManager.set_global_view(nffg=mapped_nffg)
                else:
                    log.warning(
                        "Detected virtualized Infrastructure node in mapped NFFG! Skip "
                        "DoV update...")
                # In case of Local manager skip the rest of the update
                continue
            # Explicit domain update
            self.DoVManager.update_domain(domain=domain, nffg=part)
        log.debug("NF-FG installation is finished by %s" %
                  self.__class__.__name__)
        # Post-mapping steps
        if mapping_result:
            log.info(
                "All installation process has been finished with success! ")
            # Notify remote visualizer about the installation result if it's needed
            notify_remote_visualizer(
                data=self.DoVManager.dov.get_resource_info(), id=LAYER_NAME)
        else:
            log.error("%s installation was not successful!" % mapped_nffg)
        return mapping_result
예제 #13
0
파일: domain.py 프로젝트: hsnlab/fero
    def poll(self):
        """
    Poll the defined domain agent. Handle different connection errors and go
    to slow/rapid poll. When an agent is (re)detected update the current
    resource information.

    :return: None
    """
        # If domain is not detected
        if not self._detected:
            # Check the topology is reachable
            if self._detect_topology():
                # Domain is detected and topology is updated -> restart domain polling
                self.restart_polling()
                # Notify all components for topology change --> this event causes
                # the DoV updating
                self.raiseEventNoErrors(
                    DomainChangedEvent,
                    domain=self.domain_name,
                    data=self.internal_topo,
                    cause=DomainChangedEvent.TYPE.DOMAIN_UP)
                return
        # If domain has already detected
        else:
            # Check the domain is still reachable
            changed = self.topoAdapter.check_topology_changed()
            # No changes
            if changed is False:
                # Nothing to do
                log.log(
                    VERBOSE,
                    "Remote domain: %s has not changed!" % self.domain_name)
                return
            # Domain has changed
            elif isinstance(changed, NFFG):
                log.info(
                    "Remote domain: %s has changed. Update global domain view..."
                    % self.domain_name)
                log.debug("Save changed topology: %s" % changed)
                # Update the received new topo
                self.internal_topo = changed
                # Notify all components for topology change --> this event causes
                # the DoV updating
                self.raiseEventNoErrors(
                    DomainChangedEvent,
                    domain=self.domain_name,
                    data=self.internal_topo,
                    cause=DomainChangedEvent.TYPE.DOMAIN_CHANGED)
                return
            # If changed is None something went wrong, probably remote domain is not
            # reachable. Step to the other half of the function
            elif changed is None:
                log.warning(
                    "Lost connection with %s agent! Going to slow poll..." %
                    self.domain_name)
                # Clear internal topology
                log.debug("Clear topology from domain: %s" % self.domain_name)
                self.internal_topo = None
                self.raiseEventNoErrors(
                    DomainChangedEvent,
                    domain=self.domain_name,
                    cause=DomainChangedEvent.TYPE.DOMAIN_DOWN)
            else:
                log.warning(
                    "Got unexpected return value from check_topology_changed(): %s"
                    % type(changed))
                return
        # If this is the first call of poll()
        if self._detected is None:
            log.warning(
                "Local agent in domain: %s is not detected! Keep trying..." %
                self.domain_name)
            self._detected = False
        elif self._detected:
            # Detected before -> lost connection = big Problem
            self._detected = False
            self.restart_polling()
        else:
            # No success but not for the first try -> keep trying silently
            pass