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
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"])
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
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 }
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
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, }
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()
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
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 }), }
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, }
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
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)])
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
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, }
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
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
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, }
def _refresh_managed_object(self): from noc.sa.models.servicesummary import ServiceSummary mo = self.get_managed_object() if mo: ServiceSummary.refresh_object(mo)
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}), }
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)