Ejemplo n.º 1
0
 def get_n_subs_n_serv():
     r = defaultdict(dict)
     service_pipeline = [
         {
             "$unwind": "$service"
         },
         {
             "$group": {
                 "_id": "$managed_object",
                 "service_sum": {
                     "$sum": "$service.summary"
                 }
             }
         },
     ]
     for doc in ServiceSummary._get_collection().aggregate(
             service_pipeline):
         r[doc["_id"]]["n_services"] = doc["service_sum"]
     subscriber_pipeline = [
         {
             "$unwind": "$subscriber"
         },
         {
             "$group": {
                 "_id": "$managed_object",
                 "subscriber_sum": {
                     "$sum": "$subscriber.summary"
                 },
             }
         },
     ]
     for doc in ServiceSummary._get_collection().aggregate(
             subscriber_pipeline):
         r[doc["_id"]]["n_subscribers"] = doc["subscriber_sum"]
     return r
Ejemplo n.º 2
0
 def update_summary(segment):
     """
     Calculate summary for segment and all nested segments
     """
     services = {}
     subscribers = {}
     # Calculate direct segments' coverage
     for o in six.itervalues(segment["objects"]):
         update_dict(services, o["services"])
         update_dict(subscribers, o["subscribers"])
     # Flatten objects
     segment["objects"] = sorted(six.itervalues(segment["objects"]),
                                 key=lambda x: -x["weight"])
     # Calculate children's coverage
     for s in six.itervalues(segment["segments"]):
         update_summary(s)
         update_dict(services, s["services"])
         update_dict(subscribers, s["subscribers"])
     segment["segments"] = sorted(six.itervalues(segment["segments"]),
                                  key=lambda x: -x["weight"])
     segment["services"] = services
     segment["subscribers"] = subscribers
     segment["summary"] = {
         "service": services,
         "subscriber": subscribers
     }
     segment["weight"] = ServiceSummary.get_weight(segment["summary"])
Ejemplo n.º 3
0
 def get_direct_summary(self):
     objects = dict(
         (d["object_profile"], d["count"])
         for d in self.managed_objects.values("object_profile").annotate(
             count=Count("id")).order_by("count"))
     # Direct services
     mo_ids = self.managed_objects.values_list("id", flat=True)
     services, subscribers = ServiceSummary.get_direct_summary(mo_ids)
     return services, subscribers, objects
Ejemplo n.º 4
0
 def get_data(self):
     # Calculate contained objects
     summary = {
         "service": SummaryItem.items_to_dict(self.object.total_services),
         "subscriber": SummaryItem.items_to_dict(self.object.total_subscribers)
     }
     objects = []
     for mo in self.object.managed_objects.filter(is_managed=True):
         ss = ServiceSummary.get_object_summary(mo)
         objects += [{
             "id": mo.id,
             "name": mo.name,
             "object": mo,
             "summary": ss
         }]
     # Update object statuses
     mos = [o["id"] for o in objects]
     alarms = set(d["managed_object"] for d in ActiveAlarm._get_collection().find({
         "managed_object": {
             "$in": mos
         }
     }, {"_id": 0, "managed_object": 1}))
     o_status = ObjectStatus.get_statuses(mos)
     for o in objects:
         if o["id"] in o_status:
             if o["id"] in alarms:
                 o["status"] = "alarm"
             else:
                 o["status"] = "up"
         else:
             o["status"] = "down"
     # Calculate children
     children = []
     for ns in NetworkSegment.objects.filter(parent=self.object.id):
         children += [{
             "id": ns.id,
             "name": ns.name,
             "object": ns,
             "summary": {
                 "service": SummaryItem.items_to_dict(ns.total_services),
                 "subscriber": SummaryItem.items_to_dict(ns.total_subscribers),
             }
         }]
     # Calculate VLANs
     vlans = []
     if self.object.vlan_border:
         vlans = list(VLAN.objects.filter(segment=self.object.id).order_by("vlan"))
     #
     return {
         "object": self.object,
         "managed_objects": sorted(objects, key=operator.itemgetter("name")),
         "children": sorted(children, key=operator.itemgetter("name")),
         "parent": self.object.parent,
         "summary": summary,
         "vlans": vlans
     }
Ejemplo n.º 5
0
    def update_summary(self):
        """
        Update summaries
        :return:
        """
        def update_dict(d1, d2):
            for k in d2:
                if k in d1:
                    d1[k] += d2[k]
                else:
                    d1[k] = d2[k]

        objects = dict(
            (d["object_profile"], d["count"])
            for d in self.managed_objects.values(
                "object_profile"
            ).annotate(
                count=Count("id")
            ).order_by("count"))
        # Direct services
        mo_ids = self.managed_objects.values_list("id", flat=True)
        services, subscribers = ServiceSummary.get_direct_summary(mo_ids)
        self.direct_services = SummaryItem.dict_to_items(services)
        self.direct_subscribers = SummaryItem.dict_to_items(subscribers)
        self.direct_objects = ObjectSummaryItem.dict_to_items(objects)
        siblings = set()
        for ns in NetworkSegment.objects.filter(parent=self.id):
            if ns.id in siblings:
                continue
            update_dict(services, SummaryItem.items_to_dict(ns.total_services))
            update_dict(subscribers, SummaryItem.items_to_dict(ns.total_subscribers))
            update_dict(objects, ObjectSummaryItem.items_to_dict(ns.total_objects))
            siblings.add(ns.id)
            if ns.sibling:
                siblings.add(ns.sibling.id)
        self.total_services = SummaryItem.dict_to_items(services)
        self.total_subscribers = SummaryItem.dict_to_items(subscribers)
        self.total_objects = ObjectSummaryItem.dict_to_items(objects)
        self.save()
        # Update upwards
        ns = self.parent
        while ns:
            services = SummaryItem.items_to_dict(ns.direct_services)
            subscribers = SummaryItem.items_to_dict(ns.direct_subscribers)
            objects = ObjectSummaryItem.items_to_dict(ns.direct_objects)
            for nsc in NetworkSegment.objects.filter(parent=ns.id):
                update_dict(services, SummaryItem.items_to_dict(nsc.total_services))
                update_dict(subscribers, SummaryItem.items_to_dict(nsc.total_subscribers))
                update_dict(objects, ObjectSummaryItem.items_to_dict(nsc.total_objects))
            ns.total_services = SummaryItem.dict_to_items(services)
            ns.total_subscribers = SummaryItem.dict_to_items(subscribers)
            ns.total_objects = ObjectSummaryItem.dict_to_items(objects)
            ns.save()
            ns = ns.parent
Ejemplo n.º 6
0
    def get_data(self):
        def update_dict(s, d):
            for k in d:
                if k in s:
                    s[k] += d[k]
                else:
                    s[k] = d[k]

        stpl = self.object.type.card_template or self.default_title_template
        now = datetime.datetime.now()
        if self.object.start > now:
            status = "before"
        elif self.object.is_completed:
            status = "complete"
        else:
            status = "progress"
        # Calculate affected objects
        affected = []
        summary = {"service": {}, "subscriber": {}}
        for ao in self.object.affected_objects:
            mo = ao.object
            ss = ServiceSummary.get_object_summary(mo)
            affected += [
                {
                    "id": mo.id,
                    "object": mo,
                    "name": mo.name,
                    "address": mo.address,
                    "platform": mo.platform,
                    "summary": ss,
                }
            ]
            update_dict(summary["service"], ss.get("service", {}))
            update_dict(summary["subscriber"], ss.get("subscriber", {}))
        #
        return {
            "title": jinja2.Template(stpl).render({"object": self.object}),
            "object": self.object,
            "subject": self.object.subject,
            "contacts": self.object.contacts,
            "start": self.object.start,
            "stop": self.object.stop,
            "description": self.object.description,
            "status": status,
            "affected": affected,
            "summary": summary,
        }
