class MetricSet(Document): meta = {"collection": "noc.pm.metricsets"} name = StringField(unique=True) is_active = BooleanField(default=True) description = StringField(required=False) interval = IntField(default=60) metrics = ListField(EmbeddedDocumentField(MetricItem)) def __unicode__(self): return self.name def get_effective_metrics(self): """ Returns a list of MetricItems, containing all effective metrics and thresholds for group """ def apply_settings(name, mi): """ Apply settings to node and all children """ dst = mt_tree[name][0] dst.is_active = mi.is_active dst.low_warn = mi.low_warn dst.high_warn = mi.high_warn dst.low_error = mi.low_error dst.high_error = mi.high_error for c in mt_tree[name][1]: apply_settings(c, mi) # Build metric type tree mt_tree = {} # Metric type name -> (metric item, [children]) for mi in self.metrics: mt = mi.metric_type if mt.name in mt_tree: continue # Find all children nmt = [mt] + sorted( MetricType.objects.filter(name__startswith=mt.name + " | "), key=lambda x: len(x.name)) for m in nmt: if m.name in mt_tree: continue mt_tree[m.name] = [ MetricItem(metric_type=m, is_active=True), [] ] parent = " | ".join(p for p in m.name.split(" | ")[:-1]) if parent in mt_tree: mt_tree[parent][1] += [m.name] # Apply settings for mi in self.metrics: apply_settings(mi.metric_type.name, mi) # Fetch leaf nodes r = [mi[0] for mi in mt_tree.itervalues() if not mi[1]] return r
class MRTConfig(Document): meta = {"collection": "noc.mrtconfig", "allow_inheritance": False} name = StringField(unique=True) is_active = BooleanField(default=True) description = StringField(required=False) permission_name = StringField(required=True) selector = ForeignKeyField(ManagedObjectSelector, required=True) reduce_pyrule = ForeignKeyField(PyRule, required=True) map_script = StringField(required=True) timeout = IntField(required=False) def __unicode__(self): return self.name
class ObjectStatus(Document): meta = { "collection": "noc.cache.object_status", "allow_inheritance": False, "indexes": ["object"] } # Object id object = IntField(required=True) # True - object is Up # False - object is Down status = BooleanField() def __unicode__(self): return u"%s: %s" % (self.object, self.status) @classmethod def get_status(cls, object): s = cls.objects.filter(object=object.id).first() if s: return s.status else: return True @classmethod def set_status(cls, object, status): from noc.fm.models.outage import Outage from noc.inv.models.discoveryjob import DiscoveryJob s = cls.objects.filter(object=object.id).first() if s: if s.status != status: s.status = status s.save() if status: # False -> True transition DiscoveryJob.reset_deferred(object) else: # True -> False transition DiscoveryJob.set_deferred(object) else: cls(object=object.id, status=status).save() Outage.register_outage(object, not status)
class Favorites(Document): meta = { "collection": "noc.favorites", "strict": False, "auto_create_index": False, "indexes": ["user", ("user", "app")] } user = ForeignKeyField(User) app = StringField() favorite_app = BooleanField(default=False) favorites = ListField() def unicode(self): return "%s:%s" % (self.user.username, self.app) @classmethod def add_item(cls, user, app_id, item): fv = Favorites.objects.filter( user=user.id, app=app_id).first() if not fv: fv = Favorites(user=user.id, app=app_id, favorites=[]) fi = list(fv.favorites) or [] if item not in fi: logger.info("Setting favorite item %s@%s for user %s", item, app_id, user.username) fv.favorites = fi + [item] fv.save() @classmethod def remove_item(cls, user, app_id, item): fv = Favorites.objects.filter( user=user.id, app=app_id).first() fi = list(fv.favorites) or [] if fv and item and item in fi: logger.info("Resetting favorite item %s@%s for user %s", item, app_id, user.username) fi.remove(item) fv.favorites = fi fv.save()
class InterfaceProfile(Document): """ Interface SLA profile and settings """ meta = {"collection": "noc.interface_profiles", "allow_inheritance": False} name = StringField(unique=True) description = StringField() style = ForeignKeyField(Style, required=False) # Interface-level events processing link_events = StringField(required=True, choices=[("I", "Ignore Events"), ("L", "Log events, do not raise alarms"), ("A", "Raise alarms")], default="A") # Discovery settings mac_discovery = BooleanField(default=False) # check_link alarm job interval settings # Either None or T0,I0,T1,I1,...,Tn-1,In-1,,In # See MultiIntervalJob settings for details check_link_interval = StringField(default=",60") def __unicode__(self): return self.name @classmethod def get_default_profile(cls): try: return cls._default_profile except AttributeError: cls._default_profile = cls.objects.filter(name="default").first() return cls._default_profile def get_probe_config(self, config): try: return get_probe_config(self, config) except ValueError: pass raise ValueError("Invalid config '%s'" % config)
class InterfaceClassificationRule(Document): meta = { "collection": "noc.inv.interfaceclassificationrules", "allow_inheritance": False } name = StringField(required=False) is_active = BooleanField(default=True) description = StringField(required=False) order = IntField() selector = ForeignKeyField(ManagedObjectSelector, required=False) match = ListField( EmbeddedDocumentField(InterfaceClassificationMatch), required=False) profile = PlainReferenceField(InterfaceProfile, default=InterfaceProfile.get_default_profile) def __unicode__(self): r = [unicode(x) for x in self.match] return "%s -> %s" % (", ".join(r), self.profile.name) @property def match_expr(self): """ Stringified match expression """ if not len(self.match): return u"any" elif len(self.match) == 1: return unicode(self.match[0]) else: return u" AND ".join(u"(%s)" % unicode(m) for m in self.match) @classmethod def get_classificator_code(cls): r = ["import re"] mf = [ "gsc = {}", "def classify(interface):", " def in_selector(o, s):", " if s in s_cache:", " return s_cache[s]", " if s in gsc:", " selector = gsc[s]", " else:", " selector = ManagedObjectSelector.objects.get(id=s)", " gsc[s] = selector", " r = o in selector", " s_cache[s] = r", " return r", " s_cache = {}", " mo = interface.managed_object" ] for rule in cls.objects.filter(is_active=True).order_by("order"): rid = str(rule.id) lmn = [] for i, m in enumerate(rule.match): mn = "match_%s_%d" % (rid, i) r += [m.compile(mn)] lmn += ["%s(interface)" % mn] if lmn: mf += [ " if in_selector(mo, %d) and %s:" % (rule.selector.id, " and ".join(lmn)), " return %r" % rule.profile.name ] else: mf += [" return %r" % rule.profile.name] r += mf return "\n".join(r) @classmethod def get_classificator(cls): code = cls.get_classificator_code() + "\nhandlers[0] = classify\n" # Hack to retrieve reference handlers = {} # Compile code exec code in { "re": re, "PrefixTable": PrefixTable, "VCFilter": VCFilter, "ManagedObjectSelector": ManagedObjectSelector, "handlers": handlers } return handlers[0]
class MetricSettingsItem(EmbeddedDocument): metric_set = PlainReferenceField(MetricSet) is_active = BooleanField(default=True) def __unicode__(self): return self.metric_set.name
class Interface(Document): """ Interfaces """ meta = { "collection": "noc.interfaces", "allow_inheritance": False, "indexes": [ ("managed_object", "name"), "mac", ("managed_object", "ifindex") ] } managed_object = ForeignKeyField(ManagedObject) name = StringField() # Normalized via Profile.convert_interface_name type = StringField(choices=[(x, x) for x in INTERFACE_TYPES]) description = StringField(required=False) ifindex = IntField(required=False) mac = StringField(required=False) aggregated_interface = PlainReferenceField("self", required=False) enabled_protocols = ListField(StringField( choices=[(x, x) for x in INTERFACE_PROTOCOLS] ), default=[]) # @todo: admin status + oper status profile = PlainReferenceField(InterfaceProfile, default=InterfaceProfile.get_default_profile) # profile locked on manual user change profile_locked = BooleanField(required=False, default=False) # project = ForeignKeyField(Project) state = ForeignKeyField(ResourceState) vc_domain = ForeignKeyField(VCDomain) # Coverage coverage = PlainReferenceField(Coverage) technologies = ListField(StringField()) PROFILE_LINK = "profile" def __unicode__(self): return u"%s: %s" % (self.managed_object.name, self.name) def save(self, *args, **kwargs): self.name = self.managed_object.profile.convert_interface_name(self.name) if self.mac: self.mac = MACAddressParameter().clean(self.mac) super(Interface, self).save(*args, **kwargs) def delete(self, *args, **kwargs): # Remove all subinterfaces for si in self.subinterface_set.all(): si.delete() # Unlink link = self.link if link: self.unlink() # Flush MACDB MACDB.objects.filter(interface=self.id).delete() # Remove interface super(Interface, self).delete(*args, **kwargs) @property def link(self): """ Return Link instance or None :return: """ return Link.objects.filter(interfaces=self.id).first() @property def is_linked(self): """ Check interface is linked :returns: True if interface is linked, False otherwise """ return bool(Link.objects.filter(interfaces=self.id).limit(1).count()) def unlink(self): """ Remove existing link. Raise ValueError if interface is not linked """ link = self.link if link is None: raise ValueError("Interface is not linked") if link.is_ptp: link.delete() else: raise ValueError("Cannot unlink non p-t-p link") def link_ptp(self, other, method=""): """ Create p-t-p link with other interface Raise ValueError if either of interface already connected. :type other: Interface :returns: Link instance """ # Try to check existing LAG el = Link.objects.filter(interfaces=self.id).first() if el and other not in el.interfaces: el = None if (self.is_linked or other.is_linked) and not el: raise ValueError("Already linked") if self.id == other.id: raise ValueError("Cannot link with self") if self.type in ("physical", "management"): if other.type in ("physical", "management"): # Refine LAG if el: left_ifaces = [i for i in el.interfaces if i not in (self, other)] if left_ifaces: el.interfaces = left_ifaces el.save() else: el.delete() # link = Link(interfaces=[self, other], discovery_method=method) link.save() return link else: raise ValueError("Cannot connect %s interface to %s" % ( self.type, other.type)) elif self.type == "aggregated": # LAG if other.type == "aggregated": # Check LAG size match # Skip already linked members l_members = [i for i in self.lag_members if not i.is_linked] r_members = [i for i in other.lag_members if not i.is_linked] if len(l_members) != len(r_members): raise ValueError("LAG size mismatch") # Create link if l_members: link = Link(interfaces=l_members + r_members, discovery_method=method) link.save() return link else: return else: raise ValueError("Cannot connect %s interface to %s" % ( self.type, other.type)) raise ValueError("Cannot link") @classmethod def get_interface(cls, s): """ Parse <managed object>@<interface> string and return interface instance or None """ if "@" not in s: raise ValueError("Invalid interface: %s" % s) o, i = s.rsplit("@", 1) # Get managed object try: mo = ManagedObject.objects.get(name=o) except ManagedObject.DoesNotExist: raise ValueError("Invalid manged object: %s" % o) # Normalize interface name i = mo.profile.convert_interface_name(i) # Look for interface iface = Interface.objects.filter(managed_object=mo.id, name=i).first() return iface @property def subinterface_set(self): return SubInterface.objects.filter(interface=self.id) @property def lag_members(self): if self.type != "aggregated": raise ValueError("Cannot net LAG members for not-aggregated interface") return Interface.objects.filter(aggregated_interface=self.id) @property def effective_vc_domain(self): if self.type in ("null", "tunnel", "other", "unknown"): return None if self.vc_domain: return self.vc_domain if self.managed_object.vc_domain: return self.managed_object.vc_domain return VCDomain.get_default() def get_probe_config(self, config): # Get via solutions try: return get_probe_config(self, config) except ValueError: pass # Fallback if config == "interface__name": return self.name elif config == "interface__ifindex": if self.ifindex is None: raise ValueError("No ifindex for %s" % self) else: return self.ifindex try: return self.managed_object.get_probe_config(config) except ValueError: pass # Fallback to interface profile return self.profile.get_probe_config(config)