コード例 #1
0
 def handler(self):
     self.logger.info("Checking CPEs")
     now = datetime.datetime.now()
     result = self.object.scripts.get_cpe()
     for cpe in result:
         if cpe["status"] != "active":
             self.logger.debug(
                 "[%s|%s] CPE status is '%s'. Skipping",
                 cpe["id"],
                 cpe["global_id"],
                 cpe["status"],
             )
             continue
         mo = self.find_cpe(cpe["global_id"])
         if mo:
             changes = self.update_if_changed(
                 mo,
                 {
                     "controller": self.object,
                     "local_cpe_id": cpe["id"],
                     "global_cpe_id": cpe["global_id"],
                     "address": cpe["ip"],
                     "last_seen": now,
                 },
             )
             if changes:
                 self.logger.info(
                     "[%s|%s] Changed: %s",
                     cpe["id"],
                     cpe["global_id"],
                     ", ".join("%s='%s'" % c for c in changes),
                 )
         else:
             name = cpe.get("name") or "cpe-%s" % cpe["global_id"]
             if ManagedObject.objects.filter(name=name).exists():
                 name = "cpe-%s" % cpe["global_id"]
             self.logger.info("[%s|%s] Created CPE %s", cpe["id"],
                              cpe["global_id"], name)
             mo = ManagedObject(
                 name=name,
                 pool=self.object.pool,
                 profile=Profile.get_by_id(
                     Profile.get_generic_profile_id()),
                 object_profile=self.object.object_profile.cpe_profile
                 or self.object.object_profile,
                 administrative_domain=self.object.administrative_domain,
                 scheme=self.object.scheme,
                 segment=self.object.segment,
                 auth_profile=self.object.object_profile.cpe_auth_profile
                 or self.object.auth_profile,
                 address=cpe.get("ip") or "0.0.0.0",
                 controller=self.object,
                 last_seen=now,
                 local_cpe_id=cpe["id"],
                 global_cpe_id=cpe["global_id"],
             )
             mo.save()
コード例 #2
0
 def OP_ATTR_MAP(self):
     return {
         "2": {"1": False, "2": True},
         "7": {
             "1": str(Profile.get_generic_profile_id()),
             "2": str(Profile.get_generic_profile_id()),
             "ne": ["2"],
         },
         "13020": {"1": False, "2": True, "model": ManagedObjectProfile},
         "1403": {"5": "S", "model": AuthProfile},
     }
コード例 #3
0
ファイル: views.py プロジェクト: marcosvella/noc
 def api_test(self, request, id):
     r = []
     out = {"total": 0, "success": True, "data": None}
     data = [
         d
         for d in AffectedObjects._get_collection().aggregate(
             [
                 {"$match": {"maintenance": bson.ObjectId(id)}},
                 {
                     "$project": {"objects": "$affected_objects.object"},
                 },
             ]
         )
     ]
     if data:
         for mo in (
             ManagedObject.objects.filter(is_managed=True, id__in=data[0].get("objects"))
             .values("id", "name", "is_managed", "profile", "address", "description", "labels")
             .distinct()
         ):
             r += [
                 {
                     "id": mo["id"],
                     "name": mo["name"],
                     "is_managed": mo["is_managed"],
                     "profile": Profile.get_by_id(mo["profile"]).name,
                     "address": mo["address"],
                     "description": mo["description"],
                     "labels": mo["labels"],
                 }
             ]
             out = {"total": len(r), "success": True, "data": r}
     return self.response(out, status=self.OK)
コード例 #4
0
def event(request):
    path, cfg = request.param
    coll = cfg.get("$collection", COLLECTION_NAME)
    assert coll == COLLECTION_NAME, "Invalid collection %s" % coll
    ec = EventClass.get_by_name(
        cfg.get("eventclass__name", DEFAULT_EVENT_CLASS)
    )
    mo = ManagedObject(
        id=MO_ID,
        name=MO_NAME,
        address=MO_ADDRESS,
        profile=Profile.get_by_name(cfg.get("profile__name", DEFAULT_PROFILE))
    )
    now = datetime.datetime.now()
    data = cfg.get("data", {})
    source = data.pop("source", "other")
    event = ActiveEvent(
        timestamp=now,
        start_timestamp=now,
        managed_object=mo,
        source=source,
        raw_vars=data,
        repeats=1
    )
    request.fixturename = "events-%s" % cfg.get("uuid")
    # request.fspath = path
    return event, ec, cfg.get("vars", {})
コード例 #5
0
ファイル: whois.py プロジェクト: skripkar/noc
 def handle_prefix_list(self, as_set, name=None, profile=None, *args, **options):
     from noc.peer.models.whoiscache import WhoisCache
     from noc.sa.models.profile import Profile
     p = Profile.get_by_name(profile)
     if not p:
         self.die("Invalid profile %s" % profile)
     prefixes = WhoisCache.resolve_as_set_prefixes_maxlen(as_set[0])
     self.print(p.get_profile().generate_prefix_list(name, prefixes))
コード例 #6
0
ファイル: report_objectstat.py プロジェクト: skripkar/noc
class AttributeIsolator(IsolatorClass):
    name = "attribute"

    OP_ATTR_MAP = {
        "2": {"1": False,
              "2": True},
        "7": {"1": str(Profile.get_by_name("Generic.Host").id),
              "2": str(Profile.get_by_name("Generic.Host").id),
              "ne": ["2"]},
        "13020": {"1": False,
                  "2": True,
                  "model": ManagedObjectProfile},
        "1403": {"5": "S",
                 "model": AuthProfile}
    }

    fields = [n.name for n in ManagedObject._meta._fields()]

    def default(self, num, index):
        return self.f_attribute(num, index)

    def f_attribute(self, num, value):
        """
        Islated object by atribute number
        :param num: Attribute number
        :param value: Attribute value
        :return:
        """
        # print "Attr a %s, %s" % (num, value)
        if "0" in num:
            # Cross link
            num1, num2 = num.split("0", 1)
            ff2 = [n.name for n in self.OP_ATTR_MAP[num]["model"]._meta._fields()][int(num2)]
            field = "%s__%s" % (self.fields[int(num1)], ff2)
        else:
            field = self.fields[int(num)]

        if value in self.OP_ATTR_MAP[num].get("ne", []):
            return ~d_Q(**{field: self.OP_ATTR_MAP[num][value]})
        else:
            return d_Q(**{field: self.OP_ATTR_MAP[num][value]})
コード例 #7
0
 def extract(self):
     containers = ReportContainerData(
         sorted(
             set(ManagedObject.objects.all().order_by(
                 "container").values_list("container", flat=True))))
     containers = containers.get_dictionary()
     for (
             mo_id,
             bi_id,
             name,
             address,
             profile,
             platform,
             version,
             remote_id,
             remote_system,
             adm_id,
             adm_name,
             container,
     ) in (ManagedObject.objects.all().order_by("id").values_list(
             "id",
             "bi_id",
             "name",
             "address",
             "profile",
             "platform",
             "version",
             "remote_id",
             "remote_system",
             "administrative_domain",
             "administrative_domain__name",
             "container",
     )):
         yield (
             bi_id,
             mo_id,
             name,
             address,
             Profile.get_by_id(profile).name if profile else "",
             Platform.get_by_id(platform).name if platform else "",
             Firmware.get_by_id(version).version if version else "",
             remote_id if remote_id else "",
             RemoteSystem.get_by_id(remote_system).name
             if remote_system else "",
             adm_id,
             adm_name,
             containers.get(container, ("", ))[0] if container else "",
         )
コード例 #8
0
ファイル: managedobject.py プロジェクト: skripkar/noc
 def clean(self, row):
     """
     Fix pool
     """
     v = super(ManagedObjectLoader, self).clean(row)
     v["pool"] = self.pools[v["pool"]]
     if "tags" in v:
         v["tags"] = [
             x.strip().strip('"') for x in v["tags"].split(",")
             if x.strip()
         ] if v["tags"] else []
     v["profile"] = Profile.get_by_name(v["profile"])
     v["static_client_groups"] = [v["static_client_groups"]
                                  ] if v["static_client_groups"] else []
     v["static_service_groups"] = [v["static_service_groups"]
                                   ] if v["static_service_groups"] else []
     return v
コード例 #9
0
ファイル: prefix-list.py プロジェクト: 0pt1on/noc
 def handle(self, *args, **options):
     # Check expression
     if len(args) != 1:
         raise CommandError("No expression given")
     expression = args[0]
     # Process profile
     profile = None
     if options["profile"]:
         profile = Profile.get_by_name(options["profile"])
         if not profile:
             raise CommandError("Invalid profile: %s" % options["profile"])
     # Create output
     try:
         out = open(options["output"], "w")
     except IOError as e:
         raise CommandError(str(e))
     # Build
     self.build_prefix_list(out, expression, options["name"], profile)
     # Finalize
     out.close()
コード例 #10
0
 def get_profile(self):
     """
     Returns profile for object, or None when not known
     """
     # Get SNMP version and community
     if hasattr(self.object, "_suggest_snmp") and self.object._suggest_snmp:
         # Use guessed community
         # as defined one may be invalid
         snmp_community = self.object._suggest_snmp[0]
         snmp_version = [{
             "snmp_v1_get": SNMP_v1,
             "snmp_v2c_get": SNMP_v2c
         }[self.object._suggest_snmp[2]]]
     else:
         snmp_community = self.object.credentials.snmp_ro
         caps = self.object.get_caps()
         if caps.get("SNMP | v2c") is False or caps.get(
                 "SNMP | v2c") is None:
             snmp_version = [SNMP_v1, SNMP_v2c]
         else:
             snmp_version = [SNMP_v2c, SNMP_v1]
     #
     checker = ProfileChecker(
         self.object.address,
         self.object.pool.name,
         logger=self.logger,
         calling_service="discovery",
         snmp_community=snmp_community,
         snmp_version=snmp_version,
     )
     profile = checker.get_profile()
     if profile:
         return profile
     # Report problem
     self.set_problem(
         alarm_class="Discovery | Guess | Profile",
         message=checker.get_error(),
         fatal=self.object.profile.id == Profile.get_generic_profile_id(),
     )
     self.logger.debug("Result %s" % self.job.problems)
     return None
コード例 #11
0
 def bulk_field_managed_object(self, data):
     """
     Apply managed objects field
     :param data:
     :return:
     """
     mo_ids = [x["id"] for x in data]
     if not mo_ids:
         return data
     mos = {
         x[0]: {
             "name": x[1],
             "address": x[2],
             "profile_name": str(Profile.get_by_id(x[3]))
         }
         for x in ManagedObject.objects.filter(
             id__in=mo_ids).values_list("id", "name", "address", "profile")
     }
     for x in data:
         x.update(mos[x["id"]])
     return data
