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_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 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 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, }