[Python-modules-commits] [napalm-iosxr] 01/03: Import napalm-iosxr_0.2.2.orig.tar.gz

Vincent Bernat bernat at moszumanska.debian.org
Sat Sep 3 10:28:32 UTC 2016


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

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

commit 08ef66967d7c89f452c67088027bf4dcbb5e18ad
Author: Vincent Bernat <bernat at debian.org>
Date:   Sat Sep 3 12:20:18 2016 +0200

    Import napalm-iosxr_0.2.2.orig.tar.gz
---
 PKG-INFO                            |   2 +-
 napalm_iosxr.egg-info/PKG-INFO      |   2 +-
 napalm_iosxr.egg-info/SOURCES.txt   |   5 +-
 napalm_iosxr.egg-info/requires.txt  |   2 +-
 napalm_iosxr.egg-info/top_level.txt |   1 +
 napalm_iosxr/iosxr.py               | 450 +++++++++++++++++++++---------------
 requirements.txt                    |   2 +-
 setup.py                            |   2 +-
 test/__init__.py                    |   0
 test/unit/TestIOSXRDriver.py        |  81 +++++++
 test/unit/__init__.py               |   0
 11 files changed, 358 insertions(+), 189 deletions(-)

diff --git a/PKG-INFO b/PKG-INFO
index 302f33e..ce48e66 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: napalm-iosxr
-Version: 0.2.1
+Version: 0.2.2
 Summary: Network Automation and Programmability Abstraction Layer with Multivendor support
 Home-page: https://github.com/napalm-automation/napalm-iosxr
 Author: David Barroso
diff --git a/napalm_iosxr.egg-info/PKG-INFO b/napalm_iosxr.egg-info/PKG-INFO
index 302f33e..ce48e66 100644
--- a/napalm_iosxr.egg-info/PKG-INFO
+++ b/napalm_iosxr.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: napalm-iosxr
-Version: 0.2.1
+Version: 0.2.2
 Summary: Network Automation and Programmability Abstraction Layer with Multivendor support
 Home-page: https://github.com/napalm-automation/napalm-iosxr
 Author: David Barroso
diff --git a/napalm_iosxr.egg-info/SOURCES.txt b/napalm_iosxr.egg-info/SOURCES.txt
index b32b62b..f10aac1 100644
--- a/napalm_iosxr.egg-info/SOURCES.txt
+++ b/napalm_iosxr.egg-info/SOURCES.txt
@@ -13,4 +13,7 @@ napalm_iosxr/templates/delete_probes.j2
 napalm_iosxr/templates/schedule_probes.j2
 napalm_iosxr/templates/set_hostname.j2
 napalm_iosxr/templates/set_ntp_peers.j2
-napalm_iosxr/templates/set_probes.j2
\ No newline at end of file
+napalm_iosxr/templates/set_probes.j2
+test/__init__.py
+test/unit/TestIOSXRDriver.py
+test/unit/__init__.py
\ No newline at end of file
diff --git a/napalm_iosxr.egg-info/requires.txt b/napalm_iosxr.egg-info/requires.txt
index 24f01f2..2a3c075 100644
--- a/napalm_iosxr.egg-info/requires.txt
+++ b/napalm_iosxr.egg-info/requires.txt
@@ -1,3 +1,3 @@
 napalm-base
-pyIOSXR
+pyIOSXR>=0.20
 netaddr
diff --git a/napalm_iosxr.egg-info/top_level.txt b/napalm_iosxr.egg-info/top_level.txt
index c93dcbf..7d5acaf 100644
--- a/napalm_iosxr.egg-info/top_level.txt
+++ b/napalm_iosxr.egg-info/top_level.txt
@@ -1 +1,2 @@
 napalm_iosxr
+test
diff --git a/napalm_iosxr/iosxr.py b/napalm_iosxr/iosxr.py
index 9acdee4..66fe695 100644
--- a/napalm_iosxr/iosxr.py
+++ b/napalm_iosxr/iosxr.py
@@ -18,16 +18,19 @@ import copy
 from collections import defaultdict
 
 # third party libs
