Пример #1
0
 def interface_classification(self, iface):
     """
     Perform interface classification
     :param iface: Interface instance
     :return:
     """
     if iface.profile_locked:
         return
     try:
         p_id = self.get_interface_profile(iface)
     except NotImplementedError:
         self.logger.error("Uses not implemented rule")
         return
     if p_id and p_id != iface.profile.id:
         # Change profile
         profile = InterfaceProfile.get_by_id(p_id)
         if not profile:
             self.logger.error(
                 "Invalid interface profile '%s' for interface '%s'. "
                 "Skipping",
                 p_id,
                 iface.name,
             )
             return
         elif profile != iface.profile:
             self.logger.info("Interface %s has been classified as '%s'",
                              iface.name, profile.name)
             iface.profile = profile
             iface.save()
Пример #2
0
 def migrate(self):
     collections = [InterfaceProfile._get_collection()]
     for collection in collections:
         bulk = []
         for ip in collection.find({"metrics.is_active": {
                 "$exists": True
         }}):
             metrics = []
             if "metrics" not in ip:
                 continue  # Not configured
             for metric in ip["metrics"]:
                 metric["enable_periodic"] = bool(
                     metric.get("is_active", False))
                 metric["enable_box"] = False
                 if "is_active" in metric:
                     del metric["is_active"]
                 metrics += [metric]
             bulk += [
                 UpdateOne({"_id": ip["_id"]},
                           {"$set": {
                               "metrics": metrics
                           }})
             ]
         if bulk:
             collection.bulk_write(bulk)
Пример #3
0
 def _get_interface(iface, subs, links, ifcache):
     r = {
         "name": qs(iface["name"]),
         "type": iface["type"],
         "description": qs(iface.get("description")),
         "enabled_protocols": iface.get("enabled_protocols") or [],
         "admin_status": iface.get("admin_status", False),
     }
     if iface.get("ifindex"):
         r["snmp_ifindex"] = iface["ifindex"]
     if iface.get("mac"):
         r["mac"] = iface["mac"]
     if iface.get("aggregated_interface"):
         r["aggregated_interface"] = ifcache[
             iface["aggregated_interface"]][-1]
     # Apply profile
     if iface.get("profile"):
         profile = InterfaceProfile.get_by_id(iface["profile"])
         r["profile"] = ManagedObjectDataStream._get_interface_profile(
             profile)
     # Apply subinterfaces
     r["subinterfaces"] = [
         ManagedObjectDataStream._get_subinterface(s)
         for s in sorted(subs, key=lambda x: alnum_key(x["name"]))
     ]
     # Apply links
     if links:
         r["link"] = ManagedObjectDataStream._get_link(
             iface, links, ifcache)
     return r
Пример #4
0
 def handle_apply(self, moo, *args, **kwargs):
     # sol = config.get("interface_discovery", "get_interface_profile")
     # @todo Classification pyrule
     get_profile = None
     if not get_profile:
         get_profile = InterfaceClassificationRule
         get_profile = get_profile.get_classificator()
         # raise CommandError("No classification solution")
     pcache = {}
     for o in self.get_objects(moo):
         self.stdout.write(
             "%s (%s):\n" %
             (o.name, o.platform.name if o.platform else o.profile.name))
         ifaces = self.get_interfaces(o)
         if not ifaces:
             self.stdout.write("No ifaces on object\n")
             continue
         tps = self.get_interface_template(ifaces)
         for i in ifaces:
             if not i.profile or not i.profile_locked:
                 pn = get_profile(i)
                 if pn:
                     p = pcache.get(pn)
                     if not p:
                         p = InterfaceProfile.get_by_id(pn)
                         pcache[pn] = p
                     i.profile = p
                     i.save()
                     v = "Set %s" % p.name
                 else:
                     v = "Not matched"
                 self.show_interface(tps, i, v)
Пример #5
0
 def get_interface_profile_metrics(cls, p_id):
     r = {}
     ipr = InterfaceProfile.get_by_id(id=p_id)
     if not ipr:
         return r
     for m in ipr.metrics:
         r[m.metric_type.name] = cls.config_from_settings(m)
     return r