コード例 #12
0
 def handler(self):
     # Decode request
     try:
         req = ujson.loads(self.request.body)
     except ValueError:
         return 400, "Cannot decode JSON"
     # Validate
     try:
         req = Request.clean(req)
     except ValueError as e:
         return 400, "Bad request: %s" % e
     # Check timestamps
     from_ts = dateutil.parser.parse(req["from"])
     to_ts = dateutil.parser.parse(req["to"])
     if to_ts < from_ts:
         return 400, "Invalid range"
     # Check time range
     delta = to_ts - from_ts
     if delta.total_seconds() > config.nbi.objectmetrics_max_interval:
         return 400, "Requested range too large"
     # Prepare data for queries
     objects = set()
     for mc in req["metrics"]:
         try:
             mo_id = int(mc["object"])
             objects.add(mo_id)
         except ValueError:
             return 400, "Invalid object id: %s" % mc["object"]
     #
     if not objects:
         return 200, []
     # Map managed object id to bi_id
     id_to_bi = {}
     profiles = {}  # object id -> profile
     for mo_id, bi_id, profile_id in ManagedObject.objects.filter(
             id__in=list(objects)).values_list("id", "bi_id", "profile"):
         id_to_bi[str(mo_id)] = bi_id
         profiles[str(mo_id)] = Profile.get_by_id(profile_id).get_profile()
     if not id_to_bi:
         return 404, "Object(s) id not found: %s" % ",".join(
             [str(o) for o in objects])
     # Prepare queries
     scopes = {}  # table_name -> ([fields, ..], [where, ..])
     for mc in req["metrics"]:
         profile = profiles[mc["object"]]
         ifaces = tuple(
             sorted(
                 profile.convert_interface_name(i)
                 for i in mc.get("interfaces", [])))
         for mn in mc["metric_types"]:
             mt = MetricType.get_by_name(mn)
             if not mt:
                 return 400, "Invalid metric_type: %s" % mn
             table = mt.scope.table_name
             q = scopes.get(table)
             if not q:
                 q = (set(), set())
                 scopes[table] = q
             q[0].add(mt.field_name)
             if table == S_INTERFACE:
                 q[1].add((id_to_bi[mc["object"]], ifaces))
             else:
                 q[1].add((id_to_bi[mc["object"]], ))
     # Execute queries and collect result
     from_date = from_ts.strftime("%Y-%m-%d")
     to_date = to_ts.strftime("%Y-%m-%d")
     if from_date == to_date:
         date_q = "date = '%s'" % from_date
     else:
         date_q = "date >= '%s' AND date <= '%s'" % (from_date, to_date)
     date_q = "%s AND ts >= '%s' AND ts <= '%s'" % (
         date_q,
         from_ts.replace(tzinfo=None).isoformat(),
         to_ts.replace(tzinfo=None).isoformat(),
     )
     connect = ClickhouseClient()
     scope_data = {}
     for table in scopes:
         sdata = {
         }  # managed_object.bi_id, interface, field -> ([(ts, value), ...], path)
         scope_data[table] = sdata
         # Build SQL request
         qx = []
         for wx in scopes[table][1]:
             if len(wx) == 1 or not wx[1]:
                 qx += ["(managed_object = %d)" % wx[0]]
             elif len(wx[1]) == 1:
                 qx += [
                     "(managed_object = %d AND path[4] = '%s')" %
                     (wx[0], wx[1][0])
                 ]
             else:
                 qx += [
                     "(managed_object = %d AND path[4] IN (%s))" %
                     (wx[0], ", ".join("'%s'" % x for x in wx[1]))
                 ]
         fields = ["ts", "managed_object", "path"] + sorted(
             scopes[table][0])
         query = "SELECT %s FROM %s WHERE %s AND (%s)" % (
             ", ".join(fields),
             table,
             date_q,
             " OR ".join(qx),
         )
         # Execute
         self.logger.info("%s", query)
         try:
             data = connect.execute(query)
         except ClickhouseError as e:
             self.logger.error("SQL Error: %s", e)
             return 500, "SQL Error: %s" % e
         # Process result
         for row in data:
             d = dict(zip(fields, row))
             ts = d.pop("ts")
             mo = int(d.pop("managed_object"))
             path = self.clear_path(d.pop("path"))
             if table == S_INTERFACE:
                 iface = path[3]
             else:
                 iface = None
             for field in d:
                 key = (mo, iface, field)
                 item = (ts, d[field])
                 bucket = sdata.get(key)
                 if bucket:
                     xdata = bucket[0]
                     xdata += [item]
                 else:
                     sdata[key] = ([item], path)
     # Format result
     result = []
     for mc in req["metrics"]:
         ifaces = tuple(sorted(mc.get("interfaces", [])))
         mo_bi_id = id_to_bi[mc["object"]]
         for mn in mc["metric_types"]:
             mt = MetricType.get_by_name(mn)
             table = mt.scope.table_name
             field = mt.field_name
             if table == S_INTERFACE:
                 if_list = ifaces
             else:
                 if_list = (None, )
             sdata = scope_data[table]
             for iface in if_list:
                 key = (mo_bi_id, iface, field)
                 mdata = sdata.get(key)
                 if not mdata:
                     continue
                 points, path = mdata
                 # Clean data type
                 points = sorted(
                     ((p[0].replace(" ", "T"), mt.clean_value(p[1]))
                      for p in points),
                     key=operator.itemgetter(0),
                 )
                 #
                 r = {
                     "object": mc["object"],
                     "metric_type": mn,
                     "path": path,
                     "values": points
                 }
                 if iface is not None:
                     r["interface"] = iface
                 result += [r]
     # Return response
     return 200, {"from": req["from"], "to": req["to"], "metrics": result}
コード例 #13
0
class Command(BaseCommand):
    """
    Manage Jobs
    """

    logger = logging.getLogger("main")
    TZ = pytz.timezone(noc.settings.TIME_ZONE)
    TMP = "/tmp/noc-import-rancid"

    help = "Import data from rancid"

    def add_arguments(self, parser):

        parser.add_argument(
            parser.add_argument("--routerdb",
                                action="append",
                                dest="routerdb",
                                help="Path to the router.db"),
            parser.add_argument("--cloginrc",
                                action="append",
                                dest="cloginrc",
                                help="Path to the .cloginrc"),
            parser.add_argument("--hosts",
                                action="append",
                                dest="hosts",
                                help="Path to the /etc/hosts"),
            parser.add_argument("--repo",
                                action="store",
                                dest="repo",
                                help="CVS repository"),
            parser.add_argument(
                "--repo-prefix",
                action="store",
                dest="repoprefix",
                help="File path prefix to checkout from repo",
            ),
            parser.add_argument(
                "--dry-run",
                action="store_true",
                dest="dry_run",
                help="Check only, do not write to database",
            ),
            parser.add_argument("--tags",
                                action="append",
                                dest="tags",
                                help="Mark created managed objects by tags"),
            parser.add_argument(
                "--profile",
                action="store",
                dest="object_profile",
                help="Set managed object profile for created objects",
                default="default",
            ),
            parser.add_argument(
                "--domain",
                action="store",
                dest="domain",
                help="Set administrative domain for created objects",
                default="default",
            ),
            parser.add_argument(
                "--pool",
                action="store",
                dest="pool",
                help="Set pool for created objects",
                default="default",
            ),
            parser.add_argument("--shard",
                                action="store",
                                dest="shard",
                                help="Shard import to separate processes"),
        )

    PROFILE_MAP = {
        "cisco": Profile.get_by_name("Cisco.IOS"),
        "juniper": Profile.get_by_name("Juniper.JUNOS"),
    }

    rx_f = re.compile(r"^RCS file: (?P<file>.+?),v$", re.MULTILINE | re.DOTALL)

    rx_fn = re.compile(r"^Working file: (?P<fn>.+?)$",
                       re.MULTILINE | re.DOTALL)

    rx_rev = re.compile(
        r"^-----+\n"
        r"revision (?P<rev>\S+)\n"
        r"date: (?P<date>\S+ \S+(?: \S+)?);.+? state: (?P<state>\S+)",
        re.MULTILINE | re.DOTALL,
    )

    # Regular expresion to split config
    # Config is a final part
    SPLIT_MAP = {
        "Cisco.IOS":
        re.compile(r"^\n", re.MULTILINE),
        "Juniper.JUNOS":
        re.compile(r"^#[^#>\n]+> show configuration\s*\n", re.MULTILINE),
    }

    def parse_hosts(self, hosts):
        """
        Parse /etc/hosts
        :returns: dict of name -> ip
        """
        r = {}
        for path in hosts:
            self.logger.info("Reading hosts from %s", path)
            with open(path) as f:
                for line in f.readlines():
                    if "#" in line:
                        line = line.split("#", 1)[0]
                    line = line.strip()
                    if not line:
                        continue
                    if ":" in line:
                        # Skip IPv6
                        continue
                    parts = line.split()
                    for p in parts[1:]:
                        r[p] = parts[0]
        return r

    def parse_routerdb(self, routerdb):
        rdb = {}  # Name -> profile
        for path in routerdb:
            self.logger.info("Reading routers from %s", path)
            with open(path) as f:
                for line in f.readlines():
                    if "#" in line:
                        line = line.split("#", 1)[0]
                    line = line.strip()
                    if not line:
                        continue
                    r = line.split(":")
                    if len(r) != 3:
                        continue
                    name, t, s = r
                    if s != "up":
                        self.logger.debug("Skipping %s", name)
                        continue
                    p = self.PROFILE_MAP.get(t)
                    if not p:
                        self.logger.info("Unknown type '%s'. Skipping", t)
                        continue
                    rdb[name] = p
        return rdb

    def parse_cloginrc(self, cloginrc):
        login = {}
        defaults = {}
        for path in cloginrc:
            self.logger.info("Reading cloginrc from %s", path)
            with open(path) as f:
                for line in f.readlines():
                    if "#" in line:
                        line = line.split("#", 1)[0]
                    line = line.strip()
                    if not line:
                        continue
                    line = line.replace("\t", " ")
                    r = line.split()
                    if len(r) > 4:
                        op, v, host = r[:3]
                        value = " ".join(r[3:])
                    elif len(r) == 3:
                        op, v, value = r
                        defaults[v] = value
                        continue
                    else:
                        op, v, host, value = r
                    if op != "add":
                        continue
                    if host not in login:
                        login[host] = {}
                    login[host][v] = value
        return login, defaults

    def index_cvs(self, repo):
        r = {}  # path -> (revision, date)
        p = subprocess.Popen(["cvs", "log"], cwd=repo, stdout=subprocess.PIPE)
        data = p.stdout.read()
        parts = self.rx_f.split(data)[2::2]
        for data in parts:
            match = self.rx_fn.search(data)
            if not match:
                continue
            fn = match.group("fn")
            r[fn] = []
            for match in self.rx_rev.finditer(data):
                # if match.group("state").lower() == "dead":
                #    continue  # Ignore object replacement
                rev = match.group("rev")
                date = match.group("date")
                ds = date.split()
                if "/" in ds[0]:
                    fmt = "%Y/%m/%d %H:%M:%S"
                else:
                    fmt = "%Y-%m-%d %H:%M:%S"
                if len(ds) == 3:
                    # Date with TZ
                    date = "%s %s" % (ds[0], ds[1])
                r[fn] += [(
                    rev,
                    self.TZ.normalize(
                        pytz.utc.localize(datetime.datetime.strptime(
                            date, fmt))),
                )]
        return r

    def handle(self, *args, **options):
        connect()
        if options["verbosity"] >= 2:
            self.logger.setLevel(logging.DEBUG)
        else:
            self.logger.setLevel(logging.INFO)
        for h in self.logger.handlers:
            h.setFormatter(
                logging.Formatter("%(asctime)s [%(levelname)s] %(message)s"))
        if not options["routerdb"]:
            raise CommandError("No routerdb given")
        if not options["cloginrc"]:
            raise CommandError("No cloginrc given")
        if not options["hosts"]:
            options["hosts"] = ["/etc/hosts"]
        if not options["repo"]:
            raise CommandError("No CVS repository")
        repo_prefix = options.get("repoprefix") or ""
        if not options["object_profile"]:
            raise CommandError("No object profile set")
        try:
            object_profile = ManagedObjectProfile.objects.get(
                name=options["object_profile"].strip())
        except ManagedObjectProfile.DoesNotExist:
            raise CommandError("Invalid object profile: %s" %
                               options["object_profile"])
        if not options["domain"]:
            raise CommandError("No administrative domain set")
        try:
            domain = AdministrativeDomain.objects.get(
                name=options["domain"].strip())
        except AdministrativeDomain.DoesNotExist:
            raise CommandError("Invalid administrative domain: %s" %
                               options["domain"])
        if not options["pool"]:
            raise CommandError("No pool set")
        try:
            pool = Pool.objects.get(name=options["domain"].strip())
        except Pool.DoesNotExist:
            raise CommandError("Invalid pool: %s" % options["pool"])
        shard_member = 0
        shard_members = 0
        if options.get("shard"):
            shard = options["shard"]
            if "/" not in shard:
                raise CommandError("Shard must be <member>/<members>")
            shard_member, shard_members = [int(x) for x in shard.split("/")]
        tags = []
        if options["tags"]:
            for t in options["tags"]:
                tags += [x.strip() for x in t.split(",")]
        self.dry_run = bool(options["dry_run"])
        #
        if not os.path.isdir(self.TMP):
            os.mkdir(self.TMP)
        #
        revisions = self.index_cvs(options["repo"])
        # Read configs
        hosts = self.parse_hosts(options["hosts"])
        rdb = self.parse_routerdb(options["routerdb"])
        login, ldefaults = self.parse_cloginrc(options["cloginrc"])
        # Process data
        n = 0
        count = len(rdb)
        for name in sorted(rdb):
            if shard_members:
                if n % shard_members != shard_member:
                    n += 1
                    continue  # Processed by other shard
            self.logger.debug("[%s/%s] Processing host %s", n, count, name)
            n += 1
            profile = Profile.get_by_name(rdb[name])
            address = hosts.get(name)
            if not address:
                # @todo: Resolve
                self.logger.info("Cannot resolve address for %s. Skipping",
                                 name)
                continue
            ld = login.get(name, ldefaults)
            if not ld:
                self.logger.info("No credentials for %s. Skipping", name)
                continue
            user = ld.get("user")
            password = ld.get("password")
            if "method" in ld and "ssh" in ld["method"]:
                method = "ssh"
            else:
                method = "telnet"
            self.logger.info(
                "Managed object found: %s (%s, %s://%s@%s/)",
                name,
                profile.name,
                method,
                user,
                address,
            )
            if not self.dry_run:
                try:
                    mo = ManagedObject.objects.get(
                        Q(name=name) | Q(address=address))
                    self.logger.info("Already in the database")
                except ManagedObject.DoesNotExist:
                    self.logger.info("Creating managed object %s", name)
                    mo = ManagedObject(
                        name=name,
                        object_profile=object_profile,
                        administrative_domain=domain,
                        pool=pool,
                        scheme=SSH if method == "ssh" else TELNET,
                        address=address,
                        profile=profile,
                        user=user,
                        password=password,
                        trap_source_ip=address,
                        tags=tags,
                    )
                    mo.save()
            if name not in revisions:
                self.logger.error("Cannot find config for %s", name)
                continue
            if not self.dry_run:
                self.import_revisions(options["repo"], repo_prefix, mo, name,
                                      revisions[name])

    def get_diff(self, repo, name, r0, r1):
        p = subprocess.Popen(
            ["cvs", "diff", "-r%s" % r0,
             "-r%s" % r1, name],
            cwd=repo,
            stdout=subprocess.PIPE)
        return p.stdout.read()

    def import_revisions(self, repo, repo_prefix, mo, name, revisions):
        """
        Import CVS file revisions
        """
        def write_file(path, data):
            with open(path, "w") as f:
                f.write(data)

        path = os.path.join(self.TMP, name)
        lr = len(revisions)
        n = 1
        gridvcs = GridVCS("config")
        split_re = self.SPLIT_MAP[mo.profile.name]
        for rev, ts in reversed(revisions):
            self.logger.debug("%s: importing rev %s [%s/%s]", name, rev, n, lr)
            n += 1
            try:
                subprocess.check_call(
                    "cvs co -p -r%s -f %s > %s" %
                    (rev, os.path.join(repo_prefix, name), path),
                    cwd=repo,
                    shell=True,
                )
            except subprocess.CalledProcessError as e:
                self.logger.error("Failed to import %s@%s. Skipping", name,
                                  rev)
                self.logger.error("CVS reported: %s", e)
                continue
            if not self.dry_run:
                with open(path, "r") as f:
                    data = f.read()
                # Strip config
                data = split_re.split(data, 1)[-1]
                # Save to GridVCS
                gridvcs.put(mo.id, data, ts=ts)
        if os.path.exists(path):
            os.unlink(path)
