diff --git a/.github/workflows/pythopackage.yml b/.github/workflows/pythopackage.yml index 87ca3d8..80dd534 100644 --- a/.github/workflows/pythopackage.yml +++ b/.github/workflows/pythopackage.yml @@ -9,7 +9,7 @@ jobs: strategy: max-parallel: 3 matrix: - python-version: [3.5, 3.6, 3.7] + python-version: [3.6, 3.7, 3.8] steps: - uses: actions/checkout@v1 diff --git a/README.md b/README.md index b083160..546f1ab 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,6 @@ +[![PyPI](https://img.shields.io/pypi/v/napalm-arubaos-switch.svg)](https://pypi.python.org/pypi/napalm-arubaos-switch) +[![PyPI](https://img.shields.io/pypi/dm/napalm-arubaos-switch.svg)](https://pypi.python.org/pypi/napalm-arubaos-switch) +[![Building Status](https://github.com/napalm-automation-community/napalm-arubaos-switch/workflows/Python%20package/badge.svg?branch=master)](https://github.com/napalm-automation-community/napalm-arubaos-switch/actions?query=workflow%3A"Python%20package") # Napalm-arubaoss Driver implementation for Aruba OS Switch. Tested in AOS > WC.16.09.0004, some modules may not work properly in older versions. @@ -7,6 +10,7 @@ Driver implementation for Aruba OS Switch. Tested in AOS > WC.16.09.0004, some m * commit_config() ✅ * compare_config() ✅ * compliance_report() ✅ + * confirm_commit() ✅ * discard_config() ✅ * get_arp_table() ✅ * get_bgp_config() ❌* @@ -32,6 +36,7 @@ Driver implementation for Aruba OS Switch. Tested in AOS > WC.16.09.0004, some m * get_route_to() ✅ * get_snmp_information() ❌ - Planned * get_users() ❌ - Planned + * has_pending_commit() ✅ * is_alive() ✅ * load_merge_candidate() ✅** * load_replace_candidate() ✅ @@ -75,6 +80,27 @@ rest-interface rest-interface session-idle-timeout 120 #optional ``` +### optional_args +optional_args can be set during initialization like this: +```Python +from napalm import get_network_driver + +d = get_network_driver("arubaoss") + +with d('1.2.3.4', 'username', 'password', optional_args={'ssl_verify': False, "debugging": True}) as aruba: + print(aruba.get_config()) +``` + +The following values can be set in optional_args: +- ssl_verify: bool/str = defaults to **True** - will be passed to the requests object (description can be found [here](https://docs.python-requests.org/en/latest/_modules/requests/sessions/#Session.request)) +- keepalive: bool = defaults to **False** - sets the underlying TCP connection to either keep the connection or not and is a workaround for an issue with ArubaOS devices + (discussed [here](https://community.arubanetworks.com/community-home/digestviewer/viewthread?MID=28798#bme4aa3703-e476-4880-9cb4-9b208f86b2f4)) +- keep_alive: bool = same as keepalive, just shadows it to be able to use the same keyword as in older Python requests versions +- debugging: bool = defaults to **False** - sets the level of the logging handler to logging.DEBUG +- disable_ssl_warnings: bool = defaults to **False** - disables ssl warnings from urllib3 +- api: string = defaults to **v6** - defines the API version +- ssl: bool = defaults to **True**, sets http or https + ### Saltstack To use the driver with Saltstack, you would typically need a proxy minion. @@ -100,23 +126,23 @@ mine_enabled: true # not required, but nice to have #### Supported Salt execution modules - - [grains.items](docs/saltstack.md#grains.items) - - [net.arp](docs/saltstack.md#net.arp) - - [net.mac](docs/saltstack.md#net.mac) - - [net.ipaddrs](docs/saltstack.md#net.ipaddrs) - - [net.lldp](docs/saltstack.md#net.lldp) - - [net.facts](docs/saltstack.md#net.facts) - - [net.ping](docs/saltstack.md#net.ping) - - [net.traceroute](docs/saltstack.md#net.traceroute) - - [route.show](docs/saltstack.md#route.show) - - [net.cli](docs/saltstack.md#net.cli) - - [net.config](docs/saltstack.md#net.config) - - [net.load_config](docs/saltstack.md#net.load_config) - - [net.compare_config](docs/saltstack.md#net.load_config) + - [grains.items](docs/saltstack.md#grainsitems) + - [net.arp](docs/saltstack.md#netarp) + - [net.mac](docs/saltstack.md#netmac) + - [net.ipaddrs](docs/saltstack.md#netipaddrs) + - [net.lldp](docs/saltstack.md#netlldp) + - [net.facts](docs/saltstack.md#netfacts) + - [net.ping](docs/saltstack.md#netping) + - [net.traceroute](docs/saltstack.md#nettraceroute) + - [route.show](docs/saltstack.md#routeshow) + - [net.cli](docs/saltstack.md#netcli) + - [net.config](docs/saltstack.md#netconfig) + - [net.load_config](docs/saltstack.md#netload_config) + - [net.compare_config](docs/saltstack.md#netload_config) - net.load_template ( Issue #18) - net.discard_config - - [ntp.servers](docs/saltstack.md#ntp.servers) - - [napalm.compliance_report](docs/saltstack.md#napalm.compliance_report) + - [ntp.servers](docs/saltstack.md#ntpservers) + - [napalm.compliance_report](docs/saltstack.md#napalmcompliance_report) More details in [Saltstack examples](docs/saltstack.md) diff --git a/napalm_arubaoss/ArubaOS.py b/napalm_arubaoss/ArubaOS.py index ec821bf..82b2d1f 100644 --- a/napalm_arubaoss/ArubaOS.py +++ b/napalm_arubaoss/ArubaOS.py @@ -1,211 +1,226 @@ """ArubaOS-Switch Napalm driver.""" -import base64 -from itertools import zip_longest -from time import sleep - -import requests import logging -from netaddr import IPNetwork +import urllib3 + +from napalm_arubaoss.helper.base import Connection +from napalm_arubaoss.helper import ( + backup_config, + commit_config, + compare_config, + confirm_commit, + get_mac_address_table, + get_facts, + get_arp_table, + get_config, + get_interfaces, + get_interfaces_ip, + get_lldp_neighbors, + get_lldp_neighbors_detail, + get_ntp_stats, + get_ntp_servers, + get_route_to, + has_pending_commit, + is_alive, + load_merge_candidate, + load_replace_candidate, + ping, + rollback, + traceroute, +) -from napalm.base.helpers import textfsm_extractor from napalm.base.base import NetworkDriver -from napalm.base.exceptions import ( - ConnectAuthError, - ConnectionClosedException, - CommandErrorException, - CommandTimeoutException, - MergeConfigException, - ReplaceConfigException -) -""" Debugging -import http.client -http.client.HTTPConnection.debuglevel = 1 -logging.basicConfig() -logging.getLogger().setLevel(logging.DEBUG) -requests_log = logging.getLogger("requests.packages.urllib3") -requests_log.setLevel(logging.DEBUG) -requests_log.propagate = True -""" +logger = logging.getLogger("arubaoss") +logger.setLevel(logging.INFO) -log = logging.getLogger(__name__) +stream_formatter = logging.Formatter( + "%(asctime)s - %(name)s - %(levelname)s - %(message)s" +) -# disable anoying warning -# requests.packages.urllib3.disable_warnings() +streamhandler = logging.StreamHandler() +streamhandler.setFormatter(stream_formatter) +streamhandler.setLevel(logging.INFO) + +logger.addHandler(streamhandler) class ArubaOSS(NetworkDriver): """Class for connecting to aruba-os devices using the rest-api.""" - def __init__(self, hostname, - username='', - password='', - timeout=10, - optional_args=None): - """Instantiate the module.""" - self._headers = {'Content-Type': 'application/json'} + def __init__( + self, + hostname, + username, + password, + timeout=60, + optional_args=None + ): + """ + Initialize Class ArubaOSS. + + :param hostname: Hostname of the device + :param username: Username for the login + :param password: Password for the login + :param timeout: timeout to be passed to Request-Futures + :param optional_args: Optional Args to be passed to Request-Futures + """ + if not optional_args: + optional_args = {} + + if optional_args.get("debugging", False): + logger.setLevel(logging.DEBUG) + streamhandler.setLevel(logging.DEBUG) + + if optional_args.get("disable_ssl_warnings", False): + urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) + self.hostname = hostname self.username = username self.password = password self.timeout = timeout + self.optional_args = optional_args - # ---------------------------------------------------------------------------------------- - # optional arguments - # ---------------------------------------------------------------------------------------- - if optional_args is None: - optional_args = {} + self.cli_output = {} - self.api = optional_args.get("api", "v6") - ssl = optional_args.get("ssl", True) - self.keepalive = optional_args.get("keepalive", None) - self.ssl_verify = optional_args.get("ssl_verify", False) - if ssl: - self.proto = 'https' - else: - self.proto = 'http' + self.connection = Connection() - # URL encoding + def cli(self, commands): + """ + Run CLI commands through the REST API. - self._api_url = '{}://{}/rest/{}/'.format(self.proto, - self.hostname, - self.api) + :param commands: + :return: + """ + ret = self.connection.cli(commands) - def open(self): - """Open connection to the network device.""" - self._login_url = self._api_url + "login-sessions" + return ret - params = {'userName': self.username, 'password': self.password} - self._apisession = requests.Session() + def close(self): + """ + Close device connection and delete sessioncookie. - if not self.ssl_verify: - self._apisession.verify = False + :return: + """ + ret = self.connection.logout() - self._apisession.headers = self._headers - # bug #4 - random delay while re-using TCP connection - workaroud: - if self.keepalive is None: - self._apisession.keep_alive = False + return ret - rest_login = self._apisession.post(self._login_url, json=params, - timeout=self.timeout) + def commit_config(self, message="", revert_in=None): + """ + Backups and commit the configuration, and handles commit confirm. - if rest_login.status_code == 201: - session = rest_login.json() - self._headers['cookie'] = session['cookie'] - return True - else: - raise ConnectAuthError("Login failed") + :param message: + :param revert_in: + :return: + """ + ret = commit_config(self=self, revert_in=revert_in) - def is_alive(self): - """Check if device connection is alive.""" - """check if session cookie is still valid - Returns: - True - Session cookie is still valid - None - There's an error - """ - url = self._api_url + 'system' - endpoint = self._apisession.get(url) - if endpoint.status_code == 200: - "Session cookie is still valid" - return {"is_alive": True} - else: - raise ConnectionClosedException("HTTP session is closed") - - @staticmethod - def _read_candidate(candidate): - with open(candidate) as candidate_config: - return ''.join(candidate_config.readlines()) - - def _transaction_status(self, url): - status = 'CRS_IN_PROGRESS' - elapsed = 0 - while status == 'CRS_IN_PROGRESS' and elapsed < self.timeout: - call = self._apisession.get(url) - if 300 > call.status_code >= 200: - status = call.json() - return call - elapsed += 1 - sleep(1) - if elapsed == (int(self.timeout) - 1) and status == 'CRS_IN_PROGRESS': - raise CommandTimeoutException("Transaction timed out") - - @staticmethod - def _str_to_b64(spayload): - """Convert from str to b64 for aoss API.""" - payload_b64 = base64.b64encode(spayload.encode()) - return payload_b64.decode('utf-8') - - @staticmethod - def _mac_reformat(mac): - t = iter(mac.replace("-", "")) - return ':'.join(a+b for a, b in zip_longest(t, t, fillvalue="")) + return ret - def load_replace_candidate(self, filename=None, config=None): - """Replace running config with the candidate.""" - """ Implentation of napalm module load_replace_candidate() - ArubaOS-Switch supports payload_type options: - - "RPT_PATCH_FILE" -> not implemented - - "RPT_BACKUP_FILE" -> Implemented + def compare_config(self): + """ + Compare the running config with the candidate one. - Note: the maximum content_length = 16072, - "HTTP/1.1 413 Request Entity Too Large" is returned above that!!! + :return: """ - url = self._api_url + 'system/config/payload' - payload = {"payload_type": "RPT_BACKUP_FILE"} - if filename is not None: - config = self._read_candidate(filename) + ret = compare_config(self=self) - if config is not None: - payload['config_base64_encoded'] = ArubaOSS._str_to_b64(config) - load = self._apisession.post(url, json=payload) - if load.status_code != 200: - raise ReplaceConfigException("Load configuration failed") + return ret - def load_merge_candidate(self, filename=None, config=None): - """Merge candidate configuration with the running one.""" + def compliance_report(self, validation_file=None, validation_source=None): """ - Imperative config change: - Merge new config with existing one. There's no config validation - nor atomic commit!. Only configuration commands are supported, - "configure terminal" is not required. Use with caution. + Get Compliance report - NOT IMPLEMENTED. + :param validation_file: + :param validation_source: + :return: """ - if filename is not None: - config = self._read_candidate(filename) + return super(ArubaOSS, self).compliance_report() - if config is not None: - if isinstance(config, str): - config = config.split('\n') - if not self._config_batch(cmd_list=config): - raise MergeConfigException("Configuration merge failed") + def confirm_commit(self): + """ + Confirm the changes requested via commit_config when commit_confirm=True. - # mimic load_replace_candidate behaviour, by making sure candidate - # config exactly matches our merged configuration - self._backup_config(destination='REST_Payload_Backup') + Should cause self.has_pending_commit to return False when done. + :return: None + """ + return confirm_commit(self=self) - def cli(self, commands): - """Run CLI commands through the REST API.""" - output = {} - if isinstance(commands, list): - for cmd in commands: - output[cmd] = str(self._run_cmd(cmd)) - return output - elif isinstance(commands, str): - cmd_list = commands.splitlines() - return self.cli(cmd_list) - - def get_arp_table(self): - """Get device's ARP table.""" - raw_arp = self._run_cmd("show arp") - arp_table = textfsm_extractor(self, "show_arp", raw_arp) - for arp in arp_table: - arp['interface'] = arp.pop('port') - arp['mac'] = self._mac_reformat(arp['mac']) - arp['age'] = 'N/A' - return arp_table + def connection_tests(self): + """ + Show connection tests - NOT IMPLEMENTED. + + :return: + """ + return super(ArubaOSS, self).connection_tests() + + def discard_config(self): + """ + Discard the candidate configuration. + + :return: + """ + if self.has_pending_commit(): + self.load_merge_candidate(config="no job ROLLBACK") + + backup_config(self=self, destination="REST_Payload_Backup") + + def get_arp_table(self, vrf=""): + """ + Get device's ARP table. + + :param vrf: + :return: + """ + ret = get_arp_table(self=self, vrf=vrf) + + return ret + + def get_bgp_config(self, group="", neighbor=""): + """ + Get BGP config - NOT IMPLEMENTED. + + :param group: + :param neighbor: + :return: + """ + return super(ArubaOSS, self).get_bgp_config() + + def get_bgp_neighbors(self): + """ + Get BGP neighbors - NOT IMPLEMENTED. + + :return: + """ + return super(ArubaOSS, self).get_bgp_neighbors() + + def get_bgp_neighbors_detail(self, neighbor_address=""): + """ + Get BGP Neighbors detail - NOT IMPLEMENTED. + + :param neighbor_address: + :return: + """ + return super(ArubaOSS, self).get_bgp_neighbors_detail() + + def get_config(self, retrieve="all", full=False, sanitized=False): + """ + Get configuration stored on the device. + + :param retrieve: + :param full: + :param sanitized: + :return: + """ + # TODO check why "full" exists + ret = get_config(self=self, retrieve=retrieve) + + return ret def get_environment(self): - """Get environment readings.""" """ + Get environment readings - NOT IMPLEMENTED. + Currently (API v7) the API does not support reading information about fans, temperature, power or CPU. A textfsm template needs to be created to parse: @@ -214,384 +229,425 @@ def get_environment(self): - show system power-consumption - show system power-supply - show system information (CPU/MEM) - """ + + :return: output = { - "fans": {}, - "temperature": {}, - "power": {}, - "cpu": {}, - "memory": {} - } - return output - - def get_config(self, retrieve="all"): - """Get configuration stored on the device.""" - out = {'startup': '', 'candidate': '', 'running': ''} - - if (retrieve == 'all' or retrieve == 'startup'): - out['startup'] = str(self._run_cmd("display saved-configuration")) - if (retrieve == 'all' or retrieve == 'running'): - out['running'] = str(self._run_cmd("show running-config")) - if (retrieve == 'all' or retrieve == 'candidate'): - out['candidate'] = str(self._run_cmd( - "show config REST_Payload_Backup")) - return out + "fans": {}, + "temperature": {}, + "power": {}, + "cpu": {}, + "memory": {} + } + """ + return super(ArubaOSS, self).get_environment() def get_facts(self): - """Get general device information.""" - out = {'vendor': 'HPE Aruba'} - out['interface_list'] = [] - - url = self._api_url + 'system/status' - call = self._apisession.get(url) - if 300 > call.status_code >= 200: - rest_out = call.json() - out['hostname'] = rest_out['name'] - out['os_version'] = rest_out['firmware_version'] - out['serial_number'] = rest_out['serial_number'] - out['model'] = rest_out['product_model'] - - # get domain name to generate the FQDN - url = self._api_url + 'dns' - call = self._apisession.get(url) - if 300 > call.status_code >= 200: - rest_out = call.json() - out['fqdn'] = out['hostname'] + "." + \ - rest_out['dns_domain_names'][0] - - # Get interface list - url = self._api_url + 'system/status/switch' - call = self._apisession.get(url) - if 300 > call.status_code >= 200: - rest_out = call.json() - for blade in rest_out['blades']: - for ports in blade['data_ports']: - out['interface_list'].append(ports['port_name']) - - return out + """ + Get general device information. - def discard_config(self): - """Discard the candidate configuration.""" - self._backup_config(destination='REST_Payload_Backup') + :return: + """ + ret = get_facts(self=self) - def compare_config(self): - """Compare the running config with the candidate one.""" - url = self._api_url + 'system/config/cfg_restore/latest_diff' - check_url = url + '/status' - data = { - "server_type": "ST_FLASH", - "file_name": "REST_Payload_Backup", - "is_oobm": False - } - # trigger configuration comparison - diff = self._apisession.post(url, json=data) - if 300 > diff.status_code >= 200: - diff_output = self._apisession.get(check_url) - if diff_output.status_code == 200: - if not diff_output.json()['diff_add_list'] and \ - not diff_output.json()['diff_remove_list']: - # return empty string to signal the candidate - # and running configs are the same - return "" - else: - return diff_output.json() - else: - raise CommandErrorException("diff generation failed,\ - raise status") - else: - raise CommandErrorException("diff generation failed, raise status") - - def commit_config(self, message=None, confirm=0): - """Backups and commit the configuration, and handles commit confirm.""" - self._backup_config() - log.debug("Confirm rollback time is {}".format(str(confirm))) - if confirm > 0: - candidate = self.get_config(retrieve='candidate')['candidate'][:-2] - candidate_confirm = candidate + 'job ROLLBACK delay {} \ - "cfg-restore flash backup_running"\n'.format(str(confirm)) - self.load_replace_candidate(config=candidate_confirm) - self._commit_candidate(config='REST_Payload_Backup') - - def _commit_candidate(self, config): - """Commit the candidate configuration.""" - url = self._api_url + 'system/config/cfg_restore' - data = { - "server_type": "ST_FLASH", - "file_name": config, - "is_oobm": False + return ret + + def get_firewall_policies(self): + """ + Get firewall policies - NOT IMPLEMENTED. + + :return: + """ + return super(ArubaOSS, self).get_firewall_policies() + + def get_interfaces(self): + """ + Return a dictionary of dictionaries. The keys for the first dictionary will be the \ + interfaces in the devices. The inner dictionary will contain the following data for \ + each interface. + + * is_up (True/False) + * is_enabled (True/False) + * description (string) + * last_flapped (float in seconds) - NOT IMPLEMENTED (always -1.0) + * speed (int in Mbit) + * MTU (in Bytes) - NOT IMPLEMENTED (always -1) + * mac_address (string) + + Example:: + + { + u'Management1': + { + 'is_up': False, + 'is_enabled': False, + 'description': '', + 'last_flapped': -1.0, + 'speed': 1000, + 'mtu': 1500, + 'mac_address': 'FA:16:3E:57:33:61', + }, + u'Ethernet1': + { + 'is_up': True, + 'is_enabled': True, + 'description': 'foo', + 'last_flapped': 1429978575.1554043, + 'speed': 1000, + 'mtu': 1500, + 'mac_address': 'FA:16:3E:57:33:62', + }, + u'Ethernet2': + { + 'is_up': True, + 'is_enabled': True, + 'description': 'bla', + 'last_flapped': 1429978575.1555667, + 'speed': 1000, + 'mtu': 1500, + 'mac_address': 'FA:16:3E:57:33:63', + }, + u'Ethernet3': + { + 'is_up': False, + 'is_enabled': True, + 'description': 'bar', + 'last_flapped': -1.0, + 'speed': 1000, + 'mtu': 1500, + 'mac_address': 'FA:16:3E:57:33:64', } - cmd_post = self._apisession.post(url, json=data) + } + """ + ret = get_interfaces(self) - if not cmd_post.json()['failure_reason']: - check_url = url + '/status' - return self._transaction_status(check_url).json() + return ret - def get_mac_address_table(self): - """Get the mac-address table of the device.""" - url = self._api_url + 'mac-table' - resp = self._apisession.get(url) - if resp.status_code == 200: - table = [] - for entry in resp.json().get('mac_table_entry_element'): - item = {} - item['mac'] = self._mac_reformat(entry['mac_address']) - item['interface'] = entry['port_id'] - item['vlan'] = entry['vlan_id'] - item['active'] = True - """ Not supported: - item['static'] = False - item['moves'] = 0 - item['last_move'] = 0.0 - """ - table.append(item) - return table + def get_interfaces_counters(self): + """ + Get interfaces counters - NOT IMPLEMENTED. + + :return: + """ + return super(ArubaOSS, self).get_interfaces_counters() def get_interfaces_ip(self): - """Get IP interface IP addresses.""" - url = self._api_url + 'ipaddresses' - url = self._api_url + 'ipaddresses' - "Looks like there's a bug n ArubaOS and is not returning IPv6" - - resp = self._apisession.get(url) - if resp.status_code == 200: - output = {} - for address in resp.json().get('ip_address_subnet_element'): - iface_name = "VLAN" + str(address['vlan_id']) - if iface_name not in output.keys(): - output[iface_name] = {} - ip = IPNetwork("{}/{}".format( - address['ip_address']['octets'], - address['ip_mask']['octets'])) - version = 'ipv' + str(ip.version) - if version not in output[iface_name].keys(): - output[iface_name][version] = {} - output[iface_name][version][str(ip.ip)] = { - 'prefix_length': ip.prefixlen} - return output + """ + Get IP interface IP addresses. + + Looks like there's a bug on ArubaOS and is not returning IPv6 + + :return: + """ + ret = get_interfaces_ip(self=self) + + return ret + + def get_ipv6_neighbors_table(self): + """ + Get IPv6 neighbors table - NOT IMPLEMENTED. + + :return: + """ + return super(ArubaOSS, self).get_ipv6_neighbors_table() def get_lldp_neighbors(self): - """Get a list of LLDP neighbors.""" - url = self._api_url + '/lldp/remote-device' - resp = self._apisession.get(url) - log.debug("API returned {}".format(resp.status_code)) - if 300 > resp.status_code >= 200: - neighbor_table = {} - for neighbor in resp.json()['lldp_remote_device_element']: - port = neighbor['local_port'] - if not neighbor_table.get(port): - neighbor_table[port] = [] - remote_device = { - 'hostname': neighbor.get('system_name'), - 'port': neighbor.get('port_id') - } - neighbor_table[port].append(remote_device) - return neighbor_table - - def get_lldp_neighbors_detail(self): - """Get LLDP neighbor information.""" - url = self._api_url + '/lldp/remote-device' - resp = self._apisession.get(url) - log.debug("API returned {}".format(resp.status_code)) - if 300 > resp.status_code >= 200: - neighbor_table = {} - for neighbor in resp.json()['lldp_remote_device_element']: - port = neighbor['local_port'] - if not neighbor_table.get(port): - neighbor_table[port] = [] - remote_device = { - 'remote_system_name': neighbor.get('system_name'), - 'remote_chassis_id': neighbor.get('chassis_id'), - 'remote_port': neighbor.get('port_id'), - 'remote_port_description': - neighbor.get('port_description'), - 'remote_system_description': - ''.join(neighbor.get('system_description')), - 'remote_system_capab': - [k for k, v in neighbor.get( - 'capabilities_supported').items() if v is True], - 'remote_system_enable_capab': - [k for k, v in neighbor.get( - 'capabilities_enabled').items() if v is True] - } - neighbor_table[port].append(remote_device) - return neighbor_table + """ + Get a list of LLDP neighbors. + + :return: + """ + ret = get_lldp_neighbors(self=self) + + return ret + + def get_lldp_neighbors_detail(self, interface=""): + """ + Get LLDP neighbor information. + + NOTE: Parent Interface is always empty, + as the information isn't available. + + :param interface: + :return: + """ + ret = get_lldp_neighbors_detail(self=self, interface=interface) + + return ret + + def get_mac_address_table(self): + """ + Get the mac-address table of the device. + + "static", "moves" and "last_move" have always default values, + as there is no helpful information from the device. + + static: False, # not supported + moves: 0, # not supported + last_move: 0.0 # not supported + + :return: + """ + ret = get_mac_address_table(self=self) + + return ret + + def get_network_instances(self, name=""): + """ + Get network instances - NOT IMPLEMENTED. + + :param name: + :return: + """ + return super(ArubaOSS, self).get_network_instances() def get_ntp_peers(self): - """Get NTP peers.""" """ + Get NTP peers. + ArubaOS does not support NTP "peers", just upstream servers. This method is just an alias of get_ntp_servers() + + :return: """ - self.get_ntp_servers() + ret = get_ntp_servers(self=self) + + return ret def get_ntp_servers(self): - """Get NTP servers.""" - " TO-DO: add IPv6 support, currently getting 404 from the API" - url = self._api_url + 'config/ntp/server/ip4addr' - resp = self._apisession.get(url) - if resp.status_code == 200: - output = {} - for server in resp.json().get('ntpServerIp4addr_element'): - output[server['ip4addr']['ip4addr_value']] = {} - return output + """ + Get NTP servers. + + TO-DO: add IPv6 support, currently getting 404 from the API + + :return: + """ + ret = get_ntp_servers(self=self) + + return ret def get_ntp_stats(self): - """Get NTP peer statistics.""" - out = [] - associations = self.get_ntp_servers() - - for association in associations.keys(): - url = self._api_url + \ - 'monitoring/ntp/associations/detail/' + association - resp = self._apisession.get(url) - if resp.status_code == 200: - ntp_entry = {} - ntp_entry['remote'] = resp.json()['IP Address'] - ntp_entry['referenceid'] = resp.json()['Reference ID'] - - if resp.json()['Status'].find("Master") == -1: - ntp_entry['synchronized'] = False - else: - ntp_entry['synchronized'] = True - - ntp_entry['stratum'] = int(resp.json()['Stratum']) - ntp_entry['type'] = resp.json()['Peer Mode'] - ntp_entry['when'] = resp.json()['Origin Time'] - ntp_entry['hostpoll'] = int(resp.json()['Peer Poll Intvl']) - ntp_entry['reachability'] = int(resp.json()['Reach']) - ntp_entry['delay'] = \ - float(resp.json()['Root Delay'].split(' ')[0]) - ntp_entry['offset'] = \ - float(resp.json()['Offset'].split(' ')[0]) - ntp_entry['jitter'] = \ - float(resp.json()['Root Dispersion'].split(' ')[0]) - out.append(ntp_entry) - return out + """ + Get NTP peer statistics. + + :return: + """ + ret = get_ntp_stats(self=self) + + return ret def get_optics(self): - """Transceiver output/input readings. We need to parse CLI.""" - """ CMDs: + """ + Transceiver output/input readings. We need to parse CLI. + + CMDs: - show interfaces transceiver detail + + :return: + """ + return super(ArubaOSS, self).get_optics() + + def get_probes_config(self): + """ + Get probes config - NOT IMPLEMENTED. + + :return: + """ + return super(ArubaOSS, self).get_probes_config() + + def get_probes_results(self): + """ + Get probes results - NOT IMPLEMENTED. + + :return: + """ + return super(ArubaOSS, self).get_probes_results() + + def get_route_to(self, destination="", protocol="", longer=False): + """ + Get route to destination. + + :param destination: + :param protocol: + :param longer: + :return: + """ + ret = get_route_to( + self=self, + destination=destination, + protocol=protocol + ) + + return ret + + def get_snmp_information(self): + """ + Get SNMP information - NOT IMPLEMENTED. + + :return: + """ + return super(ArubaOSS, self).get_snmp_information() + + def get_users(self): + """ + Get users - NOT IMPLEMENTED. + + :return: + """ + return super(ArubaOSS, self).get_users() + + def has_pending_commit(self): + """ + Boolean indicates if a commit_config that needs confirmed is in process. + + :return Boolean + """ + return has_pending_commit(self=self) + + def is_alive(self): """ - return super().get_optics() - - def get_route_to(self, destination='', protocol=''): - """Get active route for a given destination.""" - v4_table = [] - v6_table = [] - if destination != '': - ip_address = IPNetwork(destination) - if ip_address.version == 4: - raw_v4_table = self._run_cmd( - "show ip route {} {}".format(protocol, ip_address.ip)) - v4_table = textfsm_extractor( - self, "show_ip_route", raw_v4_table) - elif ip_address.version == 6: - raw_v6_table = self._run_cmd( - "show ipv6 route {} {}".format(protocol, ip_address.ip)) - v6_table = textfsm_extractor( - self, "show_ipv6_route", raw_v6_table) - else: - raw_v4_table = self._run_cmd( - "show ip route {} {}".format(protocol, destination)) - v4_table = textfsm_extractor( - self, "show_ip_route", raw_v4_table) - raw_v6_table = self._run_cmd( - "show ipv6 route {} {}".format(protocol, destination)) - v6_table = textfsm_extractor(self, "show_ipv6_route", raw_v6_table) - route_table = v4_table + v6_table - - out = {} - for route in route_table: - if not out.get(route['destination']): - out[route['destination']] = [] - new_path = {} - new_path['protocol'] = route['type'] - new_path['preference'] = int(route['distance']) - new_path['next_hop'] = route['gateway'] - out[route['destination']].append(new_path) - return out - - def _run_cmd(self, cmd): - url = self._api_url + 'cli' - data = {} - data['cmd'] = cmd - cmd_post = self._apisession.post(url, json=data) - if cmd_post.status_code == 200: - return base64.b64decode( - cmd_post.json()['result_base64_encoded']).decode('utf-8') - else: - raise CommandErrorException("Parsing CLI commands failed") - - def _config_batch(self, cmd_list): - url = self._api_url + 'cli_batch' - data = {} - data['cli_batch_base64_encoded'] = ArubaOSS._str_to_b64( - '\n'.join(cmd_list)) - batch_run = self._apisession.post(url, json=data) - if batch_run.status_code == 202: - check_status = self._apisession.get(url + "/status") - if check_status.status_code == 200: - for cmd_status in check_status.json()['cmd_exec_logs']: - if cmd_status['status'] != "CCS_SUCCESS": - log.debug("command failed to execute with error \ - {}".format(cmd_status['result'])) - return False - else: - return True - return True - else: - log.debug("Failed to paste commands") - return False - - def _backup_config(self, config='running', destination='backup'): - """Backup config.""" - """Supported configs - API: - - "CT_RUNNING_CONFIG", - - "CT_STARTUP_CONFIG" - """ - url = self._api_url + 'system/config/cfg_backup_files' - payload = {} - if destination == 'backup': - payload['file_name'] = 'backup_{}'.format(config) - elif destination == 'REST_Payload_Backup': - """ - Discard running config by copying running to candidate - """ - payload['file_name'] = 'REST_Payload_Backup' - - if config == 'running': - payload['config_type'] = 'CT_RUNNING_CONFIG' - elif config == 'startup': - payload['config_type'] = 'CT_STARTUP_CONFIG' - else: - "unsupported argument; raise error" - return False - cmd_post = self._apisession.post(url, json=payload) - if not 300 > cmd_post.status_code >= 200: - "raise error" - pass - else: - return cmd_post.json() + Is alive method. + + :return: + """ + ret = is_alive(self=self) + + return ret + + def load_merge_candidate(self, filename=None, config=None): + """ + Merge candidate configuration with the running one. + + Imperative config change: + Merge new config with existing one. There's no config validation + nor atomic commit!. Only configuration commands are supported, + "configure terminal" is not required. Use with caution. + + :param filename: + :param config: + :return: + """ + ret = load_merge_candidate( + self=self, filename=filename, config=config + ) + + return ret + + def load_replace_candidate(self, filename=None, config=None): + """ + Replace running config with the candidate. + + Implentation of napalm module load_replace_candidate() + ArubaOS-Switch supports payload_type options: + - "RPT_PATCH_FILE" -> not implemented + - "RPT_BACKUP_FILE" -> Implemented + + Note: the maximum content_length = 16072, + "HTTP/1.1 413 Request Entity Too Large" is returned above that!!! + + :param filename: + :param config: + :return: + """ + ret = load_replace_candidate( + self=self, filename=filename, config=config + ) + + return ret + + def load_template( + self, template_name, template_source=None, template_path=None, **template_vars + ): + """ + Load template - NOT IMPLEMENTED. + + :param template_name: + :param template_source: + :param template_path: + :param template_vars: + :return: + """ + return super(ArubaOSS, self).load_template() + + def open(self): + """ + Open connection to the network device. + + :return: + """ + self.connection.login( + hostname=self.hostname, + username=self.username, + password=self.password, + timeout=self.timeout, + optional_args=self.optional_args, + ) + + return True + + def ping( + self, + destination, + source="", + ttl=255, + timeout=2, + size=100, + count=5, + vrf="", + source_interface="" + ): + """ + Execute ping on the device and returns a dictionary with the result. + + :param destination: needed argument + :param source: not implemented as not available from device + :param ttl: not implemented as not available from device + :param timeout: Maximum seconds to wait after sending final packet + :param vrf: not implemented as not available from device + :param size: not implemented as not available from device + :param count: not implemented as not available from device + :param source_interface: not implemented as not available from device + :return: returns a dictionary containing the hops and probes + """ + ret = ping(self=self, destination=destination, timeout=timeout) + return ret + + def post_connection_tests(self): + """ + Post connection tests - NOT IMPLEMENTED. + + :return: + """ + return super(ArubaOSS, self).post_connection_tests() + + def pre_connection_tests(self): + """ + Pre connection tests - NOT IMPLEMENTED. + + :return: + """ + return super(ArubaOSS, self).pre_connection_tests() def rollback(self): - """Rollback configuration.""" - diff = self.compare_config() - if diff != '' and isinstance(diff, dict): - if not (len(diff.get('diff_add_list')) - and len(diff.get('diff_remove_list'))): - self._commit_candidate(config='backup_running') - return True - else: - return False + """ + Rollback configuration. - def close(self): - """Close device connection and delete sessioncookie.""" - rest_logout = self._apisession.delete(self._login_url) - self._headers['cookie'] = '' - - if rest_logout.status_code != 204: - log.debug("Logout Failed") - else: - return "logout ok" + :return: + """ + ret = rollback(self=self) + + return ret + + def traceroute(self, destination, source="", ttl=255, timeout=2, vrf=""): + """ + Execute traceroute on the device. + + :param destination: needed argument + :param source: not implemented as not available from device + :param ttl: not implemented as not available from device + :param timeout: not implemented as not available from device + :param vrf: not implemented as not available from device + :return: returns a dictionary containing the hops and probes + """ + ret = traceroute(self=self, destination=destination) + + return ret diff --git a/napalm_arubaoss/helper/__init__.py b/napalm_arubaoss/helper/__init__.py new file mode 100644 index 0000000..2b58398 --- /dev/null +++ b/napalm_arubaoss/helper/__init__.py @@ -0,0 +1,65 @@ +"""Import all functions of this directory.""" + +from napalm_arubaoss.helper.base import Connection +from napalm_arubaoss.helper.commit_config import commit_config +from napalm_arubaoss.helper.compare_config import compare_config +from napalm_arubaoss.helper.confirm_commit import confirm_commit +from napalm_arubaoss.helper.get_arp_table import get_arp_table +from napalm_arubaoss.helper.get_config import get_config +from napalm_arubaoss.helper.get_facts import get_facts +from napalm_arubaoss.helper.get_interfaces import get_interfaces +from napalm_arubaoss.helper.get_interfaces_ip import get_interfaces_ip +from napalm_arubaoss.helper.get_lldp_neighbors import get_lldp_neighbors +from napalm_arubaoss.helper.get_lldp_neighbors_detail import get_lldp_neighbors_detail +from napalm_arubaoss.helper.get_mac_address_table import get_mac_address_table +from napalm_arubaoss.helper.get_ntp_servers import get_ntp_servers +from napalm_arubaoss.helper.get_ntp_stats import get_ntp_stats +from napalm_arubaoss.helper.get_route_to import get_route_to +from napalm_arubaoss.helper.has_pending_commit import has_pending_commit +from napalm_arubaoss.helper.is_alive import is_alive +from napalm_arubaoss.helper.load_merge_candidate import load_merge_candidate +from napalm_arubaoss.helper.load_replace_candidate import load_replace_candidate +from napalm_arubaoss.helper.ping import ping +from napalm_arubaoss.helper.rollback import rollback +from napalm_arubaoss.helper.traceroute import traceroute +from napalm_arubaoss.helper.utils import ( + backup_config, + mac_reformat, + commit_candidate, + config_batch, + read_candidate, + str_to_b64, + transaction_status, +) + +__all__ = ( + "Connection", + "backup_config", + "commit_candidate", + "commit_config", + "compare_config", + "config_batch", + "confirm_commit", + "get_mac_address_table", + "get_facts", + "get_arp_table", + "get_config", + "get_interfaces", + "get_interfaces_ip", + "get_lldp_neighbors", + "get_lldp_neighbors_detail", + "get_ntp_stats", + "get_ntp_servers", + "get_route_to", + "has_pending_commit", + "is_alive", + "load_merge_candidate", + "load_replace_candidate", + "mac_reformat", + "ping", + "read_candidate", + "rollback", + "str_to_b64", + "traceroute", + "transaction_status", +) diff --git a/napalm_arubaoss/helper/base.py b/napalm_arubaoss/helper/base.py new file mode 100644 index 0000000..f4621e9 --- /dev/null +++ b/napalm_arubaoss/helper/base.py @@ -0,0 +1,237 @@ +"""Create the Session.""" + + +import base64 +import logging + +from json import JSONDecodeError + +from requests import Session +from requests.models import Response +from napalm.base.exceptions import ConnectAuthError, NapalmException + + +logger = logging.getLogger("arubaoss.helper.base") + + +class KeepAliveBoolError(NapalmException): + pass + + +class Connection: + """Connection class.""" + + config = {"api_url": ""} + + def __init__(self): + """Initialize the class.""" + self._apisession: Session = Session() + + self.hostname = "" + self.username = "" + self.password = "" + self.timeout = 10 + self.api = "v6" + self.proto = "https" + + self.cli_output = {} + + def login(self, hostname, username="", password="", timeout=10, optional_args=None): + """ + Login to the Rest-API. + + :param hostname: + :param username: + :param password: + :param timeout: + :param optional_args: + :return: + """ + logger.debug("logging in") + self.hostname = hostname + self.username = username + self.password = password + self.timeout = timeout + + self.api = optional_args.get("api", "v6") + + if not optional_args: + optional_args = {} + + self.proto = "https" if optional_args.get("ssl", True) else "http" + + self.config["api_url"] = "{}://{}/rest/{}/".format( + self.proto, self.hostname, self.api + ) + + url = self.config["api_url"] + "login-sessions" + + self._apisession = Session() + self._apisession.verify = optional_args.get("ssl_verify", True) + self._apisession.headers = { + "Content-Type": "application/json", + } + + keep_alive = optional_args.get( + "keepalive", + optional_args.get( + "keep_alive", + False + ) + ) + + if not isinstance(keep_alive, bool): + raise KeepAliveBoolError( + "\"keepalive\"/\"keep_alive\" needs to be of type \"bool\"" + ) + + if not keep_alive: + self._apisession.headers.update( + {"Connection": "close"} + ) + + params = {"userName": self.username, "password": self.password} + + rest_login = self.post(url, json=params, timeout=self.timeout) + + if not rest_login.status_code == 201: + raise ConnectAuthError("Login failed") + + session = rest_login.json() + self._apisession.headers["cookie"] = session["cookie"] + + def logout(self): + """Close device connection and delete sessioncookie.""" + url = self.config["api_url"] + "login-sessions" + + rest_logout = self.delete(url, timeout=self.timeout) + self._apisession.headers["cookie"] = "" + + if not rest_logout.status_code == 204: + logger.debug("Logout Failed") + else: + self._apisession.close() + return "logout ok" + + def get(self, *args, **kwargs) -> Response: + """ + Call a single command (Helper-Function). + + :param args: + :param kwargs: + :return: + """ + ret = self._apisession.get(*args, **kwargs) + + return ret + + def post(self, *args, **kwargs) -> Response: + """ + Call a single command (Helper-Function). + + :param args: + :param kwargs: + :return: + """ + ret = self._apisession.post(*args, **kwargs) + + return ret + + def put(self, *args, **kwargs) -> Response: + """ + Call a single command (Helper-Function). + + :param args: + :param kwargs: + :return: + """ + ret = self._apisession.put(*args, **kwargs) + + return ret + + def delete(self, *args, **kwargs) -> Response: + """ + Call a single command (Helper-Function). + + :param args: + :param kwargs: + :return: + """ + ret = self._apisession.delete(*args, **kwargs) + + return ret + + def cli(self, commands): + """ + Run CLI commands through the REST API. + + :param commands: + :return: + """ + self.cli_output = {} + + url = self.config["api_url"] + "cli" + + if not isinstance(commands, list): + self.cli_output["error"] = "Provide a list of commands" + return self.cli_output + + for command in commands: + self._apisession.post( + url=url, + json={"cmd": command}, + timeout=self.timeout, + hooks={ + "response": self._callback( + output=self.cli_output, + command=command + ) + } + ) + + return self.cli_output + + def _callback(self, *args, **kwargs): + """ + Return Callback for request calls. + + ArubaOSS.cli uses it. + + :param args: + :param kwargs: + :return: callback function + """ + + def callback(call, *cargs, **ckwargs): + cli_output = kwargs.get("output") + passed_cmd = kwargs.get("command") + try: + json_ret = call.json() + except JSONDecodeError: + json_ret = {} + + cmd = json_ret.get("cmd") + result_base64 = json_ret.get("result_base64_encoded", "") + + if not cmd == passed_cmd: + cli_output[passed_cmd] = "cmd not found in output" + return + + if not result_base64: + cli_output[passed_cmd] = "no result found in output" + return + + result = base64.b64decode(result_base64).decode("utf-8") + cli_output[passed_cmd] = result + + return callback + + def run_cmd(self, cmd): + """ + Run the command on the device and return the raw output. + + :param cmd: + :return: + """ + ret = self.cli([cmd]) + return ret[cmd] diff --git a/napalm_arubaoss/helper/commit_config.py b/napalm_arubaoss/helper/commit_config.py new file mode 100644 index 0000000..73e3b86 --- /dev/null +++ b/napalm_arubaoss/helper/commit_config.py @@ -0,0 +1,60 @@ +"""Backups and commit the configuration, and handles commit confirm.""" + +import logging + +from napalm.base.exceptions import CommitError + +from napalm_arubaoss.helper.utils import backup_config, commit_candidate +from napalm_arubaoss.helper.get_config import get_config +from napalm_arubaoss.helper.load_replace_candidate import load_replace_candidate +from napalm_arubaoss.helper.has_pending_commit import has_pending_commit + +logger = logging.getLogger("arubaoss.helper.commit_config") + + +def commit_config(self, message="", revert_in=None): + """ + Backups and commit the configuration, and handles commit confirm. + + :param self: object from class + :param message: Optional - configuration session commit message + :type message: str + :param revert_in: Optional - number of seconds before the configuration + will be rolled back using a commit confirm mechanism. + :type revert_in: int|None + """ + if message: + msg = "\"message\" support has not been added " \ + "for this getter on this platform." + raise NotImplementedError(msg) + + if not revert_in: + revert_in = 0 + + if not type(revert_in) == int: + err_msg = "Invalid \"revert_in\" value, "\ + "commit confirn cannot be carried out" + logger.error(err_msg) + raise TypeError(err_msg) + + if has_pending_commit(self=self): + raise CommitError("Pending commit confirm already in process!") + + backup_config(self=self) + + logger.debug('Confirm rollback time is {}'.format(str(revert_in))) + if revert_in > 0: + candidate = get_config( + self=self, + retrieve='candidate' + )['candidate'] + candidate = candidate[:-2] # remove unneeded chars + + candidate_confirm = ( + f"{candidate}" + f"job ROLLBACK delay {str(revert_in)} " + "\"cfg-restore flash backup_running\"\n" + ) + load_replace_candidate(self=self, config=candidate_confirm) + + commit_candidate(self=self, config="REST_Payload_Backup") diff --git a/napalm_arubaoss/helper/compare_config.py b/napalm_arubaoss/helper/compare_config.py new file mode 100644 index 0000000..82d37ac --- /dev/null +++ b/napalm_arubaoss/helper/compare_config.py @@ -0,0 +1,52 @@ +"""Backups and commit the configuration, and handles commit confirm.""" + +import logging + +from time import sleep + +from napalm.base.exceptions import CommandErrorException + +logger = logging.getLogger("arubaoss.helper.compare_config") + + +def compare_config(self): + """ + Compare the running config with the candidate one. + + :param self: object from class + :return: + """ + url = self.connection.config["api_url"] + "system/config/cfg_restore/latest_diff" + check_url = url + "/status" + data = { + "server_type": "ST_FLASH", + "file_name": "REST_Payload_Backup", + "is_oobm": False, + } + # trigger configuration comparison + diff = self.connection.post(url, json=data) + + if not diff.ok: + raise CommandErrorException("diff generation failed, raise status") + + for loop_round in range(1, 6): + # wait a second to give the device time to process + logger.debug(f"loop round \"{loop_round}\"") + sleep(1) + + diff_output = self.connection.get(check_url) + + if not diff_output.status_code == 200: + raise CommandErrorException("diff generation failed, raise status") + + if ( + not diff_output.json()["diff_add_list"] + and not diff_output.json()["diff_remove_list"] + ): + if loop_round == 5: + # return empty string to signal the candidate + # and running configs are the same + return "" + continue + else: + return diff_output.json() diff --git a/napalm_arubaoss/helper/confirm_commit.py b/napalm_arubaoss/helper/confirm_commit.py new file mode 100644 index 0000000..2862203 --- /dev/null +++ b/napalm_arubaoss/helper/confirm_commit.py @@ -0,0 +1,23 @@ +"""Confirm the changes requested via commit_config when `type(revert_in)=int`.""" + +import logging + +from napalm_arubaoss.helper.commit_config import commit_config +from napalm_arubaoss.helper.has_pending_commit import has_pending_commit +from napalm_arubaoss.helper.load_merge_candidate import load_merge_candidate + +logger = logging.getLogger('arubaoss.helper.confirm_commit') + + +def confirm_commit(self): + """ + Confirm the changes requested via commit_config when `type(revert_in)=int`. + + :param self: object from class + :return: + """ + if has_pending_commit(self=self): + load_merge_candidate(self=self, config="no job ROLLBACK") + ret = commit_config(self=self) + + return ret diff --git a/napalm_arubaoss/helper/get_arp_table.py b/napalm_arubaoss/helper/get_arp_table.py new file mode 100644 index 0000000..f86d265 --- /dev/null +++ b/napalm_arubaoss/helper/get_arp_table.py @@ -0,0 +1,32 @@ +"""Backups and commit the configuration, and handles commit confirm.""" + +from napalm.base.helpers import textfsm_extractor +import logging + +from napalm_arubaoss.helper.utils import mac_reformat + +logger = logging.getLogger("arubaoss.helper.get_arp_table") + + +def get_arp_table(self, vrf): + """ + Get device's ARP table. + + :param self: object from class + :param vrf: not supported + :return: + """ + if vrf: + msg = "VRF support has not been added " \ + "for this getter on this platform." + raise NotImplementedError(msg) + + raw_arp = self.connection.run_cmd("show arp") + arp_table = textfsm_extractor(self, "show_arp", raw_arp) + for arp in arp_table: + arp["interface"] = arp.pop("port") + arp["mac"] = mac_reformat(arp["mac"]) + arp["age"] = -1.00 # needs to be a float - -1.00 to signal "N/A" + arp.pop("type") # pop because it is not present in the napalm model + + return arp_table diff --git a/napalm_arubaoss/helper/get_config.py b/napalm_arubaoss/helper/get_config.py new file mode 100644 index 0000000..e4dc113 --- /dev/null +++ b/napalm_arubaoss/helper/get_config.py @@ -0,0 +1,45 @@ +"""Get configuration stored on the device.""" + +import logging + +logger = logging.getLogger("arubaoss.helper.get_config") + + +def get_config(self, retrieve="all", full=False): + """ + Get configuration stored on the device. + + :param self: object from class + :param retrieve: + :param full: + + :return: + """ + if full: + msg = "\"full\" is not available " \ + "for this getter on this platform." + raise NotImplementedError(msg) + + out = {"startup": "", "candidate": "", "running": ""} + + cmd_mapping = { + "display saved-configuration": "startup", + "show config REST_Payload_Backup": "candidate", + "show running-config": "running", + } + cmd_mapping = ( + {key: value for key, value in cmd_mapping.items() if retrieve == value} + if not retrieve == "all" + else cmd_mapping + ) + + outputs = self.connection.cli( + [ + cmd for cmd, config in cmd_mapping.items() + ] + ) + + for okey, ovalue in outputs.items(): + out[cmd_mapping[okey]] = ovalue + + return out diff --git a/napalm_arubaoss/helper/get_facts.py b/napalm_arubaoss/helper/get_facts.py new file mode 100644 index 0000000..3635234 --- /dev/null +++ b/napalm_arubaoss/helper/get_facts.py @@ -0,0 +1,92 @@ +"""Get general device information.""" + +import logging + +logger = logging.getLogger("arubaoss.helper.get_facts") + + +def get_facts(self): + """ + Get general device information. + + :param self: object from class + :return: + """ + url = "{base_url}{endpoint}" + + system_status_url = url.format( + base_url=self.connection.config["api_url"], + endpoint="system/status" + ) + switch_status_url = url.format( + base_url=self.connection.config["api_url"], + endpoint="system/status/switch" + ) + dns_url = url.format( + base_url=self.connection.config["api_url"], + endpoint="dns" + ) + + out = { + "uptime": -1, + "vendor": "HPE Aruba", + "model": "", + "hostname": "", + "fqdn": "", + "os_version": "", + "serial_number": "", + "interface_list": [], + + } + + call = self.connection.get(system_status_url) + + # If it's a Stack, use `/system/status/global_info` + if call.status_code == 404: + system_status_url = url.format( + base_url=self.connection.config["api_url"], + endpoint="system/status/global_info" + ) + call = self.connection.get(system_status_url) + + if call.ok: + rest_out = call.json() + out["hostname"] = rest_out.get("name", "") + out["os_version"] = rest_out.get("firmware_version", "") + out["serial_number"] = rest_out.get("serial_number", "") + out["model"] = rest_out.get("product_model", "") + + # get domain name to generate the FQDN + call = self.connection.get(dns_url) + if call.ok: + rest_out = call.json() + # return "{{hostname}}." if no domain is configured + domain_names = rest_out.get("dns_domain_names") + domain = ".{}".format(domain_names[0]) if domain_names else "." + out["fqdn"] = "{hostname}{domain}".format( + hostname=out["hostname"], + domain=domain + ) + + # Get interface list + call = self.connection.get(switch_status_url) + if call.ok: + rest_out = call.json() + if rest_out.get("switch_type", "ST_STANDALONE") == "ST_STACKED": + serial_url = url.format( + base_url=self.connection.config["api_url"], + endpoint="system/status/members/1" + ) + call = self.connection.get(serial_url) + + if call.ok: + out["serial_number"] = call.json().get("serial_number", "") + out["model"] = call.json().get("product_model", "") + + for blade in rest_out.get("blades", []): + for ports in blade.get("data_ports", []): + out["interface_list"].append( + ports.get("port_name", "") + ) + + return out diff --git a/napalm_arubaoss/helper/get_interfaces.py b/napalm_arubaoss/helper/get_interfaces.py new file mode 100644 index 0000000..0949f1a --- /dev/null +++ b/napalm_arubaoss/helper/get_interfaces.py @@ -0,0 +1,74 @@ +"""Get the interfaces of the device.""" + +import logging + +logger = logging.getLogger("arubaoss.helper.get_interfaces") + + +def get_interfaces(self): + """Get IP interface IP addresses.""" + url_ports = self.connection.config["api_url"] + "ports" + url_port_stats = self.connection.config["api_url"] + "port-statistics" + + interface_template = { + 'is_up': False, + 'is_enabled': False, + 'description': '', + 'last_flapped': -1.0, + 'speed': 1000, + 'mtu': -1, + 'mac_address': 'FA:16:3E:57:33:61', + } + output = {} + + resp_ports = self.connection.get(url_ports) + resp_port_stats = self.connection.get(url_port_stats) + + if not resp_ports.status_code == 200: + logger.error("didn't get status code 200 from %s", url_ports) + return output + + if not resp_port_stats.status_code == 200: + logger.error("didn't get status code 200 from %s", url_port_stats) + return output + + resp_ports_json = resp_ports.json() + for interface in resp_ports_json.get("port_element", []): + # show interfaces 1 | include MAC[[:space:]]Address + i_id = interface.get("id") + description = interface.get("name") + is_up = interface.get("is_port_up") + is_enabled = interface.get("is_port_enabled") + + if i_id not in output.keys(): + output[i_id] = interface_template.copy() + + output[i_id]["description"] = description + output[i_id]["is_up"] = is_up + output[i_id]["is_enabled"] = is_enabled + + resp_port_stats_json = resp_port_stats.json() + for interface_stats in resp_port_stats_json.get("port_statistics_element", []): + i_id = interface_stats.get("id") + speed = interface_stats.get("port_speed_mbps") + + if i_id not in output.keys(): + output[i_id] = interface_template.copy() + + output[i_id]["speed"] = speed + + for interface_id, interface_values in output.items(): + resp = self.connection.run_cmd( + f"show interfaces {interface_id} | include MAC[[:space:]]Address" + ) + + resp = resp.replace(" ", "") + resp = resp.split(":") + mac_raw = resp[1] + mac_raw = mac_raw.replace("-", "") + mac = ':'.join(mac_raw[i:i+2] for i in range(0, 12, 2)) + mac = mac.upper() + + output[interface_id]["mac_address"] = mac + + return output diff --git a/napalm_arubaoss/helper/get_interfaces_ip.py b/napalm_arubaoss/helper/get_interfaces_ip.py new file mode 100644 index 0000000..94d15b6 --- /dev/null +++ b/napalm_arubaoss/helper/get_interfaces_ip.py @@ -0,0 +1,48 @@ +"""Get IP interface IP addresses.""" + +from netaddr import IPNetwork +import logging + +logger = logging.getLogger("arubaoss.helper.get_interfaces_ip") + + +def get_interfaces_ip(self): + """ + Get IP interface IP addresses. + + !!! Looks like there's a bug n ArubaOS and is not returning IPv6 + + :param self: object from class + :return: + """ + url = self.connection.config["api_url"] + "ipaddresses" + output = {} + resp = self.connection.get(url) + if resp.status_code == 200: + for address in resp.json().get("ip_address_subnet_element", []): + vlan_id = address.get("vlan_id", "") + iface_name = "VLAN{vlan_id}".format(vlan_id=str(vlan_id)) + + if iface_name not in output.keys(): + output[iface_name] = {} + + ip_address = address.get("ip_address", {}).get("octets") + ip_mask = address.get("ip_mask", {}).get("octets") + + if ip_address and ip_mask: + ip = IPNetwork( + "{ip_address}/{ip_mask}".format( + ip_address=ip_address, + ip_mask=ip_mask + ) + ) + + version = "ipv{ip_version}".format(ip_version=str(ip.version)) + + if version not in output[iface_name].keys(): + output[iface_name][version] = {} + output[iface_name][version][str(ip.ip)] = { + "prefix_length": ip.prefixlen + } + + return output diff --git a/napalm_arubaoss/helper/get_lldp_neighbors.py b/napalm_arubaoss/helper/get_lldp_neighbors.py new file mode 100644 index 0000000..9a3f622 --- /dev/null +++ b/napalm_arubaoss/helper/get_lldp_neighbors.py @@ -0,0 +1,31 @@ +"""Get a list of LLDP neighbors.""" + +import logging + +logger = logging.getLogger("arubaoss.helper.get_lldp_neighbors") + + +def get_lldp_neighbors(self): + """ + Get a list of LLDP neighbors. + + :param self: object from class + :return: + """ + url = self.connection.config["api_url"] + "lldp/remote-device" + resp = self.connection.get(url) + logger.debug("API returned {}".format(resp.status_code)) + + if resp.ok: + neighbor_table = {} + for neighbor in resp.json()["lldp_remote_device_element"]: + port = neighbor["local_port"] + if not neighbor_table.get(port): + neighbor_table[port] = [] + remote_device = { + "hostname": neighbor.get("system_name"), + "port": neighbor.get("port_id"), + } + neighbor_table[port].append(remote_device) + + return neighbor_table diff --git a/napalm_arubaoss/helper/get_lldp_neighbors_detail.py b/napalm_arubaoss/helper/get_lldp_neighbors_detail.py new file mode 100644 index 0000000..e4b399e --- /dev/null +++ b/napalm_arubaoss/helper/get_lldp_neighbors_detail.py @@ -0,0 +1,49 @@ +"""Get LLDP neighbor information.""" + +import logging + +logger = logging.getLogger("arubaoss.helper.get_lldp_neighbors_detail") + + +def get_lldp_neighbors_detail(self, *args, **kwargs): + """ + Get LLDP neighbor information. + + :param self: object from class + :param args: + :param kwargs: + :return: + """ + url = self.connection.config["api_url"] + "lldp/remote-device" + resp = self.connection.get(url) + logger.debug("API returned {}".format(resp.status_code)) + + if resp.ok: + neighbor_table = {} + for neighbor in resp.json()["lldp_remote_device_element"]: + port = neighbor["local_port"] + if not neighbor_table.get(port): + neighbor_table[port] = [] + remote_device = { + "parent_interface": "", + "remote_system_name": neighbor.get("system_name"), + "remote_chassis_id": neighbor.get("chassis_id"), + "remote_port": neighbor.get("port_id"), + "remote_port_description": neighbor.get("port_description"), + "remote_system_description": "".join( + neighbor.get("system_description") + ), + "remote_system_capab": [ + k + for k, v in neighbor.get("capabilities_supported").items() + if v is True + ], + "remote_system_enable_capab": [ + k + for k, v in neighbor.get("capabilities_enabled").items() + if v is True + ], + } + neighbor_table[port].append(remote_device) + + return neighbor_table diff --git a/napalm_arubaoss/helper/get_mac_address_table.py b/napalm_arubaoss/helper/get_mac_address_table.py new file mode 100644 index 0000000..131540b --- /dev/null +++ b/napalm_arubaoss/helper/get_mac_address_table.py @@ -0,0 +1,33 @@ +"""Get the mac-address table of the device.""" + +import logging + +from napalm_arubaoss.helper.utils import mac_reformat + +logger = logging.getLogger("arubaoss.helper.get_mac_address_table") + + +def get_mac_address_table(self): + """ + Get the mac-address table of the device. + + :param self: object from class + :return: + """ + url = self.connection.config["api_url"] + "mac-table" + resp = self.connection.get(url) + if resp.status_code == 200: + table = [] + for entry in resp.json().get("mac_table_entry_element"): + item = { + "mac": mac_reformat(entry["mac_address"]), + "interface": entry["port_id"], + "vlan": entry["vlan_id"], + "active": True, + "static": False, # not supported + "moves": 0, # not supported + "last_move": 0.0 # not supported + } + table.append(item) + + return table diff --git a/napalm_arubaoss/helper/get_ntp_servers.py b/napalm_arubaoss/helper/get_ntp_servers.py new file mode 100644 index 0000000..334448e --- /dev/null +++ b/napalm_arubaoss/helper/get_ntp_servers.py @@ -0,0 +1,34 @@ +"""Get NTP servers.""" + +import logging + +logger = logging.getLogger("arubaoss.helper.get_ntp_servers") + + +def get_ntp_servers(self): + """ + Get NTP servers. + + # TODO: add IPv6 support, currently getting 404 from the API + + :param self: object from class + :return: + """ + base_url = self.connection.config["api_url"] + ipv4_url = f"{base_url}config/ntp/server/ip4addr" + name_url = f"{base_url}config/ntp/server-name/ASCII-STR" + + ipv4_resp = self.connection.get(ipv4_url) + name_resp = self.connection.get(name_url) + + output = {} + + if ipv4_resp.status_code == 200: + for server in ipv4_resp.json().get("ntpServerIp4addr_element"): + output[server["ip4addr"]["ip4addr_value"]] = {} + + if name_resp.status_code == 200: + for server in name_resp.json().get("ntpServerNameASCIISTR_element"): + output[server["ASCII-STR"]["ASCII-STR_value"]] = {} + + return output diff --git a/napalm_arubaoss/helper/get_ntp_stats.py b/napalm_arubaoss/helper/get_ntp_stats.py new file mode 100644 index 0000000..576f760 --- /dev/null +++ b/napalm_arubaoss/helper/get_ntp_stats.py @@ -0,0 +1,78 @@ +"""Get NTP peer statistics.""" + +import logging + +logger = logging.getLogger("arubaoss.helper.get_ntp_stats") + + +def get_ntp_stats(self): + """ + Get NTP peer statistics. + + :param self: object from class + :return: + """ + out = [] + base_url = self.connection.config["api_url"] + ret = self.connection.get( + f"{base_url}monitoring/ntp/servers" + ) + + ret_json = ret.json() if hasattr(ret, "json") else {} + + ntp_ips = [ + address.get("Server address") + for address in ret_json.get("NTP_Server_Address_Information", []) + ] + + for association in ntp_ips: + url = f"{base_url}monitoring/ntp/associations/detail/{association}" + + resp = self.connection.get(url) + if resp.status_code == 200: + data = resp.json() if hasattr(resp, "json") else {} + + ntp_entry = _create_ntp_entry(data) + + if ntp_entry: + out.append(ntp_entry) + + if not ntp_ips: + # assumes no IPs have been configured but a name + url = f"{base_url}monitoring/ntp/associations/detail" + resp = self.connection.get(url) + + if resp.status_code == 200: + data = resp.json() if hasattr(resp, "json") else {} + + ntp_entry = _create_ntp_entry(data) + + if ntp_entry: + out.append(ntp_entry) + + return out + + +def _create_ntp_entry(data): + if not data: + return None + + ntp_entry = { + "remote": data.get("IP Address", ""), + "referenceid": data.get("Reference ID", ""), + "stratum": int(data.get("Stratum", 0)), + "type": data.get("Peer Mode", ""), + "when": data.get("Origin Time", ""), + "hostpoll": int(data.get("Peer Poll Intvl", 0)), + "reachability": int(data.get("Reach", 0)), + "delay": float(data.get("Root Delay", "").split(" ")[0]), + "offset": float(data.get("Offset", "").split(" ")[0]), + "jitter": float(data.get("Root Dispersion", "").split(" ")[0]), + } + + if data.get("Status").find("Master") == -1: + ntp_entry["synchronized"] = False + else: + ntp_entry["synchronized"] = True + + return ntp_entry diff --git a/napalm_arubaoss/helper/get_route_to.py b/napalm_arubaoss/helper/get_route_to.py new file mode 100644 index 0000000..2547022 --- /dev/null +++ b/napalm_arubaoss/helper/get_route_to.py @@ -0,0 +1,106 @@ +"""Get route to destination.""" + +from napalm.base.helpers import textfsm_extractor +from netaddr import IPNetwork +import logging + + +logger = logging.getLogger("arubaoss.helper.get_route_to") + + +def get_route_to(self, destination="", protocol=""): + """ + Get route to destination. + + :param self: object from class + :param destination: + :param protocol: + :return: + """ + inner_dictionary = { + "protocol": "", + "current_active": True, + "last_active": True, + "age": -1, + "next_hop": "", + "outgoing_interface": "", + "selected_next_hop": True, + "preference": -1, + "inactive_reason": "", + "routing_table": "", + "protocol_attributes": {} + } + + bgp_dictionary = { + "local_as": -1, + "remote_as": -1, + "peer_id": "", + "as_path": "", + "communities": -1, + "local_preference": -1, + "preference2": -1, + "metric": -1, + "metric2": -1 + } + + isis_dictionary = { + "level": -1 + } + + if destination: + ip_address = IPNetwork(destination) + + cmds = { + 4: { + "template": "show_ip_route", + "command": "show ip route {} {}".format(ip_address.ip, protocol), + }, + 6: { + "template": "show_ipv6_route", + "command": "show ipv6 route {} {}".format(ip_address.ip, protocol), + }, + } + cmd_dict = cmds[ip_address.version] + ret = self.connection.run_cmd(cmd_dict["command"]) + + route_table = textfsm_extractor(self, cmd_dict["template"], ret) + else: + cmds = [ + { + "template": "show_ip_route", + "command": "show ip route {} {}".format(destination, protocol), + }, + { + "template": "show_ipv6_route", + "command": "show ipv6 route {} {}".format(destination, protocol), + }, + ] + + ret = self.connection.cli([cmd["command"] for cmd in cmds]) + + route_table = [] + for cmd in cmds: + route_table.extend( + textfsm_extractor(self, cmd["template"], ret[cmd["command"]]) + ) + + out = {} + for route in route_table: + if not out.get(route["destination"]): + out[route["destination"]] = [] + + new_path = inner_dictionary.copy() + new_path["protocol"] = route["type"] + new_path["preference"] = int(route["distance"]) + new_path["next_hop"] = route["gateway"] + + # doesn't exist, but will be handled to be compliant with the tests + if route["type"] == "bgp": + new_path["protocol_attributes"] = bgp_dictionary.copy() + + # doesn't exist, but will be handled to be compliant with the tests + if route["type"] == "isis": + new_path["protocol_attributes"] = isis_dictionary.copy() + + out[route["destination"]].append(new_path) + return out diff --git a/napalm_arubaoss/helper/has_pending_commit.py b/napalm_arubaoss/helper/has_pending_commit.py new file mode 100644 index 0000000..e1f1b66 --- /dev/null +++ b/napalm_arubaoss/helper/has_pending_commit.py @@ -0,0 +1,24 @@ +"""Confirm the changes requested via commit_config when `type(revert_in)=int`.""" + +import logging + +from napalm_arubaoss.helper.get_config import get_config + + +logger = logging.getLogger('arubaoss.helper.has_pending_commit') + + +def has_pending_commit(self): + """ + Boolean indicates if a commit_config that needs confirmed is in process. + + :param self: object from class + :return Boolean + """ + running = get_config(self=self, retrieve='running')['running'][:-2] + + for line in running.split("\n"): + if line.find("ROLLBACK") > 0: + return True + + return False diff --git a/napalm_arubaoss/helper/is_alive.py b/napalm_arubaoss/helper/is_alive.py new file mode 100644 index 0000000..ee23a40 --- /dev/null +++ b/napalm_arubaoss/helper/is_alive.py @@ -0,0 +1,22 @@ +"""Check if device connection is alive.""" + +from napalm.base.exceptions import ConnectionClosedException +import logging + +logger = logging.getLogger("arubaoss.helper.is_alive") + + +def is_alive(self): + """ + Check if device connection is alive. + + :param self: object from class + :return: + """ + url = self.connection.config["api_url"] + "system" + endpoint = self.connection.get(url) + if endpoint.status_code == 200: + "Session cookie is still valid" + return {"is_alive": True} + else: + raise ConnectionClosedException("HTTP session is closed") diff --git a/napalm_arubaoss/helper/load_merge_candidate.py b/napalm_arubaoss/helper/load_merge_candidate.py new file mode 100644 index 0000000..846d55f --- /dev/null +++ b/napalm_arubaoss/helper/load_merge_candidate.py @@ -0,0 +1,36 @@ +"""Merge candidate configuration with the running one.""" + +from napalm.base.exceptions import MergeConfigException +import logging + +from napalm_arubaoss.helper.utils import read_candidate, config_batch, backup_config + +logger = logging.getLogger("arubaoss.helper.load_merge_candidate") + + +def load_merge_candidate(self, filename=None, config=None): + """ + Merge candidate configuration with the running one. + + Imperative config change: + Merge new config with existing one. There's no config validation + nor atomic commit!. Only configuration commands are supported, + "configure terminal" is not required. Use with caution. + + :param self: object from class + :param filename: + :param config: + :return: + """ + if filename: + config = read_candidate(candidate=filename) + + if config is not None: + if isinstance(config, str): + config = config.split("\n") + if not config_batch(self=self, cmd_list=config): + raise MergeConfigException("Configuration merge failed") + + # mimic load_replace_candidate behaviour, by making sure candidate + # config exactly matches our merged configuration + backup_config(self=self, destination="REST_Payload_Backup") diff --git a/napalm_arubaoss/helper/load_replace_candidate.py b/napalm_arubaoss/helper/load_replace_candidate.py new file mode 100644 index 0000000..188e57a --- /dev/null +++ b/napalm_arubaoss/helper/load_replace_candidate.py @@ -0,0 +1,39 @@ +"""Replace running config with the candidate.""" + +from napalm.base.exceptions import ReplaceConfigException +import logging + +from napalm_arubaoss.helper.utils import str_to_b64, read_candidate + +logger = logging.getLogger("arubaoss.helper.load_replace_candidate") + + +def load_replace_candidate(self, filename=None, config=None): + """ + Replace running config with the candidate. + + Implentation of napalm module load_replace_candidate() + ArubaOS-Switch supports payload_type options: + - "RPT_PATCH_FILE" -> not implemented + - "RPT_BACKUP_FILE" -> Implemented + + Note: the maximum content_length = 16072, + "HTTP/1.1 413 Request Entity Too Large" is returned above that!!! + + :param self: object from class + :param filename: + :param config: + :return: + """ + url = self.connection.config["api_url"] + "system/config/payload" + payload = {"payload_type": "RPT_BACKUP_FILE"} + if filename is not None: + config = read_candidate(candidate=filename) + + if config is not None: + payload["config_base64_encoded"] = str_to_b64(config) + load = self.connection.post(url, json=payload) + if load.status_code != 200: + raise ReplaceConfigException( + f"Load configuration failed - Reason: {load.text}" + ) diff --git a/napalm_arubaoss/helper/ping.py b/napalm_arubaoss/helper/ping.py new file mode 100644 index 0000000..62a4c40 --- /dev/null +++ b/napalm_arubaoss/helper/ping.py @@ -0,0 +1,49 @@ +"""Execute ping on the device and returns a dictionary with the result.""" + +import logging + +logger = logging.getLogger("arubaoss.helper.ping") + + +def ping(self, destination, timeout=2): + """ + Execute ping on the device and returns a dictionary with the result. + + :param self: object from class + :param destination: needed argument + :param timeout: not implemented as not available from device + :return: returns a dictionary containing the hops and probes + """ + url = self.connection.config["api_url"] + "ping" + data = { + "destination": {"ip_address": {"version": "IAV_IP_V4", "octets": destination}}, + "timeout_in_seconds": timeout, + } + data_post = self.connection.post(url, json=data) + + if not data_post.status_code == 200: + return {"error": "unknown host {}".format(destination)} + + return_post = data_post.json() if hasattr(data_post, "json") else {} + result_post = return_post.get("result", "") + rtt = return_post.get("rtt_in_milliseconds", 0) + rtt_float = float(rtt) + + if "PR_OK" in result_post: + result = { + "success": { + "probes_sent": 1, + "packet_loss": 0, + "rtt_min": rtt_float, + "rtt_max": rtt_float, + "rtt_avg": rtt_float, + "rtt_stddev": 0.0, + "results": [ + { + "ip_address": destination, + "rtt": rtt_float + } + ] + } + } + return result diff --git a/napalm_arubaoss/helper/rollback.py b/napalm_arubaoss/helper/rollback.py new file mode 100644 index 0000000..fbd6c15 --- /dev/null +++ b/napalm_arubaoss/helper/rollback.py @@ -0,0 +1,25 @@ +"""Rollback configuration.""" + +import logging + +from napalm_arubaoss.helper.utils import commit_candidate +from napalm_arubaoss.helper.compare_config import compare_config + +logger = logging.getLogger("arubaoss.helper.rollback") + + +def rollback(self): + """ + Rollback configuration. + + :param self: object from class + :return: + """ + diff = compare_config(self=self) + if diff and isinstance(diff, dict): + if not (len(diff.get("diff_add_list")) and len(diff.get("diff_remove_list"))): + commit_candidate(self=self, config="backup_running") + + return True + else: + return False diff --git a/napalm_arubaoss/helper/traceroute.py b/napalm_arubaoss/helper/traceroute.py new file mode 100644 index 0000000..e72fbd5 --- /dev/null +++ b/napalm_arubaoss/helper/traceroute.py @@ -0,0 +1,55 @@ +"""Execute traceroute on the device and returns a dictionary with the result.""" + +import socket +import logging + +logger = logging.getLogger("arubaoss.helper.traceroute") + + +def traceroute(self, destination): + """ + Execute traceroute on the device and returns a dictionary with the result. + + :param self: object from class + :param destination: needed argument + :return: returns a dictionary containing the hops and probes + """ + url = self.connection.config["api_url"] + "trace-route" + data = { + "destination": {"ip_address": {"version": "IAV_IP_V4", "octets": destination}} + } + data_post = self.connection.post(url, json=data) + + if not data_post.status_code == 200: + return {"error": "unknown host {}".format(destination)} + + ret = {"success": {}} + ttl_data = data_post.json().get("ttl_data", []) + + for hop_count in range(len(ttl_data)): + ret["success"][hop_count + 1] = {"probes": {}} + ttl_probe_data = ttl_data[hop_count].get("ttl_probe_data", []) + for probe_count in range(len(ttl_probe_data)): + try: + hostname, _, _ = socket.gethostbyaddr( + ttl_probe_data[probe_count] + .get("gateway", {}) + .get("ip_address", {}) + .get("octets", "") + ) + except socket.herror: # fetch if nothing can be found + hostname = "" + + probe = { + "rtt": float(ttl_probe_data[probe_count]["probe_time_in_millis"]), + "ip_address": ttl_probe_data[probe_count] + .get("gateway", {}) + .get("ip_address", {}) + .get("octets", ""), + "host_name": hostname, + } + + ret["success"][hop_count + 1]["probes"][probe_count + 1] = probe + del probe + + return ret diff --git a/napalm_arubaoss/helper/utils.py b/napalm_arubaoss/helper/utils.py new file mode 100644 index 0000000..dc3d2f8 --- /dev/null +++ b/napalm_arubaoss/helper/utils.py @@ -0,0 +1,152 @@ +"""Implement all utilities used by other modules.""" + +import base64 +import logging +from time import sleep +from itertools import zip_longest +from napalm.base.exceptions import CommandTimeoutException + +logger = logging.getLogger("arubaoss.helper.utils") + + +def read_candidate(candidate): + """ + Open the candidate config. + + :param candidate: + :return: + """ + with open(candidate) as candidate_config: + return "".join(candidate_config.readlines()) + + +def str_to_b64(spayload): + """ + Convert from str to b64 for aoss API. + + :param spayload: + :return: + """ + payload_b64 = base64.b64encode(spayload.encode()) + + return payload_b64.decode("utf-8") + + +def config_batch(self, cmd_list): + """ + Load a batch of configuration commands into the running-config. + + :param self: object from class + :param cmd_list: + :return: + """ + url = self.connection.config["api_url"] + "cli_batch" + data = {"cli_batch_base64_encoded": str_to_b64("\n".join(cmd_list))} + batch_run = self.connection.post(url, json=data) + + if not batch_run.status_code == 202: + logger.debug("Failed to paste commands") + + return False + + check_status = self.connection.get(url + "/status") + if check_status.status_code == 200: + for cmd_status in check_status.json()["cmd_exec_logs"]: + if not cmd_status["status"] == "CCS_SUCCESS": + logger.warning( + "command failed to execute with error {}".format( + cmd_status["result"] + ) + ) + return False + return True + + +def backup_config(self, config="running", destination="backup"): + """ + Backup config. + + Supported configs + API: + - "CT_RUNNING_CONFIG", + - "CT_STARTUP_CONFIG" + + :param self: object from class + :param config: + :param destination: + :return: + """ + url = self.connection.config["api_url"] + "system/config/cfg_backup_files" + payload = {} + dest_map = { + "backup": "backup_{}".format(config), + "REST_Payload_Backup": "REST_Payload_Backup", + } + conf_map = { + "running": "CT_RUNNING_CONFIG", + "startup": "CT_STARTUP_CONFIG" + } + payload["file_name"] = dest_map.get(destination) + payload["config_type"] = conf_map.get(config, False) + + if not payload["config_type"]: + "unsupported argument; raise error" + return False + + cmd_post = self.connection.post(url, json=payload) + if not cmd_post.ok: + "raise error" + pass + else: + return cmd_post.json() + + +def transaction_status(self, url): + """ + Wait for the requested transaction to finish within the specified timeout. + + :param self: object from class + :param url: + :return: + """ + status = "CRS_IN_PROGRESS" + elapsed = 0 + while status == "CRS_IN_PROGRESS" and elapsed < self.connection.timeout: + call = self.connection.get(url) + if call.status_code in range(200, 300): + status = call.json() + return status + elapsed += 1 + sleep(1) + if elapsed == (int(self.connection.timeout) - 1) and status == "CRS_IN_PROGRESS": + raise CommandTimeoutException("Transaction timed out") + + +def commit_candidate(self, config): + """ + Commit the candidate configuration. + + :param self: object from class + :param config: + :return: + """ + url = self.connection.config["api_url"] + "system/config/cfg_restore" + data = {"server_type": "ST_FLASH", "file_name": config, "is_oobm": False} + cmd_post = self.connection.post(url, json=data) + + if not cmd_post.json()["failure_reason"]: + check_url = url + "/status" + + return transaction_status(self=self, url=check_url) + + +def mac_reformat(mac): + """ + Reformat the MAC addresses to standard notation. + + :param mac: + :return: + """ + t = iter(mac.replace("-", "")) + + return ":".join(a + b for a, b in zip_longest(t, t, fillvalue="")) diff --git a/pylama.ini b/pylama.ini index 3146a20..5f1daf1 100644 --- a/pylama.ini +++ b/pylama.ini @@ -1,6 +1,6 @@ [pylama] linters = mccabe,pep257,pep8,pyflakes -ignore = D203, +ignore = D203,D212 [pylama:pep8] max_line_length = 120 diff --git a/requirements.txt b/requirements.txt index 89ae1e3..6c8147e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ -napalm>=2.0.0 +napalm>=3.3.0 netaddr requests -requests-toolbelt textfsm>=1.1.0 +urllib3 \ No newline at end of file diff --git a/setup.cfg b/setup.cfg index a42a367..23a7705 100644 --- a/setup.cfg +++ b/setup.cfg @@ -11,9 +11,11 @@ addopts = --cov=napalm_arubaoss --cov-report term-missing -vs - --pylama +# --pylama json_report = report.json jsonapi = true +testpaths = + test [coverage:run] source = napalm_arubaoss diff --git a/setup.py b/setup.py index afe915c..44bb06c 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ setup( name="napalm-arubaos-switch", - version="0.1.1", + version="0.2.0", packages=find_packages(), author="Guillermo Cotone", author_email="15230109+gcotone@users.noreply.github.com", @@ -26,6 +26,8 @@ "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", "Operating System :: POSIX :: Linux", ], url="https://github.com/napalm-automation-community/napalm-arubaos-switch/", diff --git a/test/__init__.py b/test/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/test/unit/__init__.py b/test/unit/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/test/unit/conftest.py b/test/unit/conftest.py new file mode 100644 index 0000000..edfe782 --- /dev/null +++ b/test/unit/conftest.py @@ -0,0 +1,130 @@ +"""Test fixtures.""" + +from re import search + +import pytest +from napalm.base.test import conftest as parent_conftest + +from napalm.base.test.double import BaseTestDouble + +from napalm_arubaoss import ArubaOS + + +@pytest.fixture(scope='class') +def set_device_parameters(request): + """Set up the class.""" + def fin(): + request.cls.device.close() + request.addfinalizer(fin) + + request.cls.driver = ArubaOS.ArubaOSS + request.cls.patched_driver = PatchedArubaOSDriver + request.cls.vendor = 'napalm_arubaoss' + parent_conftest.set_device_parameters(request) + + +def pytest_generate_tests(metafunc): + """Generate test cases dynamically.""" + parent_conftest.pytest_generate_tests(metafunc, __file__) + + +class PatchedArubaOSDriver(ArubaOS.ArubaOSS): + """Patched ArubaOS Driver.""" + + def __init__(self, hostname, username, password, timeout=60, optional_args=None): + super().__init__(hostname, username, password, timeout, optional_args) + + self.patched_attrs = ['connection'] + self.connection = FakeArubaOSDevice() + self.platform = "arubaos" + + def disconnect(self): + pass + + def is_alive(self): + return { + 'is_alive': True # In testing everything works.. + } + + def open(self): + pass + + +class FakeArubaOSDevice(BaseTestDouble): + """ArubaOS device test double.""" + def __init__(self): + super().__init__() + self.config = {'api_url': ''} + + def get(self, url: str): + full_path = self.find_file('facts.json') + facts = self.read_json_file(full_path) + + facts = facts.get(url) + resp = Response( + facts.get('data', {}), + status=facts.get('status', 204), + ok=facts.get('ok', True) + ) + return resp + + def post(self, url: str, json=None): + full_path = self.find_file('facts.json') + facts = self.read_json_file(full_path) + + facts = facts.get(url) + resp = Response( + facts.get('data', {}), + status=facts.get('status', 204), + ok=facts.get('ok', True) + ) + return resp + + def cli(self, commands): + full_path = self.find_file('cli_mapping.json') + cli_mapping = self.read_json_file(full_path) + + fake_return = {} + + for cmd in commands: + cli_match = cli_mapping.get(cmd) + if not cli_match: + return + fake_return[cmd] = cli_match + + return fake_return + + def run_cmd(self, cmd): + return self.cli([cmd])[cmd] + + def show(self, command, raw_text=False): + """Fake show.""" + filename = '{}.json'.format(command.replace(' ', '_')) + full_path = self.find_file(filename) + + if raw_text: + result = self.read_txt_file(full_path) + else: + result = self.read_json_file(full_path) + + return result + + def login(self): + pass + + def logout(self): + pass + + def config_list(self, command): + """Fake config_list.""" + pass + + +class Response: + def __init__(self, data, status=204, ok=True): + self.status_code = status + self.ok = ok + self.data = data + + def json(self): + return self.data diff --git a/test/unit/mocked_data/test_get_arp_table/normal/cli_mapping.json b/test/unit/mocked_data/test_get_arp_table/normal/cli_mapping.json new file mode 100644 index 0000000..553bcac --- /dev/null +++ b/test/unit/mocked_data/test_get_arp_table/normal/cli_mapping.json @@ -0,0 +1,3 @@ +{ + "show arp": "\n IP ARP table\n\n IP Address MAC Address Type Port\n --------------- ----------------- ------- ----\n 10.0.4.55 1a2b3c-4d5e6f dynamic Trk1\n 10.0.65.1 abcdef-123456 dynamic 1/15\n 10.2.3.2 123456-abcdef dynamic 1/3 \n" +} \ No newline at end of file diff --git a/test/unit/mocked_data/test_get_arp_table/normal/expected_result.json b/test/unit/mocked_data/test_get_arp_table/normal/expected_result.json new file mode 100644 index 0000000..218006f --- /dev/null +++ b/test/unit/mocked_data/test_get_arp_table/normal/expected_result.json @@ -0,0 +1,20 @@ +[ + { + "interface": "Trk1", + "mac": "1a:2b:3c:4d:5e:6f", + "ip": "10.0.4.55", + "age": -1.00 + }, + { + "interface": "1/15", + "mac": "ab:cd:ef:12:34:56", + "ip": "10.0.65.1", + "age": -1.00 + }, + { + "interface": "1/3", + "mac": "12:34:56:ab:cd:ef", + "ip": "10.2.3.2", + "age": -1.00 + } +] \ No newline at end of file diff --git a/test/unit/mocked_data/test_get_arp_table/stack/cli_mapping.json b/test/unit/mocked_data/test_get_arp_table/stack/cli_mapping.json new file mode 100644 index 0000000..553bcac --- /dev/null +++ b/test/unit/mocked_data/test_get_arp_table/stack/cli_mapping.json @@ -0,0 +1,3 @@ +{ + "show arp": "\n IP ARP table\n\n IP Address MAC Address Type Port\n --------------- ----------------- ------- ----\n 10.0.4.55 1a2b3c-4d5e6f dynamic Trk1\n 10.0.65.1 abcdef-123456 dynamic 1/15\n 10.2.3.2 123456-abcdef dynamic 1/3 \n" +} \ No newline at end of file diff --git a/test/unit/mocked_data/test_get_arp_table/stack/expected_result.json b/test/unit/mocked_data/test_get_arp_table/stack/expected_result.json new file mode 100644 index 0000000..218006f --- /dev/null +++ b/test/unit/mocked_data/test_get_arp_table/stack/expected_result.json @@ -0,0 +1,20 @@ +[ + { + "interface": "Trk1", + "mac": "1a:2b:3c:4d:5e:6f", + "ip": "10.0.4.55", + "age": -1.00 + }, + { + "interface": "1/15", + "mac": "ab:cd:ef:12:34:56", + "ip": "10.0.65.1", + "age": -1.00 + }, + { + "interface": "1/3", + "mac": "12:34:56:ab:cd:ef", + "ip": "10.2.3.2", + "age": -1.00 + } +] \ No newline at end of file diff --git a/test/unit/mocked_data/test_get_config/normal/cli_mapping.json b/test/unit/mocked_data/test_get_config/normal/cli_mapping.json new file mode 100644 index 0000000..2dccc53 --- /dev/null +++ b/test/unit/mocked_data/test_get_config/normal/cli_mapping.json @@ -0,0 +1,5 @@ +{ + "display saved-configuration": "; hpStack_WC Configuration Editor; Created on release #WC.16.10.0009\n; Ver #14:67.6f.f8.1d.9b.3f.bf.bb.ef.7c.59.fc.6b.fb.9f.fc.ff.ff.37.ef:44\n\nstacking\n member 1 type \"JL322A\" mac-address 000000-000000\n exit\nhostname \"Aruba-Stack-2930M\"\nrest-interface session-idle-timeout 120\nweb-management ssl\nip default-gateway 172.16.6.1\nip dns domain-name \"arubaos.napalm\"\nip dns server-address priority 1 8.8.8.8\nip dns server-address priority 2 1.1.1.1\ninterface 1/10\n name \"test\"\n exit\ninterface 1/12\n name \"blubdf\"\n exit\ninterface 1/48\n name \"test\"\n exit\nsnmp-server community \"public\" unrestricted\noobm\n ip address 172.16.7.3 255.255.254.0\n ip default-gateway 172.16.6.1\n ipv6 enable\n ipv6 address dhcp full\n member 1\n ip address dhcp-bootp\n exit\n exit\nvlan 1\n name \"DEFAULT_VLAN\"\n untagged 1/1-1/48\n ip address 172.16.7.3 255.255.254.0\n ipv6 enable\n ipv6 address dhcp full\n exit\npassword password\n\n\u0000", + "show config REST_Payload_Backup": "; hpStack_WC Configuration Editor; Created on release #WC.16.10.0009\n; Ver #14:67.6f.f8.1d.9b.3f.bf.bb.ef.7c.59.fc.6b.fb.9f.fc.ff.ff.37.ef:44\n\nstacking\n member 1 type \"JL322A\" mac-address 000000-000000\n exit\nhostname \"Aruba-Stack-2930M\"\nrest-interface session-idle-timeout 120\nweb-management ssl\nip default-gateway 172.16.6.1\nip dns domain-name \"arubaos.napalm\"\nip dns server-address priority 1 8.8.8.8\nip dns server-address priority 2 1.1.1.1\ninterface 1/10\n name \"test\"\n exit\ninterface 1/48\n name \"test\"\n exit\nsnmp-server community \"public\" unrestricted\noobm\n ip address 172.16.7.3 255.255.254.0\n ip default-gateway 172.16.6.1\n ipv6 enable\n ipv6 address dhcp full\n member 1\n ip address dhcp-bootp\n exit\n exit\nvlan 1\n name \"DEFAULT_VLAN\"\n untagged 1/1-1/48\n ip address 172.16.7.3 255.255.254.0\n ipv6 enable\n ipv6 address dhcp full\n exit\npassword password\n\n\u0000", + "show running-config": "\nRunning configuration:\n\n; hpStack_WC Configuration Editor; Created on release #WC.16.10.0009\n; Ver #14:67.6f.f8.1d.9b.3f.bf.bb.ef.7c.59.fc.6b.fb.9f.fc.ff.ff.37.ef:44\n\nstacking\n member 1 type \"JL322A\" mac-address 000000-000000\n exit\nhostname \"Aruba-Stack-2930M\"\nrest-interface session-idle-timeout 120\nweb-management ssl\nip default-gateway 172.16.6.1\nip dns domain-name \"arubaos.napalm\"\nip dns server-address priority 1 8.8.8.8\nip dns server-address priority 2 1.1.1.1\ninterface 1/10\n name \"test\"\n exit\ninterface 1/12\n name \"blubdf\"\n exit\ninterface 1/48\n name \"test\"\n exit\nsnmp-server community \"public\" unrestricted\noobm\n ip address 172.16.7.3 255.255.254.0\n ip default-gateway 172.16.6.1\n ipv6 enable\n ipv6 address dhcp full\n member 1\n ip address dhcp-bootp\n exit\n exit\nvlan 1\n name \"DEFAULT_VLAN\"\n untagged 1/1-1/48\n ip address 172.16.7.3 255.255.254.0\n ipv6 enable\n ipv6 address dhcp full\n exit\npassword password\n\n\u0000" +} \ No newline at end of file diff --git a/test/unit/mocked_data/test_get_config/normal/expected_result.json b/test/unit/mocked_data/test_get_config/normal/expected_result.json new file mode 100644 index 0000000..b92be02 --- /dev/null +++ b/test/unit/mocked_data/test_get_config/normal/expected_result.json @@ -0,0 +1,5 @@ +{ + "startup": "; hpStack_WC Configuration Editor; Created on release #WC.16.10.0009\n; Ver #14:67.6f.f8.1d.9b.3f.bf.bb.ef.7c.59.fc.6b.fb.9f.fc.ff.ff.37.ef:44\n\nstacking\n member 1 type \"JL322A\" mac-address 000000-000000\n exit\nhostname \"Aruba-Stack-2930M\"\nrest-interface session-idle-timeout 120\nweb-management ssl\nip default-gateway 172.16.6.1\nip dns domain-name \"arubaos.napalm\"\nip dns server-address priority 1 8.8.8.8\nip dns server-address priority 2 1.1.1.1\ninterface 1/10\n name \"test\"\n exit\ninterface 1/12\n name \"blubdf\"\n exit\ninterface 1/48\n name \"test\"\n exit\nsnmp-server community \"public\" unrestricted\noobm\n ip address 172.16.7.3 255.255.254.0\n ip default-gateway 172.16.6.1\n ipv6 enable\n ipv6 address dhcp full\n member 1\n ip address dhcp-bootp\n exit\n exit\nvlan 1\n name \"DEFAULT_VLAN\"\n untagged 1/1-1/48\n ip address 172.16.7.3 255.255.254.0\n ipv6 enable\n ipv6 address dhcp full\n exit\npassword password\n\n\u0000", + "candidate": "; hpStack_WC Configuration Editor; Created on release #WC.16.10.0009\n; Ver #14:67.6f.f8.1d.9b.3f.bf.bb.ef.7c.59.fc.6b.fb.9f.fc.ff.ff.37.ef:44\n\nstacking\n member 1 type \"JL322A\" mac-address 000000-000000\n exit\nhostname \"Aruba-Stack-2930M\"\nrest-interface session-idle-timeout 120\nweb-management ssl\nip default-gateway 172.16.6.1\nip dns domain-name \"arubaos.napalm\"\nip dns server-address priority 1 8.8.8.8\nip dns server-address priority 2 1.1.1.1\ninterface 1/10\n name \"test\"\n exit\ninterface 1/48\n name \"test\"\n exit\nsnmp-server community \"public\" unrestricted\noobm\n ip address 172.16.7.3 255.255.254.0\n ip default-gateway 172.16.6.1\n ipv6 enable\n ipv6 address dhcp full\n member 1\n ip address dhcp-bootp\n exit\n exit\nvlan 1\n name \"DEFAULT_VLAN\"\n untagged 1/1-1/48\n ip address 172.16.7.3 255.255.254.0\n ipv6 enable\n ipv6 address dhcp full\n exit\npassword password\n\n\u0000", + "running": "\nRunning configuration:\n\n; hpStack_WC Configuration Editor; Created on release #WC.16.10.0009\n; Ver #14:67.6f.f8.1d.9b.3f.bf.bb.ef.7c.59.fc.6b.fb.9f.fc.ff.ff.37.ef:44\n\nstacking\n member 1 type \"JL322A\" mac-address 000000-000000\n exit\nhostname \"Aruba-Stack-2930M\"\nrest-interface session-idle-timeout 120\nweb-management ssl\nip default-gateway 172.16.6.1\nip dns domain-name \"arubaos.napalm\"\nip dns server-address priority 1 8.8.8.8\nip dns server-address priority 2 1.1.1.1\ninterface 1/10\n name \"test\"\n exit\ninterface 1/12\n name \"blubdf\"\n exit\ninterface 1/48\n name \"test\"\n exit\nsnmp-server community \"public\" unrestricted\noobm\n ip address 172.16.7.3 255.255.254.0\n ip default-gateway 172.16.6.1\n ipv6 enable\n ipv6 address dhcp full\n member 1\n ip address dhcp-bootp\n exit\n exit\nvlan 1\n name \"DEFAULT_VLAN\"\n untagged 1/1-1/48\n ip address 172.16.7.3 255.255.254.0\n ipv6 enable\n ipv6 address dhcp full\n exit\npassword password\n\n\u0000" +} \ No newline at end of file diff --git a/test/unit/mocked_data/test_get_config/stack/cli_mapping.json b/test/unit/mocked_data/test_get_config/stack/cli_mapping.json new file mode 100644 index 0000000..2dccc53 --- /dev/null +++ b/test/unit/mocked_data/test_get_config/stack/cli_mapping.json @@ -0,0 +1,5 @@ +{ + "display saved-configuration": "; hpStack_WC Configuration Editor; Created on release #WC.16.10.0009\n; Ver #14:67.6f.f8.1d.9b.3f.bf.bb.ef.7c.59.fc.6b.fb.9f.fc.ff.ff.37.ef:44\n\nstacking\n member 1 type \"JL322A\" mac-address 000000-000000\n exit\nhostname \"Aruba-Stack-2930M\"\nrest-interface session-idle-timeout 120\nweb-management ssl\nip default-gateway 172.16.6.1\nip dns domain-name \"arubaos.napalm\"\nip dns server-address priority 1 8.8.8.8\nip dns server-address priority 2 1.1.1.1\ninterface 1/10\n name \"test\"\n exit\ninterface 1/12\n name \"blubdf\"\n exit\ninterface 1/48\n name \"test\"\n exit\nsnmp-server community \"public\" unrestricted\noobm\n ip address 172.16.7.3 255.255.254.0\n ip default-gateway 172.16.6.1\n ipv6 enable\n ipv6 address dhcp full\n member 1\n ip address dhcp-bootp\n exit\n exit\nvlan 1\n name \"DEFAULT_VLAN\"\n untagged 1/1-1/48\n ip address 172.16.7.3 255.255.254.0\n ipv6 enable\n ipv6 address dhcp full\n exit\npassword password\n\n\u0000", + "show config REST_Payload_Backup": "; hpStack_WC Configuration Editor; Created on release #WC.16.10.0009\n; Ver #14:67.6f.f8.1d.9b.3f.bf.bb.ef.7c.59.fc.6b.fb.9f.fc.ff.ff.37.ef:44\n\nstacking\n member 1 type \"JL322A\" mac-address 000000-000000\n exit\nhostname \"Aruba-Stack-2930M\"\nrest-interface session-idle-timeout 120\nweb-management ssl\nip default-gateway 172.16.6.1\nip dns domain-name \"arubaos.napalm\"\nip dns server-address priority 1 8.8.8.8\nip dns server-address priority 2 1.1.1.1\ninterface 1/10\n name \"test\"\n exit\ninterface 1/48\n name \"test\"\n exit\nsnmp-server community \"public\" unrestricted\noobm\n ip address 172.16.7.3 255.255.254.0\n ip default-gateway 172.16.6.1\n ipv6 enable\n ipv6 address dhcp full\n member 1\n ip address dhcp-bootp\n exit\n exit\nvlan 1\n name \"DEFAULT_VLAN\"\n untagged 1/1-1/48\n ip address 172.16.7.3 255.255.254.0\n ipv6 enable\n ipv6 address dhcp full\n exit\npassword password\n\n\u0000", + "show running-config": "\nRunning configuration:\n\n; hpStack_WC Configuration Editor; Created on release #WC.16.10.0009\n; Ver #14:67.6f.f8.1d.9b.3f.bf.bb.ef.7c.59.fc.6b.fb.9f.fc.ff.ff.37.ef:44\n\nstacking\n member 1 type \"JL322A\" mac-address 000000-000000\n exit\nhostname \"Aruba-Stack-2930M\"\nrest-interface session-idle-timeout 120\nweb-management ssl\nip default-gateway 172.16.6.1\nip dns domain-name \"arubaos.napalm\"\nip dns server-address priority 1 8.8.8.8\nip dns server-address priority 2 1.1.1.1\ninterface 1/10\n name \"test\"\n exit\ninterface 1/12\n name \"blubdf\"\n exit\ninterface 1/48\n name \"test\"\n exit\nsnmp-server community \"public\" unrestricted\noobm\n ip address 172.16.7.3 255.255.254.0\n ip default-gateway 172.16.6.1\n ipv6 enable\n ipv6 address dhcp full\n member 1\n ip address dhcp-bootp\n exit\n exit\nvlan 1\n name \"DEFAULT_VLAN\"\n untagged 1/1-1/48\n ip address 172.16.7.3 255.255.254.0\n ipv6 enable\n ipv6 address dhcp full\n exit\npassword password\n\n\u0000" +} \ No newline at end of file diff --git a/test/unit/mocked_data/test_get_config/stack/expected_result.json b/test/unit/mocked_data/test_get_config/stack/expected_result.json new file mode 100644 index 0000000..b92be02 --- /dev/null +++ b/test/unit/mocked_data/test_get_config/stack/expected_result.json @@ -0,0 +1,5 @@ +{ + "startup": "; hpStack_WC Configuration Editor; Created on release #WC.16.10.0009\n; Ver #14:67.6f.f8.1d.9b.3f.bf.bb.ef.7c.59.fc.6b.fb.9f.fc.ff.ff.37.ef:44\n\nstacking\n member 1 type \"JL322A\" mac-address 000000-000000\n exit\nhostname \"Aruba-Stack-2930M\"\nrest-interface session-idle-timeout 120\nweb-management ssl\nip default-gateway 172.16.6.1\nip dns domain-name \"arubaos.napalm\"\nip dns server-address priority 1 8.8.8.8\nip dns server-address priority 2 1.1.1.1\ninterface 1/10\n name \"test\"\n exit\ninterface 1/12\n name \"blubdf\"\n exit\ninterface 1/48\n name \"test\"\n exit\nsnmp-server community \"public\" unrestricted\noobm\n ip address 172.16.7.3 255.255.254.0\n ip default-gateway 172.16.6.1\n ipv6 enable\n ipv6 address dhcp full\n member 1\n ip address dhcp-bootp\n exit\n exit\nvlan 1\n name \"DEFAULT_VLAN\"\n untagged 1/1-1/48\n ip address 172.16.7.3 255.255.254.0\n ipv6 enable\n ipv6 address dhcp full\n exit\npassword password\n\n\u0000", + "candidate": "; hpStack_WC Configuration Editor; Created on release #WC.16.10.0009\n; Ver #14:67.6f.f8.1d.9b.3f.bf.bb.ef.7c.59.fc.6b.fb.9f.fc.ff.ff.37.ef:44\n\nstacking\n member 1 type \"JL322A\" mac-address 000000-000000\n exit\nhostname \"Aruba-Stack-2930M\"\nrest-interface session-idle-timeout 120\nweb-management ssl\nip default-gateway 172.16.6.1\nip dns domain-name \"arubaos.napalm\"\nip dns server-address priority 1 8.8.8.8\nip dns server-address priority 2 1.1.1.1\ninterface 1/10\n name \"test\"\n exit\ninterface 1/48\n name \"test\"\n exit\nsnmp-server community \"public\" unrestricted\noobm\n ip address 172.16.7.3 255.255.254.0\n ip default-gateway 172.16.6.1\n ipv6 enable\n ipv6 address dhcp full\n member 1\n ip address dhcp-bootp\n exit\n exit\nvlan 1\n name \"DEFAULT_VLAN\"\n untagged 1/1-1/48\n ip address 172.16.7.3 255.255.254.0\n ipv6 enable\n ipv6 address dhcp full\n exit\npassword password\n\n\u0000", + "running": "\nRunning configuration:\n\n; hpStack_WC Configuration Editor; Created on release #WC.16.10.0009\n; Ver #14:67.6f.f8.1d.9b.3f.bf.bb.ef.7c.59.fc.6b.fb.9f.fc.ff.ff.37.ef:44\n\nstacking\n member 1 type \"JL322A\" mac-address 000000-000000\n exit\nhostname \"Aruba-Stack-2930M\"\nrest-interface session-idle-timeout 120\nweb-management ssl\nip default-gateway 172.16.6.1\nip dns domain-name \"arubaos.napalm\"\nip dns server-address priority 1 8.8.8.8\nip dns server-address priority 2 1.1.1.1\ninterface 1/10\n name \"test\"\n exit\ninterface 1/12\n name \"blubdf\"\n exit\ninterface 1/48\n name \"test\"\n exit\nsnmp-server community \"public\" unrestricted\noobm\n ip address 172.16.7.3 255.255.254.0\n ip default-gateway 172.16.6.1\n ipv6 enable\n ipv6 address dhcp full\n member 1\n ip address dhcp-bootp\n exit\n exit\nvlan 1\n name \"DEFAULT_VLAN\"\n untagged 1/1-1/48\n ip address 172.16.7.3 255.255.254.0\n ipv6 enable\n ipv6 address dhcp full\n exit\npassword password\n\n\u0000" +} \ No newline at end of file diff --git a/test/unit/mocked_data/test_get_config_filtered/normal/cli_mapping.json b/test/unit/mocked_data/test_get_config_filtered/normal/cli_mapping.json new file mode 100644 index 0000000..2dccc53 --- /dev/null +++ b/test/unit/mocked_data/test_get_config_filtered/normal/cli_mapping.json @@ -0,0 +1,5 @@ +{ + "display saved-configuration": "; hpStack_WC Configuration Editor; Created on release #WC.16.10.0009\n; Ver #14:67.6f.f8.1d.9b.3f.bf.bb.ef.7c.59.fc.6b.fb.9f.fc.ff.ff.37.ef:44\n\nstacking\n member 1 type \"JL322A\" mac-address 000000-000000\n exit\nhostname \"Aruba-Stack-2930M\"\nrest-interface session-idle-timeout 120\nweb-management ssl\nip default-gateway 172.16.6.1\nip dns domain-name \"arubaos.napalm\"\nip dns server-address priority 1 8.8.8.8\nip dns server-address priority 2 1.1.1.1\ninterface 1/10\n name \"test\"\n exit\ninterface 1/12\n name \"blubdf\"\n exit\ninterface 1/48\n name \"test\"\n exit\nsnmp-server community \"public\" unrestricted\noobm\n ip address 172.16.7.3 255.255.254.0\n ip default-gateway 172.16.6.1\n ipv6 enable\n ipv6 address dhcp full\n member 1\n ip address dhcp-bootp\n exit\n exit\nvlan 1\n name \"DEFAULT_VLAN\"\n untagged 1/1-1/48\n ip address 172.16.7.3 255.255.254.0\n ipv6 enable\n ipv6 address dhcp full\n exit\npassword password\n\n\u0000", + "show config REST_Payload_Backup": "; hpStack_WC Configuration Editor; Created on release #WC.16.10.0009\n; Ver #14:67.6f.f8.1d.9b.3f.bf.bb.ef.7c.59.fc.6b.fb.9f.fc.ff.ff.37.ef:44\n\nstacking\n member 1 type \"JL322A\" mac-address 000000-000000\n exit\nhostname \"Aruba-Stack-2930M\"\nrest-interface session-idle-timeout 120\nweb-management ssl\nip default-gateway 172.16.6.1\nip dns domain-name \"arubaos.napalm\"\nip dns server-address priority 1 8.8.8.8\nip dns server-address priority 2 1.1.1.1\ninterface 1/10\n name \"test\"\n exit\ninterface 1/48\n name \"test\"\n exit\nsnmp-server community \"public\" unrestricted\noobm\n ip address 172.16.7.3 255.255.254.0\n ip default-gateway 172.16.6.1\n ipv6 enable\n ipv6 address dhcp full\n member 1\n ip address dhcp-bootp\n exit\n exit\nvlan 1\n name \"DEFAULT_VLAN\"\n untagged 1/1-1/48\n ip address 172.16.7.3 255.255.254.0\n ipv6 enable\n ipv6 address dhcp full\n exit\npassword password\n\n\u0000", + "show running-config": "\nRunning configuration:\n\n; hpStack_WC Configuration Editor; Created on release #WC.16.10.0009\n; Ver #14:67.6f.f8.1d.9b.3f.bf.bb.ef.7c.59.fc.6b.fb.9f.fc.ff.ff.37.ef:44\n\nstacking\n member 1 type \"JL322A\" mac-address 000000-000000\n exit\nhostname \"Aruba-Stack-2930M\"\nrest-interface session-idle-timeout 120\nweb-management ssl\nip default-gateway 172.16.6.1\nip dns domain-name \"arubaos.napalm\"\nip dns server-address priority 1 8.8.8.8\nip dns server-address priority 2 1.1.1.1\ninterface 1/10\n name \"test\"\n exit\ninterface 1/12\n name \"blubdf\"\n exit\ninterface 1/48\n name \"test\"\n exit\nsnmp-server community \"public\" unrestricted\noobm\n ip address 172.16.7.3 255.255.254.0\n ip default-gateway 172.16.6.1\n ipv6 enable\n ipv6 address dhcp full\n member 1\n ip address dhcp-bootp\n exit\n exit\nvlan 1\n name \"DEFAULT_VLAN\"\n untagged 1/1-1/48\n ip address 172.16.7.3 255.255.254.0\n ipv6 enable\n ipv6 address dhcp full\n exit\npassword password\n\n\u0000" +} \ No newline at end of file diff --git a/test/unit/mocked_data/test_get_config_filtered/normal/expected_result.json b/test/unit/mocked_data/test_get_config_filtered/normal/expected_result.json new file mode 100644 index 0000000..8dc7869 --- /dev/null +++ b/test/unit/mocked_data/test_get_config_filtered/normal/expected_result.json @@ -0,0 +1,5 @@ +{ + "startup": "", + "candidate": "; hpStack_WC Configuration Editor; Created on release #WC.16.10.0009\n; Ver #14:67.6f.f8.1d.9b.3f.bf.bb.ef.7c.59.fc.6b.fb.9f.fc.ff.ff.37.ef:44\n\nstacking\n member 1 type \"JL322A\" mac-address 000000-000000\n exit\nhostname \"Aruba-Stack-2930M\"\nrest-interface session-idle-timeout 120\nweb-management ssl\nip default-gateway 172.16.6.1\nip dns domain-name \"arubaos.napalm\"\nip dns server-address priority 1 8.8.8.8\nip dns server-address priority 2 1.1.1.1\ninterface 1/10\n name \"test\"\n exit\ninterface 1/48\n name \"test\"\n exit\nsnmp-server community \"public\" unrestricted\noobm\n ip address 172.16.7.3 255.255.254.0\n ip default-gateway 172.16.6.1\n ipv6 enable\n ipv6 address dhcp full\n member 1\n ip address dhcp-bootp\n exit\n exit\nvlan 1\n name \"DEFAULT_VLAN\"\n untagged 1/1-1/48\n ip address 172.16.7.3 255.255.254.0\n ipv6 enable\n ipv6 address dhcp full\n exit\npassword password\n\n\u0000", + "running": "" +} \ No newline at end of file diff --git a/test/unit/mocked_data/test_get_config_filtered/stack/cli_mapping.json b/test/unit/mocked_data/test_get_config_filtered/stack/cli_mapping.json new file mode 100644 index 0000000..2dccc53 --- /dev/null +++ b/test/unit/mocked_data/test_get_config_filtered/stack/cli_mapping.json @@ -0,0 +1,5 @@ +{ + "display saved-configuration": "; hpStack_WC Configuration Editor; Created on release #WC.16.10.0009\n; Ver #14:67.6f.f8.1d.9b.3f.bf.bb.ef.7c.59.fc.6b.fb.9f.fc.ff.ff.37.ef:44\n\nstacking\n member 1 type \"JL322A\" mac-address 000000-000000\n exit\nhostname \"Aruba-Stack-2930M\"\nrest-interface session-idle-timeout 120\nweb-management ssl\nip default-gateway 172.16.6.1\nip dns domain-name \"arubaos.napalm\"\nip dns server-address priority 1 8.8.8.8\nip dns server-address priority 2 1.1.1.1\ninterface 1/10\n name \"test\"\n exit\ninterface 1/12\n name \"blubdf\"\n exit\ninterface 1/48\n name \"test\"\n exit\nsnmp-server community \"public\" unrestricted\noobm\n ip address 172.16.7.3 255.255.254.0\n ip default-gateway 172.16.6.1\n ipv6 enable\n ipv6 address dhcp full\n member 1\n ip address dhcp-bootp\n exit\n exit\nvlan 1\n name \"DEFAULT_VLAN\"\n untagged 1/1-1/48\n ip address 172.16.7.3 255.255.254.0\n ipv6 enable\n ipv6 address dhcp full\n exit\npassword password\n\n\u0000", + "show config REST_Payload_Backup": "; hpStack_WC Configuration Editor; Created on release #WC.16.10.0009\n; Ver #14:67.6f.f8.1d.9b.3f.bf.bb.ef.7c.59.fc.6b.fb.9f.fc.ff.ff.37.ef:44\n\nstacking\n member 1 type \"JL322A\" mac-address 000000-000000\n exit\nhostname \"Aruba-Stack-2930M\"\nrest-interface session-idle-timeout 120\nweb-management ssl\nip default-gateway 172.16.6.1\nip dns domain-name \"arubaos.napalm\"\nip dns server-address priority 1 8.8.8.8\nip dns server-address priority 2 1.1.1.1\ninterface 1/10\n name \"test\"\n exit\ninterface 1/48\n name \"test\"\n exit\nsnmp-server community \"public\" unrestricted\noobm\n ip address 172.16.7.3 255.255.254.0\n ip default-gateway 172.16.6.1\n ipv6 enable\n ipv6 address dhcp full\n member 1\n ip address dhcp-bootp\n exit\n exit\nvlan 1\n name \"DEFAULT_VLAN\"\n untagged 1/1-1/48\n ip address 172.16.7.3 255.255.254.0\n ipv6 enable\n ipv6 address dhcp full\n exit\npassword password\n\n\u0000", + "show running-config": "\nRunning configuration:\n\n; hpStack_WC Configuration Editor; Created on release #WC.16.10.0009\n; Ver #14:67.6f.f8.1d.9b.3f.bf.bb.ef.7c.59.fc.6b.fb.9f.fc.ff.ff.37.ef:44\n\nstacking\n member 1 type \"JL322A\" mac-address 000000-000000\n exit\nhostname \"Aruba-Stack-2930M\"\nrest-interface session-idle-timeout 120\nweb-management ssl\nip default-gateway 172.16.6.1\nip dns domain-name \"arubaos.napalm\"\nip dns server-address priority 1 8.8.8.8\nip dns server-address priority 2 1.1.1.1\ninterface 1/10\n name \"test\"\n exit\ninterface 1/12\n name \"blubdf\"\n exit\ninterface 1/48\n name \"test\"\n exit\nsnmp-server community \"public\" unrestricted\noobm\n ip address 172.16.7.3 255.255.254.0\n ip default-gateway 172.16.6.1\n ipv6 enable\n ipv6 address dhcp full\n member 1\n ip address dhcp-bootp\n exit\n exit\nvlan 1\n name \"DEFAULT_VLAN\"\n untagged 1/1-1/48\n ip address 172.16.7.3 255.255.254.0\n ipv6 enable\n ipv6 address dhcp full\n exit\npassword password\n\n\u0000" +} \ No newline at end of file diff --git a/test/unit/mocked_data/test_get_config_filtered/stack/expected_result.json b/test/unit/mocked_data/test_get_config_filtered/stack/expected_result.json new file mode 100644 index 0000000..8dc7869 --- /dev/null +++ b/test/unit/mocked_data/test_get_config_filtered/stack/expected_result.json @@ -0,0 +1,5 @@ +{ + "startup": "", + "candidate": "; hpStack_WC Configuration Editor; Created on release #WC.16.10.0009\n; Ver #14:67.6f.f8.1d.9b.3f.bf.bb.ef.7c.59.fc.6b.fb.9f.fc.ff.ff.37.ef:44\n\nstacking\n member 1 type \"JL322A\" mac-address 000000-000000\n exit\nhostname \"Aruba-Stack-2930M\"\nrest-interface session-idle-timeout 120\nweb-management ssl\nip default-gateway 172.16.6.1\nip dns domain-name \"arubaos.napalm\"\nip dns server-address priority 1 8.8.8.8\nip dns server-address priority 2 1.1.1.1\ninterface 1/10\n name \"test\"\n exit\ninterface 1/48\n name \"test\"\n exit\nsnmp-server community \"public\" unrestricted\noobm\n ip address 172.16.7.3 255.255.254.0\n ip default-gateway 172.16.6.1\n ipv6 enable\n ipv6 address dhcp full\n member 1\n ip address dhcp-bootp\n exit\n exit\nvlan 1\n name \"DEFAULT_VLAN\"\n untagged 1/1-1/48\n ip address 172.16.7.3 255.255.254.0\n ipv6 enable\n ipv6 address dhcp full\n exit\npassword password\n\n\u0000", + "running": "" +} \ No newline at end of file diff --git a/test/unit/mocked_data/test_get_config_sanitized/normal/cli_mapping.json b/test/unit/mocked_data/test_get_config_sanitized/normal/cli_mapping.json new file mode 100644 index 0000000..2dccc53 --- /dev/null +++ b/test/unit/mocked_data/test_get_config_sanitized/normal/cli_mapping.json @@ -0,0 +1,5 @@ +{ + "display saved-configuration": "; hpStack_WC Configuration Editor; Created on release #WC.16.10.0009\n; Ver #14:67.6f.f8.1d.9b.3f.bf.bb.ef.7c.59.fc.6b.fb.9f.fc.ff.ff.37.ef:44\n\nstacking\n member 1 type \"JL322A\" mac-address 000000-000000\n exit\nhostname \"Aruba-Stack-2930M\"\nrest-interface session-idle-timeout 120\nweb-management ssl\nip default-gateway 172.16.6.1\nip dns domain-name \"arubaos.napalm\"\nip dns server-address priority 1 8.8.8.8\nip dns server-address priority 2 1.1.1.1\ninterface 1/10\n name \"test\"\n exit\ninterface 1/12\n name \"blubdf\"\n exit\ninterface 1/48\n name \"test\"\n exit\nsnmp-server community \"public\" unrestricted\noobm\n ip address 172.16.7.3 255.255.254.0\n ip default-gateway 172.16.6.1\n ipv6 enable\n ipv6 address dhcp full\n member 1\n ip address dhcp-bootp\n exit\n exit\nvlan 1\n name \"DEFAULT_VLAN\"\n untagged 1/1-1/48\n ip address 172.16.7.3 255.255.254.0\n ipv6 enable\n ipv6 address dhcp full\n exit\npassword password\n\n\u0000", + "show config REST_Payload_Backup": "; hpStack_WC Configuration Editor; Created on release #WC.16.10.0009\n; Ver #14:67.6f.f8.1d.9b.3f.bf.bb.ef.7c.59.fc.6b.fb.9f.fc.ff.ff.37.ef:44\n\nstacking\n member 1 type \"JL322A\" mac-address 000000-000000\n exit\nhostname \"Aruba-Stack-2930M\"\nrest-interface session-idle-timeout 120\nweb-management ssl\nip default-gateway 172.16.6.1\nip dns domain-name \"arubaos.napalm\"\nip dns server-address priority 1 8.8.8.8\nip dns server-address priority 2 1.1.1.1\ninterface 1/10\n name \"test\"\n exit\ninterface 1/48\n name \"test\"\n exit\nsnmp-server community \"public\" unrestricted\noobm\n ip address 172.16.7.3 255.255.254.0\n ip default-gateway 172.16.6.1\n ipv6 enable\n ipv6 address dhcp full\n member 1\n ip address dhcp-bootp\n exit\n exit\nvlan 1\n name \"DEFAULT_VLAN\"\n untagged 1/1-1/48\n ip address 172.16.7.3 255.255.254.0\n ipv6 enable\n ipv6 address dhcp full\n exit\npassword password\n\n\u0000", + "show running-config": "\nRunning configuration:\n\n; hpStack_WC Configuration Editor; Created on release #WC.16.10.0009\n; Ver #14:67.6f.f8.1d.9b.3f.bf.bb.ef.7c.59.fc.6b.fb.9f.fc.ff.ff.37.ef:44\n\nstacking\n member 1 type \"JL322A\" mac-address 000000-000000\n exit\nhostname \"Aruba-Stack-2930M\"\nrest-interface session-idle-timeout 120\nweb-management ssl\nip default-gateway 172.16.6.1\nip dns domain-name \"arubaos.napalm\"\nip dns server-address priority 1 8.8.8.8\nip dns server-address priority 2 1.1.1.1\ninterface 1/10\n name \"test\"\n exit\ninterface 1/12\n name \"blubdf\"\n exit\ninterface 1/48\n name \"test\"\n exit\nsnmp-server community \"public\" unrestricted\noobm\n ip address 172.16.7.3 255.255.254.0\n ip default-gateway 172.16.6.1\n ipv6 enable\n ipv6 address dhcp full\n member 1\n ip address dhcp-bootp\n exit\n exit\nvlan 1\n name \"DEFAULT_VLAN\"\n untagged 1/1-1/48\n ip address 172.16.7.3 255.255.254.0\n ipv6 enable\n ipv6 address dhcp full\n exit\npassword password\n\n\u0000" +} \ No newline at end of file diff --git a/test/unit/mocked_data/test_get_config_sanitized/normal/expected_result.json b/test/unit/mocked_data/test_get_config_sanitized/normal/expected_result.json new file mode 100644 index 0000000..b92be02 --- /dev/null +++ b/test/unit/mocked_data/test_get_config_sanitized/normal/expected_result.json @@ -0,0 +1,5 @@ +{ + "startup": "; hpStack_WC Configuration Editor; Created on release #WC.16.10.0009\n; Ver #14:67.6f.f8.1d.9b.3f.bf.bb.ef.7c.59.fc.6b.fb.9f.fc.ff.ff.37.ef:44\n\nstacking\n member 1 type \"JL322A\" mac-address 000000-000000\n exit\nhostname \"Aruba-Stack-2930M\"\nrest-interface session-idle-timeout 120\nweb-management ssl\nip default-gateway 172.16.6.1\nip dns domain-name \"arubaos.napalm\"\nip dns server-address priority 1 8.8.8.8\nip dns server-address priority 2 1.1.1.1\ninterface 1/10\n name \"test\"\n exit\ninterface 1/12\n name \"blubdf\"\n exit\ninterface 1/48\n name \"test\"\n exit\nsnmp-server community \"public\" unrestricted\noobm\n ip address 172.16.7.3 255.255.254.0\n ip default-gateway 172.16.6.1\n ipv6 enable\n ipv6 address dhcp full\n member 1\n ip address dhcp-bootp\n exit\n exit\nvlan 1\n name \"DEFAULT_VLAN\"\n untagged 1/1-1/48\n ip address 172.16.7.3 255.255.254.0\n ipv6 enable\n ipv6 address dhcp full\n exit\npassword password\n\n\u0000", + "candidate": "; hpStack_WC Configuration Editor; Created on release #WC.16.10.0009\n; Ver #14:67.6f.f8.1d.9b.3f.bf.bb.ef.7c.59.fc.6b.fb.9f.fc.ff.ff.37.ef:44\n\nstacking\n member 1 type \"JL322A\" mac-address 000000-000000\n exit\nhostname \"Aruba-Stack-2930M\"\nrest-interface session-idle-timeout 120\nweb-management ssl\nip default-gateway 172.16.6.1\nip dns domain-name \"arubaos.napalm\"\nip dns server-address priority 1 8.8.8.8\nip dns server-address priority 2 1.1.1.1\ninterface 1/10\n name \"test\"\n exit\ninterface 1/48\n name \"test\"\n exit\nsnmp-server community \"public\" unrestricted\noobm\n ip address 172.16.7.3 255.255.254.0\n ip default-gateway 172.16.6.1\n ipv6 enable\n ipv6 address dhcp full\n member 1\n ip address dhcp-bootp\n exit\n exit\nvlan 1\n name \"DEFAULT_VLAN\"\n untagged 1/1-1/48\n ip address 172.16.7.3 255.255.254.0\n ipv6 enable\n ipv6 address dhcp full\n exit\npassword password\n\n\u0000", + "running": "\nRunning configuration:\n\n; hpStack_WC Configuration Editor; Created on release #WC.16.10.0009\n; Ver #14:67.6f.f8.1d.9b.3f.bf.bb.ef.7c.59.fc.6b.fb.9f.fc.ff.ff.37.ef:44\n\nstacking\n member 1 type \"JL322A\" mac-address 000000-000000\n exit\nhostname \"Aruba-Stack-2930M\"\nrest-interface session-idle-timeout 120\nweb-management ssl\nip default-gateway 172.16.6.1\nip dns domain-name \"arubaos.napalm\"\nip dns server-address priority 1 8.8.8.8\nip dns server-address priority 2 1.1.1.1\ninterface 1/10\n name \"test\"\n exit\ninterface 1/12\n name \"blubdf\"\n exit\ninterface 1/48\n name \"test\"\n exit\nsnmp-server community \"public\" unrestricted\noobm\n ip address 172.16.7.3 255.255.254.0\n ip default-gateway 172.16.6.1\n ipv6 enable\n ipv6 address dhcp full\n member 1\n ip address dhcp-bootp\n exit\n exit\nvlan 1\n name \"DEFAULT_VLAN\"\n untagged 1/1-1/48\n ip address 172.16.7.3 255.255.254.0\n ipv6 enable\n ipv6 address dhcp full\n exit\npassword password\n\n\u0000" +} \ No newline at end of file diff --git a/test/unit/mocked_data/test_get_config_sanitized/stack/cli_mapping.json b/test/unit/mocked_data/test_get_config_sanitized/stack/cli_mapping.json new file mode 100644 index 0000000..2dccc53 --- /dev/null +++ b/test/unit/mocked_data/test_get_config_sanitized/stack/cli_mapping.json @@ -0,0 +1,5 @@ +{ + "display saved-configuration": "; hpStack_WC Configuration Editor; Created on release #WC.16.10.0009\n; Ver #14:67.6f.f8.1d.9b.3f.bf.bb.ef.7c.59.fc.6b.fb.9f.fc.ff.ff.37.ef:44\n\nstacking\n member 1 type \"JL322A\" mac-address 000000-000000\n exit\nhostname \"Aruba-Stack-2930M\"\nrest-interface session-idle-timeout 120\nweb-management ssl\nip default-gateway 172.16.6.1\nip dns domain-name \"arubaos.napalm\"\nip dns server-address priority 1 8.8.8.8\nip dns server-address priority 2 1.1.1.1\ninterface 1/10\n name \"test\"\n exit\ninterface 1/12\n name \"blubdf\"\n exit\ninterface 1/48\n name \"test\"\n exit\nsnmp-server community \"public\" unrestricted\noobm\n ip address 172.16.7.3 255.255.254.0\n ip default-gateway 172.16.6.1\n ipv6 enable\n ipv6 address dhcp full\n member 1\n ip address dhcp-bootp\n exit\n exit\nvlan 1\n name \"DEFAULT_VLAN\"\n untagged 1/1-1/48\n ip address 172.16.7.3 255.255.254.0\n ipv6 enable\n ipv6 address dhcp full\n exit\npassword password\n\n\u0000", + "show config REST_Payload_Backup": "; hpStack_WC Configuration Editor; Created on release #WC.16.10.0009\n; Ver #14:67.6f.f8.1d.9b.3f.bf.bb.ef.7c.59.fc.6b.fb.9f.fc.ff.ff.37.ef:44\n\nstacking\n member 1 type \"JL322A\" mac-address 000000-000000\n exit\nhostname \"Aruba-Stack-2930M\"\nrest-interface session-idle-timeout 120\nweb-management ssl\nip default-gateway 172.16.6.1\nip dns domain-name \"arubaos.napalm\"\nip dns server-address priority 1 8.8.8.8\nip dns server-address priority 2 1.1.1.1\ninterface 1/10\n name \"test\"\n exit\ninterface 1/48\n name \"test\"\n exit\nsnmp-server community \"public\" unrestricted\noobm\n ip address 172.16.7.3 255.255.254.0\n ip default-gateway 172.16.6.1\n ipv6 enable\n ipv6 address dhcp full\n member 1\n ip address dhcp-bootp\n exit\n exit\nvlan 1\n name \"DEFAULT_VLAN\"\n untagged 1/1-1/48\n ip address 172.16.7.3 255.255.254.0\n ipv6 enable\n ipv6 address dhcp full\n exit\npassword password\n\n\u0000", + "show running-config": "\nRunning configuration:\n\n; hpStack_WC Configuration Editor; Created on release #WC.16.10.0009\n; Ver #14:67.6f.f8.1d.9b.3f.bf.bb.ef.7c.59.fc.6b.fb.9f.fc.ff.ff.37.ef:44\n\nstacking\n member 1 type \"JL322A\" mac-address 000000-000000\n exit\nhostname \"Aruba-Stack-2930M\"\nrest-interface session-idle-timeout 120\nweb-management ssl\nip default-gateway 172.16.6.1\nip dns domain-name \"arubaos.napalm\"\nip dns server-address priority 1 8.8.8.8\nip dns server-address priority 2 1.1.1.1\ninterface 1/10\n name \"test\"\n exit\ninterface 1/12\n name \"blubdf\"\n exit\ninterface 1/48\n name \"test\"\n exit\nsnmp-server community \"public\" unrestricted\noobm\n ip address 172.16.7.3 255.255.254.0\n ip default-gateway 172.16.6.1\n ipv6 enable\n ipv6 address dhcp full\n member 1\n ip address dhcp-bootp\n exit\n exit\nvlan 1\n name \"DEFAULT_VLAN\"\n untagged 1/1-1/48\n ip address 172.16.7.3 255.255.254.0\n ipv6 enable\n ipv6 address dhcp full\n exit\npassword password\n\n\u0000" +} \ No newline at end of file diff --git a/test/unit/mocked_data/test_get_config_sanitized/stack/expected_result.json b/test/unit/mocked_data/test_get_config_sanitized/stack/expected_result.json new file mode 100644 index 0000000..b92be02 --- /dev/null +++ b/test/unit/mocked_data/test_get_config_sanitized/stack/expected_result.json @@ -0,0 +1,5 @@ +{ + "startup": "; hpStack_WC Configuration Editor; Created on release #WC.16.10.0009\n; Ver #14:67.6f.f8.1d.9b.3f.bf.bb.ef.7c.59.fc.6b.fb.9f.fc.ff.ff.37.ef:44\n\nstacking\n member 1 type \"JL322A\" mac-address 000000-000000\n exit\nhostname \"Aruba-Stack-2930M\"\nrest-interface session-idle-timeout 120\nweb-management ssl\nip default-gateway 172.16.6.1\nip dns domain-name \"arubaos.napalm\"\nip dns server-address priority 1 8.8.8.8\nip dns server-address priority 2 1.1.1.1\ninterface 1/10\n name \"test\"\n exit\ninterface 1/12\n name \"blubdf\"\n exit\ninterface 1/48\n name \"test\"\n exit\nsnmp-server community \"public\" unrestricted\noobm\n ip address 172.16.7.3 255.255.254.0\n ip default-gateway 172.16.6.1\n ipv6 enable\n ipv6 address dhcp full\n member 1\n ip address dhcp-bootp\n exit\n exit\nvlan 1\n name \"DEFAULT_VLAN\"\n untagged 1/1-1/48\n ip address 172.16.7.3 255.255.254.0\n ipv6 enable\n ipv6 address dhcp full\n exit\npassword password\n\n\u0000", + "candidate": "; hpStack_WC Configuration Editor; Created on release #WC.16.10.0009\n; Ver #14:67.6f.f8.1d.9b.3f.bf.bb.ef.7c.59.fc.6b.fb.9f.fc.ff.ff.37.ef:44\n\nstacking\n member 1 type \"JL322A\" mac-address 000000-000000\n exit\nhostname \"Aruba-Stack-2930M\"\nrest-interface session-idle-timeout 120\nweb-management ssl\nip default-gateway 172.16.6.1\nip dns domain-name \"arubaos.napalm\"\nip dns server-address priority 1 8.8.8.8\nip dns server-address priority 2 1.1.1.1\ninterface 1/10\n name \"test\"\n exit\ninterface 1/48\n name \"test\"\n exit\nsnmp-server community \"public\" unrestricted\noobm\n ip address 172.16.7.3 255.255.254.0\n ip default-gateway 172.16.6.1\n ipv6 enable\n ipv6 address dhcp full\n member 1\n ip address dhcp-bootp\n exit\n exit\nvlan 1\n name \"DEFAULT_VLAN\"\n untagged 1/1-1/48\n ip address 172.16.7.3 255.255.254.0\n ipv6 enable\n ipv6 address dhcp full\n exit\npassword password\n\n\u0000", + "running": "\nRunning configuration:\n\n; hpStack_WC Configuration Editor; Created on release #WC.16.10.0009\n; Ver #14:67.6f.f8.1d.9b.3f.bf.bb.ef.7c.59.fc.6b.fb.9f.fc.ff.ff.37.ef:44\n\nstacking\n member 1 type \"JL322A\" mac-address 000000-000000\n exit\nhostname \"Aruba-Stack-2930M\"\nrest-interface session-idle-timeout 120\nweb-management ssl\nip default-gateway 172.16.6.1\nip dns domain-name \"arubaos.napalm\"\nip dns server-address priority 1 8.8.8.8\nip dns server-address priority 2 1.1.1.1\ninterface 1/10\n name \"test\"\n exit\ninterface 1/12\n name \"blubdf\"\n exit\ninterface 1/48\n name \"test\"\n exit\nsnmp-server community \"public\" unrestricted\noobm\n ip address 172.16.7.3 255.255.254.0\n ip default-gateway 172.16.6.1\n ipv6 enable\n ipv6 address dhcp full\n member 1\n ip address dhcp-bootp\n exit\n exit\nvlan 1\n name \"DEFAULT_VLAN\"\n untagged 1/1-1/48\n ip address 172.16.7.3 255.255.254.0\n ipv6 enable\n ipv6 address dhcp full\n exit\npassword password\n\n\u0000" +} \ No newline at end of file diff --git a/test/unit/mocked_data/test_get_facts/normal/expected_result.json b/test/unit/mocked_data/test_get_facts/normal/expected_result.json new file mode 100644 index 0000000..8e757fc --- /dev/null +++ b/test/unit/mocked_data/test_get_facts/normal/expected_result.json @@ -0,0 +1,63 @@ +{ + "vendor": "HPE Aruba", + "interface_list": [ + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "10", + "11", + "12", + "13", + "14", + "15", + "16", + "17", + "18", + "19", + "20", + "21", + "22", + "23", + "24", + "25", + "26", + "27", + "28", + "29", + "30", + "31", + "32", + "33", + "34", + "35", + "36", + "37", + "38", + "39", + "40", + "41", + "42", + "43", + "44", + "45T", + "46T", + "47T", + "48T", + "45S", + "46S", + "47S", + "48S" + ], + "uptime": -1, + "hostname": "Aruba-2930M-48G-PoEP", + "os_version": "WC.16.10.0009", + "serial_number": "ABC123456", + "model": "Aruba2930M-48G-PoE+ Switch(JL322A)", + "fqdn": "Aruba-2930M-48G-PoEP.arubaos.napalm" +} \ No newline at end of file diff --git a/test/unit/mocked_data/test_get_facts/normal/facts.json b/test/unit/mocked_data/test_get_facts/normal/facts.json new file mode 100644 index 0000000..b08bcf7 --- /dev/null +++ b/test/unit/mocked_data/test_get_facts/normal/facts.json @@ -0,0 +1,832 @@ +{ + "system/status/global_info": { + "status": 404, + "ok": false, + "data": {} + }, + "system/status": { + "status": 200, + "data": { + "uri": "/system/status", + "name": "Aruba-2930M-48G-PoEP", + "serial_number": "ABC123456", + "firmware_version": "WC.16.10.0009", + "hardware_revision": "JL322A", + "product_model": "Aruba2930M-48G-PoE+ Switch(JL322A)", + "base_ethernet_address": { + "version": "MAV_EUI_48", + "octets": "000000-000000" + }, + "current_ip_address": { + "version": "IAV_IP_V4", + "octets": "172.16.7.3" + }, + "total_memory_in_bytes": 339329536, + "total_poe_consumption": 0, + "sys_temp": 22, + "sys_temp_threshold": 55, + "sys_fan_status": true + } + }, + "system/status/members/1": { + "status": 404, + "ok": false, + "data": {} + }, + "system/status/switch": { + "status": 200, + "data": { + "uri": "/system/status/switch", + "switch_type": "ST_STANDALONE", + "product_name": "Aruba2930M-48G-PoE+ Switch(JL322A)", + "product_number": "JL322A", + "hardware_info": [ + { + "hardware_type": "SHT_FAN", + "status": "SHS_OK" + }, + { + "hardware_type": "SHT_TEMP", + "status": "SHS_OK" + }, + { + "hardware_type": "SHT_PS", + "status": "SHS_OK" + }, + { + "hardware_type": "SHT_PS", + "status": "SHS_OK" + } + ], + "oobm_ports": [ + { + "port_id": 4883, + "port_name": "OOBM", + "type": "PT_RJ45", + "sub_type": "10/100TX", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_UP", + "mode": "PCM_AUTO", + "alignment": "PA_TOP" + } + ], + "is_poe_supported": true, + "blades": [ + { + "product_number": "JL322A", + "data_ports": [ + { + "port_id": 1, + "port_name": "1", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_TOP", + "is_smartrate": false + }, + { + "port_id": 2, + "port_name": "2", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_BOTTOM", + "is_smartrate": false + }, + { + "port_id": 3, + "port_name": "3", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_TOP", + "is_smartrate": false + }, + { + "port_id": 4, + "port_name": "4", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_BOTTOM", + "is_smartrate": false + }, + { + "port_id": 5, + "port_name": "5", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_TOP", + "is_smartrate": false + }, + { + "port_id": 6, + "port_name": "6", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_BOTTOM", + "is_smartrate": false + }, + { + "port_id": 7, + "port_name": "7", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_TOP", + "is_smartrate": false + }, + { + "port_id": 8, + "port_name": "8", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_BOTTOM", + "is_smartrate": false + }, + { + "port_id": 9, + "port_name": "9", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_TOP", + "is_smartrate": false + }, + { + "port_id": 10, + "port_name": "10", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_BOTTOM", + "is_smartrate": false + }, + { + "port_id": 11, + "port_name": "11", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_TOP", + "is_smartrate": false + }, + { + "port_id": 12, + "port_name": "12", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_BOTTOM", + "is_smartrate": false + }, + { + "port_id": 13, + "port_name": "13", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_TOP", + "is_smartrate": false + }, + { + "port_id": 14, + "port_name": "14", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_BOTTOM", + "is_smartrate": false + }, + { + "port_id": 15, + "port_name": "15", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_TOP", + "is_smartrate": false + }, + { + "port_id": 16, + "port_name": "16", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_BOTTOM", + "is_smartrate": false + }, + { + "port_id": 17, + "port_name": "17", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_TOP", + "is_smartrate": false + }, + { + "port_id": 18, + "port_name": "18", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_BOTTOM", + "is_smartrate": false + }, + { + "port_id": 19, + "port_name": "19", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_TOP", + "is_smartrate": false + }, + { + "port_id": 20, + "port_name": "20", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_BOTTOM", + "is_smartrate": false + }, + { + "port_id": 21, + "port_name": "21", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_TOP", + "is_smartrate": false + }, + { + "port_id": 22, + "port_name": "22", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_BOTTOM", + "is_smartrate": false + }, + { + "port_id": 23, + "port_name": "23", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_TOP", + "is_smartrate": false + }, + { + "port_id": 24, + "port_name": "24", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_BOTTOM", + "is_smartrate": false + }, + { + "port_id": 25, + "port_name": "25", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_TOP", + "is_smartrate": false + }, + { + "port_id": 26, + "port_name": "26", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_BOTTOM", + "is_smartrate": false + }, + { + "port_id": 27, + "port_name": "27", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_TOP", + "is_smartrate": false + }, + { + "port_id": 28, + "port_name": "28", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_BOTTOM", + "is_smartrate": false + }, + { + "port_id": 29, + "port_name": "29", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_TOP", + "is_smartrate": false + }, + { + "port_id": 30, + "port_name": "30", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_BOTTOM", + "is_smartrate": false + }, + { + "port_id": 31, + "port_name": "31", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_TOP", + "is_smartrate": false + }, + { + "port_id": 32, + "port_name": "32", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_BOTTOM", + "is_smartrate": false + }, + { + "port_id": 33, + "port_name": "33", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_TOP", + "is_smartrate": false + }, + { + "port_id": 34, + "port_name": "34", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_BOTTOM", + "is_smartrate": false + }, + { + "port_id": 35, + "port_name": "35", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_TOP", + "is_smartrate": false + }, + { + "port_id": 36, + "port_name": "36", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_BOTTOM", + "is_smartrate": false + }, + { + "port_id": 37, + "port_name": "37", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_TOP", + "is_smartrate": false + }, + { + "port_id": 38, + "port_name": "38", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_BOTTOM", + "is_smartrate": false + }, + { + "port_id": 39, + "port_name": "39", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_TOP", + "is_smartrate": false + }, + { + "port_id": 40, + "port_name": "40", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_BOTTOM", + "is_smartrate": false + }, + { + "port_id": 41, + "port_name": "41", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_TOP", + "is_smartrate": false + }, + { + "port_id": 42, + "port_name": "42", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_BOTTOM", + "is_smartrate": false + }, + { + "port_id": 43, + "port_name": "43", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_TOP", + "is_smartrate": false + }, + { + "port_id": 44, + "port_name": "44", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_BOTTOM", + "is_smartrate": false + }, + { + "port_id": 45, + "port_name": "45T", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_TOP", + "is_smartrate": false + }, + { + "port_id": 46, + "port_name": "46T", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_BOTTOM", + "is_smartrate": false + }, + { + "port_id": 47, + "port_name": "47T", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_TOP", + "is_smartrate": false + }, + { + "port_id": 48, + "port_name": "48T", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_BOTTOM", + "is_smartrate": false + }, + { + "port_id": 45, + "port_name": "45S", + "type": "PT_GBIC", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_TOP", + "is_smartrate": false + }, + { + "port_id": 46, + "port_name": "46S", + "type": "PT_GBIC", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_BOTTOM", + "is_smartrate": false + }, + { + "port_id": 47, + "port_name": "47S", + "type": "PT_GBIC", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_TOP", + "is_smartrate": false + }, + { + "port_id": 48, + "port_name": "48S", + "type": "PT_GBIC", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_BOTTOM", + "is_smartrate": false + } + ], + "expansion_modules": [] + } + ] + } + }, + "dns": { + "status": 200, + "data": { + "uri": "/dns", + "dns_config_mode": "DCM_MANUAL", + "server_1": { + "version": "IAV_IP_V4", + "octets": "8.8.8.8" + }, + "server_2": { + "version": "IAV_IP_V4", + "octets": "1.1.1.1" + }, + "dns_domain_names": [ + "arubaos.napalm" + ], + "server_3": null, + "server_4": null + } + } +} \ No newline at end of file diff --git a/test/unit/mocked_data/test_get_facts/stack/expected_result.json b/test/unit/mocked_data/test_get_facts/stack/expected_result.json new file mode 100644 index 0000000..b9b00d3 --- /dev/null +++ b/test/unit/mocked_data/test_get_facts/stack/expected_result.json @@ -0,0 +1,63 @@ +{ + "vendor": "HPE Aruba", + "interface_list": [ + "1/1", + "1/2", + "1/3", + "1/4", + "1/5", + "1/6", + "1/7", + "1/8", + "1/9", + "1/10", + "1/11", + "1/12", + "1/13", + "1/14", + "1/15", + "1/16", + "1/17", + "1/18", + "1/19", + "1/20", + "1/21", + "1/22", + "1/23", + "1/24", + "1/25", + "1/26", + "1/27", + "1/28", + "1/29", + "1/30", + "1/31", + "1/32", + "1/33", + "1/34", + "1/35", + "1/36", + "1/37", + "1/38", + "1/39", + "1/40", + "1/41", + "1/42", + "1/43", + "1/44", + "1/45T", + "1/46T", + "1/47T", + "1/48T", + "1/45S", + "1/46S", + "1/47S", + "1/48S" + ], + "uptime": -1, + "hostname": "Aruba-Stack-2930M", + "os_version": "WC.16.10.0009", + "serial_number": "ABC123456", + "model": "Aruba2930M-48G-PoE+ Swit(JL322A)", + "fqdn": "Aruba-Stack-2930M.arubaos.napalm" +} \ No newline at end of file diff --git a/test/unit/mocked_data/test_get_facts/stack/facts.json b/test/unit/mocked_data/test_get_facts/stack/facts.json new file mode 100644 index 0000000..2a4e741 --- /dev/null +++ b/test/unit/mocked_data/test_get_facts/stack/facts.json @@ -0,0 +1,837 @@ +{ + "system/status/global_info": { + "status": 200, + "data": { + "name": "Aruba-Stack-2930M", + "firmware_version": "WC.16.10.0009", + "base_ethernet_address": { + "version": "MAV_EUI_48", + "octets": "000000-000000" + }, + "current_ip_address": { + "version": "IAV_IP_V4", + "octets": "172.16.7.3" + } + } + }, + "system/status": { + "status": 404, + "ok": false, + "data": {} + }, + "system/status/members/1": { + "status": 200, + "data": { + "uri": "/system/status/members/1", + "member_id": 1, + "serial_number": "ABC123456", + "hardware_revision": "JL322A", + "product_model": "Aruba2930M-48G-PoE+ Swit(JL322A)", + "mac_address": { + "version": "MAV_EUI_48", + "octets": "000000-000000" + }, + "total_memory_in_bytes": 339329536, + "total_poe_consumption": 0, + "sys_temp": "22C", + "sys_temp_threshold": "55C", + "sys_fan_status": false + } + }, + "system/status/switch": { + "status": 200, + "data": { + "uri": "/system/status/switch", + "switch_type": "ST_STACKED", + "blades": [ + { + "stack_member": 1, + "product_name": "Aruba2930M-48G-PoE+ Swit(JL322A)", + "product_number": "JL322A", + "hardware_info": [ + { + "hardware_type": "SHT_FAN", + "status": "SHS_OK" + }, + { + "hardware_type": "SHT_TEMP", + "status": "SHS_OK" + }, + { + "hardware_type": "SHT_PS", + "status": "SHS_OK" + }, + { + "hardware_type": "SHT_PS", + "status": "SHS_ERROR" + } + ], + "oobm_ports": [ + { + "port_id": 4884, + "port_name": "OOBM", + "type": "PT_RJ45", + "sub_type": "10/100TX", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_UP", + "mode": "PCM_AUTO", + "alignment": "PA_TOP" + } + ], + "is_poe_supported": true, + "data_ports": [ + { + "port_id": 1, + "port_name": "1/1", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_TOP", + "is_smartrate": false + }, + { + "port_id": 2, + "port_name": "1/2", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_BOTTOM", + "is_smartrate": false + }, + { + "port_id": 3, + "port_name": "1/3", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_TOP", + "is_smartrate": false + }, + { + "port_id": 4, + "port_name": "1/4", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_BOTTOM", + "is_smartrate": false + }, + { + "port_id": 5, + "port_name": "1/5", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_TOP", + "is_smartrate": false + }, + { + "port_id": 6, + "port_name": "1/6", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_BOTTOM", + "is_smartrate": false + }, + { + "port_id": 7, + "port_name": "1/7", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_TOP", + "is_smartrate": false + }, + { + "port_id": 8, + "port_name": "1/8", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_BOTTOM", + "is_smartrate": false + }, + { + "port_id": 9, + "port_name": "1/9", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_TOP", + "is_smartrate": false + }, + { + "port_id": 10, + "port_name": "1/10", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_BOTTOM", + "is_smartrate": false + }, + { + "port_id": 11, + "port_name": "1/11", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_TOP", + "is_smartrate": false + }, + { + "port_id": 12, + "port_name": "1/12", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_BOTTOM", + "is_smartrate": false + }, + { + "port_id": 13, + "port_name": "1/13", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_TOP", + "is_smartrate": false + }, + { + "port_id": 14, + "port_name": "1/14", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_BOTTOM", + "is_smartrate": false + }, + { + "port_id": 15, + "port_name": "1/15", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_TOP", + "is_smartrate": false + }, + { + "port_id": 16, + "port_name": "1/16", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_BOTTOM", + "is_smartrate": false + }, + { + "port_id": 17, + "port_name": "1/17", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_TOP", + "is_smartrate": false + }, + { + "port_id": 18, + "port_name": "1/18", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_BOTTOM", + "is_smartrate": false + }, + { + "port_id": 19, + "port_name": "1/19", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_TOP", + "is_smartrate": false + }, + { + "port_id": 20, + "port_name": "1/20", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_BOTTOM", + "is_smartrate": false + }, + { + "port_id": 21, + "port_name": "1/21", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_TOP", + "is_smartrate": false + }, + { + "port_id": 22, + "port_name": "1/22", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_BOTTOM", + "is_smartrate": false + }, + { + "port_id": 23, + "port_name": "1/23", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_TOP", + "is_smartrate": false + }, + { + "port_id": 24, + "port_name": "1/24", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_BOTTOM", + "is_smartrate": false + }, + { + "port_id": 25, + "port_name": "1/25", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_TOP", + "is_smartrate": false + }, + { + "port_id": 26, + "port_name": "1/26", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_BOTTOM", + "is_smartrate": false + }, + { + "port_id": 27, + "port_name": "1/27", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_TOP", + "is_smartrate": false + }, + { + "port_id": 28, + "port_name": "1/28", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_BOTTOM", + "is_smartrate": false + }, + { + "port_id": 29, + "port_name": "1/29", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_TOP", + "is_smartrate": false + }, + { + "port_id": 30, + "port_name": "1/30", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_BOTTOM", + "is_smartrate": false + }, + { + "port_id": 31, + "port_name": "1/31", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_TOP", + "is_smartrate": false + }, + { + "port_id": 32, + "port_name": "1/32", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_BOTTOM", + "is_smartrate": false + }, + { + "port_id": 33, + "port_name": "1/33", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_TOP", + "is_smartrate": false + }, + { + "port_id": 34, + "port_name": "1/34", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_BOTTOM", + "is_smartrate": false + }, + { + "port_id": 35, + "port_name": "1/35", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_TOP", + "is_smartrate": false + }, + { + "port_id": 36, + "port_name": "1/36", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_BOTTOM", + "is_smartrate": false + }, + { + "port_id": 37, + "port_name": "1/37", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_TOP", + "is_smartrate": false + }, + { + "port_id": 38, + "port_name": "1/38", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_BOTTOM", + "is_smartrate": false + }, + { + "port_id": 39, + "port_name": "1/39", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_TOP", + "is_smartrate": false + }, + { + "port_id": 40, + "port_name": "1/40", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_BOTTOM", + "is_smartrate": false + }, + { + "port_id": 41, + "port_name": "1/41", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_TOP", + "is_smartrate": false + }, + { + "port_id": 42, + "port_name": "1/42", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_BOTTOM", + "is_smartrate": false + }, + { + "port_id": 43, + "port_name": "1/43", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_TOP", + "is_smartrate": false + }, + { + "port_id": 44, + "port_name": "1/44", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_BOTTOM", + "is_smartrate": false + }, + { + "port_id": 45, + "port_name": "1/45T", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_TOP", + "is_smartrate": false + }, + { + "port_id": 46, + "port_name": "1/46T", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_BOTTOM", + "is_smartrate": false + }, + { + "port_id": 47, + "port_name": "1/47T", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_TOP", + "is_smartrate": false + }, + { + "port_id": 48, + "port_name": "1/48T", + "type": "PT_RJ45", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_BOTTOM", + "is_smartrate": false + }, + { + "port_id": 45, + "port_name": "1/45S", + "type": "PT_GBIC", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_TOP", + "is_smartrate": false + }, + { + "port_id": 46, + "port_name": "1/46S", + "type": "PT_GBIC", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_BOTTOM", + "is_smartrate": false + }, + { + "port_id": 47, + "port_name": "1/47S", + "type": "PT_GBIC", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_TOP", + "is_smartrate": false + }, + { + "port_id": 48, + "port_name": "1/48S", + "type": "PT_GBIC", + "adminStatus": "ADMIN_UP", + "operStatus": "OPER_DOWN", + "sub_type": "100/1000T", + "mode": "PCM_AUTO", + "is_internal": false, + "oper_mode": "OM_1000_FDX", + "poe_status": "POES_SEARCHING", + "alignment": "PA_BOTTOM", + "is_smartrate": false + } + ], + "expansion_modules": [] + } + ] + } + }, + "dns": { + "status": 200, + "data": { + "uri": "/dns", + "dns_config_mode": "DCM_MANUAL", + "server_1": { + "version": "IAV_IP_V4", + "octets": "8.8.8.8" + }, + "server_2": { + "version": "IAV_IP_V4", + "octets": "1.1.1.1" + }, + "dns_domain_names": [ + "arubaos.napalm" + ], + "server_3": null, + "server_4": null + } + } +} \ No newline at end of file diff --git a/test/unit/mocked_data/test_get_interfaces/normal/cli_mapping.json b/test/unit/mocked_data/test_get_interfaces/normal/cli_mapping.json new file mode 100644 index 0000000..96e9b54 --- /dev/null +++ b/test/unit/mocked_data/test_get_interfaces/normal/cli_mapping.json @@ -0,0 +1,16 @@ +{ + "show interfaces 1 | include MAC[[:space:]]Address": " MAC Address : 000000-00aebf ", + "show interfaces 2 | include MAC[[:space:]]Address": " MAC Address : 000000-00aebe ", + "show interfaces 3 | include MAC[[:space:]]Address": " MAC Address : 000000-00aebd ", + "show interfaces 4 | include MAC[[:space:]]Address": " MAC Address : 000000-00aebc ", + "show interfaces 5 | include MAC[[:space:]]Address": " MAC Address : 000000-00aebb ", + "show interfaces 6 | include MAC[[:space:]]Address": " MAC Address : 000000-00aeba ", + "show interfaces 7 | include MAC[[:space:]]Address": " MAC Address : 000000-00aeb9 ", + "show interfaces 8 | include MAC[[:space:]]Address": " MAC Address : 000000-00aeb8 ", + "show interfaces 9 | include MAC[[:space:]]Address": " MAC Address : 000000-00aeb7 ", + "show interfaces 10 | include MAC[[:space:]]Address": " MAC Address : 000000-00aeb6 ", + "show interfaces 11 | include MAC[[:space:]]Address": " MAC Address : 000000-00aeb5 ", + "show interfaces 12 | include MAC[[:space:]]Address": " MAC Address : 000000-00aeb4 ", + "show interfaces 13 | include MAC[[:space:]]Address": " MAC Address : 000000-00aeb3 ", + "show interfaces 14 | include MAC[[:space:]]Address": " MAC Address : 000000-00aeb2 " +} diff --git a/test/unit/mocked_data/test_get_interfaces/normal/expected_result.json b/test/unit/mocked_data/test_get_interfaces/normal/expected_result.json new file mode 100644 index 0000000..e5dbfa0 --- /dev/null +++ b/test/unit/mocked_data/test_get_interfaces/normal/expected_result.json @@ -0,0 +1,128 @@ +{ + "1": { + "is_up": false, + "is_enabled": true, + "description": "", + "last_flapped": -1.0, + "speed": 1000, + "mtu": -1, + "mac_address": "00:00:00:00:AE:BF" + }, + "2": { + "is_up": false, + "is_enabled": true, + "description": "", + "last_flapped": -1.0, + "speed": 1000, + "mtu": -1, + "mac_address": "00:00:00:00:AE:BE" + }, + "3": { + "is_up": false, + "is_enabled": true, + "description": "", + "last_flapped": -1.0, + "speed": 1000, + "mtu": -1, + "mac_address": "00:00:00:00:AE:BD" + }, + "4": { + "is_up": false, + "is_enabled": true, + "description": "", + "last_flapped": -1.0, + "speed": 1000, + "mtu": -1, + "mac_address": "00:00:00:00:AE:BC" + }, + "5": { + "is_up": false, + "is_enabled": true, + "description": "", + "last_flapped": -1.0, + "speed": 1000, + "mtu": -1, + "mac_address": "00:00:00:00:AE:BB" + }, + "6": { + "is_up": false, + "is_enabled": true, + "description": "", + "last_flapped": -1.0, + "speed": 1000, + "mtu": -1, + "mac_address": "00:00:00:00:AE:BA" + }, + "7": { + "is_up": false, + "is_enabled": true, + "description": "", + "last_flapped": -1.0, + "speed": 1000, + "mtu": -1, + "mac_address": "00:00:00:00:AE:B9" + }, + "8": { + "is_up": false, + "is_enabled": true, + "description": "", + "last_flapped": -1.0, + "speed": 1000, + "mtu": -1, + "mac_address": "00:00:00:00:AE:B8" + }, + "9": { + "is_up": false, + "is_enabled": true, + "description": "", + "last_flapped": -1.0, + "speed": 1000, + "mtu": -1, + "mac_address": "00:00:00:00:AE:B7" + }, + "10": { + "is_up": false, + "is_enabled": true, + "description": "test-new", + "last_flapped": -1.0, + "speed": 1000, + "mtu": -1, + "mac_address": "00:00:00:00:AE:B6" + }, + "11": { + "is_up": false, + "is_enabled": true, + "description": "", + "last_flapped": -1.0, + "speed": 1000, + "mtu": -1, + "mac_address": "00:00:00:00:AE:B5" + }, + "12": { + "is_up": false, + "is_enabled": true, + "description": "blah", + "last_flapped": -1.0, + "speed": 1000, + "mtu": -1, + "mac_address": "00:00:00:00:AE:B4" + }, + "13": { + "is_up": false, + "is_enabled": true, + "description": "", + "last_flapped": -1.0, + "speed": 1000, + "mtu": -1, + "mac_address": "00:00:00:00:AE:B3" + }, + "14": { + "is_up": false, + "is_enabled": true, + "description": "", + "last_flapped": -1.0, + "speed": 1000, + "mtu": -1, + "mac_address": "00:00:00:00:AE:B2" + } +} diff --git a/test/unit/mocked_data/test_get_interfaces/normal/facts.json b/test/unit/mocked_data/test_get_interfaces/normal/facts.json new file mode 100644 index 0000000..e3fd26a --- /dev/null +++ b/test/unit/mocked_data/test_get_interfaces/normal/facts.json @@ -0,0 +1,416 @@ +{ + "ports": { + "status": 200, + "data": { + "collection_result": { + "total_elements_count": 14, + "filtered_elements_count": 14 + }, + "port_element": [ + { + "uri": "/ports/1", + "id": "1", + "name": "", + "is_port_enabled": true, + "is_port_up": false, + "config_mode": "PCM_AUTO", + "trunk_mode": "PTT_NONE", + "lacp_status": "LAS_DISABLED", + "trunk_group": "", + "is_flow_control_enabled": false, + "is_dsnoop_port_trusted": false + }, + { + "uri": "/ports/2", + "id": "2", + "name": "", + "is_port_enabled": true, + "is_port_up": false, + "config_mode": "PCM_AUTO", + "trunk_mode": "PTT_NONE", + "lacp_status": "LAS_DISABLED", + "trunk_group": "", + "is_flow_control_enabled": false, + "is_dsnoop_port_trusted": false + }, + { + "uri": "/ports/3", + "id": "3", + "name": "", + "is_port_enabled": true, + "is_port_up": false, + "config_mode": "PCM_AUTO", + "trunk_mode": "PTT_NONE", + "lacp_status": "LAS_DISABLED", + "trunk_group": "", + "is_flow_control_enabled": false, + "is_dsnoop_port_trusted": false + }, + { + "uri": "/ports/4", + "id": "4", + "name": "", + "is_port_enabled": true, + "is_port_up": false, + "config_mode": "PCM_AUTO", + "trunk_mode": "PTT_NONE", + "lacp_status": "LAS_DISABLED", + "trunk_group": "", + "is_flow_control_enabled": false, + "is_dsnoop_port_trusted": false + }, + { + "uri": "/ports/5", + "id": "5", + "name": "", + "is_port_enabled": true, + "is_port_up": false, + "config_mode": "PCM_AUTO", + "trunk_mode": "PTT_NONE", + "lacp_status": "LAS_DISABLED", + "trunk_group": "", + "is_flow_control_enabled": false, + "is_dsnoop_port_trusted": false + }, + { + "uri": "/ports/6", + "id": "6", + "name": "", + "is_port_enabled": true, + "is_port_up": false, + "config_mode": "PCM_AUTO", + "trunk_mode": "PTT_NONE", + "lacp_status": "LAS_DISABLED", + "trunk_group": "", + "is_flow_control_enabled": false, + "is_dsnoop_port_trusted": false + }, + { + "uri": "/ports/7", + "id": "7", + "name": "", + "is_port_enabled": true, + "is_port_up": false, + "config_mode": "PCM_AUTO", + "trunk_mode": "PTT_NONE", + "lacp_status": "LAS_DISABLED", + "trunk_group": "", + "is_flow_control_enabled": false, + "is_dsnoop_port_trusted": false + }, + { + "uri": "/ports/8", + "id": "8", + "name": "", + "is_port_enabled": true, + "is_port_up": false, + "config_mode": "PCM_AUTO", + "trunk_mode": "PTT_NONE", + "lacp_status": "LAS_DISABLED", + "trunk_group": "", + "is_flow_control_enabled": false, + "is_dsnoop_port_trusted": false + }, + { + "uri": "/ports/9", + "id": "9", + "name": "", + "is_port_enabled": true, + "is_port_up": false, + "config_mode": "PCM_AUTO", + "trunk_mode": "PTT_NONE", + "lacp_status": "LAS_DISABLED", + "trunk_group": "", + "is_flow_control_enabled": false, + "is_dsnoop_port_trusted": false + }, + { + "uri": "/ports/10", + "id": "10", + "name": "test-new", + "is_port_enabled": true, + "is_port_up": false, + "config_mode": "PCM_AUTO", + "trunk_mode": "PTT_NONE", + "lacp_status": "LAS_DISABLED", + "trunk_group": "", + "is_flow_control_enabled": false, + "is_dsnoop_port_trusted": false + }, + { + "uri": "/ports/11", + "id": "11", + "name": "", + "is_port_enabled": true, + "is_port_up": false, + "config_mode": "PCM_AUTO", + "trunk_mode": "PTT_NONE", + "lacp_status": "LAS_DISABLED", + "trunk_group": "", + "is_flow_control_enabled": false, + "is_dsnoop_port_trusted": false + }, + { + "uri": "/ports/12", + "id": "12", + "name": "blah", + "is_port_enabled": true, + "is_port_up": false, + "config_mode": "PCM_AUTO", + "trunk_mode": "PTT_NONE", + "lacp_status": "LAS_DISABLED", + "trunk_group": "", + "is_flow_control_enabled": false, + "is_dsnoop_port_trusted": false + }, + { + "uri": "/ports/13", + "id": "13", + "name": "", + "is_port_enabled": true, + "is_port_up": false, + "config_mode": "PCM_AUTO", + "trunk_mode": "PTT_NONE", + "lacp_status": "LAS_DISABLED", + "trunk_group": "", + "is_flow_control_enabled": false, + "is_dsnoop_port_trusted": false + }, + { + "uri": "/ports/14", + "id": "14", + "name": "", + "is_port_enabled": true, + "is_port_up": false, + "config_mode": "PCM_AUTO", + "trunk_mode": "PTT_NONE", + "lacp_status": "LAS_DISABLED", + "trunk_group": "", + "is_flow_control_enabled": false, + "is_dsnoop_port_trusted": false + } + ] + } + }, + "port-statistics": { + "status": 200, + "data": { + "port_statistics_element": [ + { + "uri": "/port-statistics/1", + "id": "1", + "name": "", + "packets_tx": 0, + "packets_rx": 0, + "bytes_tx": 0, + "bytes_rx": 0, + "throughput_tx_bps": 0, + "throughput_rx_bps": 0, + "error_tx": 0, + "error_rx": 0, + "drop_tx": 0, + "port_speed_mbps": 1000 + }, + { + "uri": "/port-statistics/2", + "id": "2", + "name": "", + "packets_tx": 0, + "packets_rx": 0, + "bytes_tx": 0, + "bytes_rx": 0, + "throughput_tx_bps": 0, + "throughput_rx_bps": 0, + "error_tx": 0, + "error_rx": 0, + "drop_tx": 0, + "port_speed_mbps": 1000 + }, + { + "uri": "/port-statistics/3", + "id": "3", + "name": "", + "packets_tx": 0, + "packets_rx": 0, + "bytes_tx": 0, + "bytes_rx": 0, + "throughput_tx_bps": 0, + "throughput_rx_bps": 0, + "error_tx": 0, + "error_rx": 0, + "drop_tx": 0, + "port_speed_mbps": 1000 + }, + { + "uri": "/port-statistics/4", + "id": "4", + "name": "", + "packets_tx": 0, + "packets_rx": 0, + "bytes_tx": 0, + "bytes_rx": 0, + "throughput_tx_bps": 0, + "throughput_rx_bps": 0, + "error_tx": 0, + "error_rx": 0, + "drop_tx": 0, + "port_speed_mbps": 1000 + }, + { + "uri": "/port-statistics/5", + "id": "5", + "name": "", + "packets_tx": 0, + "packets_rx": 0, + "bytes_tx": 0, + "bytes_rx": 0, + "throughput_tx_bps": 0, + "throughput_rx_bps": 0, + "error_tx": 0, + "error_rx": 0, + "drop_tx": 0, + "port_speed_mbps": 1000 + }, + { + "uri": "/port-statistics/6", + "id": "6", + "name": "", + "packets_tx": 0, + "packets_rx": 0, + "bytes_tx": 0, + "bytes_rx": 0, + "throughput_tx_bps": 0, + "throughput_rx_bps": 0, + "error_tx": 0, + "error_rx": 0, + "drop_tx": 0, + "port_speed_mbps": 1000 + }, + { + "uri": "/port-statistics/7", + "id": "7", + "name": "", + "packets_tx": 0, + "packets_rx": 0, + "bytes_tx": 0, + "bytes_rx": 0, + "throughput_tx_bps": 0, + "throughput_rx_bps": 0, + "error_tx": 0, + "error_rx": 0, + "drop_tx": 0, + "port_speed_mbps": 1000 + }, + { + "uri": "/port-statistics/8", + "id": "8", + "name": "", + "packets_tx": 0, + "packets_rx": 0, + "bytes_tx": 0, + "bytes_rx": 0, + "throughput_tx_bps": 0, + "throughput_rx_bps": 0, + "error_tx": 0, + "error_rx": 0, + "drop_tx": 0, + "port_speed_mbps": 1000 + }, + { + "uri": "/port-statistics/9", + "id": "9", + "name": "", + "packets_tx": 0, + "packets_rx": 0, + "bytes_tx": 0, + "bytes_rx": 0, + "throughput_tx_bps": 0, + "throughput_rx_bps": 0, + "error_tx": 0, + "error_rx": 0, + "drop_tx": 0, + "port_speed_mbps": 1000 + }, + { + "uri": "/port-statistics/10", + "id": "10", + "name": "test-new", + "packets_tx": 0, + "packets_rx": 0, + "bytes_tx": 0, + "bytes_rx": 0, + "throughput_tx_bps": 0, + "throughput_rx_bps": 0, + "error_tx": 0, + "error_rx": 0, + "drop_tx": 0, + "port_speed_mbps": 1000 + }, + { + "uri": "/port-statistics/11", + "id": "11", + "name": "", + "packets_tx": 0, + "packets_rx": 0, + "bytes_tx": 0, + "bytes_rx": 0, + "throughput_tx_bps": 0, + "throughput_rx_bps": 0, + "error_tx": 0, + "error_rx": 0, + "drop_tx": 0, + "port_speed_mbps": 1000 + }, + { + "uri": "/port-statistics/12", + "id": "12", + "name": "blah", + "packets_tx": 0, + "packets_rx": 0, + "bytes_tx": 0, + "bytes_rx": 0, + "throughput_tx_bps": 0, + "throughput_rx_bps": 0, + "error_tx": 0, + "error_rx": 0, + "drop_tx": 0, + "port_speed_mbps": 1000 + }, + { + "uri": "/port-statistics/13", + "id": "13", + "name": "", + "packets_tx": 0, + "packets_rx": 0, + "bytes_tx": 0, + "bytes_rx": 0, + "throughput_tx_bps": 0, + "throughput_rx_bps": 0, + "error_tx": 0, + "error_rx": 0, + "drop_tx": 0, + "port_speed_mbps": 1000 + }, + { + "uri": "/port-statistics/14", + "id": "14", + "name": "", + "packets_tx": 0, + "packets_rx": 0, + "bytes_tx": 0, + "bytes_rx": 0, + "throughput_tx_bps": 0, + "throughput_rx_bps": 0, + "error_tx": 0, + "error_rx": 0, + "drop_tx": 0, + "port_speed_mbps": 1000 + } + ], + "collection_result": { + "total_elements_count": 14, + "filtered_elements_count": 14 + } + } + } +} \ No newline at end of file diff --git a/test/unit/mocked_data/test_get_interfaces_ip/normal/expected_result.json b/test/unit/mocked_data/test_get_interfaces_ip/normal/expected_result.json new file mode 100644 index 0000000..a4ed18e --- /dev/null +++ b/test/unit/mocked_data/test_get_interfaces_ip/normal/expected_result.json @@ -0,0 +1,9 @@ +{ + "VLAN1": { + "ipv4": { + "172.16.7.3": { + "prefix_length": 23 + } + } + } +} \ No newline at end of file diff --git a/test/unit/mocked_data/test_get_interfaces_ip/normal/facts.json b/test/unit/mocked_data/test_get_interfaces_ip/normal/facts.json new file mode 100644 index 0000000..408ab4f --- /dev/null +++ b/test/unit/mocked_data/test_get_interfaces_ip/normal/facts.json @@ -0,0 +1,26 @@ +{ + "ipaddresses": { + "status": 200, + "data": { + "collection_result": { + "total_elements_count": 1, + "filtered_elements_count": 1 + }, + "ip_address_subnet_element": [ + { + "uri": "/vlans/1/ipaddresses/IAAM_STATIC-172.16.7.3", + "ip_address_mode": "IAAM_STATIC", + "vlan_id": 1, + "ip_address": { + "version": "IAV_IP_V4", + "octets": "172.16.7.3" + }, + "ip_mask": { + "version": "IAV_IP_V4", + "octets": "255.255.254.0" + } + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/mocked_data/test_get_interfaces_ip/stack/expected_result.json b/test/unit/mocked_data/test_get_interfaces_ip/stack/expected_result.json new file mode 100644 index 0000000..a4ed18e --- /dev/null +++ b/test/unit/mocked_data/test_get_interfaces_ip/stack/expected_result.json @@ -0,0 +1,9 @@ +{ + "VLAN1": { + "ipv4": { + "172.16.7.3": { + "prefix_length": 23 + } + } + } +} \ No newline at end of file diff --git a/test/unit/mocked_data/test_get_interfaces_ip/stack/facts.json b/test/unit/mocked_data/test_get_interfaces_ip/stack/facts.json new file mode 100644 index 0000000..408ab4f --- /dev/null +++ b/test/unit/mocked_data/test_get_interfaces_ip/stack/facts.json @@ -0,0 +1,26 @@ +{ + "ipaddresses": { + "status": 200, + "data": { + "collection_result": { + "total_elements_count": 1, + "filtered_elements_count": 1 + }, + "ip_address_subnet_element": [ + { + "uri": "/vlans/1/ipaddresses/IAAM_STATIC-172.16.7.3", + "ip_address_mode": "IAAM_STATIC", + "vlan_id": 1, + "ip_address": { + "version": "IAV_IP_V4", + "octets": "172.16.7.3" + }, + "ip_mask": { + "version": "IAV_IP_V4", + "octets": "255.255.254.0" + } + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/mocked_data/test_get_lldp_neighbors/normal/expected_result.json b/test/unit/mocked_data/test_get_lldp_neighbors/normal/expected_result.json new file mode 100644 index 0000000..d06d053 --- /dev/null +++ b/test/unit/mocked_data/test_get_lldp_neighbors/normal/expected_result.json @@ -0,0 +1,8 @@ +{ + "oobm": [ + { + "hostname": "LAB-EDGE-SWITCH01", + "port": "GigabitEthernet1/0/8" + } + ] +} \ No newline at end of file diff --git a/test/unit/mocked_data/test_get_lldp_neighbors/normal/facts.json b/test/unit/mocked_data/test_get_lldp_neighbors/normal/facts.json new file mode 100644 index 0000000..08abafe --- /dev/null +++ b/test/unit/mocked_data/test_get_lldp_neighbors/normal/facts.json @@ -0,0 +1,48 @@ +{ + "lldp/remote-device": { + "status": 200, + "data": { + "collection_result": { + "total_elements_count": 1, + "filtered_elements_count": 1 + }, + "lldp_remote_device_element": [ + { + "local_port": "oobm", + "chassis_type": "RCT_MAC_ADDRESS", + "chassis_id": "00 00 00 00 00 00", + "port_type": "LPT_INTERFACE_NAME", + "port_id": "GigabitEthernet1/0/8", + "port_description": "ARUBA-MGMT", + "system_name": "LAB-EDGE-SWITCH01", + "system_description": "HP Comware Platform Software, Software Version 5.20.99 Release 2222P01", + "pvid": null, + "capabilities_supported": { + "repeater": false, + "bridge": true, + "wlan_access_point": false, + "router": true, + "telephone": false, + "cable_device": false, + "station_only": false + }, + "capabilities_enabled": { + "repeater": false, + "bridge": true, + "wlan_access_point": false, + "router": true, + "telephone": false, + "cable_device": false, + "station_only": false + }, + "remote_management_address": [ + { + "type": "AFM_IP4", + "address": "192.168.6.6" + } + ] + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/mocked_data/test_get_lldp_neighbors_detail/normal/expected_result.json b/test/unit/mocked_data/test_get_lldp_neighbors_detail/normal/expected_result.json new file mode 100644 index 0000000..1479369 --- /dev/null +++ b/test/unit/mocked_data/test_get_lldp_neighbors_detail/normal/expected_result.json @@ -0,0 +1,20 @@ +{ + "oobm": [ + { + "parent_interface": "", + "remote_system_name": "LAB-EDGE-SWITCH01", + "remote_chassis_id": "00 00 00 00 00 00", + "remote_port": "GigabitEthernet1/0/8", + "remote_port_description": "ARUBA-MGMT", + "remote_system_description": "HP Comware Platform Software, Software Version 5.20.99 Release 2222P01", + "remote_system_capab": [ + "bridge", + "router" + ], + "remote_system_enable_capab": [ + "bridge", + "router" + ] + } + ] +} \ No newline at end of file diff --git a/test/unit/mocked_data/test_get_lldp_neighbors_detail/normal/facts.json b/test/unit/mocked_data/test_get_lldp_neighbors_detail/normal/facts.json new file mode 100644 index 0000000..dd4a8e1 --- /dev/null +++ b/test/unit/mocked_data/test_get_lldp_neighbors_detail/normal/facts.json @@ -0,0 +1,48 @@ +{ + "lldp/remote-device": { + "status": 200, + "data": { + "collection_result": { + "total_elements_count": 1, + "filtered_elements_count": 1 + }, + "lldp_remote_device_element": [ + { + "local_port": "oobm", + "chassis_type": "RCT_MAC_ADDRESS", + "chassis_id": "00 00 00 00 00 00", + "port_type": "LPT_INTERFACE_NAME", + "port_id": "GigabitEthernet1/0/8", + "port_description": "ARUBA-MGMT", + "system_name": "LAB-EDGE-SWITCH01", + "system_description": "HP Comware Platform Software, Software Version 5.20.99 Release 2222P01", + "pvid": null, + "capabilities_supported": { + "repeater": false, + "bridge": true, + "wlan_access_point": false, + "router": true, + "telephone": false, + "cable_device": false, + "station_only": false + }, + "capabilities_enabled": { + "repeater": false, + "bridge": true, + "wlan_access_point": false, + "router": true, + "telephone": false, + "cable_device": false, + "station_only": false + }, + "remote_management_address": [ + { + "type": "AFM_IP4", + "address": "192.168.6.6" + } + ] + } + ] + } + } +} diff --git a/test/unit/mocked_data/test_get_mac_address_table/normal/expected_result.json b/test/unit/mocked_data/test_get_mac_address_table/normal/expected_result.json new file mode 100644 index 0000000..4507923 --- /dev/null +++ b/test/unit/mocked_data/test_get_mac_address_table/normal/expected_result.json @@ -0,0 +1,56 @@ +[ + { + "mac": "ec:00:8b:f7:00:e5", + "interface": "Trk1", + "vlan": 1, + "active": true, + "static": false, + "moves": 0, + "last_move": 0.0 + }, + { + "mac": "4e:11:14:b1:11:3c", + "interface": "Trk1", + "vlan": 48, + "active": true, + "static": false, + "moves": 0, + "last_move": 0.0 + }, + { + "mac": "78:22:77:60:22:3f", + "interface": "3/44", + "vlan": 64, + "active": true, + "static": false, + "moves": 0, + "last_move": 0.0 + }, + { + "mac": "00:33:98:16:33:85", + "interface": "2/32", + "vlan": 64, + "active": true, + "static": false, + "moves": 0, + "last_move": 0.0 + }, + { + "mac": "e0:44:43:5d:44:b3", + "interface": "Trk1", + "vlan": 104, + "active": true, + "static": false, + "moves": 0, + "last_move": 0.0 + }, + { + "mac": "00:55:98:17:55:78", + "interface": "4/25", + "vlan": 64, + "active": true, + "static": false, + "moves": 0, + "last_move": 0.0 + } +] \ No newline at end of file diff --git a/test/unit/mocked_data/test_get_mac_address_table/normal/facts.json b/test/unit/mocked_data/test_get_mac_address_table/normal/facts.json new file mode 100644 index 0000000..312b900 --- /dev/null +++ b/test/unit/mocked_data/test_get_mac_address_table/normal/facts.json @@ -0,0 +1,49 @@ +{ + "mac-table": { + "status": 200, + "data": { + "collection_result": { + "total_elements_count": 400, + "filtered_elements_count": 400 + }, + "mac_table_entry_element": [ + { + "uri": "/mac-table/ec008b-f700e5", + "mac_address": "ec008b-f700e5", + "port_id": "Trk1", + "vlan_id": 1 + }, + { + "uri": "/mac-table/4e1114-b1113c", + "mac_address": "4e1114-b1113c", + "port_id": "Trk1", + "vlan_id": 48 + }, + { + "uri": "/mac-table/782277-60223f", + "mac_address": "782277-60223f", + "port_id": "3/44", + "vlan_id": 64 + }, + { + "uri": "/mac-table/003398-163385", + "mac_address": "003398-163385", + "port_id": "2/32", + "vlan_id": 64 + }, + { + "uri": "/mac-table/e04443-5d44b3", + "mac_address": "e04443-5d44b3", + "port_id": "Trk1", + "vlan_id": 104 + }, + { + "uri": "/mac-table/005598-175578", + "mac_address": "005598-175578", + "port_id": "4/25", + "vlan_id": 64 + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/mocked_data/test_get_ntp_peers/normal/expected_result.json b/test/unit/mocked_data/test_get_ntp_peers/normal/expected_result.json new file mode 100644 index 0000000..6813943 --- /dev/null +++ b/test/unit/mocked_data/test_get_ntp_peers/normal/expected_result.json @@ -0,0 +1,4 @@ +{ + "116.203.116.168": {}, + "\"de.pool.ntp.org\"": {} +} diff --git a/test/unit/mocked_data/test_get_ntp_peers/normal/facts.json b/test/unit/mocked_data/test_get_ntp_peers/normal/facts.json new file mode 100644 index 0000000..2061a36 --- /dev/null +++ b/test/unit/mocked_data/test_get_ntp_peers/normal/facts.json @@ -0,0 +1,46 @@ +{ + "config/ntp/server/ip4addr": { + "status": 200, + "data": { + "ntpServerIp4addr_element": [ + { + "ip4addr": { + "ip4addr_value": "116.203.116.168", + "ip4addr_reference": { + "min-poll": { + "min-poll_value": 6 + }, + "max-poll": { + "max-poll_value": 10 + }, + "oobm": true + } + }, + "uri": "/config/ntp/server/ip4addr/116.203.116.168" + } + ] + } + }, + "config/ntp/server-name/ASCII-STR": { + "status": 200, + "data": { + "ntpServerNameASCIISTR_element": [ + { + "ASCII-STR": { + "ASCII-STR_value": "\"de.pool.ntp.org\"", + "ASCII-STR_reference": { + "min-poll": { + "min-poll_value": 6 + }, + "max-poll": { + "max-poll_value": 10 + }, + "oobm": true + } + }, + "uri": "/config/ntp/server-name/ASCII-STR/%22de.pool.ntp.org%22" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/mocked_data/test_get_ntp_servers/normal/expected_result.json b/test/unit/mocked_data/test_get_ntp_servers/normal/expected_result.json new file mode 100644 index 0000000..6813943 --- /dev/null +++ b/test/unit/mocked_data/test_get_ntp_servers/normal/expected_result.json @@ -0,0 +1,4 @@ +{ + "116.203.116.168": {}, + "\"de.pool.ntp.org\"": {} +} diff --git a/test/unit/mocked_data/test_get_ntp_servers/normal/facts.json b/test/unit/mocked_data/test_get_ntp_servers/normal/facts.json new file mode 100644 index 0000000..2061a36 --- /dev/null +++ b/test/unit/mocked_data/test_get_ntp_servers/normal/facts.json @@ -0,0 +1,46 @@ +{ + "config/ntp/server/ip4addr": { + "status": 200, + "data": { + "ntpServerIp4addr_element": [ + { + "ip4addr": { + "ip4addr_value": "116.203.116.168", + "ip4addr_reference": { + "min-poll": { + "min-poll_value": 6 + }, + "max-poll": { + "max-poll_value": 10 + }, + "oobm": true + } + }, + "uri": "/config/ntp/server/ip4addr/116.203.116.168" + } + ] + } + }, + "config/ntp/server-name/ASCII-STR": { + "status": 200, + "data": { + "ntpServerNameASCIISTR_element": [ + { + "ASCII-STR": { + "ASCII-STR_value": "\"de.pool.ntp.org\"", + "ASCII-STR_reference": { + "min-poll": { + "min-poll_value": 6 + }, + "max-poll": { + "max-poll_value": 10 + }, + "oobm": true + } + }, + "uri": "/config/ntp/server-name/ASCII-STR/%22de.pool.ntp.org%22" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/mocked_data/test_get_ntp_stats/server-name/expected_result.json b/test/unit/mocked_data/test_get_ntp_stats/server-name/expected_result.json new file mode 100644 index 0000000..4f871e4 --- /dev/null +++ b/test/unit/mocked_data/test_get_ntp_stats/server-name/expected_result.json @@ -0,0 +1,15 @@ +[ + { + "remote": "173.249.33.207", + "referenceid": "205.46.178.169", + "stratum": 2, + "type": "Server", + "when": "Wed Nov 10 18:01:18 2021", + "hostpoll": 7, + "reachability": 17, + "delay": 0.01628, + "offset": 0.0, + "jitter": 0.00075, + "synchronized": true + } +] \ No newline at end of file diff --git a/test/unit/mocked_data/test_get_ntp_stats/server-name/facts.json b/test/unit/mocked_data/test_get_ntp_stats/server-name/facts.json new file mode 100644 index 0000000..5e2201c --- /dev/null +++ b/test/unit/mocked_data/test_get_ntp_stats/server-name/facts.json @@ -0,0 +1,47 @@ +{ + "monitoring/ntp/servers": { + "status": 200, + "data": { + "NTP_Server_Name_Information": [ + { + "Server Name": "de.pool.ntp.org", + "Resolved Address": "173.249.33.207", + "Server Status": "Success: NTP server active" + }, + { + "Server Name": "0.de.pool.ntp.org", + "Resolved Address": "", + "Server Status": "Failed: NTP server not active" + } + ] + } + }, + "monitoring/ntp/associations/detail": { + "status": 200, + "data": { + "IP Address": "173.249.33.207", + "Peer Mode": "Server", + "Status": "Config,Sane,Master", + "Peer Poll Intvl": 7, + "Stratum": 2, + "Root Delay": "0.01628 sec", + "Ref Assoc ID": 1, + "Root Dispersion": "0.00075 sec", + "Assoc Name": "NTP Association 1", + "Reach": 17, + "Reference ID": "205.46.178.169", + "Delay": "0.00000 sec", + "Our Mode": "Client", + "Offset": "0.00000 sec", + "Our Poll Intvl": 7, + "Precision": "2**-25", + "Dispersion": "15.53054 sec", + "Association In Packets": 11, + "Association Out Packets": 11, + "Association Error Packets": 0, + "Origin Time": "Wed Nov 10 18:01:18 2021", + "Receive Time": "Wed Nov 10 18:01:18 2021", + "Transmit Time": "Wed Nov 10 18:01:18 2021" + } + } +} diff --git a/test/unit/mocked_data/test_get_route_to/normal/cli_mapping.json b/test/unit/mocked_data/test_get_route_to/normal/cli_mapping.json new file mode 100644 index 0000000..25f16c6 --- /dev/null +++ b/test/unit/mocked_data/test_get_route_to/normal/cli_mapping.json @@ -0,0 +1 @@ +{"show ip route 1.0.4.0 bgp": "\n IP Route Entries to 1.0.4.0\n\n Destination Gateway VLAN Type Sub-Type Metric Dist.\n ------------------ --------------- ---- --------- ---------- ---------- -----\n 1.0.4.0/24 NET_MGMT 4 bgp 1 0 \n \n\n\u0000"} \ No newline at end of file diff --git a/test/unit/mocked_data/test_get_route_to/normal/expected_result.json b/test/unit/mocked_data/test_get_route_to/normal/expected_result.json new file mode 100644 index 0000000..18aca65 --- /dev/null +++ b/test/unit/mocked_data/test_get_route_to/normal/expected_result.json @@ -0,0 +1,27 @@ +{ + "1.0.4.0/24": [ + { + "protocol": "bgp", + "current_active": true, + "last_active": true, + "age": -1, + "next_hop": "NET_MGMT", + "outgoing_interface": "", + "selected_next_hop": true, + "preference": 0, + "inactive_reason": "", + "routing_table": "", + "protocol_attributes": { + "local_as": -1, + "remote_as": -1, + "peer_id": "", + "as_path": "", + "communities": -1, + "local_preference": -1, + "preference2": -1, + "metric": -1, + "metric2": -1 + } + } + ] +} \ No newline at end of file diff --git a/test/unit/mocked_data/test_get_route_to_longer/normal/cli_mapping.json b/test/unit/mocked_data/test_get_route_to_longer/normal/cli_mapping.json new file mode 100644 index 0000000..25f16c6 --- /dev/null +++ b/test/unit/mocked_data/test_get_route_to_longer/normal/cli_mapping.json @@ -0,0 +1 @@ +{"show ip route 1.0.4.0 bgp": "\n IP Route Entries to 1.0.4.0\n\n Destination Gateway VLAN Type Sub-Type Metric Dist.\n ------------------ --------------- ---- --------- ---------- ---------- -----\n 1.0.4.0/24 NET_MGMT 4 bgp 1 0 \n \n\n\u0000"} \ No newline at end of file diff --git a/test/unit/mocked_data/test_get_route_to_longer/normal/expected_result.json b/test/unit/mocked_data/test_get_route_to_longer/normal/expected_result.json new file mode 100644 index 0000000..18aca65 --- /dev/null +++ b/test/unit/mocked_data/test_get_route_to_longer/normal/expected_result.json @@ -0,0 +1,27 @@ +{ + "1.0.4.0/24": [ + { + "protocol": "bgp", + "current_active": true, + "last_active": true, + "age": -1, + "next_hop": "NET_MGMT", + "outgoing_interface": "", + "selected_next_hop": true, + "preference": 0, + "inactive_reason": "", + "routing_table": "", + "protocol_attributes": { + "local_as": -1, + "remote_as": -1, + "peer_id": "", + "as_path": "", + "communities": -1, + "local_preference": -1, + "preference2": -1, + "metric": -1, + "metric2": -1 + } + } + ] +} \ No newline at end of file diff --git a/test/unit/mocked_data/test_is_alive/normal/expected_result.json b/test/unit/mocked_data/test_is_alive/normal/expected_result.json new file mode 100644 index 0000000..fd599e5 --- /dev/null +++ b/test/unit/mocked_data/test_is_alive/normal/expected_result.json @@ -0,0 +1 @@ +{"is_alive": true} \ No newline at end of file diff --git a/test/unit/mocked_data/test_ping/normal/expected_result.json b/test/unit/mocked_data/test_ping/normal/expected_result.json new file mode 100644 index 0000000..28fece2 --- /dev/null +++ b/test/unit/mocked_data/test_ping/normal/expected_result.json @@ -0,0 +1,16 @@ +{ + "success": { + "probes_sent": 1, + "packet_loss": 0, + "rtt_min": 21, + "rtt_max": 21, + "rtt_avg": 21, + "rtt_stddev": 0, + "results": [ + { + "ip_address": "8.8.8.8", + "rtt": 21 + } + ] + } +} \ No newline at end of file diff --git a/test/unit/mocked_data/test_ping/normal/facts.json b/test/unit/mocked_data/test_ping/normal/facts.json new file mode 100644 index 0000000..2a518ea --- /dev/null +++ b/test/unit/mocked_data/test_ping/normal/facts.json @@ -0,0 +1,10 @@ +{ + "ping": { + "status": 200, + "data": { + "uri": "/ping", + "result": "PR_OK", + "rtt_in_milliseconds": 21 + } + } +} \ No newline at end of file diff --git a/test/unit/mocked_data/test_traceroute/normal/expected_result.json b/test/unit/mocked_data/test_traceroute/normal/expected_result.json new file mode 100644 index 0000000..c480013 --- /dev/null +++ b/test/unit/mocked_data/test_traceroute/normal/expected_result.json @@ -0,0 +1,99 @@ +{ + "success": { + "1": { + "probes": { + "1": { + "rtt": 2.0, + "ip_address": "10.20.4.1", + "host_name": "" + }, + "2": { + "rtt": 1.0, + "ip_address": "10.20.4.1", + "host_name": "" + }, + "3": { + "rtt": 2.0, + "ip_address": "10.20.4.1", + "host_name": "" + } + } + }, + "2": { + "probes": { + "1": { + "rtt": 0.0, + "ip_address": "10.191.253.109", + "host_name": "" + }, + "2": { + "rtt": 1.0, + "ip_address": "10.191.253.109", + "host_name": "" + }, + "3": { + "rtt": 1.0, + "ip_address": "10.191.253.109", + "host_name": "" + } + } + }, + "3": { + "probes": { + "1": { + "rtt": 6.0, + "ip_address": "10.191.250.69", + "host_name": "" + }, + "2": { + "rtt": 5.0, + "ip_address": "10.191.250.69", + "host_name": "" + }, + "3": { + "rtt": 5.0, + "ip_address": "10.191.250.69", + "host_name": "" + } + } + }, + "4": { + "probes": { + "1": { + "rtt": 20.0, + "ip_address": "142.251.225.135", + "host_name": "" + }, + "2": { + "rtt": 21.0, + "ip_address": "142.251.48.177", + "host_name": "" + }, + "3": { + "rtt": 22.0, + "ip_address": "142.250.224.133", + "host_name": "" + } + } + }, + "5": { + "probes": { + "1": { + "rtt": 20.0, + "ip_address": "8.8.8.8", + "host_name": "dns.google" + }, + "2": { + "rtt": 20.0, + "ip_address": "8.8.8.8", + "host_name": "dns.google" + }, + "3": { + "rtt": 21.0, + "ip_address": "8.8.8.8", + "host_name": "dns.google" + } + } + } + } +} \ No newline at end of file diff --git a/test/unit/mocked_data/test_traceroute/normal/facts.json b/test/unit/mocked_data/test_traceroute/normal/facts.json new file mode 100644 index 0000000..c6b7b43 --- /dev/null +++ b/test/unit/mocked_data/test_traceroute/normal/facts.json @@ -0,0 +1,166 @@ +{ + "trace-route": { + "status": 200, + "data": { + "ttl_data": [ + { + "ttl_probe_data": [ + { + "gateway": { + "ip_address": { + "version": "IAV_IP_V4", + "octets": "10.20.4.1" + } + }, + "probe_time_in_millis": 2 + }, + { + "gateway": { + "ip_address": { + "version": "IAV_IP_V4", + "octets": "10.20.4.1" + } + }, + "probe_time_in_millis": 1 + }, + { + "gateway": { + "ip_address": { + "version": "IAV_IP_V4", + "octets": "10.20.4.1" + } + }, + "probe_time_in_millis": 2 + } + ] + }, + { + "ttl_probe_data": [ + { + "gateway": { + "ip_address": { + "version": "IAV_IP_V4", + "octets": "10.191.253.109" + } + }, + "probe_time_in_millis": 0 + }, + { + "gateway": { + "ip_address": { + "version": "IAV_IP_V4", + "octets": "10.191.253.109" + } + }, + "probe_time_in_millis": 1 + }, + { + "gateway": { + "ip_address": { + "version": "IAV_IP_V4", + "octets": "10.191.253.109" + } + }, + "probe_time_in_millis": 1 + } + ] + }, + { + "ttl_probe_data": [ + { + "gateway": { + "ip_address": { + "version": "IAV_IP_V4", + "octets": "10.191.250.69" + } + }, + "probe_time_in_millis": 6 + }, + { + "gateway": { + "ip_address": { + "version": "IAV_IP_V4", + "octets": "10.191.250.69" + } + }, + "probe_time_in_millis": 5 + }, + { + "gateway": { + "ip_address": { + "version": "IAV_IP_V4", + "octets": "10.191.250.69" + } + }, + "probe_time_in_millis": 5 + } + ] + }, + { + "ttl_probe_data": [ + { + "gateway": { + "ip_address": { + "version": "IAV_IP_V4", + "octets": "142.251.225.135" + } + }, + "probe_time_in_millis": 20 + }, + { + "gateway": { + "ip_address": { + "version": "IAV_IP_V4", + "octets": "142.251.48.177" + } + }, + "probe_time_in_millis": 21 + }, + { + "gateway": { + "ip_address": { + "version": "IAV_IP_V4", + "octets": "142.250.224.133" + } + }, + "probe_time_in_millis": 22 + } + ] + }, + { + "ttl_probe_data": [ + { + "gateway": { + "ip_address": { + "version": "IAV_IP_V4", + "octets": "8.8.8.8" + } + }, + "probe_time_in_millis": 20 + }, + { + "gateway": { + "ip_address": { + "version": "IAV_IP_V4", + "octets": "8.8.8.8" + } + }, + "probe_time_in_millis": 20 + }, + { + "gateway": { + "ip_address": { + "version": "IAV_IP_V4", + "octets": "8.8.8.8" + } + }, + "probe_time_in_millis": 21 + } + ] + } + ], + "result": "TRR_OK", + "uri": "/trace-route" + } + } +} \ No newline at end of file diff --git a/test/unit/test_getters.py b/test/unit/test_getters.py new file mode 100644 index 0000000..6a16ea5 --- /dev/null +++ b/test/unit/test_getters.py @@ -0,0 +1,10 @@ +"""Tests for getters.""" + +from napalm.base.test.getters import BaseTestGetters + +import pytest + + +@pytest.mark.usefixtures("set_device_parameters") +class TestGetter(BaseTestGetters): + """Test get_* methods.""" diff --git a/test/unit/utils/textfsm_templates/show_arp.tpl b/test/unit/utils/textfsm_templates/show_arp.tpl new file mode 100644 index 0000000..4dd9c4d --- /dev/null +++ b/test/unit/utils/textfsm_templates/show_arp.tpl @@ -0,0 +1,10 @@ +Value IP (\S+) +Value MAC ([0-9a-fA-F]{6}-[0-9a-fA-F]{6}) +Value TYPE (\S+) +Value PORT (\S+) + +Start + ^.*IP ARP table -> ARP + +ARP + ^\s+${IP}\s+${MAC}\s+${TYPE}\s+${PORT} -> Record diff --git a/test/unit/utils/textfsm_templates/show_ip_route.tpl b/test/unit/utils/textfsm_templates/show_ip_route.tpl new file mode 100644 index 0000000..69ef9a5 --- /dev/null +++ b/test/unit/utils/textfsm_templates/show_ip_route.tpl @@ -0,0 +1,15 @@ +Value Required DESTINATION (\S+) +Value GATEWAY (\S+) +Value VLAN ([0-9]*) +Value TYPE (\w+) +Value SUBTYPE (\S*) +Value METRIC ([0-9]+) +Value DISTANCE ([0-9]+) + + +Start + ^.*IP Route Entries -> Routes + +Routes + ^\s+${DESTINATION}\s+${GATEWAY}\s+${VLAN}\s+${TYPE}\s+${SUBTYPE}\s+${METRIC}\s+${DISTANCE} -> Record + diff --git a/test/unit/utils/textfsm_templates/show_ipv6_route.tpl b/test/unit/utils/textfsm_templates/show_ipv6_route.tpl new file mode 100644 index 0000000..5745f71 --- /dev/null +++ b/test/unit/utils/textfsm_templates/show_ipv6_route.tpl @@ -0,0 +1,15 @@ +Value DESTINATION ([0-9a-z:/%]+) +Value GATEWAY (\w+) +Value VLAN (\w+) +Value TYPE ([SCOR]) +Value SUBTYPE ([A-Z0-9][A-Z0-9]) +Value METRIC ([0-9]+) +Value DISTANCE ([0-9]+) + + +Start + ^.*IPv6 Route Entries -> Routes + +Routes + ^\s${DESTINATION}\s+ + ^\s+${GATEWAY}\s(\(${VLAN}\))?\s+${TYPE}\s+${SUBTYPE}\s+${DISTANCE}\s+${METRIC} -> Record