Пример #6
0
 def get_interface_metrics(self):
     """
     Populate metrics list with interface metrics
     :return:
     """
     subs = None
     metrics = []
     for i in (Interface._get_collection().with_options(
             read_preference=ReadPreference.SECONDARY_PREFERRED).find(
                 {
                     "managed_object": self.object.id,
                     "type": "physical"
                 },
                 {
                     "_id": 1,
                     "name": 1,
                     "ifindex": 1,
                     "profile": 1
                 },
             )):
         ipr = self.get_interface_profile_metrics(i["profile"])
         self.logger.debug("Interface %s. ipr=%s", i["name"], ipr)
         if not ipr:
             continue  # No metrics configured
         i_profile = InterfaceProfile.get_by_id(i["profile"])
         if i_profile.allow_subinterface_metrics and subs is None:
             # Resolve subinterfaces
             subs = self.get_subinterfaces()
         ifindex = i.get("ifindex")
         for metric in ipr:
             if (self.is_box and not ipr[metric].enable_box) or (
                     self.is_periodic and not ipr[metric].enable_periodic):
                 continue
             m_id = next(self.id_count)
             m = {
                 "id": m_id,
                 "metric": metric,
                 "path": ["", "", "", i["name"]]
             }
             if ifindex is not None:
                 m["ifindex"] = ifindex
             metrics += [m]
             self.id_metrics[m_id] = ipr[metric]
             if i_profile.allow_subinterface_metrics:
                 for si in subs[i["_id"]]:
                     m_id = next(self.id_count)
                     m = {
                         "id": m_id,
                         "metric": metric,
                         "path": ["", "", "", i["name"], si["name"]],
                     }
                     if si["ifindex"] is not None:
                         m["ifindex"] = si["ifindex"]
                     metrics += [m]
                     self.id_metrics[m_id] = ipr[metric]
     if not metrics:
         self.logger.info("Interface metrics are not configured. Skipping")
     return metrics
Пример #7
0
 def handle_apply_confdb(self, moo, *args, **kwargs):
     default_profile = InterfaceProfile.get_default_profile()
     for o in self.get_objects(moo):
         self.stdout.write(
             "%s (%s):\n" %
             (o.name, o.platform.name if o.platform else o.profile.name))
         ifmap = {i.name: i for i in self.get_interfaces(o)}
         if not ifmap:
             self.stdout.write("No ifaces on object\n")
             continue
         tps = self.get_interface_template(ifmap.values())
         proccessed = set()
         selectors_skipping = set()  # if selectors has not match
         cdb = o.get_confdb()
         ifprofilemap = {}
         for icr in InterfaceClassificationRule.objects.filter(
                 is_active=True).order_by("order"):
             if icr.selector.id in selectors_skipping:
                 continue
             r = next(cdb.query(icr.selector.get_confdb_query), None)
             if r is None:
                 # Selectors already fail check
                 selectors_skipping.add(icr.selector.id)
                 continue
             self.print("[%s] Check selector" % icr)
             for match in cdb.query(icr.get_confdb_query):
                 if match["ifname"] in proccessed or match[
                         "ifname"] not in ifmap:
                     continue
                 self.print("[%s] Match %s" % (icr, match["ifname"]))
                 iface = ifmap[match["ifname"]]
                 proccessed.add(match["ifname"])
                 if iface.profile_locked:
                     continue
                 ifprofilemap[iface.name] = icr.profile
         # Set profile
         for ifname in ifmap:
             i = ifmap[ifname]
             if ifname in ifprofilemap and i.profile.id != ifprofilemap[
                     ifname].id:
                 i.profile = ifprofilemap[ifname]
                 i.save()
                 v = "Set %s" % ifprofilemap[ifname].name
             elif ifname in ifprofilemap and i.profile.id == ifprofilemap[
                     ifname].id:
                 v = "Already set %s" % ifprofilemap[ifname].name
             else:
                 v = "Not matched"
                 if kwargs.get(
                         "reset_default") and i.profile != default_profile:
                     i.profile = default_profile
                     i.save()
                     v = "Not matched. Reset to default"
             self.show_interface(tps, i, v)