コード例 #14
0
 def handle(self, *args, **options):
     connect()
     if options["verbosity"] >= 2:
         self.logger.setLevel(logging.DEBUG)
     else:
         self.logger.setLevel(logging.INFO)
     for h in self.logger.handlers:
         h.setFormatter(
             logging.Formatter("%(asctime)s [%(levelname)s] %(message)s"))
     if not options["routerdb"]:
         raise CommandError("No routerdb given")
     if not options["cloginrc"]:
         raise CommandError("No cloginrc given")
     if not options["hosts"]:
         options["hosts"] = ["/etc/hosts"]
     if not options["repo"]:
         raise CommandError("No CVS repository")
     repo_prefix = options.get("repoprefix") or ""
     if not options["object_profile"]:
         raise CommandError("No object profile set")
     try:
         object_profile = ManagedObjectProfile.objects.get(
             name=options["object_profile"].strip())
     except ManagedObjectProfile.DoesNotExist:
         raise CommandError("Invalid object profile: %s" %
                            options["object_profile"])
     if not options["domain"]:
         raise CommandError("No administrative domain set")
     try:
         domain = AdministrativeDomain.objects.get(
             name=options["domain"].strip())
     except AdministrativeDomain.DoesNotExist:
         raise CommandError("Invalid administrative domain: %s" %
                            options["domain"])
     if not options["pool"]:
         raise CommandError("No pool set")
     try:
         pool = Pool.objects.get(name=options["domain"].strip())
     except Pool.DoesNotExist:
         raise CommandError("Invalid pool: %s" % options["pool"])
     shard_member = 0
     shard_members = 0
     if options.get("shard"):
         shard = options["shard"]
         if "/" not in shard:
             raise CommandError("Shard must be <member>/<members>")
         shard_member, shard_members = [int(x) for x in shard.split("/")]
     tags = []
     if options["tags"]:
         for t in options["tags"]:
             tags += [x.strip() for x in t.split(",")]
     self.dry_run = bool(options["dry_run"])
     #
     if not os.path.isdir(self.TMP):
         os.mkdir(self.TMP)
     #
     revisions = self.index_cvs(options["repo"])
     # Read configs
     hosts = self.parse_hosts(options["hosts"])
     rdb = self.parse_routerdb(options["routerdb"])
     login, ldefaults = self.parse_cloginrc(options["cloginrc"])
     # Process data
     n = 0
     count = len(rdb)
     for name in sorted(rdb):
         if shard_members:
             if n % shard_members != shard_member:
                 n += 1
                 continue  # Processed by other shard
         self.logger.debug("[%s/%s] Processing host %s", n, count, name)
         n += 1
         profile = Profile.get_by_name(rdb[name])
         address = hosts.get(name)
         if not address:
             # @todo: Resolve
             self.logger.info("Cannot resolve address for %s. Skipping",
                              name)
             continue
         ld = login.get(name, ldefaults)
         if not ld:
             self.logger.info("No credentials for %s. Skipping", name)
             continue
         user = ld.get("user")
         password = ld.get("password")
         if "method" in ld and "ssh" in ld["method"]:
             method = "ssh"
         else:
             method = "telnet"
         self.logger.info(
             "Managed object found: %s (%s, %s://%s@%s/)",
             name,
             profile.name,
             method,
             user,
             address,
         )
         if not self.dry_run:
             try:
                 mo = ManagedObject.objects.get(
                     Q(name=name) | Q(address=address))
                 self.logger.info("Already in the database")
             except ManagedObject.DoesNotExist:
                 self.logger.info("Creating managed object %s", name)
                 mo = ManagedObject(
                     name=name,
                     object_profile=object_profile,
                     administrative_domain=domain,
                     pool=pool,
                     scheme=SSH if method == "ssh" else TELNET,
                     address=address,
                     profile=profile,
                     user=user,
                     password=password,
                     trap_source_ip=address,
                     tags=tags,
                 )
                 mo.save()
         if name not in revisions:
             self.logger.error("Cannot find config for %s", name)
             continue
         if not self.dry_run:
             self.import_revisions(options["repo"], repo_prefix, mo, name,
                                   revisions[name])
コード例 #15
0
ファイル: views.py プロジェクト: nbashev/noc
 def get_data(self,
              request,
              repo="config",
              days=1,
              adm_domain=None,
              managed_object=None,
              **kwargs):
     baseline = datetime.datetime.now() - datetime.timedelta(days=days)
     coll = get_db()["noc.gridvcs.%s.files" % repo].with_options(
         read_preference=ReadPreference.SECONDARY_PREFERRED)
     pipeline = [
         {
             "$match": {
                 "ts": {
                     "$gte": baseline
                 }
             }
         },
         {
             "$group": {
                 "_id": "$object",
                 "last_ts": {
                     "$max": "$ts"
                 }
             }
         },
         {
             "$sort": {
                 "_id": 1
             }
         },
     ]
     if repo == "config":
         objects = ManagedObject.objects.filter()
         if not request.user.is_superuser:
             objects = objects.filter(administrative_domain__in=UserAccess.
                                      get_domains(request.user))
         if adm_domain:
             adm_domain = AdministrativeDomain.get_nested_ids(adm_domain)
             objects = objects.filter(administrative_domain__in=adm_domain)
         if managed_object:
             mo_q = ManagedObject.get_search_Q(managed_object)
             if not mo_q:
                 objects = objects.filter(name__contains=managed_object)
             else:
                 objects = objects.filter(mo_q)
         pipeline = [{
             "$match": {
                 "object": {
                     "$in": list(objects.values_list("id", flat=True))
                 }
             }
         }] + pipeline
     # Perform query
     data = list(coll.aggregate(pipeline))
     # Resolve names
     result = []
     if data:
         seen_ids = list(set(d["_id"] for d in data))
         n_map = {}
         if repo == "config":
             n_map = {
                 x[0]: x[1:]
                 for x in ManagedObject.objects.filter(
                     id__in=list(seen_ids)).values_list(
                         "id", "name", "address", "profile")
             }
         elif repo == "dns":
             n_map = {
                 x[0]: x[1:]
                 for x in DNSZone.objects.filter(
                     id__in=list(seen_ids)).values_list(
                         "id", "name", "address", "profile")
             }
         for d in data:
             name, profile = n_map.get(d["_id"], ("-", None))
             result += [(d["_id"], name,
                         Profile.get_by_id(profile) if profile else "-",
                         d["last_ts"])]
     return self.from_dataset(
         title="%s: %s in %d days" % (self.title, repo, days),
         columns=[
             "ID",
             "Name",
             "Address",
             "Profile",
             TableColumn(_("Last Changed"), format="datetime"),
         ],
         data=result,
         enumerate=True,
     )
