def walk(self, oid: OID, check_plugin_name: Optional[CheckPluginNameStr] = None, table_base_oid: Optional[OID] = None, context_name: Optional[SNMPContextName] = None) -> SNMPRowInfo: if oid.startswith("."): oid = oid[1:] if oid.endswith(".*"): oid_prefix = oid[:-2] dot_star = True else: oid_prefix = oid dot_star = False if snmp_cache.host_cache_contains(self.config.hostname): lines = snmp_cache.host_cache_get(self.config.hostname) else: path = cmk.utils.paths.snmpwalks_dir + "/" + self.config.hostname console.vverbose(" Loading %s from %s\n" % (oid, path)) try: lines = open(path).readlines() except IOError: raise MKSNMPError("No snmpwalk file %s" % path) snmp_cache.host_cache_set(self.config.hostname, lines) begin = 0 end = len(lines) hit = None while end - begin > 0: current = (begin + end) // 2 # skip over values including newlines to the next oid while not lines[current].startswith(".") and current < end: current += 1 parts = lines[current].split(None, 1) comp = parts[0] hit = StoredWalkSNMPBackend._compare_oids(oid_prefix, comp) if hit == 0: break if hit == 1: # we are too low begin = current + 1 else: end = current if hit != 0: return [] # not found rowinfo = StoredWalkSNMPBackend._collect_until(oid, oid_prefix, lines, current, -1) rowinfo.reverse() rowinfo += StoredWalkSNMPBackend._collect_until( oid, oid_prefix, lines, current + 1, 1) if dot_star: return [rowinfo[0]] return rowinfo
def walk( self, oid: OID, section_name: Optional[SectionName] = None, table_base_oid: Optional[OID] = None, context_name: Optional[SNMPContextName] = None, ) -> SNMPRowInfo: if oid.startswith("."): oid = oid[1:] if oid.endswith(".*"): oid_prefix = oid[:-2] dot_star = True else: oid_prefix = oid dot_star = False host_cache = snmp_cache.host_cache() try: lines = host_cache[self.config.hostname] except KeyError: path = cmk.utils.paths.snmpwalks_dir + "/" + self.config.hostname console.vverbose(" Loading %s from %s\n" % (oid, path)) try: lines = StoredWalkSNMPBackend.read_walk_data(path) except IOError: raise MKSNMPError("No snmpwalk file %s" % path) host_cache[self.config.hostname] = lines begin = 0 end = len(lines) hit = None while end - begin > 0: current = (begin + end) // 2 parts = lines[current].split(None, 1) comp = parts[0] hit = StoredWalkSNMPBackend._compare_oids(oid_prefix, comp) if hit == 0: break if hit == 1: # we are too low begin = current + 1 else: end = current if hit != 0: return [] # not found rowinfo = StoredWalkSNMPBackend._collect_until(oid, oid_prefix, lines, current, -1) rowinfo.reverse() rowinfo += StoredWalkSNMPBackend._collect_until( oid, oid_prefix, lines, current + 1, 1) if dot_star: return [rowinfo[0]] return rowinfo
def get(self, oid: OID, context_name: Optional[SNMPContextName] = None) -> Optional[SNMPRawValue]: if oid.endswith(".*"): oid_prefix = oid[:-2] commandtype = "getnext" else: oid_prefix = oid commandtype = "get" protospec = self._snmp_proto_spec() ipaddress = self.config.ipaddress if self.config.is_ipv6_primary: ipaddress = "[" + ipaddress + "]" portspec = self._snmp_port_spec() command = ( self._snmp_base_command(commandtype, context_name) + ["-On", "-OQ", "-Oe", "-Ot", "%s%s%s" % (protospec, ipaddress, portspec), oid_prefix]) console.vverbose("Running '%s'\n" % subprocess.list2cmdline(command)) snmp_process = subprocess.Popen( command, close_fds=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding="utf-8", ) exitstatus = snmp_process.wait() if snmp_process.stderr is None or snmp_process.stdout is None: raise TypeError() if exitstatus: console.verbose(tty.red + tty.bold + "ERROR: " + tty.normal + "SNMP error\n") console.verbose(snmp_process.stderr.read() + "\n") return None line = snmp_process.stdout.readline().strip() if not line: console.verbose("Error in response to snmpget.\n") return None parts = line.split("=", 1) if len(parts) != 2: return None item = parts[0] value = parts[1].strip() console.vverbose("SNMP answer: ==> [%s]\n" % value) if value.startswith('No more variables') or \ value.startswith('End of MIB') or \ value.startswith('No Such Object available') or \ value.startswith('No Such Instance currently exists'): return None # In case of .*, check if prefix is the one we are looking for if commandtype == "getnext" and not item.startswith(oid_prefix + "."): return None return strip_snmp_value(value)
def get(self, oid: OID, context_name: Optional[SNMPContextName] = None) -> Optional[SNMPRawValue]: walk = self.walk(oid) # get_stored_snmpwalk returns all oids that start with oid but here # we need an exact match if len(walk) == 1 and oid == walk[0][0]: return walk[0][1] if oid.endswith(".*") and len(walk) > 0: return walk[0][1] return None
def _to_bin_string(oid: OID) -> Tuple[int, ...]: try: return tuple(map(int, oid.strip(".").split("."))) except Exception: raise MKGeneralException("Invalid OID %s" % oid)