def metadata(self, resource_type: str, os_id: str) -> PolicyResourceMeta:
        if resource_type == Provider.SG_RULES:
            with LockManager.get_lock(Provider.SG_RULES):
                meta = self._metadata[Provider.SG_RULES].meta.get(os_id)
                if meta:
                    if not meta.rules:
                        meta.rules = self._fetch_rules_from_nsx(meta)
                return meta

        with LockManager.get_lock(resource_type):
            return self._metadata[resource_type].meta.get(os_id)
    def metadata(self, resource_type, os_id) -> ResourceMeta:
        if resource_type == Provider.SG_RULE:
            with LockManager.get_lock(Provider.SG_RULES):
                meta = self._metadata[Provider.SG_RULES].meta.get(os_id)
                if meta:
                    rules = self.client.get_all(API.RULES.format(meta.id))
                    meta = {Resource(o).os_id: o for o in rules}
                return meta

        with LockManager.get_lock(resource_type):
            return self._metadata[resource_type].meta.get(os_id)
Example #3
0
 def wrapper(self, *args, **kwargs):
     with LockManager.get_lock(API.MIGR_UNIT):
         initiated = False
         try:
             m_data: Payload.MigrationData = build_migr_data_func(
                 self, *args, **kwargs)
             json_migdata = m_data.json() if m_data else None
             if not json_migdata:
                 LOG.warn(
                     "No migration data provided. Migration skiped.")
                 return
             self._initiate_migration()
             initiated = True
             self._set_migration(migr_data=json_migdata)
             self._start_migration(migr_data=json_migdata)
             LOG.debug("Pre-checking migration ...")
             self._precheck_migration(migr_data=json_migdata)
             self._continue_migration(migr_data=json_migdata)
             LOG.debug("Post-checking migration ...")
             self._await_migration(migr_data=json_migdata)
             LOG.info("Migration completed.")
         finally:
             if initiated:
                 self._end_migration()
         return m_data
Example #4
0
    def security_group_members(self, os_id: str, reference=False):
        """
        Realize security group members state.
        Realization will happen only if the group has active ports on the host
        or if it used as remote security group by a group having such ports.
        :os_id: -- OpenStack ID of the Security Group
        :reference: -- if True will create the group if unknown by the provider
        """
        with LockManager.get_lock("member-{}".format(os_id)):
            pp = self.plcy_provider
            meta = pp.metadata(pp.SG_MEMBERS, os_id)
            if not (reference and meta):
                if self.rpc.has_security_group_used_by_host(os_id):
                    cidrs = self.rpc.get_security_group_members_effective_ips(
                        os_id)
                    port_ids = set(self.rpc.get_security_group_port_ids(os_id))

                    segment_ports = pp.get_port_meta_by_ids(port_ids)
                    paths = [p.path for p in segment_ports]

                    # SG Members are not revisionable, use default "0"
                    pp.sg_members_realize({
                        "id": os_id,
                        "cidrs": cidrs,
                        "revision_number": "0",
                        "member_paths": paths
                    })
                else:
                    pp.sg_members_realize({"id": os_id}, delete=True)
Example #5
0
    def _login(self):
        LOG.info("Session token - acquiring")
        now = int(time.time())
        with LockManager.get_lock(self._base_path):
            if now > self._login_timestamp:
                resp = requests.post(
                    **self._params(path=self._login_path,
                                   data=self._login_data,
                                   verify=self._session.verify))

                resp.raise_for_status()

                self._session.headers["Cookie"] = \
                    resp.headers.get("Set-Cookie")
                self._session.headers["X-XSRF-TOKEN"] = \
                    resp.headers.get("X-XSRF-TOKEN")
                self._session.headers["Accept"] = "application/json"
                self._session.headers["Content-Type"] = "application/json"

                self._login_timestamp = int(time.time())

        try:
            # Refresh version after login
            self.version(refresh=True)
        except Exception:
            pass
        LOG.info("Session token - acquired, connected to NSX-T {}".format(
            self._version))