コード例 #16
0
ファイル: views.py プロジェクト: gabrielat/noc
    def get_data(self, request, pool=None, obj_profile=None, **kwargs):
        problems = {}  # id -> problem

        mos = ManagedObject.objects.filter(is_managed=True, pool=pool)
        if not request.user.is_superuser:
            mos = mos.filter(administrative_domain__in=UserAccess.get_domains(request.user))
        if obj_profile:
            # Get all managed objects
            mos = mos.filter(object_profile=obj_profile)
        mos = {
            mo[0]: (mo[1], mo[2], Profile.get_by_id(mo[3]), mo[4], mo[5])
            for mo in mos.values_list("id", "name", "address", "profile", "platform", "segment")
        }
        mos_set = set(mos)
        # Get all managed objects with generic profile
        for mo in mos:
            if mos[mo][2] == GENERIC_PROFILE:
                problems[mo] = _("Profile check failed")
        # Get all managed objects without interfaces
        if_mo = dict(
            (x["_id"], x.get("managed_object"))
            for x in Interface._get_collection().find({}, {"_id": 1, "managed_object": 1})
        )
        for mo in mos_set - set(problems) - set(six.itervalues(if_mo)):
            problems[mo] = _("No interfaces")
        # Get all managed objects without links
        linked_mos = set()
        for d in Link._get_collection().find({}):
            for i in d["interfaces"]:
                linked_mos.add(if_mo.get(i))
        for mo in mos_set - set(problems) - linked_mos:
            problems[mo] = _("No links")
        # Get all managed objects without uplinks
        uplinks = {}
        for d in ObjectData._get_collection().find():
            nu = len(d.get("uplinks", []))
            if nu:
                uplinks[d["_id"]] = nu
        for mo in mos_set - set(problems) - set(uplinks):
            problems[mo] = _("No uplinks")
        #
        data = []
        for mo_id in problems:
            if mo_id not in mos:
                continue
            name, address, profile, platform, segment = mos[mo_id]
            data += [
                [
                    name,
                    address,
                    profile.name,
                    Platform.get_by_id(platform).name if platform else "",
                    NetworkSegment.get_by_id(segment).name if segment else "",
                    problems[mo_id],
                ]
            ]
        data = sorted(data)
        return self.from_dataset(
            title=self.title,
            columns=["Name", "Address", "Profile", "Platform", "Segment", "Problem"],
            data=data,
            enumerate=True,
        )
コード例 #17
0
ファイル: test_discovery.py プロジェクト: 0pt1on/noc
def get_profile(name):
    return Profile.get_by_name(name)
コード例 #18
0
    def update_spec(self, name, script):
        """
        Update named spec
        :param name: Spec name
        :param script: BaseScript instance
        :return:
        """
        from noc.dev.models.quiz import Quiz
        from noc.dev.models.spec import Spec, SpecAnswer
        from noc.sa.models.profile import Profile

        self.print("Updating spec: %s" % name)
        spec = Spec.get_by_name(name)
        changed = False
        if not spec:
            self.print("   Spec not found. Creating")
            # Get Ad-Hoc quiz
            quiz = Quiz.get_by_name("Ad-Hoc")
            if not quiz:
                self.print("   'Ad-Hoc' quiz not found. Skipping")
                return
            # Create Ad-Hoc spec for profile
            spec = Spec(
                name,
                description="Auto-generated Ad-Hoc spec for %s profile" %
                script.profile.name,
                revision=1,
                quiz=quiz,
                author="NOC",
                profile=Profile.get_by_name(script.profile.name),
                changes=[],
                answers=[])
            changed = True
        # Fetch commands from spans
        cli_svc = {"beef_cli", "cli", "telnet", "ssh"}
        commands = set()
        for sd in get_spans():
            row = sd.split("\t")
            if row[6] not in cli_svc:
                continue
            commands.add(row[12].decode("string_escape").strip())
        # Update specs
        s_name = "cli_%s" % script.name.rsplit(".", 1)[-1]
        names = set()
        for ans in spec.answers:
            if ((ans.name == s_name or ans.name.startswith(s_name + "."))
                    and ans.type == "cli"):
                names.add(ans.name)
                if ans.value in commands:
                    # Already recorded
                    commands.remove(ans.value)
        if commands:
            # New commands left
            max_n = 0
            for n in names:
                if "." in n:
                    nn = int(n.rsplit(".", 1)[-1])
                    if nn > max_n:
                        max_n = nn
            #
            ntpl = "%s.%%d" % s_name
            for nn, cmd in enumerate(sorted(commands)):
                spec.answers += [
                    SpecAnswer(name=ntpl % (nn + 1), type="cli", value=cmd)
                ]
            changed = True
        if changed:
            spec.save()
