示例#1
0
    def _get_asset(o: Object):
        def get_asset_data(data):
            rd = {}
            for d in data:
                if d.interface not in rd:
                    rd[d.interface] = {}
                rd[d.interface][d.attr] = d.value
            return rd

        rev = o.get_data("asset", "revision")
        if rev == "None":
            rev = ""
        r = {
            "id": str(o.id),
            "model": {
                "id": str(o.model.id),
                "name": str(o.model.name),
                "vendor": {"id": str(o.model.vendor.id), "name": str(o.model.vendor.name)},
                "labels": [str(t) for t in o.model.labels or []],
                # Alias
                "tags": [str(t) for t in o.model.labels or []],
            },
            "serial": o.get_data("asset", "serial") or "",
            "revision": rev,
            "data": get_asset_data(o.data),
            "slots": [],
        }
        if_map = {c.name: c.interface_name for c in o.connections if c.interface_name}
        for n in o.model.connections:
            if n.direction == "i":
                c, r_object, _ = o.get_p2p_connection(n.name)
                r["slots"] += [
                    {
                        "name": n.name,
                        "direction": n.direction,
                        "protocols": [str(p) for p in n.protocols],
                    }
                ]
                if c:
                    r["slots"][-1]["asset"] = ManagedObjectDataStream._get_asset(r_object)
            elif n.direction == "s":
                r["slots"] += [
                    {
                        "name": n.name,
                        "direction": n.direction,
                        "protocols": [str(p) for p in n.protocols],
                    }
                ]
            if n.name in if_map:
                r["slots"][-1]["interface"] = if_map[n.name]
        return r
示例#2
0
 def connect_twinax(self, o1: Object, c1: str, o2: Object, c2: str):
     """
     Connect twinax object o1 and virtual connection c1 to o2:c2
     """
     free_connections = []
     # Resolve virtual name c1 to real connection
     r_names = [
         o1.get_data("twinax", "connection%d" % i) for i in range(1, 3)
     ]
     # Check connection is already exists
     for n in r_names:
         cn, o, c = o1.get_p2p_connection(n)
         if not cn:
             free_connections += [n]
             continue
         if o.id == o2.id and c == c2:
             # Already connected
             return
     # Check twinax has free connection
     if not free_connections:
         self.logger.error("Twinax has no free connections")
         return
     # Connect first free to o2:c2
     c = free_connections[0]
     self.logger.info("Using twinax connection '%s' instead of '%s'", c, c1)
     self.connect_p2p(o1, c, o2, c2)
示例#3
0
 def get_name(obj: Object, managed_object: Optional[Any] = None) -> str:
     """
     Generate discovered object's name
     """
     name = None
     if managed_object:
         name = managed_object.name
         sm = obj.get_data("stack", "member")
         if sm is not None:
             # Stack member
             name += "#%s" % sm
     return name
示例#4
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
示例#5
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