Esempio n. 1
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. 2
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. 3
0
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
            }))
Esempio n. 4
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
Esempio n. 5
0
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)
Esempio n. 6
0
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
Esempio n. 7
0
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
Esempio n. 8
0
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
Esempio n. 9
0
File: tag.py Progetto: skripkar/noc
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)
Esempio n. 10
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. 11
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. 12
0
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)
Esempio n. 13
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. 14
0
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)
Esempio n. 15
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. 16
0
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]
Esempio n. 17
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. 18
0
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)
Esempio n. 19
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. 20
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