def execute_cli(self): r = [] # Fallback to CLI lldp = self.cli("show lldp neighbors") for link in parse_table( lldp, allow_wrap=True, line_wrapper=None, row_wrapper=lambda x: x.strip(), footer="\r\n\r\n", ): if link[0] == "": continue local_interface = link[0] remote_chassis_id = link[1] remote_port = link[2] remote_system_name = link[3] # Build neighbor data # Get capability cap = lldp_caps_to_bits( link[4].strip().split(","), { "O": LLDP_CAP_OTHER, "r": LLDP_CAP_REPEATER, "B": LLDP_CAP_BRIDGE, "W": LLDP_CAP_WLAN_ACCESS_POINT, "R": LLDP_CAP_ROUTER, "T": LLDP_CAP_TELEPHONE, "D": LLDP_CAP_DOCSIS_CABLE_DEVICE, "S": LLDP_CAP_STATION_ONLY, # S-VLAN "C": 256, # C-VLAN "H": 512, # Host "TP": 1024, # Two Ports MAC Relay }, ) if is_ipv4(remote_chassis_id) or is_ipv6(remote_chassis_id): remote_chassis_id_subtype = LLDP_CHASSIS_SUBTYPE_NETWORK_ADDRESS elif is_mac(remote_chassis_id): remote_chassis_id = MACAddressParameter().clean( remote_chassis_id) remote_chassis_id_subtype = LLDP_CHASSIS_SUBTYPE_MAC else: remote_chassis_id_subtype = LLDP_CHASSIS_SUBTYPE_LOCAL # Get remote port subtype remote_port_subtype = LLDP_PORT_SUBTYPE_ALIAS if is_ipv4(remote_port): # Actually networkAddress(4) remote_port_subtype = LLDP_PORT_SUBTYPE_NETWORK_ADDRESS elif is_mac(remote_port): # Actually macAddress(3) # Convert MAC to common form remote_port = MACAddressParameter().clean(remote_port) remote_port_subtype = LLDP_PORT_SUBTYPE_MAC elif is_int(remote_port): # Actually local(7) remote_port_subtype = LLDP_PORT_SUBTYPE_LOCAL i = {"local_interface": local_interface, "neighbors": []} n = { "remote_chassis_id": remote_chassis_id, "remote_chassis_id_subtype": remote_chassis_id_subtype, "remote_port": remote_port, "remote_port_subtype": remote_port_subtype, "remote_capabilities": cap, } if remote_system_name: n["remote_system_name"] = remote_system_name # # XXX: Dirty hack for older firmware. Switch rebooted. # if remote_chassis_id_subtype != LLDP_CHASSIS_SUBTYPE_LOCAL: i["neighbors"] = [n] r += [i] continue try: c = self.cli("show lldp neighbors %s" % local_interface) match = self.rx_detail.search(c) if match: remote_chassis_id = match.group("dev_id") if is_ipv4(remote_chassis_id) or is_ipv6( remote_chassis_id): remote_chassis_id_subtype = LLDP_CHASSIS_SUBTYPE_NETWORK_ADDRESS elif is_mac(remote_chassis_id): remote_chassis_id = MACAddressParameter().clean( remote_chassis_id) remote_chassis_id_subtype = LLDP_CHASSIS_SUBTYPE_MAC else: remote_chassis_id_subtype = LLDP_CHASSIS_SUBTYPE_LOCAL n["remote_chassis_id"] = remote_chassis_id n["remote_chassis_id_subtype"] = remote_chassis_id_subtype if match.group("sys_name").strip(): sys_name = match.group("sys_name").strip() n["remote_system_name"] = sys_name if match.group("sys_descr").strip(): sys_descr = match.group("sys_descr").strip() n["remote_system_description"] = sys_descr if match.group("port_descr").strip(): port_descr = match.group("port_descr").strip() n["remote_port_description"] = port_descr except Exception: pass i["neighbors"] += [n] r += [i] return r
def execute(self): r = [] try: v = self.cli("show lldp neighbors") except self.CLISyntaxError: raise self.NotSupportedError() if v.startswith("%"): # % LLDP is not enabled return [] v = self.rx_summary_split.split(v)[1] lldp_interfaces = [] # Get LLDP interfaces with neighbors for ll in v.splitlines(): ll = ll.strip() if not ll: break match = self.rx_s_line.match(ll) if not match: continue lldp_interfaces += [match.group("local_if")] # Get LLDP neighbors for local_if in lldp_interfaces: i = {"local_interface": local_if, "neighbors": []} # Get neighbors details try: v = self.cli("show lldp neighbors interface %s detail" % local_if) except self.CLISyntaxError: # Found strange CLI syntax on Catalyst 4900 # Allow ONLY interface name or "detail" # Need testing... raise self.NotSupportedError() # Get remote port match = self.rx_remote_port.search(v) remote_port = match.group("remote_if") remote_port_subtype = 128 if self.rx_mac.match(remote_port): # Actually macAddress(3) # Convert MAC to common form remote_port = MACAddressParameter().clean(remote_port) remote_port_subtype = 3 elif is_ipv4(remote_port): # Actually networkAddress(4) remote_port_subtype = 4 elif is_int(remote_port): # Actually local(7) remote_port_subtype = 7 n = { "remote_port": remote_port, "remote_port_subtype": remote_port_subtype, "remote_chassis_id_subtype": 4, } # Get chassis id match = self.rx_chassis_id.search(v) if not match: continue n["remote_chassis_id"] = match.group("id") # Get capabilities cap = 0 match = self.rx_enabled_caps.search(v) if match: for c in match.group("caps").split(","): c = c.strip() if c: cap |= { "O": 1, "P": 2, "B": 4, "W": 8, "R": 16, "T": 32, "C": 64, "S": 128, "N/A": 256, }[c] n["remote_capabilities"] = cap # Get remote chassis id match = self.rx_system.search(v) if match: n["remote_system_name"] = match.group("name") i["neighbors"] += [n] r += [i] return r
def execute_cli(self): r = [] try: v = self.cli("show lldp neighbors") except self.CLISyntaxError: raise self.NotSupportedError() t = parse_table(v, allow_wrap=True) for i in t: chassis_id = i[1] if is_ipv4(chassis_id) or is_ipv6(chassis_id): chassis_id_subtype = LLDP_CHASSIS_SUBTYPE_NETWORK_ADDRESS elif is_mac(chassis_id): chassis_id_subtype = LLDP_CHASSIS_SUBTYPE_MAC else: chassis_id_subtype = LLDP_CHASSIS_SUBTYPE_LOCAL port_id = i[2] if is_ipv4(port_id) or is_ipv6(port_id): port_id_subtype = LLDP_PORT_SUBTYPE_NETWORK_ADDRESS elif is_mac(port_id): port_id_subtype = LLDP_PORT_SUBTYPE_MAC else: port_id_subtype = LLDP_PORT_SUBTYPE_LOCAL caps = lldp_caps_to_bits( i[4].split(","), { "o": LLDP_CAP_OTHER, "p": LLDP_CAP_REPEATER, "b": LLDP_CAP_BRIDGE, "w": LLDP_CAP_WLAN_ACCESS_POINT, "r": LLDP_CAP_ROUTER, "t": LLDP_CAP_TELEPHONE, "c": LLDP_CAP_DOCSIS_CABLE_DEVICE, "s": LLDP_CAP_STATION_ONLY, }, ) neighbor = { "remote_chassis_id": chassis_id, "remote_chassis_id_subtype": chassis_id_subtype, "remote_port": port_id, "remote_port_subtype": port_id_subtype, "remote_capabilities": caps, } if i[3]: neighbor["remote_system_name"] = i[3] r += [{"local_interface": i[0], "neighbors": [neighbor]}] if not t: for iface in self.scripts.get_interface_status(): c = self.cli("show lldp neighbors interface %s" % iface["interface"], ignore_errors=True) c = c.replace("\n\n", "\n") neighbors = [] for match in self.rx_neighbor.finditer(c): chassis_id = match.group("chassis_id") if is_ipv4(chassis_id) or is_ipv6(chassis_id): chassis_id_subtype = 5 elif is_mac(chassis_id): chassis_id_subtype = 4 else: chassis_id_subtype = 7 port_id = match.group("port_id") if is_ipv4(port_id) or is_ipv6(port_id): port_id_subtype = 4 elif is_mac(port_id): port_id_subtype = 3 else: port_id_subtype = 7 caps = 0 if match.group("caps").strip(): for c in match.group("caps").split(): c = c.strip() if c in {"not", "advertised"}: # not caps break if c and (c != "--"): caps |= { "O": 1, "P": 2, "B": 4, "W": 8, "R": 16, "r": 16, "T": 32, "C": 64, "S": 128, }[c] neighbor = { "remote_chassis_id": chassis_id, "remote_chassis_id_subtype": chassis_id_subtype, "remote_port": port_id, "remote_port_subtype": port_id_subtype, "remote_capabilities": caps, } port_descr = match.group("port_descr").strip() system_name = match.group("system_name").strip() system_descr = match.group("system_descr").strip() if bool(port_descr): neighbor["remote_port_description"] = port_descr if bool(system_name): neighbor["remote_system_name"] = system_name if bool(system_descr): neighbor["remote_system_description"] = system_descr neighbors += [neighbor] if neighbors: r += [{ "local_interface": iface["interface"], "neighbors": neighbors }] return r
def normalize_ntp_server(self, tokens): if is_ipv4(".".join(tokens[4:])): yield self.make_ntp_server_address(name="0", address=".".join(tokens[4:]))
def execute(self): r = [] # Try SNMP first # Fallback to CLI # LLDP First try: lldp = self.cli("show lldp neighbors") except self.CLISyntaxError: raise self.NotSupportedError() for match in self.rx_lldp_nei.finditer(lldp): local_interface = match.group("interface") remote_chassis_id = match.group("chassis_id") remote_port = match.group("port_id") # Build neighbor data # Get capability cap = 4 # Get remote port subtype remote_port_subtype = LLDP_PORT_SUBTYPE_NAME if is_ipv4(remote_port): # Actually networkAddress(4) remote_port_subtype = LLDP_PORT_SUBTYPE_NETWORK_ADDRESS elif is_mac(remote_port): # Actually macAddress(3) # Convert MAC to common form remote_port = MACAddressParameter().clean(remote_port) remote_port_subtype = LLDP_PORT_SUBTYPE_MAC elif is_int(remote_port): # Actually local(7) remote_port_subtype = LLDP_PORT_SUBTYPE_LOCAL i = {"local_interface": local_interface, "neighbors": []} n = { "remote_chassis_id": remote_chassis_id, "remote_port": remote_port, "remote_capabilities": cap, "remote_port_subtype": remote_port_subtype, } if is_ipv4(n["remote_chassis_id"]) or is_ipv6( n["remote_chassis_id"]): n["remote_chassis_id_subtype"] = LLDP_CHASSIS_SUBTYPE_NETWORK_ADDRESS else: n["remote_chassis_id_subtype"] = LLDP_CHASSIS_SUBTYPE_MAC try: c = self.cli("show lldp ports %s neighbors detailed" % local_interface) match = self.rx_lldp_detail.search(c) if match: port_descr = match.group("port_descr") if port_descr: n["remote_port_description"] = port_descr.replace( '"', "").strip() n["remote_port_description"] = re.sub( r"\\\n\s*", "", n["remote_port_description"]) n["remote_system_name"] = match.group( "system_name").replace('"', "").strip() n["remote_system_name"] = re.sub(r"\\\n\s*", "", n["remote_system_name"]) sys_descr = match.group("system_descr") if sys_descr: n["remote_system_description"] = sys_descr.replace( '"', "").strip() n["remote_system_description"] = re.sub( r"\\\n\s*", "", n["remote_system_description"]) n["remote_port_subtype"] = self.port_types[match.group( "port_id_subtype").strip()] n["remote_chassis_id_subtype"] = self.chassis_types[ match.group("chassis_id_subtype").strip()] except self.CLISyntaxError: pass i["neighbors"].append(n) r.append(i) # Try EDP Second try: lldp = self.cli("show edp ports all") except self.CLISyntaxError: raise self.NotSupportedError() for match in self.rx_edp_nei.finditer(lldp): local_interface = match.group("interface") remote_chassis_id = match.group("chassis_id") remote_port = match.group("port_id") remote_system_name = match.group("name") # Build neighbor data # Get capability cap = 4 # Get remote port subtype remote_port_subtype = LLDP_PORT_SUBTYPE_NAME if is_ipv4(remote_port): # Actually networkAddress(4) remote_port_subtype = LLDP_PORT_SUBTYPE_NETWORK_ADDRESS elif is_mac(remote_port): # Actually macAddress(3) # Convert MAC to common form remote_port = MACAddressParameter().clean(remote_port) remote_port_subtype = LLDP_PORT_SUBTYPE_MAC elif is_int(remote_port): # Actually local(7) remote_port_subtype = LLDP_PORT_SUBTYPE_LOCAL i = {"local_interface": local_interface, "neighbors": []} n = { "remote_chassis_id": remote_chassis_id, "remote_port": remote_port, "remote_capabilities": cap, "remote_port_subtype": remote_port_subtype, } if remote_system_name: n["remote_system_name"] = remote_system_name if is_ipv4(n["remote_chassis_id"]) or is_ipv6( n["remote_chassis_id"]): n["remote_chassis_id_subtype"] = LLDP_CHASSIS_SUBTYPE_NETWORK_ADDRESS else: n["remote_chassis_id_subtype"] = LLDP_CHASSIS_SUBTYPE_MAC i["neighbors"].append(n) r.append(i) return r
def execute_cli(self): r = [] data = [] try: v = self.cli("show lldp neighbors") except self.CLISyntaxError: raise self.NotSupportedError() v = v.replace("\n\n", "\n") for l in parse_table(v): if not l[0]: data[-1] = [s[0] + s[1] for s in zip(data[-1], l)] continue data += [l] for d in data: try: ifname = self.profile.convert_interface_name(d[0]) except ValueError: continue v = self.cli("show lldp neighbors %s" % ifname) match = self.rx_neighbor.search(v) chassis_id = match.group("chassis_id").strip() if is_ipv4(chassis_id) or is_ipv6(chassis_id): chassis_id_subtype = LLDP_CHASSIS_SUBTYPE_NETWORK_ADDRESS elif is_mac(chassis_id): chassis_id_subtype = LLDP_CHASSIS_SUBTYPE_MAC else: chassis_id_subtype = LLDP_CHASSIS_SUBTYPE_LOCAL port_id = match.group("port_id").strip() if is_ipv4(port_id) or is_ipv6(port_id): port_id_subtype = LLDP_PORT_SUBTYPE_NETWORK_ADDRESS elif is_mac(port_id): port_id_subtype = LLDP_PORT_SUBTYPE_MAC else: port_id_subtype = LLDP_PORT_SUBTYPE_LOCAL caps = lldp_caps_to_bits( match.group("caps").strip().split(","), { "other": LLDP_CAP_OTHER, "repeater": LLDP_CAP_REPEATER, "bridge": LLDP_CAP_BRIDGE, "wlan-access-point": LLDP_CAP_WLAN_ACCESS_POINT, "router": LLDP_CAP_ROUTER, "telephone": LLDP_CAP_TELEPHONE, "d": LLDP_CAP_DOCSIS_CABLE_DEVICE, "h": LLDP_CAP_STATION_ONLY, }, ) neighbor = { "remote_chassis_id": chassis_id, "remote_chassis_id_subtype": chassis_id_subtype, "remote_port": port_id, "remote_port_subtype": port_id_subtype, "remote_capabilities": caps, } system_name = match.group("system_name").strip() if system_name: neighbor["remote_system_name"] = system_name system_descr = match.group("system_descr").strip() if system_descr: neighbor["remote_system_description"] = system_descr port_descr = match.group("port_descr").strip() if port_descr: neighbor["remote_port_description"] = port_descr r += [{"local_interface": ifname, "neighbors": [neighbor]}] return r
def test_is_ipv4(raw, expected): assert is_ipv4(raw) is expected
def execute_cli(self): r = [] r_rem = [] v = self.cli("show lldp remote") for match in self.rx_lldp_rem.finditer(v): chassis_id = match.group("ch_id") if is_ipv4(chassis_id) or is_ipv6(chassis_id): chassis_id_subtype = LLDP_CHASSIS_SUBTYPE_NETWORK_ADDRESS elif is_mac(chassis_id): chassis_id_subtype = LLDP_CHASSIS_SUBTYPE_MAC else: chassis_id_subtype = LLDP_CHASSIS_SUBTYPE_LOCAL r_rem += [{ "local_interface": match.group("port"), "remote_chassis_id": chassis_id, "remote_chassis_id_subtype": chassis_id_subtype, }] v = self.cli("show lldp remote detail") # If detail command not contain ch id ext_ch_id = False lldp_iter = list(self.rx_lldp.finditer(v)) if not lldp_iter: ext_ch_id = True lldp_iter = list(self.rx_lldp_womac.finditer(v)) self.logger.debug("Not Find MAC in re") for match in lldp_iter: i = {"local_interface": match.group("port"), "neighbors": []} cap = lldp_caps_to_bits( match.group("sys_caps_enabled").strip().split(","), { "n/a": 0, "other": LLDP_CAP_OTHER, "repeater/hub": LLDP_CAP_REPEATER, "bridge/switch": LLDP_CAP_BRIDGE, "router": LLDP_CAP_ROUTER, "telephone": LLDP_CAP_TELEPHONE, "station": LLDP_CAP_STATION_ONLY, }, ) n = { "remote_chassis_id_subtype": { "macAddress": LLDP_CHASSIS_SUBTYPE_MAC, "networkAddress": LLDP_CHASSIS_SUBTYPE_NETWORK_ADDRESS, }[match.group("ch_type")], "remote_chassis_id": match.group("ch_id") if not ext_ch_id else None, "remote_port_subtype": { "ifAlias": LLDP_PORT_SUBTYPE_ALIAS, "macAddress": LLDP_PORT_SUBTYPE_MAC, "ifName": LLDP_PORT_SUBTYPE_NAME, "portComponent": LLDP_PORT_SUBTYPE_NAME, "local": LLDP_PORT_SUBTYPE_LOCAL, }[match.group("port_id_subtype")], "remote_port": match.group("port_id"), "remote_capabilities": cap, } if match.group("sys_name").strip() != "N/A": n["remote_system_name"] = match.group("sys_name").strip() if match.group("sys_descr").strip() != "N/A": sd = match.group("sys_descr").strip() if "SysDesc:" in sd: sd = sd.split()[-1] n["remote_system_description"] = re.sub(r"\n\s{29,30}", "", sd) if match.group("port_descr").strip() != "N/A": n["remote_port_description"] = re.sub( r"\n\s{29,30}", "", match.group("port_descr").strip()) match.group("port_descr") if n["remote_chassis_id"] is None: for j in r_rem: if i["local_interface"] == j["local_interface"]: n["remote_chassis_id"] = j["remote_chassis_id"] n["remote_chassis_id_subtype"] = j[ "remote_chassis_id_subtype"] break i["neighbors"] += [n] r += [i] return r
def execute_cli(self, **kwargs): r = [] # Fallback to CLI try: lldp = self.cli("show lldp interface") except self.CLISyntaxError: raise NotImplementedError for match in self.rx_line.finditer(lldp): local_interface = match.group("interface") remote_chassis_id = match.group("chassis_id") remote_port = match.group("port_id") remote_system_name = match.group("name") system_description = match.group("system_description") port_description = match.group("port_description") # Build neighbor data # Get capability cap = 0 """ for c in match.group("capabilities").split(","): if cap: c = c.strip() if c: cap |= { "O": 1, "r": 2, "B": 4, "W": 8, "R": 16, "T": 32, "C": 64, "S": 128, "D": 256, "H": 512, "TP": 1024, }[c] """ # Get remote port subtype remote_port_subtype = 5 if is_ipv4(remote_port): # Actually networkAddress(4) remote_port_subtype = 4 elif is_mac(remote_port): # Actually macAddress(3) remote_port_subtype = 3 elif is_int(remote_port): # Actually local(7) remote_port_subtype = 7 i = {"local_interface": local_interface, "neighbors": []} n = { "remote_chassis_id": remote_chassis_id, "remote_port": remote_port, "remote_capabilities": cap, "remote_port_subtype": remote_port_subtype, } if remote_system_name and remote_system_name != "NULL": n["remote_system_name"] = remote_system_name if system_description and system_description != "NULL": n["remote_system_description"] = system_description if port_description and port_description != "NULL": n["remote_port_description"] = port_description # TODO: # n["remote_chassis_id_subtype"] = 4 i["neighbors"].append(n) r.append(i) return r
def execute_cli(self): r = [] try: v = self.cli("show lldp neighbors") except self.CLISyntaxError: raise self.NotSupportedError() if v.startswith("%"): # % LLDP is not enabled return [] v = self.rx_summary_split.split(v)[1] lldp_interfaces = [] # Get LLDP interfaces with neighbors for line in v.splitlines(): line = line.strip() if not line: break match = self.rx_s_line.match(line) if not match: continue lldp_interfaces += [match.group("local_if")] # Get LLDP neighbors for local_if in lldp_interfaces: i = {"local_interface": local_if, "neighbors": []} # Get neighbors details try: v = self.cli("show lldp neighbors %s detail" % local_if) except self.CLISyntaxError: # Found strange CLI syntax on Catalyst 4900 # Allow ONLY interface name or "detail" # Need testing... raise self.NotSupportedError() # Get remote port match = self.re_search(self.rx_remote_port, v) remote_port = match.group("remote_if") remote_port_subtype = LLDP_PORT_SUBTYPE_ALIAS if is_ipv4(remote_port): remote_port = IPv4Parameter().clean(remote_port) remote_port_subtype = LLDP_PORT_SUBTYPE_NETWORK_ADDRESS elif is_mac(remote_port): # Convert MAC to common form remote_port = MACAddressParameter().clean(remote_port) remote_port_subtype = LLDP_PORT_SUBTYPE_MAC elif is_int(remote_port): remote_port_subtype = LLDP_PORT_SUBTYPE_LOCAL n = { "remote_port": remote_port, "remote_port_subtype": remote_port_subtype, "remote_chassis_id_subtype": LLDP_CHASSIS_SUBTYPE_MAC, } match = self.rx_descr.search(v) if match: n["remote_port_description"] = match.group("descr") # Get chassis id match = self.rx_chassis_id.search(v) if not match: continue n["remote_chassis_id"] = match.group("id") # Get capabilities cap = 0 match = self.rx_enabled_caps.search(v) if match: cap = lldp_caps_to_bits( match.group("caps").strip().split(","), { "o": LLDP_CAP_OTHER, "p": LLDP_CAP_REPEATER, "b": LLDP_CAP_BRIDGE, "w": LLDP_CAP_WLAN_ACCESS_POINT, "r": LLDP_CAP_ROUTER, "t": LLDP_CAP_TELEPHONE, "c": LLDP_CAP_DOCSIS_CABLE_DEVICE, "s": LLDP_CAP_STATION_ONLY, }, ) n["remote_capabilities"] = cap # Get remote chassis id match = self.rx_system.search(v) if match: n["remote_system_name"] = match.group("name") if is_ipv4(n["remote_chassis_id"]) or is_ipv6( n["remote_chassis_id"]): n["remote_chassis_id_subtype"] = LLDP_CHASSIS_SUBTYPE_NETWORK_ADDRESS elif is_mac(n["remote_chassis_id"]): pass else: n["remote_chassis_id_subtype"] = LLDP_CHASSIS_SUBTYPE_LOCAL i["neighbors"] += [n] r += [i] return r
async def fetch( url: str, method: str = "GET", headers=None, body: Optional[bytes] = None, connect_timeout=DEFAULT_CONNECT_TIMEOUT, request_timeout=DEFAULT_REQUEST_TIMEOUT, resolver=resolve, max_buffer_size=DEFAULT_BUFFER_SIZE, follow_redirects: bool = False, max_redirects=DEFAULT_MAX_REDIRECTS, validate_cert=config.http_client.validate_certs, allow_proxy: bool = False, proxies=None, user: Optional[str] = None, password: Optional[str] = None, content_encoding: Optional[str] = None, eof_mark: Optional[bytes] = None, ) -> Tuple[int, Dict[str, Any], bytes]: """ :param url: Fetch URL :param method: request method "GET", "POST", "PUT" etc :param headers: Dict of additional headers :param body: Request body for POST and PUT request :param connect_timeout: :param request_timeout: :param resolver: :param follow_redirects: :param max_redirects: :param validate_cert: :param allow_proxy: :param proxies: :param user: :param password: :param max_buffer_size: :param content_encoding: :param eof_mark: Do not consider connection reset as error if eof_mark received (string or list) :return: code, headers, body """ def get_connect_options(): opts = {} if use_tls and not proxy: ctx = ssl.create_default_context(ssl.Purpose.SERVER_AUTH) if validate_cert: ctx.check_hostname = True ctx.verify_mode = ssl.CERT_REQUIRED else: ctx.check_hostname = False ctx.verify_mode = ssl.CERT_NONE opts["ssl"] = ctx return opts metrics["httpclient_requests", ("method", method.lower())] += 1 # if eof_mark: eof_mark = smart_bytes(eof_mark) # Detect proxy when necessary u = urlparse(str(url)) use_tls = u.scheme == "https" proto = "HTTPS" if use_tls else "HTTP" logger.debug("%s %s %s", proto, method, url) if ":" in u.netloc: host, port = u.netloc.rsplit(":") port = int(port) else: host = u.netloc port = DEFAULT_PORTS.get(u.scheme) if not port: return ERR_TIMEOUT, {}, b"Cannot resolve port for scheme: %s" % smart_bytes( u.scheme) if is_ipv4(host): addr = host else: addr = await resolver(host) if not addr: return ERR_TIMEOUT, {}, "Cannot resolve host: %s" % host # Detect proxy server if allow_proxy: proxy = (proxies or SYSTEM_PROXIES).get(u.scheme) else: proxy = None # Connect reader, writer = None, None if proxy: connect_address = proxy elif isinstance(addr, tuple): connect_address = addr else: connect_address = (addr, port) try: try: if proxy: logger.debug("Connecting to proxy %s:%s", connect_address[0], connect_address[1]) reader, writer = await asyncio.wait_for( asyncio.open_connection(connect_address[0], connect_address[1], **get_connect_options()), connect_timeout, ) except ConnectionRefusedError: metrics["httpclient_timeouts"] += 1 return ERR_TIMEOUT, {}, b"Connection refused" except OSError as e: metrics["httpclient_timeouts"] += 1 return ERR_TIMEOUT, {}, b"Connection error: %s" % smart_bytes(e) except asyncio.TimeoutError: metrics["httpclient_timeouts"] += 1 return ERR_TIMEOUT, {}, b"Connection timed out" # Proxy CONNECT if proxy: logger.debug("Sending CONNECT %s:%s", addr, port) # Send CONNECT request req = b"CONNECT %s:%s HTTP/1.1\r\nUser-Agent: %s\r\n\r\n" % ( smart_bytes(addr), smart_bytes(port), smart_bytes(DEFAULT_USER_AGENT), ) writer.write(smart_bytes(req)) try: await asyncio.wait_for(writer.drain(), request_timeout) except asyncio.TimeoutError: metrics["httpclient_proxy_timeouts"] += 1 return ERR_TIMEOUT, {}, b"Timed out while sending request to proxy" # Wait for proxy response parser = HttpParser() while not parser.is_headers_complete(): try: data = await asyncio.wait_for(reader.read(max_buffer_size), request_timeout) except asyncio.TimeoutError: metrics["httpclient_proxy_timeouts"] += 1 return ERR_TIMEOUT, {}, b"Timed out while sending request to proxy" received = len(data) parsed = parser.execute(data, received) if parsed != received: return ERR_PARSE_ERROR, {}, b"Parse error" code = parser.get_status_code() logger.debug("Proxy response: %s", code) if not 200 <= code <= 299: return code, parser.get_headers(), "Proxy error: %s" % code # Process request body = body or "" content_type = "application/binary" if not isinstance(body, (str, bytes)): body = smart_text(orjson.dumps(body)) content_type = "text/json" body = smart_bytes(body) # Here and below body is binary h = { "Host": str(u.netloc), "Connection": "close", "User-Agent": DEFAULT_USER_AGENT } if body and content_encoding: if content_encoding == CE_DEFLATE: # Deflate compression h["Content-Encoding"] = CE_DEFLATE compress = zlib.compressobj( zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -zlib.MAX_WBITS, zlib.DEF_MEM_LEVEL, zlib.Z_DEFAULT_STRATEGY, ) body = compress.compress(body) + compress.flush() elif content_encoding == CE_GZIP: # gzip compression h["Content-Encoding"] = CE_GZIP compress = zlib.compressobj(6, zlib.DEFLATED, -zlib.MAX_WBITS, zlib.DEF_MEM_LEVEL, 0) crc = zlib.crc32(body, 0) & 0xFFFFFFFF body = b"\x1f\x8b\x08\x00%s\x02\xff%s%s%s%s" % ( to32u(int(time.time())), compress.compress(body), compress.flush(), to32u(crc), to32u(len(body)), ) if method in REQUIRE_LENGTH_METHODS: h["Content-Length"] = str(len(body)) h["Content-Type"] = content_type if user and password: # Include basic auth header uh = smart_text("%s:%s" % (user, password)) h["Authorization"] = b"Basic %s" % codecs.encode( uh.encode("utf-8"), "base64").strip() if headers: h.update(headers) path = u.path if u.query: path += "?%s" % u.query req = b"%s %s HTTP/1.1\r\n%s\r\n\r\n%s" % ( smart_bytes(method), smart_bytes(path), b"\r\n".join(b"%s: %s" % (smart_bytes(k), smart_bytes(h[k])) for k in h), body, ) try: writer.write(req) await asyncio.wait_for(writer.drain(), request_timeout) except ConnectionResetError: metrics["httpclient_timeouts"] += 1 return ERR_TIMEOUT, {}, b"Connection reset while sending request" except asyncio.TimeoutError: metrics["httpclient_timeouts"] += 1 return ERR_TIMEOUT, {}, b"Timed out while sending request" parser = HttpParser() response_body: List[bytes] = [] while not parser.is_message_complete(): try: data = await asyncio.wait_for(reader.read(max_buffer_size), request_timeout) is_eof = not data except (asyncio.IncompleteReadError, ConnectionResetError): is_eof = True except asyncio.TimeoutError: metrics["httpclient_timeouts"] += 1 return ERR_READ_TIMEOUT, {}, b"Request timed out" if is_eof: if eof_mark and response_body: # Check if EOF mark is in received data response_body = [b"".join(response_body)] if isinstance(eof_mark, str): if eof_mark in response_body[0]: break else: found = False for m in eof_mark: if m in response_body[0]: found = True break if found: break metrics["httpclient_timeouts"] += 1 return ERR_READ_TIMEOUT, {}, b"Connection reset" received = len(data) parsed = parser.execute(data, received) if parsed != received: return ERR_PARSE_ERROR, {}, b"Parse error" if parser.is_partial_body(): response_body += [parser.recv_body()] code = parser.get_status_code() parsed_headers = parser.get_headers() logger.debug("HTTP Response %s", code) if 300 <= code <= 399 and follow_redirects: # Process redirects if max_redirects > 0: new_url = parsed_headers.get("Location") if not new_url: return ERR_PARSE_ERROR, {}, b"No Location header" logger.debug("HTTP redirect %s %s", code, new_url) return await fetch( new_url, method="GET", headers=headers, connect_timeout=connect_timeout, request_timeout=request_timeout, resolver=resolver, max_buffer_size=max_buffer_size, follow_redirects=follow_redirects, max_redirects=max_redirects - 1, validate_cert=validate_cert, allow_proxy=allow_proxy, proxies=proxies, ) else: return 404, {}, b"Redirect limit exceeded" # @todo: Process gzip and deflate Content-Encoding return code, parsed_headers, b"".join(response_body) finally: if writer: writer.close() try: await writer.wait_closed() except ConnectionResetError: pass
def execute_cli(self): r = [] try: v = self.cli("show lldp neighbors") except self.CLISyntaxError: raise self.NotSupportedError() t = parse_table(v, allow_wrap=True) for i in t: local_if = i[0] v = self.cli("show lldp neighbors %s" % local_if) match = self.rx_neighbor.search(v) remote_chassis_id = match.group("remote_chassis_id") if is_ipv4(remote_chassis_id) or is_ipv6(remote_chassis_id): # Actually networkAddress(4) remote_chassis_id_subtype = 5 elif is_mac(remote_chassis_id): # Actually macAddress(3) # Convert MAC to common form remote_chassis_id_subtype = 4 else: remote_chassis_id_subtype = 7 remote_port = match.group("remote_port") if is_ipv4(remote_port) or is_ipv6(remote_port): # Actually networkAddress(4) remote_port_subtype = 4 elif is_mac(remote_port): # Actually macAddress(3) remote_port_subtype = 3 elif is_int(remote_port): # Actually local(7) remote_port_subtype = 7 else: remote_port_subtype = 5 # Get capability cap = 0 s = match.group("caps") for c in s.strip().split(", "): cap |= { "Other": 1, "Repeater": 2, "Bridge": 4, "WLAN": 8, "Router": 16, "Telephone": 32, "Cable": 64, "Station": 128, }[c] n = { "remote_chassis_id": remote_chassis_id, "remote_chassis_id_subtype": remote_chassis_id_subtype, "remote_port": remote_port, "remote_port_subtype": remote_port_subtype, "remote_capabilities": cap, } match = self.rx_system_name.search(v) if match and match.group("system_name"): n["remote_system_name"] = match.group("system_name") match = self.rx_port_descr.search(v) if match and match.group("port_descr"): n["remote_port_description"] = match.group("port_descr") i = {"local_interface": local_if, "neighbors": [n]} r += [i] return r