Exemple #1
0
 def api_action_group_edit(self, request):
     validator = DictParameter(
         attrs={"ids": ListOfParameter(element=ModelParameter(self.model), convert=True)}
     )
     rv = self.deserialize(request.body)
     try:
         v = validator.clean(rv)
     except InterfaceTypeError as e:
         self.logger.info("Bad request: %r (%s)", request.body, e)
         return self.render_json(
             {"status": False, "message": "Bad request", "traceback": str(e)},
             status=self.BAD_REQUEST,
         )
     objects = v["ids"]
     del v["ids"]
     try:
         v = self.clean(v)
     except ValueError as e:
         return self.render_json(
             {"status": False, "message": "Bad request", "traceback": str(e)},
             status=self.BAD_REQUEST,
         )
     for o in objects:
         for p in v:
             setattr(o, p, v[p])
         o.save()
     return "%d records has been updated" % len(objects)
Exemple #2
0
class VRFApplication(ExtModelApplication):
    """
    VRF application
    """

    title = _("VRF")
    menu = _("VRF")
    model = VRF
    query_fields = ["name", "rd", "description"]

    mrt_config = {
        "get_vrfs": {
            "map_script": "get_mpls_vpn",
            "access": "import"
        }
    }

    def field_row_class(self, o):
        return o.profile.style.css_class_name if o.profile.style else ""

    def clean(self, data):
        if not data.get("vpn_id"):
            vdata = {"type": "VRF", "name": data["name"], "rd": data.get("rd")}
            data["vpn_id"] = get_vpn_id(vdata)
        return super().clean(data)

    @view(
        url="^bulk/import/$",
        method=["POST"],
        access="import",
        api=True,
        validate={
            "items":
            ListOfParameter(element=DictParameter(
                attrs={
                    "name": StringParameter(),
                    "rd": RDParameter(),
                    "vrf_group": ModelParameter(model=VRFGroup),
                    "afi_ipv4": BooleanParameter(default=False),
                    "afi_ipv6": BooleanParameter(default=False),
                    "description": StringParameter(required=False),
                }))
        },
    )
    def api_bulk_import(self, request, items):
        n = 0
        for i in items:
            if not VRF.objects.filter(name=i["name"], rd=i["rd"]).exists():
                # Add only new
                VRF(
                    name=i["name"],
                    vrf_group=i["vrf_group"],
                    rd=i["rd"],
                    afi_ipv4=i["afi_ipv4"],
                    afi_ipv6=i["afi_ipv6"],
                    description=i.get("description"),
                ).save()
                n += 1
        return {"status": True, "imported": n}
Exemple #3
0
def test_dict_parameter():
    assert DictParameter(attrs={
        "i": IntParameter(),
        "s": StringParameter()
    }).clean({
        "i": 10,
        "s": "ten"
    }) == {
        "i": 10,
        "s": "ten"
    }
    with pytest.raises(InterfaceTypeError):
        DictParameter(attrs={
            "i": IntParameter(),
            "s": StringParameter()
        }).clean({
            "i": "10",
            "x": "ten"
        })
Exemple #4
0
 def clean_config(self, handler):
     v = {}
     if isinstance(handler.config, dict):
         ci = DictParameter(attrs=handler.config)
     else:
         ci = handler.config
     # Read config
     for opt in self.config.options(handler.name):
         if opt not in ("enabled", "handler"):
             v[opt] = self.config.get(handler.name, opt)
     # Clean config
     return ci.clean(v)
Exemple #5
0
 def decorate(f):
     f.url = url
     f.url_name = url_name
     # Process access
     if isinstance(access, bool):
         f.access = Permit() if access else Deny()
     elif isinstance(access, six.string_types):
         f.access = HasPerm(access)
     else:
         f.access = access
     f.menu = menu
     f.method = method
     f.api = api
     if isinstance(validate, dict):
         f.validate = DictParameter(attrs=validate)
     else:
         f.validate = validate
     return f
Exemple #6
0
)
from noc.sa.models.managedobject import ManagedObject
from noc.pm.models.metrictype import MetricType
from noc.core.clickhouse.connect import ClickhouseClient
from noc.core.clickhouse.error import ClickhouseError
from noc.sa.models.profile import Profile
from ..base import NBIAPI

Request = DictParameter(
    attrs={
        "from":
        DateTimeShiftParameter(required=True),
        "to":
        DateTimeShiftParameter(required=True),
        "metrics":
        DictListParameter(
            attrs={
                "object": StringParameter(required=True),
                "interfaces": StringListParameter(required=False),
                "metric_types": StringListParameter(required=True),
            },
            required=True,
        ),
    })

S_INTERFACE = "interface"


class ObjectMetricsAPI(NBIAPI):
    name = "objectmetrics"

    @authenticated
Exemple #7
0
from noc.sa.interfaces.base import (
    DictParameter,
    DictListParameter,
    StringParameter,
    StringListParameter,
    IntParameter,
    ListOfParameter,
    ListParameter,
)
from noc.pm.models.metrictype import MetricType
from noc.services.nbi.base import NBIAPI

Request = DictParameter(
    attrs={
        "org": StringParameter(required=True),
    }
)


class GetoltAPI(NBIAPI):
    name = "getolt"

    @authenticated
    @tornado.gen.coroutine
    def post(self):
        connect()
        code, result = yield self.executor.submit(self.handler)
        self.set_status(code)
        if isinstance(result, six.string_types):
            self.write(result)
Exemple #8
0
def test_dict_parameter_error(raw, config):
    with pytest.raises(InterfaceTypeError):
        assert DictParameter(**config).clean(raw)
Exemple #9
0
def test_dict_parameter(raw, config, expected):
    assert DictParameter(**config).clean(raw) == expected