Ejemplo n.º 7
0
    def update_summary(self):
        def update_dict(d1, d2):
            for k in d2:
                if k in d1:
                    d1[k] += d2[k]
                else:
                    d1[k] = d2[k]

        services = SummaryItem.items_to_dict(self.direct_services)
        subscribers = SummaryItem.items_to_dict(self.direct_subscribers)
        objects = {
            self.managed_object.object_profile.id: 1
        }

        for a in ActiveAlarm.objects.filter(root=self.id):
            a.update_summary()
            update_dict(
                objects,
                SummaryItem.items_to_dict(a.total_objects)
            )
            update_dict(
                services,
                SummaryItem.items_to_dict(a.total_services)
            )
            update_dict(
                subscribers,
                SummaryItem.items_to_dict(a.total_subscribers)
            )
        obj_list = ObjectSummaryItem.dict_to_items(objects)
        svc_list = SummaryItem.dict_to_items(services)
        sub_list = SummaryItem.dict_to_items(subscribers)
        if svc_list != self.total_services or sub_list != self.total_subscribers or obj_list != self.total_objects:
            ns = ServiceSummary.get_severity({
                "service": services,
                "subscriber": subscribers,
                "objects": objects
            })
            self.total_objects = obj_list
            self.total_services = svc_list
            self.total_subscribers = sub_list
            if ns != self.severity:
                self.change_severity(severity=ns, to_save=False)
            self.safe_save()
Ejemplo n.º 8
0
    def get_objects_summary_met(mos_ids, info_all=False):
        kk = {}
        pipeline = []
        name = "service"
        if not info_all:
            pipeline += [{"$match": {"managed_object": {"$in": mos_ids}}}]

        group = {
            "_id": {
                "mo": "$managed_object"
            },
            "count": {
                "$push": "$%s.profile" % name
            }
        }
        pipeline += [{"$unwind": "$%s" % name}, {"$group": group}]
        for ss in (ServiceSummary._get_collection().with_options(
                read_preference=ReadPreference.SECONDARY_PREFERRED).aggregate(
                    pipeline)):
            kk[ss["_id"]["mo"]] = ss["count"]
        return kk
Ejemplo n.º 9
0
    def get_ajax_data(self, **kwargs):
        def update_dict(d, s):
            for k in s:
                if k in d:
                    d[k] -= s[k]
                else:
                    d[k] = s[k]

        object_id = self.handler.get_argument("object_id")
        # zoom = int(self.handler.get_argument("z"))
        # west = float(self.handler.get_argument("w"))
        # east = float(self.handler.get_argument("e"))
        # north = float(self.handler.get_argument("n"))
        # south = float(self.handler.get_argument("s"))
        # ms = int(self.handler.get_argument("maintenance"))
        # active_layers = [l for l in self.get_pop_layers() if l.min_zoom <= zoom <= l.max_zoom]
        if self.current_user.is_superuser:
            moss = ManagedObject.objects.filter(is_managed=True)
        else:
            moss = ManagedObject.objects.filter(
                is_managed=True,
                administrative_domain__in=self.get_user_domains())
        objects = []
        objects_status = {
            "error": [],
            "warning": [],
            "good": [],
            "maintenance": []
        }
        sss = {"error": {}, "warning": {}, "good": {}, "maintenance": {}}
        # s_def = {
        #     "service": {},
        #     "subscriber": {},
        #     "interface": {}
        # }
        services = defaultdict(list)
        try:
            object_root = Object.objects.filter(id=object_id).first()
        except ValidationError:
            object_root = None
        if object_root:
            con = [str(c) for c in self.get_containers_by_root(object_root.id)]
            moss = moss.filter(container__in=con).order_by("container")
        else:
            moss = moss.exclude(container=None).order_by("container")
            con = list(moss.values_list("container", flat=True))
        mo_ids = list(moss.values_list("id", flat=True))
        # Getting Alarms severity dict MO: Severity @todo List alarms
        if not object_root:
            alarms = self.get_alarms_info(None, alarms_all=True)
        else:
            alarms = self.get_alarms_info(mo_ids)
        # Get maintenance
        maintenance = Maintenance.currently_affected()
        # Getting services
        if not object_root:
            services_map = self.get_objects_summary_met(mo_ids, info_all=True)
        else:
            services_map = self.get_objects_summary_met(mo_ids)
        # Getting containers name and coordinates
        containers = {
            str(o["_id"]): (o["name"], o["data"])
            for o in Object.objects.filter(
                data__geopoint__exists=True,
                id__in=con,
                read_preference=ReadPreference.SECONDARY_PREFERRED,
            ).fields(id=1, name=1, data__geopoint__x=1,
                     data__geopoint__y=1).as_pymongo()
        }
        # Main Loop. Get ManagedObject group by container
        for container, mol in itertools.groupby(moss.values_list(
                "id", "name", "container").order_by("container"),
                                                key=lambda o: o[2]):
            name, data = containers.get(container, ("", {"geopoint": {}}))
            x = data["geopoint"].get("x")
            y = data["geopoint"].get("y")
            ss = {
                "objects": [],
                "total": 0,
                "error": 0,
                "warning": 0,
                "good": 0,
                "maintenance": 0
            }
            for mo_id, mo_name, container in mol:
                # Status by alarm severity
                # s_service = s_services.get(mo_id, s_def)
                status = "good"
                if mo_id in maintenance:
                    status = "maintenance"
                elif 100 < alarms.get(mo_id) <= 2000:
                    status = "warning"
                elif alarms.get(mo_id) > 2000:
                    status = "error"
                objects_status[status] += [mo_id]
                # update_dict(sss[status], s_service["service"])
                ss[status] += 1
                ss["total"] += 1
                services_ss = [
                    "%s-%s" % (sm, status)
                    for sm in services_map.get(mo_id, [self.fake_service])
                ]
                ss["objects"] += [{
                    "id": mo_id,
                    "name": mo_name,
                    "status": status,
                    "services": services_ss
                }]
            if not x or not y:
                continue
            objects += [{
                "name": name,
                "id": str(container),
                "x": x if x > -168 else x + 360,  # For Chukotskiy AO
                "y": y,
                "objects": [],
                "total": 0,
                "error": 0,
                "warning": 0,
                "good": 0,
                "maintenance": 0,
            }]
            objects[-1].update(ss)

        profiles = set()
        for r in ["error", "warning", "good", "maintenance"]:
            if not objects_status[r]:
                continue
            if not object_root and r == "good":
                m_services, m_subscribers = ServiceSummary.get_direct_summary(
                    objects_status[r], summary_all=True)
            else:
                m_services, m_subscribers = ServiceSummary.get_direct_summary(
                    objects_status[r])
            # update_dict(s_services["service"], m["serivce"])
            # if not object_root and r == "good":
            #     for s in s_services["service"]:
            #         if s in m["service"]:
            #             s_services["service"][s] -= m["service"][s]
            #     m = s_services
            profiles |= set(m_services)
            sss[r] = m_services

        for r in sorted(sss,
                        key=lambda k:
                        ("error", "warning", "good", "maintenance").index(k)):
            # for p in sss[r]:
            for p in profiles:
                services[p] += [(r, sss[r].get(p, None))]
        return {
            "objects":
            objects,
            "summary":
            self.f_glyph_summary({
                "service": services
                # "subscriber": subscribers
            }),
        }