コード例 #19
0
ファイル: views.py プロジェクト: nbashev/noc
    def api_report(
        self,
        request,
        from_date,
        to_date,
        o_format,
        min_duration=0,
        max_duration=0,
        min_objects=0,
        min_subscribers=0,
        segment=None,
        administrative_domain=None,
        selector=None,
        ex_selector=None,
        columns=None,
        source="both",
        alarm_class=None,
        subscribers=None,
        enable_autowidth=False,
    ):
        def row(row, container_path, segment_path):
            def qe(v):
                if v is None:
                    return ""
                if isinstance(v, str):
                    return smart_text(v)
                elif isinstance(v, datetime.datetime):
                    return v.strftime("%Y-%m-%d %H:%M:%S")
                elif not isinstance(v, str):
                    return smart_text(v)
                else:
                    return v

            r = [qe(x) for x in row]
            if len(container_path) < self.CONTAINER_PATH_DEPTH:
                container_path += [""] * (self.CONTAINER_PATH_DEPTH -
                                          len(container_path))
            else:
                container_path = container_path[:self.CONTAINER_PATH_DEPTH]
            if len(segment_path) < self.SEGMENT_PATH_DEPTH:
                segment_path += [""] * (self.SEGMENT_PATH_DEPTH -
                                        len(segment_path))
            else:
                segment_path = segment_path[:self.SEGMENT_PATH_DEPTH]
            return r + container_path + segment_path

        def translate_row(row, cmap):
            return [row[i] for i in cmap]

        cols = ([
            "id",
            "root_id",
            "from_ts",
            "to_ts",
            "duration_sec",
            "object_name",
            "object_address",
            "object_hostname",
            "object_profile",
            "object_admdomain",
            "object_platform",
            "object_version",
            "alarm_class",
            "alarm_subject",
            "maintenance",
            "objects",
            "subscribers",
            "tt",
            "escalation_ts",
            "location",
            "container_address",
        ] + ["container_%d" % i for i in range(self.CONTAINER_PATH_DEPTH)] +
                ["segment_%d" % i for i in range(self.SEGMENT_PATH_DEPTH)])

        header_row = (
            [
                "ID",
                _("ROOT_ID"),
                _("FROM_TS"),
                _("TO_TS"),
                _("DURATION_SEC"),
                _("OBJECT_NAME"),
                _("OBJECT_ADDRESS"),
                _("OBJECT_HOSTNAME"),
                _("OBJECT_PROFILE"),
                _("OBJECT_ADMDOMAIN"),
                _("OBJECT_PLATFORM"),
                _("OBJECT_VERSION"),
                _("ALARM_CLASS"),
                _("ALARM_SUBJECT"),
                _("MAINTENANCE"),
                _("OBJECTS"),
                _("SUBSCRIBERS"),
                _("TT"),
                _("ESCALATION_TS"),
                _("LOCATION"),
                _("CONTAINER_ADDRESS"),
            ] + ["CONTAINER_%d" % i
                 for i in range(self.CONTAINER_PATH_DEPTH)] +
            ["SEGMENT_%d" % i for i in range(self.SEGMENT_PATH_DEPTH)])

        if columns:
            cmap = []
            for c in columns.split(","):
                try:
                    cmap += [cols.index(c)]
                except ValueError:
                    continue
        else:
            cmap = list(range(len(cols)))
        subscribers_profile = self.default_subscribers_profile
        if subscribers:
            subscribers_profile = set(
                SubscriberProfile.objects.filter(
                    id__in=subscribers.split(",")).scalar("id"))
        r = [translate_row(header_row, cmap)]
        fd = datetime.datetime.strptime(
            to_date, "%d.%m.%Y") + datetime.timedelta(days=1)
        match = {
            "timestamp": {
                "$gte": datetime.datetime.strptime(from_date, "%d.%m.%Y"),
                "$lte": fd
            }
        }

        match_duration = {"duration": {"$gte": min_duration}}
        if max_duration:
            match_duration = {
                "duration": {
                    "$gte": min_duration,
                    "$lte": max_duration
                }
            }
        mos = ManagedObject.objects.filter(is_managed=True)

        if segment:
            try:
                match["segment_path"] = bson.ObjectId(segment)
            except bson.errors.InvalidId:
                pass

        ads = []
        if administrative_domain:
            if administrative_domain.isdigit():
                administrative_domain = [int(administrative_domain)]
                ads = AdministrativeDomain.get_nested_ids(
                    administrative_domain[0])

        if not request.user.is_superuser:
            user_ads = UserAccess.get_domains(request.user)
            if administrative_domain and ads:
                if administrative_domain[0] not in user_ads:
                    ads = list(set(ads) & set(user_ads))
                    if not ads:
                        return HttpResponse(
                            "<html><body>Permission denied: Invalid Administrative Domain</html></body>"
                        )
            else:
                ads = user_ads
        if ads:
            mos = mos.filter(administrative_domain__in=ads)
        if selector:
            selector = ManagedObjectSelector.get_by_id(int(selector))
            mos = mos.filter(selector.Q)
        if ex_selector:
            ex_selector = ManagedObjectSelector.get_by_id(int(ex_selector))
            mos = mos.exclude(ex_selector.Q)

        # Working if Administrative domain set
        if ads:
            try:
                match["adm_path"] = {"$in": ads}
                # @todo More 2 level hierarhy
            except bson.errors.InvalidId:
                pass

        mos_id = list(mos.order_by("id").values_list("id", flat=True))
        mo_hostname = {}
        maintenance = []
        if mos_id and (selector or ex_selector):
            match["managed_object"] = {"$in": mos_id}
        if "maintenance" in columns.split(","):
            maintenance = Maintenance.currently_affected()
        if "object_hostname" in columns.split(","):
            mo_hostname = ReportObjectsHostname1(sync_ids=mos_id)
            mo_hostname = mo_hostname.get_dictionary()
        moss = ReportAlarmObjects(mos_id).get_all()
        # container_lookup = ReportContainer(mos_id)
        container_lookup = None
        subject = "alarm_subject" in columns
        loc = AlarmApplication([])
        if source in ["archive", "both"]:
            # Archived Alarms
            for a in (ArchivedAlarm._get_collection().with_options(
                    read_preference=ReadPreference.SECONDARY_PREFERRED
            ).aggregate([
                {
                    "$match": match
                },
                {
                    "$addFields": {
                        "duration": {
                            "$divide": [
                                {
                                    "$subtract":
                                    ["$clear_timestamp", "$timestamp"]
                                },
                                1000,
                            ]
                        }
                    }
                },
                {
                    "$match": match_duration
                },
                    # {"$sort": {"timestamp": 1}}
            ])):
                if int(a["managed_object"]) not in moss:
                    continue
                dt = a["clear_timestamp"] - a["timestamp"]
                duration = int(dt.total_seconds())
                total_objects = sum(ss["summary"] for ss in a["total_objects"])
                if min_objects and total_objects < min_objects:
                    continue
                total_subscribers = sum(
                    ss["summary"] for ss in a["total_subscribers"]
                    if subscribers_profile
                    and ss["profile"] in subscribers_profile)
                if min_subscribers and total_subscribers < min_subscribers:
                    continue
                if "segment_" in columns.split(
                        ",") or "container_" in columns.split(","):
                    path = ObjectPath.get_path(a["managed_object"])
                    if path:
                        segment_path = [
                            NetworkSegment.get_by_id(s).name
                            for s in path.segment_path
                            if NetworkSegment.get_by_id(s)
                        ]
                        container_path = [
                            Object.get_by_id(s).name
                            for s in path.container_path if Object.get_by_id(s)
                        ]
                    else:
                        segment_path = []
                        container_path = []
                else:
                    segment_path = []
                    container_path = []
                r += [
                    translate_row(
                        row(
                            [
                                smart_text(a["_id"]),
                                smart_text(a["root"]) if a.get("root") else "",
                                a["timestamp"],
                                a["clear_timestamp"],
                                smart_text(duration),
                                moss[a["managed_object"]][0],
                                moss[a["managed_object"]][1],
                                smart_text(
                                    mo_hostname.get(a["managed_object"], "")),
                                Profile.get_by_id(
                                    moss[a["managed_object"]][3]).name
                                if moss[a["managed_object"]][5] else "",
                                moss[a["managed_object"]][6],
                                Platform.get_by_id(
                                    moss[a["managed_object"]][9])
                                if moss[a["managed_object"]][9] else "",
                                smart_text(
                                    Firmware.get_by_id(
                                        moss[a["managed_object"]][10]).version)
                                if moss[a["managed_object"]][10] else "",
                                AlarmClass.get_by_id(a["alarm_class"]).name,
                                ArchivedAlarm.objects.get(
                                    id=a["_id"]).subject if subject else "",
                                "",
                                total_objects,
                                total_subscribers,
                                a.get("escalation_tt"),
                                a.get("escalation_ts"),
                                ", ".join(ll for ll in (
                                    loc.location(moss[a["managed_object"]][5]
                                                 ) if moss[a["managed_object"]]
                                    [5] is not None else "") if ll),
                                container_lookup[a["managed_object"]].get(
                                    "text", "") if container_lookup else "",
                            ],
                            container_path,
                            segment_path,
                        ),
                        cmap,
                    )
                ]
        # Active Alarms
        if source in ["active", "both"]:
            datenow = datetime.datetime.now()
            for a in (ActiveAlarm._get_collection().with_options(
                    read_preference=ReadPreference.SECONDARY_PREFERRED).
                      aggregate([
                          {
                              "$match": match
                          },
                          {
                              "$addFields": {
                                  "duration": {
                                      "$divide": [{
                                          "$subtract": [fd, "$timestamp"]
                                      }, 1000]
                                  }
                              }
                          },
                          {
                              "$match": match_duration
                          },
                          # {"$sort": {"timestamp": 1}}
                      ])):
                dt = datenow - a["timestamp"]
                duration = int(dt.total_seconds())
                total_objects = sum(ss["summary"] for ss in a["total_objects"])
                if min_objects and total_objects < min_objects:
                    continue
                total_subscribers = sum(
                    ss["summary"] for ss in a["total_subscribers"]
                    if subscribers_profile
                    and ss["profile"] in subscribers_profile)
                if min_subscribers and total_subscribers < min_subscribers:
                    continue
                if "segment_" in columns.split(
                        ",") or "container_" in columns.split(","):
                    path = ObjectPath.get_path(a["managed_object"])
                    if path:
                        segment_path = [
                            NetworkSegment.get_by_id(s).name
                            for s in path.segment_path
                            if NetworkSegment.get_by_id(s)
                        ]
                        container_path = [
                            Object.get_by_id(s).name
                            for s in path.container_path if Object.get_by_id(s)
                        ]
                    else:
                        segment_path = []
                        container_path = []
                else:
                    segment_path = []
                    container_path = []
                r += [
                    translate_row(
                        row(
                            [
                                smart_text(a["_id"]),
                                smart_text(a["root"]) if a.get("root") else "",
                                a["timestamp"],
                                # a["clear_timestamp"],
                                "",
                                smart_text(duration),
                                moss[a["managed_object"]][0],
                                moss[a["managed_object"]][1],
                                smart_text(
                                    mo_hostname.get(a["managed_object"], "")),
                                Profile.get_by_id(moss[a["managed_object"]][3])
                                if moss[a["managed_object"]][5] else "",
                                moss[a["managed_object"]][6],
                                Platform.get_by_id(
                                    moss[a["managed_object"]][9])
                                if moss[a["managed_object"]][9] else "",
                                smart_text(
                                    Firmware.get_by_id(
                                        moss[a["managed_object"]][10]).version)
                                if moss[a["managed_object"]][10] else "",
                                AlarmClass.get_by_id(a["alarm_class"]).name,
                                ActiveAlarm.objects.get(
                                    id=a["_id"]).subject if subject else None,
                                "Yes" if a["managed_object"] in maintenance
                                else "No",
                                total_objects,
                                total_subscribers,
                                a.get("escalation_tt"),
                                a.get("escalation_ts"),
                                ", ".join(ll for ll in (
                                    loc.location(moss[a["managed_object"]][5]
                                                 ) if moss[a["managed_object"]]
                                    [5] is not None else "") if ll),
                                container_lookup[a["managed_object"]].get(
                                    "text", "") if container_lookup else "",
                            ],
                            container_path,
                            segment_path,
                        ),
                        cmap,
                    )
                ]
        if source in ["long_archive"]:
            o_format = "csv_zip"
            columns = [
                "ALARM_ID",
                "MO_ID",
                "OBJECT_PROFILE",
                "VENDOR",
                "PLATFORM",
                "VERSION",
                "OPEN_TIMESTAMP",
                "CLOSE_TIMESTAMP",
                "LOCATION",
                "",
                "POOL",
                "ADM_DOMAIN",
                "MO_NAME",
                "IP",
                "ESCALATION_TT",
                "DURATION",
                "SEVERITY",
                "REBOOTS",
            ]
            from noc.core.clickhouse.connect import connection

            ch = connection()
            fd = datetime.datetime.strptime(from_date, "%d.%m.%Y")
            td = datetime.datetime.strptime(
                to_date, "%d.%m.%Y") + datetime.timedelta(days=1)
            if td - fd > datetime.timedelta(days=390):
                return HttpResponseBadRequest(
                    _("Report more than 1 year not allowed. If nedeed - request it from Administrator"
                      ))
            ac = AlarmClass.objects.get(
                name="NOC | Managed Object | Ping Failed")
            subs = ", ".join(
                "subscribers.summary[indexOf(subscribers.profile, '%s')] as `%s`"
                % (sp.bi_id, sp.name)
                for sp in SubscriberProfile.objects.filter().order_by("name"))
            if subs:
                columns += [
                    sp.name for sp in
                    SubscriberProfile.objects.filter().order_by("name")
                ]
            r = ch.execute(LONG_ARCHIVE_QUERY % (
                ", %s" % subs if subs else "",
                fd.date().isoformat(),
                td.date().isoformat(),
                ac.bi_id,
            ))

        filename = "alarms.csv"
        if o_format == "csv":
            response = HttpResponse(content_type="text/csv")
            response[
                "Content-Disposition"] = 'attachment; filename="%s"' % filename
            writer = csv.writer(response)
            writer.writerows(r)
            return response
        elif o_format == "csv_zip":
            response = BytesIO()
            f = TextIOWrapper(TemporaryFile(mode="w+b"), encoding="utf-8")
            writer = csv.writer(f,
                                dialect="excel",
                                delimiter=";",
                                quotechar='"')
            writer.writerow(columns)
            writer.writerows(r)
            f.seek(0)
            with ZipFile(response, "w", compression=ZIP_DEFLATED) as zf:
                zf.writestr(filename, f.read())
                zf.filename = "%s.zip" % filename
            # response = HttpResponse(content_type="text/csv")
            response.seek(0)
            response = HttpResponse(response.getvalue(),
                                    content_type="application/zip")
            response[
                "Content-Disposition"] = 'attachment; filename="%s.zip"' % filename
            return response
        elif o_format == "xlsx":
            response = BytesIO()
            wb = xlsxwriter.Workbook(response)
            cf1 = wb.add_format({"bottom": 1, "left": 1, "right": 1, "top": 1})
            ws = wb.add_worksheet("Alarms")
            max_column_data_length = {}
            for rn, x in enumerate(r):
                for cn, c in enumerate(x):
                    if rn and (r[0][cn] not in max_column_data_length or
                               len(str(c)) > max_column_data_length[r[0][cn]]):
                        max_column_data_length[r[0][cn]] = len(str(c))
                    ws.write(rn, cn, c, cf1)
            ws.autofilter(0, 0, rn, cn)
            ws.freeze_panes(1, 0)
            for cn, c in enumerate(r[0]):
                # Set column width
                width = get_column_width(c)
                if enable_autowidth and width < max_column_data_length[c]:
                    width = max_column_data_length[c]
                ws.set_column(cn, cn, width=width)
            wb.close()
            response.seek(0)
            response = HttpResponse(response.getvalue(),
                                    content_type="application/vnd.ms-excel")
            response[
                "Content-Disposition"] = 'attachment; filename="alarms.xlsx"'
            response.close()
            return response
コード例 #20
0
 def handle(
     self, paths, profile, format, report=None, reject=None, progress=False, *args, **options
 ):
     connect()
     assert profile_loader.has_profile(profile), "Invalid profile: %s" % profile
     if report:
         report_writer = csv.writer(
             report, delimiter=",", quotechar='"', quoting=csv.QUOTE_MINIMAL
         )
         report_writer.writerow(["message", "event class", "rule name", "vars"])
     t0 = time.time()
     ruleset = RuleSet()
     ruleset.load()
     self.print("Ruleset load in %.2fms" % ((time.time() - t0) * 1000))
     reader = getattr(self, "read_%s" % format, None)
     assert reader, "Invalid format %s" % format
     self.managed_object = ManagedObject(
         id=1, name="test", address="127.0.0.1", profile=Profile.get_by_name(profile)
     )
     t0 = time.time()
     stats = defaultdict(int)
     total = 0
     for p in paths:
         if not os.path.isfile(p):
             continue
         for f in iter_open(p):
             for event in reader(f):
                 e_vars = event.raw_vars.copy()
                 if event.source == "SNMP Trap":
                     e_vars.update(MIB.resolve_vars(event.raw_vars))
                 rule, r_vars = ruleset.find_rule(event, e_vars)
                 if report:
                     report_writer.writerow(
                         [event.raw_vars["message"], rule.event_class.name, rule.name, r_vars]
                     )
                 if reject and rule.is_unknown:
                     reject.write(f'{event.raw_vars["message"]}\n')
                 stats[rule.event_class.name] += 1
                 total += 1
                 if progress and total % 1000 == 0:
                     self.print("%d records processed" % total)
     dt = time.time() - t0
     self.print(
         "%d events processed in %.2fms (%.fevents/sec)" % (total, dt * 1000, float(total) / dt)
     )
     if stats:
         # Prepare statistics
         s_data = sorted(
             [(k, stats[k]) for k in stats], key=operator.itemgetter(1), reverse=True
         )
         s_total = sum(stats[k] for k in stats if not self.is_ignored(k))
         data = [["Events", "%", "Event class"]]
         for ecls, qty in s_data:
             data += [[str(qty), "%3.2f%%" % (float(stats[ecls] * 100) / float(total)), ecls]]
         # Calculate classification quality
         data += [["", "%3.2f%%" % (float(s_total * 100) / total), "Classification Quality"]]
         # Ruleset hit rate
         rs_rate = float(metrics["rules_checked"].value) / float(total)
         data += [["", "%.2f" % rs_rate, "Rule checks per event"]]
         # Dump table
         self.print("Event classes summary:")
         self.print(format_table([4, 6, 10], data))
