コード例 #1
0
 def change_object(self, object_id: str, v: Dict[str, Any]):
     self.logger.debug("Changed object: %s", v)
     # See: https://code.getnoc.com/noc/noc/merge_requests/49
     try:
         o: ObjectM = self.model.objects.get(pk=object_id)
     except self.model.DoesNotExist:
         self.logger.error("Cannot change %s:%s: Does not exists", self.name, object_id)
         return None
     if "name" in v and v["name"] != o.name:
         o.name = v["name"]
     if "model" in v and isinstance(v["model"], str):
         # Fix if model is name?
         v["model"] = ObjectModel.get_by_name(v["model"])
     if "model" in v and v["model"].name != o.model.name:
         o.model = v["model"]
     if (not o.container and v.get("container")) or (
         v.get("container") and v["container"] != str(o.container.id)
     ):
         o.container = v["container"]
     if "data" not in v or not v["data"]:
         # reset only RemoteSystem Scope
         # o.data = []
         for item in o.data:
             if item.scope == self.system.name:
                 o.reset_data(interface=item.interface, key=item.attr, scope=self.system.name)
     elif v["data"]:
         self.merge_data(o, v["data"])
     o.save()
     return o
コード例 #2
0
ファイル: views.py プロジェクト: skripkar/noc
 def api_add_group(self, request, type, name, container=None, serial=None):
     if is_objectid(container):
         c = Object.get_by_id(container)
         if not c:
             return self.response_not_found()
         c = c.id
     elif container:
         return self.response_bad_request()
     m = ObjectModel.get_by_id(type)
     if not m:
         return self.response_not_found()
     o = Object(name=name, model=m, container=c)
     if serial and m.get_data("asset", "part_no0"):
         o.set_data("asset", "serial", serial)
     o.save()
     o.log("Created", user=request.user.username, system="WEB", op="CREATE")
     return str(o.id)
コード例 #3
0
 def get_data(self, **kwargs):
     self.model_name = {}  # oid -> name
     data = list(Object._get_collection().aggregate([{
         "$group": {
             "_id": "$model",
             "total": {
                 "$sum": 1
             }
         }
     }]))
     oms = [x["_id"] for x in data if x["_id"]]
     c = ObjectModel._get_collection()
     om_names = {}
     while oms:
         chunk, oms = oms[:500], oms[500:]
         om_names.update({
             x["_id"]: x["name"]
             for x in c.find({"_id": {
                 "$in": chunk
             }}, {
                 "_id": 1,
                 "name": 1
             })
         })
     data = sorted(
         ([om_names[x["_id"]], x["total"]]
          for x in data if x["_id"] in om_names),
         key=lambda x: -x[1],
     )
     return self.from_dataset(
         title=self.title,
         columns=[
             "Model",
             TableColumn("Count",
                         format="numeric",
                         align="right",
                         total="sum")
         ],
         data=data,
         enumerate=True,
     )
コード例 #4
0
 def api_connect(
     self,
     request,
     object,
     name,
     remote_object,
     remote_name,
     cable: Optional[str] = None,
     reconnect=False,
 ):
     lo: Object = self.get_object_or_404(Object, id=object)
     ro: Object = self.get_object_or_404(Object, id=remote_object)
     cable_o: Optional[Object] = None
     if cable:
         cable = ObjectModel.get_by_name(cable)
         cable_o = Object(
             name="Wire %s:%s <-> %s:%s" %
             (lo.name, name, ro.name, remote_name),
             model=cable,
             container=lo.container.id,
         )
         cable_o.save()
     print(lo, ro, cable_o)
     try:
         if cable_o:
             c1, c2 = cable_o.model.connections[:2]
             self.logger.debug("Wired connect c1:c2", c1, c2)
             lo.connect_p2p(name, cable_o, c1.name, {}, reconnect=reconnect)
             ro.connect_p2p(remote_name,
                            cable_o,
                            c2.name, {},
                            reconnect=reconnect)
             lo.save()
             ro.save()
         else:
             lo.connect_p2p(name, ro, remote_name, {}, reconnect=reconnect)
     except ConnectionError as e:
         self.logger.warning("Connection Error: %s", str(e))
         return self.render_json({"status": False, "text": str(e)})
     return True
