Ejemplo n.º 1
0
 def _apply_interfaces(mo, r):
     # id -> (object id, name)
     ifcache = {}
     # Get interfaces
     interfaces = sorted(
         Interface._get_collection().find({"managed_object": mo.id}),
         key=lambda x: split_alnum(x["name"]),
     )
     # Populate cache
     for i in interfaces:
         ifcache[i["_id"]] = (i["managed_object"], i["name"])
     # Get subs
     subs = defaultdict(list)
     for s in SubInterface._get_collection().find({"managed_object": mo.id}):
         subs[s["interface"]] += [s]
     # Get links
     links = defaultdict(list)
     for l in Link._get_collection().find({"linked_objects": mo.id}):
         for li in l.get("interfaces", []):
             links[li] += [l]
     # Populate cache with linked interfaces
     if links:
         for i in Interface._get_collection().find(
             {"_id": {"$in": list(links)}}, {"_id": 1, "managed_object": 1, "name": 1}
         ):
             ifcache[i["_id"]] = (i["managed_object"], i["name"])
     # Populate
     r["interfaces"] = [
         ManagedObjectDataStream._get_interface(i, subs[i["_id"]], links[i["_id"]], ifcache)
         for i in interfaces
     ]
Ejemplo n.º 2
0
    def unbind_interface(self):
        from noc.inv.models.interface import Interface

        Interface._get_collection().update({"service": self.id},
                                           {"$unset": {
                                               "service": ""
                                           }})
        self._refresh_managed_object()
Ejemplo n.º 3
0
    def load(mo_ids, zero, def_profile, interface_profile):
        match = {
            "managed_object": {"$in": mo_ids},
            "type": {"$in": ["physical"]},
            "admin_status": True,
        }

        if interface_profile:
            match["profile"] = {"$in": [ObjectId(str(interface_profile))]}

        if zero:
            match["oper_status"] = True

        if def_profile and interface_profile is None:
            def_prof = [pr.id for pr in InterfaceProfile.objects.filter(name__contains="default")]
            match["profile"] = {"$nin": def_prof}
        lookup = {
            "from": "noc.subinterfaces",
            "localField": "_id",
            "foreignField": "interface",
            "as": "subs",
        }
        result = (
            Interface._get_collection()
            .with_options(read_preference=ReadPreference.SECONDARY_PREFERRED)
            .aggregate([{"$match": match}, {"$lookup": lookup}])
        )
        return result
Ejemplo n.º 4
0
 def extract(self):
     mos_id = dict(ManagedObject.objects.filter().values_list("id", "bi_id"))
     iface_prof = {
         i[0]: (i[1], int(i[2] or 0))
         for i in InterfaceProfile.objects.filter().values_list("id", "name", "is_uni")
     }
     ifs = Interface._get_collection().with_options(
         read_preference=ReadPreference.SECONDARY_PREFERRED
     )
     for iface in ifs.find(
         {"type": "physical"},
         {
             "_id": 0,
             "managed_object": 1,
             "name": 1,
             "description": 1,
             "profile": 1,
             "in_speed": 1,
         },
     ).sort("managed_object"):
         yield (
             mos_id[iface["managed_object"]],
             iface["name"],
             iface.get("description", ""),
             iface_prof[iface["profile"]][0],
             abs(iface.get("in_speed", 0)) * 1000,  # iface speed in kbit/s convert to bit/s,
             # some vendors set speed -1 for iface down
             iface_prof[iface["profile"]][1],
         )
Ejemplo n.º 5
0
 def extract(self):
     mos_id = dict(ManagedObject.objects.filter().values_list(
         "id", "bi_id"))
     iface_prof = {
         i[0]: (i[1], int(i[2] or 0))
         for i in InterfaceProfile.objects.filter().values_list(
             "id", "name", "is_uni")
     }
     ifs = Interface._get_collection().with_options(
         read_preference=ReadPreference.SECONDARY_PREFERRED)
     for iface in ifs.find({
             "description": {
                 "$exists": True
             }
     }, {
             "_id": 0,
             "managed_object": 1,
             "name": 1,
             "description": 1,
             "profile": 1,
             "in_speed": 1
     }).sort("managed_object"):
         yield (mos_id[iface["managed_object"]], iface["name"],
                iface.get("description",
                          ""), iface_prof[iface["profile"]][0],
                iface.get("in_speed", 0), iface_prof[iface["profile"]][1])
Ejemplo n.º 6
0
 def set_nri_aliases(self, mo):
     """
     Fill interface alias cache with nri names
     :param mo:
     :return:
     """
     if mo in self.seen_neighbors:
         return
     seen = False
     for d in Interface._get_collection().find(
         {
             "managed_object": mo.id,
             "nri_name": {
                 "$exists": True
             }
         },
         {
             "_id": 0,
             "name": 1,
             "nri_name": 1
         },
     ):
         self.set_interface_alias(mo, d["name"], d["nri_name"])
         seen = True
     self.seen_neighbors.add(mo)
     if not seen:
         self.logger.info(
             "[%s] Object has no nri interface name. Topology may be incomplete",
             mo.name)
Ejemplo n.º 7
0
 def get_linked_pops(self):
     linked = set()
     self.pops = set(self.get_pop_objects())
     self_interfaces = set(
         Interface.objects.filter(
             managed_object__in=self.pops).values_list("id"))
     r_ifaces = set()
     for ld in Link._get_collection().find(
         {"interfaces": {
             "$in": list(self_interfaces)
         }}, {
             "_id": 0,
             "interfaces": 1
         }):
         r_ifaces |= set(ld.get("interfaces", []))
     r_ifaces -= self_interfaces
     r_mos = set(i["managed_object"]
                 for i in Interface._get_collection().find(
                     {"_id": {
                         "$in": list(r_ifaces)
                     }}, {
                         "_id": 0,
                         "managed_object": 1
                     }))
     for o in Object.objects.filter(
             data__match={
                 "interface": "management",
                 "attr": "managed_object",
                 "value__in": list(r_mos),
             }):
         pop = o.get_pop()
         if pop:
             linked.add(pop)
     return linked
