[Python-modules-commits] [napalm-eos] 01/03: Import napalm-eos_0.4.2.orig.tar.gz

Vincent Bernat bernat at moszumanska.debian.org
Wed Nov 2 18:57:58 UTC 2016


This is an automated email from the git hooks/post-receive script.

bernat pushed a commit to branch master
in repository napalm-eos.

commit c480182d1566220f5ba0706afd5e01eabdbec184
Author: Vincent Bernat <bernat at debian.org>
Date:   Wed Nov 2 19:54:31 2016 +0100

    Import napalm-eos_0.4.2.orig.tar.gz
---
 PKG-INFO                                          |   2 +-
 napalm_eos.egg-info/PKG-INFO                      |   2 +-
 napalm_eos.egg-info/SOURCES.txt                   |   2 +
 napalm_eos.egg-info/requires.txt                  |   2 +-
 napalm_eos/__init__.py                            |   8 +
 napalm_eos/eos.py                                 | 768 ++++++++++++++++------
 napalm_eos/utils/textfsm_templates/bgp_detail.tpl |  46 ++
 requirements.txt                                  |   2 +-
 setup.cfg                                         |  16 +
 setup.py                                          |   2 +-
 10 files changed, 636 insertions(+), 214 deletions(-)

diff --git a/PKG-INFO b/PKG-INFO
index f546c4f..2f87f6c 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: napalm-eos
-Version: 0.2.1
+Version: 0.4.2
 Summary: Network Automation and Programmability Abstraction Layer with Multivendor support
 Home-page: https://github.com/napalm-automation/napalm-eos
 Author: David Barroso
diff --git a/napalm_eos.egg-info/PKG-INFO b/napalm_eos.egg-info/PKG-INFO
index f546c4f..2f87f6c 100644
--- a/napalm_eos.egg-info/PKG-INFO
+++ b/napalm_eos.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: napalm-eos
-Version: 0.2.1
+Version: 0.4.2
 Summary: Network Automation and Programmability Abstraction Layer with Multivendor support
 Home-page: https://github.com/napalm-automation/napalm-eos
 Author: David Barroso
diff --git a/napalm_eos.egg-info/SOURCES.txt b/napalm_eos.egg-info/SOURCES.txt
index 59f4055..3385ad8 100644
--- a/napalm_eos.egg-info/SOURCES.txt
+++ b/napalm_eos.egg-info/SOURCES.txt
@@ -1,5 +1,6 @@
 MANIFEST.in
 requirements.txt
+setup.cfg
 setup.py
 napalm_eos/__init__.py
 napalm_eos/eos.py
@@ -11,5 +12,6 @@ napalm_eos.egg-info/top_level.txt
 napalm_eos/templates/delete_ntp_peers.j2
 napalm_eos/templates/set_ntp_peers.j2
 napalm_eos/utils/__init__.py
+napalm_eos/utils/textfsm_templates/bgp_detail.tpl
 napalm_eos/utils/textfsm_templates/ntp_peers.tpl
 napalm_eos/utils/textfsm_templates/snmp_config.tpl
\ No newline at end of file
diff --git a/napalm_eos.egg-info/requires.txt b/napalm_eos.egg-info/requires.txt
index 5e773d3..64f2b11 100644
--- a/napalm_eos.egg-info/requires.txt
+++ b/napalm_eos.egg-info/requires.txt
@@ -1,2 +1,2 @@
-napalm-base
+napalm-base>=0.18.0
 pyeapi
diff --git a/napalm_eos/__init__.py b/napalm_eos/__init__.py
index 7015fd1..c398f99 100644
--- a/napalm_eos/__init__.py
+++ b/napalm_eos/__init__.py
@@ -14,3 +14,11 @@
 
 """napalm_eos package."""
 from eos import EOSDriver
+import pkg_resources
+
+try:
+    __version__ = pkg_resources.get_distribution('napalm-eos').version
+except pkg_resources.DistributionNotFound:
+    __version__ = "Not installed"
+
+__all__ = ('EOSDriver',)
diff --git a/napalm_eos/eos.py b/napalm_eos/eos.py
index 050e57c..5ffc224 100644
--- a/napalm_eos/eos.py
+++ b/napalm_eos/eos.py
@@ -21,10 +21,12 @@ Read napalm.readthedocs.org for more information.
 # std libs
 import re
 import time
+
 from datetime import datetime
+
 from netaddr import IPAddress
 from netaddr import IPNetwork
-from collections import defaultdict
+
 from netaddr.core import AddrFormatError
 
 # third party libs
@@ -35,8 +37,8 @@ from pyeapi.eapilib import ConnectionError
 import napalm_base.helpers
 from napalm_base.base import NetworkDriver
 from napalm_base.utils import string_parsers
-from napalm_base.exceptions import ConnectionException, MergeConfigException, ReplaceConfigException,\
-                                   SessionLockedException, CommandErrorException
+from napalm_base.exceptions import ConnectionException, MergeConfigException, \
+                        ReplaceConfigException, SessionLockedException, CommandErrorException
 
 # local modules
 # here add local imports
@@ -46,6 +48,8 @@ from napalm_base.exceptions import ConnectionException, MergeConfigException, Re
 class EOSDriver(NetworkDriver):
     """Napalm driver for Arista EOS."""
 
+    SUPPORTED_OC_MODELS = []
+
     def __init__(self, hostname, username, password, timeout=60, optional_args=None):
         """Constructor."""
         self.device = None