Ejemplo n.º 10
0
    def get_ajax_data(self, **kwargs):
        def update_dict(d, s):
            for k in s:
                if k in d:
                    d[k] += s[k]
                else:
                    d[k] = s[k]

        zoom = int(self.handler.get_argument("z"))
        west = float(self.handler.get_argument("w"))
        east = float(self.handler.get_argument("e"))
        north = float(self.handler.get_argument("n"))
        south = float(self.handler.get_argument("s"))
        ms = int(self.handler.get_argument("maintenance"))
        active_layers = [
            l for l in self.get_pop_layers()
            if l.min_zoom <= zoom <= l.max_zoom
        ]
        alarms = []
        services = {}
        subscribers = {}
        t_data = defaultdict(list)
        if self.current_user.is_superuser:
            qs = ActiveAlarm.objects.all()
        else:
            qs = ActiveAlarm.objects.filter(
                adm_path__in=self.get_user_domains())
        if ms == 0:
            # Filter out equipment under maintenance
            qs = qs.filter(
                managed_object__nin=Maintenance.currently_affected())
        for a in qs.only("id", "managed_object", "direct_subscribers",
                         "direct_services"):
            s_sub, s_service = {}, {}
            if a.direct_subscribers:
                s_sub = SummaryItem.items_to_dict(a.direct_subscribers)
            if a.direct_services:
                s_service = SummaryItem.items_to_dict(a.direct_services)
            mo = a.managed_object
            if not mo:
                continue
            if mo.x and mo.y:
                w = ServiceSummary.get_weight({
                    "subscriber": s_sub,
                    "service": s_service
                })
                # @todo: Should we add the object's weight to summary?
                # @todo: Check west/south hemisphere
                if active_layers and west <= mo.x <= east and south <= mo.y <= north:
                    t_data[mo.x, mo.y] += [(mo, w)]
            else:
                w = 0
            alarms += [{
                "alarm_id": str(a.id),
                "managed_object": mo.name,
                "x": mo.x,
                "y": mo.y,
                "w": max(w, 1),
            }]
            if s_service:
                update_dict(services, s_service)
            if s_sub:
                update_dict(subscribers, s_sub)
        links = None
        o_seen = set()
        points = None
        o_data = {}
        if t_data and active_layers:
            # Create lines
            bbox = get_bbox(west, east, north, south)
            lines = []
            for d in ObjectConnection._get_collection().find(
                {
                    "type": "pop_link",
                    "layer": {
                        "$in": [l.id for l in active_layers]
                    },
                    "line": {
                        "$geoIntersects": {
                            "$geometry": bbox
                        }
                    },
                },
                {
                    "_id": 0,
                    "connection": 1,
                    "line": 1
                },
            ):
                for c in d["line"]["coordinates"]:
                    if tuple(c) in t_data:
                        for c in d["line"]["coordinates"]:
                            tc = tuple(c)
                            o_data[tc] = t_data.get(tc, [])
                        o_seen.add(tuple(c))
                        lines += [d["line"]]
                        break
            if lines:
                links = geojson.FeatureCollection(features=lines)
            # Create points
            points = []
            for x, y in o_data:
                mos = {}
                for mo, w in o_data[x, y]:
                    if mo not in mos:
                        mos[mo] = w
                mos = sorted(mos, key=lambda z: mos[z],
                             reverse=True)[:self.TOOLTIP_LIMIT]
                points += [
                    geojson.Feature(
                        geometry=geojson.Point(coordinates=[x, y]),
                        properties={
                            "alarms":
                            len(t_data[x, y]),
                            "objects": [{
                                "id": mo.id,
                                "name": mo.name,
                                "address": mo.address
                            } for mo in mos],
                        },
                    )
                ]
            points = geojson.FeatureCollection(features=points)
        return {
            "alarms":
            alarms,
            "summary":
            self.f_glyph_summary({
                "service": services,
                "subscriber": subscribers
            }),
            "links":
            links,
            "pops":
            points,
        }
Ejemplo n.º 11
0
    def get_data(self):
        def get_container_path(self):
            # Get container path
            if not self.object:
                return None
            cp = []
            if self.object.container:
                c = self.object.container.id
                while c:
                    try:
                        o = Object.objects.get(id=c)
                        # @todo: Address data
                        if o.container:
                            cp.insert(0, {"id": o.id, "name": o.name})
                        c = o.container.id if o.container else None
                    except DoesNotExist:
                        metrics["error", ("type", "no_such_object")] += 1
                        break
            return cp

        if not self.object:
            return None
        # @todo: Stage
        # @todo: Service range
        # @todo: Open TT
        now = datetime.datetime.now()
        # Get object status and uptime

        alarms = list(
            ActiveAlarm.objects.filter(managed_object=self.object.id))

        current_start = None
        duration = None
        if self.object.is_managed:
            if self.object.get_status():
                if alarms:
                    current_state = "alarm"
                else:
                    current_state = "up"
                uptime = Uptime.objects.filter(object=self.object.id,
                                               stop=None).first()
                if uptime:
                    current_start = uptime.start
            else:
                current_state = "down"
                outage = Outage.objects.filter(object=self.object.id,
                                               stop=None).first()
                if outage is not None:
                    current_start = outage.start
        else:
            current_state = "unmanaged"
        if current_start:
            duration = now - current_start

        cp = get_container_path(self)

        # MAC addresses
        macs = []
        o_macs = DiscoveryID.macs_for_object(self.object)
        if o_macs:
            for f, l in o_macs:
                if f == l:
                    macs += [f]
                else:
                    macs += ["%s - %s" % (f, l)]

        # Links
        uplinks = set(self.object.data.uplinks)
        if len(uplinks) > 1:
            if self.object.segment.lost_redundancy:
                redundancy = "L"
            else:
                redundancy = "R"
        else:
            redundancy = "N"
        links = []
        for l in Link.object_links(self.object):
            local_interfaces = []
            remote_interfaces = []
            remote_objects = set()
            for i in l.interfaces:
                if i.managed_object.id == self.object.id:
                    local_interfaces += [i]
                else:
                    remote_interfaces += [i]
                    remote_objects.add(i.managed_object)
            if len(remote_objects) == 1:
                ro = remote_objects.pop()
                if ro.id in uplinks:
                    role = "uplink"
                else:
                    role = "downlink"
                links += [{
                    "id":
                    l.id,
                    "role":
                    role,
                    "local_interface":
                    sorted(local_interfaces,
                           key=lambda x: split_alnum(x.name)),
                    "remote_object":
                    ro,
                    "remote_interface":
                    sorted(remote_interfaces,
                           key=lambda x: split_alnum(x.name)),
                    "remote_status":
                    "up" if ro.get_status() else "down",
                }]
            links = sorted(
                links,
                key=lambda x: (x["role"] != "uplink",
                               split_alnum(x["local_interface"][0].name)),
            )
        # Build global services summary
        service_summary = ServiceSummary.get_object_summary(self.object)

        # Interfaces
        interfaces = []
        metrics_map = [
            "Interface | Load | In",
            "Interface | Load | Out",
            "Interface | Errors | In",
            "Interface | Errors | Out",
        ]

        mo = ManagedObject.objects.filter(id=self.object.id)

        ifaces_metrics, last_ts = get_interface_metrics(mo[0])
        ifaces_metrics = ifaces_metrics[mo[0]]

        objects_metrics, last_time = get_objects_metrics(mo[0])
        objects_metrics = objects_metrics.get(mo[0])

        meta = {}
        metric_type_name = dict(MetricType.objects.filter().scalar(
            "name", "measure"))
        metric_type_field = dict(MetricType.objects.filter().scalar(
            "field_name", "measure"))
        if objects_metrics:
            for path, mres in six.iteritems(objects_metrics):
                for key in mres:
                    metric_name = "%s | %s" % (key, path) if any(
                        path.split("|")) else key
                    meta[metric_name] = {
                        "type": metric_type_name[key],
                        "value": mres[key]
                    }

        for i in Interface.objects.filter(managed_object=self.object.id,
                                          type="physical"):
            load_in = "-"
            load_out = "-"
            errors_in = "-"
            errors_out = "-"
            iface_metrics = ifaces_metrics.get(str(i.name))
            if iface_metrics:
                for key, value in six.iteritems(iface_metrics):
                    if key not in metrics_map:
                        continue
                    metric_type = metric_type_name.get(
                        key) or metric_type_field.get(key)
                    if key == "Interface | Load | In":
                        load_in = ("%s%s" %
                                   (self.humanize_speed(value, metric_type),
                                    metric_type) if value else "-")
                    if key == "Interface | Load | Out":
                        load_out = ("%s%s" %
                                    (self.humanize_speed(value, metric_type),
                                     metric_type) if value else "-")
                    if key == "Interface | Errors | In":
                        errors_in = value if value else "-"
                    if key == "Interface | Errors | Out":
                        errors_out = value if value else "-"
            interfaces += [{
                "id":
                i.id,
                "name":
                i.name,
                "admin_status":
                i.admin_status,
                "oper_status":
                i.oper_status,
                "mac":
                i.mac or "",
                "full_duplex":
                i.full_duplex,
                "load_in":
                load_in,
                "load_out":
                load_out,
                "errors_in":
                errors_in,
                "errors_out":
                errors_out,
                "speed":
                max([i.in_speed or 0, i.out_speed or 0]) / 1000,
                "untagged_vlan":
                None,
                "tagged_vlan":
                None,
                "profile":
                i.profile,
                "service":
                i.service,
                "service_summary":
                service_summary.get("interface").get(i.id, {}),
                "description":
                i.description,
            }]

            si = list(i.subinterface_set.filter(enabled_afi="BRIDGE"))
            if len(si) == 1:
                si = si[0]
                interfaces[-1]["untagged_vlan"] = si.untagged_vlan
                interfaces[-1]["tagged_vlans"] = list_to_ranges(
                    si.tagged_vlans).replace(",", ", ")
        interfaces = sorted(interfaces, key=lambda x: split_alnum(x["name"]))
        # Resource groups
        # Service groups (i.e. server)
        static_services = set(self.object.static_service_groups)
        service_groups = []
        for rg_id in self.object.effective_service_groups:
            rg = ResourceGroup.get_by_id(rg_id)
            service_groups += [{
                "id": rg_id,
                "name": rg.name,
                "technology": rg.technology,
                "is_static": rg_id in static_services,
            }]
        # Client groups (i.e. client)
        static_clients = set(self.object.static_client_groups)
        client_groups = []
        for rg_id in self.object.effective_client_groups:
            rg = ResourceGroup.get_by_id(rg_id)
            client_groups += [{
                "id": rg_id,
                "name": rg.name,
                "technology": rg.technology,
                "is_static": rg_id in static_clients,
            }]
        # @todo: Administrative domain path
        # Alarms
        alarm_list = []
        for a in alarms:
            alarm_list += [{
                "id": a.id,
                "root_id": self.get_root(alarms),
                "timestamp": a.timestamp,
                "duration": now - a.timestamp,
                "subject": a.subject,
                "managed_object": a.managed_object,
                "service_summary": {
                    "service": SummaryItem.items_to_dict(a.total_services),
                    "subscriber":
                    SummaryItem.items_to_dict(a.total_subscribers),
                },
                "alarm_class": a.alarm_class,
            }]
        alarm_list = sorted(alarm_list, key=operator.itemgetter("timestamp"))

        # Maintenance
        maintenance = []
        for m in Maintenance.objects.filter(
                affected_objects__object=self.object.id,
                is_completed=False,
                start__lte=now + datetime.timedelta(hours=1),
        ):
            maintenance += [{
                "maintenance": m,
                "id": m.id,
                "subject": m.subject,
                "start": m.start,
                "stop": m.stop,
                "in_progress": m.start <= now,
            }]
        # Get Inventory
        inv = []
        for p in self.object.get_inventory():
            c = self.get_nested_inventory(p)
            c["name"] = p.name or self.object.name
            inv += [c]
        # Build result

        if self.object.platform is not None:
            platform = self.object.platform.name
        else:
            platform = "Unknown"
        if self.object.version is not None:
            version = self.object.version.version
        else:
            version = ""

        r = {
            "id":
            self.object.id,
            "object":
            self.object,
            "name":
            self.object.name,
            "address":
            self.object.address,
            "platform":
            platform,
            # self.object.platform.name if self.object.platform else "Unknown",
            "version":
            version,
            # self.object.version.version if self.object.version else "",
            "description":
            self.object.description,
            "object_profile":
            self.object.object_profile.id,
            "object_profile_name":
            self.object.object_profile.name,
            "macs":
            ", ".join(sorted(macs)),
            "segment":
            self.object.segment,
            "firmware_status":
            FirmwarePolicy.get_status(self.object.platform,
                                      self.object.version),
            "firmware_recommended":
            FirmwarePolicy.get_recommended_version(self.object.platform),
            "service_summary":
            service_summary,
            "container_path":
            cp,
            "current_state":
            current_state,
            # Start of uptime/downtime
            "current_start":
            current_start,
            # Current uptime/downtime
            "current_duration":
            duration,
            "service_groups":
            service_groups,
            "client_groups":
            client_groups,
            "tt": [],
            "links":
            links,
            "alarms":
            alarm_list,
            "interfaces":
            interfaces,
            "metrics":
            meta,
            "maintenance":
            maintenance,
            "redundancy":
            redundancy,
            "inventory":
            self.flatten_inventory(inv),
            "serial_number":
            self.object.get_attr("Serial Number"),
            "attributes":
            list(
                ManagedObjectAttribute.objects.filter(
                    managed_object=self.object.id)),
            "confdb":
            self.object.get_confdb(),
        }
        return r