Ejemplo n.º 8
0
    def _get_loopback_addresses(cls, mo_id):
        from noc.inv.models.interface import Interface
        from noc.inv.models.subinterface import SubInterface

        # Get all loopbacks
        if_ids = []
        for d in Interface._get_collection().find(
            {
                "managed_object": int(mo_id),
                "type": "loopback"
            }, {"_id": 1}):
            if_ids += [d["_id"]]
        if not if_ids:
            return []
        # Get loopback's addresses
        r = []
        for d in SubInterface._get_collection().find(
            {
                "managed_object": int(mo_id),
                "interface": {
                    "$in": if_ids
                },
                "ipv4_addresses": {
                    "$exists": True
                },
            },
            {
                "_id": 0,
                "ipv4_addresses": 1
            },
        ):
            for a in d.get("ipv4_addresses", []):
                r += [str(a).split("/")[0]]
        return r
Ejemplo n.º 9
0
 def bulk_field_interface_count(self, data):
     """
     Apply interface_count fields
     :param data:
     :return:
     """
     mo_ids = [x["id"] for x in data]
     if not mo_ids:
         return data
     # Collect interface counts
     r = Interface._get_collection().aggregate([
         {
             "$match": {
                 "managed_object": {
                     "$in": mo_ids
                 },
                 "type": "physical"
             }
         },
         {
             "$group": {
                 "_id": "$managed_object",
                 "total": {
                     "$sum": 1
                 }
             }
         },
     ])
     ifcount = dict((x["_id"], x["total"]) for x in r)
     # Apply interface counts
     for x in data:
         x["interface_count"] = ifcount.get(x["id"]) or 0
     return data
Ejemplo n.º 10
0
 def handler(self):
     self.logger.info("NRI Portmapper")
     if not self.object.remote_system:
         self.logger.info("Created directly. No NRI integration. Skipping check")
         return
     nri = self.object.remote_system.name
     # Check object has interfaces
     if not self.has_capability("DB | Interfaces"):
         self.logger.info("No interfaces discovered. " "Skipping interface status check")
         return
     # Get portmapper instance
     portmapper = portmapper_loader.get_loader(self.object.remote_system.name)(self.object)
     if not portmapper:
         self.logger.info("[%s] No portmapper for NRI. Skipping checks", nri)
         return
     # Process interfaces
     bulk = []
     icol = Interface._get_collection()
     for d in icol.find(
         {"managed_object": self.object.id, "type": "physical"},
         {"_id": 1, "name": 1, "nri_name": 1},
     ):
         nri_name = portmapper.to_remote(d["name"])
         self.logger.debug("[%s] Port mapping %s <-> %s", nri, d["name"], nri_name)
         if not nri_name:
             self.logger.info("[%s] Cannot map port name '%s'", nri, d["name"])
         elif d.get("nri_name") != nri_name:
             self.logger.info("[%s] Mapping '%s' to '%s'", nri, nri_name, d["name"])
             bulk += [UpdateOne({"_id": d["_id"]}, {"$set": {"nri_name": nri_name}})]
     if bulk:
         self.logger.info("Sending %d updates", len(bulk))
         icol.bulk_write(bulk)
Ejemplo n.º 11
0
 def refine_ifindexes(self):
     missed_ifindexes = [
         x["name"] for x in Interface._get_collection().find(
             {
                 "managed_object": self.object.id,
                 "ifindex": None
             }, {"name": 1})
     ]
     if not missed_ifindexes:
         return
     self.logger.info("Missed ifindexes for: %s",
                      ", ".join(missed_ifindexes))
     r = self.object.scripts.get_ifindexes()
     if not r:
         return
     updates = {}
     for n in missed_ifindexes:
         if n in r:
             updates[n] = r[n]
     if not updates:
         return
     for n, i in updates.iteritems():
         iface = Interface.objects.filter(managed_object=self.object.id,
                                          name=n).first()
         if iface:
             self.logger.info("Set infindex for %s: %s", n, i)
             iface.ifindex = i
             iface.save()  # Signals will be sent
Ejemplo n.º 12
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
Ejemplo n.º 13
0
 def interface_tags_to_id(cls, object_name, interface_name):
     mo = cls.managedobject_name_to_id(object_name)
     i = Interface._get_collection().find_one({
         "managed_object": mo,
         "name": interface_name
     })
     if i:
         return i["_id"]
     return None
Ejemplo n.º 14
0
Archivo: views.py Proyecto: nbashev/noc
    def api_metrics(self, request, metrics):
        def q(s):
            if isinstance(s, str):
                s = s.encode("utf-8")
            return s

        def qt(t):
            return "|".join(["%s=%s" % (v, t[v]) for v in sorted(t)])

        # Build query
        tag_id = {}  # object, interface -> id
        if_ids = {}  # id -> port id
        mlst = []  # (metric, object, interface)
        for m in metrics:
            if "object" in m["tags"] and "interface" in m["tags"]:
                if not m["tags"]["object"]:
                    continue
                try:
                    if_ids[
                        self.interface_tags_to_id(m["tags"]["object"], m["tags"]["interface"])
                    ] = m["id"]
                    object = ManagedObject.objects.get(name=m["tags"]["object"])
                    tag_id[object, m["tags"]["interface"]] = m["id"]
                    mlst += [(m["metric"], object, m["tags"]["interface"])]
                except KeyError:
                    pass
        # @todo: Get last values from cache
        if not mlst:
            return {}

        r = {}
        # Apply interface statuses
        for d in Interface._get_collection().find(
            {"_id": {"$in": list(if_ids)}}, {"_id": 1, "admin_status": 1, "oper_status": 1}
        ):
            r[if_ids[d["_id"]]] = {
                "admin_status": d.get("admin_status", True),
                "oper_status": d.get("oper_status", True),
            }
        metric_map, last_ts = get_interface_metrics([m[1] for m in mlst])
        # Apply metrics
        for rq_mo, rq_iface in tag_id:
            pid = tag_id.get((rq_mo, rq_iface))
            if not pid:
                continue
            if pid not in r:
                r[pid] = {}
            if rq_mo not in metric_map:
                continue
            if rq_iface not in metric_map[rq_mo]:
                continue
            r[pid]["Interface | Load | In"] = metric_map[rq_mo][rq_iface]["Interface | Load | In"]
            r[pid]["Interface | Load | Out"] = metric_map[rq_mo][rq_iface]["Interface | Load | Out"]

        return r