@@ -57,20 +61,35 @@ class EOSDriver(NetworkDriver):
 
         if optional_args is None:
             optional_args = {}
-        self.port = optional_args.get('port', 443)
+
+        self.transport = optional_args.get('eos_transport', 'https')
+
+        if self.transport == 'https':
+            self.port = optional_args.get('port', 443)
+        elif self.transrpot == 'http':
+            self.port = optional_args.get('port', 80)
+
+        self.enablepwd = optional_args.get('enable_password', '')
 
     def open(self):
-        """Implemantation of NAPALM method open."""
+        """Implementation of NAPALM method open."""
         try:
-            connection = pyeapi.client.connect(
-                transport='https',
-                host=self.hostname,
-                username=self.username,
-                password=self.password,
-                port=self.port,
-                timeout=self.timeout
-            )
-            self.device = pyeapi.client.Node(connection)
+            if self.transport in ('http', 'https'):
+                connection = pyeapi.client.connect(
+                    transport='https',
+                    host=self.hostname,
+                    username=self.username,
+                    password=self.password,
+                    port=self.port,
+                    timeout=self.timeout
+                )
+            elif self.transport == 'socket':
+                connection = pyeapi.client.connect(transport=self.transport)
+            else:
+                raise ConnectionException("Unknown transport: {}".format(self.transport))
+
+            if self.device is None:
+                self.device = pyeapi.client.Node(connection, enablepwd=self.enablepwd)
             # does not raise an Exception if unusable
 
             # let's try to run a very simple command
@@ -82,7 +101,7 @@ class EOSDriver(NetworkDriver):
             raise ConnectionException(ce.message)
 
     def close(self):
-        """Implemantation of NAPALM method close."""
+        """Implementation of NAPALM method close."""
         self.discard_config()
 
     def _load_config(self, filename=None, config=None, replace=True):
@@ -125,15 +144,15 @@ class EOSDriver(NetworkDriver):
                 raise MergeConfigException(e.message)
 
     def load_replace_candidate(self, filename=None, config=None):
-        """Implemantation of NAPALM method load_replace_candidate."""
+        """Implementation of NAPALM method load_replace_candidate."""
         self._load_config(filename, config, True)
 
     def load_merge_candidate(self, filename=None, config=None):
-        """Implemantation of NAPALM method load_merge_candidate."""
+        """Implementation of NAPALM method load_merge_candidate."""
         self._load_config(filename, config, False)
 
     def compare_config(self):
-        """Implemantation of NAPALM method compare_config."""
+        """Implementation of NAPALM method compare_config."""
         if self.config_session is None:
             return ''
         else:
@@ -145,7 +164,7 @@ class EOSDriver(NetworkDriver):
             return result.strip()
 
     def commit_config(self):
-        """Implemantation of NAPALM method commit_config."""
+        """Implementation of NAPALM method commit_config."""
         commands = list()
         commands.append('copy startup-config flash:rollback-0')
         commands.append('configure session {}'.format(self.config_session))
@@ -156,7 +175,7 @@ class EOSDriver(NetworkDriver):
         self.config_session = None
 
     def discard_config(self):
-        """Implemantation of NAPALM method discard_config."""
+        """Implementation of NAPALM method discard_config."""
         if self.config_session is not None:
             commands = list()
             commands.append('configure session {}'.format(self.config_session))
@@ -165,14 +184,14 @@ class EOSDriver(NetworkDriver):
             self.config_session = None
 
     def rollback(self):
-        """Implemantation of NAPALM method rollback."""
+        """Implementation of NAPALM method rollback."""
         commands = list()
         commands.append('configure replace flash:rollback-0')
         commands.append('write memory')
         self.device.run_commands(commands)
 
     def get_facts(self):
-        """Implemantation of NAPALM method get_facts."""
+        """Implementation of NAPALM method get_facts."""
         commands = list()
         commands.append('show version')
         commands.append('show hostname')
@@ -225,7 +244,8 @@ class EOSDriver(NetworkDriver):
             interfaces[interface]['last_flapped'] = values.pop('lastStatusChangeTimestamp', None)
 
             interfaces[interface]['speed'] = int(values['bandwidth'] * 1e-6)
-            interfaces[interface]['mac_address'] = values.pop('physicalAddress', u'')
+            interfaces[interface]['mac_address'] = napalm_base.helpers.convert(
+                napalm_base.helpers.mac, values.pop('physicalAddress', u''))
 
         return interfaces
 
@@ -304,12 +324,17 @@ class EOSDriver(NetworkDriver):
         return m.group('as')
 
     @staticmethod
+    def _bgp_neighbor_enabled(line):
+        m = re.match('\s+BGP\s+state\s+is\s+.*,\s+Administratively\s+shut\s+down', line)
+        return m is None
+
+    @staticmethod
     def _parse_prefix_info(line):
         m = re.match('(\s*?)(?P<af>IPv[46]) Unicast:\s*(?P<sent>\d+)\s*(?P<received>\d+)', line)
         return m.group('sent'), m.group('received')
 
     def get_bgp_neighbors(self):
-        NEIGHBOR_FILTER = 'bgp neighbors vrf all | include remote AS | remote router ID |^\s*IPv[46] Unicast:.*[0-9]+|^Local AS|Desc'
+        NEIGHBOR_FILTER = 'bgp neighbors vrf all | include remote AS | remote router ID |IPv[46] Unicast:.*[0-9]+|^Local AS|Desc|BGP state'  # noqa
         output_summary_cmds = self.device.run_commands(
             ['show ipv6 bgp summary vrf all', 'show ip bgp summary vrf all'],
             encoding='json')