コード例 #21
0
ファイル: test_sa_profile.py プロジェクト: nbashev/noc
def test_generic_profile_id():
    p = Profile.get_generic_profile_id()
    assert p
    assert isinstance(p, bson.ObjectId)
コード例 #22
0
    def api_report(
        self,
        request,
        from_date,
        to_date,
        o_format,
        min_duration=0,
        max_duration=0,
        min_objects=0,
        min_subscribers=0,
        segment=None,
        administrative_domain=None,
        selector=None,
        ex_selector=None,
        columns=None,
        source="both",
        alarm_class=None,
        subscribers=None,
        enable_autowidth=False,
    ):
        def row(row, container_path, segment_path):
            def qe(v):
                if v is None:
                    return ""
                if isinstance(v, unicode):
                    return v.encode("utf-8")
                elif isinstance(v, datetime.datetime):
                    return v.strftime("%Y-%m-%d %H:%M:%S")
                elif not isinstance(v, str):
                    return str(v)
                else:
                    return v

            r = [qe(x) for x in row]
            if len(container_path) < self.CONTAINER_PATH_DEPTH:
                container_path += [""] * (self.CONTAINER_PATH_DEPTH -
                                          len(container_path))
            else:
                container_path = container_path[:self.CONTAINER_PATH_DEPTH]
            if len(segment_path) < self.SEGMENT_PATH_DEPTH:
                segment_path += [""] * (self.SEGMENT_PATH_DEPTH -
                                        len(segment_path))
            else:
                segment_path = segment_path[:self.SEGMENT_PATH_DEPTH]
            return r + container_path + segment_path

        def translate_row(row, cmap):
            return [row[i] for i in cmap]

        cols = ([
            "id",
            "root_id",
            "from_ts",
            "to_ts",
            "duration_sec",
            "object_name",
            "object_address",
            "object_hostname",
            "object_profile",
            "object_admdomain",
            "object_platform",
            "object_version",
            "alarm_class",
            "alarm_subject",
            "maintenance",
            "objects",
            "subscribers",
            "tt",
            "escalation_ts",
            "location",
            "container_address",
        ] + ["container_%d" % i for i in range(self.CONTAINER_PATH_DEPTH)] +
                ["segment_%d" % i for i in range(self.SEGMENT_PATH_DEPTH)])

        header_row = (
            [
                "ID",
                _("ROOT_ID"),
                _("FROM_TS"),
                _("TO_TS"),
                _("DURATION_SEC"),
                _("OBJECT_NAME"),
                _("OBJECT_ADDRESS"),
                _("OBJECT_HOSTNAME"),
                _("OBJECT_PROFILE"),
                _("OBJECT_ADMDOMAIN"),
                _("OBJECT_PLATFORM"),
                _("OBJECT_VERSION"),
                _("ALARM_CLASS"),
                _("ALARM_SUBJECT"),
                _("MAINTENANCE"),
                _("OBJECTS"),
                _("SUBSCRIBERS"),
                _("TT"),
                _("ESCALATION_TS"),
                _("LOCATION"),
                _("CONTAINER_ADDRESS"),
            ] + ["CONTAINER_%d" % i
                 for i in range(self.CONTAINER_PATH_DEPTH)] +
            ["SEGMENT_%d" % i for i in range(self.SEGMENT_PATH_DEPTH)])

        if columns:
            cmap = []
            for c in columns.split(","):
                try:
                    cmap += [cols.index(c)]
                except ValueError:
                    continue
        else:
            cmap = list(range(len(cols)))
        subscribers_profile = self.default_subscribers_profile
        if subscribers:
            subscribers_profile = set(
                SubscriberProfile.objects.filter(
                    id__in=subscribers.split(",")).scalar("id"))
        r = [translate_row(header_row, cmap)]
        fd = datetime.datetime.strptime(
            to_date, "%d.%m.%Y") + datetime.timedelta(days=1)
        match = {
            "timestamp": {
                "$gte": datetime.datetime.strptime(from_date, "%d.%m.%Y"),
                "$lte": fd
            }
        }

        match_duration = {"duration": {"$gte": min_duration}}
        if max_duration:
            match_duration = {
                "duration": {
                    "$gte": min_duration,
                    "$lte": max_duration
                }
            }
        mos = ManagedObject.objects.filter(is_managed=True)

        if segment:
            try:
                match["segment_path"] = bson.ObjectId(segment)
            except bson.errors.InvalidId:
                pass

        ads = []
        if administrative_domain:
            if administrative_domain.isdigit():
                administrative_domain = [int(administrative_domain)]
                ads = AdministrativeDomain.get_nested_ids(
                    administrative_domain[0])

        if not request.user.is_superuser:
            user_ads = UserAccess.get_domains(request.user)
            if administrative_domain and ads:
                if administrative_domain[0] not in user_ads:
                    ads = list(set(ads) & set(user_ads))
                else:
                    ads = administrative_domain
            else:
                ads = user_ads
        if ads:
            mos = mos.filter(administrative_domain__in=ads)
        if selector:
            selector = ManagedObjectSelector.get_by_id(int(selector))
            mos = mos.filter(selector.Q)
        if ex_selector:
            ex_selector = ManagedObjectSelector.get_by_id(int(ex_selector))
            mos = mos.exclude(ex_selector.Q)

        # Working if Administrative domain set
        if ads:
            try:
                match["adm_path"] = {"$in": ads}
                # @todo More 2 level hierarhy
            except bson.errors.InvalidId:
                pass

        mos_id = list(mos.order_by("id").values_list("id", flat=True))
        mo_hostname = {}
        maintenance = []
        if mos_id and (selector or ex_selector):
            match["managed_object"] = {"$in": mos_id}
        if "maintenance" in columns.split(","):
            maintenance = Maintenance.currently_affected()
        if "object_hostname" in columns.split(","):
            mo_hostname = ReportObjectsHostname1(sync_ids=mos_id)
            mo_hostname = mo_hostname.get_dictionary()
        moss = ReportAlarmObjects(mos_id).get_all()
        # container_lookup = ReportContainer(mos_id)
        container_lookup = None
        subject = "alarm_subject" in columns
        loc = AlarmApplication([])
        if source in ["archive", "both"]:
            # Archived Alarms
            for a in (ArchivedAlarm._get_collection().with_options(
                    read_preference=ReadPreference.SECONDARY_PREFERRED
            ).aggregate([
                {
                    "$match": match
                },
                {
                    "$addFields": {
                        "duration": {
                            "$divide": [
                                {
                                    "$subtract":
                                    ["$clear_timestamp", "$timestamp"]
                                },
                                1000,
                            ]
                        }
                    }
                },
                {
                    "$match": match_duration
                },
                    # {"$sort": {"timestamp": 1}}
            ])):
                if int(a["managed_object"]) not in moss:
                    continue
                dt = a["clear_timestamp"] - a["timestamp"]
                duration = int(dt.total_seconds())
                total_objects = sum(ss["summary"] for ss in a["total_objects"])
                if min_objects and total_objects < min_objects:
                    continue
                total_subscribers = sum(
                    ss["summary"] for ss in a["total_subscribers"]
                    if subscribers_profile
                    and ss["profile"] in subscribers_profile)
                if min_subscribers and total_subscribers < min_subscribers:
                    continue
                if "segment_" in columns.split(
                        ",") or "container_" in columns.split(","):
                    path = ObjectPath.get_path(a["managed_object"])
                    if path:
                        segment_path = [
                            NetworkSegment.get_by_id(s).name
                            for s in path.segment_path
                            if NetworkSegment.get_by_id(s)
                        ]
                        container_path = [
                            Object.get_by_id(s).name
                            for s in path.container_path if Object.get_by_id(s)
                        ]
                    else:
                        segment_path = []
                        container_path = []
                else:
                    segment_path = []
                    container_path = []
                r += [
                    translate_row(
                        row(
                            [
                                str(a["_id"]),
                                str(a["root"]) if a.get("root") else "",
                                a["timestamp"],
                                a["clear_timestamp"],
                                str(duration),
                                moss[a["managed_object"]][0],
                                moss[a["managed_object"]][1],
                                mo_hostname.get(a["managed_object"], ""),
                                Profile.get_by_id(
                                    moss[a["managed_object"]][3]).name
                                if moss[a["managed_object"]][5] else "",
                                moss[a["managed_object"]][6],
                                Platform.get_by_id(
                                    moss[a["managed_object"]][9])
                                if moss[a["managed_object"]][9] else "",
                                Firmware.get_by_id(
                                    moss[a["managed_object"]][10])
                                if moss[a["managed_object"]][10] else "",
                                AlarmClass.get_by_id(a["alarm_class"]).name,
                                ArchivedAlarm.objects.get(
                                    id=a["_id"]).subject if subject else "",
                                "",
                                total_objects,
                                total_subscribers,
                                a.get("escalation_tt"),
                                a.get("escalation_ts"),
                                ", ".join(l for l in (
                                    loc.location(moss[a["managed_object"]][5]
                                                 ) if moss[a["managed_object"]]
                                    [5] is not None else "") if l),
                                container_lookup[a["managed_object"]].get(
                                    "text", "") if container_lookup else "",
                            ],
                            container_path,
                            segment_path,
                        ),
                        cmap,
                    )
                ]
        # Active Alarms
        if source in ["active", "both"]:
            for a in (ActiveAlarm._get_collection().with_options(
                    read_preference=ReadPreference.SECONDARY_PREFERRED).
                      aggregate([
                          {
                              "$match": match
                          },
                          {
                              "$addFields": {
                                  "duration": {
                                      "$divide": [{
                                          "$subtract": [fd, "$timestamp"]
                                      }, 1000]
                                  }
                              }
                          },
                          {
                              "$match": match_duration
                          },
                          # {"$sort": {"timestamp": 1}}
                      ])):
                dt = fd - a["timestamp"]
                duration = int(dt.total_seconds())
                total_objects = sum(ss["summary"] for ss in a["total_objects"])
                if min_objects and total_objects < min_objects:
                    continue
                total_subscribers = sum(
                    ss["summary"] for ss in a["total_subscribers"]
                    if subscribers_profile
                    and ss["profile"] in subscribers_profile)
                if min_subscribers and total_subscribers < min_subscribers:
                    continue
                if "segment_" in columns.split(
                        ",") or "container_" in columns.split(","):
                    path = ObjectPath.get_path(a["managed_object"])
                    if path:
                        segment_path = [
                            NetworkSegment.get_by_id(s).name
                            for s in path.segment_path
                            if NetworkSegment.get_by_id(s)
                        ]
                        container_path = [
                            Object.get_by_id(s).name
                            for s in path.container_path if Object.get_by_id(s)
                        ]
                    else:
                        segment_path = []
                        container_path = []
                else:
                    segment_path = []
                    container_path = []
                r += [
                    translate_row(
                        row(
                            [
                                str(a["_id"]),
                                str(a["root"]) if a.get("root") else "",
                                a["timestamp"],
                                # a["clear_timestamp"],
                                "",
                                str(duration),
                                moss[a["managed_object"]][0],
                                moss[a["managed_object"]][1],
                                mo_hostname.get(a["managed_object"], ""),
                                Profile.get_by_id(moss[a["managed_object"]][3])
                                if moss[a["managed_object"]][5] else "",
                                moss[a["managed_object"]][6],
                                Platform.get_by_id(
                                    moss[a["managed_object"]][9])
                                if moss[a["managed_object"]][9] else "",
                                Firmware.get_by_id(
                                    moss[a["managed_object"]][10])
                                if moss[a["managed_object"]][10] else "",
                                AlarmClass.get_by_id(a["alarm_class"]).name,
                                ActiveAlarm.objects.get(
                                    id=a["_id"]).subject if subject else None,
                                "Yes" if a["managed_object"] in maintenance
                                else "No",
                                total_objects,
                                total_subscribers,
                                a.get("escalation_tt"),
                                a.get("escalation_ts"),
                                ", ".join(l for l in (
                                    loc.location(moss[a["managed_object"]][5]
                                                 ) if moss[a["managed_object"]]
                                    [5] is not None else "") if l),
                                container_lookup[a["managed_object"]].get(
                                    "text", "") if container_lookup else "",
                            ],
                            container_path,
                            segment_path,
                        ),
                        cmap,
                    )
                ]

        if o_format == "csv":
            response = HttpResponse(content_type="text/csv")
            response[
                "Content-Disposition"] = 'attachment; filename="alarms.csv"'
            writer = csv.writer(response)
            writer.writerows(r)
            return response
        elif o_format == "xlsx":
            response = StringIO()
            wb = xlsxwriter.Workbook(response)
            cf1 = wb.add_format({"bottom": 1, "left": 1, "right": 1, "top": 1})
            ws = wb.add_worksheet("Alarms")
            max_column_data_length = {}
            for rn, x in enumerate(r):
                for cn, c in enumerate(x):
                    if rn and (r[0][cn] not in max_column_data_length or
                               len(str(c)) > max_column_data_length[r[0][cn]]):
                        max_column_data_length[r[0][cn]] = len(str(c))
                    ws.write(rn, cn, c, cf1)
            ws.autofilter(0, 0, rn, cn)
            ws.freeze_panes(1, 0)
            for cn, c in enumerate(r[0]):
                # Set column width
                width = get_column_width(c)
                if enable_autowidth and width < max_column_data_length[c]:
                    width = max_column_data_length[c]
                ws.set_column(cn, cn, width=width)
            wb.close()
            response.seek(0)
            response = HttpResponse(response.getvalue(),
                                    content_type="application/vnd.ms-excel")
            response[
                "Content-Disposition"] = 'attachment; filename="alarms.xlsx"'
            response.close()
            return response