Exemple #10
0
from noc.core.topology.constraint.base import BaseConstraint
from noc.core.topology.constraint.vlan import VLANConstraint
from noc.core.topology.constraint.upwards import UpwardsConstraint
from noc.core.topology.constraint.any import AnyConstraint
from noc.core.topology.goal.base import BaseGoal
from noc.core.topology.goal.managedobject import ManagedObjectGoal
from noc.core.topology.goal.level import ManagedObjectLevelGoal
from noc.core.text import split_alnum
from ..base import NBIAPI

# Constants
MAX_DEPTH_DEFAULT = 20
N_SHORTEST_DEFAULT = 10

# id/remote system pointer
PointerId = DictParameter(attrs={"id": StringParameter()})
PointerRemote = DictParameter(attrs={
    "remote_system": StringParameter(),
    "remote_id": StringParameter()
})
Pointer = PointerId | PointerRemote

# from: section
ObjectPointer = DictParameter(
    attrs={
        "object":
        Pointer,
        "interface":
        DictParameter(attrs={"name": StringParameter()}, required=False),
    })
InterfacePointer = DictParameter(
Exemple #11
0
class MapApplication(ExtApplication):
    """
    inv.net application
    """

    title = _("Network Map")
    menu = _("Network Map")
    glyph = "globe"

    implied_permissions = {"launch": ["inv:networksegment:lookup"]}

    # Object statuses
    ST_UNKNOWN = 0  # Object state is unknown
    ST_OK = 1  # Object is OK
    ST_ALARM = 2  # Object is reachable, Active alarms
    ST_UNREACH = 3  # Object is unreachable due to other's object failure
    ST_DOWN = 4  # Object is down
    ST_MAINTENANCE = 32  # Maintenance bit

    @view(r"^(?P<id>[0-9a-f]{24})/data/$",
          method=["GET"],
          access="read",
          api=True)
    def api_data(self, request, id):
        def q_mo(d):
            x = d.copy()
            if x["type"] == "managedobject":
                del x["mo"]
                x["external"] = x["id"] not in mos if is_view else x.get(
                    "role") != "segment"
            elif d["type"] == "cloud":
                del x["link"]
                x["external"] = False
            return x

        # Find segment
        segment = self.get_object_or_404(NetworkSegment, id=id)
        if segment.managed_objects.count() > segment.max_objects:
            # Too many objects
            return {
                "id": str(segment.id),
                "name": segment.name,
                "error": _("Too many objects")
            }
        # if we set selector in segment
        is_view = segment.selector
        if is_view:
            mos = segment.selector.managed_objects.values_list("id", flat=True)
        # Load settings
        settings = MapSettings.objects.filter(segment=id).first()
        node_hints = {}
        link_hints = {}
        if settings:
            self.logger.info("Using stored positions")
            for n in settings.nodes:
                node_hints[n.id] = {
                    "type": n.type,
                    "id": n.id,
                    "x": n.x,
                    "y": n.y
                }
            for ll in settings.links:
                link_hints[ll.id] = {
                    "connector":
                    ll.connector if len(ll.vertices) else "normal",
                    "vertices": [{
                        "x": v.x,
                        "y": v.y
                    } for v in ll.vertices],
                }
        else:
            self.logger.info("Generating positions")
        # Generate topology
        topology = SegmentTopology(
            segment,
            node_hints,
            link_hints,
            force_spring=request.GET.get("force") == "spring")
        topology.layout()
        # Build output
        r = {
            "id": str(segment.id),
            "max_links": int(segment.max_shown_downlinks),
            "name": segment.name,
            "caps": list(topology.caps),
            "nodes": [q_mo(x) for x in topology.G.nodes.values()],
            "links": [topology.G[u][v] for u, v in topology.G.edges()],
        }
        # Parent info
        if segment.parent:
            r["parent"] = {
                "id": str(segment.parent.id),
                "name": segment.parent.name
            }
        # Save settings
        if not settings:
            self.logger.debug("Saving first-time layout")
            MapSettings.load_json({
                "id":
                str(segment.id),
                "nodes":
                [{
                    "type": n["type"],
                    "id": n["id"],
                    "x": n["x"],
                    "y": n["y"]
                } for n in r["nodes"]
                 if n.get("x") is not None and n.get("y") is not None],
                "links": [{
                    "type": n["type"],
                    "id": n["id"],
                    "vertices": n.get("vertices", []),
                    "connector": n.get("connector", "normal"),
                } for n in r["links"]],
            })
        return r

    @view(r"^(?P<id>[0-9a-f]{24})/data/$",
          method=["POST"],
          access="write",
          api=True)
    def api_save(self, request, id):
        self.get_object_or_404(NetworkSegment, id=id)
        data = self.deserialize(request.body)
        data["id"] = id
        MapSettings.load_json(data, request.user.username)
        return {"status": True}

    @view(url=r"^(?P<id>[0-9a-f]{24})/info/segment/$",
          method=["GET"],
          access="read",
          api=True)
    def api_info_segment(self, request, id):
        segment = self.get_object_or_404(NetworkSegment, id=id)
        r = {
            "name": segment.name,
            "description": segment.description,
            "objects": segment.managed_objects.count(),
        }
        return r

    @view(
        url=r"^(?P<id>[0-9a-f]{24})/info/managedobject/(?P<mo_id>\d+)/$",
        method=["GET"],
        access="read",
        api=True,
    )
    def api_info_managedobject(self, request, id, mo_id):
        segment = self.get_object_or_404(NetworkSegment, id=id)
        object = self.get_object_or_404(ManagedObject, id=int(mo_id))
        s = {1: "telnet", 2: "ssh", 3: "http", 4: "https"}[object.scheme]
        r = {
            "id": object.id,
            "name": object.name,
            "description": object.description,
            "address": object.address,
            "platform": object.platform.full_name if object.platform else "",
            "profile": object.profile.name,
            "external": object.segment.id != segment.id,
            "external_segment": {
                "id": str(object.segment.id),
                "name": object.segment.name
            },
            "caps": object.get_caps(),
            "console_url": "%s://%s/" % (s, object.address),
        }
        return r

    @view(
        url=r"^(?P<id>[0-9a-f]{24})/info/link/(?P<link_id>[0-9a-f]{24})/$",
        method=["GET"],
        access="read",
        api=True,
    )
    def api_info_link(self, request, id, link_id):
        def q(s):
            if isinstance(s, str):
                s = s.encode("utf-8")
            return s

        self.get_object_or_404(NetworkSegment, id=id)
        link = self.get_object_or_404(Link, id=link_id)
        r = {
            "id": str(link.id),
            "name": link.name or None,
            "description": link.description or None,
            "objects": [],
            "method": link.discovery_method,
        }
        o = defaultdict(list)
        for i in link.interfaces:
            o[i.managed_object] += [i]
        for mo in sorted(o, key=lambda x: x.name):
            r["objects"] += [{
                "id":
                mo.id,
                "name":
                mo.name,
                "interfaces": [{
                    "name": i.name,
                    "description": i.description or None,
                    "status": i.status
                } for i in sorted(o[mo], key=lambda x: alnum_key(x.name))],
            }]
        # Get link bandwidth
        mo_in = defaultdict(float)
        mo_out = defaultdict(float)
        mos = [ManagedObject.get_by_id(mo["id"]) for mo in r["objects"]]
        metric_map, last_ts = get_interface_metrics(list(o))
        for mo in o:
            if mo not in metric_map:
                continue
            for i in o[mo]:
                if i.name not in metric_map[mo]:
                    continue
                mo_in[mo] += metric_map[mo][i.name]["Interface | Load | In"]
                mo_out[mo] += metric_map[mo][i.name]["Interface | Load | Out"]
        if len(mos) == 2:
            mo1, mo2 = mos
            r["utilisation"] = [
                int(max(mo_in[mo1], mo_out[mo2])),
                int(max(mo_in[mo2], mo_out[mo1])),
            ]
        else:
            mv = list(mo_in.values()) + list(mo_out.values())
            if mv:
                r["utilisation"] = [int(max(mv))]
            else:
                r["utilisation"] = 0
        return r

    @view(
        url=r"^(?P<id>[0-9a-f]{24})/info/cloud/(?P<link_id>[0-9a-f]{24})/$",
        method=["GET"],
        access="read",
        api=True,
    )
    def api_info_cloud(self, request, id, link_id):
        self.get_object_or_404(NetworkSegment, id=id)
        link = self.get_object_or_404(Link, id=link_id)
        r = {
            "id": str(link.id),
            "name": link.name or None,
            "description": link.description or None,
            "objects": [],
            "method": link.discovery_method,
        }
        o = defaultdict(list)
        for i in link.interfaces:
            o[i.managed_object] += [i]
        for mo in sorted(o, key=lambda x: x.name):
            r["objects"] += [{
                "id":
                mo.id,
                "name":
                mo.name,
                "interfaces": [{
                    "name": i.name,
                    "description": i.description or None,
                    "status": i.status
                } for i in sorted(o[mo], key=lambda x: alnum_key(x.name))],
            }]
        return r

    @view(
        url=r"^objects_statuses/$",
        method=["POST"],
        access="read",
        api=True,
        validate={"objects": ListOfParameter(IntParameter())},
    )
    def api_objects_statuses(self, request, objects: List[int]):
        def get_alarms(objects: List[int]) -> Set[int]:
            """
            Returns a set of objects with alarms
            """
            alarms: Set[int] = set()
            coll = ActiveAlarm._get_collection()
            while objects:
                chunk, objects = objects[:500], objects[500:]
                a = coll.aggregate([
                    {
                        "$match": {
                            "managed_object": {
                                "$in": chunk
                            }
                        }
                    },
                    {
                        "$group": {
                            "_id": "$managed_object",
                            "count": {
                                "$sum": 1
                            }
                        }
                    },
                ])
                alarms.update(d["_id"] for d in a)
            return alarms

        def get_maintenance(objects: List[int]) -> Set[int]:
            """
            Returns a set of objects currently in maintenance
            :param objects:
            :return:
            """
            now = datetime.datetime.now()
            so = set(objects)
            mnt_objects = set()
            pipeline = [
                {
                    "$match": {
                        "affected_objects.object": {
                            "$in": list(so)
                        }
                    }
                },
                {
                    "$unwind": "$affected_objects"
                },
                {
                    "$lookup": {
                        "from":
                        "noc.maintenance",
                        "as":
                        "m",
                        "let": {
                            "maintenance": "_id"
                        },
                        "pipeline": [{
                            "$match": {
                                "m.is_completed": False,
                                "m.start": {
                                    "$lte": now
                                },
                                "m.stop": {
                                    "gte": now
                                },
                            },
                        }],
                    },
                },
                {
                    "$project": {
                        "_id": 0,
                        "object": "$affected_objects.object",
                    }
                },
                {
                    "$group": {
                        "_id": "$object"
                    }
                },
            ]
            mnt_objects |= so & {
                x["_id"]
                for x in AffectedObjects._get_collection().aggregate(pipeline)
            }
            return mnt_objects

        # Mark all as unknown
        r = {o: self.ST_UNKNOWN for o in objects}
        sr = ObjectStatus.get_statuses(objects)
        sa = get_alarms(objects)
        mo = get_maintenance(objects)
        for o in sr:
            if sr[o]:
                # Check for alarms
                if o in sa:
                    r[o] = self.ST_ALARM
                else:
                    r[o] = self.ST_OK
            else:
                r[o] = self.ST_DOWN
            if o in mo:
                r[o] |= self.ST_MAINTENANCE
        return r

    @classmethod
    @cachedmethod(key="managedobject-name-to-id-%s", lock=lambda _: tags_lock)
    def managedobject_name_to_id(cls, name):
        r = ManagedObject.objects.filter(name=name).values_list("id")
        if r:
            return r[0][0]
        return None

    @classmethod
    @cachedmethod(key="interface-tags-to-id-%s-%s", lock=lambda _: tags_lock)
    def interface_tags_to_id(cls, object_name, interface_name):
        mo = cls.managedobject_name_to_id(object_name)
        i = Interface._get_collection().find_one({
            "managed_object": mo,
            "name": interface_name
        })
        if i:
            return i["_id"]
        return None

    @view(
        url=r"^metrics/$",
        method=["POST"],
        access="read",
        api=True,
        validate={
            "metrics":
            DictListParameter(
                attrs={
                    "id": StringParameter(),
                    "metric": StringParameter(),
                    "tags": DictParameter(),
                })
        },
    )
    def api_metrics(self, request, metrics):
        def q(s):
            if isinstance(s, str):
                s = s.encode("utf-8")
            return s

        def qt(t):
            return "|".join(["%s=%s" % (v, t[v]) for v in sorted(t)])

        # Build query
        tag_id = {}  # object, interface -> id
        if_ids = {}  # id -> port id
        mlst = []  # (metric, object, interface)
        for m in metrics:
            if "object" in m["tags"] and "interface" in m["tags"]:
                if not m["tags"]["object"]:
                    continue
                try:
                    if_ids[self.interface_tags_to_id(
                        m["tags"]["object"], m["tags"]["interface"])] = m["id"]
                    object = ManagedObject.objects.get(
                        name=m["tags"]["object"])
                    tag_id[object, m["tags"]["interface"]] = m["id"]
                    mlst += [(m["metric"], object, m["tags"]["interface"])]
                except KeyError:
                    pass
        # @todo: Get last values from cache
        if not mlst:
            return {}

        r = {}
        # Apply interface statuses
        for d in Interface._get_collection().find(
            {"_id": {
                "$in": list(if_ids)
            }}, {
                "_id": 1,
                "admin_status": 1,
                "oper_status": 1
            }):
            r[if_ids[d["_id"]]] = {
                "admin_status": d.get("admin_status", True),
                "oper_status": d.get("oper_status", True),
            }
        metric_map, last_ts = get_interface_metrics([m[1] for m in mlst])
        # Apply metrics
        for rq_mo, rq_iface in tag_id:
            pid = tag_id.get((rq_mo, rq_iface))
            if not pid:
                continue
            if pid not in r:
                r[pid] = {}
            if rq_mo not in metric_map:
                continue
            if rq_iface not in metric_map[rq_mo]:
                continue
            r[pid]["Interface | Load | In"] = metric_map[rq_mo][rq_iface][
                "Interface | Load | In"]
            r[pid]["Interface | Load | Out"] = metric_map[rq_mo][rq_iface][
                "Interface | Load | Out"]

        return r

    @view(r"^(?P<id>[0-9a-f]{24})/data/$",
          method=["DELETE"],
          access="write",
          api=True)
    def api_reset(self, request, id):
        self.get_object_or_404(NetworkSegment, id=id)
        MapSettings.objects.filter(segment=id).delete()
        return {"status": True}

    @view(
        url=r"^stp/status/$",
        method=["POST"],
        access="read",
        api=True,
        validate={"objects": ListOfParameter(IntParameter())},
    )
    def api_objects_stp_status(self, request, objects):
        def get_stp_status(object_id):
            roots = set()
            blocked = set()
            object = ManagedObject.get_by_id(object_id)
            sr = object.scripts.get_spanning_tree()
            for instance in sr["instances"]:
                ro = DiscoveryID.find_object(instance["root_id"])
                if ro:
                    roots.add(ro)
                for i in instance["interfaces"]:
                    if i["state"] == "discarding" and i["role"] == "alternate":
                        iface = object.get_interface(i["interface"])
                        if iface:
                            link = iface.link
                            if link:
                                blocked.add(str(link.id))
            return object_id, roots, blocked

        r = {"roots": [], "blocked": []}
        futures = []
        with ThreadPoolExecutor(max_workers=10) as executor:
            for o in objects:
                futures += [executor.submit(get_stp_status, o)]
            for future in as_completed(futures):
                try:
                    obj, roots, blocked = future.result()
                    for ro in roots:
                        if ro.id not in r["roots"]:
                            r["roots"] += [ro.id]
                    r["blocked"] += blocked
                except Exception as e:
                    self.logger.error("[stp] Exception: %s", e)
        return r
Exemple #12
0
class VCApplication(ExtModelApplication):
    """
    VC application
    """

    title = _("VC")
    menu = _("Virtual Circuits")
    model = VC

    query_fields = ["name", "description"]
    query_condition = "icontains"
    int_query_fields = ["l1", "l2"]

    implied_permissions = {"read": ["vc:vcdomain:lookup", "main:style:lookup"]}

    def get_vc_domain_objects(self, vc_domain):
        return vc_domain.managedobject_set.all()

    def lookup_vcfilter(self, q, name, value):
        """
        Resolve __vcflter lookups
        :param q:
        :param name:
        :param value:
        :return:
        """
        value = ModelParameter(VCFilter).clean(value)
        x = value.to_sql(name)
        try:
            q[None] += [x]
        except KeyError:
            q[None] = [x]

    @cachedmethod(key="vc-interface-count-%s")
    def get_vc_interfaces_count(self, vc_id):
        vc = VC.get_by_id(vc_id)
        if not vc:
            return 0
        objects = vc.vc_domain.managedobject_set.values_list("id", flat=True)
        l1 = vc.l1
        n = SubInterface.objects.filter(
            Q(managed_object__in=objects)
            & (
                Q(untagged_vlan=l1, enabled_afi=["BRIDGE"])
                | Q(tagged_vlans=l1, enabled_afi=["BRIDGE"])
                | Q(vlan_ids=l1)
            )
        ).count()
        return n

    @cachedmethod(key="vc-prefixes-%s")
    def get_vc_prefixes(self, vc_id):
        vc = VC.get_by_id(vc_id)
        if not vc:
            return []
        objects = vc.vc_domain.managedobject_set.values_list("id", flat=True)
        ipv4 = set()
        ipv6 = set()
        # @todo: Exact match on vlan_ids
        for si in SubInterface.objects.filter(
            Q(managed_object__in=objects)
            & Q(vlan_ids=vc.l1)
            & (Q(enabled_afi=["IPv4"]) | Q(enabled_afi=["IPv6"]))
        ).only("enabled_afi", "ipv4_addresses", "ipv6_addresses"):
            if "IPv4" in si.enabled_afi:
                ipv4.update([IP.prefix(ip).first for ip in si.ipv4_addresses])
            if "IPv6" in si.enabled_afi:
                ipv6.update([IP.prefix(ip).first for ip in si.ipv6_addresses])
        p = [str(x.first) for x in sorted(ipv4)]
        p += [str(x.first) for x in sorted(ipv6)]
        return p

    def field_interfaces_count(self, obj):
        return self.get_vc_interfaces_count(obj.id)

    def field_prefixes(self, obj):
        p = self.get_vc_prefixes(obj.id)
        if p:
            return ", ".join(p)
        else:
            return "-"

    def field_row_class(self, o):
        return o.style.css_class_name if o.style else ""

    @view(
        url="^find_free/$",
        method=["GET"],
        access="read",
        api=True,
        validate={"vc_domain": ModelParameter(VCDomain), "vc_filter": ModelParameter(VCFilter)},
    )
    def api_find_free(self, request, vc_domain, vc_filter, **kwargs):
        return vc_domain.get_free_label(vc_filter)

    @view(
        url="^bulk/import/",
        method=["POST"],
        access="import",
        api=True,
        validate={
            "vc_domain": ModelParameter(VCDomain),
            "items": ListOfParameter(
                element=DictParameter(
                    attrs={
                        "l1": IntParameter(),
                        "l2": IntParameter(),
                        "name": StringParameter(),
                        "description": StringParameter(default=""),
                    }
                )
            ),
        },
    )
    def api_bulk_import(self, request, vc_domain, items):
        n = 0
        for i in items:
            if not VC.objects.filter(vc_domain=vc_domain, l1=i["l1"], l2=i["l2"]).exists():
                # Add only not-existing
                VC(
                    vc_domain=vc_domain,
                    l1=i["l1"],
                    l2=i["l2"],
                    name=i["name"],
                    description=i["description"],
                ).save()
                n += 1
        return {"status": True, "imported": n}

    @view(url=r"^(?P<vc_id>\d+)/interfaces/$", method=["GET"], access="read", api=True)
    def api_interfaces(self, request, vc_id):
        """
        Returns a dict of {untagged: ..., tagged: ...., l3: ...}
        :param request:
        :param vc_id:
        :return:
        """
        vc = self.get_object_or_404(VC, id=int(vc_id))
        l1 = vc.l1
        # Managed objects in VC domain
        objects = set(vc.vc_domain.managedobject_set.values_list("id", flat=True))
        # Find untagged interfaces
        si_objects = defaultdict(list)
        for si in SubInterface.objects.filter(
            managed_object__in=objects, untagged_vlan=l1, enabled_afi="BRIDGE"
        ):
            si_objects[si.managed_object] += [{"name": si.name}]
        untagged = [
            {
                "managed_object_id": o.id,
                "managed_object_name": o.name,
                "interfaces": sorted(si_objects[o], key=lambda x: x["name"]),
            }
            for o in si_objects
        ]
        # Find tagged interfaces
        si_objects = defaultdict(list)
        for si in SubInterface.objects.filter(
            managed_object__in=objects, tagged_vlans=l1, enabled_afi="BRIDGE"
        ):
            si_objects[si.managed_object] += [{"name": si.name}]
        tagged = [
            {
                "managed_object_id": o.id,
                "managed_object_name": o.name,
                "interfaces": sorted(si_objects[o], key=lambda x: x["name"]),
            }
            for o in si_objects
        ]
        # Find l3 interfaces
        si_objects = defaultdict(list)
        for si in SubInterface.objects.filter(managed_object__in=objects, vlan_ids=l1):
            si_objects[si.managed_object] += [
                {
                    "name": si.name,
                    "ipv4_addresses": si.ipv4_addresses,
                    "ipv6_addresses": si.ipv6_addresses,
                }
            ]
        l3 = [
            {
                "managed_object_id": o.id,
                "managed_object_name": o.name,
                "interfaces": sorted(si_objects[o], key=lambda x: x["name"]),
            }
            for o in si_objects
        ]
        # Update caches
        ic = sum(len(x["interfaces"]) for x in untagged)
        ic += sum(len(x["interfaces"]) for x in tagged)
        ic += sum(len(x["interfaces"]) for x in l3)
        #
        return {
            "untagged": sorted(untagged, key=lambda x: x["managed_object_name"]),
            "tagged": sorted(tagged, key=lambda x: x["managed_object_name"]),
            "l3": sorted(l3, key=lambda x: x["managed_object_name"]),
        }
Exemple #13
0
# Python modules
from __future__ import absolute_import

# Third-party modules
import tornado.gen
import ujson
import six

# NOC modules
from noc.core.service.apiaccess import authenticated
from noc.sa.interfaces.base import DictParameter, StringListParameter
from noc.sa.models.objectstatus import ObjectStatus
from ..base import NBIAPI

Request = DictParameter(attrs={"objects": StringListParameter(required=True)})


class ObjectStatusAPI(NBIAPI):
    name = "objectstatus"

    @authenticated
    @tornado.gen.coroutine
    def post(self):
        code, result = yield self.executor.submit(self.handler)
        self.set_status(code)
        if isinstance(result, six.string_types):
            self.write(result)
        else:
            self.write(ujson.dumps(result))
Exemple #14
0
class ObjectListApplication(ExtApplication):
    """
    ManagedObject application
    """

    model = ManagedObject
    # Default filter by is_managed
    managed_filter = True

    def queryset(self, request, query=None):
        """
        Filter records for lookup
        """
        self.logger.info("Queryset %s" % query)
        if self.managed_filter:
            q = d_Q(is_managed=True)
        else:
            q = d_Q()
        if not request.user.is_superuser:
            q &= UserAccess.Q(request.user)
        if query:
            sq = ManagedObject.get_search_Q(query)
            if sq:
                q &= sq
            else:
                q &= d_Q(name__contains=query)
        return self.model.objects.filter(q)

    def instance_to_dict(self, o, fields=None):
        return {
            "id":
            str(o.id),
            "name":
            o.name,
            "address":
            o.address,
            "profile_name":
            o.profile.name,
            "platform":
            o.platform.name if o.platform else "",
            "version":
            o.version.version if o.version else "",
            "row_class":
            o.object_profile.style.css_class_name
            if o.object_profile.style else ""
            # "row_class": ""
        }

    def cleaned_query(self, q):
        nq = {}
        for k in q:
            if not k.startswith("_") and "__" not in k:
                nq[k] = q[k]
        ids = set()
        self.logger.debug("Cleaned query: %s" % nq)
        if "ids" in nq:
            ids = {int(nid) for nid in nq["ids"]}
            del nq["ids"]

        if "administrative_domain" in nq:
            ad = AdministrativeDomain.get_nested_ids(
                int(nq["administrative_domain"]))
            if ad:
                del nq["administrative_domain"]
                nq["administrative_domain__in"] = ad

        if "selector" in nq:
            s = self.get_object_or_404(ManagedObjectSelector,
                                       id=int(q["selector"]))
            if s:
                if ids:
                    # nq["id__in"] = set(ManagedObject.objects.filter(s.Q).values_list("id", flat=True))
                    ids = ids.intersection(
                        set(
                            ManagedObject.objects.filter(s.Q).values_list(
                                "id", flat=True)))
                else:
                    ids = set(
                        ManagedObject.objects.filter(s.Q).values_list(
                            "id", flat=True))
            del nq["selector"]
        mq = None
        c_in = []
        c_nin = []
        for cc in [part for part in nq if part.startswith("caps")]:
            """
            Caps: caps0=CapsID,caps1=CapsID:true....
            cq - caps query
            mq - main_query
            caps0=CapsID - caps is exists
            caps0=!CapsID - caps is not exists
            caps0=CapsID:true - caps value equal True
            caps0=CapsID:2~50 - caps value many then 2 and less then 50
            c_ids = set(ObjectCapabilities.objects(cq).distinct('object'))
            """
            # @todo Убирать дубликаты (повторно не добавлять)

            c = nq.pop(cc)
            if not c:
                continue
            if not mq:
                mq = m_Q()
            self.logger.info("Caps: %s" % c)
            if "!" in c:
                # @todo Добавить исключение (только этот) !ID
                c_id = c[1:]
                c_query = "nexists"
            elif ":" not in c:
                c_id = c
                c_query = "exists"
            else:
                c_id, c_query = c.split(":", 1)

            try:
                c_id = bson.ObjectId(c_id)
            except bson.errors.InvalidId as e:
                self.logger.warning(e)
                continue
            if "~" in c_query:
                l, r = c_query.split("~")
                if not l:
                    cond = {"$lte": int(r)}
                elif not r:
                    cond = {"$gte": int(l)}
                else:
                    cond = {"$lte": int(r), "$gte": int(l)}
                cq = m_Q(__raw__={
                    "caps": {
                        "$elemMatch": {
                            "capability": c_id,
                            "value": cond
                        }
                    }
                })
            elif c_query in ("false", "true"):
                cq = m_Q(caps__match={
                    "capability": c_id,
                    "value": c_query == "true"
                })
            elif c_query == "exists":
                c_in += [c_id]
                continue
            elif c_query == "nexists":
                c_nin += [c_id]
                continue
            else:
                try:
                    c_query = int(c_query)
                    cq = m_Q(
                        __raw__={
                            "caps": {
                                "$elemMatch": {
                                    "capability": c_id,
                                    "value": int(c_query)
                                }
                            }
                        })
                except ValueError:
                    cq = m_Q(
                        __raw__={
                            "caps": {
                                "$elemMatch": {
                                    "capability": c_id,
                                    "value": {
                                        "$regex": c_query
                                    }
                                }
                            }
                        })
            mq &= cq
        if c_in:
            mq &= m_Q(caps__capability__in=c_in)
        if c_nin:
            mq &= m_Q(caps__capability__nin=c_nin)
        if mq:
            c_ids = set(el["_id"] for el in ObjectCapabilities.objects(
                mq).values_list("object").as_pymongo())
            self.logger.info("Caps objects count: %d" % len(c_ids))
            ids = ids.intersection(c_ids) if ids else c_ids

        if "addresses" in nq:
            if isinstance(nq["addresses"], list):
                nq["address__in"] = nq["addresses"]
            else:
                nq["address__in"] = [nq["addresses"]]
            del nq["addresses"]
        if ids:
            nq["id__in"] = list(ids)

        xf = list((set(nq.keys())) -
                  set(f.name for f in self.model._meta.get_fields()))
        # @todo move validation fields
        for x in xf:
            if x in ["address__in", "id__in", "administrative_domain__in"]:
                continue
            self.logger.warning("Remove element not in model: %s" % x)
            del nq[x]
        return nq

    def extra_query(self, q, order):
        extra = {"select": {}}
        if "address" in order:
            extra["select"]["ex_address"] = " cast_test_to_inet(address) "
            extra["order_by"] = ["ex_address", "address"]
        elif "-address" in order:
            extra["select"]["ex_address"] = " cast_test_to_inet(address) "
            extra["order_by"] = ["-ex_address", "-address"]

        self.logger.info("Extra: %s" % extra)
        return extra, [] if "order_by" in extra else order

    @view(method=["GET", "POST"], url="^$", access="read", api=True)
    def api_list(self, request):
        return self.list_data(request, self.instance_to_dict)

    @view(
        method=["POST"],
        url="^iplist/$",
        access="launch",
        api=True,
        validate={
            "query":
            DictParameter(
                attrs={
                    "addresses":
                    ListOfParameter(element=IPv4Parameter(), convert=True)
                })
        },
    )
    def api_action_ip_list(self, request, query):
        # @todo Required user vault implementation
        return self.render_json({"status": True})
Exemple #15
0
class RunCommandsApplication(ExtApplication):
    title = _("Run Commands")
    menu = [_("Run Commands")]

    implied_permissions = {"launch": ["sa:objectlist:read"]}

    @view(url=r"^form/snippet/(?P<snippet_id>\d+)/$",
          method=["GET"],
          access="launch",
          api=True)
    def api_form_snippet(self, request, snippet_id):
        snippet = self.get_object_or_404(CommandSnippet, id=int(snippet_id))
        r = []
        vars = snippet.vars
        for k in vars:
            cfg = {
                "name": k,
                "fieldLabel": k,
                "allowBlank": not vars[k].get("required", False)
            }
            t = vars[k].get("type")
            if t == "int":
                cfg["xtype"] = "numberfield"
            else:
                cfg["xtype"] = "textfield"
            r += [cfg]
        return r

    @view(url=r"^form/action/(?P<action_id>[0-9a-f]{24})/$",
          method=["GET"],
          access="launch",
          api=True)
    def api_form_action(self, request, action_id):
        action = self.get_object_or_404(Action, id=action_id)
        r = []
        for p in action.params:
            cfg = {
                "name": p.name,
                "fieldLabel": p.description or p.name,
                "allowBlank": not p.is_required,
            }
            if p.type == "int":
                cfg["xtype"] = "numberfield"
            else:
                cfg["xtype"] = "textfield"
            r += [cfg]
        return r

    @view(
        url=r"^render/snippet/(?P<snippet_id>\d+)/$",
        method=["POST"],
        validate={
            "objects": ListOfParameter(element=ModelParameter(ManagedObject)),
            "config": DictParameter(),
        },
        access="launch",
        api=True,
    )
    def api_render_snippet(self, request, snippet_id, objects, config):
        snippet = self.get_object_or_404(CommandSnippet, id=int(snippet_id))
        r = {}
        for mo in objects:
            config["object"] = mo
            r[mo.id] = snippet.expand(config)
        return r

    @view(
        url=r"^render/action/(?P<action_id>[0-9a-f]{24})/$",
        method=["POST"],
        validate={
            "objects": ListOfParameter(element=ModelParameter(ManagedObject)),
            "config": DictParameter(),
        },
        access="launch",
        api=True,
    )
    def api_render_action(self, request, action_id, objects, config):
        action = self.get_object_or_404(Action, id=action_id)
        r = {}
        for mo in objects:
            r[mo.id] = action.expand(mo, **config)
        return r
Exemple #16
0
    StringListParameter,
    IntParameter,
    ListOfParameter,
    ListParameter,
)
from noc.pm.models.metrictype import MetricType
from ..base import NBIAPI