@@ -317,7 +342,7 @@ class EOSDriver(NetworkDriver):
             ['show ip ' + NEIGHBOR_FILTER, 'show ipv6 ' + NEIGHBOR_FILTER],
             encoding='text')
 
-        bgp_counters = defaultdict(lambda: dict(peers=dict()))
+        bgp_counters = {}
         for summary in output_summary_cmds:
             """
             Json output looks as follows
@@ -344,14 +369,19 @@ class EOSDriver(NetworkDriver):
             }
             """
             for vrf, vrf_data in summary['vrfs'].iteritems():
+                if vrf not in bgp_counters.keys():
+                    bgp_counters[vrf] = {
+                        'peers': {}
+                    }
                 bgp_counters[vrf]['router_id'] = vrf_data['routerId']
                 for peer, peer_data in vrf_data['peers'].iteritems():
                     peer_info = {
                         'is_up': peer_data['peerState'] == 'Established',
-                        'is_enabled': peer_data['peerState'] == 'Established' or peer_data['peerState'] == 'Active',
+                        'is_enabled': peer_data['peerState'] == 'Established' or
+                        peer_data['peerState'] == 'Active',
                         'uptime': int(peer_data['upDownTime'])
                     }
-                    bgp_counters[vrf]['peers'][peer] = peer_info
+                    bgp_counters[vrf]['peers'][napalm_base.helpers.ip(peer)] = peer_info
         lines = []
         [lines.extend(x['output'].splitlines()) for x in output_neighbor_cmds]
         for line in lines:
@@ -361,6 +391,7 @@ class EOSDriver(NetworkDriver):
               BGP neighbor is 1.1.1.1, remote AS 1, external link
                 Description: Very info such descriptive
                 BGP version 4, remote router ID 1.1.1.1, VRF my_vrf
+                BGP state is Idle, Administratively shut down
                  IPv4 Unicast:         683        78
                  IPv6 Unicast:           0         0
               Local AS is 2, local router ID 2.2.2.2
@@ -377,12 +408,13 @@ class EOSDriver(NetworkDriver):
             else:
                 rid, vrf = self._parse_rid_info(lines.pop(0))
 
+            is_enabled = self._bgp_neighbor_enabled(lines.pop(0))
             v4_sent, v4_recv = self._parse_prefix_info(lines.pop(0))
             v6_sent, v6_recv = self._parse_prefix_info(lines.pop(0))
             local_as = self._parse_local_info(lines.pop(0))
             data = {
                 'remote_as': int(r_as),
-                'remote_id': unicode(rid),
+                'remote_id': napalm_base.helpers.ip(rid),
                 'local_as': int(local_as),
                 'description': unicode(desc),
                 'address_family': {
@@ -398,30 +430,22 @@ class EOSDriver(NetworkDriver):
                     }
                 }
             }
-            bgp_counters[vrf]['peers'][neighbor].update(data)
+            peer_addr = napalm_base.helpers.ip(neighbor)
+            if peer_addr not in bgp_counters[vrf]['peers'].keys():
+                bgp_counters[vrf]['peers'][peer_addr] = {
+                    'is_up': False,  # if not found, means it was not found in the oper stats
+                    # i.e. neighbor down,
+                    'uptime': 0,
+                    'is_enabled': is_enabled
+                }
+            bgp_counters[vrf]['peers'][peer_addr].update(data)
 
         if 'default' in bgp_counters.keys():
             bgp_counters['global'] = bgp_counters.pop('default')
         return bgp_counters
 
     def get_environment(self):
-        """
-        Returns a dictionary where:
-            * fans is a dictionary of dictionaries where the key is the location and the values:
-                * status (boolean) - True if it's ok, false if it's broken
-            * temperature is a dictionary of dictionaries where the key is the location and the values:
-                * temperature (int) - Temperature in celsius the sensor is reporting.
-                * is_alert (boolean) - True if the temperature is above the alert threshold
-                * is_critical (boolean) - True if the temperature is above the critical threshold
-            * power is a dictionary of dictionaries where the key is the PSU id and the values:
-                * status (boolean) - True if it's ok, false if it's broken
-                * capacity (int) - Capacity in W that the power supply can support
-                * output (int) - Watts drawn by the system
-            * cpu is a dictionary of dictionaries where the key is the ID and the values
-                * %usage
-            * available_ram (int) - Total amount of RAM installed in the device
-            * used_ram (int) - RAM that is still free in the device
-        """
+        """Impplementation of get_environment"""
         command = list()
         command.append('show environment cooling')
         command.append('show environment temperature')
@@ -439,7 +463,8 @@ class EOSDriver(NetworkDriver):
         fans_output = output[0]
         temp_output = output[1]
         power_output = output[2]
-        cpu_output = self.device.run_commands(['show processes top once'], encoding='text')[0]['output']
+        cpu_output = self.device.run_commands(['show processes top once'],
+                                              encoding='text')[0]['output']
 
         ''' Get fans counters '''
         for slot in fans_output['fanTraySlots']:
@@ -452,9 +477,9 @@ class EOSDriver(NetworkDriver):
                 for sensorsgroup in temp_output[slot]:
                     for sensor in sensorsgroup['tempSensors']:
                         environment_counters['temperature'][sensor['name']] = {
-                            'temperature': sensor['currentTemperature'],
-                            'is_alert': sensor['currentTemperature'] > sensor['overheatThreshold'],
-                            'is_critical': sensor['currentTemperature'] > sensor['criticalThreshold']
+                           'temperature': sensor['currentTemperature'],
+                           'is_alert': sensor['currentTemperature'] > sensor['overheatThreshold'],
+                           'is_critical': sensor['currentTemperature'] > sensor['criticalThreshold']
                         }
             except:
                 pass
@@ -482,7 +507,7 @@ class EOSDriver(NetworkDriver):
 
         return environment_counters
 
-    def get_lldp_neighbors_detail(self, interface = ''):
+    def get_lldp_neighbors_detail(self, interface=''):
 
         lldp_neighbors_out = dict()
 
@@ -493,42 +518,44 @@ class EOSDriver(NetworkDriver):
         commands = list()
         commands.append(
             'show lldp neighbors {filters} detail'.format(
-                filters = ' '.join(filters)
+                filters=' '.join(filters)
             )
         )
 
         lldp_neighbors_in = {}
-        try:
-            lldp_neighbors_in = self.device.run_commands(commands)[0].get('lldpNeighbors', {})
-        except Exception:
-            return {}
+        lldp_neighbors_in = self.device.run_commands(commands)[0].get('lldpNeighbors', {})
 
         for interface in lldp_neighbors_in:
             interface_neighbors = lldp_neighbors_in.get(interface).get('lldpNeighborInfo', {})
             if not interface_neighbors:
                 # in case of empty infos
                 continue
-            for neighbor in interface_neighbors: # it is provided a list of neighbors per interface
+
+            # it is provided a list of neighbors per interface
+            for neighbor in interface_neighbors:
                 if interface not in lldp_neighbors_out.keys():
                     lldp_neighbors_out[interface] = list()
                 capabilities = neighbor.get('systemCapabilities')
                 lldp_neighbors_out[interface].append(
                     {
-                        'parent_interface'              : interface, # no parent interfaces
-                        'remote_port'                   : neighbor.get('neighborInterfaceInfo', {}).get('interfaceId', u''),
-                        'remote_port_description'       : u'',
-                        'remote_system_name'            : neighbor.get('systemName', u''),
-                        'remote_system_description'     : neighbor.get('systemDescription', u''),
-                        'remote_chassis_id'             : neighbor.get('chassisId', u''),
-                        'remote_system_capab'           : unicode(', '.join(capabilities)),
-                        'remote_system_enable_capab'   : unicode(', '.join([capability for capability in capabilities.keys() if capabilities[capability]]))
+                        'parent_interface': interface,  # no parent interfaces
+                        'remote_port':
+                            neighbor.get('neighborInterfaceInfo', {}).get('interfaceId', u''),
+                        'remote_port_description': u'',
+                        'remote_system_name': neighbor.get('systemName', u''),
+                        'remote_system_description': neighbor.get('systemDescription', u''),
+                        'remote_chassis_id': napalm_base.helpers.mac(
+                            neighbor.get('chassisId', u'')),
+                        'remote_system_capab': unicode(', '.join(capabilities)),
+                        'remote_system_enable_capab': unicode(', '.join(
+                            [capability for capability in capabilities.keys()
+                             if capabilities[capability]]))
                     }
                 )
 
         return lldp_neighbors_out
 
-    def cli(self, commands = None):
-
+    def cli(self, commands=None):
         cli_output = dict()
 
         if type(commands) is not list:
@@ -536,7 +563,8 @@ class EOSDriver(NetworkDriver):
 
         for command in commands:
             try:
-                cli_output[unicode(command)] = self.device.run_commands([command], encoding='text')[0].get('output')
+                cli_output[unicode(command)] = self.device.run_commands(
+                    [command], encoding='text')[0].get('output')
                 # not quite fair to not exploit rum_commands
                 # but at least can have better control to point to wrong command in case of failure
             except pyeapi.eapilib.CommandError:
@@ -556,7 +584,7 @@ class EOSDriver(NetworkDriver):
         return cli_output
 
     def get_bgp_config(self, group='', neighbor=''):