コード例 #5
0
 def submit(
     self,
     type: str,
     part_no: List[str],
     number: Optional[str] = None,
     builtin: bool = False,
     vendor: Optional[str] = None,
     revision: Optional[str] = None,
     serial: Optional[str] = None,
     mfg_date: Optional[str] = None,
     description: Optional[str] = None,
 ):
     # Check the vendor and the serial are sane
     # OEM transceivers return binary trash often
     if vendor:
         # Possible dead code
         try:
             vendor.encode("utf-8")
         except UnicodeDecodeError:
             self.logger.info("Trash submited as vendor id: %s",
                              vendor.encode("hex"))
             return
     if serial:
         # Possible dead code
         try:
             serial.encode("utf-8")
         except UnicodeDecodeError:
             self.logger.info("Trash submited as serial: %s",
                              serial.encode("hex"))
             return
     #
     is_unknown_xcvr = not builtin and part_no[0].startswith(
         "Unknown | Transceiver | ")
     if not type and is_unknown_xcvr:
         type = "XCVR"
     # Skip builtin modules
     if builtin:
         # Adjust context anyway
         self.prepare_context(type, number)
         return  # Builtin must aways have type set
     #
     if is_unknown_xcvr:
         self.logger.info("%s S/N %s should be resolved later", part_no[0],
                          serial)
         self.prepare_context(type, number)
         self.objects += [("XCVR", part_no[0], self.ctx.copy(), serial)]
         return
     # Cache description
     if description:
         for p in part_no:
             if p not in self.pn_description:
                 self.pn_description[p] = description
     # Find vendor
     vnd = self.get_vendor(vendor)
     if not vnd:
         # Try to resolve via model map
         m = self.get_model_map(vendor, part_no, serial)
         if not m:
             self.logger.error("Unknown vendor '%s' for S/N %s (%s)",
                               vendor, serial, description)
             return
     else:
         # Find model
         m = ObjectModel.get_model(vnd, part_no)
         if not m:
             # Try to resolve via model map
             m = self.get_model_map(vendor, part_no, serial)
             if not m:
                 self.logger.info(
                     "Unknown model: vendor=%s, part_no=%s (%s). "
                     "Skipping",
                     vnd.name,
                     part_no,
                     description,
                 )
                 self.register_unknown_part_no(vnd, part_no, description)
                 return
     # Sanitize serial number against the model
     serial = self.clean_serial(m, number, serial)
     #
     if m.cr_context and type != m.cr_context:
         # Override type with object mode's one
         self.logger.info("Model changes type to '%s'", m.cr_context)
         type = m.cr_context
     if not type:
         self.logger.info(
             "Cannot resolve type for: vendor=%s, part_no=%s (%s). "
             "Skipping",
             vnd.name,
             description,
             part_no,
         )
         return
     self.prepare_context(type, number)
     # Get connection rule
     if not self.rule and m.connection_rule:
         self.set_rule(m.connection_rule)
         # Set initial context
         if type in self.rule_context:
             scope = self.rule_context[type][0]
             if scope:
                 self.set_context(scope, number)
     # Find existing object or create new
     o: Optional["Object"] = Object.objects.filter(model=m.id,
                                                   data__match={
                                                       "interface": "asset",
                                                       "attr": "serial",
                                                       "value": serial
                                                   }).first()
     if not o:
         # Create new object
         self.logger.info("Creating new object. model='%s', serial='%s'",
                          m.name, serial)
         data = [
             ObjectAttr(scope="",
                        interface="asset",
                        attr="serial",
                        value=serial)
         ]
         if revision:
             data += [
                 ObjectAttr(scope="",
                            interface="asset",
                            attr="revision",
                            value=revision)
             ]
         if mfg_date:
             data += [
                 ObjectAttr(scope="",
                            interface="asset",
                            attr="mfg_date",
                            value=mfg_date)
             ]
         if self.object.container:
             container = self.object.container.id
         else:
             container = self.lost_and_found
         o = Object(model=m, data=data, container=container)
         o.save()
         o.log(
             "Created by asset_discovery",
             system="DISCOVERY",
             managed_object=self.object,
             op="CREATE",
         )
     else:
         # Add all connection to disconnect list
         self.to_disconnect.update(
             set((o, c[0], c[1], c[2]) for c in o.iter_inner_connections()))
     # Check revision
     if o.get_data("asset", "revision") != revision:
         # Update revision
         self.logger.info(
             "Object revision changed [%s %s] %s -> %s",
             m.name,
             o.id,
             o.get_data("asset", "revision"),
             revision,
         )
         o.set_data("asset", "revision", revision)
         o.save()
         o.log(
             "Object revision changed: %s -> %s" %
             (o.get_data("asset", "revision"), revision),
             system="DISCOVERY",
             managed_object=self.object,
             op="CHANGE",
         )
     # Check manufacturing date
     if mfg_date and o.get_data("asset", "revision") != revision:
         # Update revision
         self.logger.info(
             "Object manufacturing date changed [%s %s] %s -> %s",
             m.name,
             o.id,
             o.get_data("asset", "mfg_date"),
             mfg_date,
         )
         o.set_data("asset", "mfg_date", mfg_date)
         o.save()
         o.log(
             "Object manufacturing date: %s -> %s" %
             (o.get_data("asset", "mfg_date"), mfg_date),
             system="DISCOVERY",
             managed_object=self.object,
             op="CHANGE",
         )
     # Check management
     if o.get_data("management", "managed"):
         if o.get_data("management", "managed_object") != self.object.id:
             self.logger.info("Changing object management to '%s'",
                              self.object.name)
             o.set_data("management", "managed_object", self.object.id)
             o.save()
             o.log(
                 "Management granted",
                 system="DISCOVERY",
                 managed_object=self.object,
                 op="CHANGE",
             )
         self.update_name(o)
         if o.id in self.managed:
             self.managed.remove(o.id)
     self.objects += [(type, o, self.ctx.copy(), serial)]
     # Collect stack members
     if number and o.get_data("stack", "stackable"):
         self.stack_member[o] = number