Request = DictParameter(
    attrs={
        "bi_id": IntParameter(required=True),
        "metrics": DictListParameter(
            attrs={
                "metric_type": StringParameter(required=True),
                "path": StringListParameter(required=True),
                "values": ListOfParameter(ListParameter(), required=True),
            },
            required=True,
        ),
    }
)


class TelemetryAPI(NBIAPI):
    name = "telemetry"

    @authenticated
    @tornado.gen.coroutine
    def post(self):
        code, result = yield self.executor.submit(self.handler)
Exemple #17
0
from noc.aaa.models.group import Group
from noc.pm.models.metricscope import MetricScope
from noc.pm.models.metrictype import MetricType
from noc.bi.models.dashboard import Dashboard, DashboardAccess, DAL_ADMIN, DAL_RO
from noc.sa.interfaces.base import DictListParameter, DictParameter, IntParameter, StringParameter
from noc.core.perf import metrics
from noc.core.translation import ugettext as _

# Access items validations
I_VALID = DictListParameter(
    attrs={
        "group":
        DictParameter(
            attrs={
                "id": IntParameter(required=True),
                "name": StringParameter(required=False)
            },
            required=False,
        ),
        "user":
        DictParameter(
            attrs={
                "id": IntParameter(required=True),
                "name": StringParameter(required=False)
            },
            required=False,
        ),
        "level":
        IntParameter(min_value=-1, max_value=3, default=-1),
    })