Example #6
0
    def security_group_rules(self, os_id: str):
        """
        Realize security group rules state.
        Realization will happen only if the group has active ports on the host.
        :os_id: -- OpenStack ID of the Security Group
        """
        with LockManager.get_lock("rules-{}".format(os_id)):
            os_sg = self.rpc.get_security_group(os_id)

            if os_sg and os_sg.get("ports"):
                # Create Members Container
                self.security_group_members(os_id, reference=True)

                os_sg["rules"] = self.rpc.get_rules_for_security_group_id(
                    os_id)

                for os_rule in os_sg["rules"]:
                    remote_id = os_rule.get("remote_group_id")
                    if remote_id:
                        self.security_group_members(remote_id, reference=True)

                logged = self.rpc.has_security_group_logging(os_id)
                LOG.info(
                    f"Neutron DB logged flag for {os_id}: rpc.has_security_group_logging(os_id): {logged}"
                )
                self.plcy_provider.sg_rules_realize(os_sg, logged=logged)

            else:
                self.plcy_provider.sg_rules_realize({"id": os_id}, delete=True)
    def metadata_refresh(self, resource_type, params=dict()):
        provider = self._metadata[resource_type]
        with provider.meta:
            LOG.info("[%s] Fetching Policy NSX-T metadata for Type:%s.",
                     self.provider, resource_type)
            endpoint = provider.endpoint
            if resource_type == Provider.SEGM_PORT:
                endpoint = API.SEARCH_QUERY
                params = API.SEARCH_Q_SEG_PORTS
            if resource_type == Provider.SEGM_QOS:
                endpoint = API.SEARCH_QUERY
                params = API.SEARCH_Q_QOS_PROFILES
            resources = self.client.get_all(path=endpoint, params=params)
            with LockManager.get_lock(resource_type):
                provider.meta.reset()
                for o in resources:
                    res = Resource(o)
                    if not res.is_managed:
                        continue
                    if resource_type == Provider.SG_RULES and not res.has_valid_os_uuid:
                        continue
                    if resource_type == Provider.SG_MEMBERS and NSXV3_REVISION_SCOPE not in res.tags:
                        continue
                    if resource_type == Provider.SG_RULES_REMOTE_PREFIX and NSXV3_REVISION_SCOPE in res.tags:
                        continue
                    if resource_type == Provider.SEGM_PORT and not self._is_valid_vlan(
                            res):
                        continue

                    provider.meta.add(res)
 def metadata_update(self, resource_type,
                     provider_object) -> PolicyResourceMeta:
     if resource_type != Provider.SG_RULE:
         with LockManager.get_lock(resource_type):
             res = Resource(provider_object)
             self._metadata[resource_type].meta.update(res)
             return res.meta
Example #9
0
 def update_policy_logging(self, log_obj: dict):
     """
     Realize security policy logging state update.
     :os_seg_id: -- OpenStack Security Group ID
     :return: -- None
     """
     with LockManager.get_lock("rules-{}".format(log_obj['resource_id'])):
         self.plcy_provider.update_policy_logging(log_obj)
 def get_port_meta_by_ids(self,
                          port_ids: Set[str]) -> Set[PolicyResourceMeta]:
     segment_ports = set()
     with LockManager.get_lock(self.SEGM_PORT):
         keys = set(self._metadata[self.SEGM_PORT].meta.keys())
         segment_ports.update([
             self._metadata[self.SEGM_PORT].meta.meta.get(id)
             for id in keys.intersection(port_ids)
         ])
     return segment_ports
Example #11
0
 def network(self, os_seg_id: str):
     """
     Realize Network state.
     :os_seg_id: -- OpenStack Network Segmentation ID
     :return: -- provider ID for the network
     """
     with LockManager.get_lock("network-{}".format(os_seg_id)):
         meta = self._network_realize(os_seg_id)
         return {
             "nsx-logical-switch-id": meta.id,
             "external-id": meta.id,
             "segmentation_id": os_seg_id
         }
Example #12
0
 def check_service_availability(self):
     with LockManager.get_lock(API.MIGR_UNIT):
         try:
             self.client.post(path=API.MP_TO_POLICY,
                              data={}).raise_for_status()
             self.client.post(path=API.MIGRATION_ABORT,
                              data=None).raise_for_status()
             stat = self.client.get(path=API.SERVICE_STATUS)
             srvc_stat = stat.json()
             if not srvc_stat or not srvc_stat.get("enabled"):
                 raise RuntimeError(f"{stat.content}")
         except Exception as e:
             raise RuntimeError(
                 f"MP-TO-POLICY API not enabled or service down. ({e})")
Example #13
0
 def port(self, os_id: str):
     """
     Realize port state.
     :os_id: -- OpenStack ID of the Port
     """
     with LockManager.get_lock("port-{}".format(os_id)):
         port: dict = self.rpc.get_port(os_id)
         if port:
             os_qid = port.get("qos_policy_id")
             if os_qid:
                 self.qos(os_qid, reference=True)
             self._port_realize(port)
         else:
             self._port_realize({"id": os_id}, delete=True)