-        """Implemantation of NAPALM method get_bgp_config."""
+        """Implementation of NAPALM method get_bgp_config."""
         _GROUP_FIELD_MAP_ = {
             'type': 'type',
             'multipath': 'multipath',
@@ -592,40 +620,40 @@ class EOSDriver(NetworkDriver):
         _PROPERTY_TYPE_MAP_ = {
             # used to determine the default value
             # and cast the values
-            'remote-as'             : int,
-            'ebgp-multihop'         : int,
-            'local-v4-addr'         : unicode,
-            'local-v6-addr'         : unicode,
-            'local-as'              : int,
-            'remove-private-as'     : bool,
-            'next-hop-self'         : bool,
-            'description'           : unicode,
+            'remote-as': int,
+            'ebgp-multihop': int,
+            'local-v4-addr': unicode,
+            'local-v6-addr': unicode,
+            'local-as': int,
+            'remove-private-as': bool,
+            'next-hop-self': bool,
+            'description': unicode,
             'route-reflector-client': bool,
-            'password'              : unicode,
-            'route-map'             : unicode,
-            'apply-groups'          : list,
-            'type'                  : unicode,
-            'import-policy'         : unicode,
-            'export-policy'         : unicode,
-            'multipath'             : bool
+            'password': unicode,
+            'route-map': unicode,
+            'apply-groups': list,
+            'type': unicode,
+            'import-policy': unicode,
+            'export-policy': unicode,
+            'multipath': bool
         }
 
         _DATATYPE_DEFAULT_ = {
-            unicode     : u'',
-            int         : 0,
-            bool        : False,
-            list        : []
+            unicode: u'',
+            int: 0,
+            bool: False,
+            list: []
         }
 
-        def parse_options(options, default_value = False):
+        def parse_options(options, default_value=False):
 
             if not options:
                 return dict()
 
             config_property = options[0]
-            field_name  = _PROPERTY_FIELD_MAP_.get(config_property)
-            field_type  = _PROPERTY_TYPE_MAP_.get(config_property)
-            field_value = _DATATYPE_DEFAULT_.get(field_type) # to get the default value
+            field_name = _PROPERTY_FIELD_MAP_.get(config_property)
+            field_type = _PROPERTY_TYPE_MAP_.get(config_property)
+            field_value = _DATATYPE_DEFAULT_.get(field_type)  # to get the default value
 
             if not field_type:
                 # no type specified at all => return empty dictionary
@@ -649,7 +677,7 @@ class EOSDriver(NetworkDriver):
                     direction = None
                     if len(options) == 3:
                         direction = options[2]
-                        field_value = field_type(options[1]) # the name of the policy
+                        field_value = field_type(options[1])  # the name of the policy
                     elif len(options) == 2:
                         direction = options[1]
                     if direction == 'in':
@@ -675,13 +703,13 @@ class EOSDriver(NetworkDriver):
         last_peer_group = ''
         local_as = 0
         for bgp_conf_line in bgp_conf_lines:
-            raw_line = bgp_conf_line
             default_value = False
             bgp_conf_line = bgp_conf_line.strip()
             if bgp_conf_line.startswith('router bgp'):
                 local_as = int(bgp_conf_line.replace('router bgp', '').strip())
                 continue
-            if not (bgp_conf_line.startswith('neighbor') or bgp_conf_line.startswith('no neighbor')):
+            if not (bgp_conf_line.startswith('neighbor') or
+                    bgp_conf_line.startswith('no neighbor')):
                 continue
             if bgp_conf_line.startswith('no'):
                 default_value = True
@@ -718,20 +746,22 @@ class EOSDriver(NetworkDriver):
                 #
                 # because the lines are parsed sequentially
                 # can use the last group detected
-                # that way we avoid one more loop to match the neighbors with the group they belong to
+                # that way we avoid one more loop to
+                # match the neighbors with the group they belong to
                 # directly will apend the neighbor in the neighbor list of the group at the end
                 if last_peer_group not in bgp_neighbors.keys():
                     bgp_neighbors[last_peer_group] = dict()
                 if peer_address not in bgp_neighbors[last_peer_group]:
                     bgp_neighbors[last_peer_group][peer_address] = dict()
                     bgp_neighbors[last_peer_group][peer_address].update({
-                        key:_DATATYPE_DEFAULT_.get(_PROPERTY_TYPE_MAP_.get(prop)) for prop, key in _PEER_FIELD_MAP_.iteritems()
-                    }) # populating with default values
+                        key: _DATATYPE_DEFAULT_.get(_PROPERTY_TYPE_MAP_.get(prop))
+                        for prop, key in _PEER_FIELD_MAP_.iteritems()
+                    })  # populating with default values
                     bgp_neighbors[last_peer_group][peer_address].update({
                         'prefix_limit': {},
-                        'local_as'    : local_as,
+                        'local_as': local_as,
                         'authentication_key': u''
-                    }) # few more default values
+                    })  # few more default values
                 bgp_neighbors[last_peer_group][peer_address].update(
                     parse_options(options, default_value)
                 )
@@ -744,13 +774,14 @@ class EOSDriver(NetworkDriver):
                 if group_name not in bgp_config.keys():
                     bgp_config[group_name] = dict()
                     bgp_config[group_name].update({
-                        key:_DATATYPE_DEFAULT_.get(_PROPERTY_TYPE_MAP_.get(prop)) for prop, key in _GROUP_FIELD_MAP_.iteritems()
+                        key: _DATATYPE_DEFAULT_.get(_PROPERTY_TYPE_MAP_.get(prop))
+                        for prop, key in _GROUP_FIELD_MAP_.iteritems()
                     })
                     bgp_config[group_name].update({
-                        'prefix_limit'   : {},
-                        'neighbors'      : {},
-                        'local_as'       : local_as
-                    }) # few more default values
+                        'prefix_limit': {},
+                        'neighbors': {},
+                        'local_as': local_as
+                    })  # few more default values
                 bgp_config[group_name].update(
                     parse_options(options, default_value)
                 )
@@ -778,37 +809,32 @@ class EOSDriver(NetworkDriver):
             return []
 
         for neighbor in ipv4_neighbors:
