[Python-modules-commits] [napalm-ios] 01/03: Import napalm-ios_0.3.1.orig.tar.gz

Vincent Bernat bernat at moszumanska.debian.org
Thu Nov 3 19:59:26 UTC 2016


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

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

commit 08f820e66bae1af3f59482f71b18974ccb2dbf58
Author: Vincent Bernat <bernat at debian.org>
Date:   Thu Nov 3 20:56:59 2016 +0100

    Import napalm-ios_0.3.1.orig.tar.gz
---
 PKG-INFO                         |   2 +-
 napalm_ios.egg-info/PKG-INFO     |   2 +-
 napalm_ios.egg-info/SOURCES.txt  |   1 +
 napalm_ios.egg-info/requires.txt |   4 +-
 napalm_ios/__init__.py           |  10 ++-
 napalm_ios/ios.py                | 187 ++++++++++++++++++++++++++++++---------
 requirements.txt                 |   4 +-
 setup.cfg                        |   7 ++
 setup.py                         |   3 +-
 9 files changed, 170 insertions(+), 50 deletions(-)

diff --git a/PKG-INFO b/PKG-INFO
index 50bbb69..1100a50 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: napalm-ios
-Version: 0.1.7
+Version: 0.3.1
 Summary: Network Automation and Programmability Abstraction Layer with Multivendor support
 Home-page: https://github.com/napalm-automation/napalm-ios
 Author: David Barroso
diff --git a/napalm_ios.egg-info/PKG-INFO b/napalm_ios.egg-info/PKG-INFO
index 50bbb69..1100a50 100644
--- a/napalm_ios.egg-info/PKG-INFO
+++ b/napalm_ios.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: napalm-ios
-Version: 0.1.7
+Version: 0.3.1
 Summary: Network Automation and Programmability Abstraction Layer with Multivendor support
 Home-page: https://github.com/napalm-automation/napalm-ios
 Author: David Barroso
diff --git a/napalm_ios.egg-info/SOURCES.txt b/napalm_ios.egg-info/SOURCES.txt
index 76839b0..e1fe75a 100644
--- a/napalm_ios.egg-info/SOURCES.txt
+++ b/napalm_ios.egg-info/SOURCES.txt
@@ -1,5 +1,6 @@
 MANIFEST.in
 requirements.txt
+setup.cfg
 setup.py
 napalm_ios/__init__.py
 napalm_ios/ios.py
diff --git a/napalm_ios.egg-info/requires.txt b/napalm_ios.egg-info/requires.txt
index ec5f5f1..93aafe3 100644
--- a/napalm_ios.egg-info/requires.txt
+++ b/napalm_ios.egg-info/requires.txt
@@ -1,2 +1,2 @@
-napalm-base
-netmiko>=0.5.0
+napalm-base>=0.18.0
+netmiko>=1.0.0
diff --git a/napalm_ios/__init__.py b/napalm_ios/__init__.py
index b268bc6..a322d7f 100644
--- a/napalm_ios/__init__.py
+++ b/napalm_ios/__init__.py
@@ -13,4 +13,12 @@
 # the License.
 
 """napalm_ios package."""
-from ios import IOSDriver
+import pkg_resources
+from napalm_ios.ios import IOSDriver
+
+try:
+    __version__ = pkg_resources.get_distribution('napalm-ios').version
+except pkg_resources.DistributionNotFound:
+    __version__ = "Not installed"
+
+__all__ = ['IOSDriver']
diff --git a/napalm_ios/ios.py b/napalm_ios/ios.py
index c7bd093..620814f 100644
--- a/napalm_ios/ios.py
+++ b/napalm_ios/ios.py
@@ -1,5 +1,4 @@
 """NAPALM Cisco IOS Handler."""
-
 # Copyright 2015 Spotify AB. All rights reserved.
 #
 # The contents of this file are licensed under the Apache License, Version 2.0
@@ -17,9 +16,9 @@
 from __future__ import print_function
 
 import re
-from datetime import datetime
 
 from netmiko import ConnectHandler, FileTransfer
+from netmiko import __version__ as netmiko_version
 from napalm_base.base import NetworkDriver
 from napalm_base.exceptions import ReplaceConfigException, MergeConfigException
 
@@ -41,15 +40,49 @@ class IOSDriver(NetworkDriver):
         self.username = username
         self.password = password
         self.timeout = timeout
+
+        # Retrieve file names
         self.candidate_cfg = optional_args.get('candidate_cfg', 'candidate_config.txt')
         self.merge_cfg = optional_args.get('merge_cfg', 'merge_config.txt')
         self.rollback_cfg = optional_args.get('rollback_cfg', 'rollback_config.txt')
 
         # None will cause autodetection of dest_file_system
         self.dest_file_system = optional_args.get('dest_file_system', None)
-        self.global_delay_factor = optional_args.get('global_delay_factor', .5)
-        self.port = optional_args.get('port', 22)
         self.auto_rollback_on_error = optional_args.get('auto_rollback_on_error', True)
+
+        # Netmiko possible arguments
+        netmiko_argument_map = {
+            'port': None,
+            'secret': '',
+            'verbose': False,
+            'global_delay_factor': 1,
+            'use_keys': False,
+            'key_file': None,
+            'ssh_strict': False,
+            'system_host_keys': False,
+            'alt_host_keys': False,
+            'alt_key_file': '',
+            'ssh_config_file': None,
+        }
+
+        fields = netmiko_version.split('.')
+        fields = [int(x) for x in fields]
+        maj_ver, min_ver, bug_fix = fields
+        if maj_ver >= 2:
+            netmiko_argument_map['allow_agent'] = False
+        elif maj_ver == 1 and min_ver >= 1:
+            netmiko_argument_map['allow_agent'] = False
+
+        # Build dict of any optional Netmiko args
+        self.netmiko_optional_args = {}
+        for k, v in netmiko_argument_map.items():
+            try:
+                self.netmiko_optional_args[k] = optional_args[k]
+            except KeyError:
+                pass
+        self.global_delay_factor = optional_args.get('global_delay_factor', 1)
+        self.port = optional_args.get('port', 22)
+
         self.device = None
         self.config_replace = False
         self.interface_map = {}
@@ -57,12 +90,10 @@ class IOSDriver(NetworkDriver):
     def open(self):
         """Open a connection to the device."""
         self.device = ConnectHandler(device_type='cisco_ios',
-                                     ip=self.hostname,
-                                     port=self.port,
+                                     host=self.hostname,
                                      username=self.username,
                                      password=self.password,
-                                     global_delay_factor=self.global_delay_factor,
-                                     verbose=False)
+                                     **self.netmiko_optional_args)
         if not self.dest_file_system:
             try:
                 self.dest_file_system = self.device._autodetect_fs()
@@ -113,7 +144,8 @@ class IOSDriver(NetworkDriver):
     @staticmethod
     def normalize_compare_config(diff):
         """Filter out strings that should not show up in the diff."""
-        ignore_strings = ['Contextual Config Diffs', 'No changes were found', 'file prompt quiet', 'ntp clock-period']
+        ignore_strings = ['Contextual Config Diffs', 'No changes were found',
+                          'file prompt quiet', 'ntp clock-period']
 
         new_list = []
         for line in diff.splitlines():
@@ -191,7 +223,6 @@ class IOSDriver(NetworkDriver):
 
         If merge operation, perform copy <file> running-config.
         """
-        debug = False
         # Always generate a rollback config on commit
         self._gen_rollback_cfg()
 
@@ -258,7 +289,6 @@ class IOSDriver(NetworkDriver):
         """
         # Will automaticall enable SCP on remote device
         enable_scp = True
-        debug = False
 
         with FileTransfer(self.device,
                           source_file=source_file,
@@ -423,10 +453,12 @@ class IOSDriver(NetworkDriver):
             system_capabilities = re.findall(r"System Capabilities: (.+)", output)
             enabled_capabilities = re.findall(r"Enabled Capabilities: (.+)", output)
             remote_address = re.findall(r"Management Addresses:\n    IP: (.+)", output)
-
+            if not remote_address:
+                remote_address = re.findall(r"Management Addresses:\n    Other: (.+)", output)
             number_entries = len(port_id)
             lldp_fields = [port_id, port_description, chassis_id, system_name, system_description,
                            system_capabilities, enabled_capabilities, remote_address]
+
             # Check length of each list
             for test_list in lldp_fields:
                 if len(test_list) > number_entries:
@@ -438,8 +470,9 @@ class IOSDriver(NetworkDriver):
             # Standardize the fields
             port_id, port_description, chassis_id, system_name, system_description, \
                 system_capabilities, enabled_capabilities, remote_address = lldp_fields
-            standardized_fields = zip(port_id, port_description, chassis_id, system_name, system_description,
-                                      system_capabilities, enabled_capabilities, remote_address)
+            standardized_fields = zip(port_id, port_description, chassis_id, system_name,
+                                      system_description, system_capabilities,
+                                      enabled_capabilities, remote_address)
 
             lldp.setdefault(local_port, [])
             for entry in standardized_fields:
@@ -511,7 +544,11 @@ class IOSDriver(NetworkDriver):
                 serial_number = serial_number.strip()
 
             if re.search(r"Cisco IOS Software", line):
-                _, os_version = line.split("Cisco IOS Software, ")
+                try:
+                    _, os_version = line.split("Cisco IOS Software, ")
+                except ValueError:
+                    # Handle 'Cisco IOS Software [Denali],'
+                    _, os_version = re.split(r"Cisco IOS Software \[.*?\], ", line)
                 os_version = os_version.strip()
             elif re.search(r"IOS (tm).+Software", line):
                 _, os_version = line.split("IOS (tm) ")
@@ -715,15 +752,16 @@ class IOSDriver(NetworkDriver):
                     if len(fields) == 3:
                         # Check for 'ip address dhcp', convert to ip address and mask
                         if fields[2] == 'dhcp':
-                            show_command = "show interface {0} | in Internet address is".format(interface)
-                            show_int = self.device.send_command(show_command)
+                            cmd = "show interface {} | in Internet address is".format(interface)
+                            show_int = self.device.send_command(cmd)
                             int_fields = show_int.split()
                             ip_address, subnet = int_fields[3].split(r'/')
                             interfaces[interface]['ipv4'] = {ip_address: {}}
                             try:
-                                interfaces[interface]['ipv4'][ip_address] = {'prefix_length': int(subnet)}
+                                val = {'prefix_length': int(subnet)}
                             except ValueError:
-                                interfaces[interface]['ipv4'][ip_address] = {'prefix_length': u'N/A'}
+                                val = {'prefix_length': u'N/A'}
+                            interfaces[interface]['ipv4'][ip_address] = val
                     elif len(fields) in [4, 5]:
                         # Check for 'ip address 10.10.10.1 255.255.255.0'
                         # Check for 'ip address 10.10.11.1 255.255.255.0 secondary'
@@ -1074,7 +1112,8 @@ class IOSDriver(NetworkDriver):
         environment.setdefault('fans', {})
         environment['fans']['invalid'] = {'status': True}
         environment.setdefault('temperature', {})
-        environment['temperature']['invalid'] = {'is_alert': False, 'is_critical': False, 'temperature': -1.0}
+        env_value = {'is_alert': False, 'is_critical': False, 'temperature': -1.0}
+        environment['temperature']['invalid'] = env_value
         return environment
 
     def get_arp_table(self):
@@ -1137,7 +1176,8 @@ class IOSDriver(NetworkDriver):
 
     def cli(self, commands=None):
         """
-        Execute a list of commands and return the output in a dictionary format using the command as the key.
+        Execute a list of commands and return the output in a dictionary format using the command
+        as the key.
 
         Example input:
         ['show clock', 'show calendar']
@@ -1199,10 +1239,9 @@ class IOSDriver(NetworkDriver):
         return ntp_stats
 
     def get_mac_address_table(self):
-
         """
-        Returns a lists of dictionaries. Each dictionary represents an entry in the MAC Address Table,
-        having the following keys
+        Returns a lists of dictionaries. Each dictionary represents an entry in the MAC Address
+        Table, having the following keys
             * mac (string)
             * interface (string)
             * vlan (int)
@@ -1211,31 +1250,26 @@ class IOSDriver(NetworkDriver):
             * moves (int)
             * last_move (float)
         """
-
         mac_address_table = []
         command = 'show mac-address-table'
         output = self.device.send_command(command)
         output = output.strip().split('\n')
 
         # Skip the first two lines which are headers
-        output = output[2:-1]
-
+        output = output[2:]
         for line in output:
             if len(line) == 0:
                 return mac_address_table
             elif len(line.split()) == 4:
                 mac, mac_type, vlan, interface = line.split()
-
                 if mac_type.lower() in ['self', 'static']:
                     static = True
                 else:
                     static = False
-
                 if mac_type.lower() in ['dynamic']:
                     active = True
                 else:
                     active = False
-
                 entry = {
                     'mac': mac,
                     'interface': interface,
@@ -1245,11 +1279,9 @@ class IOSDriver(NetworkDriver):
                     'moves': -1,
                     'last_move': -1.0
                 }
-
                 mac_address_table.append(entry)
             else:
                 raise ValueError("Unexpected output from: {}".format(line.split()))
-
         return mac_address_table
 
     def get_snmp_information(self):
@@ -1268,10 +1300,13 @@ class IOSDriver(NetworkDriver):
         'location': u'123 Anytown USA Rack 404'}
 
         """
-
         # default values
-
-        snmp_dict = {}
+        snmp_dict = {
+            'chassis_id': u'unknown',
+            'community': {},
+            'contact': u'unknown',
+            'location': u'unknown'
+        }
         command = 'show run | include snmp-server'
         output = self.device.send_command(command)
         for line in output.splitlines():
@@ -1281,24 +1316,94 @@ class IOSDriver(NetworkDriver):
                 if 'community' not in snmp_dict.keys():
                     snmp_dict.update({'community': {}})
                 snmp_dict['community'].update({name: {}})
-
                 try:
                     snmp_dict['community'][name].update({'mode': fields[3].lower()})
                 except IndexError:
                     snmp_dict['community'][name].update({'mode': u'N/A'})
-
                 try:
                     snmp_dict['community'][name].update({'acl': fields[4]})
                 except IndexError:
                     snmp_dict['community'][name].update({'acl': u'N/A'})
-
             elif 'snmp-server location' in line:
                 snmp_dict['location'] = ' '.join(fields[2:])
             elif 'snmp-server contact' in line:
                 snmp_dict['contact'] = ' '.join(fields[2:])
             elif 'snmp-server chassis-id' in line:
                 snmp_dict['chassis_id'] = ' '.join(fields[2:])
-            else:
-                raise ValueError("Unexpected Response from the device")
-
+        # If SNMP Chassis wasn't found; obtain using direct command
+        if snmp_dict['chassis_id'] == 'unknown':
+            command = 'show snmp chassis'
+            snmp_chassis = self.device.send_command(command)
+            snmp_dict['chassis_id'] = snmp_chassis
         return snmp_dict
+
+    def ping(self, destination, source='', ttl=255, timeout=2, size=100, count=5):
+        """
+        Execute ping on the device and returns a dictionary with the result.
+
+        Output dictionary has one of following keys:
+            * success
+            * error
+        In case of success, inner dictionary will have the followin keys:
+            * probes_sent (int)
+            * packet_loss (int)
+            * rtt_min (float)
+            * rtt_max (float)
+            * rtt_avg (float)
+            * rtt_stddev (float)
+            * results (list)
+        'results' is a list of dictionaries with the following keys:
+            * ip_address (str)
+            * rtt (float)
+        """
+        ping_dict = {}
+        command = 'ping {}'.format(destination)
+        command += ' timeout {}'.format(timeout)
+        command += ' size {}'.format(size)
+        command += ' repeat {}'.format(count)
+        if source != '':
+            command += ' source {}'.format(source)
+
+        output = self.device.send_command(command)
+
+        if '%' in output:
+            ping_dict['error'] = output
+        elif 'Sending' in output:
+            ping_dict['success'] = {
+                                'probes_sent': 0,
+                                'probes_sent': 0,
+                                'packet_loss': 0,
+                                'rtt_min': 0.0,
+                                'rtt_max': 0.0,
+                                'rtt_avg': 0.0,
+                                'rtt_stddev': 0.0,
+                                'results': []
+            }
+
+            for line in output.splitlines():
+                fields = line.split()
+                if 'Success rate is 0' in line:
+                    sent_and_received = re.search(r'\((\d*)/(\d*)\)', fields[5])
+                    probes_sent = int(sent_and_received.groups()[0])
+                    probes_received = int(sent_and_received.groups()[1])
+                    ping_dict['success']['probes_sent'] = probes_sent
+                    ping_dict['success']['packet_loss'] = probes_sent - probes_received
+                elif 'Success rate is' in line:
+                    sent_and_received = re.search(r'\((\d*)/(\d*)\)', fields[5])
+                    probes_sent = int(sent_and_received.groups()[0])
+                    probes_received = int(sent_and_received.groups()[1])
+                    min_avg_max = re.search(r'(\d*)/(\d*)/(\d*)', fields[9])
+                    ping_dict['success']['probes_sent'] = probes_sent
+                    ping_dict['success']['packet_loss'] = probes_sent - probes_received
+                    ping_dict['success'].update({
+                                    'rtt_min': float(min_avg_max.groups()[0]),
+                                    'rtt_avg': float(min_avg_max.groups()[1]),
+                                    'rtt_max': float(min_avg_max.groups()[2]),
+                    })
+                    results_array = []
+                    for i in range(probes_received):
+                        results_array.append({'ip_address': unicode(destination), 'rtt': 0.0})
+
+                    ping_dict['success'].update({'results': results_array})
+
+        return ping_dict
diff --git a/requirements.txt b/requirements.txt
index ec5f5f1..be2156f 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,2 +1,2 @@
-napalm-base
-netmiko>=0.5.0
+napalm_base>=0.18.0
+netmiko>=1.0.0
diff --git a/setup.cfg b/setup.cfg
index 861a9f5..5f3d64f 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,3 +1,10 @@
+[pylama]
+linters = mccabe,pep8,pyflakes
+ignore = D203,C901
+
+[pylama:pep8]
+max_line_length = 100
+
 [egg_info]
 tag_build = 
 tag_date = 0
diff --git a/setup.py b/setup.py
index 11e046e..0840267 100644
--- a/setup.py
+++ b/setup.py
@@ -1,5 +1,4 @@
 """setup.py file."""
-
 import uuid
 
 from setuptools import setup, find_packages
@@ -12,7 +11,7 @@ reqs = [str(ir.req) for ir in install_reqs]
 
 setup(
     name="napalm-ios",
-    version="0.1.7",
+    version="0.3.1",
     packages=find_packages(),
     author="David Barroso",
     author_email="dbarrosop at dravetech.com",

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



More information about the Python-modules-commits mailing list