Пример #8
0
 def handle_reset(self, moo, *args, **kwargs):
     for o in self.get_objects(moo):
         self.stdout.write(
             "%s (%s):\n" %
             (o.name,
              (o.platform.name if o.platform else None) or o.profile.name))
         for i in Interface.objects.filter(managed_object=o.id):
             if i.profile:
                 self.stdout.write(
                     "    resetting profile on %s to default\n" % i.name)
                 i.profile = InterfaceProfile.get_default_profile()
                 i.save()
Пример #9
0
class Command(BaseCommand):
    help = "Show Links"
    def_iface_prof = InterfaceProfile.get_by_name("default")

    def add_arguments(self, parser):
        subparsers = parser.add_subparsers(dest="cmd")
        # extract command
        show_parser = subparsers.add_parser("show",
                                            help="Show interface profiles")
        show_parser.add_argument("mos",
                                 nargs=argparse.REMAINDER,
                                 help="List of object to showing")
        # clean command
        reset_parser = subparsers.add_parser("reset",
                                             help="Reset interface profile")
        reset_parser.add_argument("mos",
                                  nargs=argparse.REMAINDER,
                                  help="List of object to showing")
        # load command
        apply_parser = subparsers.add_parser("apply",
                                             help="Apply classification rules")
        apply_parser.add_argument("mos",
                                  nargs=argparse.REMAINDER,
                                  help="List of object to showing")

    def handle(self, cmd, *args, **options):
        if "mos" in options:
            moo = options["mos"]
        else:
            self.stdout.write("No ManagedObject for proccessed")
            self.die("No ManagedObject for proccessed")
            return False
        return getattr(self, "handle_%s" % cmd)(moo, *args, **options)

    @staticmethod
    def get_objects(exprs):
        objects = set()
        for s in exprs:
            objects.update(ManagedObjectSelector.resolve_expression(s))
        return sorted(objects, key=lambda x: x.name)

    @staticmethod
    def get_interfaces(mo):
        return sorted(Interface.objects.filter(managed_object=mo.id,
                                               type="physical"),
                      key=split_alnum)

    @staticmethod
    def get_interface_template(interfaces):
        il = max(len(i.name) for i in interfaces)
        il = max(il, 15)
        tps = "    %%-%ds  %%-12s  %%-30s  %%s\n" % il
        return tps

    def show_interface(self, tpl, i, status):
        if i.description:
            d = i.description[:30]
        else:
            d = ""
        self.stdout.write(tpl % (i.name, i.status, d, status))

    def handle_show(self, moo, *args, **options):
        for o in self.get_objects(moo):
            self.stdout.write(
                "%s (%s):\n" %
                (o.name,
                 (o.platform.name if o.platform else None) or o.profile.name))
            ifaces = self.get_interfaces(o)
            if not ifaces:
                self.stdout.write("No ifaces on object\n")
                continue
            tps = self.get_interface_template(ifaces)
            for i in ifaces:
                self.show_interface(tps, i,
                                    i.profile.name if i.profile else "-")

    def handle_reset(self, moo, *args, **kwargs):
        for o in self.get_objects(moo):
            self.stdout.write(
                "%s (%s):\n" %
                (o.name,
                 (o.platform.name if o.platform else None) or o.profile.name))
            for i in Interface.objects.filter(managed_object=o.id):
                if i.profile:
                    self.stdout.write(
                        "    resetting profile on %s to default\n" % i.name)
                    i.profile = self.def_iface_prof
                    i.save()

    def handle_apply(self, moo, *args, **kwargs):
        # sol = config.get("interface_discovery", "get_interface_profile")
        # @todo Classification pyrule
        get_profile = None
        if not get_profile:
            get_profile = InterfaceClassificationRule
            get_profile = get_profile.get_classificator()
            # raise CommandError("No classification solution")
        pcache = {}
        for o in self.get_objects(moo):
            self.stdout.write(
                "%s (%s):\n" %
                (o.name, o.platform.name if o.platform else o.profile.name))
            ifaces = self.get_interfaces(o)
            if not ifaces:
                self.stdout.write("No ifaces on object\n")
                continue
            tps = self.get_interface_template(ifaces)
            for i in ifaces:
                if not i.profile or not i.profile_locked:
                    pn = get_profile(i)
                    if pn:
                        p = pcache.get(pn)
                        if not p:
                            p = InterfaceProfile.get_by_id(pn)
                            pcache[pn] = p
                        i.profile = p
                        i.save()
                        v = "Set %s" % p.name
                    else:
                        v = "Not matched"
                    self.show_interface(tps, i, v)
