diff --git a/VERSION b/VERSION index 90a27f9..227cea2 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.0.5 +2.0.0 diff --git a/examples/example.py b/examples/example.py new file mode 100644 index 0000000..fe3ab78 --- /dev/null +++ b/examples/example.py @@ -0,0 +1,77 @@ +# Copyright 2020 Nokia +# Licensed under the Apache License 2.0. +# SPDX-License-Identifier: Apache-2.0 +""" +This is a simple example of how to use napalm-srlinux. +First, deploy the SR Linux container using containerlab: + +``` +CLAB_LABDIR_BASE=/tmp \ +sudo -E clab deploy -c -t srlinux.dev/clab-srl +``` + +Then uncomment the NAPALM API calls that you want to run and run this script: + +python examples/example.py +""" + +from napalm import get_network_driver + +# using rich to pretty print the output +# feel free to remove it if you don't want to install it +from rich import print_json + +driver = get_network_driver("srlinux") +optional_args = { + # "jsonrpc_port": 80, + # "skip_verify": True, + "insecure": True +} +with driver("srl", "admin", "NokiaSrl1!", optional_args=optional_args) as device: + # print_json(data=device.get_bgp_config(neighbor="", group="")) #Done + # print_json(data=device.get_bgp_config(neighbor="", group="ebgp")) #Done + # print_json(data=device.get_bgp_config(neighbor="10.1.1.2", group="")) #Done + # print_json(data=device.get_config(retrieve="all", full=False, sanitized=False)) + # print_json(data=device.get_config(retrieve="running", full=False, sanitized=False)) + # print_json(data=device.get_config(retrieve="candidate", full=False, sanitized=False)) + # print_json(data=device.get_config(retrieve="state", full=False, sanitized=False)) + # print_json(data=device.get_ntp_stats()) + # print_json(data=device.get_optics()) + # print_json(data=device.get_route_to()) + # print_json(data=device.get_route_to("1.0.4.0/24")) + # print_json(data=device.get_route_to("100.100.100.100")) + # print_json(data=device.get_route_to(destination="172.20.20.0/24")) + # print_json(data=device.get_route_to(protocol="bgp")) + # print_json(data=device.get_route_to(protocol="host")) + # print_json(data=device.get_mac_address_table()) #Done + # print_json(data=device.get_snmp_information()) + # print(device.is_alive()) + # print_json(data=device.cli(["date","info system information","show network-instance default protocols bgp neighbor"])) + # print(device.load_merge_candidate(filename="/root/syed/backup/napalm-srl-dev/demo_merge.json")) + # print(device.load_replace_candidate(filename="/home/nuage/json_compare/srl2_2000_Ori_WithBGP.json")) + # print_json(data=device.commit_config("test commit")) + # print_json(data=device.compare_config()) + # print_json(data=device.discard_config()) + # print_json(data=device.rollback()) + # print_json(data=device.ping(destination="11.1.1.2")) + # print_json(data=device.ping(destination="11.1.1.2",source="10.1.1.1",ttl=2, timeout=2, size=64, count=2, vrf="default")) + # print_json(data=device.traceroute(destination="11.1.1.2",vrf = "")) + # print_json(data=device.traceroute(destination="21.1.1.2",ttl=5, vrf = "ip_vrf1")) + # print_json(data=device.get_arp_table()) + # print_json(data=device.get_arp_table("ip_vrf1")) + # print_json(data=device.get_bgp_neighbors()) + # print_json(data=device.get_bgp_neighbors_detail()) + # print_json(data=device.get_bgp_neighbors_detail("10.1.1.2")) + # print_json(data=device.get_environment()) + # print_json(data=device.get_facts()) + # print_json(data=device.get_interfaces()) + # print_json(data=device.get_interfaces_counters()) + # print_json(data=device.get_interfaces_ip()) + # print_json(data=device.get_ipv6_neighbors_table())#----------TBD + # print_json(data=device.get_lldp_neighbors()) + # print_json(data=device.get_lldp_neighbors_detail()) + # print_json(data=device.get_lldp_neighbors_detail("ethernet-1/3")) + # print_json(data=device.get_network_instances()) + # print_json(data=device.get_network_instances()) + print_json(data=device.get_users()) + # print_json(data=device.test()) diff --git a/examples/example_script.py b/examples/example_script.py deleted file mode 100644 index 171025b..0000000 --- a/examples/example_script.py +++ /dev/null @@ -1,64 +0,0 @@ -# Copyright 2020 Nokia -# Licensed under the Apache License 2.0. -# SPDX-License-Identifier: Apache-2.0 - -from napalm import get_network_driver -import json - -driver = get_network_driver("srlinux") -optional_args = { - "jsonrpc_port": 80, - #"skip_verify": True, - #"insecure": False -} -device = driver("172.20.20.2", "admin", "admin", 60, optional_args) -device.open() -#print(json.dumps(device.get_bgp_config(neighbor="", group=""))) #Done -#print(json.dumps(device.get_bgp_config(neighbor="", group="ebgp"))) #Done -#print(json.dumps(device.get_bgp_config(neighbor="10.1.1.2", group=""))) #Done -#print(json.dumps(device.get_config(retrieve="all", full=False, sanitized=False))) -#print(json.dumps(device.get_config(retrieve="running", full=False, sanitized=False))) -#print(json.dumps(device.get_config(retrieve="candidate", full=False, sanitized=False))) -#print(json.dumps(device.get_config(retrieve="state", full=False, sanitized=False))) -#print(json.dumps(device.get_ntp_stats())) -#print(json.dumps(device.get_optics())) -#print(json.dumps(device.get_route_to())) -#print(json.dumps(device.get_route_to("1.0.4.0/24"))) -#print(json.dumps(device.get_route_to("100.100.100.100"))) -#print(json.dumps(device.get_route_to(destination="172.20.20.0/24"))) -#print(json.dumps(device.get_route_to(protocol="bgp"))) -#print(json.dumps(device.get_route_to(protocol="host"))) -#print(json.dumps(device.get_mac_address_table())) #Done -#print(json.dumps(device.get_snmp_information())) -#print(device.is_alive()) -#print(json.dumps(device.cli(["date","info system information","show network-instance default protocols bgp neighbor"]))) -#print(device.load_merge_candidate(filename="/root/syed/backup/napalm-srl-dev/demo_merge.json")) -#print(device.load_replace_candidate(filename="/home/nuage/json_compare/srl2_2000_Ori_WithBGP.json")) -#print(json.dumps(device.commit_config("test commit"))) -#print(json.dumps(device.compare_config())) -#print(json.dumps(device.discard_config())) -#print(json.dumps(device.rollback())) -#print(json.dumps(device.ping(destination="11.1.1.2"))) -#print(json.dumps(device.ping(destination="11.1.1.2",source="10.1.1.1",ttl=2, timeout=2, size=64, count=2, vrf="default"))) -#print(json.dumps(device.traceroute(destination="11.1.1.2",vrf = ""))) -#print(json.dumps(device.traceroute(destination="21.1.1.2",ttl=5, vrf = "ip_vrf1"))) -#print(json.dumps(device.get_arp_table())) -#print(json.dumps(device.get_arp_table("ip_vrf1"))) -#print(json.dumps(device.get_bgp_neighbors())) -#print(json.dumps(device.get_bgp_neighbors_detail())) -#print(json.dumps(device.get_bgp_neighbors_detail("10.1.1.2"))) -#print(json.dumps(device.get_environment())) -#print(json.dumps(device.get_facts())) -#print(json.dumps(device.get_interfaces())) -#print(json.dumps(device.get_interfaces_counters())) -#print(json.dumps(device.get_interfaces_ip())) -#print(json.dumps(device.get_ipv6_neighbors_table()))#----------TBD -#print(json.dumps(device.get_lldp_neighbors())) -#print(json.dumps(device.get_lldp_neighbors_detail())) -#print(json.dumps(device.get_lldp_neighbors_detail("ethernet-1/3"))) -#print(json.dumps(device.get_network_instances())) -#print(json.dumps(device.get_network_instances())) -#print(json.dumps(device.get_users())) -#print(json.dumps(device.test())) - -device.close() diff --git a/napalm_srlinux/srlinux.py b/napalm_srlinux/srlinux.py index 45635b9..314976d 100644 --- a/napalm_srlinux/srlinux.py +++ b/napalm_srlinux/srlinux.py @@ -24,7 +24,7 @@ import enum import logging import re -from typing import AnyStr, Optional, Union +from typing import Any, AnyStr, Optional, Union import httpx import jsonpath_ng @@ -875,7 +875,7 @@ def __init__( optional_args = {} # Optional Arguments - self.jsonrpc_port = optional_args.get("jsonrpc_port", 443) + self.jsonrpc_port = self._determine_jsonrpc_port(optional_args) self.skip_verify = optional_args.get("skip_verify", False) self.insecure = optional_args.get("insecure", False) self.tls_ca = optional_args.get("tls_ca", "") @@ -883,7 +883,8 @@ def __init__( self.tls_key_path = optional_args.get("tls_key_path", "") self.tls_key_password = optional_args.get("tls_key_password", "") - self.jsonrpc_session = self._new_jsonrpc_client() + self.jsonrpc_client = self._new_jsonrpc_client() + self.jsonrpc_url = self._compose_jsonrpc_url() # Warn about incompatible/oddball settings if self.jsonrpc_port == 80: @@ -907,22 +908,18 @@ def __init__( def open(self): """Check the supplied init params actually work, throw an exception if not.""" - # Set up a JSON RPC Client and test connectivity to the endpoint. - path = "/system/information/version" - ok, data = self.get_paths([path], SRLinuxDevice.Datastore.STATE) - - if ok: - return True - - raise Exception( - "Error opening connection. Error: " + data.get("error").get("message") - ) + try: + self.jsonrpc_client.head(self.jsonrpc_url) + except httpx.RequestError as exc: + raise ConnectionError( + "Error opening http(s) connection to JSON-RPC server" + ) from exc def close(self): """Cleanup the HTTP Client""" - self.jsonrpc_session.close() + self.jsonrpc_client.close() - def get_paths(self, paths: list, datastore: Datastore) -> list: + def get_paths(self, paths: list, datastore: Datastore) -> Any: """ Get the subtrees from a list of YANG paths from the specified datastore. Returns a list of results. @@ -971,18 +968,8 @@ def _jsonrpc_request(self, method: RPCMethod, params: dict) -> tuple[bool, dict] "params": params, } - proto = ( - "https" - if ( - self.jsonrpc_port == 443 - or (self.jsonrpc_port != 80 and not self.insecure) - ) - else "http" - ) - url = f"{proto}://{self.hostname}:{self.jsonrpc_port}/jsonrpc" - - result = self.jsonrpc_session.post( - url, headers=headers, json=request_data, timeout=self.timeout + result = self.jsonrpc_client.post( + self.jsonrpc_url, headers=headers, json=request_data, timeout=self.timeout ) if result.status_code == httpx.codes.OK and result.json().get("error"): @@ -1012,3 +999,38 @@ def _new_jsonrpc_client(self): opts["cert"] = cert return httpx.Client(**opts) + + def _compose_jsonrpc_url(self): + """ + Compose the JSON RPC URL, based on the initialized arguments. + """ + + proto = ( + "https" + if ( + self.jsonrpc_port == 443 + or (self.jsonrpc_port != 80 and not self.insecure) + ) + else "http" + ) + url = f"{proto}://{self.hostname}:{self.jsonrpc_port}/jsonrpc" + # print(url) + + return url + + def _determine_jsonrpc_port(self, opt_args): + """ + Determine the JSON RPC port based on the optional arguments. + """ + + # by default assume 443 port is used by jsonrpc server + port: int = 443 + + # if jsonrpc_port is specified, use that + if opt_args.get("jsonrpc_port"): + port = opt_args.get("jsonrpc_port") + # when insecure is set and jsonrpc_port is not specified, use 80 + elif opt_args.get("insecure"): + port = 80 + + return port