Esempio n. 1
0
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
        })
Esempio n. 2
0
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()
Esempio n. 3
0
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)
Esempio n. 4
0
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()
Esempio n. 5
0
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)
Esempio n. 6
0
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()
Esempio n. 7
0
class Cache(Document):
    meta = {
        "collection": "noc.cache",
        "allow_inheritance": False,
        "indexes": [
            {
                "fields": ["expires"],
                "expireAfterSeconds": 0
            }
        ]
    }
    key = StringField(db_field="_id", primary_key=True)
    value = BinaryField(db_field="v")
    pickled_value = BinaryField(db_field="p")
    expires = DateTimeField(db_field="e")

    def __unicode__(self):
        return unicode(self.key)
Esempio n. 8
0
class PendingLinkCheck(Document):
    """
    Customer MAC address changes
    """
    meta = {
        "collection": "noc.inv.pending_link_check",
        "allow_inheritance": False,
        "indexes": [("method", "local_object")]
    }
    method = StringField()
    local_object = ForeignKeyField(ManagedObject)
    local_interface = StringField()  # optional
    remote_object = ForeignKeyField(ManagedObject)
    remote_interface = StringField()
    expire = DateTimeField()

    def __unicode__(self):
        return u"%s:%s:%s:%s:%s" % (
            self.method, self.local_object.name, self.local_interface,
            self.remote_object.name, self.remote_interface)

    @classmethod
    def submit(cls, method, local_object, local_interface, remote_object,
               remote_interface):
        expire = datetime.datetime.now() + datetime.timedelta(days=2)
        plc = PendingLinkCheck.objects.filter(
            method=method,
            local_object=local_object.id,
            local_interface=local_interface,
            remote_object=remote_object.id,
            remote_interface=remote_interface).first()
        if plc:
            plc.expire = expire
        else:
            plc = cls(method=method,
                      local_object=local_object.id,
                      local_interface=local_interface,
                      remote_object=remote_object.id,
                      remote_interface=remote_interface,
                      expire=expire)
        plc.save()
Esempio n. 9
0
File: link.py Progetto: skripkar/noc
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"
Esempio n. 10
0
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
            })
Esempio n. 11
0
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