From e61692148cd0267e9455997e2dc4e8302d91f6d6 Mon Sep 17 00:00:00 2001 From: Andrey Vertiprahov Date: Thu, 19 Aug 2021 09:49:20 +0500 Subject: [PATCH] Add defaults to workflow fields. --- inv/models/sensorprofile.py | 5 +- pm/models/agentprofile.py | 9 +- sa/models/serviceprofile.py | 8 +- sla/models/slaprofile.py | 5 +- ui/web/inv/sensorprofile/Application.js | 2 +- ui/web/pm/agentprofile/Application.js | 2 +- ui/web/sla/slaprofile/Application.js | 2 +- wf/migrations/0012_agent_default.py | 196 ++++++++++++++++++++++++ wf/models/workflow.py | 25 ++- 9 files changed, 241 insertions(+), 13 deletions(-) create mode 100644 wf/migrations/0012_agent_default.py diff --git a/inv/models/sensorprofile.py b/inv/models/sensorprofile.py index 87af730a99..e1998580bd 100644 --- a/inv/models/sensorprofile.py +++ b/inv/models/sensorprofile.py @@ -8,6 +8,7 @@ # NOC modules from threading import Lock import operator +from functools import partial # Third-party modules from mongoengine.document import Document, EmbeddedDocument @@ -51,7 +52,9 @@ class SensorProfile(Document): name = StringField(unique=True) description = StringField() - workflow = PlainReferenceField(Workflow) + workflow = PlainReferenceField( + Workflow, default=partial(Workflow.get_default_workflow, "inv.SensorProfile") + ) style = ForeignKeyField(Style) enable_collect = BooleanField(default=False) collect_interval = IntField(default=60) diff --git a/pm/models/agentprofile.py b/pm/models/agentprofile.py index ebb5832d12..bfd2c0a50c 100644 --- a/pm/models/agentprofile.py +++ b/pm/models/agentprofile.py @@ -8,6 +8,7 @@ # Python modules import operator from threading import Lock +from functools import partial # Third-party modules from mongoengine.document import Document @@ -28,15 +29,17 @@ class AgentProfile(Document): name = StringField(unique=True) description = StringField() - zk_check_interval = IntField() - workflow = PlainReferenceField(Workflow) + zk_check_interval = IntField(default=60) + workflow = PlainReferenceField( + Workflow, default=partial(Workflow.get_default_workflow, "pm.AgentProfile") + ) update_addresses = BooleanField(default=True) _id_cache = cachetools.TTLCache(maxsize=100, ttl=60) _default_cache = cachetools.TTLCache(maxsize=100, ttl=60) DEFAULT_PROFILE_NAME = "default" - DEFAULT_WORKFLOW_NAME = "Default" + DEFAULT_WORKFLOW_NAME = "Agent Default" def __str__(self): return self.name diff --git a/sa/models/serviceprofile.py b/sa/models/serviceprofile.py index 1de75b1edb..da9bd5118f 100644 --- a/sa/models/serviceprofile.py +++ b/sa/models/serviceprofile.py @@ -8,6 +8,7 @@ # Python modules import operator from threading import Lock +from functools import partial # Third-party modules from pymongo import UpdateOne @@ -60,7 +61,9 @@ class ServiceProfile(Document): display_order = IntField(default=100) # Show in total summary show_in_summary = BooleanField(default=True) - workflow = PlainReferenceField(Workflow) + workflow = PlainReferenceField( + Workflow, default=partial(Workflow.get_default_workflow, "sa.ServiceProfile") + ) # Auto-assign interface profile when service binds to interface interface_profile = ReferenceField(InterfaceProfile) # Alarm weight @@ -80,6 +83,9 @@ class ServiceProfile(Document): _id_cache = cachetools.TTLCache(maxsize=100, ttl=60) + DEFAULT_PROFILE_NAME = "default" + DEFAULT_WORKFLOW_NAME = "Service Default" + def __str__(self): return self.name diff --git a/sla/models/slaprofile.py b/sla/models/slaprofile.py index 5ba09ca2c5..b5f9ba7921 100644 --- a/sla/models/slaprofile.py +++ b/sla/models/slaprofile.py @@ -8,6 +8,7 @@ # Python modules from threading import Lock import operator +from functools import partial # Third-party modules from mongoengine.document import Document, EmbeddedDocument @@ -59,7 +60,9 @@ class SLAProfile(Document): name = StringField(unique=True) description = StringField() # - workflow = PlainReferenceField(Workflow) + workflow = PlainReferenceField( + Workflow, default=partial(Workflow.get_default_workflow, "sla.SLAProfile") + ) style = ForeignKeyField(Style, required=False) # Agent collected intervale collect_interval = IntField(default=120) diff --git a/ui/web/inv/sensorprofile/Application.js b/ui/web/inv/sensorprofile/Application.js index 12bc8409ce..4b1c3a3dfc 100644 --- a/ui/web/inv/sensorprofile/Application.js +++ b/ui/web/inv/sensorprofile/Application.js @@ -57,7 +57,7 @@ Ext.define("NOC.inv.sensorprofile.Application", { name: "workflow", xtype: "wf.workflow.LookupField", fieldLabel: __("WorkFlow"), - allowBlank: false + allowBlank: true }, { name: "style", diff --git a/ui/web/pm/agentprofile/Application.js b/ui/web/pm/agentprofile/Application.js index 0853445697..bd7419ce29 100644 --- a/ui/web/pm/agentprofile/Application.js +++ b/ui/web/pm/agentprofile/Application.js @@ -63,7 +63,7 @@ Ext.define("NOC.pm.agentprofile.Application", { name: "workflow", xtype: "wf.workflow.LookupField", fieldLabel: __("Workflow"), - allowBlank: false + allowBlank: true } ] }); diff --git a/ui/web/sla/slaprofile/Application.js b/ui/web/sla/slaprofile/Application.js index d99064fdc6..1cd76f5e01 100644 --- a/ui/web/sla/slaprofile/Application.js +++ b/ui/web/sla/slaprofile/Application.js @@ -56,7 +56,7 @@ Ext.define("NOC.sla.slaprofile.Application", { name: "workflow", xtype: "wf.workflow.LookupField", fieldLabel: __("WorkFlow"), - allowBlank: false + allowBlank: true }, { name: "style", diff --git a/wf/migrations/0012_agent_default.py b/wf/migrations/0012_agent_default.py new file mode 100644 index 0000000000..0f16b34432 --- /dev/null +++ b/wf/migrations/0012_agent_default.py @@ -0,0 +1,196 @@ +# ---------------------------------------------------------------------- +# Agent Default workflow +# ---------------------------------------------------------------------- +# Copyright (C) 2007-2020 The NOC Project +# See LICENSE for details +# ---------------------------------------------------------------------- + +# Third-party modules +from bson import ObjectId + +# NOC modules +from noc.core.migration.base import BaseMigration + + +class Migration(BaseMigration): + def migrate(self): + db = self.mongo_db + # Workflow + db["workflows"].insert_one( + { + "_id": ObjectId("610bcff0902971a3863306fb"), + "name": "Agent Default", + "is_active": True, + "description": "Agent Default Workflow", + "bi_id": 3468966898630074545, + } + ) + # State + db["states"].insert_many( + [ + { + "_id": ObjectId("610be4c771b6da38e5f5acb2"), + "workflow": ObjectId("610bcff0902971a3863306fb"), + "name": "Approved", + "description": "Agent is approved for ready", + "is_default": False, + "is_productive": False, + "update_last_seen": False, + "ttl": 0, + "update_expired": False, + "on_enter_handlers": [], + "on_leave_handlers": [], + "x": 260, + "y": 50, + "labels": ["noc::agent::auth::pre"], + "effective_labels": ["noc::agent::auth::pre"], + "bi_id": 3373553393116727828, + }, + { + "_id": ObjectId("610be3c671b6da38e5f5acb0"), + "workflow": ObjectId("610bcff0902971a3863306fb"), + "name": "New", + "description": "New registered agent on System", + "is_default": True, + "is_productive": False, + "update_last_seen": False, + "ttl": 0, + "update_expired": False, + "on_enter_handlers": [], + "on_leave_handlers": [], + "x": 50, + "y": 50, + "labels": ["noc::agent::auth::none"], + "effective_labels": ["noc::agent::auth::none"], + "bi_id": 6693212396144621794, + }, + { + "_id": ObjectId("610bd09371b6da38e5f5acae"), + "workflow": ObjectId("610bcff0902971a3863306fb"), + "name": "Ready", + "description": "Agent is in productive usage", + "is_default": False, + "is_productive": True, + "update_last_seen": True, + "ttl": 0, + "update_expired": False, + "on_enter_handlers": [], + "on_leave_handlers": [], + "x": 260, + "y": 200, + "labels": ["noc::agent::auth::auth"], + "effective_labels": ["noc::agent::auth::auth"], + "bi_id": 6323558026723790432, + }, + { + "_id": ObjectId("610be4fd902971a3863306ff"), + "workflow": ObjectId("610bcff0902971a3863306fb"), + "name": "Removing", + "description": "Agent is removed from system use", + "is_default": False, + "is_productive": False, + "update_last_seen": False, + "ttl": 0, + "update_expired": False, + "on_enter_handlers": [], + "on_leave_handlers": [], + "x": 350, + "y": 370, + "labels": ["noc::agent::auth::none"], + "effective_labels": ["noc::agent::auth::none"], + "bi_id": 5644536921567111119, + }, + { + "_id": ObjectId("610be4d9902971a3863306fd"), + "workflow": ObjectId("610bcff0902971a3863306fb"), + "name": "Suspended", + "description": "Agent is temporary suspended/blocked for organisational reasons", + "is_default": False, + "is_productive": False, + "update_last_seen": False, + "ttl": 0, + "update_expired": False, + "on_enter_handlers": [], + "on_leave_handlers": [], + "x": 140, + "y": 300, + "labels": ["noc::agent::auth::pre"], + "effective_labels": ["noc::agent::auth::pre"], + "bi_id": 7418372945801511030, + }, + ] + ) + # Transitions + db["transitions"].insert_many( + [ + { + "_id": ObjectId("610be699902971a386330701"), + "workflow": ObjectId("610bcff0902971a3863306fb"), + "from_state": ObjectId("610be4c771b6da38e5f5acb2"), + "to_state": ObjectId("610bd09371b6da38e5f5acae"), + "is_active": True, + "event": "seen", + "label": "Seen", + "enable_manual": True, + "handlers": [], + "vertices": [], + "bi_id": 2789875778847456366, + "description": "", + }, + { + "_id": ObjectId("610be6b471b6da38e5f5acb5"), + "workflow": ObjectId("610bcff0902971a3863306fb"), + "from_state": ObjectId("610bd09371b6da38e5f5acae"), + "to_state": ObjectId("610be4d9902971a3863306fd"), + "is_active": True, + "event": "suspend", + "label": "Suspend", + "enable_manual": True, + "handlers": [], + "vertices": [], + "bi_id": 7385490058000949812, + "description": "", + }, + { + "_id": ObjectId("610be6c771b6da38e5f5acb7"), + "workflow": ObjectId("610bcff0902971a3863306fb"), + "from_state": ObjectId("610be4d9902971a3863306fd"), + "to_state": ObjectId("610bd09371b6da38e5f5acae"), + "is_active": True, + "event": "resume", + "label": "Resume", + "enable_manual": True, + "handlers": [], + "vertices": [], + "bi_id": 3738440408351158595, + "description": "", + }, + { + "_id": ObjectId("610be6f871b6da38e5f5acb9"), + "workflow": ObjectId("610bcff0902971a3863306fb"), + "from_state": ObjectId("610be4d9902971a3863306fd"), + "to_state": ObjectId("610be4fd902971a3863306ff"), + "is_active": True, + "label": "Remove", + "enable_manual": True, + "handlers": [], + "vertices": [], + "bi_id": 6195769163155286672, + "description": "", + }, + { + "_id": ObjectId("610be76671b6da38e5f5acbb"), + "workflow": ObjectId("610bcff0902971a3863306fb"), + "from_state": ObjectId("610be3c671b6da38e5f5acb0"), + "to_state": ObjectId("610be4c771b6da38e5f5acb2"), + "is_active": True, + "event": "approve", + "label": "Approve", + "enable_manual": True, + "handlers": [], + "vertices": [], + "bi_id": 8807158971147672185, + "description": "", + }, + ] + ) diff --git a/wf/models/workflow.py b/wf/models/workflow.py index 1438a07de1..c8ba65414c 100644 --- a/wf/models/workflow.py +++ b/wf/models/workflow.py @@ -9,6 +9,7 @@ from threading import Lock import operator import logging +from typing import Optional # Third-party modules from mongoengine.document import Document @@ -59,22 +60,38 @@ class Workflow(Document): # Object id in BI bi_id = LongField(unique=True) - _id_cache = cachetools.TTLCache(maxsize=1000, ttl=60) - _bi_id_cache = cachetools.TTLCache(maxsize=1000, ttl=60) + DEFAULT_WORKFLOW_NAME = "Default" + + _id_cache = cachetools.TTLCache(maxsize=100, ttl=60) + _name_cache = cachetools.TTLCache(maxsize=100, ttl=60) + _bi_id_cache = cachetools.TTLCache(maxsize=100, ttl=60) def __str__(self): return self.name @classmethod @cachetools.cachedmethod(operator.attrgetter("_id_cache"), lock=lambda _: id_lock) - def get_by_id(cls, id): + def get_by_id(cls, id) -> Optional["Workflow"]: return Workflow.objects.filter(id=id).first() @classmethod @cachetools.cachedmethod(operator.attrgetter("_bi_id_cache"), lock=lambda _: id_lock) - def get_by_bi_id(cls, id): + def get_by_bi_id(cls, id) -> Optional["Workflow"]: return Workflow.objects.filter(bi_id=id).first() + @classmethod + @cachetools.cachedmethod(operator.attrgetter("_name_cache"), lock=lambda _: id_lock) + def get_by_name(cls, name) -> Optional["Workflow"]: + return Workflow.objects.filter(name=name).first() + + @classmethod + def get_default_workflow(cls, model_id): + from noc.models import get_model + + model = get_model(model_id) + workflow = getattr(model, "DEFAULT_WORKFLOW_NAME", cls.DEFAULT_WORKFLOW_NAME) + return Workflow.get_by_name(workflow) + @cachetools.cached(_default_state_cache, key=lambda x: str(x.id), lock=id_lock) def get_default_state(self): from .state import State -- GitLab