コード例 #6
0
ファイル: views.py プロジェクト: skripkar/noc
    def api_node(self, request):
        children = []
        if request.GET and "node" in request.GET:
            container = request.GET["node"]
            if is_objectid(container):
                container = Object.get_by_id(container)
                if not container:
                    return self.response_not_found()
                children = [
                    (o.name, o)
                    for o in Object.objects.filter(container=container.id)
                ]
                # Collect inner connections
                children += [
                    (name, o)
                    for name, o, _ in container.get_inner_connections()
                ]
            elif container == "root":
                cmodels = [
                    d["_id"] for d in ObjectModel._get_collection().find(
                        {"data.container.container": True}, {"_id": 1})
                ]
                children = [(o.name, o)
                            for o in Object.objects.filter(__raw__={
                                "container": None,
                                "model": {
                                    "$in": cmodels
                                }
                            })]

            else:
                return self.response_bad_request()
        r = []
        # Build node interface
        for name, o in children:
            m_plugins = o.model.plugins or []
            disabled_plugins = set(p[1:] for p in m_plugins
                                   if p.startswith("-"))
            n = {
                "id": str(o.id),
                "name": name,
                "plugins": [],
                "can_add": bool(o.get_data("container", "container")),
                "can_delete": str(o.model.uuid) not in self.UNDELETABLE
            }
            if (o.get_data("container", "container")
                    or o.has_inner_connections()):
                # n["expanded"] = Object.objects.filter(container=o.id).count() == 1
                n["expanded"] = False
            else:
                n["leaf"] = True
            if o.get_data("rack", "units"):
                n["plugins"] += [self.get_plugin_data("rack")]
            if o.model.connections:
                n["plugins"] += [self.get_plugin_data("inventory")]
            if o.get_data("geopoint", "layer"):
                n["plugins"] += [self.get_plugin_data("map")]
            if o.get_data("management", "managed_object"):
                n["plugins"] += [self.get_plugin_data("managedobject")]
            if o.get_data("contacts", "has_contacts"):
                n["plugins"] += [self.get_plugin_data("contacts")]
            # Append model's plugins
            for p in m_plugins:
                if not p.startswith("-"):
                    n["plugins"] += [self.get_plugin_data(p)]
            n["plugins"] += [
                self.get_plugin_data("data"),
                self.get_plugin_data("comment"),
                self.get_plugin_data("file"),
                self.get_plugin_data("log")
            ]
            # Process disabled plugins
            n["plugins"] = [
                p for p in n["plugins"] if p["name"] not in disabled_plugins
            ]
            r += [n]
        return r
