diff --git a/README.md b/README.md index 776d593..85c861a 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,6 @@ may have not been properly tested in older versions. * get_lldp_neighbors_detail - Get LLDP Neighbor details from a device. * get_mac_address_table - Get the MAC Address table from a device. * get_ntp_servers - Gets NTP information from a network device. - * get_route_to - Shows an IP route on a device. * get_snmp_information - Get the SNMP information of a device. * is_alive - Check to see if the connection to the device is up. * ping - Execute a ping command from the device. diff --git a/napalm_aoscx/aoscx.py b/napalm_aoscx/aoscx.py index bf096f7..d19509b 100644 --- a/napalm_aoscx/aoscx.py +++ b/napalm_aoscx/aoscx.py @@ -49,7 +49,7 @@ # Aruba AOS-CX lib import pyaoscx -from pyaoscx import session, interface, system, common_ops, port, lldp, mac +from pyaoscx import session, interface, system, common_ops, port, lldp, mac, vrf, arp class AOSCXDriver(NetworkDriver): """NAPALM driver for Aruba AOS-CX.""" @@ -114,9 +114,22 @@ def get_facts(self): * interface_list - List of the interfaces of the device """ systeminfo = pyaoscx.system.get_system_info(**self.session_info) - productinfo = pyaoscx.system.get_product_info(**self.session_info) + if systeminfo['platform_name'] == 'X86-64': #it is Virtual CX (OVA) + #there is no product_info on Virtual CX (OVA)... + productinfo = dict( + product_info = dict ( + serial_number = "N/A", + product_name = "VirtualCX (OVA)", + ) + ) + else: + productinfo = pyaoscx.system.get_product_info(**self.session_info) uptime_seconds = (int(systeminfo['boot_time']))/1000 + if 'hostname' not in systeminfo: + hostname = "ArubaCX" + else: + hostname = systeminfo['hostname'] fact_info = { 'uptime': uptime_seconds, @@ -124,8 +137,8 @@ def get_facts(self): 'os_version': systeminfo['software_info']['build_id'], 'serial_number': productinfo['product_info']['serial_number'], 'model': productinfo['product_info']['product_name'], - 'hostname': systeminfo['hostname'], - 'fqdn':systeminfo['hostname'], + 'hostname': hostname, + 'fqdn': hostname, 'interface_list': pyaoscx.interface.get_all_interface_names(**self.session_info) } return fact_info @@ -183,8 +196,7 @@ def get_interfaces_counters(self): """ Implementation of NAPALM method get_interfaces_counters. This gives statistic information for all interfaces that are on the switch. - Note: Not currently implementing tx_errors, rx_errors, rx_discards, and tx_discards, and - those values will return -1. + Note: rx_discards, and tx_discards are equal to rx/tx dropped counters on Aruba CX :return: Returns a dictionary of dictionaries where the first key is an interface name and the inner dictionary contains the following keys: @@ -204,32 +216,62 @@ def get_interfaces_counters(self): interface_stats_dictionary = {} interface_list = pyaoscx.interface.get_all_interface_names(**self.session_info) for line in interface_list: - interface_details = pyaoscx.interface.get_interface(line, **self.session_info) - print(interface_details['name']) - interface_stats_dictionary.update( - { - line: { - 'tx_errors': -1, - 'rx_errors': -1, - 'tx_discards': -1, - 'rx_discards': -1, - 'tx_octets': interface_details['statistics']['tx_bytes'], - 'rx_octets': interface_details['statistics']['rx_bytes'], - 'tx_unicast_packets': - interface_details['statistics']['if_hc_out_unicast_packets'], - 'rx_unicast_packets': - interface_details['statistics']['if_hc_in_unicast_packets'], - 'tx_multicast_packets': - interface_details['statistics']['if_out_multicast_packets'], - 'rx_multicast_packets': - interface_details['statistics']['if_in_multicast_packets'], - 'tx_broadcast_packets': - interface_details['statistics']['if_out_broadcast_packets'], - 'rx_broadcast_packets': - interface_details['statistics']['if_in_broadcast_packets'] - } - } - ) + interface_details = pyaoscx.interface.get_interface( + line, selector="statistics", **self.session_info) + intf_counter = { + 'tx_errors': 0, + 'rx_errors': 0, + 'tx_discards': 0, + 'rx_discards': 0, + 'tx_octets': 0, + 'rx_octets': 0, + 'tx_unicast_packets': 0, + 'rx_unicast_packets': 0, + 'tx_multicast_packets': 0, + 'rx_multicast_packets': 0, + 'tx_broadcast_packets': 0, + 'rx_broadcast_packets': 0 + } + if 'tx_bytes' in interface_details['statistics']: + intf_counter['tx_octets'] = interface_details['statistics']['tx_bytes'] + + if 'rx_bytes' in interface_details['statistics']: + intf_counter['rx_octets'] = interface_details['statistics']['rx_bytes'] + + if 'if_hc_out_unicast_packets' in interface_details['statistics']: + intf_counter['tx_unicast_packets'] = interface_details['statistics']['if_hc_out_unicast_packets'] + + if 'if_hc_in_unicast_packets' in interface_details['statistics']: + intf_counter['rx_unicast_packets'] = interface_details['statistics']['if_hc_in_unicast_packets'] + + if 'if_out_multicast_packets' in interface_details['statistics']: + intf_counter['tx_multicast_packets'] = interface_details['statistics']['if_out_multicast_packets'] + + if 'if_in_multicast_packets' in interface_details['statistics']: + intf_counter['rx_multicast_packets'] = interface_details['statistics']['if_in_multicast_packets'] + + if 'if_out_broadcast_packets' in interface_details['statistics']: + intf_counter['rx_bytes'] = interface_details['statistics']['if_out_broadcast_packets'] + + if 'if_in_broadcast_packets' in interface_details['statistics']: + intf_counter['rx_broadcast_packets'] = interface_details['statistics']['if_in_broadcast_packets'] + + if 'tx_errors' in interface_details['statistics']: + intf_counter['tx_errors'] = interface_details['statistics']['tx_errors'] + + if 'rx_errors' in interface_details['statistics']: + intf_counter['rx_errors'] = interface_details['statistics']['rx_errors'] + + if 'tx_dropped' in interface_details['statistics']: + intf_counter['tx_discards'] = interface_details['statistics']['tx_dropped'] + + if 'rx_dropped' in interface_details['statistics']: + intf_counter['rx_discards'] = interface_details['statistics']['rx_dropped'] + + interface_stats_dictionary.update({ + line: intf_counter + }) + return interface_stats_dictionary def get_lldp_neighbors(self): @@ -256,7 +298,7 @@ def get_lldp_neighbors(self): lldp_brief_return[interface_name].append( { 'hostname': interface_details['neighbor_info']['chassis_name'], - 'port:': interface_details['port_id'] + 'port': interface_details['port_id'] } ) @@ -382,16 +424,30 @@ def get_environment(self): cpu_dict = {} mem_dict = {} for mm in resources_details: + if 'cpu' not in mm['resource_utilization']: + cpu = 'N/A' + else: + cpu = mm['resource_utilization']['cpu'] + new_dict = { mm['name']: { - '%usage': mm['resource_utilization']['cpu'] + '%usage': cpu } } cpu_dict.update(new_dict) - mem_dict = { - 'available_ram': 'N/A', - 'used_ram': mm['resource_utilization']['memory'] + + if 'memory' not in mm['resource_utilization']: + memory = 'N/A' + else: + memory = mm['resource_utilization']['memory'] + + new_dict = { + mm['name']: { + 'available_ram': 'N/A', + 'used_ram': memory + } } + mem_dict.update(new_dict) environment = { 'fans': fan_dict, @@ -419,16 +475,20 @@ def get_arp_table(self, vrf=""): """ arp_entries = [] vrf_list = pyaoscx.vrf.get_all_vrfs(**self.session_info) + #prepend vrf + vrf = '/rest/v1/system/vrfs/' + vrf if vrf in vrf_list: vrf_list = [vrf] for vrf_entry in vrf_list: - arp_list = pyaoscx.arp.get_arp_entries(vrf_entry, **self.session_info) + #remove '/rest/v1/system/vrfs' from vrf name... + myvrf = vrf_entry.replace('/rest/v1/system/vrfs/','') + arp_list = pyaoscx.arp.get_arp_entries(myvrf, **self.session_info) for entry in arp_list: arp_entries.append( { 'interface': entry['Physical Port'], 'mac': entry['MAC Address'], - 'ip': entry['MAC Address'], + 'ip': entry['IPv4 Address'], 'age': 0.0 } ) @@ -608,9 +668,9 @@ def get_config(self, retrieve="all", full=False): "candidate": "" } if retrieve in ["running", "all"]: - config_dict['running'] = self._get_json_configuration("running-config") + config_dict['running'] = self._get_json_configuration("running-config", **self.session_info) if retrieve in ["startup", "all"]: - config_dict['startup'] = self._get_json_configuration("startup-config") + config_dict['startup'] = self._get_json_configuration("startup-config", **self.session_info) if retrieve in ["candidate", "all"]: config_dict['candidate'] = self.candidate_config @@ -866,11 +926,11 @@ def _get_ntp_associations(self, params={}, **kwargs): associations_dict[server_name] = {} if not common_ops._response_ok(response, "GET"): - logging.warning("FAIL: Getting dictionary of resource utilization info failed with status code %d: %s" + logging.warning("FAIL: Getting dictionary of NTP associations information failed with status code %d: %s" % (response.status_code, response.text)) associations_dict = {} else: - logging.info("SUCCESS: Getting dictionary of resource utilization information succeeded") + logging.info("SUCCESS: Getting dictionary of NTP associations information succeeded") associations_dict = response.json() return associations_dict