[Python-modules-commits] [napalm-base] 01/03: Import napalm-base_0.18.0.orig.tar.gz
Vincent Bernat
bernat at moszumanska.debian.org
Tue Nov 1 20:19:21 UTC 2016
This is an automated email from the git hooks/post-receive script.
bernat pushed a commit to branch master
in repository napalm-base.
commit b98c5980a5dad5d2c23b4c6939fbdcf7c0c92eb4
Author: Vincent Bernat <bernat at debian.org>
Date: Tue Nov 1 21:16:36 2016 +0100
Import napalm-base_0.18.0.orig.tar.gz
---
PKG-INFO | 5 +-
napalm_base.egg-info/PKG-INFO | 5 +-
napalm_base.egg-info/SOURCES.txt | 12 +-
napalm_base.egg-info/entry_points.txt | 1 +
napalm_base.egg-info/requires.txt | 3 +-
napalm_base.egg-info/top_level.txt | 1 +
napalm_base/__init__.py | 57 ++--
napalm_base/base.py | 348 ++++++++++++++++-------
napalm_base/clitools/cl_napalm_configure.py | 122 ++------
napalm_base/clitools/cl_napalm_test.py | 45 +++
napalm_base/clitools/helpers.py | 110 +++++++
napalm_base/exceptions.py | 14 +
napalm_base/helpers.py | 122 ++++++--
napalm_base/test/base.py | 279 +++++++++++++-----
napalm_base/test/conftest.py | 49 ++++
napalm_base/test/double.py | 78 +++++
napalm_base/test/getters.py | 427 ++++++++++++++++++++++++++++
napalm_base/test/helpers.py | 23 ++
napalm_base/test/models.py | 296 ++++++++++---------
napalm_base/utils/jinja_filters.py | 53 ++++
napalm_base/utils/py23_compat.py | 15 +
napalm_base/utils/string_parsers.py | 43 +--
requirements.txt | 3 +-
setup.cfg | 11 +-
setup.py | 8 +-
test/__init__.py | 0
26 files changed, 1646 insertions(+), 484 deletions(-)
diff --git a/PKG-INFO b/PKG-INFO
index 05c9677..7e31242 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: napalm-base
-Version: 0.14.1
+Version: 0.18.0
Summary: Network Automation and Programmability Abstraction Layer with Multivendor support
Home-page: https://github.com/napalm-automation/napalm-base
Author: David Barroso
@@ -12,5 +12,8 @@ Classifier: Topic :: Utilities
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.4
+Classifier: Operating System :: POSIX :: Linux
Classifier: Operating System :: POSIX :: Linux
Classifier: Operating System :: MacOS
diff --git a/napalm_base.egg-info/PKG-INFO b/napalm_base.egg-info/PKG-INFO
index 05c9677..7e31242 100644
--- a/napalm_base.egg-info/PKG-INFO
+++ b/napalm_base.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: napalm-base
-Version: 0.14.1
+Version: 0.18.0
Summary: Network Automation and Programmability Abstraction Layer with Multivendor support
Home-page: https://github.com/napalm-automation/napalm-base
Author: David Barroso
@@ -12,5 +12,8 @@ Classifier: Topic :: Utilities
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.4
+Classifier: Operating System :: POSIX :: Linux
Classifier: Operating System :: POSIX :: Linux
Classifier: Operating System :: MacOS
diff --git a/napalm_base.egg-info/SOURCES.txt b/napalm_base.egg-info/SOURCES.txt
index 8260714..a727a17 100644
--- a/napalm_base.egg-info/SOURCES.txt
+++ b/napalm_base.egg-info/SOURCES.txt
@@ -1,5 +1,6 @@
MANIFEST.in
requirements.txt
+setup.cfg
setup.py
napalm_base/__init__.py
napalm_base/base.py
@@ -13,8 +14,17 @@ napalm_base.egg-info/requires.txt
napalm_base.egg-info/top_level.txt
napalm_base/clitools/__init__.py
napalm_base/clitools/cl_napalm_configure.py
+napalm_base/clitools/cl_napalm_test.py
+napalm_base/clitools/helpers.py
napalm_base/test/__init__.py
napalm_base/test/base.py
+napalm_base/test/conftest.py
+napalm_base/test/double.py
+napalm_base/test/getters.py
+napalm_base/test/helpers.py
napalm_base/test/models.py
napalm_base/utils/__init__.py
-napalm_base/utils/string_parsers.py
\ No newline at end of file
+napalm_base/utils/jinja_filters.py
+napalm_base/utils/py23_compat.py
+napalm_base/utils/string_parsers.py
+test/__init__.py
\ No newline at end of file
diff --git a/napalm_base.egg-info/entry_points.txt b/napalm_base.egg-info/entry_points.txt
index 4a94e3e..30cf208 100644
--- a/napalm_base.egg-info/entry_points.txt
+++ b/napalm_base.egg-info/entry_points.txt
@@ -1,3 +1,4 @@
[console_scripts]
cl_napalm_configure = napalm_base.clitools.cl_napalm_configure:main
+cl_napalm_test = napalm_base.clitools.cl_napalm_test:main
diff --git a/napalm_base.egg-info/requires.txt b/napalm_base.egg-info/requires.txt
index 62b0e5a..d8a6f3e 100644
--- a/napalm_base.egg-info/requires.txt
+++ b/napalm_base.egg-info/requires.txt
@@ -1,2 +1,3 @@
+jtextfsm
jinja2
-gtextfsm
+netaddr
diff --git a/napalm_base.egg-info/top_level.txt b/napalm_base.egg-info/top_level.txt
index d140051..4c74f08 100644
--- a/napalm_base.egg-info/top_level.txt
+++ b/napalm_base.egg-info/top_level.txt
@@ -1 +1,2 @@
napalm_base
+test
diff --git a/napalm_base/__init__.py b/napalm_base/__init__.py
index b14c82a..3b09d4d 100644
--- a/napalm_base/__init__.py
+++ b/napalm_base/__init__.py
@@ -14,13 +14,33 @@
"""napalm_base package."""
+# Python3 support
+from __future__ import print_function
+from __future__ import unicode_literals
+
# Python std lib
+import sys
import inspect
import importlib
+import pkg_resources
+
+# Verify Python Version that is running
+try:
+ if not(sys.version_info.major == 2 and sys.version_info.minor == 7) and \
+ not(sys.version_info.major == 3):
+ raise RuntimeError('NAPALM requires Python 2.7 or Python3')
+except AttributeError:
+ raise RuntimeError('NAPALM requires Python 2.7 or Python3')
# NAPALM base
from napalm_base.base import NetworkDriver
from napalm_base.exceptions import ModuleImportError
+from napalm_base.utils import py23_compat
+
+try:
+ __version__ = pkg_resources.get_distribution('napalm-base').version
+except pkg_resources.DistributionNotFound:
+ __version__ = "Not installed"
__all__ = [
@@ -30,19 +50,22 @@ __all__ = [
def get_network_driver(module_name):
-
"""
Searches for a class derived form the base NAPALM class NetworkDriver in a specific library.
The library name must repect the following pattern: napalm_[DEVICE_OS].
- NAPALM community supports a list of devices and provides the corresponding libraries; for full reference
- please refer to the `Supported Network Operation Systems`_ paragraph on `Read the Docs`_.
+ NAPALM community supports a list of devices and provides the corresponding libraries; for
+ full reference please refer to the `Supported Network Operation Systems`_ paragraph on
+ `Read the Docs`_.
- .. _`Supported Network Operation Systems`: http://napalm.readthedocs.io/en/latest/#supported-network-operating-systems
- .. _`Read the Docs`: http://napalm.readthedocs.io/
+ .. _`Supported Network Operation Systems`: \
+ http://napalm.readthedocs.io/en/latest/#supported-network-operating-systems
+ .. _`Read the Docs`: \
+ http://napalm.readthedocs.io/
- :param module_name: the name of the device operating system, or the name of the library.
+ :param module_name: the name of the device operating system or the name of the library.
:return: the first class derived from NetworkDriver, found in the library.
- :raise ModuleImportError: when the library is not installed, or a derived class from NetworkDriver was not found.
+ :raise ModuleImportError: when the library is not installed or a derived class from \
+ NetworkDriver was not found.
Example::
@@ -55,16 +78,20 @@ def get_network_driver(module_name):
>>> get_network_driver('napalm_eos')
<class 'napalm_eos.eos.EOSDriver'>
>>> get_network_driver('wrong')
- napalm_base.exceptions.ModuleImportError: Cannot import "napalm_wrong". Is the library installed?
+ napalm_base.exceptions.ModuleImportError: Cannot import "napalm_wrong". Is the library \
+ installed?
"""
- if not (isinstance(module_name, basestring) and len(module_name) > 0):
+ if not (isinstance(module_name, py23_compat.string_types) and len(module_name) > 0):
raise ModuleImportError('Please provide a valid driver name.')
try:
- module_name = module_name.lower() # only lowercase allowed
- module_install_name = module_name.replace('-', '') # to not raise error when users requests IOS-XR for e.g.
- if 'napalm_' not in module_install_name: # can also request using napalm_[SOMETHING]
+ # Only lowercase allowed
+ module_name = module_name.lower()
+ # Try to not raise error when users requests IOS-XR for e.g.
+ module_install_name = module_name.replace('-', '')
+ # Can also request using napalm_[SOMETHING]
+ if 'napalm_' not in module_install_name:
module_install_name = 'napalm_{name}'.format(name=module_install_name)
module = importlib.import_module(module_install_name)
except ImportError:
@@ -80,7 +107,5 @@ def get_network_driver(module_name):
# looks like you don't have any Driver class in your module...
raise ModuleImportError(
- 'No class inheriting "napalm_base.base.NetworkDriver" found in "{install_name}".'.format(
- install_name=module_install_name
- )
- )
+ 'No class inheriting "napalm_base.base.NetworkDriver" found in "{install_name}".'
+ .format(install_name=module_install_name))
diff --git a/napalm_base/base.py b/napalm_base/base.py
index 19d6c9f..7a94d4c 100644
--- a/napalm_base/base.py
+++ b/napalm_base/base.py
@@ -12,6 +12,10 @@
# License for the specific language governing permissions and limitations under
# the License.
+# Python3 support
+from __future__ import print_function
+from __future__ import unicode_literals
+
# std libs
import sys
@@ -24,9 +28,10 @@ class NetworkDriver(object):
def __init__(self, hostname, username, password, timeout, optional_args):
"""
- This is the base class you have to inherit from when writing your own Network Driver to manage any device. You
- will, in addition, have to override all the methods specified on this class. Make sure you follow the guidelines
- for every method and that you return the correct data.
+ This is the base class you have to inherit from when writing your own Network Driver to
+ manage any device. You will, in addition, have to override all the methods specified on
+ this class. Make sure you follow the guidelines for every method and that you return the
+ correct data.
:param hostname: (str) IP or FQDN of the device you want to connect to.
:param username: (str) Username you want to use
@@ -53,21 +58,24 @@ class NetworkDriver(object):
@staticmethod
def __raise_clean_exception(exc_type, exc_value, exc_traceback):
"""
- This method is going to check if the exception exc_type is part of the builtins exceptions or part of the
- napalm exceptions. If it is not, it will print a message on the screen giving instructions to fill a bug.
+ This method is going to check if the exception exc_type is part of the builtins exceptions
+ or part of the napalm exceptions. If it is not, it will print a message on the screen
+ giving instructions to fill a bug.
+
Finally it will raise the original exception.
:param exc_type: Exception class.
:param exc_value: Exception object.
:param exc_traceback: Traceback.
"""
- if exc_type.__name__ not in dir(napalm_base.exceptions) and \
- exc_type.__name__ not in __builtins__.keys():
+ if (exc_type.__name__ not in dir(napalm_base.exceptions) and
+ exc_type.__name__ not in __builtins__.keys()):
epilog = ("NAPALM didn't catch this exception. Please, fill a bugfix on "
"https://github.com/napalm-automation/napalm/issues\n"
"Don't forget to include this traceback.")
print(epilog)
- raise exc_type, exc_value, exc_traceback
+ # Traceback should already be attached to exception; no need to re-attach
+ raise exc_value
def open(self):
"""
@@ -81,21 +89,22 @@ class NetworkDriver(object):
"""
raise NotImplementedError
- def load_template(self, template_name, template_source=None, template_path=None, **template_vars):
+ def load_template(self, template_name, template_source=None,
+ template_path=None, **template_vars):
"""
Will load a templated configuration on the device.
:param cls: Instance of the driver class.
:param template_name: Identifies the template name.
- :param template_source (optional): A custom config template to be rendered and loaded on the device
- :param template_path (optional): Specifies the absolute path to a different directory for the configuration \
- templates
- :param template_vars: Dictionary with the arguments to be used when the template is rendered.
- :raise DriverTemplateNotImplemented: No template defined for the device type
- :raise TemplateNotImplemented: The template specified in template_name does not exist in the default path or \
- in the custom path if any specified using parameter `template_path`
- :raise TemplateRenderException: The template could not be rendered. Either the template source does not have \
- the right format, either the arguments in `template_vars` are not properly specified.
+ :param template_source (optional): Custom config template rendered and loaded on device
+ :param template_path (optional): Absolute path to directory for the configuration templates
+ :param template_vars: Dictionary with arguments to be used when the template is rendered.
+ :raise DriverTemplateNotImplemented: No template defined for the device type.
+ :raise TemplateNotImplemented: The template specified in template_name does not exist in \
+ the default path or in the custom path if any specified using parameter `template_path`.
+ :raise TemplateRenderException: The template could not be rendered. Either the template \
+ source does not have the right format, either the arguments in `template_vars` are not \
+ properly specified.
"""
return napalm_base.helpers.load_template(self,
template_name,
@@ -105,11 +114,13 @@ class NetworkDriver(object):
def load_replace_candidate(self, filename=None, config=None):
"""
- Populates the candidate configuration. You can populate it from a file or from a string. If you send both a
- filename and a string containing the configuration, the file takes precedence.
+ Populates the candidate configuration. You can populate it from a file or from a string.
+ If you send both a filename and a string containing the configuration, the file takes
+ precedence.
- If you use this method the existing configuration will be replaced entirely by the candidate configuration once
- you commit the changes. This method will not change the configuration by itself.
+ If you use this method the existing configuration will be replaced entirely by the
+ candidate configuration once you commit the changes. This method will not change the
+ configuration by itself.
:param filename: Path to the file containing the desired configuration. By default is None.
:param config: String containing the desired configuration.
@@ -119,11 +130,13 @@ class NetworkDriver(object):
def load_merge_candidate(self, filename=None, config=None):
"""
- Populates the candidate configuration. You can populate it from a file or from a string. If you send both a
- filename and a string containing the configuration, the file takes precedence.
+ Populates the candidate configuration. You can populate it from a file or from a string.
+ If you send both a filename and a string containing the configuration, the file takes
+ precedence.
- If you use this method the existing configuration will be merged with the candidate configuration once
- you commit the changes. This method will not change the configuration by itself.
+ If you use this method the existing configuration will be merged with the candidate
+ configuration once you commit the changes. This method will not change the configuration
+ by itself.
:param filename: Path to the file containing the desired configuration. By default is None.
:param config: String containing the desired configuration.
@@ -133,8 +146,9 @@ class NetworkDriver(object):
def compare_config(self):
"""
- :return: A string showing the difference between the running configuration and the candidate configuration. The\
- running_config is loaded automatically just before doing the comparison so there is no need for you to do it.
+ :return: A string showing the difference between the running configuration and the \
+ candidate configuration. The running_config is loaded automatically just before doing the \
+ comparison so there is no need for you to do it.
"""
raise NotImplementedError
@@ -186,8 +200,9 @@ class NetworkDriver(object):
def get_interfaces(self):
"""
- Returns a dictionary of dictionaries. The keys for the first dictionary will be the interfaces in the devices.\
- The inner dictionary will containing the following data for each interface:
+ Returns a dictionary of dictionaries. The keys for the first dictionary will be the \
+ interfaces in the devices. The inner dictionary will containing the following data for \
+ each interface:
* is_up (True/False)
* is_enabled (True/False)
* description (string)
@@ -240,8 +255,8 @@ class NetworkDriver(object):
def get_lldp_neighbors(self):
"""
- Returns a dictionary where the keys are local ports and the value is a list of dictionaries with the following \
- information:
+ Returns a dictionary where the keys are local ports and the value is a list of \
+ dictionaries with the following information:
* hostname
* port
@@ -286,11 +301,12 @@ class NetworkDriver(object):
def get_bgp_neighbors(self):
"""
- Returns a dictionary of dictionaries. The keys for the first dictionary will be the vrf (global if no vrf).
- The inner dictionary will contain the following data for each vrf:
+ Returns a dictionary of dictionaries. The keys for the first dictionary will be the vrf
+ (global if no vrf). The inner dictionary will contain the following data for each vrf:
* router_id
- * peers - another dictionary of dictionaries. Outer keys are the IPs of the neighbors. The inner keys are:
+ * peers - another dictionary of dictionaries. Outer keys are the IPs of the neighbors. \
+ The inner keys are:
* local_as (int)
* remote_as (int)
* remote_id - peer router id
@@ -298,8 +314,8 @@ class NetworkDriver(object):
* is_enabled (True/False)
* description (string)
* uptime (int in seconds)
- * address_family (dictionary) - A dictionary of address families available for the neighbor. So far it can\
- be 'ipv4' or 'ipv6'
+ * address_family (dictionary) - A dictionary of address families available for the \
+ neighbor. So far it can be 'ipv4' or 'ipv6'
* received_prefixes (int)
* accepted_prefixes (int)
* sent_prefixes (int)
@@ -312,10 +328,10 @@ class NetworkDriver(object):
* fans is a dictionary of dictionaries where the key is the location and the values:
* status (True/False) - True if it's ok, false if it's broken
- * temperature is a dictionary of dictionaries where the key is the location and the values:
+ * temperature is a dict of dictionaries where the key is the location and the values:
* temperature (float) - Temperature in celsius the sensor is reporting.
* is_alert (True/False) - True if the temperature is above the alert threshold
- * is_critical (True/False) - True if the temperature is above the critical threshold
+ * is_critical (True/False) - True if the temp is above the critical threshold
* power is a dictionary of dictionaries where the key is the PSU id and the values:
* status (True/False) - True if it's ok, false if it's broken
* capacity (float) - Capacity in W that the power supply can support
@@ -330,8 +346,8 @@ class NetworkDriver(object):
def get_interfaces_counters(self):
"""
- Returns a dictionary of dictionaries where the first key is an interface name and the inner dictionary contains
- the following keys:
+ Returns a dictionary of dictionaries where the first key is an interface name and the
+ inner dictionary contains the following keys:
* tx_errors (int)
* rx_errors (int)
@@ -395,7 +411,7 @@ class NetworkDriver(object):
"""
raise NotImplementedError
- def get_lldp_neighbors_detail(self, interface = ''):
+ def get_lldp_neighbors_detail(self, interface=''):
"""
Returns a detailed view of the LLDP neighbors as a dictionary
containing lists of dictionaries for each interface.
@@ -420,7 +436,8 @@ class NetworkDriver(object):
'remote_system_name': u'switch',
'remote_port': u'Eth2/2/1',
'remote_port_description': u'Ethernet2/2/1',
- 'remote_system_description': u'''Cisco Nexus Operating System (NX-OS) Software 7.1(0)N1(1a)
+ 'remote_system_description': u'''Cisco Nexus Operating System (NX-OS)
+ Software 7.1(0)N1(1a)
TAC support: http://www.cisco.com/tac
Copyright (c) 2002-2015, Cisco Systems, Inc. All rights reserved.''',
'remote_system_capab': u'B, R',
@@ -439,7 +456,8 @@ class NetworkDriver(object):
:param group: Returns the configuration of a specific BGP group.
:param neighbor: Returns the configuration of a specific BGP neighbor.
- Main dictionary keys represent the group name and the values represent a dictionary having the following keys:
+ Main dictionary keys represent the group name and the values represent a dictionary having
+ the following keys:
* type (string)
* description (string)
* apply_groups (string list)
@@ -541,14 +559,14 @@ class NetworkDriver(object):
I just saw Episode Two
You're my only hope
''',
- u'show chassis fan' : u'''Item Status RPM Measurement
- Top Rear Fan OK 3840 Spinning at intermediate-speed
- Bottom Rear Fan OK 3840 Spinning at intermediate-speed
- Top Middle Fan OK 3900 Spinning at intermediate-speed
- Bottom Middle Fan OK 3840 Spinning at intermediate-speed
- Top Front Fan OK 3810 Spinning at intermediate-speed
- Bottom Front Fan OK 3840 Spinning at intermediate-speed
- '''
+ u'show chassis fan' : u'''
+ Item Status RPM Measurement
+ Top Rear Fan OK 3840 Spinning at intermediate-speed
+ Bottom Rear Fan OK 3840 Spinning at intermediate-speed
+ Top Middle Fan OK 3900 Spinning at intermediate-speed
+ Bottom Middle Fan OK 3840 Spinning at intermediate-speed
+ Top Front Fan OK 3810 Spinning at intermediate-speed
+ Bottom Front Fan OK 3840 Spinning at intermediate-speed'''
}
"""
raise NotImplementedError
@@ -560,11 +578,15 @@ class NetworkDriver(object):
:param neighbor_address: Retuns the statistics for a spcific BGP neighbor.
- The keys of the dictionary represent the AS number of the neighbors.
- Inner dictionaries contain the following fields:
+ Returns a dictionary of dictionaries. The keys for the first dictionary will be the vrf
+ (global if no vrf).
+ The keys of the inner dictionary represent the AS number of the neighbors.
+ Leaf dictionaries contain the following fields:
+
* up (True/False)
* local_as (int)
* remote_as (int)
+ * router_id (string)
* local_address (string)
* routing_table (string)
* local_address_configured (True/False)
@@ -600,44 +622,46 @@ class NetworkDriver(object):
Example::
{
- 8121: [
- {
- 'up' : True,
- 'local_as' : 13335,
- 'remote_as' : 8121,
- 'local_address' : u'172.101.76.1',
- 'local_address_configured' : True,
- 'local_port' : 179,
- 'routing_table' : u'inet.0',
- 'remote_address' : u'192.247.78.0',
- 'remote_port' : 58380,
- 'multihop' : False,
- 'multipath' : True,
- 'remove_private_as' : True,
- 'import_policy' : u'4-NTT-TRANSIT-IN',
- 'export_policy' : u'4-NTT-TRANSIT-OUT',
- 'input_messages' : 123,
- 'output_messages' : 13,
- 'input_updates' : 123,
- 'output_updates' : 5,
- 'messages_queued_out' : 23,
- 'connection_state' : u'Established',
- 'previous_connection_state' : u'EstabSync',
- 'last_event' : u'RecvKeepAlive',
- 'suppress_4byte_as' : False,
- 'local_as_prepend' : False,
- 'holdtime' : 90,
- 'configured_holdtime' : 90,
- 'keepalive' : 30,
- 'configured_keepalive' : 30,
- 'active_prefix_count' : 132808,
- 'received_prefix_count' : 566739,
- 'accepted_prefix_count' : 566479,
- 'suppressed_prefix_count' : 0,
- 'advertise_prefix_count' : 0,
- 'flap_count' : 27
- }
- ]
+ 'global': {
+ 8121: [
+ {
+ 'up' : True,
+ 'local_as' : 13335,
+ 'remote_as' : 8121,
+ 'local_address' : u'172.101.76.1',
+ 'local_address_configured' : True,
+ 'local_port' : 179,
+ 'routing_table' : u'inet.0',
+ 'remote_address' : u'192.247.78.0',
+ 'remote_port' : 58380,
+ 'multihop' : False,
+ 'multipath' : True,
+ 'remove_private_as' : True,
+ 'import_policy' : u'4-NTT-TRANSIT-IN',
+ 'export_policy' : u'4-NTT-TRANSIT-OUT',
+ 'input_messages' : 123,
+ 'output_messages' : 13,
+ 'input_updates' : 123,
+ 'output_updates' : 5,
+ 'messages_queued_out' : 23,
+ 'connection_state' : u'Established',
+ 'previous_connection_state' : u'EstabSync',
+ 'last_event' : u'RecvKeepAlive',
+ 'suppress_4byte_as' : False,
+ 'local_as_prepend' : False,
+ 'holdtime' : 90,
+ 'configured_holdtime' : 90,
+ 'keepalive' : 30,
+ 'configured_keepalive' : 30,
+ 'active_prefix_count' : 132808,
+ 'received_prefix_count' : 566739,
+ 'accepted_prefix_count' : 566479,
+ 'suppressed_prefix_count' : 0,
+ 'advertised_prefix_count' : 0,
+ 'flap_count' : 27
+ }
+ ]
+ }
}
"""
raise NotImplementedError
@@ -671,7 +695,6 @@ class NetworkDriver(object):
"""
raise NotImplementedError
-
def get_ntp_peers(self):
"""
@@ -692,6 +715,25 @@ class NetworkDriver(object):
raise NotImplementedError
+ def get_ntp_servers(self):
+
+ """
+ Returns the NTP servers configuration as dictionary.
+ The keys of the dictionary represent the IP Addresses of the servers.
+ Inner dictionaries do not have yet any available keys.
+
+ Example::
+
+ {
+ '192.168.0.1': {},
+ '17.72.148.53': {},
+ '37.187.56.220': {},
+ '162.158.20.18': {}
+ }
+
+ """
+
+ raise NotImplementedError
def get_ntp_stats(self):
@@ -736,7 +778,8 @@ class NetworkDriver(object):
Returns all configured IP addresses on all interfaces as a dictionary of dictionaries.
Keys of the main dictionary represent the name of the interface.
Values of the main dictionary represent are dictionaries that may consist of two keys
- 'ipv4' and 'ipv6' (one, both or none) which are themselvs dictionaries witht the IP addresses as keys.
+ 'ipv4' and 'ipv6' (one, both or none) which are themselvs dictionaries witht the IP
+ addresses as keys.
Each IP Address dictionary has the following keys:
* prefix_length (int)
@@ -785,8 +828,8 @@ class NetworkDriver(object):
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)
@@ -835,7 +878,8 @@ class NetworkDriver(object):
def get_route_to(self, destination='', protocol=''):
"""
- Returns a dictionary of dictionaries containing details of all available routes to a destination.
+ Returns a dictionary of dictionaries containing details of all available routes to a
+ destination.
:param destination: The destination prefix to be used when filtering the routes.
:param protocol (optional): Retrieve the routes only for a specific protocol.
@@ -950,7 +994,8 @@ class NetworkDriver(object):
def get_probes_config(self):
"""
Returns a dictionary with the probes configured on the device.
- Probes can be either RPM on JunOS devices, either SLA on IOS-XR. Other vendors do not support probes.
+ Probes can be either RPM on JunOS devices, either SLA on IOS-XR. Other vendors do not
+ support probes.
The keys of the main dictionary represent the name of the probes.
Each probe consists on multiple tests, each test name being a key in the probe dictionary.
A test has the following keys:
@@ -1051,7 +1096,6 @@ class NetworkDriver(object):
"""
raise NotImplementedError
-
def ping(self, destination, source='', ttl=0, timeout=0, size=0, count=0):
"""
Executes ping on the device and returns a dictionary with the result
@@ -1115,7 +1159,6 @@ class NetworkDriver(object):
"""
raise NotImplementedError
-
def traceroute(self, destination, source='', ttl=0, timeout=0):
"""
Executes traceroute on the device and returns a dictionary with the result.
@@ -1130,9 +1173,8 @@ class NetworkDriver(object):
* success
* error
- In case of success, the keys of the dictionary represent the hop ID, while values are dictionaries
- containing the probes results:
-
+ In case of success, the keys of the dictionary represent the hop ID, while values are
+ dictionaries containing the probes results:
* rtt (float)
* ip_address (str)
* host_name (str)
@@ -1223,18 +1265,17 @@ class NetworkDriver(object):
"""
raise NotImplementedError
-
def get_users(self):
"""
Returns a dictionary with the configured users.
- The keys of the main dictionary represents the username. The values represent the details of the user,
- represented by the following keys:
-
+ The keys of the main dictionary represents the username. The values represent the details
+ of the user, represented by the following keys:
* level (int)
* password (str)
* sshkeys (list)
- The level is an integer between 0 and 15, where 0 is the lowest access and 15 represents full access to the device.
+ The level is an integer between 0 and 15, where 0 is the lowest access and 15 represents
+ full access to the device.
Example::
@@ -1243,9 +1284,98 @@ class NetworkDriver(object):
'level': 15,
'password': '$1$0P70xKPa$z46fewjo/10cBTckk6I/w/',
'sshkeys': [
- 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC4pFn+shPwTb2yELO4L7NtQrKOJXNeCl1jel9STXVaGnRAnuc2PXl35vnWmcUq6YbUEcgUTRzzXfmelJKuVJTJIlMXii7h2xkbQp0YZIEs4P8ipwnRBAxFfk/ZcDsN3mjep4/yjN56eorF5xs7zP9HbqbJ1dsqk1p3A/9LIL7l6YewLBCwJj6D+fWSJ0/YW+7oH17Fk2HH+tw0L5PcWLHkwA4t60iXn16qDbIk/ze6jv2hDGdCdz7oYQeCE55CCHOHMJWYfN3jcL4s0qv8/u6Ka1FVkV7iMmro7ChThoV/5snI4Ljf2wKqgHH7TfNaCfpU0WvHAnTs8zhOrGScSrtb mircea at master-roshi'
+ 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC4pFn+shPwTb2yELO4L7NtQrKOJXNeCl1je\
+ l9STXVaGnRAnuc2PXl35vnWmcUq6YbUEcgUTRzzXfmelJKuVJTJIlMXii7h2xkbQp0YZIEs4P\
+ 8ipwnRBAxFfk/ZcDsN3mjep4/yjN56eorF5xs7zP9HbqbJ1dsqk1p3A/9LIL7l6YewLBCwJj6\
+ D+fWSJ0/YW+7oH17Fk2HH+tw0L5PcWLHkwA4t60iXn16qDbIk/ze6jv2hDGdCdz7oYQeCE55C\
+ CHOHMJWYfN3jcL4s0qv8/u6Ka1FVkV7iMmro7ChThoV/5snI4Ljf2wKqgHH7TfNaCfpU0WvHA\
+ nTs8zhOrGScSrtb mircea at master-roshi'
]
}
}
"""
raise NotImplementedError
+
+ def get_optics(self):
+ """Fetches the power usage on the various transceivers installed
+ on the switch (in dbm), and returns a view that conforms with the
+ openconfig model openconfig-platform-transceiver.yang
+
+ Returns a dictionary where the keys are as listed below:
+
+ * intf_name (unicode)
+ * physical_channels
+ * channels (list of dicts)
+ * index (int)
+ * state
+ * input_power
+ * instant (float)
+ * avg (float)
+ * min (float)
+ * max (float)
+ * output_power
+ * instant (float)
+ * avg (float)
+ * min (float)
+ * max (float)
+ * laser_bias_current
+ * instant (float)
+ * avg (float)
+ * min (float)
+ * max (float)
+
+ Example:
+
+ {
+ 'et1': {
+ 'physical_channels': {
+ 'channel': [
+ {
+ 'index': 0,
+ 'state': {
+ 'input_power': {
+ 'instant': 0.0,
+ 'avg': 0.0,
+ 'min': 0.0,
+ 'max': 0.0,
+ },
+ 'output_power': {
+ 'instant': 0.0,
+ 'avg': 0.0,
+ 'min': 0.0,
+ 'max': 0.0,
+ },
+ 'laser_bias_current': {
+ 'instant': 0.0,
+ 'avg': 0.0,
+ 'min': 0.0,
+ 'max': 0.0,
+ },
+ }
+ }
+ ]
+ }
+ }
+ }
+ """
+ raise NotImplementedError
+
+ def get_config(self, retrieve='all'):
+ """
+ Return the configuration of a device.
+
+ Args:
+ retrieve(string): Which configuration type you want to populate, default is all of them.
+ The rest will be set to "".
+
+ Returns:
+ The object returned is a dictionary with the following keys:
+ - running(string) - Representation of the native running configuration
+ - candidate(string) - Representation of the native candidate configuration. If the
+ device doesnt differentiate between running and startup configuration this will an
+ empty string
+ - startup(string) - Representation of the native startup configuration. If the
+ device doesnt differentiate between running and startup configuration this will an
+ empty string
+ """
+ raise NotImplementedError
diff --git a/napalm_base/clitools/cl_napalm_configure.py b/napalm_base/clitools/cl_napalm_configure.py
index 0f6df15..1251a33 100644
--- a/napalm_base/clitools/cl_napalm_configure.py
+++ b/napalm_base/clitools/cl_napalm_configure.py
@@ -1,113 +1,34 @@
-from __future__ import print_function
+# -*- coding: utf-8 -*-
+'''
+NAPALM CLI Tools: configure
+===========================
-import argparse
-import sys
-import getpass
+Deploy device config from the shell.
+'''
-from napalm import get_network_driver
+# Python3 support
+from __future__ import print_function
+from __future__ import unicode_literals
+# import helpers
+from napalm_base import get_network_driver
+from napalm_base.clitools.helpers import build_help
+from napalm_base.clitools.helpers import configure_logging
+from napalm_base.clitools.helpers import parse_optional_args
+
+import sys
import logging
logger = logging.getLogger('cl-napalm-config.py')
-def build_help():
- parser = argparse.ArgumentParser(
- description='Command line tool to handle configuration on devices using NAPALM.'
- 'The script will print the diff on the screen',
- epilog='Automate all the things!!!'
- )
- parser.add_argument(
- dest='config_file',
- action='store',
- help='File containing the configuration you want to deploy.'
- )
- parser.add_argument(
- dest='hostname',
- action='store',
- help='Host where you want to deploy the configuration.'
- )
- parser.add_argument(
- '--user', '-u',
- dest='user',
- action='store',
- default=getpass.getuser(),
- help='User for authenticating to the host. Default: user running the script.'
- )
- parser.add_argument(
- '--password', '-p',
- dest='password',
- action='store',
- help='Password for authenticating to the host.'
- 'If you do not provide a password in the CLI you will be prompted.',
- )
- parser.add_argument(
- '--vendor', '-v',
- dest='vendor',
- action='store',
- required=True,
- help='Host Operating System.'
- )
- parser.add_argument(
- '--strategy', '-s',
- dest='strategy',
- action='store',
- choices=['replace', 'merge'],
- default='replace',
- help='Strategy to use to deploy configuration. Default: replace.'
- )
- parser.add_argument(
- '--optional_args', '-o',
- dest='optional_args',
- action='store',
- help='String with comma separated key=value pairs that will be passed via optional_args to the driver.',
- )
- parser.add_argument(
- '--dry-run', '-d',
- dest='dry_run',
- action='store_true',
- default=None,
- help='Only returns diff, it does not deploy the configuration.',
- )
- parser.add_argument(
- '--debug',
- dest='debug',
- action='store_true',
- help='Enables debug mode; more verbosity.'
- )
- args = parser.parse_args()
-
- if args.password is None:
- password = getpass.getpass('Enter password: ')
- setattr(args, 'password', password)
-
- return args
-
-
-def configure_logging(debug):
- if debug:
- logger.setLevel(logging.DEBUG)
- else:
- logger.setLevel(logging.INFO)
-
- ch = logging.StreamHandler(sys.stdout)
- formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
- ch.setFormatter(formatter)
- logger.addHandler(ch)
-
-
-class CustomException(Exception):
- pass
-
-
def run(vendor, hostname, user, password, strategy, optional_args, config_file, dry_run):
+
logger.debug('Getting driver for OS "{driver}"'.format(driver=vendor))
driver = get_network_driver(vendor)
- if optional_args is not None:
- optional_args = {x.split('=')[0]: x.split('=')[1] for x in optional_args.replace(' ', '').split(',')}
-
- logger.debug('Connecting to device "{device}" with user "{user}" and optional_args={optional_args}'.format(
- device=hostname, user=user, optional_args=optional_args))
+ optional_args = parse_optional_args(optional_args)
+ logger.debug('Connecting to device "{}" with user "{}" and optional_args={}'.format(
+ hostname, user, optional_args))
with driver(hostname, user, password, optional_args=optional_args) as device:
logger.debug('Strategy for loading configuration is "{strategy}"'.format(strategy=strategy))
if strategy == 'replace':
@@ -127,13 +48,12 @@ def run(vendor, hostname, user, password, strategy, optional_args, config_file,
logger.debug('Committing configuration')
device.commit_config()
logger.debug('Closing session')
-
return diff
def main():
args = build_help()
- configure_logging(args.debug)
+ configure_logging(logger, args.debug)
print(run(args.vendor, args.hostname, args.user, args.password, args.strategy,
args.optional_args, args.config_file, args.dry_run))
diff --git a/napalm_base/clitools/cl_napalm_test.py b/napalm_base/clitools/cl_napalm_test.py
new file mode 100644
index 0000000..86b14bd
--- /dev/null
+++ b/napalm_base/clitools/cl_napalm_test.py
@@ -0,0 +1,45 @@
+# -*- coding: utf-8 -*-
+'''
+NAPALM CLI Tools: test connectivity
+===================================
+
+Module to test connectivity with the network device through NAPALM.
+'''
+from __future__ import absolute_import
+from __future__ import print_function
... 2188 lines suppressed ...
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/napalm-base.git
More information about the Python-modules-commits
mailing list