コード例 #7
0
 def submit(self,
            type,
            part_no,
            number=None,
            builtin=False,
            vendor=None,
            revision=None,
            serial=None,
            description=None):
     # Check the vendor and the serial are sane
     # OEM transceivers return binary trash often
     if vendor:
         try:
             vendor.encode("utf-8")
         except UnicodeDecodeError:
             self.info("Trash submited as vendor id: %s" %
                       vendor.encode("hex"))
             return
     if serial:
         try:
             serial.encode("utf-8")
         except UnicodeDecodeError:
             self.info("Trash submited as serial: %s" %
                       serial.encode("hex"))
             return
     #
     is_unknown_xcvr = (not builtin and
                        part_no[0].startswith("Unknown | Transceiver | "))
     if not type and is_unknown_xcvr:
         type = "XCVR"
     # Skip builtin modules
     if builtin:
         # Adjust context anyway
         self.prepare_context(type, number)
         return  # Builtin must aways have type set
     #
     if is_unknown_xcvr:
         self.debug("%s S/N %s should be resolved later" %
                    (part_no[0], serial))
         self.prepare_context(type, number)
         self.objects += [("XCVR", part_no[0], self.ctx.copy(), serial)]
         return
     # Cache description
     if description:
         for p in part_no:
             if p not in self.pn_description:
                 self.pn_description[p] = description
     # Find vendor
     vnd = self.get_vendor(vendor)
     if not vnd:
         # Try to resolve via model map
         m = self.get_model_map(vendor, part_no, serial)
         if not m:
             self.error("Unknown vendor '%s' for S/N %s (%s)" %
                        (vendor, serial, description))
             return
     else:
         # Find model
         m = ObjectModel.get_model(vnd, part_no)
         if not m:
             # Try to resolve via model map
             m = self.get_model_map(vendor, part_no, serial)
             if not m:
                 self.debug(
                     "Unknown model: vendor=%s, part_no=%s (%s). Skipping" %
                     (vnd.name, description, part_no))
                 self.register_unknown_part_no(vnd, part_no, description)
                 return
     if m.cr_context and type != m.cr_context:
         # Override type with object mode's one
         self.debug("Model changes type to '%s'" % m.cr_context)
         type = m.cr_context
     if not type:
         self.debug(
             "Cannot resolve type for: vendor=%s, part_no=%s (%s). Skipping"
             % (vnd.name, description, part_no))
         return
     self.prepare_context(type, number)
     # Get connection rule
     if not self.rule and m.connection_rule:
         self.set_rule(m.connection_rule)
         # Set initial context
         if type in self.rule_context:
             scope = self.rule_context[type][0]
             if scope:
                 self.set_context(scope, number)
     #
     if not serial or serial == "None":
         serial = self.generate_serial(m, number)
         self.info("Generating virtual serial: %s" % serial)
     # Find existing object or create new
     o = Object.objects.filter(model=m.id,
                               data__asset__serial=serial).first()
     if not o:
         # Create new object
         self.info("Creating new object. model='%s', serial='%s'" %
                   (m.name, serial))
         data = {"asset": {"serial": serial}}
         if revision:
             data["asset"]["revision"] = revision
         o = Object(model=m, data=data, container=self.lost_and_found)
         o.save()
         o.log("Created by asset_discovery",
               system="DISCOVERY",
               managed_object=self.object,
               op="CREATE")
     # Check revision
     if o.get_data("asset", "revision") != revision:
         # Update revision
         self.info(
             "Object revision changed [%s %s] %s -> %s" %
             (m.name, o.id, o.get_data("asset", "revision"), revision))
         o.set_data("asset", "revision", revision)
         o.save()
         o.log("Object revision changed: %s -> %s" %
               (o.get_data("asset", "revision"), revision),
               system="DISCOVERY",
               managed_object=self.object,
               op="CHANGE")
     # Check management
     if o.get_data("management", "managed"):
         if o.get_data("management", "managed_object") != self.object.id:
             self.info("Changing object management to '%s'" %
                       self.object.name)
             o.set_data("management", "managed_object", self.object.id)
             o.save()
             o.log("Management granted",
                   system="DISCOVERY",
                   managed_object=self.object,
                   op="CHANGE")
         self.update_name(o)
         if o.id in self.managed:
             self.managed.remove(o.id)
     self.objects += [(type, o, self.ctx.copy(), serial)]
     # Collect stack members
     if number and o.get_data("stack", "stackable"):
         self.stack_member[o] = number
