class L3Link(Document): """ Network L3 links. Always contains a list of subinterface references """ meta = { "collection": "noc.links", "strict": False, "auto_create_index": False, "indexes": ["subinterfaces", "linked_objects"] } subinterfaces = PlainReferenceListField("inv.SubInterface") # List of linked objects linked_objects = ListField(IntField()) # Name of discovery method or "manual" discovery_method = StringField() # Timestamp of first discovery first_discovered = DateTimeField(default=datetime.datetime.now) # Timestamp of last confirmation last_seen = DateTimeField() # L3 path cost l3_cost = IntField(default=1) def __unicode__(self): return u"(%s)" % ", ".join([unicode(i) for i in self.subinterfaces]) def clean(self): self.linked_objects = sorted( set(i.managed_object.id for i in self.subinterfaces)) super(L3Link, self).clean()
class Reboot(Document): meta = { "collection": "noc.fm.reboots", "indexes": ["object", ("object", "ts")] } object = IntField() ts = DateTimeField() # Recovered time last = DateTimeField() # Last up timestamp def __unicode__(self): return u"%d" % self.object @classmethod def register(cls, managed_object, ts=None, last=None): """ Register reboot. Populated via Uptime.register(...) :param managed_object: Managed object reference :param ts: Recover time :params last: Last seen time """ oid = managed_object.id if not ts: ts = datetime.datetime.now() if not last: last = ts logger.debug("[%s] Register reboot at %s", managed_object.name, ts) cls._get_collection().insert({ "object": oid, "ts": ts, "last": last })
class ObjectMap(Document): meta = { "collection": "noc.cache.object_map", "allow_inheritance": False, "indexes": ["object", "collector"] } # Object id object = IntField(required=True, unique=True) # collector = IntField(required=True) # sources = ListField(StringField()) def __unicode__(self): return u"%s: %s" % (self.object, self.sources) @classmethod def update_map(cls, object, collector, sources): if hasattr(object, "id"): object = object.id if hasattr(collector, "id"): collector = collector.id if not isinstance(sources, (list, tuple)): sources = [sources] cls._get_collection().update( {"object": object}, {"$set": { "collector": collector, "sources": sources }}, upsert=True) @classmethod def delete_map(cls, object): if hasattr(object, "id"): object = object.id cls._get_collection().remove({"object": object}) @classmethod def get_map(cls, collector): c = cls._get_collection() return list( c.find({"collector": collector}, { "object": 1, "sources": 1, "_id": 0 }))
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 SelectorCache(Document): meta = { "collection": "noc.cache.selector", "allow_inheritance": False, "indexes": ["object", "selector", "vc_domain"] } object = IntField(required=True) selector = IntField(required=False) vc_domain = IntField(required=False) def __unicode__(self): return "%s:%s" % (self.object, self.selector) @classmethod def refresh(cls): sliding_job("main.jobs", "sa.refresh_selector_cache", delta=5) @classmethod def get_object_selectors(cls, object): oid = object if hasattr(object, "id"): oid = object.id return cls.objects.filter(object=oid).values_list("selector") @classmethod def rebuild_for_object(cls, object): # Remove old data cls.objects.filter(object=object.id).delete() # r = [] for s in ManagedObjectSelector.objects.filter(is_enabled=True): for o in s.managed_objects: d = o.vc_domain.id if o.vc_domain else None r += [ { "object": o.id, "selector": s.id, "vc_domain": d } ] if r: cls._get_collection().insert(r)
class SubInterface(Document): meta = { "collection": "noc.subinterfaces", "allow_inheritance": False, "indexes": [ ("managed_object", "ifindex"), ("managed_object", "vlan_ids"), "interface", "managed_object", "untagged_vlan", "tagged_vlans", "enabled_afi" ] } interface = PlainReferenceField(Interface) managed_object = ForeignKeyField(ManagedObject) forwarding_instance = PlainReferenceField( ForwardingInstance, required=False) name = StringField() description = StringField(required=False) profile = PlainReferenceField(InterfaceProfile, default=InterfaceProfile.get_default_profile) mtu = IntField(required=False) mac = StringField(required=False) vlan_ids = ListField(IntField(), default=[]) enabled_afi = ListField(StringField( choices=[(x, x) for x in SUBINTERFACE_AFI] ), default=[]) ipv4_addresses = ListField(StringField(), default=[]) ipv6_addresses = ListField(StringField(), default=[]) iso_addresses = ListField(StringField(), default=[]) vpi = IntField(required=False) vci = IntField(required=False) enabled_protocols = ListField(StringField( choices=[(x, x) for x in SUBINTERFACE_PROTOCOLS] ), default=[]) untagged_vlan = IntField(required=False) tagged_vlans = ListField(IntField(), default=[]) # ip_unnumbered_subinterface ifindex = IntField(required=False) # Tunnel services tunnel_type = StringField( choices=[(x, x) for x in TUNNEL_TYPES], required=False) tunnel_local_address = StringField(required=False) tunnel_remote_address = StringField(required=False) project = ForeignKeyField(Project) def __unicode__(self): return "%s %s" % (self.interface.managed_object.name, self.name) @property def effective_vc_domain(self): return self.interface.effective_vc_domain def get_profile(self): if self.profile: return self.profile else: return self.interface.profile
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 Tag(Document): meta = { "collection": "noc.tags", "allow_inheritance": False, "indexes": ["models"] } tag = StringField(unique=True) models = ListField(StringField()) count = IntField(default=0) def __unicode__(self): return self.tag @classmethod def register_tag(cls, tag, model): """ Register new tag occurence :param model: :return: """ cls._get_collection().update({"tag": tag}, { "$addToSet": { "models": model }, "$inc": { "count": 1 } }, upsert=True) @classmethod def unregister_tag(cls, tag, model): """ Unregister tag occurence :param model: :return: """ pass def get_objects(self): """ Return all tagged objects :return: """ r = [] for m in self.models: al, mn = m.split("_", 1) mc = ContentType.objects.get(app_label=al, model=mn) r += [mc.objects.filter(QTags([self.tag]))] return r
class Tag(Document): meta = { "collection": "noc.tags", "strict": False, "auto_create_index": False, "indexes": ["models"] } tag = StringField(unique=True) models = ListField(StringField()) count = IntField(default=0) def __unicode__(self): return self.tag @classmethod def register_tag(cls, tag, model): """ Register new tag occurence :param tag: Tag Name :param model: Model for creating tag :return: """ cls._get_collection().update_one({"tag": tag}, { "$addToSet": { "models": model }, "$inc": { "count": 1 } }, upsert=True) @classmethod def unregister_tag(cls, tag, model): """ Unregister tag occurence :param tag: Tag Name :param model: Model for creating tag :return: """ cls._get_collection().update_one({"tag": tag}, { "$addToSet": { "models": model }, "$inc": { "count": -1 } }, upsert=True)
class Discovery(Document): meta = { "collection": "noc.schedules.inv.discovery", "strict": False, "auto_create_index": False } job_class = StringField(db_field='jcls') schedule = DictField() ts = DateTimeField(db_field='ts') last = DateTimeField() last_success = DateTimeField(db_field='st') last_duration = FloatField(db_field='ldur') last_status = StringField(db_field='ls') status = StringField(db_field='s') managed_object = ForeignKeyField(ManagedObject, db_field='key') data = DictField() traceback = DictField() runs = IntField() faults = IntField(db_field='f') log = ListField() def __unicode__(self): return "%s: %s" % (self.managed_object, self.job_class)
class MACLog(Document): """ Customer MAC address changes """ meta = { "collection": "noc.mac_log", "allow_inheritance": False, "indexes": ["mac", "-timestamp"] } # Todo: Add Validation timestamp = DateTimeField() mac = StringField() vc_domain_name = StringField() vlan = IntField() managed_object_name = StringField() interface_name = StringField()
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 FailedScriptLog(Document): meta = { "collection": "noc.log.sa.failed_scripts", "allow_inheritance": False, "indexes": ["-timestamp", { "fields": ["expires"], "expireAfterSeconds": 0 }] } timestamp = DateTimeField() managed_object = StringField() address = StringField() script = StringField() error_code = IntField() error_text = StringField() expires = DateTimeField() def __unicode__(self): return str(self.id)
class NetworkChartState(Document): """ Network Chart State """ meta = { "collection": "noc.inv.networkchartstate", "allow_inheritance": False, "indexes": [("chart", "type", "object")] } chart = IntField() # Network chart reference type = StringField( choices=[ ("mo", "Managed Object"), ("link", "Link") ]) object = StringField() # Object reference state = DictField() # Arbitrary state data def __unicode__(self): return "%s %s %s" % (self.chart, self.type, self.object)
class Outage(Document): meta = { "collection": "noc.fm.outages", "allow_inheritance": False, "indexes": ["object", "start"] } object = IntField() start = DateTimeField() stop = DateTimeField() # None for active outages def __unicode__(self): return u"%d" % self.object @property def is_active(self): return self.stop is None @classmethod def register_outage(cls, object, status): """ Change current outage status :param cls: :param object: Managed Object :param status: True - if object is down, False - otherwise :return: """ ts = datetime.datetime.now() o = cls.objects.filter( object=object.id, start__lte=datetime.datetime.now()).order_by("-start").first() if o and o.is_active and not status: # Close active outage o.stop = ts o.save() elif status and ((o and not o.is_active) or not o): # Create new outage Outage(object=object.id, start=ts, stop=None).save()
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 Link(Document): """ Network links. Always contains a list of 2*N references. 2 - for fully resolved links 2*N for unresolved N-link portchannel N, N > 2 - broadcast media """ meta = { "collection": "noc.links", "strict": False, "auto_create_index": False, "indexes": ["interfaces", "linked_objects", "linked_segments"] } # Optional link name name = StringField() # Optional description description = StringField() # Optional shape shape = StringField() # List of interfaces interfaces = PlainReferenceListField("inv.Interface") # Link type, detected automatically type = StringField( choices=[ # 2 managed objects, 2 linked interfaces ("p", "Point-to-Point"), # 2 managed objects, even number of linked interfaces (>2) ("a", "Point-to-Point Aggregated"), # >2 managed objects, one uplink ("m", "Point-to-Multipoint"), # >2 managed objects, no dedicated uplink ("M", "Multipoint-to-Multipoint"), # Unknown ("u", "Unknown") ], default="u") # List of linked objects linked_objects = ListField(IntField()) # List of linked segments linked_segments = ListField(ObjectIdField()) # Name of discovery method or "manual" discovery_method = StringField() # Timestamp of first discovery first_discovered = DateTimeField(default=datetime.datetime.now) # Timestamp of last confirmation last_seen = DateTimeField() # L2 path cost l2_cost = IntField(default=1) # L3 path cost l3_cost = IntField(default=1) def __unicode__(self): if self.interfaces: return u"(%s)" % ", ".join(unicode(i) for i in self.interfaces) else: return u"Stale link (%s)" % self.id def iter_changed_datastream(self): if config.datastream.enable_managedobject: for mo_id in self.linked_objects: yield "managedobject", mo_id def clean(self): self.linked_objects = sorted( set(i.managed_object.id for i in self.interfaces)) self.linked_segments = sorted( set(i.managed_object.segment.id for i in self.interfaces)) self.type = self.get_type() def contains(self, iface): """ Check link contains interface :return: boolean """ return iface in self.interfaces @property def is_ptp(self): """ Check link is point-to-point link :return: """ return self.type == "p" or self.type == "a" @property def is_lag(self): """ Check link is unresolved LAG :return: """ return self.type == "p" or self.type == "a" @property def is_broadcast(self): """ Check link is broadcast media :return: """ return not self.is_ptp and not self.is_lag @property def is_loop(self): """ Check link is looping to same object :return: """ return len(self.linked_objects) == 1 @property def interface_ids(self): """ Returns list of interface ids, avoiding dereference :return: """ def q(i): if hasattr(i, "id"): return i.id return i return [q(iface) for iface in self._data.get("interfaces", [])] def other(self, interface): """ Return other interfaces of the link :param interface: :return: """ return [i for i in self.interfaces if i.id != interface.id] def other_ptp(self, interface): """ Return other interface of ptp link :param interface: :return: """ return self.other(interface)[0] def touch(self, method=None): """ Touch last_seen """ now = datetime.datetime.now() op = {"last_seen": now} self.last_seen = now if method: self.discovery_method = method op["discovery_method"] = method # Do not save to prevent rebuilding topology self._get_collection().update({"_id": self.id}, {"$set": op}) # self.save() @classmethod def object_links(cls, object): return Link.objects.filter(linked_objects=object.id) @classmethod def object_links_count(cls, object): return Link.objects.filter(linked_objects=object.id).count() def on_save(self): if not hasattr( self, "_changed_fields") or "interfaces" in self._changed_fields: self.update_topology() def on_delete(self): self.update_topology() @property def managed_objects(self): """ List of connected managed objects """ from noc.sa.models.managedobject import ManagedObject return list(ManagedObject.objects.filter(id__in=self.linked_objects)) @property def segments(self): """ List of segments connected by link :return: """ from noc.inv.models.networksegment import NetworkSegment return list(NetworkSegment.objects.filter(id__in=self.linked_segments)) def update_topology(self): for mo in self.managed_objects: mo.update_topology() def get_type(self): """ Detect link type :return: Link type as value for .type """ n_objects = len(self.linked_objects) n_interfaces = len(self.interfaces) if n_objects == 2 and n_interfaces == 2: return "p" # Point-to-point if n_objects == 2 and n_interfaces > 2 and n_interfaces % 2 == 0: d = defaultdict(int) # object -> count for i in self.interfaces: d[i.managed_object.id] += 1 k = d.keys() if d[k[0]] == d[k[1]]: return "a" # Point-to-Point aggregated if n_objects > 2: if self.type == "m": return "m" else: return "M" return "u"
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)
class Uptime(Document): meta = { "collection": "noc.fm.uptimes", "indexes": ["object", ("object", "stop")] } object = IntField() start = DateTimeField() stop = DateTimeField() # None for active uptime last = DateTimeField() # Last update last_value = FloatField() # Last registred value SEC = datetime.timedelta(seconds=1) FWRAP = float((1 << 32) - 1) / 100.0 WRAP = datetime.timedelta(seconds=FWRAP) WPREC = 0.1 # Wrap precision def __unicode__(self): return u"%d" % self.object @classmethod def is_reboot(cls, old_uptime, new_uptime): """ Returns true if reboot detected :param old_uptime: :param new_uptime: :return: """ if old_uptime > new_uptime: # Check for counter wrap return True return False @classmethod def register(cls, managed_object, uptime): """ Register uptime :param managed_object: Managed object reference :param uptime: Registered uptime in seconds """ if not uptime: return oid = managed_object.id now = datetime.datetime.now() delta = datetime.timedelta(seconds=uptime) logger.debug("[%s] Register uptime %s", managed_object.name, delta) # Update data c = cls._get_collection() d = c.find_one({"object": oid, "stop": None}) if d: # Check for reboot is_rebooted = False if d["last_value"] > uptime: # Check for counter wrapping # Get wrapped delta dl = cls.FWRAP - d["last_value"] + uptime # Get timestamp delta tsd = total_seconds(now - d["last"]) if abs(dl - tsd) > tsd * cls.WPREC: is_rebooted = True else: logger.debug("Counter wrap detected") if is_rebooted: # Reboot registered # Closing existing uptime ts = now - delta logger.debug("[%s] Closing uptime (%s - %s, delta %s)", managed_object.name, d["start"], ts - cls.SEC, delta) c.update({"_id": d["_id"]}, {"$set": {"stop": ts - cls.SEC}}) # Start new uptime logger.debug("[%s] Starting new uptime from %s", managed_object.name, ts) c.insert({ "object": oid, "start": ts, "stop": None, "last": now, "last_value": uptime }) # Reboot.register(managed_object, ts, d["last"]) else: logger.debug("[%s] Refreshing existing uptime (%s - %s)", managed_object.name, d["start"], now) c.update({"_id": d["_id"]}, {"$set": { "last": now, "last_value": uptime }}) else: # First uptime logger.debug("[%s] First uptime from %s", managed_object.name, now) c.insert({ "object": oid, "start": now - delta, "stop": None, "last": now, "last_value": uptime })
class MACDB(Document): """ Customer MAC address database """ meta = { "collection": "noc.macs", "allow_inheritance": False, "indexes": ["mac", "interface"] } # Todo: Add Validation mac = StringField() vc_domain = ForeignKeyField(VCDomain, required=False) vlan = IntField() managed_object = ForeignKeyField(ManagedObject) interface = PlainReferenceField(Interface) last_changed = DateTimeField() def __unicode__(self): return self.mac def save(self): self.mac = MAC(self.mac) if not self.last_changed: self.last_changed = datetime.datetime.now() super(MACDB, self).save() @classmethod def submit(cls, mac, vc_domain, vlan, interface, timestamp=None): """ Submit mac to database Returns True if database been changed :param cls: :param mac: :param interface: :param timestamp: :return: """ if not timestamp: timestamp = datetime.datetime.now() managed_object = interface.managed_object mac = MAC(mac) vcd = vc_domain.id if vc_domain else None m = MACDB.objects.filter(mac=mac, vc_domain=vcd).first() if m: if (managed_object != m.managed_object or interface != m.interface or vlan != m.vlan): # Database change, write history MACLog(timestamp=m.last_changed, mac=mac, vc_domain_name=vc_domain.name if vc_domain else None, vlan=m.vlan, managed_object_name=m.managed_object.name, interface_name=m.interface.name).save() m.vlan = vlan m.managed_object = managed_object m.interface = interface m.last_changed = timestamp m.save() return True else: return False else: MACDB(mac=mac, vc_domain=vc_domain, vlan=vlan, managed_object=managed_object, interface=interface, last_changed=timestamp).save() return True