Пример #10
0
 def handler(self):
     self.logger.info("NRI Service Mapper")
     if not self.object.remote_system:
         self.logger.info(
             "Created directly. No NRI integration. Skipping check")
         return
     if not self.object.remote_system.enable_service:
         self.logger.info(
             "NRI does not provide link information. Skipping check")
         return
     # Check object has interfaces
     if not self.has_capability("DB | Interfaces"):
         self.logger.info(
             "No interfaces discovered. Skipping interface status check")
         return
     # Get services related to Managed object
     scol = Service._get_collection()
     slist = [
         s for s in scol.find(
             {
                 "managed_object": self.object.id,
                 "nri_port": {
                     "$exists": True
                 }
             },
             {
                 "_id": 1,
                 "nri_port": 1,
                 "profile": 1
             },
         )
     ]
     # nri_port -> service_id
     smap = {s["nri_port"]: s["_id"] for s in slist}
     # service id -> service profile
     prof_map = {
         s["_id"]: ServiceProfile.get_by_id(s["profile"])
         for s in slist
     }
     icol = Interface._get_collection()
     nmap = {}
     bulk = []
     for i in icol.find({
             "managed_object": self.object.id,
             "nri_name": {
                 "$exists": True
             }
     }):
         if not i.get("nri_name"):
             continue
         if i["nri_name"] in smap:
             svc = smap[i["nri_name"]]
             p = prof_map.get(svc)
             if svc != i.get("service"):
                 self.logger.info("Binding service %s to interface %s", svc,
                                  i["name"])
                 op = {"service": svc}
                 if p and p.interface_profile:
                     op["profile"] = p.interface_profile.id
                 bulk += [UpdateOne({"_id": i["_id"]}, {"$set": op})]
             elif p and p.interface_profile and p.interface_profile.id != i[
                     "profile"]:
                 self.logger.info("Replace profile to %s on intertace %s",
                                  p.interface_profile, i["name"])
                 bulk += [
                     UpdateOne(
                         {"_id": i["_id"]},
                         {"$set": {
                             "profile": p.interface_profile.id
                         }})
                 ]
             del smap[i["nri_name"]]
         elif i.get("service"):
             self.logger.info("Removing service %s from interface %s",
                              i["service"], i["name"])
             op = {"$unset": {"service": ""}}
             if i["service"] in prof_map:
                 op["$set"] = {
                     "profile": InterfaceProfile.get_default_profile().id
                 }
             bulk += [UpdateOne({"_id": i["_id"]}, op)]
         nmap[i["nri_name"]] = i
     # Report hanging interfaces
     for n in smap:
         svc = smap[n]
         if n not in nmap:
             self.logger.info(
                 "Cannot bind service %s. Cannot find NRI interface %s",
                 svc, n)
             continue
         i = nmap[n]
         self.logger.info("Binding service %s to interface %s", svc,
                          i["name"])
         op = {"service": svc}
         p = prof_map.get(svc)
         if p:
             op["profile"] = p.interface_profile.id
         bulk += [UpdateOne({"_id": i["_id"]}, {"$set": op})]
     if bulk:
         self.logger.info("Sending %d updates", len(bulk))
         icol.bulk_write(bulk)
         ServiceSummary.refresh_object(self.object.id)
         change_tracker.register([("managedobject", self.object.id)])