コード例 #8
0
 def api_get_crossing_proposals(
     self,
     request,
     o1,
     o2=None,
     left_filter: Optional[str] = None,
     right_filter: Optional[str] = None,
     cable_filter: Optional[str] = None,
 ):
     """
     API for connnection form.
     1) If cable_filter set, checked connection capable with cable.
     2) If left_filter set, check renmote object
     :param request:
     :param o1:
     :param o2:
     :param left_filter:
     :param right_filter:
     :param cable_filter:
     :return:
     """
     self.logger.info(
         "Crossing proposals: %s:%s, %s:%s. Cable: %s",
         o1,
         left_filter,
         o2,
         right_filter,
         cable_filter,
     )
     lo: Object = self.get_object_or_404(Object, id=o1)
     ro: Optional[Object] = None
     if o2:
         ro = self.get_object_or_404(Object, id=o2)
     lcs: List[Dict[str, Any]] = []
     cable: Optional[ObjectModel] = None
     # Getting cable
     cables = ObjectModel.objects.filter(data__length__length__gte=0)
     if cable_filter:
         cable = ObjectModel.get_by_name(cable_filter)
     for c in lo.model.connections:
         valid, disable_reason = True, ""
         if cable_filter:
             # If select cable_filter - check every connection to cable
             cable_connections = [
                 c for c in lo.model.get_connection_proposals(c.name)
                 if c[0] == cable.id
             ]
             valid = bool(cable_connections)
         elif ro and right_filter:
             rc = ro.model.get_model_connection(right_filter)
             if not rc:
                 raise
             valid, disable_reason = lo.model.check_connection(c, rc)
         elif ro:
             valid = bool([
                 c for c in lo.model.get_connection_proposals(c.name)
                 if c[0] == ro.model.id
             ])
         oc, oo, _ = lo.get_p2p_connection(c.name)
         lcs += [{
             "name": c.name,
             "type": str(c.type.id),
             "type__label": c.type.name,
             "gender": c.gender,
             "direction": c.direction,
             "protocols": c.protocols,
             "free": not bool(oc),
             "valid": valid,
             "disable_reason": disable_reason,
         }]
     rcs: List[Dict[str, Any]] = []
     if ro:
         for c in ro.model.connections:
             valid, disable_reason = True, ""
             if cable_filter:
                 cable_connections = [
                     c for c in ro.model.get_connection_proposals(c.name)
                     if c[0] == cable.id
                 ]
                 valid = bool(cable_connections)
             elif left_filter:
                 lc = lo.model.get_model_connection(left_filter)
                 if not lc:
                     raise
                 valid, disable_reason = lo.model.check_connection(c, lc)
             else:
                 valid = bool([
                     c for c in ro.model.get_connection_proposals(c.name)
                     if c[0] == lo.model.id
                 ])
             oc, oo, _ = ro.get_p2p_connection(c.name)
             rcs += [{
                 "name": c.name,
                 "type": str(c.type.id),
                 "type__label": c.type.name,
                 "gender": c.gender,
                 "direction": c.direction,
                 "protocols": c.protocols,
                 "free": not bool(oc),
                 "valid": valid,
                 "disable_reason": disable_reason,
             }]
     # Forming cable
     return {
         "left": {
             "connections": lcs
         },
         "right": {
             "connections": rcs
         },
         "cable": [{
             "name": c.name,
             "available": True
         } for c in cables],
         "valid": lcs and rcs and left_filter and right_filter,
     }
コード例 #9
0
def clean_model(name):
    r = ObjectModel.get_by_name(name)
    if not r:
        raise ValueError(f"Model {name} not found")
    return r