-            interface   = unicode(neighbor.get('interface'))
-            mac_raw     = neighbor.get('hwAddress')
-            mac_all     = mac_raw.replace('.', '').replace(':', '')
-            mac_format  = unicode(':'.join([mac_all[i:i+2] for i in range(12)[::2]]))
-            ip          = unicode(neighbor.get('address'))
-            age         = float(neighbor.get('age'))
+            interface = unicode(neighbor.get('interface'))
+            mac_raw = neighbor.get('hwAddress')
+            ip = unicode(neighbor.get('address'))
+            age = float(neighbor.get('age'))
             arp_table.append(
                 {
-                    'interface' : interface,
-                    'mac'       : mac_format,
-                    'ip'        : ip,
-                    'age'       : age
+                    'interface': interface,
+                    'mac': napalm_base.helpers.mac(mac_raw),
+                    'ip': napalm_base.helpers.ip(ip),
+                    'age': age
                 }
             )
 
         return arp_table
 
-
-    def get_ntp_peers(self):
-
+    def get_ntp_servers(self):
         commands = ['show running-config | section ntp']
 
         raw_ntp_config = self.device.run_commands(commands, encoding='text')[0].get('output', '')
 
         ntp_config = napalm_base.helpers.textfsm_extractor(self, 'ntp_peers', raw_ntp_config)
 
-        return {unicode(ntp_peer.get('ntppeer')):{} for ntp_peer in ntp_config if ntp_peer.get('ntppeer', '')}
-
+        return {unicode(ntp_peer.get('ntppeer')): {}
+                for ntp_peer in ntp_config if ntp_peer.get('ntppeer', '')}
 
     def get_ntp_stats(self):