Ejemplo n.º 12
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.º 13
0
    def _get_path_summary_bulk(self):
        def list_to_dict(summary):
            if not summary:
                return {}
            return {d["profile"]: d["summary"] for d in summary}

        def e_list_to_dict(summary):
            if not summary:
                return {}
            return {d.profile: d.summary for d in summary}

        def dict_to_list(d):
            return [{"profile": k, "summary": d[k]} for k in sorted(d)]

        def get_summary(docs, key, direct=None):
            r = direct.copy() if direct else {}
            for doc in docs:
                dv = doc.get(key)
                if not dv:
                    continue
                for k in dv:
                    nv = dv[k]
                    if nv:
                        r[k] = r.get(k, 0) + nv
            return r

        def get_root_path(alarm_id, path=None):
            path = path or []
            if alarm_id in path:
                raise ValueError("Loop detected: %s" % (str(x) for x in path))
            path = path + [alarm_id]
            root = alarms[alarm_id].get("root")
            if not root:
                return path
            return get_root_path(root, path)

        alarms = {}  # id -> alarm doc
        children = defaultdict(list)  # id -> [alarm doc, ..]
        # Inject current alarm
        alarms[self.id] = {
            "_id": self.id,
            "root": self.root,
            "severity": self.severity,
            "total_objects": e_list_to_dict(self.total_objects),
            "total_services": e_list_to_dict(self.total_services),
            "total_subscribers": e_list_to_dict(self.total_subscribers),
        }
        # Collect relevant neighbors
        for doc in ActiveAlarm._get_collection().aggregate([
                # Starting from given alarm
            {
                "$match": {
                    "_id": self.root
                }
            },
                # Add to 'path' field all alarm upwards
            {
                "$graphLookup": {
                    "from": "noc.alarms.active",
                    "connectFromField": "root",
                    "connectToField": "_id",
                    "startWith": "$root",
                    "as": "path",
                    "maxDepth": 50,
                }
            },
                # Append the necessary fields of given alarm to 'path' field
                # and wipe out all other fields
            {
                "$project": {
                    "_id": 0,
                    "path": {
                        "$concatArrays": [
                            "$path",
                            [{
                                "_id": "$_id",
                                "root": "$root",
                                "severity": "$severity",
                                "direct_services": "$direct_services",
                                "direct_subscribers": "$direct_subscribers",
                                "total_objects": "$total_objects",
                                "total_services": "$total_services",
                                "total_subscribers": "$total_subscribers",
                            }],
                        ]
                    },
                }
            },
                # Convert path field to the list of documents
            {
                "$unwind": "$path"
            },
                # Normalize resulting documents
            {
                "$project": {
                    "_id": "$path._id",
                    "root": "$path.root",
                    "severity": "$path.severity",
                    "direct_services": "$path.direct_services",
                    "direct_subscribers": "$path.direct_subscribers",
                    "total_objects": "$path.total_objects",
                    "total_services": "$path.total_services",
                    "total_subscribers": "$path.total_subscribers",
                }
            },
                # Add all children alarms to 'children' field
            {
                "$lookup": {
                    "from": "noc.alarms.active",
                    "localField": "_id",
                    "foreignField": "root",
                    "as": "children",
                }
            },
                # Append the neccessary fields of path alarms to `children` field
                # and wipe out all other fields
            {
                "$project": {
                    "_id": 0,
                    "children": {
                        "$concatArrays": [
                            "$children",
                            [{
                                "_id": "$_id",
                                "root": "$root",
                                "severity": "$severity",
                                "direct_services": "$direct_services",
                                "direct_subscribers": "$direct_subscribers",
                                "total_objects": "$total_objects",
                                "total_services": "$total_services",
                                "total_subscribers": "$total_subscribers",
                            }],
                        ]
                    },
                }
            },
                # Convert path field to the list of documents
            {
                "$unwind": "$children"
            },
                # Normalize resulting documents
            {
                "$project": {
                    "_id": "$children._id",
                    "root": "$children.root",
                    "severity": "$children.severity",
                    "direct_services": "$children.direct_services",
                    "direct_subscribers": "$children.direct_subscribers",
                    "total_objects": "$children.total_objects",
                    "total_services": "$children.total_services",
                    "total_subscribers": "$children.total_subscribers",
                }
            },
        ]):
            # May contains duplicates, perform deduplication
            doc["direct_services"] = list_to_dict(doc.get("direct_services"))
            doc["direct_subscribers"] = list_to_dict(
                doc.get("direct_subscribers"))
            doc["total_objects"] = list_to_dict(doc.get("total_objects"))
            doc["total_services"] = list_to_dict(doc.get("total_services"))
            doc["total_subscribers"] = list_to_dict(
                doc.get("total_subscribers"))
            if doc["_id"] == self.id:
                doc["root"] = self.root
            alarms[doc["_id"]] = doc

        for doc in alarms.values():
            children[doc.get("root")] += [doc]

        # Get path to from current root upwards to global root
        # Check for loops, raise Value error if loop detected
        root_path = get_root_path(self.root)
        bulk = []
        now = datetime.datetime.now()
        for root in root_path:
            doc = alarms[root]
            consequences = children[root]
            total_objects = get_summary(
                consequences, "total_objects",
                {self.managed_object.object_profile.id: 1})
            total_services = get_summary(consequences, "total_services",
                                         doc.get("direct_services"))
            total_subscribers = get_summary(consequences, "total_subscribers",
                                            doc.get("direct_subscribers"))
            if (doc["total_objects"] != total_objects
                    or doc["total_services"] != total_services
                    or doc["total_subscribers"] != total_subscribers):
                # Changed
                severity = ServiceSummary.get_severity({
                    "service":
                    total_services,
                    "subscriber":
                    total_subscribers,
                    "objects":
                    total_objects,
                })
                op = {
                    "$set": {
                        "severity": severity,
                        "total_objects": dict_to_list(total_objects),
                        "total_services": dict_to_list(total_services),
                        "total_subscribers": dict_to_list(total_subscribers),
                    }
                }
                if severity != doc.get("severity"):
                    op["$push"] = {
                        "log": {
                            "timestamp": now,
                            "from_status": "A",
                            "to_status": "A",
                            "message": "Severity changed to %d" % severity,
                        }
                    }
                bulk += [UpdateOne({"_id": root}, op)]
        return bulk