Ejemplo n.º 15
0
 def get_interfaces(self):
     """
     Build interface counts
     :return:
     """
     r = Interface._get_collection().aggregate(
         [
             {"$match": {"type": "physical"}},
             {"$group": {"_id": "$managed_object", "total": {"$sum": 1}}},
         ]
     )
     return dict((d["_id"], {"n_interfaces": d["total"]}) for d in r)
Ejemplo n.º 16
0
def refresh_interface_profiles(sp_id, ip_id):
    from .service import Service
    from noc.inv.models.interface import Interface
    svc = [
        x["_id"]
        for x in Service._get_collection().find({"profile": sp_id}, {"_id": 1})
    ]
    if not svc:
        return
    collection = Interface._get_collection()
    bulk = []
    bulk += [UpdateOne({"_id": {"$in": svc}}, {"$set": {"profile": ip_id}})]
    collection.bulk_write(bulk, ordered=False)
Ejemplo n.º 17
0
 def _apply_interfaces(mo: ManagedObject, r):
     # id -> (object id, name)
     ifcache = {}
     # Get interfaces
     interfaces = sorted(
         Interface._get_collection().find({"managed_object": mo.id}),
         key=lambda x: alnum_key(x["name"]),
     )
     # Populate cache
     for i in interfaces:
         ifcache[i["_id"]] = (i["managed_object"], i["name"])
     # Get subs
     subs = defaultdict(list)
     for s in SubInterface._get_collection().find({"managed_object": mo.id}):
         subs[s["interface"]] += [s]
     # Get links
     links = defaultdict(list)
     for link in Link._get_collection().find({"linked_objects": mo.id}):
         for li in link.get("interfaces", []):
             links[li] += [link]
     # Populate cache with linked interfaces
     if links:
         for i in Interface._get_collection().find(
             {"_id": {"$in": list(links)}}, {"_id": 1, "managed_object": 1, "name": 1}
         ):
             ifcache[i["_id"]] = (i["managed_object"], i["name"])
     # Get services
     svc_ids = [i["service"] for i in interfaces if i.get("service")]
     if svc_ids:
         services = {svc.id: svc for svc in Service.objects.filter(id__in=svc_ids)}
     else:
         services = {}
     # Populate
     r["interfaces"] = [
         ManagedObjectDataStream._get_interface(
             i, subs[i["_id"]], links[i["_id"]], ifcache, set(mo.data.uplinks), services
         )
         for i in interfaces
     ]
Ejemplo n.º 18
0
 def handle_portmap(self, portmap_objects=[]):
     for po in portmap_objects:
         for o in ManagedObjectSelector.get_objects_from_expression(po):
             if not o.remote_system:
                 self.stdout.write("%s (%s, %s) NRI: N/A\n" %
                                   (o.name, o.address, o.platform))
                 continue
             portmapper = loader.get_loader(o.remote_system.name)(o)
             nri = o.remote_system.name
             self.stdout.write("%s (%s, %s) NRI: %s\n" %
                               (o.name, o.address, o.platform, nri))
             r = []
             for i in Interface._get_collection().find(
                 {
                     "managed_object": o.id,
                     "type": "physical"
                 },
                 {
                     "_id": 1,
                     "name": 1,
                     "nri_name": 1
                 },
             ):
                 rn = portmapper.to_remote(i["name"]) or self.PORT_ERROR
                 if rn == self.PORT_ERROR:
                     ln = self.PORT_ERROR
                 else:
                     ln = portmapper.to_local(rn) or self.PORT_ERROR
                 if i.get("nri_name") == rn and ln != self.PORT_ERROR:
                     status = "OK"
                 elif not i.get("nri_name") and ln != self.PORT_ERROR:
                     status = "Not in database"
                 elif rn == self.PORT_ERROR:
                     status = "Failed to convert to remote name"
                 else:
                     self.print(ln, rn, i.get("nri_name"))
                     status = "Failed to convert to local name"
                 r += [(i["name"], rn, i.get("nri_name", "--"), status)]
             r = [("Local", "Remote", "Interface NRI", "Status")] + list(
                 sorted(r, key=lambda x: alnum_key(x[0])))
             self.stdout.write(
                 "%s\n" %
                 format_table([0, 0, 0, 0], r, sep=" | ", hsep="-+-"))