+from lxml import etree as ETREE
 import xml.etree.ElementTree as ET
 
 from netaddr import IPAddress
 from netaddr.core import AddrFormatError
 
 from pyIOSXR import IOSXR
-from pyIOSXR.iosxr import __execute_show__
-from pyIOSXR.exceptions import InvalidInputError, TimeoutError, EOFError
+from pyIOSXR.exceptions import ConnectError
+from pyIOSXR.exceptions import TimeoutError
+from pyIOSXR.exceptions import InvalidInputError
 
 # napalm_base
+from napalm_base.helpers import convert, find_txt, mac, ip
 from napalm_base.base import NetworkDriver
 from napalm_base.utils import string_parsers
 from napalm_base.exceptions import ConnectionException, MergeConfigException, ReplaceConfigException,\
@@ -51,8 +54,8 @@ class IOSXRDriver(NetworkDriver):
     def open(self):
         try:
             self.device.open()
-        except EOFError as ee:
-            raise ConnectionException(ee.message)
+        except ConnectError as conn_err:
+            raise ConnectionException(conn_err.message)
 
     def close(self):
         self.device.close()
@@ -128,88 +131,89 @@ class IOSXRDriver(NetworkDriver):
         except:
             return default
 
-
     def get_facts(self):
 
-        sh_ver = self.device.show_version()
+        facts = {
+            'vendor': u'Cisco',
+            'os_version': u'',
+            'hostname': u'',
+            'uptime': -1,
+            'serial_number': u'',
+            'fqdn': u'',
+            'model': u'',
+            'interface_list': []
+        }
+
+        facts_rpc_request = (
+            '<Get>'
+                '<Operational>'
+                    '<SystemTime/>'
+                    '<PlatformInventory/>'
+                '</Operational>'
+            '</Get>'
+        )
+
+        facts_rpc_reply = ETREE.fromstring(self.device.make_rpc_call(facts_rpc_request))
+        system_time_xpath = './/SystemTime/Uptime'
+        platform_attr_xpath = './/RackTable/Rack/Attributes/BasicInfo'
+        system_time_tree = facts_rpc_reply.xpath(system_time_xpath)[0]
+        platform_attr_tree = facts_rpc_reply.xpath(platform_attr_xpath)[0]
+
+        hostname = convert(unicode, find_txt(system_time_tree, 'Hostname'))
+        uptime = convert(int, find_txt(system_time_tree, 'Uptime'), -1)
+        serial = convert(unicode, find_txt(platform_attr_tree, 'SerialNumber'))
+        os_version = convert(unicode, find_txt(platform_attr_tree, 'SoftwareRevision'))
+        model = convert(unicode, find_txt(platform_attr_tree, 'ModelName'))
+        interface_list = self.get_interfaces().keys()
+
+        facts.update({
+            'os_version': os_version,
+            'hostname': hostname,
+            'model': model,
+            'uptime': uptime,
+            'serial_number': serial,
+            'fqdn': hostname,
+            'interface_list': interface_list
+        })
 
-        for line in sh_ver.splitlines():
-            if 'Cisco IOS XR Software' in line:
-                os_version = line.split()[-1]
-            elif 'uptime' in line:
-                uptime = string_parsers.convert_uptime_string_seconds(line)
-                hostname = line.split()[0]
-                fqdn = line.split()[0]
-            elif 'Series' in line:
-                model = ' '.join(line.split()[1:3])
+        return facts
 
-        interface_list = list()
+    def get_interfaces(self):
 
-        for x in self.device.show_interface_description().splitlines()[3:-1]:
-            if '.' not in x:
-                interface_list.append(x.split()[0])
+        interfaces = {}
 