Ejemplo n.º 14
0
    def get_data(self):
        def update_dict(s, d):
            for k in d:
                if k in s:
                    s[k] += d[k]
                else:
                    s[k] = d[k]

        stpl = self.object.type.card_template or self.default_title_template
        now = datetime.datetime.now()
        if self.object.start > now:
            status = "before"
        elif self.object.is_completed:
            status = "complete"
        else:
            status = "progress"
        # Calculate affected objects
        affected = []
        summary = {"service": {}, "subscriber": {}}
        # Maintenance
        data = [
            d
            for d in AffectedObjects._get_collection().aggregate(
                [
                    {"$match": {"maintenance": self.object.id}},
                    {
                        "$project": {"objects": "$affected_objects.object"},
                    },
                ]
            )
        ]
        hide = False
        if data:
            if len(data[0].get("objects")) > 100:
                hide = True
            for mo in (
                ManagedObject.objects.filter(is_managed=True, id__in=data[0].get("objects"))
                .values("id", "name", "platform", "address", "container")
                .distinct()
            ):
                ss, object = {}, None
                if not hide:
                    ss = ServiceSummary.get_object_summary(mo["id"])
                    object = ManagedObject.get_by_id(mo["id"])
                    update_dict(summary["service"], ss.get("service", {}))
                    update_dict(summary["subscriber"], ss.get("subscriber", {}))
                ao = {
                    "id": mo["id"],
                    "name": mo["name"],
                    "address": mo["address"],
                    "platform": Platform.get_by_id(mo["platform"]).name if mo["platform"] else "",
                    "summary": ss,
                }
                if object:
                    ao["object"] = object
                affected += [ao]
        #
        return {
            "title": jinja2.Template(stpl).render({"object": self.object}),
            "object": self.object,
            "subject": self.object.subject,
            "contacts": self.object.contacts,
            "start": self.object.start,
            "stop": self.object.stop,
            "description": self.object.description,
            "status": status,
            "affected": affected,
            "summary": summary,
        }