Ejemplo n.º 19
0
    def load(self):
        """
        Load all managed objects from segment
        """
        def get_bandwidth(if_list):
            """
            Calculate bandwidth for list of interfaces
            :param if_list:
            :return: total in bandwidth, total out bandwidth
            """
            in_bw = 0
            out_bw = 0
            for iface in if_list:
                bw = iface.get("bandwidth") or 0
                in_speed = iface.get("in_speed") or 0
                out_speed = iface.get("out_speed") or 0
                in_bw += bandwidth(in_speed, bw)
                out_bw += bandwidth(out_speed, bw)
            return in_bw, out_bw

        def bandwidth(speed, if_bw):
            if speed and if_bw:
                return min(speed, if_bw)
            elif speed and not if_bw:
                return speed
            elif if_bw:
                return if_bw
            else:
                return 0

        # Get all links, belonging to segment
        links = list(
            Link.objects.filter(
                linked_segments__in=[s.id for s in self.segment_siblings]))
        # All linked interfaces from map
        all_ifaces = list(
            itertools.chain.from_iterable(link.interface_ids
                                          for link in links))
        # Bulk fetch all interfaces data
        ifs = dict((i["_id"], i) for i in Interface._get_collection().find(
            {"_id": {
                "$in": all_ifaces
            }},
            {
                "_id": 1,
                "managed_object": 1,
                "name": 1,
                "bandwidth": 1,
                "in_speed": 1,
                "out_speed": 1,
            },
        ))
        # Bulk fetch all managed objects
        segment_mos = set(
            self.segment.managed_objects.values_list("id", flat=True))
        all_mos = list(
            set(i["managed_object"]
                for i in six.itervalues(ifs) if "managed_object" in i)
            | segment_mos)
        mos = dict(
            (mo.id, mo) for mo in ManagedObject.objects.filter(id__in=all_mos))
        self.segment_objects = set(mo_id for mo_id in all_mos
                                   if mos[mo_id].segment.id == self.segment.id)
        for mo in six.itervalues(mos):
            self.add_object(mo)
        # Process all segment's links
        pn = 0
        for link in links:
            if link.is_loop:
                continue  # Loops are not shown on map
            # Group interfaces by objects
            # avoiding non-bulk dereferencing
            mo_ifaces = defaultdict(list)
            for if_id in link.interface_ids:
                iface = ifs[if_id]
                mo_ifaces[mos[iface["managed_object"]]] += [iface]
            # Pairs of managed objects are pseudo-links
            if len(mo_ifaces) == 2:
                # ptp link
                pseudo_links = [list(mo_ifaces)]
                is_pmp = False
            else:
                # pmp
                # Create virtual cloud
                self.add_cloud(link)
                # Create virtual links to cloud
                pseudo_links = [(link, mo) for mo in mo_ifaces]
                # Create virtual cloud interface
                mo_ifaces[link] = [{"name": "cloud"}]
                is_pmp = True
            # Link all pairs
            for mo0, mo1 in pseudo_links:
                mo0_id = str(mo0.id)
                mo1_id = str(mo1.id)
                # Create virtual ports for mo0
                self.G.node[mo0_id]["ports"] += [{
                    "id":
                    pn,
                    "ports": [i["name"] for i in mo_ifaces[mo0]]
                }]
                # Create virtual ports for mo1
                self.G.node[mo1_id]["ports"] += [{
                    "id":
                    pn + 1,
                    "ports": [i["name"] for i in mo_ifaces[mo1]]
                }]
                # Calculate bandwidth
                t_in_bw, t_out_bw = get_bandwidth(mo_ifaces[mo0])
                d_in_bw, d_out_bw = get_bandwidth(mo_ifaces[mo1])
                in_bw = bandwidth(t_in_bw, d_out_bw) * 1000
                out_bw = bandwidth(t_out_bw, d_in_bw) * 1000
                # Add link
                if is_pmp:
                    link_id = "%s-%s-%s" % (link.id, pn, pn + 1)
                else:
                    link_id = str(link.id)
                self.add_link(
                    mo0_id,
                    mo1_id,
                    {
                        "id": link_id,
                        "type": "link",
                        "method": link.discovery_method,
                        "ports": [pn, pn + 1],
                        # Target to source
                        "in_bw": in_bw,
                        # Source to target
                        "out_bw": out_bw,
                        # Max bandwidth
                        "bw": max(in_bw, out_bw),
                    },
                )
                pn += 2
