class ArchivedEvent(document.Document): """ """ meta = { "collection": "noc.events.archive", "strict": False, "auto_create_index": False, "indexes": ["timestamp", "alarms"], } status = "S" timestamp = fields.DateTimeField(required=True) managed_object = nosql.ForeignKeyField(ManagedObject, required=True) event_class = nosql.PlainReferenceField(EventClass, required=True) start_timestamp = fields.DateTimeField(required=True) repeats = fields.IntField(required=True) raw_vars = nosql.RawDictField() resolved_vars = nosql.RawDictField() vars = fields.DictField() log = fields.ListField(nosql.EmbeddedDocumentField(EventLog)) alarms = fields.ListField(nosql.ObjectIdField()) def __str__(self): return "%s" % self.id @property def duration(self): """ Logged event duration in seconds """ return (self.timestamp - self.start_timestamp).total_seconds() def get_template_vars(self): """ Prepare template variables """ vars = self.vars.copy() vars.update({"event": self}) return vars @property def subject(self): ctx = Context(self.get_template_vars()) s = Template(self.event_class.subject_template).render(ctx) if len(s) >= 255: s = s[:125] + " ... " + s[-125:] return s @property def body(self): ctx = Context(self.get_template_vars()) s = Template(self.event_class.body_template).render(ctx) return s
class Node(nosql.Document): meta = {"collection": "noc.wf.nodes", "allow_inheritance": False} workflow = nosql.PlainReferenceField(Workflow) lane = nosql.PlainReferenceField(Lane) name = nosql.StringField() label = nosql.StringField() description = nosql.StringField() handler = nosql.StringField() # param -> value params = nosql.RawDictField() # Connections next_node = nosql.PlainReferenceField("self") next_true_node = nosql.PlainReferenceField("self") next_false_node = nosql.PlainReferenceField("self") # Graph position x = nosql.IntField() y = nosql.IntField() def __unicode__(self): return "%s %s" % (self.workflow, self.name) @property def handler_class(self): m = __import__("noc.wf.handlers", {}, {}, str(self.handler)) return getattr(m, "%sHandler" % self.handler)
class NewEvent(document.Document): """ Raw unclassified event as written by SAE or collector """ meta = { "collection": "noc.events.new", "allow_inheritance": False, "indexes": ["seq"] } status = "N" # Fields timestamp = fields.DateTimeField(required=True) managed_object = nosql.ForeignKeyField(ManagedObject, required=True) raw_vars = nosql.RawDictField(required=True) log = fields.ListField(fields.EmbeddedDocumentField(EventLog)) seq = fields.BinaryField(max_bytes=8, required=False) def __unicode__(self): return unicode(self.id) def mark_as_failed(self, version, traceback): """ Move event into noc.events.failed """ message = "Failed to classify on NOC version %s" % version log = self.log + [ EventLog(timestamp=datetime.datetime.now(), from_status="N", to_status="F", message=message) ] e = FailedEvent(id=self.id, timestamp=self.timestamp, managed_object=self.managed_object, raw_vars=self.raw_vars, version=version, traceback=traceback, log=log) e.save() self.delete() return e @property def source(self): """ Event source or None """ if self.raw_vars and "source" in self.raw_vars: return self.raw_vars["source"] return None def log_message(self, message): self.log += [ EventLog(timestamp=datetime.datetime.now(), from_status=self.status, to_status=self.status, message=message) ] self.save()
class FailedEvent(document.Document): """ Events that caused noc-classifier traceback """ meta = {"collection": "noc.events.failed", "allow_inheritance": False} status = "F" # Fields timestamp = fields.DateTimeField(required=True) managed_object = nosql.ForeignKeyField(ManagedObject, required=True) raw_vars = nosql.RawDictField(required=True) # NOC version caused traceback version = fields.StringField(required=True) traceback = fields.StringField() log = fields.ListField(fields.EmbeddedDocumentField(EventLog)) def __unicode__(self): return unicode(self.id) def mark_as_new(self, message=None): """ Move to unclassified queue """ if message is None: message = "Reclassification requested" log = self.log + [ EventLog(timestamp=datetime.datetime.now(), from_status="F", to_status="N", message=message) ] e = NewEvent(id=self.id, timestamp=self.timestamp, managed_object=self.managed_object, raw_vars=self.raw_vars, log=log) e.save() self.delete() return e def log_message(self, message): self.log += [ EventLog(timestamp=datetime.datetime.now(), from_status=self.status, to_status=self.status, message=message) ] self.save()
class Process(nosql.Document): meta = { "collection": "noc.wf.processes", "allow_inheritance": False } workflow = nosql.PlainReferenceField(Workflow) node = nosql.PlainReferenceField(Node) context = nosql.RawDictField() start_time = nosql.DateTimeField() trace = nosql.BooleanField(default=False) sleep_time = nosql.IntField() class SleepException(Exception): pass class CannotSleepError(Exception): pass def __unicode__(self): return "%s at %s (%s)" % (self.workflow, self.node, self.id) def info(self, msg): logging.info("[%s (PID: %s)] %s" % ( self.workflow, self.id, msg)) def update_context(self, param, value): self.context[param] = value def step(self): to_sleep = False while not to_sleep: if self.trace: self.info("Entering node '%s' (%s %s) with context %s" % ( self.node.name, self.node.handler, self.node.params, self.context )) handler = self.node.handler_class() try: r = handler.run(self, self.node) except self.SleepException: to_sleep = True if self.trace: self.info("Leaving node '%s' with context %s" % ( self.node.name, self.context )) # Detect next node if handler.conditional: if r: next_node = self.node.next_true_node else: next_node = self.node.next_false_node else: next_node = self.node.next_node # Move to next node if next_node: if self.trace: self.info("Moving to node '%s'" % next_node.name) self.node = next_node self.save() else: if self.trace: self.info("Stopping at node '%s' with context %s" % (self.node.name, self.context)) return True return False # Suspended def schedule(self): submit_job("wf.jobs", "wf.wfstep", key=self.id) def sleep(self, t): if self.node.handler_class().conditional: raise self.CannotSleepError( "Cannot sleep in conditional handler") self.sleep_time = t self.save() raise self.SleepException
class ActiveEvent(document.Document): """ Event in the Active state """ meta = { "collection": "noc.events.active", "allow_inheritance": False, "indexes": [ "timestamp", "discriminator", "alarms", ("timestamp", "event_class", "managed_object") ] } status = "A" # Fields timestamp = fields.DateTimeField(required=True) managed_object = nosql.ForeignKeyField(ManagedObject, required=True) event_class = nosql.PlainReferenceField(EventClass, required=True) start_timestamp = fields.DateTimeField(required=True) repeats = fields.IntField(required=True) raw_vars = nosql.RawDictField() resolved_vars = nosql.RawDictField() vars = fields.DictField() log = fields.ListField(fields.EmbeddedDocumentField(EventLog)) discriminator = fields.StringField(required=False) alarms = fields.ListField(nosql.ObjectIdField()) def __unicode__(self): return u"%s" % self.id def mark_as_new(self, message=None): """ Move to new queue """ if message is None: message = "Reclassification requested" log = self.log + [ EventLog(timestamp=datetime.datetime.now(), from_status="A", to_status="N", message=message) ] e = NewEvent(id=self.id, timestamp=self.timestamp, managed_object=self.managed_object, raw_vars=self.raw_vars, log=log) e.save() self.delete() return e def mark_as_failed(self, version, traceback): """ Move event into noc.events.failed """ message = "Failed to classify on NOC version %s" % version log = self.log + [ EventLog(timestamp=datetime.datetime.now(), from_status="N", to_status="F", message=message) ] e = FailedEvent(id=self.id, timestamp=self.timestamp, managed_object=self.managed_object, raw_vars=self.raw_vars, version=version, traceback=traceback, log=log) e.save() self.delete() return e def mark_as_archived(self, message): log = self.log + [ EventLog(timestamp=datetime.datetime.now(), from_status="A", to_status="S", message=message) ] e = ArchivedEvent(id=self.id, timestamp=self.timestamp, managed_object=self.managed_object, event_class=self.event_class, start_timestamp=self.start_timestamp, repeats=self.repeats, raw_vars=self.raw_vars, resolved_vars=self.resolved_vars, vars=self.vars, log=log, alarms=self.alarms) e.save() self.delete() return e def drop(self): """ Mark event to be dropped. Only for use from event trigger pyrule. All further operations on event may lead to unpredictable results. Event actually deleted by noc-classifier """ self.id = None @property def to_drop(self): """ Check event marked to be dropped """ return self.id is None def log_message(self, message): self.log += [ EventLog(timestamp=datetime.datetime.now(), from_status=self.status, to_status=self.status, message=message) ] self.save() def log_suppression(self, timestamp): """ Increate repeat count and update timestamp, if required """ self.repeats += 1 if timestamp > self.timestamp: self.timestamp = timestamp self.save() @property def duration(self): """ Logged event duration in seconds """ return total_seconds(self.timestamp - self.start_timestamp) def get_template_vars(self): """ Prepare template variables """ vars = self.vars.copy() vars.update({"event": self}) return vars @property def subject(self): ctx = Context(self.get_template_vars()) s = Template(self.event_class.subject_template).render(ctx) if len(s) >= 255: s = s[:125] + " ... " + s[-125:] return s @property def body(self): ctx = Context(self.get_template_vars()) s = Template(self.event_class.body_template).render(ctx) return s @property def managed_object_id(self): """ Hack to return managed_object.id without SQL lookup """ o = self._data["managed_object"] if type(o) in (int, long): return o return o.id