Ejemplo n.º 15
0
    def get_data(self):

        intervals = (
            ("y", 31557617),  # 60 * 60 * 24 * 7 * 52
            ("w", 604800),  # 60 * 60 * 24 * 7
            ("d", 86400),  # 60 * 60 * 24
            ("h", 3600),  # 60 * 60
            ("m", 60),
            ("s", 1),
        )

        def display_time(seconds):
            result = []

            for name, count in intervals:
                value = seconds // count
                if value:
                    seconds -= value * count
                    if value == 1:
                        name = name.rstrip("s")
                    result.append("{}{}".format(value, name))
            return ", ".join(result[:-1])

        def sortdict(dct):
            kys = sorted(dct.keys())
            res = OrderedDict()
            for x in kys:
                for k, v in dct.items():
                    if k == x:
                        res[k] = v
            return res

        def get_container_path(self):
            # Get container path
            if not self.object:
                return None
            cp = []
            if self.object.container:
                c = self.object.container.id
                while c:
                    try:
                        o = Object.objects.get(id=c)
                        # @todo: Address data
                        if o.container:
                            cp.insert(0, {"id": o.id, "name": o.name})
                        c = o.container.id if o.container else None
                    except DoesNotExist:
                        metrics["error", ("type", "no_such_object")] += 1
                        break
            return cp

        if not self.object:
            return None
        # @todo: Stage
        # @todo: Service range
        # @todo: Open TT
        now = datetime.datetime.now()
        # Get object status and uptime

        alarms = list(ActiveAlarm.objects.filter(managed_object=self.object.id))

        current_start = None
        duration = None
        if self.object.is_managed:
            if self.object.get_status():
                if alarms:
                    current_state = "alarm"
                else:
                    current_state = "up"
                uptime = Uptime.objects.filter(object=self.object.id, stop=None).first()
                if uptime:
                    current_start = uptime.start
            else:
                current_state = "down"
                outage = Outage.objects.filter(object=self.object.id, stop=None).first()
                if outage is not None:
                    current_start = outage.start
        else:
            current_state = "unmanaged"
        if current_start:
            duration = now - current_start

        cp = get_container_path(self)

        # MAC addresses
        macs = []
        o_macs = DiscoveryID.macs_for_object(self.object)
        if o_macs:
            for f, l in o_macs:
                if f == l:
                    macs += [f]
                else:
                    macs += ["%s - %s" % (f, l)]
        # Hostname
        hostname = ""
        did = DiscoveryID.objects.filter(object=self.object.id).first()
        if did and did.hostname:
            hostname = did.hostname
        # Links
        uplinks = set(self.object.data.uplinks)
        if len(uplinks) > 1:
            if self.object.segment.lost_redundancy:
                redundancy = "L"
            else:
                redundancy = "R"
        else:
            redundancy = "N"
        links = []
        for _link in Link.object_links(self.object):
            local_interfaces = []
            remote_interfaces = []
            remote_objects = set()
            for iface in _link.interfaces:
                if iface.managed_object.id == self.object.id:
                    local_interfaces += [iface]
                else:
                    remote_interfaces += [iface]
                    remote_objects.add(iface.managed_object)
            if len(remote_objects) == 1:
                ro = remote_objects.pop()
                if ro.id in uplinks:
                    role = "uplink"
                else:
                    role = "downlink"
                links += [
                    {
                        "id": _link.id,
                        "role": role,
                        "local_interface": sorted(
                            local_interfaces, key=lambda x: alnum_key(x.name)
                        ),
                        "remote_object": ro,
                        "remote_interface": sorted(
                            remote_interfaces, key=lambda x: alnum_key(x.name)
                        ),
                        "remote_status": "up" if ro.get_status() else "down",
                    }
                ]
            links = sorted(
                links,
                key=lambda x: (x["role"] != "uplink", alnum_key(x["local_interface"][0].name)),
            )
        # Build global services summary
        service_summary = ServiceSummary.get_object_summary(self.object)

        # Interfaces
        interfaces = []

        mo = ManagedObject.objects.filter(id=self.object.id)
        mo = mo[0]

        ifaces_metrics, last_ts = get_interface_metrics(mo)
        ifaces_metrics = ifaces_metrics[mo]

        objects_metrics, last_time = get_objects_metrics(mo)
        objects_metrics = objects_metrics.get(mo)

        # Sensors
        sensors_metrics = None
        s_metrics = None
        sensors = {}
        s_meta = []
        STATUS = {0: "OK", 1: "Alarm"}
        meric_map = {}
        if mo.get_caps().get("Sensor | Controller"):
            for mc in MetricType.objects.filter(scope=MetricScope.objects.get(name="Environment")):
                if meric_map:
                    meric_map["map"].update({mc.field_name: mc.name})
                else:
                    meric_map = {"table_name": mc.scope.table_name, "map": {mc.field_name: mc.name}}
            sensors_metrics, last_ts = get_interface_metrics(mo, meric_map)
            sensors_metrics = sensors_metrics[mo]

        m_tp = {}
        if mo.object_profile.metrics:
            for mt in mo.object_profile.metrics:
                if mt.get("threshold_profile"):
                    threshold_profile = ThresholdProfile.get_by_id(mt.get("threshold_profile"))
                    m_tp[MetricType.get_by_id(mt.get("metric_type")).name] = threshold_profile
        data = {}
        meta = []
        metric_type_name = dict(MetricType.objects.filter().scalar("name", "measure"))
        metric_type_field = dict(MetricType.objects.filter().scalar("field_name", "measure"))
        if objects_metrics:
            for path, mres in objects_metrics.items():
                t_v = False
                for key in mres:
                    m_path = path if any(path.split("|")) else key
                    m_path = " | ".join(kk.strip() for kk in m_path.split("|"))
                    if m_tp.get(key):
                        t_v = self.get_threshold_config(m_tp.get(key), int(mres[key]))
                    val = {
                        "name": m_path,
                        "type": "" if m_path == "Object | SysUptime" else metric_type_name[key],
                        "value": display_time(int(mres[key]))
                        if m_path == "Object | SysUptime"
                        else mres[key],
                        "threshold": t_v,
                    }
                    if data.get(key):
                        data[key] += [val]
                    else:
                        data[key] = [val]

        data = sortdict(data)
        for k, d in data.items():
            collapsed = False
            if len(d) == 1:
                collapsed = True
            for dd in d:
                isdanger = False
                if dd["threshold"]:
                    isdanger = True
                    collapsed = True
            meta.append({"name": k, "value": d, "collapsed": collapsed, "isdanger": isdanger})

        for i in Interface.objects.filter(managed_object=self.object.id, type="physical"):
            load_in = "-"
            load_out = "-"
            errors_in = "-"
            errors_out = "-"
            iface_metrics = ifaces_metrics.get(str(i.name))

            if iface_metrics:
                for key, value in iface_metrics.items():
                    metric_type = metric_type_name.get(key) or metric_type_field.get(key)
                    if key == "Interface | Load | In":
                        load_in = (
                            "%s%s" % (self.humanize_speed(value, metric_type), metric_type)
                            if value
                            else "-"
                        )
                    if key == "Interface | Load | Out":
                        load_out = (
                            "%s%s" % (self.humanize_speed(value, metric_type), metric_type)
                            if value
                            else "-"
                        )
                    if key == "Interface | Errors | In":
                        errors_in = value if value else "-"
                    if key == "Interface | Errors | Out":
                        errors_out = value if value else "-"
            interfaces += [
                {
                    "id": i.id,
                    "name": i.name,
                    "admin_status": i.admin_status,
                    "oper_status": i.oper_status,
                    "mac": i.mac or "",
                    "full_duplex": i.full_duplex,
                    "load_in": load_in,
                    "load_out": load_out,
                    "errors_in": errors_in,
                    "errors_out": errors_out,
                    "speed": max([i.in_speed or 0, i.out_speed or 0]) / 1000,
                    "untagged_vlan": None,
                    "tagged_vlan": None,
                    "profile": i.profile,
                    "service": i.service,
                    "service_summary": service_summary.get("interface").get(i.id, {}),
                    "description": i.description,
                }
            ]
            if sensors_metrics:
                s_metrics = sensors_metrics.get(str(i.name))
            if s_metrics:
                sens_metrics = []
                for i_metrics in i.profile.metrics:
                    sens_metrics.append(i_metrics.metric_type.name)
                for key, value in s_metrics.items():
                    if key not in sens_metrics:
                        continue
                    val = {
                        "name": key,
                        "type": metric_type_name[key],
                        "value": STATUS.get(value) if metric_type_name[key] == " " else value,
                        "threshold": None,
                    }
                    if sensors.get(i.name):
                        sensors[i.name] += [val]
                    else:
                        sensors[i.name] = [val]

            si = list(i.subinterface_set.filter(enabled_afi="BRIDGE"))
            if len(si) == 1:
                si = si[0]
                interfaces[-1]["untagged_vlan"] = si.untagged_vlan
                interfaces[-1]["tagged_vlans"] = list_to_ranges(si.tagged_vlans).replace(",", ", ")

        if sensors:
            sensors = sortdict(sensors)
            for k, d in sensors.items():
                for dd in d:
                    isdanger = False
                    if dd["threshold"]:
                        isdanger = True
                s_meta.append({"name": k, "value": d, "isdanger": isdanger})

        interfaces = sorted(interfaces, key=lambda x: alnum_key(x["name"]))
        # Resource groups
        # Service groups (i.e. server)
        static_services = set(self.object.static_service_groups)
        service_groups = []
        for rg_id in self.object.effective_service_groups:
            rg = ResourceGroup.get_by_id(rg_id)
            service_groups += [
                {
                    "id": rg_id,
                    "name": rg.name,
                    "technology": rg.technology,
                    "is_static": rg_id in static_services,
                }
            ]
        # Client groups (i.e. client)
        static_clients = set(self.object.static_client_groups)
        client_groups = []
        for rg_id in self.object.effective_client_groups:
            rg = ResourceGroup.get_by_id(rg_id)
            client_groups += [
                {
                    "id": rg_id,
                    "name": rg.name,
                    "technology": rg.technology,
                    "is_static": rg_id in static_clients,
                }
            ]
        # @todo: Administrative domain path
        # Alarms
        alarm_list = []
        for a in alarms:
            alarm_list += [
                {
                    "id": a.id,
                    "root_id": self.get_root(alarms),
                    "timestamp": a.timestamp,
                    "duration": now - a.timestamp,
                    "subject": a.subject,
                    "managed_object": a.managed_object,
                    "service_summary": {
                        "service": SummaryItem.items_to_dict(a.total_services),
                        "subscriber": SummaryItem.items_to_dict(a.total_subscribers),
                    },
                    "alarm_class": a.alarm_class,
                }
            ]
        alarm_list = sorted(alarm_list, key=operator.itemgetter("timestamp"))

        # Maintenance
        maintenance = []
        for m in Maintenance.objects.filter(
            affected_objects__object=self.object.id,
            is_completed=False,
            start__lte=now + datetime.timedelta(hours=1),
        ):
            maintenance += [
                {
                    "maintenance": m,
                    "id": m.id,
                    "subject": m.subject,
                    "start": m.start,
                    "stop": m.stop,
                    "in_progress": m.start <= now,
                }
            ]
        # Get Inventory
        inv = []
        for p in self.object.get_inventory():
            c = self.get_nested_inventory(p)
            c["name"] = p.name or self.object.name
            inv += [c]
        # Build result

        if self.object.platform is not None:
            platform = self.object.platform.name
        else:
            platform = "Unknown"
        if self.object.version is not None:
            version = self.object.version.version
        else:
            version = ""

        r = {
            "id": self.object.id,
            "object": self.object,
            "name": self.object.name,
            "address": self.object.address,
            "platform": platform,
            # self.object.platform.name if self.object.platform else "Unknown",
            "version": version,
            # self.object.version.version if self.object.version else "",
            "description": self.object.description,
            "object_profile": self.object.object_profile.id,
            "object_profile_name": self.object.object_profile.name,
            "hostname": hostname,
            "macs": ", ".join(sorted(macs)),
            "segment": self.object.segment,
            "firmware_status": FirmwarePolicy.get_status(self.object.platform, self.object.version),
            "firmware_recommended": FirmwarePolicy.get_recommended_version(self.object.platform),
            "service_summary": service_summary,
            "container_path": cp,
            "current_state": current_state,
            # Start of uptime/downtime
            "current_start": current_start,
            # Current uptime/downtime
            "current_duration": duration,
            "service_groups": service_groups,
            "client_groups": client_groups,
            "tt": [],
            "links": links,
            "alarms": alarm_list,
            "interfaces": interfaces,
            "metrics": meta,
            "sensors": s_meta,
            "maintenance": maintenance,
            "redundancy": redundancy,
            "inventory": self.flatten_inventory(inv),
            "serial_number": self.object.get_attr("Serial Number"),
            "attributes": list(
                ManagedObjectAttribute.objects.filter(managed_object=self.object.id)
            ),
            "confdb": None,
        }
        try:
            r["confdb"] = self.object.get_confdb()
        except (SyntaxError, ValueError):
            pass
        return r