Example #14
0
    def precreate_port(self, os_id: str, network_meta: dict):
        """
        Try to precreate port on first binding request.
        :os_id: -- OpenStack ID of the Port
        :network_meta: -- NSX Switch metadata
        """
        with LockManager.get_lock("port-{}".format(os_id)):
            port: dict = self.rpc.get_port(os_id)
            if port:
                os_qid = port.get("qos_policy_id")
                if os_qid:
                    self.qos(os_qid, reference=True)

                if not port.get("vif_details") and network_meta:
                    port["vif_details"] = network_meta

                self._port_realize(port)
 def realize_sg_members_after_port_realization(
         self, port_sgs: List[str], port_meta: PolicyResourceMeta):
     for sg_id in port_sgs:
         with LockManager.get_lock("member-{}".format(sg_id)):
             sg_meta = self.metadata(self.SG_MEMBERS, sg_id)
             if not sg_meta:
                 raise RuntimeError(
                     f"Not found SG Metadata for security_group: {sg_id}")
             if not port_meta.path:
                 raise RuntimeError(
                     f"Not found path in Metadata for port: {port_meta.id}")
             if port_meta.path not in sg_meta.sg_members:
                 sg_meta.sg_members.append(port_meta.path)
                 self.sg_members_realize({
                     "id": sg_id,
                     "cidrs": sg_meta.sg_cidrs,
                     "member_paths": sg_meta.sg_members,
                     "revision_number": "0"
                 })
Example #16
0
 def qos(self, os_id: str, reference=False):
     """
     Realize QoS Policy state.
     :os_id: -- OpenStack ID of the QoS Policy
     :reference: -- If True will create policy if unknown by the provider
     """
     with LockManager.get_lock("qos-{}".format(os_id)):
         plcy_meta = self.plcy_provider.metadata(
             self.plcy_provider.SEGM_QOS, os_id)
         mgr_meta = self.mngr_provider.metadata(self.mngr_provider.QOS,
                                                os_id)
         if not (reference and mgr_meta):
             qos = self.rpc.get_qos(os_id)
             if qos:
                 self._qos_realize(os_qos=qos,
                                   is_plcy=bool(plcy_meta),
                                   is_mngr=bool(mgr_meta))
             else:
                 self._qos_realize(os_qos={"id": os_id},
                                   is_plcy=bool(plcy_meta),
                                   is_mngr=bool(mgr_meta),
                                   delete=True)
Example #17
0
    def _get_sg_provider_rule(self, os_rule: dict, revision: int) -> dict:
        provider_rule = dict()
        if os_rule.get("remote_ip_prefix"):
            net = netaddr.IPNetwork(os_rule["remote_ip_prefix"],
                                    flags=netaddr.NOHOST)
            meta_addr = [netaddr.IPAddress("0.0.0.0"), netaddr.IPAddress("::")]
            if net.ip in meta_addr:
                cidr = str(net)
                with LockManager.get_lock(cidr):
                    meta = self.metadata(Provider.SG_RULES_REMOTE_PREFIX, cidr)
                    if not meta:
                        o = self._create_sg_provider_rule_remote_prefix(cidr)
                        meta = self.metadata_update(
                            Provider.SG_RULES_REMOTE_PREFIX, o)
                provider_rule["remote_ip_prefix_id"] = meta.id
        elif os_rule.get("remote_group_id"):
            meta = self.metadata(Provider.SG_MEMBERS,
                                 os_rule["remote_group_id"])
            if meta:
                provider_rule["remote_group_id"] = meta.id

        provider_rule["_revision"] = revision
        return provider_rule
    def metadata_refresh(self, resource_type, params=dict()):

        if resource_type != Provider.SG_RULE:
            provider = self._metadata[resource_type]
            with provider.meta:
                LOG.info("[%s] Fetching NSX-T metadata for Type:%s.", self.provider, resource_type)
                if provider.endpoint == API.PROFILES:
                    params = API.PARAMS_GET_QOS_PROFILES
                resources = self.client.get_all(path=provider.endpoint, params=params)
                with LockManager.get_lock(resource_type):
                    provider.meta.reset()
                    for o in resources:
                        res = Resource(o)
                        if not res.is_managed:
                            continue
                        if resource_type == Provider.SG_MEMBERS:
                            if NSXV3_REVISION_SCOPE not in res.tags:
                                continue
                        if resource_type == Provider.SG_RULES_REMOTE_PREFIX:
                            if NSXV3_REVISION_SCOPE in res.tags:
                                continue
                        if resource_type == Provider.SG_RULES:
                            if not res.has_valid_os_uuid:
                                continue
                        if resource_type == Provider.PORT:
                            # Ensure this port is attached to a agent managed
                            # logical switch, else skip it
                            is_valid_vlan = False
                            for name, ls in self._metadata[Provider.NETWORK].meta.meta.items():
                                if ls.id == res.resource.get("logical_switch_id") and name.isnumeric():
                                    is_valid_vlan = True
                                    break
                            if not is_valid_vlan:
                                continue

                        provider.meta.add(res)