-        result = {
-            'vendor': u'Cisco',
-            'os_version': unicode(os_version),
-            'hostname': unicode(hostname),
-            'uptime': uptime,
-            'model': unicode(model),
-            'serial_number': u'',
-            'fqdn': unicode(fqdn),
-            'interface_list': interface_list,
+        INTERFACE_DEFAULTS = {
+            'is_enabled': False,
+            'is_up': False,
+            'mac_address': u'',
+            'description': u'',
+            'speed': -1,
+            'last_flapped': -1.0
         }
 
-        return result
+        interfaces_rpc_request = '<Get><Operational><Interfaces/></Operational></Get>'
 
-    def get_interfaces(self):
+        interfaces_rpc_reply = ETREE.fromstring(self.device.make_rpc_call(interfaces_rpc_request))
 
-        # init result dict
-        result = {}
-
-        # fetch show interface output
-        sh_int = self.device.show_interfaces()
-        # split per interface, eg by empty line
-        interface_list = sh_int.rstrip().split('\n\n')
-        # for each interface...
-        for interface in interface_list:
-
-            # splitting this and matching each line avoids issues with order
-            # sorry...
-            interface_lines = interface.split('\n')
-
-            # init variables to match for
-            interface_name = None
-            is_enabled = None
-            is_up = None
-            mac_address = None
-            description = None
-            speed = None
-
-            # loop though and match each line
-            for line in interface_lines:
-                description = ''
-                if 'line protocol' in line:
-                    lp = line.split()
-                    interface_name = lp[0]
-                    is_enabled = lp[2] == 'up,'
-                    is_up = lp[6] == 'up'
-                elif 'bia' in line:
-                    mac_address = line.split()[-1].replace(')', '')
-                elif 'Description' in line:
-                    description = ' '.join(line.split()[1:])
-                elif 'BW' in line:
-                    speed = int(line.split()[4]) / 1000
-            result[interface_name] = {
-                'is_enabled': is_enabled,
+        for interface_tree in interfaces_rpc_reply.xpath('.//Interfaces/InterfaceTable/Interface'):
+            interface_name = find_txt(interface_tree, 'Naming/InterfaceName')
+            if not interface_name:
+                continue
+            is_up = (find_txt(interface_tree, 'LineState') == 'IM_STATE_UP')
+            is_enabled = (find_txt(interface_tree, 'LineState') == 'IM_STATE_UP')
+            mac_address = mac(find_txt(interface_tree, 'MACAddress/Address'))
+            speed = int(convert(int, find_txt(interface_tree, 'Bandwidth'), 0) * 1e-3)
+            description = find_txt(interface_tree, 'Description')
+            interfaces[interface_name] = copy.deepcopy(INTERFACE_DEFAULTS)
+            interfaces[interface_name].update({
                 'is_up': is_up,
-                'mac_address': unicode(mac_address),
-                'description': unicode(description),
                 'speed': speed,
-                'last_flapped': -1.0,
-            }
+                'is_enabled': is_enabled,
+                'mac_address': mac_address,
+                'description': description
+            })
 
-        return result
+        return interfaces
 
     def get_interfaces_counters(self):
         rpc_command = "<Get><Operational><Interfaces><InterfaceTable></InterfaceTable></Interfaces></Operational></Get>"
@@ -681,7 +685,7 @@ class IOSXRDriver(NetworkDriver):
 
         for command in commands:
             try:
-                cli_output[unicode(command)] = unicode(__execute_show__(self.device.device, command, self.timeout))
+                cli_output[unicode(command)] = unicode(self.device._execute_show(command))
             except TimeoutError:
                 cli_output[unicode(command)] = 'Execution of command "{command}" took too long! Please adjust your params!'.format(
                     command = command
@@ -827,37 +831,77 @@ class IOSXRDriver(NetworkDriver):
 
         return bgp_config
 
-    def get_bgp_neighbors_detail(self, neighbor_address = ''):
+    def get_bgp_neighbors_detail(self, neighbor_address=''):
+
+        bgp_neighbors_detail = {}
+
+        active_vrfs = ['default']
+
+        active_vrfs_rpc_request = (
+            '<Get>'
+                '<Operational>'
+                    '<BGP>'
+                        '<ConfigInstanceTable>'
+                            '<ConfigInstance>'
+                                '<Naming>'
+                                    '<InstanceName>'
+                                        'default'
+                                    '</InstanceName>'
+                                '</Naming>'
+                                '<ConfigInstanceVRFTable/>'
+                            '</ConfigInstance>'
+                        '</ConfigInstanceTable>'
+                    '</BGP>'
+                '</Operational>'
+            '</Get>'
+        )
 
-        bgp_neighbors = dict()
+        active_vrfs_rpc_reply = ETREE.fromstring(self.device.make_rpc_call(active_vrfs_rpc_request))
+        active_vrfs_tree = active_vrfs_rpc_reply.xpath('.//ConfigVRF')
+
+        for active_vrf_tree in active_vrfs_tree:
+            active_vrfs.append(find_txt(active_vrf_tree, 'Naming/VRFName'))
+
+        unique_active_vrfs = set(active_vrfs)
+
+        bgp_neighbors_vrf_all_rpc = (
+            '<Get>'
+                '<Operational>'
+                    '<BGP>'
+                        '<InstanceTable>'
+                            '<Instance>'
+                                '<Naming>'
+                                    '<InstanceName>'
+                                        'default'
+                                    '</InstanceName>'
+                                '</Naming>'
+        )
 
-        rpc_command = '''
-                <Get>
-                    <Operational>
-                        <BGP>
-                            <InstanceTable>
-                                <Instance>
-                                    <Naming>
-                                        <InstanceName>
-                                            default
-                                        </InstanceName>
-                                    </Naming>
-                                    <InstanceActive>
-                                        <DefaultVRF>
-                                            <GlobalProcessInfo>
-                                            </GlobalProcessInfo>
-                                            <NeighborTable>
-                                            </NeighborTable>
-                                        </DefaultVRF>
-                                    </InstanceActive>
-                                </Instance>
-                            </InstanceTable>
-                        </BGP>
-                    </Operational>
-                </Get>
-        '''
+        for active_vrf in unique_active_vrfs:
+            vrf_rpc = (
+                '<InstanceActive>'
+                    '<VRFTable>'
+                        '<VRF>'
+                            '<Naming>'
+                                '{vrf_name}'
+                            '</Naming>'
+                            '<GlobalProcessInfo/>'
+                            '<NeighborTable/>'
+                        '</VRF>'
+                    '</VRFTable>'
+                '</InstanceActive>'
+            )
+            bgp_neighbors_vrf_all_rpc += vrf_rpc.format(vrf_name=active_vrf)
+
+        bgp_neighbors_vrf_all_rpc += (
+                            '</Instance>'
+                        '</InstanceTable>'
+                    '</BGP>'
+                '</Operational>'
+            '</Get>'
+        )
 
-        result_tree = ET.fromstring(self.device.make_rpc_call(rpc_command))
+        bgp_neighbors_vrf_all_tree = ETREE.fromstring(self.device.make_rpc_call(bgp_neighbors_vrf_all_rpc))
 
         _BGP_STATE_ = {
             '0': 'Unknown',
@@ -869,92 +913,97 @@ class IOSXRDriver(NetworkDriver):
             '6': 'Established'
         }
 
-        routing_table = unicode(self._find_txt(result_tree, 'InstanceTable/Instance/Naming/InstanceName', 'default'))
-        # if multi-VRF needed, create a loop through all instances
-        for neighbor in result_tree.iter('Neighbor'):
-            try:
-                up                          = (self._find_txt(neighbor, 'ConnectionState') == 'BGP_ST_ESTAB')
-                local_as                    = int(self._find_txt(neighbor, 'LocalAS', 0))
-                remote_as                   = int(self._find_txt(neighbor, 'RemoteAS', 0))
-                remote_address              = unicode(self._find_txt(neighbor, 'Naming/NeighborAddress/IPV4Address') \
-                    or self._find_txt(neighbor, 'Naming/NeighborAddress/IPV6Address'))
-                local_address_configured    = eval(self._find_txt(neighbor, 'IsLocalAddressConfigured', 'false').title())
-                local_address               = unicode(self._find_txt(neighbor, 'ConnectionLocalAddress/IPV4Address') \
-                    or self._find_txt(neighbor, 'ConnectionLocalAddress/IPV6Address'))
-                local_port                  = int(self._find_txt(neighbor, 'ConnectionLocalPort'))
-                remote_address              = unicode(self._find_txt(neighbor, 'ConnectionRemoteAddress/IPV4Address') \
-                    or self._find_txt(neighbor, 'ConnectionRemoteAddress/IPV6Address'))
-                remote_port                 = int(self._find_txt(neighbor, 'ConnectionRemotePort'))
-                multihop                    = eval(self._find_txt(neighbor, 'IsExternalNeighborNotDirectlyConnected', 'false').title())
-                remove_private_as           = eval(self._find_txt(neighbor, 'AFData/Entry/RemovePrivateASFromUpdates', 'false').title())
-                multipath                   = eval(self._find_txt(neighbor, 'AFData/Entry/SelectiveMultipathEligible', 'false').title())
-                import_policy               = unicode(self._find_txt(neighbor, 'AFData/Entry/RoutePolicyIn'))
-                export_policy               = unicode(self._find_txt(neighbor, 'AFData/Entry/RoutePolicyOut'))
-                input_messages              = int(self._find_txt(neighbor, 'MessgesReceived', 0))
-                output_messages             = int(self._find_txt(neighbor, 'MessagesSent', 0))
-                connection_up_count         = int(self._find_txt(neighbor, 'ConnectionUpCount', 0))
-                connection_down_count       = int(self._find_txt(neighbor, 'ConnectionDownCount', 0))
-                messages_queued_out         = int(self._find_txt(neighbor, 'MessagesQueuedOut', 0))
-                connection_state            = unicode(self._find_txt(neighbor, 'ConnectionState').replace('BGP_ST_', '').title())
+        instance_active_list = bgp_neighbors_vrf_all_tree.xpath('.//InstanceTable/Instance/InstanceActive/VRFTable/VRF')
+
+        for vrf_tree in instance_active_list:
+            vrf_name = find_txt(vrf_tree, 'Naming/VRFName')
+            vrf_keepalive = convert(int, find_txt(instance_active_list, 'GlobalProcessInfo/VRF/KeepAliveTime'))
+            vrf_holdtime = convert(int, find_txt(instance_active_list, 'GlobalProcessInfo/VRF/HoldTime'))
+            if vrf_name not in bgp_neighbors_detail.keys():
+                bgp_neighbors_detail[vrf_name] = {}
+            for neighbor in vrf_tree.xpath('NeighborTable/Neighbor'):
+                up = (find_txt(neighbor, 'ConnectionState') == 'BGP_ST_ESTAB')
+                local_as = convert(int, find_txt(neighbor, 'LocalAS', 0))
+                remote_as = convert(int, find_txt(neighbor, 'RemoteAS', 0))
+                router_id = ip(find_txt(neighbor, 'RouterID'))
+                remote_address = ip(find_txt(neighbor, 'Naming/NeighborAddress/IPV4Address')) \
+                    or ip(find_txt(neighbor, 'Naming/NeighborAddress/IPV6Address'))
+                local_address_configured = eval(find_txt(neighbor, 'IsLocalAddressConfigured', 'false').title())
+                local_address = ip(find_txt(neighbor, 'ConnectionLocalAddress/IPV4Address')) \
+                    or ip(find_txt(neighbor, 'ConnectionLocalAddress/IPV6Address'))
+                local_port = convert(int, find_txt(neighbor, 'ConnectionLocalPort'))
+                remote_address = ip(find_txt(neighbor, 'ConnectionRemoteAddress/IPV4Address')) \
+                    or ip(find_txt(neighbor, 'ConnectionRemoteAddress/IPV6Address'))
+                remote_port = convert(int, find_txt(neighbor, 'ConnectionRemotePort'))
+                multihop = eval(find_txt(neighbor, 'IsExternalNeighborNotDirectlyConnected', 'false').title())
+                remove_private_as = eval(find_txt(neighbor, 'AFData/Entry/RemovePrivateASFromUpdates', 'false').title())
+                multipath = eval(find_txt(neighbor, 'AFData/Entry/SelectiveMultipathEligible', 'false').title())
+                import_policy = find_txt(neighbor, 'AFData/Entry/RoutePolicyIn')
+                export_policy = find_txt(neighbor, 'AFData/Entry/RoutePolicyOut')
+                input_messages = convert(int, find_txt(neighbor, 'MessgesReceived', 0))
+                output_messages = convert(int, find_txt(neighbor, 'MessagesSent', 0))
+                connection_up_count = convert(int, find_txt(neighbor, 'ConnectionUpCount', 0))
+                connection_down_count = convert(int, find_txt(neighbor, 'ConnectionDownCount', 0))
+                messages_queued_out = convert(int, find_txt(neighbor, 'MessagesQueuedOut', 0))
+                connection_state = find_txt(neighbor, 'ConnectionState').replace('BGP_ST_', '').title()
                 if connection_state == u'Estab':
                     connection_state = u'Established'
-                previous_connection_state   = unicode(_BGP_STATE_.get(self._find_txt(neighbor, 'PreviousConnectionState', '0')))
-                active_prefix_count         = int(self._find_txt(neighbor, 'AFData/Entry/NumberOfBestpaths', 0))
-                accepted_prefix_count       = int(self._find_txt(neighbor, 'AFData/Entry/PrefixesAccepted', 0))
-                suppressed_prefix_count     = int(self._find_txt(neighbor, 'AFData/Entry/PrefixesDenied', 0))
-                received_prefix_count       = accepted_prefix_count + suppressed_prefix_count # not quite right...
-                advertise_prefix_count      = int(self._find_txt(neighbor, 'AFData/Entry/PrefixesAdvertised', 0))
-                suppress_4byte_as           = eval(self._find_txt(neighbor, 'Suppress4ByteAs', 'false').title())
-                local_as_prepend            = not eval(self._find_txt(neighbor, 'LocalASNoPrepend', 'false').title())
-                holdtime                    = int(self._find_txt(neighbor, 'HoldTime', 0))
-                configured_holdtime         = int(self._find_txt(neighbor, 'ConfiguredHoldTime', 0))
-                keepalive                   = int(self._find_txt(neighbor, 'KeepAliveTime', 0))
-                configured_keepalive        = int(self._find_txt(neighbor, 'ConfiguredKeepalive', 0))
+                previous_connection_state = unicode(_BGP_STATE_.get(find_txt(neighbor, 'PreviousConnectionState', '0')))
+                active_prefix_count = convert(int, find_txt(neighbor, 'AFData/Entry/NumberOfBestpaths', 0))
+                accepted_prefix_count = convert(int, find_txt(neighbor, 'AFData/Entry/PrefixesAccepted', 0))
+                suppressed_prefix_count = convert(int, find_txt(neighbor, 'AFData/Entry/PrefixesDenied', 0))
+                received_prefix_count = accepted_prefix_count + suppressed_prefix_count # not quite right...
+                advertised_prefix_count = convert(int, find_txt(neighbor, 'AFData/Entry/PrefixesAdvertised', 0))
+                suppress_4byte_as = eval(find_txt(neighbor, 'Suppress4ByteAs', 'false').title())
+                local_as_prepend = not eval(find_txt(neighbor, 'LocalASNoPrepend', 'false').title())
+                holdtime = convert(int, find_txt(neighbor, 'HoldTime', 0)) or vrf_holdtime
+                configured_holdtime = convert(int, find_txt(neighbor, 'ConfiguredHoldTime', 0))
+                keepalive = convert(int, find_txt(neighbor, 'KeepAliveTime', 0)) or vrf_keepalive
+                configured_keepalive = convert(int, find_txt(neighbor, 'ConfiguredKeepalive', 0))
                 flap_count = connection_down_count / 2
                 if up:
                     flap_count -= 1
-                if remote_as not in bgp_neighbors.keys():
-                    bgp_neighbors[remote_as] = list()
-                bgp_neighbors[remote_as].append({
-                    'up'                        : up,
-                    'local_as'                  : local_as,
-                    'remote_as'                 : remote_as,
-                    'local_address'             : local_address,
-                    'routing_table'             : routing_table,
-                    'local_address_configured'  : local_address_configured,
-                    'local_port'                : local_port,
-                    'remote_address'            : remote_address,
-                    'remote_port'               : remote_port,
-                    'multihop'                  : multihop,
-                    'multipath'                 : multipath,
-                    'import_policy'             : import_policy,
-                    'export_policy'             : export_policy,
-                    'input_messages'            : input_messages,
-                    'output_messages'           : output_messages,
-                    'input_updates'             : 0,
-                    'output_updates'            : 0,
-                    'messages_queued_out'       : messages_queued_out,
-                    'connection_state'          : connection_state,
-                    'previous_connection_state' : previous_connection_state,
-                    'last_event'                : u'',
-                    'remove_private_as'         : remove_private_as,
-                    'suppress_4byte_as'         : suppress_4byte_as,
-                    'local_as_prepend'          : local_as_prepend,
-                    'holdtime'                  : holdtime,
-                    'configured_holdtime'       : configured_holdtime,
-                    'keepalive'                 : keepalive,
-                    'configured_keepalive'      : configured_keepalive,
-                    'active_prefix_count'       : active_prefix_count,
-                    'received_prefix_count'     : received_prefix_count,
-                    'accepted_prefix_count'     : accepted_prefix_count,
-                    'suppressed_prefix_count'   : suppressed_prefix_count,
-                    'advertise_prefix_count'    : advertise_prefix_count,
-                    'flap_count'                : flap_count
+                if remote_as not in bgp_neighbors_detail[vrf_name].keys():
+                    bgp_neighbors_detail[vrf_name][remote_as] = []
+                bgp_neighbors_detail[vrf_name][remote_as].append({
+                    'up': up,
+                    'local_as': local_as,
+                    'remote_as': remote_as,
+                    'router_id': router_id,
+                    'local_address': local_address,
+                    'routing_table': vrf_name,
+                    'local_address_configured': local_address_configured,
+                    'local_port': local_port,
+                    'remote_address': remote_address,
+                    'remote_port': remote_port,
+                    'multihop': multihop,
+                    'multipath': multipath,
+                    'import_policy': import_policy,
+                    'export_policy': export_policy,
+                    'input_messages': input_messages,
+                    'output_messages': output_messages,
+                    'input_updates': 0,
+                    'output_updates': 0,
+                    'messages_queued_out': messages_queued_out,
+                    'connection_state': connection_state,
+                    'previous_connection_state': previous_connection_state,
+                    'last_event': u'',
+                    'remove_private_as': remove_private_as,
+                    'suppress_4byte_as': suppress_4byte_as,
+                    'local_as_prepend': local_as_prepend,
+                    'holdtime': holdtime,
+                    'configured_holdtime': configured_holdtime,
+                    'keepalive': keepalive,
+                    'configured_keepalive': configured_keepalive,
+                    'active_prefix_count': active_prefix_count,
+                    'received_prefix_count': received_prefix_count,
+                    'accepted_prefix_count': accepted_prefix_count,
+                    'suppressed_prefix_count': suppressed_prefix_count,
+                    'advertised_prefix_count': advertised_prefix_count,
+                    'flap_count': flap_count
                 })
-            except Exception:
-                continue
 
-        return bgp_neighbors
+        return bgp_neighbors_detail
 
     def get_arp_table(self):
 
@@ -988,8 +1037,43 @@ class IOSXRDriver(NetworkDriver):
 
     def get_ntp_peers(self):
 
-        ntp_stats = self.get_ntp_stats()
-        return {ntp_peer.get('remote'): {} for ntp_peer in ntp_stats if ntp_peer.get('remote', '')}
+        ntp_peers = {}
+
+        rpc_command = '<Get><Configuration><NTP></NTP></Configuration></Get>'
+
+        result_tree = ETREE.fromstring(self.device.make_rpc_call(rpc_command))
+
+        for version in ['IPV4', 'IPV6']:
+            for peer in result_tree.findall('.//Peer{version}Table/Peer{version}'.format(version=version)):
+                peer_type = find_txt(peer, 'PeerType{version}/Naming/PeerType'.format(version=version))
+                if peer_type != 'Peer':
+                    continue
+                peer_address = find_txt(peer, 'Naming/Address{version}'.format(version=version))
+                if not peer_address:
+                    continue
+                ntp_peers[peer_address] = {}
+
+        return ntp_peers
+
+    def get_ntp_servers(self):
+
+        ntp_servers = {}
+
+        rpc_command = '<Get><Configuration><NTP></NTP></Configuration></Get>'
+
+        result_tree = ETREE.fromstring(self.device.make_rpc_call(rpc_command))
+
+        for version in ['IPV4', 'IPV6']:
+            for peer in result_tree.xpath('.//Peer{version}Table/Peer{version}'.format(version=version)):
+                peer_type = find_txt(peer, 'PeerType{version}/Naming/PeerType'.format(version=version))
+                if peer_type != 'Server':
+                    continue
+                server_address =find_txt(peer, 'Naming/Address{version}'.format(version=version))
+                if not server_address:
+                    continue
+                ntp_servers[server_address] = {}
+
+        return ntp_servers
 
     def get_ntp_stats(self):
 
diff --git a/requirements.txt b/requirements.txt
index 24f01f2..e57e41e 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,3 +1,3 @@
 napalm-base
-pyIOSXR
+pyIOSXR >= 0.20
 netaddr
diff --git a/setup.py b/setup.py
index 8c6fc1e..f4d1958 100644
--- a/setup.py
+++ b/setup.py
@@ -12,7 +12,7 @@ reqs = [str(ir.req) for ir in install_reqs]
 
 setup(
     name="napalm-iosxr",
-    version="0.2.1",
+    version="0.2.2",
     packages=find_packages(),
     author="David Barroso",
     author_email="dbarrosop at dravetech.com",
diff --git a/test/__init__.py b/test/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/test/unit/TestIOSXRDriver.py b/test/unit/TestIOSXRDriver.py
new file mode 100644
index 0000000..9eb801a
--- /dev/null
+++ b/test/unit/TestIOSXRDriver.py
@@ -0,0 +1,81 @@
+# Copyright 2015 Spotify AB. All rights reserved.
+#
+# The contents of this file are licensed under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with the
+# License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+import unittest
+import os
+
+from napalm_iosxr.iosxr import IOSXRDriver
+from napalm_base.test.base import TestConfigNetworkDriver, TestGettersNetworkDriver
+
+
+class TestConfigIOSXRDriver(unittest.TestCase, TestConfigNetworkDriver):
+
+    @classmethod
+    def setUpClass(cls):
+        hostname = '127.0.0.1'
+        username = 'vagrant'
+        password = 'vagrant'
+        cls.vendor = 'iosxr'
+
+        optional_args = {'port': 12202}
+        cls.device = IOSXRDriver(hostname, username, password, timeout=60, optional_args=optional_args)
+        cls.device.open()
+        cls.device.load_replace_candidate(filename='%s/initial.conf' % cls.vendor)
+        cls.device.commit_config()
+
+
+class TestGetterIOSXRDriver(unittest.TestCase, TestGettersNetworkDriver):
+
+    @classmethod
+    def setUpClass(cls):
+        cls.mock = True
+
+        hostname = '192.168.56.202'
+        username = 'vagrant'
+        password = 'vagrant'
+        cls.vendor = 'iosxr'
+
+        cls.device = IOSXRDriver(hostname, username, password, timeout=60)
+
+        if cls.mock:
+            cls.device.device = FakeIOSXRDevice()
+        else:
+            cls.device.open()
+
+
+class FakeIOSXRDevice:
+
+    @staticmethod
+    def read_txt_file(filename):
+        curr_dir = os.path.dirname(os.path.abspath(__file__))
+        fullpath = os.path.join(curr_dir, filename)
+        with open(fullpath) as data_file:
+            return data_file.read()
+
+    def show_version(self):
+        return self.read_txt_file('iosxr/mock_data/show_version.txt')
+
+    def show_interfaces(self):
+        return self.read_txt_file('iosxr/mock_data/show_interfaces.txt')
+
+    def show_interface_description(self):
+        return self.read_txt_file('iosxr/mock_data/show_interface_description.txt')
+
+    def show_lldp_neighbors(self):
+        return self.read_txt_file('iosxr/mock_data/show_lldp_neighbors.txt')
+
+    def make_rpc_call(self, rpc_call):
+        rpc_call = \
+            rpc_call.replace('<', '_').replace('>', '_').replace('/', '_').replace('\n', '').replace(' ', '')
+        return self.read_txt_file('iosxr/mock_data/{}.rpc'.format(rpc_call[0:150]))
diff --git a/test/unit/__init__.py b/test/unit/__init__.py
new file mode 100644
index 0000000..e69de29

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



More information about the Python-modules-commits mailing list