Verified Commit 9e1dfe8d authored by Dmitry Volodin's avatar Dmitry Volodin
Browse files

ConfDB query parameters

parent 270ddd34
......@@ -12,8 +12,14 @@ import operator
import os
# Third-party modules
from mongoengine.document import Document
from mongoengine.fields import StringField, UUIDField, BooleanField
from mongoengine.document import Document, EmbeddedDocument
from mongoengine.fields import (
StringField,
UUIDField,
BooleanField,
ListField,
EmbeddedDocumentField,
)
import six
import cachetools
......@@ -21,22 +27,47 @@ import cachetools
from noc.lib.prettyjson import to_json
from noc.lib.text import quote_safe_path
from noc.core.model.decorator import on_delete_check
from noc.sa.interfaces.base import StringParameter, IntParameter, BooleanParameter
id_lock = threading.Lock()
TYPE_MAP = {"str": StringParameter(), "int": IntParameter(), "bool": BooleanParameter()}
@six.python_2_unicode_compatible
class ConfDBQueryParam(EmbeddedDocument):
meta = {"strict": True}
name = StringField()
type = StringField(choices=["str", "int", "bool"])
default = StringField()
description = StringField()
def __str__(self):
return self.name
def to_json(self):
return {
"name": self.name,
"type": self.type,
"description": self.description,
"default": self.default,
}
def get_parameter(self):
return TYPE_MAP[self.type]
@on_delete_check(
check=[
("cm.ObjectValidationPolicy", "filer_query"),
("cm.ObjectValidationPolicy", "rules.query"),
("cm.ObjectValidationPolicy", "rules.filer_query"),
# ("cm.ObjectValidationPolicy", "rules.query"),
# ("cm.ObjectValidationPolicy", "rules.filer_query"),
]
)
@six.python_2_unicode_compatible
class ConfDBQuery(Document):
meta = {
"collection": "confdbqueries",
"strict": True,
"strict": False,
"auto_create_index": False,
"json_collection": "cm.confdbqueries",
"json_unique_fields": ["name"],
......@@ -46,6 +77,7 @@ class ConfDBQuery(Document):
uuid = UUIDField(binary=True)
description = StringField()
source = StringField()
params = ListField(EmbeddedDocumentField(ConfDBQueryParam))
allow_object_filter = BooleanField(default=False)
allow_interface_filter = BooleanField(default=False)
allow_object_validation = BooleanField(default=False)
......@@ -74,7 +106,10 @@ class ConfDBQuery(Document):
:param kwargs: Optional arguments
:return:
"""
for ctx in engine.query(self.source, **kwargs):
params = kwargs.copy()
for p in self.params:
params[p.name] = p.get_parameter().clean(params.get(p.name, p.default))
for ctx in engine.query(self.source, **params):
yield ctx
def any(self, engine, **kwargs):
......@@ -92,6 +127,7 @@ class ConfDBQuery(Document):
"$collection": self._meta["json_collection"],
"uuid": self.uuid,
"source": self.source,
"params": [p.to_json() for p in self.params],
"allow_object_filter": self.allow_object_filter,
"allow_interface_filter": self.allow_interface_filter,
"allow_object_validation": self.allow_object_validation,
......@@ -109,6 +145,7 @@ class ConfDBQuery(Document):
"uuid",
"description",
"source",
"params",
"allow_object_filter",
"allow_interface_filter",
"allow_object_validation",
......
......@@ -13,7 +13,13 @@ import operator
# Third-party modules
from mongoengine.document import Document, EmbeddedDocument
from mongoengine.fields import StringField, BooleanField, ListField, EmbeddedDocumentField
from mongoengine.fields import (
StringField,
BooleanField,
ListField,
EmbeddedDocumentField,
DictField,
)
from jinja2 import Template
import six
import cachetools
......@@ -30,6 +36,7 @@ id_lock = threading.Lock()
@six.python_2_unicode_compatible
class ObjectValidationRule(EmbeddedDocument):
query = PlainReferenceField(ConfDBQuery)
query_params = DictField()
filter_query = PlainReferenceField(ConfDBQuery)
is_active = BooleanField(default=True)
error_code = StringField()
......@@ -79,7 +86,7 @@ class ObjectValidationPolicy(Document):
if rule.filter_query:
if not rule.filter_query.any(engine):
continue
for ctx in rule.query.query(engine):
for ctx in rule.query.query(engine, **rule.query_params):
if "error" in ctx:
tpl = Template(rule.error_text_template)
problem = {
......
......@@ -9,6 +9,7 @@
# NOC modules
from noc.lib.app.extdocapplication import ExtDocApplication
from noc.cm.models.confdbquery import ConfDBQuery
from noc.core.confdb.engine.base import Engine
from noc.core.translation import ugettext as _
......@@ -20,3 +21,13 @@ class ConfDBQueryApplication(ExtDocApplication):
title = "ConfDBQuery"
menu = [_("Setup"), _("ConfDB Queries")]
model = ConfDBQuery
glyph = "file-code-o"
def clean(self, data):
data = super(ConfDBQueryApplication, self).clean(data)
src = data.get("source", "")
try:
Engine().compile(src)
except SyntaxError as e:
raise ValueError("Syntax error: %s", e)
return data
......@@ -20,3 +20,42 @@ class ObjectValidationPolicyApplication(ExtDocApplication):
title = "Object Validation Policy"
menu = [_("Setup"), _("Object Validation Policies")]
model = ObjectValidationPolicy
glyph = "ambulance"
implied_permissions = {
"create": ["cm:confdbquery:lookup", "cm:confdbquery:read"],
"update": ["cm:confdbquery:lookup", "cm:confdbquery:read"],
}
def instance_to_dict(self, o, fields=None, nocustom=False):
v = super(ObjectValidationPolicyApplication, self).instance_to_dict(
o, fields=fields, nocustom=nocustom
)
if v.get("rules") and (not fields or "rules" in fields):
for rule, edoc in zip(o.rules, v["rules"]):
edoc["query_params"] = self.params_to_list(rule, edoc.get("query_params"))
return v
@staticmethod
def params_to_list(rule, params):
params = params or {}
r = []
for p in rule.query.params:
r += [
{
"name": p.name,
"type": p.type,
"value": params.get(p.name) or "",
"default": p.default,
"description": p.description,
}
]
return r
@staticmethod
def list_to_params(params):
return dict((p["name"], p["value"]) for p in params if p["value"] != "")
def clean(self, data):
for rule in data.get("rules", []):
rule["query_params"] = self.list_to_params(rule.get("query_params") or [])
return super(ObjectValidationPolicyApplication, self).clean(data)
......@@ -62,6 +62,44 @@ Ext.define("NOC.cm.confdbquery.Application", {
flex: 1,
mode: "python"
},
{
name: "params",
xtype: "gridfield",
fieldLabel: __("Parameters"),
columns: [
{
dataIndex: "name",
text: __("Name"),
editor: "textfield",
width: 150
},
{
dataIndex: "type",
text: __("Type"),
width: 70,
editor: {
xtype: "combobox",
store: [
["str", "str"],
["int", "int"],
["bool", "bool"]
]
}
},
{
dataIndex: "default",
text: __("Default"),
editor: "textfield",
width: 200
},
{
dataIndex: "description",
text: __("Description"),
editor: "textfield",
flex: 1
}
]
},
{
xtype: "fieldset",
title: __("Allow"),
......
......@@ -54,6 +54,10 @@ Ext.define("NOC.cm.confdbquery.Model", {
{
name: "uuid",
type: "string"
},
{
name: "params",
type: "auto"
}
]
});
\ No newline at end of file
......@@ -11,7 +11,8 @@ Ext.define("NOC.cm.objectvalidationpolicy.Application", {
requires: [
"NOC.cm.objectvalidationpolicy.Model",
"NOC.cm.confdbquery.LookupField",
"NOC.fm.alarmclass.LookupField"
"NOC.fm.alarmclass.LookupField",
"NOC.core.ListFormField"
],
model: "NOC.cm.objectvalidationpolicy.Model",
search: true,
......@@ -23,7 +24,7 @@ Ext.define("NOC.cm.objectvalidationpolicy.Application", {
{
text: __("Name"),
dataIndex: "name",
width: 150
flex: 1
}
],
......@@ -52,75 +53,109 @@ Ext.define("NOC.cm.objectvalidationpolicy.Application", {
},
{
name: "rules",
xtype: "gridfield",
xtype: "listform",
fieldLabel: __("Rules"),
columns: [
items: [
{
text: __("Query"),
dataIndex: "query",
width: 200,
editor: {
xtype: "cm.confdbquery.LookupField",
allowBlank: false,
query: {
name: "query",
xtype: "cm.confdbquery.LookupField",
fieldLabel: __("Query"),
query: {
allow_object_validation: true
}
},
renderer: NOC.render.Lookup("query")
listeners: {
scope: me,
select: me.onSelectQuery
}
},
{
text: __("Filter Query"),
dataIndex: "filter_query",
width: 200,
editor: {
xtype: "cm.confdbquery.LookupField",
allowBlank: false,
query: {
allow_object_filter: true
name: "query_params",
xtype: "gridfield",
fieldLabel: __("Query Parameters"),
columns: [
{
dataIndex: "name",
text: __("Name"),
width: 150
},
{
dataIndex: "type",
text: __("Type"),
width: 70
},
{
dataIndex: "value",
text: __("Value"),
editor: "textfield",
width: 200
},
{
dataIndex: "default",
text: __("Default"),
width: 100
},
{
dataIndex: "description",
text: __("Description"),
flex: 1
}
},
renderer: NOC.render.Lookup("filter_query")
]
},
{
text: __("Active"),
dataIndex: "is_active",
editor: "checkbox",
width: 50,
renderer: NOC.render.Bool
name: "filter_query",
xtype: "cm.confdbquery.LookupField",
fieldLabel: __("Filter Query"),
allowBlank: true,
query: {
allow_object_filter: true
}
},
{
text: __("Code"),
dataIndex: "error_code",
editor: "textfield",
width: 70
name: "is_active",
xtype: "checkbox",
boxLabel: __("Active")
},
{
text: __("Error template"),
dataIndex: "error_text_template",
editor: {
xtype: "textfield",
placeHolder: "{{error}}"
},
flex: 1
name: "error_code",
xtype: "textfield",
fieldLabel: __("Code"),
allowBlank: true
},
{
text: __("Alarm Class"),
dataIndex: "alarm_class",
editor: "fm.alarmclass.LookupField",
width: 120,
renderer: NOC.render.Lookup("alarm_class")
name: "error_text_template",
xtype: "textfield",
fieldLabel: __("Error template"),
placeHolder: "{{error}}",
allowBlank: true,
uiStyle: "extra"
},
{
text: __("Fatal"),
dataIndex: "is_fatal",
editor: "checkbox",
width: 50,
renderer: NOC.render.Bool
name: "alarm_class",
xtype: "fm.alarmclass.LookupField",
fieldLabel: __("Alarm Class"),
allowBlank: true
},
{
name: "is_fatal",
xtype: "checkbox",
boxLabel: __("Fatal")
}
]
}
]
});
me.callParent();
},
//
onSelectQuery: function(field, record) {
var me = this;
Ext.Ajax.request({
url: "/cm/confdbquery/" + record.get("id") + "/",
scope: me,
success: function (response) {
var data = Ext.decode(response.responseText);
field.up().getForm().findField("query_params").setValue(data.params)
}
})
}
});
\ 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