Пример #11
0
 def get_interface_metrics(self):
     """
     Populate metrics list with interface metrics
     :return:
     """
     # @todo: Inject Interface.effective_labels
     subs = None
     metrics = []
     for i in (
         Interface._get_collection()
         .with_options(read_preference=ReadPreference.SECONDARY_PREFERRED)
         .find(
             {"managed_object": self.object.id, "type": "physical"},
             {
                 "_id": 1,
                 "name": 1,
                 "ifindex": 1,
                 "profile": 1,
                 "in_speed": 1,
                 "out_speed": 1,
                 "bandwidth": 1,
             },
         )
     ):
         ipr = self.get_interface_profile_metrics(i["profile"])
         self.logger.debug("Interface %s. ipr=%s", i["name"], ipr)
         if not ipr:
             continue  # No metrics configured
         i_profile = InterfaceProfile.get_by_id(i["profile"])
         if i_profile.allow_subinterface_metrics and subs is None:
             # Resolve subinterfaces
             subs = self.get_subinterfaces()
         ifindex = i.get("ifindex")
         for metric in ipr:
             if (self.is_box and not ipr[metric].enable_box) or (
                 self.is_periodic and not ipr[metric].enable_periodic
             ):
                 continue
             m_id = next(self.id_count)
             m = {"id": m_id, "metric": metric, "labels": [f"noc::interface::{i['name']}"]}
             if ifindex is not None:
                 m["ifindex"] = ifindex
             metrics += [m]
             self.id_metrics[m_id] = ipr[metric]
             if i_profile.allow_subinterface_metrics:
                 for si in subs[i["_id"]]:
                     if si["name"] != i["name"]:
                         m_id = next(self.id_count)
                         m = {
                             "id": m_id,
                             "metric": metric,
                             "labels": [
                                 f"noc::interface::{i['name']}",
                                 f"noc::subinterface::{si['name']}",
                             ],
                         }
                         if si["ifindex"] is not None:
                             m["ifindex"] = si["ifindex"]
                         metrics += [m]
                         self.id_metrics[m_id] = ipr[metric]
             threshold_profile = ipr[metric].threshold_profile
             if threshold_profile and threshold_profile.value_handler:
                 # Fill window context
                 in_speed: int = i.get("in_speed") or 0
                 out_speed: int = i.get("out_speed") or 0
                 bandwidth: int = i.get("bandwidth") or 0
                 if in_speed and not out_speed:
                     out_speed = in_speed
                 elif not in_speed and out_speed:
                     in_speed = out_speed
                 if not bandwidth:
                     bandwidth = max(in_speed, out_speed)
                 self.id_ctx[m_id] = {
                     "in_speed": in_speed,
                     "out_speed": out_speed,
                     "bandwidth": bandwidth,
                 }
     if not metrics:
         self.logger.info("Interface metrics are not configured. Skipping")
     return metrics
Пример #12
0
class CheckLinkJob(AlarmJob):
    name = "check_link"
    map_task = "get_interface_status"

    def get_map_task_params(self):
        return {"interface": self.data["interface"]}

    def handler(self, object, result):
        """
        Process result like
        <object>, [{'interface': 'Gi 1/0', 'status': True}]
        :param object:
        :param result:
        :return:
        """
        self.logger.debug("check_link returns %s (checking %s)", result,
                          self.data)
        for r in result:
            if (r["status"] and r["interface"] == self.data["interface"]):
                self.clear_alarm("Interface '%s' is up" %
                                 (self.data["interface"]))
                break
        return True

    def get_effective_intervals(self):
        def parse(x):
            x = x.strip()
            if not x:
                return []
            parts = [p.strip() for p in x.split(",")]
            if not parts:
                return []
            if len(parts) % 2:
                self.error(
                    "Invalid interval description '%s': Must be even size" % x)
                return []
            try:
                parts = [int(p) if p else None for p in parts]
            except ValueError, why:
                self.error("Invalid interval description '%s': %s" % (x, why))
                return []
            if parts[-2] is not None:
                self.error(
                    "Invalid interval description '%s': Next to last element must be empty"
                )
                return []
            # @todo: Check times are in ascending order
            # @todo: Check for additional Nones
            return parts

        mo = self.get_managed_object()
        ifname = mo.profile.convert_interface_name(self.data["interface"])
        iface = Interface.objects.get(managed_object=mo.id,
                                      name=ifname).first()
        # Check interface profile first
        if iface and iface.profile:
            if iface.profile.check_link_interval:
                return parse(iface.profile.check_link_interval)
        # Check Managed object's profile
        if mo.object_profile.check_link_interval:
            return parse(iface.profile.check_link_interval)
        # Fallback to default interface profile
        # when interface profile doesn't set
        if iface and not iface.profile:
            dp = InterfaceProfile.get_default_profile()
            if dp and dp.check_link_interval:
                return parse(dp.check_link_interval)
        # Job disabled
        return []