Exemple #18
0
    DictParameter,
    DictListParameter,
    StringParameter,
    StringListParameter,
    IntParameter,
    ListOfParameter,
    ListParameter,
)
from noc.pm.models.metrictype import MetricType
from noc.services.nbi.base import NBIAPI

Request = DictParameter(
    attrs={
        "action": StringParameter(required=True),
        "host": StringParameter(required=True),
        "port": StringParameter(required=True),
        "sn": StringParameter(required=True),
        "llid": IntParameter(required=True),
        "login": StringParameter(required=True),
        "passwd": StringParameter(required=True),
    })


class ZTERegONU(NBIAPI):
    name = "zteregonu"

    @authenticated
    @tornado.gen.coroutine
    def post(self):
        connect()
        code, result = yield self.executor.submit(self.handler)
        self.set_status(code)
Exemple #19
0
from noc.sa.interfaces.base import (
    DictParameter,
    DictListParameter,
    StringParameter,
    StringListParameter,
    IntParameter,
    ListOfParameter,
    ListParameter,
)
from noc.pm.models.metrictype import MetricType
from noc.services.nbi.base import NBIAPI

Request = DictParameter(
    attrs={
        "host": StringParameter(required=True),
        "port": StringParameter(required=True),
        "sn": StringParameter(required=True),
    })


