Skip to content

Commit

Permalink
Merge pull request #79 from dbarrosop/master
Browse files Browse the repository at this point in the history
Timeout, documentation revamp and IBMDriver (beta)
  • Loading branch information
dbarrosop committed Nov 3, 2015
2 parents 15fa343 + c4e8c78 commit 4fb77a9
Show file tree
Hide file tree
Showing 30 changed files with 628 additions and 72 deletions.
24 changes: 7 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,34 +1,23 @@
NAPALM
======
NAPALM (Network Automation and Programmability Abstraction Layer with Multivendor support) is python library that implements a set of functions to interact with different vendors using a unified API.
NAPALM (Network Automation and Programmability Abstraction Layer with Multivendor support) is a Python library that implements a set of functions to interact with different router vendor devices using a unified API.

![NAPALM logo](static/logo.png?raw=true "NAPALM logo")

NAPALM supports several methods to connect to the devices, to manipulate configuration and to retrieve data.
NAPALM supports several methods to connect to the devices, to manipulate configurations or to retrieve data.

Supported Network Operating Systems
-----------------------------------
* EOS - Using [pyeapi](https://github.com/arista-eosplus/pyeapi). You need version 4.14.6M or superior.
* JunOS - Using [junos-eznc](https://github.com/Juniper/py-junos-eznc)
* IOS-XR - Using [pyIOSXR](https://github.com/fooelisa/pyiosxr)
* FortiOS - Using [pyFG](https://github.com/spotify/pyfg)

| | EOS | JunOS | IOS-XR | FortiOS |
|---|---|---|---|---|
| **Name** | eos | junos | iosxr | fortios |
| **Config Management** | Full | Full | Full | Full |
| **Atomic Changes** | Yes | Yes | Yes | No |
| **Rollback** | Yes | Yes | Yes | Yes |

Please check the following [link](http://napalm.readthedocs.org/support/index.html) to see which devices are supported. Make sure you understand the [caveats](http://napalm.readthedocs.org/support/index.html#caveats).

Documentation
=============
Before using the library, please, read the documentation (link below). Specially the "caveats" section:

See the [Read the Docs](http://napalm.readthedocs.org)
Before using the library, please read the documentation at: [Read the Docs](http://napalm.readthedocs.org)

You can also watch a [live demo](https://youtu.be/93q-dHC0u0I) of NAPALM to see what it is and what it can do for you.


Install
=======
To install, execute:
Expand All @@ -39,10 +28,11 @@ To install, execute:

Ansible
=======
There is an ansible module provided by this API. Make sure you read the documentation and you understand how it works before trying to use it.
There are some ansible modules provided by this API. Make sure you read the documentation and you understand how it works before trying to use it.

Mailing List
=======

If you have any questions, join the users' mailing list at [napalm-automation@googlegroups.com](mailto:napalm-automation@googlegroups.com) and if you are developer and want to contribute to NAPALM feel free to join to the developers' mailing list at [napalm-dev@googlegroups.com](mailto:napalm-dev@googlegroups.com)

IRC
Expand Down
9 changes: 8 additions & 1 deletion ansible/napalm_install_config
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ options:
password:
description: Password
required: true
timeout:
description: Timeout for connections and requests to device
required: false
default: 60
config_file:
description: Where to load the configuration from.
required: true
Expand Down Expand Up @@ -90,6 +94,7 @@ EXAMPLES = '''
commit_changes={{ commit_changes }}
replace_config={{ replace_config }}
diff_file=../compiled/{{ inventory_hostname }}/diff
timeout={{timeout}}
From the CLI we would trigger the playbook like:
Expand All @@ -114,6 +119,7 @@ def main():
hostname=dict(required=True),
username=dict(required=True),
password=dict(required=True),
timeout=dict(required=False, default=60, type='int'),
config_file=dict(required=True),
dev_os=dict(required=True),
commit_changes=dict(required=True),
Expand All @@ -128,6 +134,7 @@ def main():
username = module.params['username']
dev_os = module.params['dev_os']
password = module.params['password']
timeout = module.params['timeout']

config_file = module.params['config_file']
commit_changes = module.params['commit_changes']
Expand All @@ -142,7 +149,7 @@ def main():

network_driver = get_network_driver(dev_os)

device = network_driver(hostname, username, password)
device = network_driver(hostname, username, password, timeout)
device.open()

if replace_config:
Expand Down
37 changes: 13 additions & 24 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,19 @@
Welcome to NAPALM's documentation!
==================================

NAPALM (Network Automation and Programmability Abstraction Layer with Multivendor support) is python library that implements a common set of functions to interact with different network Operating Systems using a unified API.
NAPALM (Network Automation and Programmability Abstraction Layer with Multivendor support) is a Python library that implements a set of functions to interact with different network device Operating Systems using a unified API.

NAPALM supports several methods to connect to the devices, to manipulate configuration or to retrieve data.
NAPALM supports several methods to connect to the devices, to manipulate configurations or to retrieve data.

Supported Network Operating System:
Supported Network Operating Systems
-----------------------------------

* eos
* junos
* iosxr
* fortios

You can get the driver you need by doing the following::
You can select the driver you need by doing the following::

>>> from napalm import get_network_driver
>>> get_network_driver('eos')
Expand All @@ -25,30 +27,17 @@ You can get the driver you need by doing the following::
<class napalm.iosxr.IOSXRDriver at 0x10706c738>
>>> get_network_driver('junos')
<class napalm.junos.JunOSDriver at 0x107861bb0>
>>> get_network_driver('fortios')
<class napalm.fortios.FortiOSDriver at 0x10bf6c1f0>

Check the tutorials to see how to use the library and the driver section to check which methods are available and some notes regarding each driver.
Check the tutorials to see how to use the library in more detail, Suppoerted Devices will provide you with detailed support information and caveats and the NetworkDriver section explains which methods are available for you to use.

Tutorials
=========

.. toctree::
:maxdepth: 1

first_steps_config

Drivers
=======
Documentation
=============

.. toctree::
:maxdepth: 2

tutorials/index
support/index
base

Caveats
=======

.. toctree::
:maxdepth: 2

eos
fortios
8 changes: 7 additions & 1 deletion docs/eos.rst → docs/support/eos.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
EOS
----
---

Minimum Version
~~~~~~~~~~~~~~~


To be able to support the ``compare_config`` method you will require to run at least EOS version `4.15.0F`.

Rollback
~~~~~~~~
Expand Down
File renamed without changes.
13 changes: 13 additions & 0 deletions docs/support/ibm.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
IBM Networking Operating System
-------

Rollback
~~~~~~~~

Rollback is simply implemented by reading current running configuration before any load actions. Rollback function executes load replace and commit.


Atomic Changes
~~~~~~~~~~~~~~

IBM plugin uses netconf to load configuration on to device. It seems that configuration is executed line by line but we can be sure that all lines will be executed. There are three options for error handling: stop-on-error, continue-on-error and rollback-on-error. Plugin uses rollback-on-error option in case of merge operation. However replace operation uses continue-on-error option. In case of typo in configuration, device will inform plugin about error but execute all the rest lines. Plugin will revert configuration using rollback function from the plugin. I do not use rollback-on-error for replace operation because in case of error device is left without any configuration. It seems like a bug. It will be investigated further. Moreover it seems that replace option wipe out whole configuration on device at the first step, so this option is good for provisioning of new device and it is not recomended for device in production.
71 changes: 71 additions & 0 deletions docs/support/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
Supported Devices
=================

General support matrix
----------------------


===================== ========== ============= =========== ============== =============
_ EOS JunOS IOS-XR FortiOS IBM
===================== ========== ============= =========== ============== =============
**Driver Name** eos junos iosxr fortios ibm
**Structured data** Yes Yes No No Yes
**Minimum version** 4.15.0F 12.1 5.1.0 5.2.0 ???
**Backend library** `pyeapi`_ `junos-eznc`_ `pyIOSXR`_ `pyFG`_ `bnclient`_
**Caveats** :doc:`eos` :doc:`fortios` :doc:`ibm`
===================== ========== ============= =========== ============== =============

.. _pyeapi: https://github.com/arista-eosplus/pyeapi
.. _junos-eznc: https://github.com/Juniper/py-junos-eznc
.. _pyIOSXR: https://github.com/fooelisa/pyiosxr
.. _pyFG: https://github.com/spotify/pyfg
.. _bnclient: https://github.com/kderynski/blade-netconf-python-client


.. warning:: Please, make sure you understand the caveats for your particular platforms before using the library.


Configuration support matrix
----------------------------

===================== ========== ===== ========== ============== =============
_ EOS JunOS IOS-XR FortiOS IBM
===================== ========== ===== ========== ============== =============
**Config. replace** Yes Yes Yes Yes Yes [#c3]_
**Config. merge** Yes Yes Yes Yes Yes
**Compare config** Yes Yes Yes [#c1]_ Yes [#c1]_ Yes [#c1]_
**Atomic Changes** Yes Yes Yes No [#c2]_ No [#c2]_
**Rollback** Yes [#c2]_ Yes Yes Yes Yes [#c2]_
===================== ========== ===== ========== ============== =============

.. [#c1] Hand-crafted by the API as the device doesn't support the feature.
.. [#c2] Not supported but emulated. Check caveats.
.. [#c3] Check the caveats, this is a dangerous operation in this device.
.. warning:: Before building a workflow to deploy configuration it is important you understand what the table above means;
what are atomic changes and which devices support it, what does replacing or merging configuration mean, etc.
The key to success is to test your workflow and to try to break things on a lab first.

Getters support matrix
----------------------

.. |yes| unicode:: U+02705 .. Yes
.. |no| unicode:: U+0274C .. No

====================== ===== ===== ====== ======= ======
_ EOS JunOS IOS-XR FortiOS IBM
====================== ===== ===== ====== ======= ======
**get_facts** |yes| |yes| |yes| |yes| |no|
**get_interfaces** |yes| |yes| |yes| |yes| |no|
**get_lldp_neighbors** |yes| |yes| |yes| |yes| |no|
====================== ===== ===== ====== ======= ======

Caveats
-------

.. toctree::
:maxdepth: 1

eos
fortios
ibm
Original file line number Diff line number Diff line change
@@ -1,28 +1,29 @@
First Steps Manipulating Config
===============================

NAPALM does not try to hide any configuration details. It only tries to provide a common interface and mechanisms to push configuration to the device so you can build your way around it. This method is very useful in combination with tools like `Ansible <http://www.ansible.com>`_.
NAPALM tries to provide a common interface and mechanisms to push configuration and retrieve state data from network devices. This method is very useful in combination with tools like `Ansible <http://www.ansible.com>`_, which in turn allows you to manage a set of devices independent of their network OS.

Connecting to the device
Connecting to the Device
------------------------

Now you can use that driver you got to connect to the device::
Use the appropriate network driver to connect to the device::

>>> from napalm import get_network_driver
>>> driver = get_network_driver('eos')
>>> device = driver('192.168.76.10', 'dbarroso', 'this_is_not_a_secure_password')
>>> device.open()

Replacing the configuration
---------------------------
Configurations can be replaced entirely or merged into the existing device config.
You can load configuration either from a string or from a file.

You can load configuration either from a string or from a file. You can also either merge configuration or replace it entirely.
Replacing the Configuration
---------------------------

To replace the configuration do the following::

>>> device.load_replace_candidate(filename='test/unit/eos/new_good.conf')

Note that the changes have not been applied yet. Before applying the configuration you can actually check the changes::
Note that the changes have not been applied yet. Before applying the configuration you can check the changes::

>>> print device.compare_config()
+ hostname pyeos-unittest-changed
Expand Down Expand Up @@ -50,17 +51,10 @@ On the contrary, if you don't want the changes you can discard them::

>>> device.discard_config()

Rollback changes
----------------

If for some reason you committed the changes and you want to rollback::

>>> device.rollback()

Merging configuration
Merging Configuration
---------------------

Merging configuration is equally easy but you need to load the configuration with another method::
Merging configuration is similar, but you need to load the configuration with the merge method::

>>> device.load_merge_candidate(config='hostname test\ninterface Ethernet2\ndescription bla')
>>> print device.compare_config()
Expand All @@ -70,7 +64,18 @@ Merging configuration is equally easy but you need to load the configuration wit
description bla
end

We can commit and rollback the changes in the same way as before:
If you are happy with the changes you can commit them::

>>> device.commit_config()

On the contrary, if you don't want the changes you can discard them::

>>> device.discard_config()

Rollback Changes
----------------

If for some reason you committed the changes and you want to rollback::

>>> device.rollback()

7 changes: 7 additions & 0 deletions docs/tutorials/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Tutorials
=========

.. toctree::
:maxdepth: 1

first_steps_config
2 changes: 2 additions & 0 deletions napalm/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from iosxr import IOSXRDriver
from junos import JunOSDriver
from fortios import FortiOSDriver
from ibm import IBMDriver

def get_network_driver(vendor):
driver_mapping = {
Expand All @@ -26,6 +27,7 @@ def get_network_driver(vendor):
'JUNOS': JunOSDriver,
'JUNIPER': JunOSDriver,
'FORTIOS': FortiOSDriver,
'IBM': IBMDriver,
}
try:
return driver_mapping[vendor.upper()]
Expand Down
3 changes: 2 additions & 1 deletion napalm/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

class NetworkDriver:

def __init__(self, hostname, username, password):
def __init__(self, hostname, username, password, timeout):
"""
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
Expand All @@ -24,6 +24,7 @@ def __init__(self, hostname, username, password):
:param hostname: (str) IP or FQDN of the device you want to connect to.
:param username: (str) Username you want to use
:param password: (str) Password
:param timeout: (int) Time in seconds to wait for the device to respond.
:return:
"""
raise NotImplementedError
Expand Down
3 changes: 2 additions & 1 deletion napalm/eos.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,12 @@

class EOSDriver(NetworkDriver):

def __init__(self, hostname, username, password):
def __init__(self, hostname, username, password, timeout=60):
self.device = None
self.hostname = hostname
self.username = username
self.password = password
self.timeout = timeout
self.config_session = None

def open(self):
Expand Down

0 comments on commit 4fb77a9

Please sign in to comment.