Ejemplo n.º 20
0
 def get_ajax_data(self, **kwargs):
     # Parse query params
     query = self.decode_query(
         self.handler.get_argument("key")
     )  # type: List[Tuple[int, int, str]]
     # Get metrics
     from_ts = datetime.datetime.now() - datetime.timedelta(seconds=1800)
     from_ts = from_ts.replace(microsecond=0)
     interface_sql = """
       SELECT
         managed_object,
         path[4] AS iface,
         argMax(load_in, ts) AS load_in,
         argMax(load_out, ts) AS load_out,
         argMax(packets_in, ts) AS packets_in,
         argMax(packets_out, ts) AS packets_out,
         argMax(errors_in, ts) AS errors_in,
         argMax(errors_out, ts) AS errors_out
       FROM interface
       WHERE
         date >= toDate('%s')
         AND ts >= toDateTime('%s')
         AND (%s)
       GROUP BY managed_object, iface
     """ % (
         from_ts.date().isoformat(),
         from_ts.isoformat(sep=" "),
         " OR ".join(
             "(managed_object=%d AND path[4]='%s')" % (q[1], q[2].replace("'", "''"))
             for q in query
         ),
     )
     # Get data
     metrics = []  # type: List[Tuple[int, str, str, str, str, str]]
     ch = ch_connection()
     try:
         for (
             mo,
             iface,
             load_in,
             load_out,
             packets_in,
             packets_out,
             errors_in,
             errors_out,
         ) in ch.execute(post=interface_sql):
             if_hash = str(bi_hash(iface))
             metrics += [
                 # (mo, if_hash, "speed", self.humanize_metric(speed)),
                 (mo, if_hash, "load_in", self.humanize_metric(load_in)),
                 (mo, if_hash, "load_out", self.humanize_metric(load_out)),
                 (mo, if_hash, "packets_in", self.humanize_metric(packets_in)),
                 (mo, if_hash, "packets_out", self.humanize_metric(packets_out)),
                 (mo, if_hash, "errors_in", self.humanize_metric(errors_in)),
                 (mo, if_hash, "errors_out", self.humanize_metric(errors_out)),
             ]
     except ClickhouseError:
         pass
     # Set defaults
     m_index = set()  # type: Set[Tuple[int, str]]
     for mo_bi_id, iface, _, _ in metrics:
         m_index.add((int(mo_bi_id), iface))
     interface_metrics = {
         "speed",
         "load_in",
         "load_out",
         "packets_in",
         "packets_out",
         "errors_in",
         "errors_out",
     }
     for _, mo_bi_id, iface in query:
         if (int(mo_bi_id), str(bi_hash(iface))) not in m_index:
             for metric in interface_metrics:
                 metrics += [(str(mo_bi_id), str(bi_hash(iface)), metric, "-")]
     # managed object id -> bi id
     mo_map = {q[0]: q[1] for q in query}  # type: Dict[int, int]
     # Get interface statuses
     for doc in Interface._get_collection().find(
         {"$or": [{"managed_object": q[0], "name": q[2]} for q in query]},
         {
             "_id": 0,
             "managed_object": 1,
             "name": 1,
             "admin_status": 1,
             "oper_status": 1,
             "in_speed": 1,
             "out_speed": 1,
             "full_duplex": 1,
         },
     ):
         mo = str(mo_map[doc["managed_object"]])
         if_hash = str(bi_hash(doc["name"]))
         status = 0
         if "admin_status" in doc and doc["admin_status"]:
             status = 2 if doc["oper_status"] else 1
         duplex = "-"
         if "full_duplex" in doc:
             duplex = "Full" if doc["full_duplex"] else "Half"
         speed = "-"
         if "in_speed" in doc:
             speed = self.humanize_metric(doc["in_speed"] * 1000)
         metrics += [
             (mo, if_hash, "speed", speed),
             (mo, if_hash, "duplex", duplex),
             (mo, if_hash, "status", status),
         ]
     # Get current object statuses
     obj_statuses = ObjectStatus.get_statuses(list(mo_map))
     statuses = {str(mo_map[mo_id]): obj_statuses.get(mo_id, True) for mo_id in obj_statuses}
     return {"metrics": metrics, "statuses": list(statuses.items())}
Ejemplo n.º 21
0
    def get_data(self, request, pool, obj_profile=None, **kwargs):
        problems = {}  # id -> problem

        if not obj_profile:
            # Get all managed objects
            mos = dict(
                (mo.id, mo)
                for mo in ManagedObject.objects.filter(is_managed=True, pool=pool)
            )
            if not request.user.is_superuser:
                mos = dict(
                    (mo.id, mo)
                    for mo in ManagedObject.objects.filter(is_managed=True, pool=pool,
                                                           administrative_domain__in=UserAccess.get_domains(request.user))
                )
        else:
            # Get all managed objects
            mos = dict(
                (mo.id, mo)
                for mo in ManagedObject.objects.filter(is_managed=True, pool=pool, object_profile=obj_profile)
            )
            if not request.user.is_superuser:
                mos = dict(
                    (mo.id, mo)
                    for mo in ManagedObject.objects.filter(is_managed=True, pool=pool, object_profile=obj_profile,
                                                           administrative_domain__in=UserAccess.get_domains(request.user))
                )

        mos_set = set(mos)
        # Get all managed objects with generic profile
        for mo in mos:
            if mos[mo].profile.name == GENERIC_PROFILE:
                problems[mo] = _("Profile check failed")
        # Get all managed objects without interfaces
        if_mo = dict(
            (x["_id"], x.get("managed_object"))
            for x in Interface._get_collection().find(
                {},
                {"_id": 1, "managed_object": 1}
            )
        )
        for mo in (mos_set - set(problems) - set(if_mo.itervalues())):
            problems[mo] = _("No interfaces")
        # Get all managed objects without links
        linked_mos = set()
        for d in Link._get_collection().find({}):
            for i in d["interfaces"]:
                linked_mos.add(if_mo.get(i))
        for mo in (mos_set - set(problems) - linked_mos):
            problems[mo] = _("No links")
        # Get all managed objects without uplinks
        uplinks = {}
        for d in ObjectData._get_collection().find():
            nu = len(d.get("uplinks", []))
            if nu:
                uplinks[d["_id"]] = nu
        for mo in (mos_set - set(problems) - set(uplinks)):
            problems[mo] = _("No uplinks")
        #
        data = []
        for mo_id in problems:
            if mo_id not in mos:
                continue
            mo = mos[mo_id]
            data += [[
                mo.name,
                mo.address,
                mo.profile.name,
                mo.platform.name if mo.platform else "",
                mo.segment.name if mo.segment else "",
                problems[mo_id]
            ]]
        data = sorted(data)
        return self.from_dataset(
            title=self.title,
            columns=[
                "Name",
                "Address",
                "Profile",
                "Platform",
                "Segment",
                "Problem"
            ],
            data=data,
            enumerate=True
        )
