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_create(self, request, model=None, name=None, srid=None, x=None, y=None): # Find suitable container to_pop = model.name == "Ducts | Cable Entry" p = (x, y, srid) if to_pop: # Cable entries are attached to nearest PoP pop_layers = list(Layer.objects.filter(code__startswith="pop_")) np, npd = map.find_nearest_d(p, pop_layers) else: # Or to the objects on same layer layer = Layer.objects.get(code=model.get_data("geopoint", "layer")) np, npd = map.find_nearest_d(p, layer) # Check nearest area layer = Layer.objects.get(code="areas") ap, apd = map.find_nearest_d(p, layer) if ap and (not np or apd < npd): np, npd = ap, apd # Check nearest city layer = Layer.objects.get(code="cities") ap, apd = map.find_nearest_d(p, layer) if ap and (not np or apd < npd): np, npd = ap, apd # Get best nearest container if to_pop and np.layer.code.startswith("pop_"): container = np.id else: container = np.container # Create object o = Object( name=name, model=model, container=container, data=[ ObjectAttr(scope="", interface="geopoint", attr="srid", value=srid), ObjectAttr(scope="", interface="geopoint", attr="x", value=x), ObjectAttr(scope="", interface="geopoint", attr="y", value=y), ], ) o.save() return {"id": 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 fix(): # check "Lost&Found" container logging.info("Checking Lost&Found object") lostfound_model = ObjectModel.objects.get( uuid="b0fae773-b214-4edf-be35-3468b53b03f2") lf = Object.objects.filter(model=lostfound_model.id).count() if lf == 0: # Create missed "Lost&Found" logging.info(" ... creating missed Lost&Found") Object(model=lostfound_model.id, name="Global Lost&Found", container=None).save() elif lf == 1: logging.info("Global Lost&Found object found") # OK # check container if Object.objects.get(name="Global Lost&Found").container: logging.info( "Global Lost&Found object not valid container - fix") # fix o = Object.objects.get(name="Global Lost&Found") o.container = None o.save() else: logging.info("Global Lost&Found object container is valid") else: logging.info("Global Lost&Found object found greater that one!!!!") # merge Lost&found lfs = Object.objects.filter(model=lostfound_model.id).order_by("id") l0 = lfs[0] for l in lfs[1:]: for ls in Object.objects.filter(container=l.id): logging.info(" ... moving %s to primary Lost&Found", unicode(ls)) ls.container = l0 ls.save() logging.info(" ... removing duplicated Lost&Found %s", l) l.delete() if Object.objects.get(name="Global Lost&Found").container: logging.info( "Global Lost&Found object not valid container - fix") # fix o = Object.objects.get(name="Global Lost&Found") o.container = None o.save() else: logging.info("Global Lost&Found object container is valid")
def get_container(self, path): if path not in self.containers: pp = path.split(" | ") # Find object c = Object.get_by_path(pp, hints=self.mappings) if c: self.containers[path] = c else: self.logger.debug("Create container: %s", path) if " | " in path: parent = self.get_container(path.rsplit(" | ", 1)[0]) else: parent = None self.containers[path] = Object( name=pp[-1], container=parent.id if parent else None, model=self.get_model(self.CONTAINER_MODEL)) self.containers[path].save() return self.containers[path]
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
def fix_inv_lost_and_found(self): from noc.inv.models.object import Object from noc.inv.models.objectmodel import ObjectModel lf_model = ObjectModel.objects.get(uuid="b0fae773-b214-4edf-be35-3468b53b03f2") self.info("Checking inventory Lost&Found") rc = Object.objects.filter(model=lf_model.id).count() if rc == 0: # Create missed l&f self.info(" ... creating missed Lost&Found") Object(model=lf_model, name="Global Lost&Found").save() elif rc == 1: return # OK else: # Merge lost&founds lfs = Object.objects.filter(model=lf_model.id).order_by("id") r0 = lfs[0] for r in lfs[1:]: for o in Object.objects.filter(container=r.id): self.info(" ... moving %s to primary Lost&Found", unicode(o)) o.container = r0.id o.save() self.info(" ... removing duplicated lost&found %s", r.uuid) r.delete()
def fix_inv_root(self): from noc.inv.models.object import Object from noc.inv.models.objectmodel import ObjectModel root_model = ObjectModel.objects.get(uuid="0f1b7c90-c611-4046-9a83-b120377eb6e0") self.info("Checking inventory Root") rc = Object.objects.filter(model=root_model.id).count() if rc == 0: # Create missed root self.info(" ... creating missed root") Object(model=root_model, name="Root").save() elif rc == 1: return # OK else: # Merge roots roots = Object.objects.filter(model=root_model.id).order_by("id") r0 = roots[0] for r in roots[1:]: for o in Object.objects.filter(container=r.id): self.info(" ... moving %s to primary root", unicode(o)) o.container = r0.id o.save() self.info(" ... removing duplicated root %s", r) r.delete()
def api_create_ducts(self, request, id, ducts=None): o = self.app.get_object_or_404(Object, id=id) conns = {} # target -> conneciton for c, t, _ in o.get_genderless_connections("ducts"): conns[t] = c conduits = defaultdict(list) # target, conduits for c, t, _ in o.get_genderless_connections("conduits"): for cc, tt, _ in t.get_genderless_connections("conduits"): if tt.id != o.id: conduits[tt] += [t] left = set(conns) for cd in ducts: target = cd["target"] if target not in left: # New record o.connect_genderless( "ducts", target, "ducts", data={"project_distance": cd["project_distance"]}, type="ducts") else: c = conns[target] # Updated if cd["project_distance"] != c.data.get("project_distance"): # Updated c.data["project_distance"] = cd["project_distance"] c.type = "ducts" c.save() left.remove(target) left_conduits = set(conduits[target]) for cc in cd["conduits"]: if "id" not in cc or cc["id"] not in left_conduits: # Create new conduit conduit = Object(name=str(cc["n"]), model=self.conduits_model) conduit.save() # Connect to both manholes o.connect_genderless( "conduits", conduit, "conduits", data={ # Conduit position "plan": { "x": cc["x"], "y": cc["y"] } }, type="conduits") target.connect_genderless( "conduits", conduit, "conduits", data={ # @todo: Mirror position # Conduit position "plan": { "x": cc["x"], "y": cc["y"] } }, type="conduits") else: # Change. conduit = cc["id"] for ccc, ro, _ in conduit.get_genderless_connections( "conduits"): odata = ccc.data.copy() ccc.data["plan"]["x"] = cc["x"] ccc.data["plan"]["y"] = cc["y"] if ccc.data != odata: ccc.save() if "id" in cc: left_conduits.remove(cc["id"]) for t in left_conduits: cc = left_conduits[t] print "DEL", cc # Deleted for x in left: for c, remote, _ in conns[x].get_genderless_connecitons( "conduits"): remote.delete() conns[x].delete() return {"status": True}
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