-
         ntp_stats = list()
 
         REGEX = (
@@ -823,33 +849,34 @@ class EOSDriver(NetworkDriver):
         commands.append('show ntp associations')
 
         # output = self.device.run_commands(commands)
-        # pyeapi.eapilib.CommandError: CLI command 2 of 2 'show ntp associations' failed: unconverted command
+        # pyeapi.eapilib.CommandError: CLI command 2 of 2 'show ntp associations'
+        # failed: unconverted command
         # JSON output not yet implemented...
 
-        ntp_assoc = self.device.run_commands(commands, encoding = 'text')[0].get('output', '\n\n')
+        ntp_assoc = self.device.run_commands(commands, encoding='text')[0].get('output', '\n\n')
         ntp_assoc_lines = ntp_assoc.splitlines()[2:]
 
         for ntp_assoc in ntp_assoc_lines:
             line_search = re.search(REGEX, ntp_assoc, re.I)
             if not line_search:
-                continue # pattern not found
+                continue  # pattern not found
             line_groups = line_search.groups()
             try:
                 ntp_stats.append({
-                    'remote'        : unicode(line_groups[1]),
-                    'synchronized'  : (line_groups[0] == '*'),
-                    'referenceid'   : unicode(line_groups[2]),
-                    'stratum'       : int(line_groups[3]),
-                    'type'          : unicode(line_groups[4]),
-                    'when'          : unicode(line_groups[5]),
-                    'hostpoll'      : int(line_groups[6]),
-                    'reachability'  : int(line_groups[7]),
-                    'delay'         : float(line_groups[8]),
-                    'offset'        : float(line_groups[9]),
-                    'jitter'        : float(line_groups[10])
+                    'remote': unicode(line_groups[1]),
+                    'synchronized': (line_groups[0] == '*'),
+                    'referenceid': unicode(line_groups[2]),
+                    'stratum': int(line_groups[3]),
+                    'type': unicode(line_groups[4]),
+                    'when': unicode(line_groups[5]),
+                    'hostpoll': int(line_groups[6]),
+                    'reachability': int(line_groups[7]),
+                    'delay': float(line_groups[8]),
+                    'offset': float(line_groups[9]),
+                    'jitter': float(line_groups[10])
                 })
             except Exception:
-                continue # jump to next line
+                continue  # jump to next line
 
         return ntp_stats
 
@@ -870,7 +897,7 @@ class EOSDriver(NetworkDriver):
             ipv4_list = list()
             if interface_name not in interfaces_ip.keys():
                 interfaces_ip[interface_name] = dict()
-                
+
             if u'ipv4' not in interfaces_ip.get(interface_name):
                 interfaces_ip[interface_name][u'ipv4'] = dict()
             if u'ipv6' not in interfaces_ip.get(interface_name):
@@ -880,15 +907,16 @@ class EOSDriver(NetworkDriver):
             if iface_details.get('primaryIp', {}).get('address') != '0.0.0.0':
                 ipv4_list.append(
                     {
-                        'address'   : iface_details.get('primaryIp', {}).get('address'),
-                        'masklen'   : iface_details.get('primaryIp', {}).get('maskLen')
+                        'address': napalm_base.helpers.ip(iface_details.get(
+                            'primaryIp', {}).get('address')),
+                        'masklen': iface_details.get('primaryIp', {}).get('maskLen')
                     }
                 )
             for secondary_ip in iface_details.get('secondaryIpsOrderedList', []):
                 ipv4_list.append(
                     {
-                        'address'   : secondary_ip.get('address'),
-                        'masklen'   : secondary_ip.get('maskLen')
+                        'address': napalm_base.helpers.ip(secondary_ip.get('address')),
+                        'masklen': secondary_ip.get('maskLen')
                     }
                 )
 
@@ -912,16 +940,19 @@ class EOSDriver(NetworkDriver):
 
             ipv6_list.append(
                 {
-                    'address'   : interface_details.get('linkLocal', {}).get('address'),
-                    'masklen'   : int(interface_details.get('linkLocal', {}).get('subnet', '::/0').split('/')[-1])
+                    'address': napalm_base.helpers.convert(
+                        napalm_base.helpers.ip, interface_details.get('linkLocal', {})
+                                                                 .get('address')),
+                    'masklen': int(
+                        interface_details.get('linkLocal', {}).get('subnet', '::/0').split('/')[-1])
                     # when no link-local set, address will be None and maslken 0
                 }
             )
             for address in interface_details.get('addresses'):
                 ipv6_list.append(
                     {
-                        'address'   : address.get('address'),
-                        'masklen'   : int(address.get('subnet').split('/')[-1])
+                        'address': napalm_base.helpers.ip(address.get('address')),
+                        'masklen': int(address.get('subnet').split('/')[-1])
                     }
                 )
             for ip in ipv6_list:
@@ -942,35 +973,33 @@ class EOSDriver(NetworkDriver):
 
         mac_entries = []
         try:
-            mac_entries = self.device.run_commands(commands)[0].get('unicastTable', {}).get('tableEntries', [])
+            mac_entries = self.device.run_commands(commands)[0].get(
+                'unicastTable', {}).get('tableEntries', [])
         except Exception:
             return {}
 
         for mac_entry in mac_entries:
-            vlan        = mac_entry.get('vlanId')
-            interface   = mac_entry.get('interface')
-            mac_raw     = mac_entry.get('macAddress')
-            mac_str     = mac_raw.replace('.', '').replace(':', '')
-            mac_format  = ':'.join([ mac_str[i:i+2] for i in range(12)[::2] ])
-            static      = (mac_entry.get('entryType') == 'static')
-            last_move   = mac_entry.get('lastMove', 0.0)
-            moves       = mac_entry.get('moves', 0)
+            vlan = mac_entry.get('vlanId')
+            interface = mac_entry.get('interface')
+            mac_raw = mac_entry.get('macAddress')
+            static = (mac_entry.get('entryType') == 'static')
+            last_move = mac_entry.get('lastMove', 0.0)
+            moves = mac_entry.get('moves', 0)
             mac_table.append(
                 {
-                    'mac'       : mac_format,
-                    'interface' : interface,
-                    'vlan'      : vlan,
-                    'active'    : True,
-                    'static'    : static,
-                    'moves'     : moves,
-                    'last_move' : last_move
+                    'mac': napalm_base.helpers.mac(mac_raw),
+                    'interface': interface,
+                    'vlan': vlan,
+                    'active': True,
+                    'static': static,
+                    'moves': moves,
+                    'last_move': last_move
                 }
             )
 
         return mac_table
 
-    def get_route_to(self, destination = '', protocol = ''):
-
+    def get_route_to(self, destination='', protocol=''):
         routes = dict()
 
         try:
@@ -981,8 +1010,8 @@ class EOSDriver(NetworkDriver):
             return 'Please specify a valid destination!'
 
         command = 'show ip{ipv} route {destination} detail'.format(
-            ipv         = ipv,
-            destination = destination
+            ipv=ipv,
+            destination=destination
         )
 
         command_output = self.device.run_commands([command])[0]
@@ -995,57 +1024,59 @@ class EOSDriver(NetworkDriver):
         for prefix, route_details in routes_out.iteritems():
             if prefix not in routes.keys():
                 routes[prefix] = list()
-            route_protocol    = route_details.get('routeType').upper()
-            preference  = route_details.get('preference')
+            route_protocol = route_details.get('routeType').upper()
+            preference = route_details.get('preference')
 
             route = {
-                'current_active'    : False,
-                'last_active'       : False,
-                'age'               : 0,
-                'next_hop'          : u'',
-                'protocol'          : route_protocol,
+                'current_active': False,
+                'last_active': False,
+                'age': 0,
+                'next_hop': u'',
+                'protocol': route_protocol,
                 'outgoing_interface': u'',
-                'preference'        : preference,
-                'inactive_reason'   : u'',
-                'routing_table'     : u'default',
-                'selected_next_hop' : False,
+                'preference': preference,
+                'inactive_reason': u'',
+                'routing_table': u'default',
+                'selected_next_hop': False,
                 'protocol_attributes': {}
             }
             if protocol == 'bgp':
-                metric      = route_details.get('metric')
+                metric = route_details.get('metric')
                 command = 'show ip{ipv} bgp {destination} detail'.format(
-                    ipv         = ipv,
-                    destination = prefix
+                    ipv=ipv,
+                    destination=prefix
                 )
-                default_vrf_details = self.device.run_commands([command])[0].get('vrfs', {}).get('default', {})
-                local_as   = default_vrf_details.get('asn')
-                bgp_routes = default_vrf_details.get('bgpRouteEntries', {}).get(prefix, {}).get('bgpRoutePaths', [])
+                default_vrf_details = self.device.run_commands([command])[0].get(
+                    'vrfs', {}).get('default', {})
+                local_as = default_vrf_details.get('asn')
+                bgp_routes = default_vrf_details.get(
+                    'bgpRouteEntries', {}).get(prefix, {}).get('bgpRoutePaths', [])
                 for bgp_route_details in bgp_routes:
                     bgp_route = route.copy()
                     as_path = bgp_route_details.get('asPathEntry', {}).get('asPath', u'')
                     remote_as = int(as_path.split()[-1])
-                    remote_address = bgp_route_details.get('routeDetail', {}).get('peerEntry', {}).get('peerAddr', '')
+                    remote_address = napalm_base.helpers.ip(bgp_route_details.get(
+                        'routeDetail', {}).get('peerEntry', {}).get('peerAddr', ''))
                     local_preference = bgp_route_details.get('localPreference')
-                    next_hop = bgp_route_details.get('nextHop')
+                    next_hop = napalm_base.helpers.ip(bgp_route_details.get('nextHop'))
                     active_route = bgp_route_details.get('routeType', {}).get('active', False)
-                    last_active = active_route # should find smth better
+                    last_active = active_route  # should find smth better
                     communities = bgp_route_details.get('routeDetail', {}).get('communityList', [])
                     preference2 = bgp_route_details.get('weight')
-                    selected_next_hop = active_route
                     bgp_route.update({
-                        'current_active'    : active_route,
-                        'last_active'       : last_active,
-                        'next_hop'          : next_hop,
-                        'selected_next_hop' : active_route,
+                        'current_active': active_route,
+                        'last_active': last_active,
+                        'next_hop': next_hop,
+                        'selected_next_hop': active_route,
                         'protocol_attributes': {
-                            'metric'            : metric,
-                            'as_path'           : as_path,
-                            'local_preference'  : local_preference,
-                            'local_as'          : local_as,
-                            'remote_as'         : remote_as,
-                            'remote_address'    : remote_address,
-                            'preference2'       : preference2,
-                            'communities'       : communities
+                            'metric': metric,
+                            'as_path': as_path,
+                            'local_preference': local_preference,
+                            'local_as': local_as,
+                            'remote_as': remote_as,
+                            'remote_address': remote_address,
+                            'preference2': preference2,
+                            'communities': communities
                         }
                     })
                     routes[prefix].append(bgp_route)
@@ -1054,7 +1085,7 @@ class EOSDriver(NetworkDriver):
                     route_next_hop = route.copy()
                     route_next_hop.update(
                         {
-                            'next_hop'          : next_hop.get('nexthopAddr'),
+                            'next_hop': napalm_base.helpers.ip(next_hop.get('nexthopAddr')),
                             'outgoing_interface': next_hop.get('interface')
                         }
                     )
@@ -1076,10 +1107,10 @@ class EOSDriver(NetworkDriver):
             return snmp_information
 
         snmp_information = {
-            'contact'   : unicode(snmp_config[0].get('contact', '')),
-            'location'  : unicode(snmp_config[0].get('location', '')),
+            'contact': unicode(snmp_config[0].get('contact', '')),
+            'location': unicode(snmp_config[0].get('location', '')),
             'chassis_id': unicode(snmp_config[0].get('chassis_id', '')),
-            'community' : {}
+            'community': {}
         }
 
         for snmp_entry in snmp_config:
@@ -1097,10 +1128,10 @@ class EOSDriver(NetworkDriver):
 
         def _sshkey_type(sshkey):
             if sshkey.startswith('ssh-rsa'):
-                return 'ssh_rsa', sshkey
+                return u'ssh_rsa', unicode(sshkey)
             elif sshkey.startswith('ssh-dss'):
-                return 'ssh_dsa', sshkey
-            return 'ssh_rsa', ''
+                return u'ssh_dsa', unicode(sshkey)
+            return u'ssh_rsa', u''
 
         users = dict()
 
@@ -1113,7 +1144,7 @@ class EOSDriver(NetworkDriver):
             sshkey_type, sshkey_value = _sshkey_type(sshkey_value)
             user_details.update({
                 'level': user_details.pop('privLevel', 0),
-                'password': user_details.pop('secret', ''),
+                'password': unicode(user_details.pop('secret', '')),
                 'sshkeys': [sshkey_value]
             })
             users[user] = user_details
@@ -1172,7 +1203,8 @@ class EOSDriver(NetworkDriver):
         )
 
         try:
-            traceroute_raw_output = self.device.run_commands([command], encoding='text')[0].get('output')
+            traceroute_raw_output = self.device.run_commands(
+                [command], encoding='text')[0].get('output')
         except CommandErrorException:
             return {'error': 'Cannot execute traceroute on the device: {}'.format(command)}
 
@@ -1187,10 +1219,13 @@ class EOSDriver(NetworkDriver):
             hop_index = int(hop_details[0])
             previous_probe_host_name = '*'
             previous_probe_ip_address = '*'
-            traceroute_result['success'][hop_index] = {'probes':{}}
+            traceroute_result['success'][hop_index] = {'probes': {}}
             for probe_index in range(probes):
                 host_name = hop_details[3+probe_index*5]
-                ip_address = hop_details[4+probe_index*5]
+                hop_addr = hop_details[4+probe_index*5]
+                ip_address = napalm_base.helpers.convert(
+                    napalm_base.helpers.ip, hop_addr, hop_addr
+                )
                 rtt = hop_details[5+probe_index*5]
                 if rtt:
                     rtt = float(rtt)
@@ -1212,3 +1247,318 @@ class EOSDriver(NetworkDriver):
                 previous_probe_ip_address = ip_address
 
         return traceroute_result
+
+    def get_bgp_neighbors_detail(self, neighbor_address=''):
+        """Implementation of get_bgp_neighbors_detail"""
+        def _parse_per_peer_bgp_detail(peer_output):
+            """This function parses the raw data per peer and returns a
+            json structure per peer.
+            """
+
+            int_fields = ['local_as', 'remote_as',
... 403 lines suppressed ...

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/napalm-eos.git



More information about the Python-modules-commits mailing list