class GetllidzteAPI(NBIAPI):
    name = "getllidzte"

    @authenticated
    @tornado.gen.coroutine
    def post(self):
        connect()
        code, result = yield self.executor.submit(self.handler)
        self.set_status(code)
        if isinstance(result, six.string_types):
            self.write(result)
Exemple #20
0
class UserProfileApplication(ExtApplication):
    """
    main.userprofile application
    """

    title = _("User Profile")
    implied_permissions = {"launch": ["main:timepattern:lookup"]}

    @view(url="^$", method=["GET"], access=PermitLogged(), api=True)
    def api_get(self, request):
        user = request.user
        language = user.preferred_language
        contacts = [{
            "time_pattern": c.time_pattern.id,
            "time_pattern__label": c.time_pattern.name,
            "notification_method": c.notification_method,
            "params": c.params,
        } for c in UserContact.objects.filter(user=user)]
        return {
            "username":
            user.username,
            "name":
            (" ".join([x for x in (user.first_name, user.last_name)
                       if x])).strip(),
            "email":
            user.email,
            "preferred_language":
            language or "en",
            "contacts":
            contacts,
            "groups": [g.name for g in user.groups.all().order_by("name")],
        }

    @view(
        url="^$",
        method=["POST"],
        access=PermitLogged(),
        api=True,
        validate={
            "preferred_language":
            StringParameter(choices=[x[0] for x in LANGUAGES]),
            "contacts":
            ListOfParameter(element=DictParameter(
                attrs={
                    "time_pattern":
                    ModelParameter(TimePattern),
                    "notification_method":
                    StringParameter(choices=[
                        x[0] for x in USER_NOTIFICATION_METHOD_CHOICES
                    ]),
                    "params":
                    StringParameter(),
                })),
        },
    )
    def api_save(self, request, preferred_language, contacts):
        user = request.user
        user.preferred_language = preferred_language
        user.save()
        # Setup contacts
        UserContact.objects.filter(user=user).delete()
        for c in contacts:
            UserContact(
                user=user,
                time_pattern=c["time_pattern"],
                notification_method=c["notification_method"],
                params=c["params"],
            ).save()
        return True
