[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