Ejemplo n.º 22
0
    def handler(self):
        def get_interface(name):
            if_name = interfaces.get(name)
            if if_name:
                return if_name
            for iname in self.object.get_profile().get_interface_names(
                    i["interface"]):
                if_name = interfaces.get(iname)
                if if_name:
                    return if_name
            return None

        has_interfaces = "DB | Interfaces" in self.object.get_caps()
        if not has_interfaces:
            self.logger.info("No interfaces discovered. "
                             "Skipping interface status check")
            return
        self.logger.info("Checking interface statuses")
        interfaces = dict((i.name, i) for i in Interface.objects.filter(
            managed_object=self.object.id,
            type="physical",
            profile__in=self.get_profiles(None),
            read_preference=ReadPreference.SECONDARY_PREFERRED,
        ))
        if not interfaces:
            self.logger.info(
                "No interfaces with status discovery enabled. Skipping")
            return
        hints = [{
            "interface": key,
            "ifindex": v.ifindex
        } for key, v in six.iteritems(interfaces)
                 if getattr(v, "ifindex", None) is not None] or None
        result = self.object.scripts.get_interface_status_ex(interfaces=hints)
        collection = Interface._get_collection()
        bulk = []
        for i in result:
            iface = get_interface(i["interface"])
            if not iface:
                continue
            kwargs = {
                "admin_status": i.get("admin_status"),
                "full_duplex": i.get("full_duplex"),
                "in_speed": i.get("in_speed"),
                "out_speed": i.get("out_speed"),
                "bandwidth": i.get("bandwidth"),
            }
            changes = self.update_if_changed(iface,
                                             kwargs,
                                             ignore_empty=list(
                                                 six.iterkeys(kwargs)),
                                             bulk=bulk)
            self.log_changes(
                "Interface %s status has been changed" % i["interface"],
                changes)
            ostatus = i.get("oper_status")
            if iface.oper_status != ostatus and ostatus is not None:
                self.logger.info("[%s] set oper status to %s", i["interface"],
                                 ostatus)
                iface.set_oper_status(ostatus)
        if bulk:
            self.logger.info("Committing changes to database")
            try:
                collection.bulk_write(bulk, ordered=False)
                # 1 bulk operations complete in 0ms: inserted=0, updated=1, removed=0
                self.logger.info("Database has been synced")
            except BulkWriteError as e:
                self.logger.error("Bulk write error: '%s'", e.details)
Ejemplo n.º 23
0
    def get_data(self, request, pool=None, obj_profile=None, **kwargs):
        problems = {}  # id -> problem

        mos = ManagedObject.objects.filter(is_managed=True, pool=pool)
        if not request.user.is_superuser:
            mos = mos.filter(administrative_domain__in=UserAccess.get_domains(request.user))
        if obj_profile:
            # Get all managed objects
            mos = mos.filter(object_profile=obj_profile)
        mos = {
            mo[0]: (mo[1], mo[2], Profile.get_by_id(mo[3]), mo[4], mo[5])
            for mo in mos.values_list("id", "name", "address", "profile", "platform", "segment")
        }
        mos_set = set(mos)
        # Get all managed objects with generic profile
        for mo in mos:
            if mos[mo][2] == GENERIC_PROFILE:
                problems[mo] = _("Profile check failed")
        # Get all managed objects without interfaces
        if_mo = dict(
            (x["_id"], x.get("managed_object"))
            for x in Interface._get_collection().find({}, {"_id": 1, "managed_object": 1})
        )
        for mo in mos_set - set(problems) - set(six.itervalues(if_mo)):
            problems[mo] = _("No interfaces")
        # Get all managed objects without links
        linked_mos = set()
        for d in Link._get_collection().find({}):
            for i in d["interfaces"]:
                linked_mos.add(if_mo.get(i))
        for mo in mos_set - set(problems) - linked_mos:
            problems[mo] = _("No links")
        # Get all managed objects without uplinks
        uplinks = {}
        for d in ObjectData._get_collection().find():
            nu = len(d.get("uplinks", []))
            if nu:
                uplinks[d["_id"]] = nu
        for mo in mos_set - set(problems) - set(uplinks):
            problems[mo] = _("No uplinks")
        #
        data = []
        for mo_id in problems:
            if mo_id not in mos:
                continue
            name, address, profile, platform, segment = mos[mo_id]
            data += [
                [
                    name,
                    address,
                    profile.name,
                    Platform.get_by_id(platform).name if platform else "",
                    NetworkSegment.get_by_id(segment).name if segment else "",
                    problems[mo_id],
                ]
            ]
        data = sorted(data)
        return self.from_dataset(
            title=self.title,
            columns=["Name", "Address", "Profile", "Platform", "Segment", "Problem"],
            data=data,
            enumerate=True,
        )
Ejemplo n.º 24
0
 def handler(self):
     self.logger.info("NRI Portmapper")
     if not self.object.remote_system:
         self.logger.info(
             "Created directly. No NRI integration. Skipping check")
         return
     nri = self.object.remote_system.name
     # Check object has interfaces
     if not self.has_capability("DB | Interfaces"):
         self.logger.info("No interfaces discovered. "
                          "Skipping interface status check")
         return
     # Get portmapper instance
     pm_cls = portmapper_loader.get_loader(self.object.remote_system.name)
     if not pm_cls:
         self.logger.info("[%s] No portmapper for NRI. Skipping checks",
                          nri)
         return
     portmapper = pm_cls(self.object)
     # Process interfaces
     bulk = []
     icol = Interface._get_collection()
     ifaces_hints = tuple(
         IFHint(name=iface["name"], ifindex=iface.get("ifindex"))
         for iface in icol.find(
             {
                 "managed_object": self.object.id,
                 "type": "physical"
             },
             {
                 "_id": 1,
                 "name": 1,
                 "ifindex": 1
             },
         ))
     for d in icol.find(
         {
             "managed_object": self.object.id,
             "type": "physical"
         },
         {
             "_id": 1,
             "name": 1,
             "nri_name": 1
         },
     ):
         try:
             nri_name = portmapper.to_remote(d["name"],
                                             iface_hints=ifaces_hints)
         except Exception as e:
             self.logger.error(
                 "[%s] Unhandled exception on portmapper handler '%s'. Skipping checks.",
                 nri, e)
             break
         self.logger.debug("[%s] Port mapping %s <-> %s", nri, d["name"],
                           nri_name)
         if not nri_name:
             self.logger.info("[%s] Cannot map port name '%s'", nri,
                              d["name"])
         elif d.get("nri_name") != nri_name:
             self.logger.info("[%s] Mapping '%s' to '%s'", nri, nri_name,
                              d["name"])
             bulk += [
                 UpdateOne({"_id": d["_id"]},
                           {"$set": {
                               "nri_name": nri_name
                           }})
             ]
     if bulk:
         self.logger.info("Sending %d updates", len(bulk))
         icol.bulk_write(bulk)