コード例 #23
0
ファイル: sae.py プロジェクト: nbashev/noc
 def get_object_data(self, object_id):
     """
     Worker to resolve credentials
     """
     object_id = int(object_id)
     # Get Object's attributes
     with self.service.get_pg_connect() as connection:
         cursor = connection.cursor()
         cursor.execute(self.RUN_SQL, [object_id, object_id])
         data = cursor.fetchall()
     if not data:
         metrics["error", ("type", "object_not_found")] += 1
         raise APIError("Object is not found")
     # Build capabilities
     capabilities = ObjectCapabilities.get_capabilities(object_id)
     # Get object credentials
     (
         name,
         is_managed,
         profile,
         vendor,
         platform,
         version,
         scheme,
         address,
         port,
         user,
         password,
         super_password,
         remote_path,
         snmp_ro,
         pool_id,
         sw_image,
         auth_profile_id,
         ap_user,
         ap_password,
         ap_super_password,
         ap_snmp_ro,
         ap_snmp_rw,
         privilege_policy,
         snmp_rate_limit,
         p_privilege_policy,
         p_snmp_rate_limit,
         access_preference,
         p_access_preference,
         beef_storage_id,
         beef_path_template_id,
         attrs,
     ) = data[0]
     # Check object is managed
     if not is_managed:
         metrics["error", ("type", "object_not_managed")] += 1
         raise APIError("Object is not managed")
     if auth_profile_id:
         user = ap_user
         password = ap_password
         super_password = ap_super_password
         snmp_ro = ap_snmp_ro
         snmp_rw = ap_snmp_rw  # noqa just to be
     #
     if privilege_policy == "E":
         raise_privileges = True
     elif privilege_policy == "P":
         raise_privileges = p_privilege_policy == "E"
     else:
         raise_privileges = False
     if access_preference == "P":
         access_preference = p_access_preference
     if not snmp_rate_limit:
         snmp_rate_limit = p_snmp_rate_limit
     # Build credentials
     credentials = {
         "name": name,
         "address": address,
         "user": user,
         "password": password,
         "super_password": super_password,
         "path": remote_path,
         "raise_privileges": raise_privileges,
         "access_preference": access_preference,
         "snmp_rate_limit": snmp_rate_limit,
     }
     if snmp_ro:
         credentials["snmp_ro"] = snmp_ro
         if capabilities.get("SNMP | v2c"):
             credentials["snmp_version"] = "v2c"
         elif capabilities.get("SNMP | v1"):
             credentials["snmp_version"] = "v1"
     if scheme in CLI_PROTOCOLS:
         credentials["cli_protocol"] = PROTOCOLS[scheme]
         if port:
             credentials["cli_port"] = port
     elif scheme in HTTP_PROTOCOLS:
         credentials["http_protocol"] = PROTOCOLS[scheme]
         if port:
             credentials["http_port"] = port
     # Build version
     if vendor and platform and version:
         vendor = Vendor.get_by_id(vendor)
         version = {
             "vendor": vendor.code[0] if vendor.code else vendor.name,
             "platform": Platform.get_by_id(platform).name,
             "version": Firmware.get_by_id(version).version,
         }
         if sw_image:
             version["image"] = sw_image
         if attrs:
             version["attributes"] = attrs
     else:
         version = None
     # Beef processing
     if scheme == BEEF and beef_storage_id and beef_path_template_id:
         mo = ManagedObject.get_by_id(object_id)
         tpl = Template.get_by_id(beef_path_template_id)
         beef_path = tpl.render_subject(object=mo)
         if beef_path:
             storage = ExtStorage.get_by_id(beef_storage_id)
             credentials["beef_storage_url"] = storage.url
             credentials["beef_path"] = beef_path
     return dict(
         profile=Profile.get_by_id(profile).name,
         pool_id=pool_id,
         credentials=credentials,
         capabilities=capabilities,
         version=version,
     )
コード例 #24
0
ファイル: views.py プロジェクト: skripkar/noc
    def get_data(self, request, **kwargs):
        data = []

        value = get_db()["noc.links"].with_options(
            read_preference=ReadPreference.SECONDARY_PREFERRED).aggregate([{
                "$unwind":
                "$interfaces"
            }, {
                "$lookup": {
                    "from": "noc.interfaces",
                    "localField": "interfaces",
                    "foreignField": "_id",
                    "as": "int"
                }
            }, {
                "$group": {
                    "_id": "$int.managed_object",
                    "count": {
                        "$sum": 1
                    }
                }
            }])
        count = {0: set([]), 1: set([]), 2: set([]), 3: set([])}
        ap = AuthProfile.objects.filter(name__startswith="TG")
        for v in value:
            if v["count"] > 2:
                count[3].add(v["_id"][0])
                continue
            if not v["_id"]:
                self.logger.warning("No IDS in response query")
                continue
            count[v["count"]].add(v["_id"][0])

        for p in Pool.objects.order_by("name"):
            if p.name == "P0001":
                continue
            data += [SectionRow(name=p.name)]
            smos = set(
                ManagedObject.objects.filter(pool=p, is_managed=True).exclude(
                    profile=Profile.get_by_name(GENERIC_PROFILE)).exclude(
                        auth_profile__in=ap).values_list('id', flat=True))
            all_p = 100.0 / len(smos) if len(smos) else 1.0
            data += [("All polling", len(smos))]
            for c in count:
                if c == 3:
                    data += [
                        ("More 3", len(count[c].intersection(smos)),
                         "%.2f %%" %
                         round(len(count[c].intersection(smos)) * all_p, 2))
                    ]
                    continue
                data += [(c, len(count[c].intersection(smos)), "%.2f %%" %
                          round(len(count[c].intersection(smos)) * all_p), 2)]

            # 0 links - All discovering- summary with links
            s0 = len(smos) - sum([d[1] for d in data[-3:]])
            data.pop(-4)
            data.insert(-3, (0, s0, "%.2f %%" % round(s0 * all_p, 2)))

        return self.from_dataset(
            title=self.title,
            columns=[_("Links count"),
                     _("MO Count"),
                     _("Percent at All")],
            data=data)
