Commit 28cda692 authored by Andrey Vertiprahov's avatar Andrey Vertiprahov
Browse files

Merge branch 'noc-1721' into 'master'

#1721 Add AlarmGroup filter.

See merge request !5905
parents d1041484 df78ac7f
Pipeline #34349 passed with stages
in 48 minutes and 17 seconds
......@@ -27,6 +27,7 @@ from noc.inv.models.object import Object
from noc.inv.models.networksegment import NetworkSegment
from noc.fm.models.activealarm import ActiveAlarm
from noc.fm.models.archivedalarm import ArchivedAlarm
from noc.fm.models.alarmclass import AlarmClass
from noc.fm.models.alarmseverity import AlarmSeverity
from noc.fm.models.activeevent import ActiveEvent
from noc.fm.models.archivedevent import ArchivedEvent
......@@ -162,6 +163,14 @@ class AlarmApplication(ExtApplication):
q["__raw__"].update(af["__raw__"])
del af["__raw__"]
q.update(af)
# Grouped Alarms
if "alarm_group" not in q:
# Show all alarm
q["alarm_group"] = "show"
if q["alarm_group"] == "only":
# Show Only Alarm without group
q["groups"] = []
del q["alarm_group"]
# Exclude maintenance
if "maintenance" not in q:
q["maintenance"] = "hide"
......@@ -212,6 +221,14 @@ class AlarmApplication(ExtApplication):
del q["collapse"]
if c != "0":
q["root__exists"] = False
#
if "ephemeral" in q:
c = q["ephemeral"]
del q["ephemeral"]
if c != "1":
q["alarm_class__nin"] = list(
AlarmClass.objects.filter(is_ephemeral=True).values_list("id")
)
if status == "C":
if (
"timestamp__gte" not in q
......@@ -311,6 +328,7 @@ class AlarmApplication(ExtApplication):
"alarm_class": str(o.alarm_class.id),
"alarm_class__label": o.alarm_class.name,
"timestamp": self.to_json(o.timestamp),
"reference": o.reference,
"subject": o.subject,
"events": n_events,
"duration": o.duration,
......@@ -460,12 +478,27 @@ class AlarmApplication(ExtApplication):
d["events"] = events
# Alarms
children = self.get_nested_alarms(alarm)
if not alarm.groups:
children += self.get_grouped_alarms(alarm)
if children:
d["alarms"] = {"expanded": True, "children": children}
# Subscribers
if alarm.status == "A":
d["subscribers"] = self.get_alarm_subscribers(alarm)
d["is_subscribed"] = user in alarm.subscribers
# Groups
if alarm.groups:
d["groups"] = []
for ag in ActiveAlarm.objects.filter(reference__in=alarm.groups):
d["groups"] += [
{
"id": str(ag.id),
"alarm_class": str(ag.alarm_class.id),
"alarm_class__label": ag.alarm_class.name,
"timestamp": self.to_json(ag.timestamp),
"subject": ag.subject,
}
]
# Apply plugins
plugins = []
acp = alarm.alarm_class.plugins or []
......@@ -480,6 +513,8 @@ class AlarmApplication(ExtApplication):
d.update(dd)
if plugins:
d["plugins"] = plugins
if "reference" in d:
del d["reference"]
return d
def get_alarm_subscribers(self, alarm):
......@@ -529,6 +564,35 @@ class AlarmApplication(ExtApplication):
children += [c]
return children
def get_grouped_alarms(self, alarm):
"""
Return nested alarms as a part of NodeInterface
:param alarm:
:return:
"""
children = []
for a in ActiveAlarm.objects.filter(groups__in=[alarm.reference]):
s = AlarmSeverity.get_severity(a.severity)
c = {
"id": str(a.id),
"subject": a.subject,
"alarm_class": str(a.alarm_class.id),
"alarm_class__label": a.alarm_class.name,
"managed_object": a.managed_object.id,
"managed_object__label": a.managed_object.name,
"timestamp": self.to_json(a.timestamp),
"iconCls": "icon_error",
"row_class": s.style.css_class_name,
}
nc = self.get_nested_alarms(a)
if nc:
c["children"] = nc
c["expanded"] = True
else:
c["leaf"] = True
children += [c]
return children
@view(
url=r"^(?P<id>[a-z0-9]{24})/post/",
method=["POST"],
......@@ -840,6 +904,26 @@ class AlarmApplication(ExtApplication):
r = [x for x in r if x]
return r
def bulk_field_total_grouped(self, data):
if not data:
return data
coll = ActiveAlarm._get_collection()
r = {
c["_id"]: c["count"]
for c in coll.aggregate(
[
{"$match": {"groups": {"$ne": []}}},
{"$unwind": "$groups"},
{"$group": {"_id": "$groups", "count": {"$sum": 1}}},
]
)
}
for x in data:
if "reference" in x:
x["total_grouped"] = r.get(x["reference"], 0)
del x["reference"]
return data
def bulk_field_isinmaintenance(self, data):
if not data:
return data
......
......@@ -13,6 +13,8 @@ Ext.define("NOC.fm.alarm.ApplicationController", {
status: "A",
collapse: 1,
maintenance: "hide",
alarm_group: "show",
ephemeral: 0,
wait_tt: 0,
managed_object: "",
segment: "",
......@@ -48,7 +50,7 @@ Ext.define("NOC.fm.alarm.ApplicationController", {
this.openForm();
} else {
if(url[0] === "fm.alarm") {
if(queryStr && queryStr !== "__format=ext&status=A&maintenance=hide&collapse=1&cleared_after=0") {
if(queryStr && queryStr !== "__format=ext&status=A&alarm_group=show&maintenance=hide&collapse=1&ephemeral=0&cleared_after=0") {
this.deserialize(queryStr, viewModel);
} else { // restore from local store
var filter = window.localStorage.getItem("fm-alarm-filter");
......@@ -297,7 +299,9 @@ Ext.define("NOC.fm.alarm.ApplicationController", {
Ext.each([
{key: "status"},
{key: "maintenance"},
{key: "alarm_group"},
{key: "collapse", defaultValue: 1},
{key: "ephemeral", defaultValue: 0},
{key: "wait_tt", defaultValue: 1},
// search field
{key: "escalation_tt__contains"},
......
......@@ -25,6 +25,14 @@ Ext.define("NOC.fm.alarm.model.Filter", {
name: "maintenance",
type: "string"
},
{
name: "alarm_group",
type: "string"
},
{
name: "ephemeral",
type: "int"
},
{
name: "managed_object",
type: "int"
......
......@@ -202,7 +202,40 @@ Ext.define("NOC.fm.alarm.view.form.Alarm", {
return c ? c : "";
}
}
}
},
{
xtype: "grid",
reference: "fm-alarm-groups",
title: __("Groups"),
scrollable: true,
bind: {
store: "{selectedGroups}"
},
columns: [
{
dataIndex: "id",
text: __("ID"),
width: 150
},
{
dataIndex: "timestamp",
text: __("Time"),
renderer: NOC.render.DateTime,
width: 120
},
{
dataIndex: "alarm_class",
text: __("Class"),
renderer: NOC.render.Lookup("alarm_class"),
width: 200
},
{
dataIndex: "subject",
text: __("Subject"),
flex: 1
}
]
},
]
}
],
......
......@@ -245,6 +245,37 @@ Ext.define("NOC.fm.alarm.view.form.AlarmModel", {
root: data
}
}
},
selectedGroups: {
bind: "{selected.groups}",
deep: true,
get: function(value) {
return {
fields: [
{
name: "id",
type: "string"
},
{
name: "timestamp",
type: "date"
},
{
name: "subject",
type: "string"
},
{
name: "alarm_class",
type: "string"
},
{
name: "alarm_class__label",
type: "string"
}
],
data: value
};
}
}
}
});
\ No newline at end of file
......@@ -302,6 +302,13 @@ Ext.define("NOC.fm.alarm.view.grids.Grid", {
width: 30,
align: "right",
sortable: false
},
{
text: __("Grouped"),
dataIndex: "total_grouped",
width: 30,
align: "right",
sortable: false
}
],
viewConfig: {
......
......@@ -204,7 +204,53 @@ Ext.define("NOC.fm.alarm.view.grids.Sidebar", {
inputValue: "show"
}
]
}
},
{
xtype: "fieldcontainer",
layout: "column",
defaults: {
xtype: "radiogroup",
columns: 2,
labelAlign: "top",
columnWidth: .5
},
items: [
{
fieldLabel: __("Alarm Group"),
name: "alarm_group",
bind: {value: "{alarm_group}"},
items: [
{
boxLabel: __("Only"),
inputValue: "only"
// tooltip: __("Show only alarm causes"),
},
{
boxLabel: __("All"),
inputValue: "show"
// tooltip: __("Show all alarms")
}
]
},
{
name: "ephemeral",
bind: {value: "{ephemeral}"},
fieldLabel: "Ephemeral",
items: [
{
boxLabel: __("Show"),
inputValue: 1
// tooltip: __("Show only waiting confirmation"),
},
{
boxLabel: __("Hide"),
inputValue: 0
// tooltip: __("Show all alarms")
}
]
}
]
},
]
},
{
......
......@@ -57,6 +57,17 @@ Ext.define("NOC.fm.alarm.view.grids.SidebarModel", {
this.set("activeFilter.wait_tt", value.wait_tt);
}
},
ephemeral: {
bind: "{activeFilter.ephemeral}",
get: function(value) {
return {
ephemeral: value
}
},
set: function(value) {
this.set("activeFilter.ephemeral", value.ephemeral);
}
},
maintenance: {
bind: "{activeFilter.maintenance}",
get: function(value) {
......@@ -67,6 +78,17 @@ Ext.define("NOC.fm.alarm.view.grids.SidebarModel", {
set: function(value) {
this.set("activeFilter.maintenance", value.maintenance);
}
},
alarm_group: {
bind: "{activeFilter.alarm_group}",
get: function(value) {
return {
alarm_group: value
}
},
set: function(value) {
this.set("activeFilter.alarm_group", value.alarm_group);
}
}
}
});
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment