[Python-modules-commits] [napalm-iosxr] 01/04: Imported Upstream version 0.2.1

Vincent Bernat bernat at moszumanska.debian.org
Tue Jun 7 15:20:34 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 016cbe1cf9bbcbc094a4206e7ec1e6a7c6ddb0bd
Author: Vincent Bernat <bernat at debian.org>
Date:   Tue Jun 7 17:13:31 2016 +0200

    Imported Upstream version 0.2.1
---
 MANIFEST.in                                |    2 +
 PKG-INFO                                   |   14 +
 napalm_iosxr.egg-info/PKG-INFO             |   14 +
 napalm_iosxr.egg-info/SOURCES.txt          |   16 +
 napalm_iosxr.egg-info/dependency_links.txt |    1 +
 napalm_iosxr.egg-info/requires.txt         |    3 +
 napalm_iosxr.egg-info/top_level.txt        |    1 +
 napalm_iosxr/__init__.py                   |   16 +
 napalm_iosxr/iosxr.py                      | 1622 ++++++++++++++++++++++++++++
 napalm_iosxr/templates/delete_ntp_peers.j2 |    3 +
 napalm_iosxr/templates/delete_probes.j2    |   16 +
 napalm_iosxr/templates/schedule_probes.j2  |   12 +
 napalm_iosxr/templates/set_hostname.j2     |    1 +
 napalm_iosxr/templates/set_ntp_peers.j2    |    3 +
 napalm_iosxr/templates/set_probes.j2       |   37 +
 requirements.txt                           |    3 +
 setup.cfg                                  |    5 +
 setup.py                                   |   29 +
 18 files changed, 1798 insertions(+)

diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000..923df30
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1,2 @@
+include requirements.txt
+include napalm_iosxr/templates/*.j2
diff --git a/PKG-INFO b/PKG-INFO
new file mode 100644
index 0000000..302f33e
--- /dev/null
+++ b/PKG-INFO
@@ -0,0 +1,14 @@
+Metadata-Version: 1.1
+Name: napalm-iosxr
+Version: 0.2.1
+Summary: Network Automation and Programmability Abstraction Layer with Multivendor support
+Home-page: https://github.com/napalm-automation/napalm-iosxr
+Author: David Barroso
+Author-email: dbarrosop at dravetech.com
+License: UNKNOWN
+Description: UNKNOWN
+Platform: UNKNOWN
+Classifier: Topic :: Utilities
+Classifier: Programming Language :: Python
+Classifier: Operating System :: POSIX :: Linux
+Classifier: Operating System :: MacOS
diff --git a/napalm_iosxr.egg-info/PKG-INFO b/napalm_iosxr.egg-info/PKG-INFO
new file mode 100644
index 0000000..302f33e
--- /dev/null
+++ b/napalm_iosxr.egg-info/PKG-INFO
@@ -0,0 +1,14 @@
+Metadata-Version: 1.1
+Name: napalm-iosxr
+Version: 0.2.1
+Summary: Network Automation and Programmability Abstraction Layer with Multivendor support
+Home-page: https://github.com/napalm-automation/napalm-iosxr
+Author: David Barroso
+Author-email: dbarrosop at dravetech.com
+License: UNKNOWN
+Description: UNKNOWN
+Platform: UNKNOWN
+Classifier: Topic :: Utilities
+Classifier: Programming Language :: Python
+Classifier: Operating System :: POSIX :: Linux
+Classifier: Operating System :: MacOS
diff --git a/napalm_iosxr.egg-info/SOURCES.txt b/napalm_iosxr.egg-info/SOURCES.txt
new file mode 100644
index 0000000..b32b62b
--- /dev/null
+++ b/napalm_iosxr.egg-info/SOURCES.txt
@@ -0,0 +1,16 @@
+MANIFEST.in
+requirements.txt
+setup.py
+napalm_iosxr/__init__.py
+napalm_iosxr/iosxr.py
+napalm_iosxr.egg-info/PKG-INFO
+napalm_iosxr.egg-info/SOURCES.txt
+napalm_iosxr.egg-info/dependency_links.txt
+napalm_iosxr.egg-info/requires.txt
+napalm_iosxr.egg-info/top_level.txt
+napalm_iosxr/templates/delete_ntp_peers.j2
+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
diff --git a/napalm_iosxr.egg-info/dependency_links.txt b/napalm_iosxr.egg-info/dependency_links.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/napalm_iosxr.egg-info/dependency_links.txt
@@ -0,0 +1 @@
+
diff --git a/napalm_iosxr.egg-info/requires.txt b/napalm_iosxr.egg-info/requires.txt
new file mode 100644
index 0000000..24f01f2
--- /dev/null
+++ b/napalm_iosxr.egg-info/requires.txt
@@ -0,0 +1,3 @@
+napalm-base
+pyIOSXR
+netaddr
diff --git a/napalm_iosxr.egg-info/top_level.txt b/napalm_iosxr.egg-info/top_level.txt
new file mode 100644
index 0000000..c93dcbf
--- /dev/null
+++ b/napalm_iosxr.egg-info/top_level.txt
@@ -0,0 +1 @@
+napalm_iosxr
diff --git a/napalm_iosxr/__init__.py b/napalm_iosxr/__init__.py
new file mode 100644
index 0000000..f01b18e
--- /dev/null
+++ b/napalm_iosxr/__init__.py
@@ -0,0 +1,16 @@
+# Copyright 2016 Dravetech 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.
+
+"""napalm_iosxr package."""
+from iosxr import IOSXRDriver
diff --git a/napalm_iosxr/iosxr.py b/napalm_iosxr/iosxr.py
new file mode 100644
index 0000000..9acdee4
--- /dev/null
+++ b/napalm_iosxr/iosxr.py
@@ -0,0 +1,1622 @@
+# 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.
+
+# python std lib
+import re
+import copy
+from collections import defaultdict
+
+# third party libs
+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
+
+# napalm_base
+from napalm_base.base import NetworkDriver
+from napalm_base.utils import string_parsers
+from napalm_base.exceptions import ConnectionException, MergeConfigException, ReplaceConfigException,\
+                                   CommandErrorException, CommandTimeoutException
+
+
+class IOSXRDriver(NetworkDriver):
+    def __init__(self, hostname, username, password, timeout=60, optional_args=None):
+        self.hostname = hostname
+        self.username = username
+        self.password = password
+        self.timeout = timeout
+        self.pending_changes = False
+        self.replace = False
+        if optional_args is None:
+            optional_args = {}
+        self.port = optional_args.get('port', 22)
+        self.lock_on_connect = optional_args.get('config_lock', True)
+        self.device = IOSXR(hostname, username, password, timeout=timeout, port=self.port, lock=self.lock_on_connect)
+
+    def open(self):
+        try:
+            self.device.open()
+        except EOFError as ee:
+            raise ConnectionException(ee.message)
+
+    def close(self):
+        self.device.close()
+
+    def load_replace_candidate(self, filename=None, config=None):
+        self.pending_changes = True
+        self.replace = True
+        if not self.lock_on_connect:
+            self.device.lock()
+
+        try:
+            self.device.load_candidate_config(filename=filename, config=config)
+        except InvalidInputError as e:
+            self.pending_changes = False
+            self.replace = False
+            raise ReplaceConfigException(e.message)
+
+    def load_merge_candidate(self, filename=None, config=None):
+        self.pending_changes = True
+        self.replace = False
+        if not self.lock_on_connect:
+            self.device.lock()
+
+        try:
+            self.device.load_candidate_config(filename=filename, config=config)
+        except InvalidInputError as e:
+            self.pending_changes = False
+            self.replace = False
+            raise MergeConfigException(e.message)
+
+    def compare_config(self):
+        if not self.pending_changes:
+            return ''
+        elif self.replace:
+            return self.device.compare_replace_config().strip()
+        else:
+            return self.device.compare_config().strip()
+
+    def commit_config(self):
+        if self.replace:
+            self.device.commit_replace_config()
+        else:
+            self.device.commit_config()
+        self.pending_changes = False
+        if not self.lock_on_connect:
+            self.device.unlock()
+
+    def discard_config(self):
+        self.device.discard_config()
+        self.pending_changes = False
+        if not self.lock_on_connect:
+            self.device.unlock()
+
+    def rollback(self):
+        self.device.rollback()
+
+
+    # perhaps both should be moved in napalm_base.helpers at some point
+    @staticmethod
+    def _find_txt(xml_tree, path, default = ''):
+        try:
+            return xml_tree.find(path).text.strip()
+        except Exception:
+            return default
+
+
+    @staticmethod
+    def _convert(to, who, default = u''):
+        if who is None:
+            return default
+        try:
+            return to(who)
+        except:
+            return default
+
+
+    def get_facts(self):
+
+        sh_ver = self.device.show_version()
+
+        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])
+
+        interface_list = list()
+
+        for x in self.device.show_interface_description().splitlines()[3:-1]:
+            if '.' not in x:
+                interface_list.append(x.split()[0])
+
+        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,
+        }
+
+        return result
+
+    def get_interfaces(self):
+
+        # 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,
+                'is_up': is_up,
+                'mac_address': unicode(mac_address),
+                'description': unicode(description),
+                'speed': speed,
+                'last_flapped': -1.0,
+            }
+
+        return result
+
+    def get_interfaces_counters(self):
+        rpc_command = "<Get><Operational><Interfaces><InterfaceTable></InterfaceTable></Interfaces></Operational></Get>"
+        result_tree = ET.fromstring(self.device.make_rpc_call(rpc_command))
+
+        interface_counters = dict()
+
+        for interface in result_tree.iter('Interface'):
+
+            interface_name = interface.find('InterfaceHandle').text
+
+            interface_stats = dict()
+
+            if interface.find('InterfaceStatistics') is None:
+                continue
+            else:
+                interface_stats = dict()
+                interface_stats['tx_multicast_packets'] = int(interface.find(
+                    'InterfaceStatistics/FullInterfaceStats/MulticastPacketsSent').text)
+                interface_stats['tx_discards'] = int(interface.find(
+                    'InterfaceStatistics/FullInterfaceStats/OutputDrops').text)
+                interface_stats['tx_octets'] = int(interface.find(
+                    'InterfaceStatistics/FullInterfaceStats/BytesSent').text)
+                interface_stats['tx_errors'] = int(interface.find(
+                    'InterfaceStatistics/FullInterfaceStats/OutputErrors').text)
+                interface_stats['rx_octets'] = int(interface.find(
+                    'InterfaceStatistics/FullInterfaceStats/BytesReceived').text)
+                interface_stats['tx_unicast_packets'] = int(interface.find(
+                    'InterfaceStatistics/FullInterfaceStats/PacketsSent').text)
+                interface_stats['rx_errors'] = int(interface.find(
+                    'InterfaceStatistics/FullInterfaceStats/InputErrors').text)
+                interface_stats['tx_broadcast_packets'] = int(interface.find(
+                    'InterfaceStatistics/FullInterfaceStats/BroadcastPacketsSent').text)
+                interface_stats['rx_multicast_packets'] = int(interface.find(
+                    'InterfaceStatistics/FullInterfaceStats/MulticastPacketsReceived').text)
+                interface_stats['rx_broadcast_packets'] = int(interface.find(
+                    'InterfaceStatistics/FullInterfaceStats/BroadcastPacketsReceived').text)
+                interface_stats['rx_discards'] = int(interface.find(
+                    'InterfaceStatistics/FullInterfaceStats/InputDrops').text)
+                interface_stats['rx_unicast_packets'] = int(interface.find(
+                    'InterfaceStatistics/FullInterfaceStats/PacketsReceived').text)
+
+            interface_counters[interface_name] = interface_stats
+
+        return interface_counters
+
+    def get_bgp_neighbors(self):
+        def generate_vrf_query(vrf_name):
+            """
+            Helper to provide XML-query for the VRF-type we're interested in.
+            """
+            if vrf_name == "global":
+                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>"""
+
+            else:
+                rpc_command = """<Get>
+                        <Operational>
+                            <BGP>
+                                <InstanceTable>
+                                    <Instance>
+                                        <Naming>
+                                            <InstanceName>
+                                                default
+                                            </InstanceName>
+                                        </Naming>
+                                        <InstanceActive>
+                                            <VRFTable>
+                                                <VRF>
+                                                    <Naming>
+                                                        %s
+                                                    </Naming>
+                                                    <GlobalProcessInfo>
+                                                    </GlobalProcessInfo>
+                                                    <NeighborTable>
+                                                    </NeighborTable>
+                                                </VRF>
+                                            </VRFTable>
+                                         </InstanceActive>
+                                    </Instance>
+                                </InstanceTable>
+                            </BGP>
+                        </Operational>
+                    </Get>""" % vrf_name
+            return rpc_command
+
+        """
+        Initial run to figure out what VRF's are available
+        Decided to get this one from Configured-section because bulk-getting all instance-data to do the same could get ridiculously heavy
+        Assuming we're always interested in the DefaultVRF
+        """
+
+        active_vrfs = ["global"]
+
+        rpc_command = """<Get>
+                            <Operational>
+                                <BGP>
+                                    <ConfigInstanceTable>
+                                        <ConfigInstance>
+                                            <Naming>
+                                                <InstanceName>
+                                                    default
+                                                </InstanceName>
+                                            </Naming>
+                                            <ConfigInstanceVRFTable>
+                                            </ConfigInstanceVRFTable>
+                                        </ConfigInstance>
+                                    </ConfigInstanceTable>
+                                </BGP>
+                            </Operational>
+                        </Get>"""
+
+        result_tree = ET.fromstring(self.device.make_rpc_call(rpc_command))
+
+        for node in result_tree.iter('ConfigVRF'):
+            active_vrfs.append(str(node.find('Naming/VRFName').text))
+
+        result = dict()
+
+        for vrf in active_vrfs:
+            rpc_command = generate_vrf_query(vrf)
+            result_tree = ET.fromstring(self.device.make_rpc_call(rpc_command))
+
+            this_vrf = dict()
+            this_vrf['peers'] = dict()
+
+            if vrf == "global":
+                this_vrf['router_id'] = unicode(result_tree.find(
+                    'Get/Operational/BGP/InstanceTable/Instance/InstanceActive/DefaultVRF/GlobalProcessInfo/VRF/RouterID').text)
+            else:
+                this_vrf['router_id'] = unicode(result_tree.find(
+                    'Get/Operational/BGP/InstanceTable/Instance/InstanceActive/VRFTable/VRF/GlobalProcessInfo/VRF/RouterID').text)
+
+            neighbors = dict()
+
+            for neighbor in result_tree.iter('Neighbor'):
+                this_neighbor = dict()
+                this_neighbor['local_as'] = int(neighbor.find('LocalAS').text)
+                this_neighbor['remote_as'] = int(neighbor.find('RemoteAS').text)
+                this_neighbor['remote_id'] = unicode(neighbor.find('RouterID').text)
+
+                if neighbor.find('ConnectionAdminStatus').text is "1":
+                    this_neighbor['is_enabled'] = True
+                try:
+                    this_neighbor['description'] = unicode(neighbor.find('Description').text)
+                except AttributeError:
+                    this_neighbor['description'] = u''
+
+                this_neighbor['is_enabled'] = str(neighbor.find('ConnectionAdminStatus').text) is "1"
+
+                if str(neighbor.find('ConnectionAdminStatus').text) is "1":
+                    this_neighbor['is_enabled'] = True
+                else:
+                    this_neighbor['is_enabled'] = False
+
+                if str(neighbor.find('ConnectionState').text) == "BGP_ST_ESTAB":
+                    this_neighbor['is_up'] = True
+                    this_neighbor['uptime'] = int(neighbor.find('ConnectionEstablishedTime').text)
+                else:
+                    this_neighbor['is_up'] = False
+                    this_neighbor['uptime'] = -1
+
+                this_neighbor['address_family'] = dict()
+
+                if neighbor.find('ConnectionRemoteAddress/AFI').text == "IPv4":
+                    this_afi = "ipv4"
+                elif neighbor.find('ConnectionRemoteAddress/AFI').text == "IPv6":
+                    this_afi = "ipv6"
+                else:
+                    this_afi = neighbor.find('ConnectionRemoteAddress/AFI').text
+
+                this_neighbor['address_family'][this_afi] = dict()
+
+                try:
+                    this_neighbor['address_family'][this_afi][
+                        "received_prefixes"] = int(neighbor.find('AFData/Entry/PrefixesAccepted').text) + int(
+                            neighbor.find('AFData/Entry/PrefixesDenied').text)
+                    this_neighbor['address_family'][this_afi][
+                        "accepted_prefixes"] = int(neighbor.find('AFData/Entry/PrefixesAccepted').text)
+                    this_neighbor['address_family'][this_afi][
+                        "sent_prefixes"] = int(neighbor.find('AFData/Entry/PrefixesAdvertised').text)
+                except AttributeError:
+                    this_neighbor['address_family'][this_afi]["received_prefixes"] = -1
+                    this_neighbor['address_family'][this_afi]["accepted_prefixes"] = -1
+                    this_neighbor['address_family'][this_afi]["sent_prefixes"] = -1
+
+                try:
+                    neighbor_ip = unicode(neighbor.find('Naming/NeighborAddress/IPV4Address').text)
+                except AttributeError:
+                    neighbor_ip = unicode(neighbor.find('Naming/NeighborAddress/IPV6Address').text)
+
+                neighbors[neighbor_ip] = this_neighbor
+
+            this_vrf['peers'] = neighbors
+            result[vrf] = this_vrf
+
+        return result
+
+    def get_environment(self):
+        def get_module_xml_query(module,selection):
+            return """<Get>
+                        <AdminOperational>
+                            <EnvironmentalMonitoring>
+                                <RackTable>
+                                    <Rack>
+                                        <Naming>
+                                            <rack>0</rack>
+                                        </Naming>
+                                        <SlotTable>
+                                            <Slot>
+                                                <Naming>
+                                                    <slot>%s</slot>
+                                                </Naming>
+                                                %s
+                                            </Slot>
+                                        </SlotTable>
+                                    </Rack>
+                                </RackTable>
+                            </EnvironmentalMonitoring>
+                        </AdminOperational>
+                    </Get>""" % (module,selection)
+
+        environment_status = dict()
+        environment_status['fans'] = dict()
+        environment_status['temperature'] = dict()
+        environment_status['power'] = dict()
+        environment_status['cpu'] = dict()
+        environment_status['memory'] = int()
+
+        # finding slots with equipment we're interested in
+        rpc_command = """<Get>
+            <AdminOperational>
+                <PlatformInventory>
+                    <RackTable>
+                        <Rack>
+                            <Naming>
+                                <Name>0</Name>
+                            </Naming>
+                            <SlotTable>
+                            </SlotTable>
+                        </Rack>
+                    </RackTable>
+                </PlatformInventory>
+            </AdminOperational>
+        </Get>"""
+
+        result_tree = ET.fromstring(self.device.make_rpc_call(rpc_command))
+
+        active_modules = defaultdict(list)
+
+        for slot in result_tree.iter("Slot"):
+            for card in slot.iter("CardTable"):
+                #find enabled slots, figoure out type and save for later
+                if card.find('Card/Attributes/FRUInfo/ModuleAdministrativeState').text == "ADMIN_UP":
+
+                    slot_name = slot.find('Naming/Name').text
+                    module_type = re.sub("\d+", "", slot_name)
+                    if len(module_type) > 0:
+                        active_modules[module_type].append(slot_name)
+                    else:
+                        active_modules["LC"].append(slot_name)
+
+        #
+        # PSU's
+        #
+
+        for psu in active_modules['PM']:
+            if psu in ["PM6", "PM7"]:    # Cisco bug, chassis difference V01<->V02
+                continue
+
+            rpc_command = get_module_xml_query(psu,'')
+            result_tree = ET.fromstring(self.device.make_rpc_call(rpc_command))
+
+            psu_status = dict()
+            psu_status['status'] = False
+            psu_status['capacity'] = float()
+            psu_status['output'] = float()
+
+            for sensor in result_tree.iter('SensorName'):
+                if sensor.find('Naming/Name').text == "host__VOLT":
+                    this_psu_voltage = float(sensor.find('ValueBrief').text)
+                elif sensor.find('Naming/Name').text == "host__CURR":
+                    this_psu_current = float(sensor.find('ValueBrief').text)
+                elif sensor.find('Naming/Name').text == "host__PM":
+                    this_psu_capacity = float(sensor.find('ValueBrief').text)
+
+            if this_psu_capacity > 0:
+                psu_status['capacity'] = this_psu_capacity
+                psu_status['status'] = True
+
+            if this_psu_current and this_psu_voltage:
+                psu_status['output'] = (this_psu_voltage * this_psu_current) / 1000000.0
+
+            environment_status['power'][psu] = psu_status
+
+        #
+        # Memory
+        #
+
+        rpc_command = "<Get><AdminOperational><MemorySummary></MemorySummary></AdminOperational></Get>"
+        result_tree = ET.fromstring(self.device.make_rpc_call(rpc_command))
+
+        for node in result_tree.iter('Node'):
+            print
+            if node.find('Naming/NodeName/Slot').text == active_modules['RSP'][0]:    # first enabled RSP
+                available_ram = int(node.find('Summary/SystemRAMMemory').text)
+                free_ram = int(node.find('Summary/FreeApplicationMemory').text)
+                break    # we're only looking at one of the RSP's
+
+        if available_ram and free_ram:
+            used_ram = available_ram - free_ram
+            memory = dict()
+            memory['available_ram'] = available_ram
+            memory['used_ram'] = used_ram
+            environment_status['memory'] = memory
+
+        #
+        # Fans
+        #
+
+        for fan in active_modules['FT']:
+            rpc_command = get_module_xml_query(fan,'')
+            result_tree = ET.fromstring(self.device.make_rpc_call(rpc_command))
+            for module in result_tree.iter('Module'):
+                for sensortype in module.iter('SensorType'):
+                    for sensorname in sensortype.iter('SensorNameTable'):
+                        if sensorname.find('SensorName/Naming/Name').text == "host__FanSpeed_0":
+                            environment_status['fans'][fan] = {'status': int(sensorname.find(
+                                'SensorName/ValueDetailed/Status').text) is 1}
+
+        #
+        # CPU
+        #
+        cpu = dict()
+
+        rpc_command = "<Get><Operational><SystemMonitoring></SystemMonitoring></Operational></Get>"
+        result_tree = ET.fromstring(self.device.make_rpc_call(rpc_command))
+
+        for module in result_tree.iter('CPUUtilization'):
+            this_cpu = dict()
+            this_cpu["%usage"] = float(module.find('TotalCPUFiveMinute').text)
+
+            rack = module.find('Naming/NodeName/Rack').text
+            slot = module.find('Naming/NodeName/Slot').text
+            instance = module.find('Naming/NodeName/Instance').text
+            position =  "%s/%s/%s" % (rack,slot,instance)
+
+            cpu[position] = this_cpu
+
+        environment_status["cpu"] = cpu
+
+        #
+        # Temperature
+        #
+
+        temperature = dict()
+
+        slot_list = set()
+        for category, slot in active_modules.iteritems():
+            slot_list |= set(slot)
+
+        for slot in slot_list:
+            rpc_command = get_module_xml_query(slot,'')
+            result_tree = ET.fromstring(self.device.make_rpc_call(rpc_command))
+
+            for sensor in result_tree.findall(".//SensorName"):
+                if not sensor.find('Naming/Name').text == "host__Inlet0":
+                    continue
+                this_reading = dict()
+                this_reading['temperature'] = float(sensor.find('ValueBrief').text)
+
+                threshold_value = [float(x.text) for x in sensor.findall("ThresholdTable/Threshold/ValueBrief")]
+
+                this_reading['is_alert'] = threshold_value[2] <= this_reading['temperature'] <= threshold_value[3]
+                this_reading['is_critical'] = threshold_value[4] <= this_reading['temperature'] <= threshold_value[5]
+
+                this_reading['temperature'] = this_reading['temperature']/10
+
+                environment_status["temperature"][slot] = this_reading
+
+        return environment_status
+
+    def get_lldp_neighbors(self):
+
+        # init result dict
+        lldp = {}
+        sh_lldp = self.device.show_lldp_neighbors().splitlines()[5:-3]
+
+        for n in sh_lldp:
+            local_interface = n.split()[1]
+            if local_interface not in lldp.keys():
+                lldp[local_interface] = list()
+
+            lldp[local_interface].append({'hostname': unicode(n.split()[0]), 'port': unicode(n.split()[4]), })
+
+        return lldp
+
+    def get_lldp_neighbors_detail(self, interface = ''):
+
+        lldp_neighbors = dict()
+
+        rpc_command = '<Get><Operational><LLDP></LLDP></Operational></Get>'
+
+        result_tree = ET.fromstring(self.device.make_rpc_call(rpc_command))
+
+        for neighbor in result_tree.findall('.//Neighbors/DetailTable/Detail/Entry'):
+            if neighbor is None:
+                continue
+            try:
+                interface_name      = unicode(neighbor.find('ReceivingInterfaceName').text)
+                parent_interface    = unicode(neighbor.find('ReceivingParentInterfaceName').text)
+                device_id           = unicode(neighbor.find('DeviceID').text)
+                chassis_id          = unicode(neighbor.find('ChassisID').text)
+                port_id             = unicode(neighbor.find('PortIDDetail').text)
+                port_descr          = unicode(neighbor.find('Detail/PortDescription').text)
+                system_name         = unicode(neighbor.find('Detail/SystemName').text)
+                system_descr        = unicode(neighbor.find('Detail/SystemDescription').text)
+                system_capabilities = unicode(neighbor.find('Detail/SystemCapabilities').text)
+                enabled_capabilities= unicode(neighbor.find('Detail/EnabledCapabilities').text)
+                # few other optional...
+                # time_remaining = neighbor.find('Detail/TimeRemaining').text
+                # media_attachement_unit_type = neighbor.find('Detail/MediaAttachmentUnitType').text
+                # port_vlan_id = neighbor.find('Detail/PortVlanID').text
+
+                if interface_name not in lldp_neighbors.keys():
+                    lldp_neighbors[interface_name] = list()
+                lldp_neighbors[interface_name].append({
+                    'parent_interface'              : parent_interface,
+                    'remote_chassis_id'             : chassis_id,
+                    'remote_port'                   : port_id,
+                    'remote_port_description'       : port_descr,
+                    'remote_system_name'            : system_name,
+                    'remote_system_description'     : system_descr,
+                    'remote_system_capab'           : system_capabilities,
+                    'remote_system_enable_capab'    :  enabled_capabilities
+                })
+            except Exception:
+                continue # jump to next neighbor
+
+        return lldp_neighbors
+
+    def cli(self, commands = None):
+
+        cli_output = dict()
+
+        if type(commands) is not list:
+            raise TypeError('Please enter a valid list of commands!')
+
+        for command in commands:
+            try:
+                cli_output[unicode(command)] = unicode(__execute_show__(self.device.device, command, self.timeout))
+            except TimeoutError:
+                cli_output[unicode(command)] = 'Execution of command "{command}" took too long! Please adjust your params!'.format(
+                    command = command
+                )
+                raise CommandTimeoutException(str(cli_output))
+            except Exception as e:
+                cli_output[unicode(command)] = 'Unable to execute command "{cmd}": {err}'.format(
+                    cmd = command,
+                    err = e
+                )
+                raise CommandErrorException(str(cli_output))
+
+        return cli_output
+
+
+    def get_bgp_config(self, group = '', neighbor = ''):
+
+        bgp_config = {}
+
+        # a helper
+        def build_prefix_limit(af_table, limit, prefix_percent, prefix_timeout):
+            prefix_limit = dict()
+            inet  = False
+            inet6 = False
+            preifx_type = 'inet'
+            if 'IPV4' in af_table:
+                inet = True
+            if 'IPv6' in af_table:
+                inet6 = True
+                preifx_type = 'inet6'
+            if inet or inet6:
+                prefix_limit = {
+                    preifx_type: {
+                        af_table[4:].lower(): {
+                            'limit': limit,
+                            'teardown': {
+                                'threshold': prefix_percent,
+                                'timeout'  : prefix_timeout
+                            }
+                        }
+                    }
+                }
+            return prefix_limit
+
+        # here begins actual method...
+
+        rpc_command = '''
+                <Get>
+                    <Configuration>
+                        <BGP>
+                            <Instance>
+                                <Naming>
+                                    <InstanceName>
+                                        default
+                                    </InstanceName>
+                                </Naming>
+                            </Instance>
+                        </BGP>
+                    </Configuration>
+                </Get>
+        '''
+        result_tree = ET.fromstring(self.device.make_rpc_call(rpc_command))
+
+        group    = group.lower()
+        neighbor = neighbor.lower()
+
+        if not group:
+            neighbor = ''
+
+        bgp_group_neighbors = {}
+        for bgp_neighbor in result_tree.iter('Neighbor'):
+            group_name     = self._find_txt(bgp_neighbor, 'NeighborGroupAddMember')
+            peer           = self._find_txt(bgp_neighbor, 'Naming/NeighborAddress/IPV4Address') or self._find_txt(bgp_neighbor, 'Naming/NeighborAddress/IPV6Address')
+            if neighbor and peer != neighbor:
+                continue
+            description    = unicode(self._find_txt(bgp_neighbor, 'Description'))
+            peer_as        = int(self._find_txt(bgp_neighbor, 'RemoteAS/AS_YY', 0))
+            local_as       = int(self._find_txt(bgp_neighbor, 'LocalAS/AS_YY', 0))
+            af_table       = self._find_txt(bgp_neighbor, 'NeighborAFTable/NeighborAF/Naming/AFName')
+            prefix_limit   = int(self._find_txt(bgp_neighbor, 'NeighborAFTable/NeighborAF/MaximumPrefixes/PrefixLimit', 0))
+            prefix_percent = int(self._find_txt(bgp_neighbor, 'NeighborAFTable/NeighborAF/MaximumPrefixes/WarningPercentage', 0))
+            prefix_timeout = int(self._find_txt(bgp_neighbor, 'NeighborAFTable/NeighborAF/MaximumPrefixes/RestartTime', 0))
+            import_policy  = unicode(self._find_txt(bgp_neighbor, 'NeighborAFTable/NeighborAF/RoutePolicyIn'))
+            export_policy  = unicode(self._find_txt(bgp_neighbor, 'NeighborAFTable/NeighborAF/RoutePolicyOut'))
+            local_address  = unicode(self._find_txt(bgp_neighbor, 'LocalAddress/LocalIPAddress/IPV4Address') or self._find_txt(bgp_neighbor, 'LocalAddress/LocalIPAddress/IPV6Address'))
+            password       = unicode(self._find_txt(bgp_neighbor, 'Password/Password/Password'))
+            nhs            = False
+            route_reflector= False
+            if group_name not in bgp_group_neighbors.keys():
+                bgp_group_neighbors[group_name] = dict()
+            bgp_group_neighbors[group_name][peer] = {
+                'description'           : description,
+                'remote_as'               : peer_as,
+                'prefix_limit'          : build_prefix_limit(af_table, prefix_limit, prefix_percent, prefix_timeout),
+                'export_policy'         : export_policy,
+                'import_policy'         : import_policy,
+                'local_address'         : local_address,
+                'local_as'              : local_as,
+                'authentication_key'    : password,
+                'nhs'                   : nhs,
+                'route_reflector_client': route_reflector
+            }
+            if neighbor and peer == neighbor:
+                break
+
+        for bgp_group in result_tree.iter('NeighborGroup'):
+            group_name    = self._find_txt(bgp_group, 'Naming/NeighborGroupName')
+            if group and group != group_name:
+                continue
+            bgp_type = 'external' # by default external
+            # must check
+            description   = unicode(self._find_txt(bgp_group, 'Description'))
+            import_policy = unicode(self._find_txt(bgp_group, 'NeighborGroupAFTable/NeighborGroupAF/RoutePolicyIn'))
+            export_policy = unicode(self._find_txt(bgp_group, 'NeighborGroupAFTable/NeighborGroupAF/RoutePolicyOut'))
+            multipath     = eval(self._find_txt(bgp_group, 'NeighborGroupAFTable/NeighborGroupAF/Multipath', 'false').title())
+
+            peer_as       = int(self._find_txt(bgp_group, 'RemoteAS/AS_YY', 0))
+            local_as      = int(self._find_txt(bgp_group, 'LocalAS/AS_YY', 0))
+            multihop_ttl  = int(self._find_txt(bgp_group, 'EBGPMultihop/MaxHopCount', 0))
+            local_address = unicode(self._find_txt(bgp_group, 'LocalAddress/LocalIPAddress/IPV4Address') or self._find_txt(bgp_group, 'LocalAddress/LocalIPAddress/IPV6Address'))
+            af_table      = self._find_txt(bgp_group, 'NeighborAFTable/NeighborAF/Naming/AFName')
+            prefix_limit  = int(self._find_txt(bgp_group, 'NeighborGroupAFTable/NeighborGroupAF/MaximumPrefixes/PrefixLimit', 0))
+            prefix_percent= int(self._find_txt(bgp_group, 'NeighborGroupAFTable/NeighborGroupAF/MaximumPrefixes/WarningPercentage', 0))
+            prefix_timeout= int(self._find_txt(bgp_group, 'NeighborGroupAFTable/NeighborGroupAF/MaximumPrefixes/RestartTime', 0))
+            remove_private= True # is it specified in the XML?
+            bgp_config[group_name] = {
+                'apply_groups'      : [], # on IOS-XR will always be empty list!
+                'description'       : description,
+                'local_as'          : local_as,
+                'type'              : unicode(bgp_type),
+                'import_policy'     : import_policy,
+                'export_policy'     : export_policy,
+                'local_address'     : local_address,
+                'multipath'         : multipath,
+                'multihop_ttl'      : multihop_ttl,
+                'remote_as'         : peer_as,
+                'remove_private_as' : remove_private,
+                'prefix_limit'      : build_prefix_limit(af_table, prefix_limit, prefix_percent, prefix_timeout),
+                'neighbors'         : bgp_group_neighbors.get(group_name, {})
+            }
+            if group and group == group_name:
+                break
+
+        return bgp_config
+
+    def get_bgp_neighbors_detail(self, neighbor_address = ''):
+
+        bgp_neighbors = dict()
+
+        rpc_command = '''
+                <Get>
+                    <Operational>
+                        <BGP>
+                            <InstanceTable>
+                                <Instance>
+                                    <Naming>
+                                        <InstanceName>
+                                            default
+                                        </InstanceName>
+                                    </Naming>
+                                    <InstanceActive>
+                                        <DefaultVRF>
+                                            <GlobalProcessInfo>
+                                            </GlobalProcessInfo>
+                                            <NeighborTable>
+                                            </NeighborTable>
+                                        </DefaultVRF>
+                                    </InstanceActive>
... 933 lines suppressed ...

-- 
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