Ejemplo n.º 25
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)])
Ejemplo n.º 26
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
Ejemplo n.º 27
0
    def get_data(self,
                 request,
                 reporttype=None,
                 from_date=None,
                 to_date=None,
                 object_profile=None,
                 percent=None,
                 filter_default=None,
                 zero=None,
                 interface_profile=None,
                 managed_object=None,
                 selectors=None,
                 administrative_domain=None,
                 allow_archive=True,
                 **kwargs):

        map_table = {
            "load_interfaces": "/Interface\s\|\sLoad\s\|\s[In|Out]/",
            "load_cpu": "/[CPU|Memory]\s\|\sUsage/",
            "errors": "/Interface\s\|\s[Errors|Discards]\s\|\s[In|Out]/",
            "ping": "/Ping\s\|\sRTT/"
        }

        # Date Time Block
        if not from_date:
            from_date = datetime.datetime.now() - datetime.timedelta(days=1)
        else:
            from_date = datetime.datetime.strptime(from_date, "%d.%m.%Y")

        if not to_date or from_date == to_date:
            to_date = from_date + datetime.timedelta(days=1)
        else:
            to_date = datetime.datetime.strptime(
                to_date, "%d.%m.%Y") + datetime.timedelta(days=1)

        interval = (to_date - from_date).days
        ts_from_date = time.mktime(from_date.timetuple())
        ts_to_date = time.mktime(to_date.timetuple())

        # Load managed objects
        mos = ManagedObject.objects.filter(is_managed=True)
        if not request.user.is_superuser:
            mos = mos.filter(
                administrative_domain__in=UserAccess.get_domains(request.user))
        if managed_object:
            mos = [managed_object]
        else:
            if selectors:
                mos = mos.filter(selectors.Q)
            if administrative_domain:
                # @todo fix
                mos = mos.filter(administrative_domain=administrative_domain)
            if object_profile:
                mos = mos.filter(object_profile=object_profile)

        columns = [_("Managed Object"), _("Address")]
        iface_dict = {}

        d_url = {
            "path": "/ui/grafana/dashboard/script/report.js",
            "rname": map_table[reporttype],
            "from": str(int(ts_from_date * 1000)),
            "to": str(int(ts_to_date * 1000)),
            # o.name.replace("#", "%23")
            "biid": "",
            "oname": "",
            "iname": ""
        }

        report_map = {
            "load_interfaces": {
                "url":
                '%(path)s?title=interface&biid=%(biid)s'
                '&obj=%(oname)s&iface=%(iname)s&from=%(from)s&to=%(to)s',
                "q_group": ["interface"],
                "columns": [
                    _("Int Name"),
                    _("Int Descr"),
                    TableColumn(_("IN bps"), align="right"),
                    TableColumn(_("OUT bps"), align="right"),
                ]
            },
            "errors": {
                "url":
                """%(path)s?title=errors&biid=%(biid)s&obj=%(oname)s&iface=%(iname)s&from=%(from)s&to=%(to)s""",
                "columns": [
                    _("Int Name"),
                    TableColumn(_("Errors IN"), align="right"),
                    TableColumn(_("Errors OUT"), align="right"),
                    TableColumn(_("Discards IN"), align="right"),
                    TableColumn(_("Discards OUT"), align="right")
                ],
                "q_group": ["interface"]
            },
            "load_cpu": {
                "url":
                """%(path)s?title=cpu&biid=%(biid)s&obj=%(oname)s&from=%(from)s&to=%(to)s""",
                "columns": [
                    TableColumn(_("Memory | Usage %"), align="right"),
                    TableColumn(_("CPU | Usage %"), align="right")
                ]
            },
            "ping": {
                "url":
                """%(path)s?title=ping&biid=%(biid)s&obj=%(oname)s&from=%(from)s&to=%(to)s""",
                "columns": [
                    TableColumn(_("Ping | RTT (ms)"), align="right"),
                    TableColumn(_("Ping | Attempts"), align="right")
                ]
            }
        }
        if not allow_archive:
            report_map["load_interfaces"].update({
                "q_select": [
                    "arrayStringConcat(path)",
                    "round(quantile(0.98)(load_in), 0) as l_in",
                    "round(quantile(0.98)(load_out), 0) as l_out"
                ],
                "q_group": ["path"],
                "q_where":
                ["(load_in != 0 and load_out != 0)"] if zero else []
            })
            report_map["errors"].update({
                "q_select": [
                    "arrayStringConcat(path)",
                    "quantile(0.98)(errors_in) as err_in",
                    "quantile(0.98)(errors_out) as err_out",
                    "quantile(0.98)(discards_in) as dis_in",
                    "quantile(0.98)(discards_out) as dis_out"
                ],
                "q_group": ["path"],
                "q_where": [
                    "(errors_in != 0 or errors_out != 0 or discards_in != 0 or discards_out != 0)"
                ] if zero else []
            })
            report_map["load_cpu"].update({
                "q_select":
                ["arrayStringConcat(path)", "quantile(0.98)(usage) as usage"],
                "q_group": ["path"]
            })
            report_map["ping"].update({
                "q_select": [
                    "managed_object", "round(quantile(0.98)(rtt) / 1000, 2)",
                    "avg(attempts)"
                ]
            })
            moss = {
                str(mo[0]): mo
                for mo in mos.values_list("bi_id", "id", "name", "address")
            }
        else:
            moss = {
                mo[0]: mo
                for mo in mos.values_list("name", "id", "name", "address")
            }
        # mos_s = set(mos.values_list("id", flat=True))
        if reporttype in ["load_interfaces", "errors"]:
            ifaces = Interface._get_collection()
            xx = set(mos.values_list("id", flat=True))
            for iface in ifaces.find({"type": "physical"}, {
                    "managed_object": 1,
                    "name": 1,
                    "description": 1,
                    "in_speed": 1,
                    "out_speed": 1
            }):
                if iface["managed_object"] not in xx:
                    continue
                iface_dict[(iface["managed_object"],
                            iface["name"])] = (iface.get("description", ""),
                                               iface.get("in_speed", 0),
                                               iface.get("out_speed", 0))

        columns += report_map[reporttype]["columns"]
        if percent:
            columns.insert(-1, TableColumn(_("IN %"), align="right"))
            columns += [TableColumn(_("OUT %"), align="right")]
        columns += [
            TableColumn(_("Graphic"), format="url"),
            TableColumn(_("Interval days"), align="right")
        ]
        url = report_map[reporttype].get("url", "")
        rm = ReportMetric()
        rm.reporttype = reporttype

        r = []
        if allow_archive:
            rm_data = rm.do_query(moss, report_map[reporttype], from_date,
                                  to_date)
        else:
            rm_data = rm.do_query_ch(moss, report_map[reporttype], from_date,
                                     to_date)

        for l, data in rm_data:
            if not l:
                continue
            mo = moss[l[0]]
            d_url["biid"] = l[0]
            d_url["oname"] = mo[2].replace("#", "%23")
            if zero and allow_archive and not sum(data):
                # For InfluxDB query
                continue
            if reporttype in ["load_interfaces", "errors"]:
                d_url["iname"] = l[1]
                res = [mo[2], mo[3], l[1]]
                res += data
                if "load_interfaces" in reporttype:
                    i_d = iface_dict.get((mo[1], l[1]), ["", "", ""])
                    res.insert(3, i_d[0])
                    if percent:
                        in_p = float(data[0])
                        in_p = round(
                            (in_p / 1000.0) /
                            (i_d[1] / 100.0), 2) if i_d[1] and in_p > 0 else 0
                        # in
                        res.insert(-1, in_p)
                        # out
                        out_p = float(data[1])
                        res += [
                            round((out_p / 1000.0) / (i_d[2] / 100.0), 2)
                            if i_d[2] and out_p > 0 else 0
                        ]
            else:
                res = [mo[2], mo[3]]
                res += data
            res += [url % d_url, interval]
            r += [res]

        return self.from_dataset(title=self.title,
                                 columns=columns,
                                 data=r,
                                 enumerate=True)