Exemple #21
0
class UserProfileApplication(ExtApplication):
    """
    main.userprofile application
    """
    title = "User Profile"
    implied_permissions = {"launch": ["main:timepattern:lookup"]}

    @view(url="^$", method=["GET"], access=PermitLogged(), api=True)
    def api_get(self, request):
        user = request.user
        try:
            profile = user.get_profile()
            language = profile.preferred_language
            theme = profile.theme
            preview_theme = profile.preview_theme
            contacts = [{
                "time_pattern": c.time_pattern.id,
                "time_pattern__label": c.time_pattern.name,
                "notification_method": c.notification_method,
                "params": c.params
            } for c in profile.userprofilecontact_set.all()]
        except UserProfile.DoesNotExist:
            language = None
            theme = None
            preview_theme = None
            contacts = []
        return {
            "username":
            user.username,
            "name":
            (" ".join([x for x in (user.first_name, user.last_name)
                       if x])).strip(),
            "email":
            user.email,
            "preferred_language":
            language or "en",
            "theme":
            theme or "gray",
            "preview_theme":
            preview_theme or "midnight",
            "contacts":
            contacts
        }

    @view(url="^$",
          method=["POST"],
          access=PermitLogged(),
          api=True,
          validate={
              "preferred_language":
              StringParameter(choices=[x[0] for x in LANGUAGES]),
              "theme":
              StringParameter(),
              "preview_theme":
              StringParameter(),
              "contacts":
              ListOfParameter(element=DictParameter(
                  attrs={
                      "time_pattern":
                      ModelParameter(TimePattern),
                      "notification_method":
                      StringParameter(choices=[
                          x[0] for x in USER_NOTIFICATION_METHOD_CHOICES
                      ]),
                      "params":
                      StringParameter()
                  }))
          })
    def api_save(self, request, preferred_language, theme, preview_theme,
                 contacts):
        user = request.user
        try:
            profile = user.get_profile()
        except UserProfile.DoesNotExist:
            profile = UserProfile(user=user)
        profile.preferred_language = preferred_language
        profile.theme = theme
        profile.preview_theme = preview_theme
        profile.save()
        # Setup contacts
        for c in profile.userprofilecontact_set.all():
            c.delete()
        for c in contacts:
            UserProfileContact(user_profile=profile,
                               time_pattern=c["time_pattern"],
                               notification_method=c["notification_method"],
                               params=c["params"]).save()
        # Setup language
        request.session["django_lang"] = preferred_language
        return True