Example #19
0
    def all(self, dryrun=False):
        """
        Enforce desired state between OpenStack and Provider objects
        Objects concidered outdated include new, updated or removed

        :force: bool -- if True concider all objects as outdated
        """
        with LockManager.get_lock("all"):
            if self.kpi().get("passive") > 0:
                return

            _slice = cfg.CONF.AGENT.synchronization_queue_size
            pp = self.plcy_provider
            mp = self.mngr_provider
            r = self.rpc

            port_meta = self._os_meta(r.get_ports_with_revisions)
            sg_meta = self._os_meta(r.get_security_groups_with_revisions)
            qos_meta = self._os_meta(r.get_qos_policies_with_revisions)

            # Force networks refresh, only
            mp.metadata_refresh(mp.NETWORK)
            pp.metadata_refresh(pp.SEGMENT)

            # Refresh entire metadata with its latest state
            LOG.info("Inventory metadata is going to be refreshed.")
            seg_port_outdated, seg_port_current = pp.outdated(
                pp.SEGM_PORT, port_meta)
            port_outdated, port_current = mp.outdated(mp.PORT, port_meta)
            sgr_outdated, sgr_current = pp.outdated(pp.SG_RULES, sg_meta)
            qos_outdated, qos_current = mp.outdated(mp.QOS, qos_meta)
            seg_qos_outdated, seg_qos_current = pp.outdated(
                pp.SEGM_QOS, qos_meta)

            # Remove duplicated policy/manager objects
            seg_port_outdated = seg_port_outdated.difference(port_outdated)
            seg_port_current = seg_port_current.difference(port_current)
            seg_qos_outdated = seg_qos_outdated.difference(qos_outdated)
            seg_qos_current = seg_qos_current.difference(qos_current)

            # There is not way to revision group members but can 'age' them
            sgm_outdated, sgm_maybe_orphans = pp.outdated(
                pp.SG_MEMBERS, {sg: 0
                                for sg in sg_meta})
            LOG.info("Inventory metadata have been refreshed.")

            if dryrun:
                LOG.info("Dryrun:%s. Metadata refresh completed.", dryrun)
                return

            # Don't count ports into synchronization limit, since they could exhaust the worker queue
            # and cause the agent to be stuck.
            outdated = list(itertools.islice(port_outdated, _slice))
            _slice -= len(outdated)
            LOG.info("Realizing %s/%s resources of Type:Ports", len(outdated),
                     len(port_outdated))
            self.callback(outdated, self.port)
            if _slice <= 0:
                return

            outdated = list(itertools.islice(seg_port_outdated, _slice))
            _slice -= len(outdated)
            LOG.info("Realizing %s/%s resources of Type:SegmentPorts",
                     len(outdated), len(seg_port_outdated))
            self.callback(outdated, self.port)
            if _slice <= 0:
                return

            outdated = list(itertools.islice(sgr_outdated, _slice))
            _slice -= len(outdated)
            LOG.info("Realizing %s/%s resources of Type:Security Group Rules",
                     len(outdated), len(sgr_outdated))
            self.callback(outdated, self.security_group_rules)
            if _slice <= 0:
                return

            # sgm_outdated only includes missing objects, orphans are removed by ageing
            outdated = list(itertools.islice(sgm_outdated, _slice))
            _slice -= len(outdated)
            LOG.info(
                "Realizing %s/%s resources of Type:Security Group Members",
                len(outdated), len(sgm_outdated))
            self.callback(outdated, self.security_group_members)
            if _slice <= 0:
                return

            outdated = list(itertools.islice(qos_outdated, _slice))
            _slice -= len(outdated)
            LOG.info("Realizing %s/%s resources of Type:QoS", len(outdated),
                     len(qos_outdated))
            self.callback(outdated, self.qos)
            if _slice <= 0:
                return

            outdated = list(itertools.islice(seg_qos_outdated, _slice))
            _slice -= len(outdated)
            LOG.info("Realizing %s/%s resources of Type:SegmentQoS",
                     len(outdated), len(seg_qos_outdated))
            self.callback(outdated, self.qos)
            if _slice <= 0:
                return

            return self._age_cycle(_slice, seg_port_current, port_current,
                                   sgr_current, seg_qos_current, qos_current,
                                   sgm_maybe_orphans)
 def metadata_delete(self, resource_type, os_id):
     if resource_type != Provider.SG_RULE:
         with LockManager.get_lock(resource_type):
             self._metadata[resource_type].meta.rm(os_id)
 def metadata_delete(self, resource_type: str, os_id: str) -> None:
     with LockManager.get_lock(resource_type):
         self._metadata[resource_type].meta.rm(os_id)