Ejemplo n.º 16
0
    def get_data(self):
        def get_segment_path(segment):
            if segment.parent:
                return segment_path[segment.parent] + [segment]
            else:
                return [segment]

        def update_summary(segment):
            """
            Calculate summary for segment and all nested segments
            """
            services = {}
            subscribers = {}
            # Calculate direct segments' coverage
            for o in segment["objects"].values():
                update_dict(services, o["services"])
                update_dict(subscribers, o["subscribers"])
            # Flatten objects
            segment["objects"] = sorted(segment["objects"].values(), key=lambda x: -x["weight"])
            # Calculate children's coverage
            for s in segment["segments"].values():
                update_summary(s)
                update_dict(services, s["services"])
                update_dict(subscribers, s["subscribers"])
            segment["segments"] = sorted(segment["segments"].values(), key=lambda x: -x["weight"])
            segment["services"] = services
            segment["subscribers"] = subscribers
            segment["summary"] = {"service": services, "subscriber": subscribers}
            segment["weight"] = ServiceSummary.get_weight(segment["summary"])

        def update_dict(d1, d2):
            for k in d2:
                if k in d1:
                    d1[k] += d2[k]
                else:
                    d1[k] = d2[k]

        segment_path = cachetools.LRUCache(maxsize=10000)
        segment_path.__missing__ = get_segment_path
        # Build tree
        tree = {"segment": None, "segments": {}, "objects": {}, "subscribers": {}, "services": {}}
        if self.current_user.is_superuser:
            qs = ActiveAlarm.objects.filter(root__exists=False)
        else:
            qs = ActiveAlarm.objects.filter(
                adm_path__in=self.get_user_domains(), root__exists=False
            )
        now = datetime.datetime.now()
        for alarm in qs:
            if not alarm.total_services and not alarm.total_subscribers:
                continue
            ct = tree
            for sp in segment_path[alarm.managed_object.segment]:
                if sp.id not in ct["segments"]:
                    ct["segments"][sp.id] = {
                        "segment": sp,
                        "segments": {},
                        "objects": {},
                        "subscribers": {},
                        "services": {},
                    }
                ct = ct["segments"][sp.id]
            subscribers = SummaryItem.items_to_dict(alarm.total_subscribers)
            services = SummaryItem.items_to_dict(alarm.total_services)
            ct["objects"][alarm.id] = {
                "object": alarm.managed_object,
                "alarm": alarm,
                "severity": alarm.severity,
                "timestamp": alarm.timestamp,
                "duration": now - alarm.timestamp,
                "escalation_tt": alarm.escalation_tt,
                "subscribers": subscribers,
                "services": services,
                "summary": {"subscriber": subscribers, "service": services},
            }
            ct["objects"][alarm.id]["weight"] = ServiceSummary.get_weight(
                ct["objects"][alarm.id]["summary"]
            )
        # Calculate segment summaries
        update_summary(tree)
        # Calculate total summaries
        services = {}
        subscribers = {}
        for s in tree["segments"]:
            update_dict(services, s["summary"]["service"])
            update_dict(subscribers, s["summary"]["subscriber"])
        for o in tree["objects"]:
            update_dict(services, o["summary"]["service"])
            update_dict(subscribers, o["summary"]["subscriber"])
        tree["summary"] = {"subscriber": subscribers, "service": services}
        return tree
Ejemplo n.º 17
0
    def get_ajax_data(self, **kwargs):
        def update_dict(d, s):
            for k in s:
                if k in d:
                    d[k] += s[k]
                else:
                    d[k] = s[k]

        zoom = int(self.handler.get_argument("z"))
        west = float(self.handler.get_argument("w"))
        east = float(self.handler.get_argument("e"))
        north = float(self.handler.get_argument("n"))
        south = float(self.handler.get_argument("s"))
        ms = int(self.handler.get_argument("maintenance"))
        active_layers = [
            l_r for l_r in self.get_pop_layers()
            if l_r.min_zoom <= zoom <= l_r.max_zoom
        ]
        alarms = []
        res = {}
        services = {}
        subscribers = {}
        t_data = defaultdict(list)
        mos = ManagedObject.objects.filter(is_managed=True).values(
            "id", "name", "x", "y")
        if not self.current_user.is_superuser:
            mos = mos.filter(administrative_domain__in=UserAccess.get_domains(
                self.current_user))
        for mo in mos:
            res[mo.pop("id")] = mo
        mos_id = list(res.keys())
        if ms == 0:
            mos_id = list(
                set(list(res.keys())) - set(Maintenance.currently_affected()))
        for a in ActiveAlarm._get_collection().find(
            {"managed_object": {
                "$in": mos_id,
                "$exists": True
            }},
            {
                "_id": 1,
                "managed_object": 1,
                "direct_subscribers": 1,
                "direct_services": 1
            },
        ):
            s_sub, s_service = {}, {}
            if a.get("direct_subscribers"):
                s_sub = {
                    dsub["profile"]: dsub["summary"]
                    for dsub in a["direct_subscribers"]
                }
            if a.get("direct_services"):
                s_service = {
                    dserv["profile"]: dserv["summary"]
                    for dserv in a["direct_services"]
                }
            mo = res.get(a["managed_object"])
            if not mo:
                continue
            if mo["x"] and mo["y"]:
                w = ServiceSummary.get_weight({
                    "subscriber": s_sub,
                    "service": s_service
                })
                # @todo: Should we add the object's weight to summary?
                # @todo: Check west/south hemisphere
                if active_layers and west <= mo["x"] <= east and south <= mo[
                        "y"] <= north:
                    t_data[mo["x"], mo["y"]] += [(mo, w)]
            else:
                w = 0
            alarms += [{
                "alarm_id": str(a.get("_id")),
                "managed_object": mo["name"],
                "x": mo["x"],
                "y": mo["y"],
                "w": max(w, 1),
            }]
            if s_service:
                update_dict(services, s_service)
            if s_sub:
                update_dict(subscribers, s_sub)
        links = None
        o_seen = set()
        points = None
        o_data = {}
        if t_data and active_layers:
            # Create lines
            bbox = get_bbox(west, east, north, south)
            lines = []
            for d in ObjectConnection._get_collection().find(
                {
                    "type": "pop_link",
                    "layer": {
                        "$in": [a_l.id for a_l in active_layers]
                    },
                    "line": {
                        "$geoIntersects": {
                            "$geometry": bbox
                        }
                    },
                },
                {
                    "_id": 0,
                    "connection": 1,
                    "line": 1
                },
            ):
                for c in d["line"]["coordinates"]:
                    if tuple(c) in t_data:
                        for c in d["line"]["coordinates"]:
                            tc = tuple(c)
                            o_data[tc] = t_data.get(tc, [])
                        o_seen.add(tuple(c))
                        lines += [d["line"]]
                        break
            if lines:
                links = geojson.FeatureCollection(features=lines)
            # Create points
            points = []
            for x, y in o_data:
                data = {}
                for mo, w in o_data[x, y]:
                    if mo not in data:
                        data[mo] = w
                data = sorted(data, key=lambda z: data[z],
                              reverse=True)[:self.TOOLTIP_LIMIT]
                points += [
                    geojson.Feature(
                        geometry=geojson.Point(coordinates=[x, y]),
                        properties={
                            "alarms":
                            len(t_data[x, y]),
                            "objects": [{
                                "id": mo.id,
                                "name": mo.name,
                                "address": mo.address
                            } for mo in mos],
                        },
                    )
                ]
            points = geojson.FeatureCollection(features=points)
        return {
            "alarms":
            alarms,
            "summary":
            self.f_glyph_summary({
                "service": services,
                "subscriber": subscribers
            }),
            "links":
            links,
            "pops":
            points,
        }
Ejemplo n.º 18
0
    def _refresh_managed_object(self):
        from noc.sa.models.servicesummary import ServiceSummary

        mo = self.get_managed_object()
        if mo:
            ServiceSummary.refresh_object(mo)