Ejemplo n.º 28
0
Archivo: link.py Proyecto: skripkar/noc
def _get_interface(object, name):
    Interface._get_collection().update({"managed_object": object.id})
Ejemplo n.º 29
0
    def build_summary_for_object(cls, managed_object):
        """
        Build active services summary for managed object
        :param managed_object: Managed Object id
        :return: dict of interface id -> {service: ..., subscriber: ....}
            interface None means unbound or box-wise services
        """
        from noc.inv.models.interface import Interface
        from noc.sa.models.service import Service

        def iter_services(sd):
            yield sd
            for cs in Service._get_collection().find(
                {
                    "parent": sd["_id"],
                    "logical_status": "R"
                }, {
                    "_id": 1,
                    "subscriber": 1,
                    "profile": 1
                }):
                for ns in iter_services(cs):
                    yield ns

        def add_dict(d1, d2):
            """
            Add all d2 values to d1
            :param d1:
            :param d2:
            :return:
            """
            for k in d2:
                d1[k] = d1.get(k, 0) + d2[k]

        # service -> interface bindings
        svc_interface = dict((
            x["service"], x["_id"]
        ) for x in Interface._get_collection().find(
            {
                "managed_object": managed_object,
                "service": {
                    "$exists": True
                }
            }, {
                "_id": 1,
                "service": 1
            },
            comment=
            "[servicesummary.build_summary_for_object] Getting services for interfaces"
        ))
        # Iterate over object's services
        # And walk underlying tree
        ri = {}
        for svc in Service._get_collection(
        ).find({
                "managed_object": managed_object,
                "logical_status": "R"
        }, {
                "_id": 1,
                "subscriber": 1,
                "profile": 1
        },
               comment=
               "[servicesummary.build_summary_for_object] Getting object services for object"
               ):
            # All subscribers for underlying tree
            subscribers = set()
            # profile_id -> count
            svc_profiles = defaultdict(int)
            for s in iter_services(svc):
                subscribers.add(s["subscriber"])
                svc_profiles[s["profile"]] += 1
            # Get subscriber profiles count
            ra = Subscriber._get_collection().aggregate([{
                "$match": {
                    "_id": {
                        "$in": list(subscribers)
                    }
                }
            }, {
                "$group": {
                    "_id": "$profile",
                    "total": {
                        "$sum": 1
                    }
                }
            }])
            subscriber_profiles = dict((x["_id"], x["total"]) for x in ra)
            # Bind to interface
            # None for unbound services
            iface = svc_interface.get(svc["_id"])
            if iface in ri:
                add_dict(ri[iface]["service"], svc_profiles)
                add_dict(ri[iface]["subscriber"], subscriber_profiles)
            else:
                ri[iface] = {
                    "service": dict(svc_profiles),  # defaultdict -> dict
                    "subscriber": subscriber_profiles
                }
        return ri