def connect_p2p(self, o1: Object, c1: str, o2: Object, c2: str): """ Create P2P connection o1:c1 - o2:c2 """ try: cn = o1.connect_p2p(c1, o2, c2, {}, reconnect=True) if cn: o1.log( "Connect %s -> %s:%s" % (c1, o2, c2), system="DISCOVERY", managed_object=self.object, op="CONNECT", ) o2.log( "Connect %s -> %s:%s" % (c2, o1, c1), system="DISCOVERY", managed_object=self.object, op="CONNECT", ) c_name = o2.model.get_model_connection(c2) # If internal_name use if (o2, c_name.name, o1, c1) in self.to_disconnect: # Remove if connection on system self.to_disconnect.remove((o2, c_name.name, o1, c1)) except ConnectionError as e: self.logger.error("Failed to connect: %s", e)
def update_name(self, object: Object): n = self.get_name(object, self.object) if n and n != object.name: object.name = n self.logger.info("Changing name to '%s'", n) object.save() object.log( "Change name to '%s'" % n, system="DISCOVERY", managed_object=self.object, op="CHANGE", )
def api_add_group(self, request, type, name, container=None, serial=None): if container is None: c = self.get_root() else: c = self.get_object_or_404(Object, id=container) m = self.get_object_or_404(ObjectModel, id=type) o = Object(name=name, model=m, container=c.id) 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)
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)
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
def resolve_object(self, name: str, m_c: str, t_object: Object, t_c: str, serial: str) -> Optional["Object"]: """ Resolve object type """ # Check object is already exists c, object, c_name = t_object.get_p2p_connection(t_c) if c is not None: if c_name == m_c and object.get_data("asset", "serial") == serial: # Object with same serial number exists return object else: # Serial number/connection mismatch return None # Check connection type c = t_object.model.get_model_connection(t_c) if c is None: self.logger.error("Connection violation for %s SN %s", name, serial) return None # ERROR # Transceiver formfactor tp = c.type.name.split(" | ") ff = tp[1] m = "NoName | Transceiver | Unknown %s" % ff if name != "Unknown | Transceiver | Unknown": mtype = name[24:].upper().replace("-", "") if "BASE" in mtype: speed, ot = mtype.split("BASE", 1) spd = {"100": "100M", "1000": "1G", "10G": "10G"}.get(speed) if spd: m = "NoName | Transceiver | %s | %s %s" % (spd, ff, ot) else: self.logger.error("Unknown transceiver speed: %s", speed) m = name else: m = name # Add vendor suffix when necessary if len(tp) == 3: m += " | %s" % tp[2] # if m in self.unk_model: model = self.unk_model[m] else: model = ObjectModel.objects.filter(name=m).first() self.unk_model[m] = model if not model: self.logger.error("Unknown model '%s'", m) self.register_unknown_part_no(self.get_vendor("NONAME"), m, "%s -> %s" % (name, m)) return None # Create object self.logger.info("Creating new object. model='%s', serial='%s'", m, serial) if self.object.container: container = self.object.container.id else: container = self.lost_and_found o = Object( model=model, data=[ ObjectAttr(scope="", interface="asset", attr="serial", value=serial) ], container=container, ) o.save() o.log( "Created by asset_discovery", system="DISCOVERY", managed_object=self.object, op="CREATE", ) return o
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