Ejemplo n.º 19
0
    def get_ajax_data(self, **kwargs):
        object_id = self.handler.get_argument("object_id")
        if self.current_user.is_superuser:
            moss = ManagedObject.objects.filter(is_managed=True)
        else:
            moss = ManagedObject.objects.filter(
                is_managed=True,
                administrative_domain__in=self.get_user_domains())
        objects = []
        objects_status = {
            "error": [],
            "warning": [],
            "good": [],
            "maintenance": []
        }
        sss = {"error": {}, "warning": {}, "good": {}, "maintenance": {}}
        services = defaultdict(list)
        try:
            object_root = Object.objects.filter(id=object_id).first()
        except ValidationError:
            object_root = None
        if object_root:
            con = [str(c) for c in self.get_containers_by_root(object_root.id)]
            moss = moss.filter(container__in=con).order_by("container")
        else:
            moss = moss.exclude(container=None).order_by("container")
            con = list(moss.values_list("container", flat=True))
        mo_ids = list(moss.values_list("id", flat=True))
        # Getting Alarms severity dict MO: Severity @todo List alarms
        if not object_root:
            alarms = self.get_alarms_info(None, alarms_all=True)
        else:
            alarms = self.get_alarms_info(mo_ids)
        # Get maintenance
        maintenance = Maintenance.currently_affected()
        # Getting services
        if not object_root:
            services_map = self.get_objects_summary_met(mo_ids, info_all=True)
        else:
            services_map = self.get_objects_summary_met(mo_ids)
        # Getting containers name and coordinates
        containers = {
            str(o["_id"]): (
                o["name"],
                {
                    "%s.%s" % (item["interface"], item["attr"]): item["value"]
                    for item in o.get("data", [])
                },
            )
            for o in Object.objects.
            filter(data__match={
                "interface": "geopoint"
            }, id__in=con).read_preference(ReadPreference.SECONDARY_PREFERRED).
            fields(id=1, name=1, data=1).as_pymongo()
        }
        # Main Loop. Get ManagedObject group by container
        for container, mol in itertools.groupby(moss.values_list(
                "id", "name", "container").order_by("container"),
                                                key=lambda o: o[2]):
            name, data = containers.get(container, ("", {"geopoint": {}}))
            x = data.get("geopoint.x")
            y = data.get("geopoint.y")
            address = data.get("address.text", "")
            ss = {
                "objects": [],
                "total": 0,
                "error": 0,
                "warning": 0,
                "good": 0,
                "maintenance": 0
            }
            for mo_id, mo_name, container in mol:
                # Status by alarm severity
                # s_service = s_services.get(mo_id, s_def)
                status = "good"
                if mo_id in maintenance:
                    status = "maintenance"
                elif 100 < alarms.get(mo_id, 0) <= 2000:
                    status = "warning"
                elif alarms.get(mo_id, 0) > 2000:
                    status = "error"
                objects_status[status] += [mo_id]
                ss[status] += 1
                ss["total"] += 1
                services_ss = [
                    "%s-%s" % (sm, status)
                    for sm in services_map.get(mo_id, [self.fake_service])
                ]
                ss["objects"] += [{
                    "id": mo_id,
                    "name": mo_name,
                    "status": status,
                    "services": services_ss
                }]
            if not x or not y:
                continue
            objects += [{
                "name": address or name,
                "id": str(container),
                "x": x if x > -168 else x + 360,  # For Chukotskiy AO
                "y": y,
                "objects": [],
                "total": 0,
                "error": 0,
                "warning": 0,
                "good": 0,
                "maintenance": 0,
            }]
            objects[-1].update(ss)

        profiles = set()
        for r in ["error", "warning", "good", "maintenance"]:
            if not objects_status[r]:
                continue
            if not object_root and r == "good":
                m_services, m_subscribers = ServiceSummary.get_direct_summary(
                    objects_status[r], summary_all=True)
            else:
                m_services, m_subscribers = ServiceSummary.get_direct_summary(
                    objects_status[r])
            profiles |= set(m_services)
            sss[r] = m_services
        for r in sorted(sss,
                        key=lambda k:
                        ("error", "warning", "good", "maintenance").index(k)):
            for p in profiles:
                services[p] += [(r, sss[r].get(p, None))]
        return {
            "objects": objects,
            "summary": self.f_glyph_summary({"service": services}),
        }
Ejemplo n.º 20
0
 def raise_alarm(self, r, e):
     managed_object = self.eval_expression(r.managed_object, event=e)
     if not managed_object:
         self.logger.info("Empty managed object, ignoring")
         return
     # @todo: Make configurable
     if not managed_object.is_managed:
         self.logger.info(
             "Managed object is not managed. Do not raise alarm")
         return
     if e.managed_object.id != managed_object.id:
         metrics["alarm_change_mo"] += 1
         self.logger.info("Changing managed object to %s",
                          managed_object.name)
     discriminator, vars = r.get_vars(e)
     if r.unique:
         assert discriminator is not None
         a = ActiveAlarm.objects.filter(
             managed_object=managed_object.id,
             discriminator=discriminator).first()
         if not a:
             # Try to reopen alarm
             a = ArchivedAlarm.objects.filter(
                 managed_object=managed_object.id,
                 discriminator=discriminator,
                 control_time__gte=e.timestamp).first()
             if a:
                 # Reopen alarm
                 self.logger.info("[%s|%s|%s] %s reopens alarm %s(%s)",
                                  e.id, managed_object.name,
                                  managed_object.address,
                                  e.event_class.name, a.alarm_class.name,
                                  a.id)
                 a = a.reopen("Reopened by disposition rule '%s'" %
                              r.u_name)
                 metrics["alarm_reopen"] += 1
         if a:
             # Active alarm found, refresh
             self.logger.info(
                 "[%s|%s|%s] Contributing event %s to active alarm %s(%s)",
                 e.id, managed_object.name, managed_object.address,
                 e.event_class.name, a.alarm_class.name, a.id)
             # Contribute event to alarm
             e.contribute_to_alarm(a)
             if e.timestamp < a.timestamp:
                 # Set to earlier date
                 a.timestamp = e.timestamp
                 a.save()
             elif e.timestamp > a.last_update:
                 # Refresh last update
                 a.last_update = e.timestamp
                 a.save()
             metrics["alarm_contribute"] += 1
             return
     # Calculate alarm coverage
     summary = ServiceSummary.get_object_summary(managed_object)
     summary["object"] = {managed_object.object_profile.id: 1}
     #
     severity = max(ServiceSummary.get_severity(summary), 1)
     self.logger.info("[%s|%s|%s] %s: Calculated alarm severity is: %s",
                      e.id, managed_object.name, managed_object.address,
                      r.u_name, severity)
     # Create new alarm
     a = ActiveAlarm(
         timestamp=e.timestamp,
         last_update=e.timestamp,
         managed_object=managed_object.id,
         alarm_class=r.alarm_class,
         severity=severity,
         vars=vars,
         discriminator=discriminator,
         direct_services=SummaryItem.dict_to_items(summary["service"]),
         direct_subscribers=SummaryItem.dict_to_items(
             summary["subscriber"]),
         total_objects=ObjectSummaryItem.dict_to_items(summary["object"]),
         total_services=SummaryItem.dict_to_items(summary["service"]),
         total_subscribers=SummaryItem.dict_to_items(summary["subscriber"]),
         log=[
             AlarmLog(timestamp=datetime.datetime.now(),
                      from_status="A",
                      to_status="A",
                      message="Alarm risen from event %s(%s) by rule '%s'" %
                      (str(e.id), str(e.event_class.name), r.u_name))
         ],
         opening_event=e.id)
     a.save()
     e.contribute_to_alarm(a)
     self.logger.info("[%s|%s|%s] %s raises alarm %s(%s): %r", e.id,
                      managed_object.name, managed_object.address,
                      e.event_class.name, a.alarm_class.name, a.id, a.vars)
     metrics["alarm_raise"] += 1
     self.correlate(r, a)
     # Notify about new alarm
     if not a.root:
         a.managed_object.event(
             a.managed_object.EV_ALARM_RISEN, {
                 "alarm": a,
                 "subject": a.subject,
                 "body": a.body,
                 "symptoms": a.alarm_class.symptoms,
                 "recommended_actions": a.alarm_class.recommended_actions,
                 "probable_causes": a.alarm_class.probable_causes
             },
             delay=a.alarm_class.get_notification_delay())
     # Gather diagnostics when necessary
     AlarmDiagnosticConfig.on_raise(a)
     # Watch for escalations, when necessary
     if config.correlator.auto_escalation and not a.root:
         AlarmEscalation.watch_escalations(a)