コード例 #25
0
    def api_report(
        self,
        request,
        o_format,
        is_managed=None,
        administrative_domain=None,
        selector=None,
        pool=None,
        segment=None,
        avail_status=False,
        columns=None,
        ids=None,
        detail_stat=None,
        enable_autowidth=False,
    ):
        def row(row):
            def qe(v):
                if v is None:
                    return ""
                if isinstance(v, unicode):
                    return v.encode("utf-8")
                elif isinstance(v, datetime.datetime):
                    return v.strftime("%Y-%m-%d %H:%M:%S")
                elif not isinstance(v, str):
                    return str(v)
                else:
                    return v

            return [qe(x) for x in row]

        def translate_row(row, cmap):
            return [row[i] for i in cmap]

        type_columns = ["Up/10G", "Up/1G", "Up/100M", "Up/10M", "Down/-", "-"]
        cols = [
            "id", "object_name", "object_address", "object_hostname",
            "object_status", "profile_name", "object_profile", "object_vendor",
            "object_platform", "object_attr_hwversion", "object_version",
            "object_attr_bootprom", "object_serial", "object_attr_patch",
            "auth_profile", "avail", "admin_domain", "container", "segment",
            "phys_interface_count", "link_count", "last_config_ts"
            # "discovery_problem"
            # "object_tags"
            # "sorted_tags"
            # "object_caps"
            # "interface_type_count"
        ]

        header_row = [
            "ID",
            "OBJECT_NAME",
            "OBJECT_ADDRESS",
            "OBJECT_HOSTNAME",
            "OBJECT_STATUS",
            "PROFILE_NAME",
            "OBJECT_PROFILE",
            "OBJECT_VENDOR",
            "OBJECT_PLATFORM",
            "OBJECT_HWVERSION",
            "OBJECT_VERSION",
            "OBJECT_BOOTPROM",
            "OBJECT_SERIAL",
            "OBJECT_ATTR_PATCH",
            "AUTH_PROFILE",
            "AVAIL",
            "ADMIN_DOMAIN",
            "CONTAINER",
            "SEGMENT",
            "PHYS_INTERFACE_COUNT",
            "LINK_COUNT",
            "LAST_CONFIG_TS",
        ]
        # "DISCOVERY_PROBLEM"
        # "ADM_PATH
        # "DISCOVERY_PROBLEM"
        # "OBJECT_TAGS"
        # "SORTED_TAGS"
        # "OBJECT_CAPS"
        # "INTERFACE_TYPE_COUNT"

        if columns:
            cmap = []
            for c in columns.split(","):
                try:
                    cmap += [cols.index(c)]
                except ValueError:
                    continue
        else:
            cmap = list(range(len(cols)))
        r = [translate_row(header_row, cmap)]
        mos = self.get_report_object(request.user, is_managed,
                                     administrative_domain, selector, pool,
                                     segment, ids)
        columns_filter = set(columns.split(","))
        mos_id = tuple(mos.order_by("id").values_list("id", flat=True))
        mos_filter = None
        if detail_stat:
            ref = ReportModelFilter()
            ids = list(six.itervalues(ref.proccessed(detail_stat)))
            mos_filter = set(mos_id).intersection(ids[0])
            mos_id = sorted(mos_filter)
        avail = {}
        if "avail" in columns_filter:
            avail = ObjectStatus.get_statuses(mos_id)
        link_count = iter(ReportObjectLinkCount(mos_id))
        iface_count = iter(ReportObjectIfacesTypeStat(mos_id))
        if "container" in columns_filter:
            container_lookup = iter(ReportContainerData(mos_id))
        else:
            container_lookup = None
        if "object_serial" in columns_filter:
            container_serials = iter(ReportContainer(mos_id))
        else:
            container_serials = None
        if "interface_type_count" in columns_filter:
            iss = iter(ReportObjectIfacesStatusStat(mos_id))
        else:
            iss = None
        if "object_attr_patch" in columns_filter or "object_serial" in columns_filter:
            roa = iter(ReportObjectAttributes(mos_id))
        else:
            roa = None
        hn = iter(ReportObjectsHostname1(mos_id))
        rc = iter(ReportObjectConfig(mos_id))
        # ccc = iter(ReportObjectCaps(mos_id))
        if "adm_path" in columns_filter:
            ad_path = ReportAdPath()
            r[-1].extend([_("ADM_PATH1"), _("ADM_PATH1"), _("ADM_PATH1")])
        if "interface_type_count" in columns_filter:
            r[-1].extend(type_columns)
        if "object_caps" in columns_filter:
            object_caps = ReportObjectCaps(mos_id)
            caps_columns = list(six.itervalues(object_caps.ATTRS))
            ccc = iter(object_caps)
            r[-1].extend(caps_columns)
        if "object_tags" in columns_filter:
            r[-1].extend([_("OBJECT_TAGS")])
        if "sorted_tags" in columns_filter:
            tags = set()
            for s in (ManagedObject.objects.filter().exclude(
                    tags=None).values_list("tags", flat=True).distinct()):
                tags.update(set(s))
            tags_o = sorted([t for t in tags if "{" not in t])
            r[-1].extend(tags_o)
        if "discovery_problem" in columns.split(","):
            discovery_result = ReportDiscoveryResult(mos_id)
            discovery_result.safe_output = True
            discovery_result.unknown_value = ([""] *
                                              len(discovery_result.ATTRS), )
            dp_columns = discovery_result.ATTRS
            dp = iter(discovery_result)
            r[-1].extend(dp_columns)
        for (
                mo_id,
                name,
                address,
                is_managed,
                sa_profile,
                o_profile,
                auth_profile,
                ad,
                m_segment,
                vendor,
                platform,
                version,
                tags,
        ) in (mos.values_list(
                "id",
                "name",
                "address",
                "is_managed",
                "profile",
                "object_profile__name",
                "auth_profile__name",
                "administrative_domain__name",
                "segment",
                "vendor",
                "platform",
                "version",
                "tags",
        ).order_by("id").iterator()):
            if (mos_filter and mo_id not in mos_filter) or not mos_id:
                continue
            if container_serials:
                mo_serials = next(container_serials)
            else:
                mo_serials = [{}]
            if container_lookup:
                mo_continer = next(container_lookup)
            else:
                mo_continer = ("", )
            if roa:
                serial, hw_ver, boot_prom, patch = next(roa)[0]  # noqa
            else:
                serial, hw_ver, boot_prom, patch = "", "", "", ""  # noqa
            r.append(
                translate_row(
                    row([
                        mo_id,
                        name,
                        address,
                        next(hn)[0],
                        "managed" if is_managed else "unmanaged",
                        Profile.get_by_id(sa_profile),
                        o_profile,
                        Vendor.get_by_id(vendor) if vendor else "",
                        Platform.get_by_id(platform) if platform else "",
                        hw_ver,
                        Firmware.get_by_id(version) if version else "",
                        boot_prom,
                        # Serial
                        mo_serials[0].get("serial", "") or serial,
                        patch or "",
                        auth_profile,
                        _("Yes") if avail.get(mo_id, None) else _("No"),
                        ad,
                        mo_continer[0],
                        NetworkSegment.get_by_id(m_segment)
                        if m_segment else "",
                        next(iface_count)[0],
                        next(link_count)[0],
                        next(rc)[0],
                    ]),
                    cmap,
                ))
            if "adm_path" in columns_filter:
                r[-1].extend([ad] + list(ad_path[ad]))
            if "interface_type_count" in columns_filter:
                r[-1].extend(next(iss)[0])
            if "object_caps" in columns_filter:
                r[-1].extend(next(ccc)[0])
            if "object_tags" in columns_filter:
                r[-1].append(",".join(tags if tags else []))
            if "sorted_tags" in columns_filter:
                out_tags = [""] * len(tags_o)
                try:
                    if tags:
                        for m in tags:
                            out_tags[tags_o.index(m)] = m
                except ValueError:
                    logger.warning("Bad value for tag: %s", m)
                r[-1].extend(out_tags)
            if "discovery_problem" in columns_filter:
                r[-1].extend(next(dp)[0])
        filename = "mo_detail_report_%s" % datetime.datetime.now().strftime(
            "%Y%m%d")
        if o_format == "csv":
            response = HttpResponse(content_type="text/csv")
            response[
                "Content-Disposition"] = 'attachment; filename="%s.csv"' % filename
            writer = csv.writer(response,
                                dialect="excel",
                                delimiter=";",
                                quotechar='"')
            writer.writerows(r)
            return response
        elif o_format == "xlsx":
            response = StringIO()
            wb = xlsxwriter.Workbook(response)
            cf1 = wb.add_format({"bottom": 1, "left": 1, "right": 1, "top": 1})
            ws = wb.add_worksheet("Objects")
            max_column_data_length = {}
            for rn, x in enumerate(r):
                for cn, c in enumerate(x):
                    if rn and (r[0][cn] not in max_column_data_length or
                               len(str(c)) > max_column_data_length[r[0][cn]]):
                        max_column_data_length[r[0][cn]] = len(str(c))
                    ws.write(rn, cn, c, cf1)
            # for
            ws.autofilter(0, 0, rn, cn)
            ws.freeze_panes(1, 0)
            for cn, c in enumerate(r[0]):
                # Set column width
                width = get_column_width(c)
                if enable_autowidth and width < max_column_data_length[c]:
                    width = max_column_data_length[c]
                ws.set_column(cn, cn, width=width)
            wb.close()
            response.seek(0)
            response = HttpResponse(response.getvalue(),
                                    content_type="application/vnd.ms-excel")
            # response = HttpResponse(
            #     content_type="application/x-ms-excel")
            response[
                "Content-Disposition"] = 'attachment; filename="%s.xlsx"' % filename
            response.close()
            return response
コード例 #26
0
ファイル: views.py プロジェクト: gabrielat/noc
    def get_data(self,
                 request,
                 interval=1,
                 from_date=None,
                 to_date=None,
                 skip_avail=False,
                 skip_zero_avail=False,
                 filter_zero_access=False,
                 **kwargs):
        """
        a1 = self.get_availability(1)
        a7 = self.get_availability(7)
        a30 = self.get_availability(30)
        """

        if not from_date:
            from_date = datetime.datetime.now() - datetime.timedelta(
                days=interval)
        else:
            from_date = datetime.datetime.strptime(from_date, "%d.%m.%Y")

        if not to_date or from_date == to_date:
            to_date = from_date + datetime.timedelta(days=1)
        else:
            to_date = datetime.datetime.strptime(
                to_date, "%d.%m.%Y") + datetime.timedelta(days=1)

        a = self.get_availability(start_date=from_date,
                                  stop_date=to_date,
                                  skip_zero_avail=skip_zero_avail)
        rb = self.get_reboots(start_date=from_date, stop_date=to_date)
        r = [SectionRow("Report from %s to %s" % (from_date, to_date))]
        mos = ManagedObject.objects.filter(is_managed=True)

        if not request.user.is_superuser:
            mos = mos.filter(
                administrative_domain__in=UserAccess.get_domains(request.user))
        if skip_avail:
            mos = mos.filter(id__in=list(a))
        mos_id = list(mos.order_by("id").values_list("id", flat=True))
        if filter_zero_access:
            iface_p = InterfaceProfile.objects.get(name="Клиентский порт")
            match = {"profile": iface_p.id, "managed_object": {"$in": mos_id}}
            pipeline = [
                {
                    "$match": match
                },
                {
                    "$group": {
                        "_id": "$managed_object",
                        "count": {
                            "$sum": 1
                        },
                        "m": {
                            "$max": "$oper_status"
                        },
                    }
                },
                {
                    "$match": {
                        "m": False
                    }
                },
                {
                    "$project": {
                        "_id": True
                    }
                },
            ]
            # data = Interface.objects._get_collection().aggregate(pipeline,
            data = (get_db()["noc.interfaces"].with_options(
                read_preference=ReadPreference.SECONDARY_PREFERRED).aggregate(
                    pipeline))
            data = [d["_id"] for d in data]
            mos = mos.exclude(id__in=data)

        mo_hostname = ReportObjectsHostname1(sync_ids=mos_id)
        mo_hostname = mo_hostname.get_dictionary()
        for mo_id, mo_name, address, profile, ad_name in mos.values_list(
                "id", "name", "address", "profile",
                "administrative_domain__name"):
            s = [
                ad_name,
                mo_name,
                mo_hostname.get(mo_id, ""),
                address,
                Profile.get_by_id(profile).name,
                round(a.get(mo_id, (100.0, 0, 0))[0], 2),
            ]
            s.extend(a.get(mo_id, (100.0, 0, 0))[1:])
            s.append(rb[mo_id] if mo_id in rb else 0)
            r += [s]
            """
            a1.get(o.id, 100),
            a7.get(o.id, 100),
            a30.get(o.id, 100)
            """
        # print r
        return self.from_dataset(
            title=self.title,
            columns=[
                _("Adm. Domain"),
                _("Managed Object"),
                _("Hostname"),
                _("Address"),
                _("Profile"),
                # TableColumn(_("Avail"), align="right", format="percent"),
                # TableColumn(_("Total avail (sec)"), align="right", format="numeric"),
                _("Avail"),
                _("Total unavail (sec)"),
                _("Count outages"),
                _("Reboots"),
            ],
            data=r,
            enumerate=True,
        )