├── test └── unit │ ├── requirements.txt │ └── TestGetNetworkDriver.py ├── MANIFEST.in ├── AUTHORS ├── static └── logo.png ├── pylama.ini ├── docs ├── tutorials │ ├── index.rst │ ├── context_manager.rst │ └── first_steps_config.rst ├── base.rst ├── support │ ├── fortios.rst │ ├── eos.rst │ ├── panos.rst │ ├── ibm.rst │ ├── ios.rst │ ├── nxos.rst │ └── index.rst ├── index.rst ├── cli.rst ├── Makefile └── conf.py ├── requirements.txt ├── .travis.yml ├── napalm └── __init__.py ├── .gitignore ├── setup.py ├── .github └── ISSUE_TEMPLATE ├── README.md └── LICENSE /test/unit/requirements.txt: -------------------------------------------------------------------------------- 1 | ddt 2 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include requirements.txt 2 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | David Barroso 2 | Elisa Jasinska 3 | -------------------------------------------------------------------------------- /static/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Netflix-Skunkworks/napalm/develop/static/logo.png -------------------------------------------------------------------------------- /pylama.ini: -------------------------------------------------------------------------------- 1 | [pylama] 2 | linters = mccabe,pep257,pep8,pyflakes 3 | ignore = D203, 4 | 5 | [pylama:pep8] 6 | max_line_length = 120 7 | -------------------------------------------------------------------------------- /docs/tutorials/index.rst: -------------------------------------------------------------------------------- 1 | Tutorials 2 | ========= 3 | 4 | .. toctree:: 5 | :maxdepth: 1 6 | 7 | first_steps_config 8 | context_manager 9 | -------------------------------------------------------------------------------- /docs/base.rst: -------------------------------------------------------------------------------- 1 | NetworkDriver 2 | ------------- 3 | 4 | .. autoclass:: napalm_base.base.NetworkDriver 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | napalm-base 2 | napalm-eos 3 | napalm-fortios 4 | napalm-ibm 5 | napalm-ios 6 | napalm-iosxr 7 | napalm-junos 8 | napalm-nxos 9 | napalm-pluribus 10 | napalm-panos 11 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: 3 | - 2.7 4 | install: 5 | - pip install -r requirements.txt 6 | - pip install -r test/unit/requirements.txt 7 | - pip install . 8 | deploy: 9 | provider: pypi 10 | user: dbarroso 11 | password: 12 | secure: kt2RgomUtrf5zXo3CyF8B7SkolvKgALAO0s72WuMd0wTGmgOvoBlt10Vfc+G+wuVAYvW/JKdsYRceancAFyWLFgjLtNxbV4cJF2RXN956sYFSJ2VrtUiB19WuKZjX6024gMs780hC/3bdK1SDg/NAAHSR7u2cma3QgRcW6O+UG4= 13 | on: 14 | tags: true 15 | branch: master 16 | script: 17 | - nosetests ./test/unit/TestGetNetworkDriver.py 18 | -------------------------------------------------------------------------------- /docs/support/fortios.rst: -------------------------------------------------------------------------------- 1 | FortiOS 2 | ------- 3 | 4 | Rollback 5 | ~~~~~~~~ 6 | 7 | To make sure the rollback feature works either use only this API to do changes or remember to save your rollback points on the CLI with the command:: 8 | 9 | execute backup config flash your_message 10 | 11 | Atomic Changes 12 | ~~~~~~~~~~~~~~ 13 | 14 | FortiOS' plugin will use the "batch" feature. All commands will not go at the same time but all of them will be processed. The sad true is that FortiOS doesn't have any proper tool to apply large chunks of configuration. -------------------------------------------------------------------------------- /test/unit/TestGetNetworkDriver.py: -------------------------------------------------------------------------------- 1 | """Test the method get_network_driver.""" 2 | 3 | 4 | import unittest 5 | from ddt import ddt, data, unpack 6 | 7 | from napalm_base import get_network_driver 8 | 9 | 10 | @ddt 11 | class TestGetNetworkDriver(unittest.TestCase): 12 | """Test the method get_network_driver.""" 13 | 14 | @data('eos', 'fortios', 'ibm', 'ios', 'iosxr', 'junos', 'nxos', 'pluribus') 15 | def test_get_network_driver(self, driver): 16 | """Check that we can get the desired driver.""" 17 | self.assertTrue(get_network_driver(driver)) 18 | -------------------------------------------------------------------------------- /docs/support/eos.rst: -------------------------------------------------------------------------------- 1 | EOS 2 | --- 3 | 4 | Minimum Version 5 | ~~~~~~~~~~~~~~~ 6 | 7 | 8 | To be able to support the ``compare_config`` method you will require to run at least EOS version `4.15.0F`. 9 | 10 | Rollback 11 | ~~~~~~~~ 12 | 13 | The rollback feature is supported only when committing from the API. In reality, what the API does during the commit operation is as follows:: 14 | 15 | copy startup-config flash:rollback-0 16 | 17 | And the rollback does:: 18 | 19 | configure replace flash:rollback-0 20 | 21 | This means that the rollback will be fine as long as you only use this library. If you are going to do changes outside this API don't forget to mark your last rollback point manually. 22 | -------------------------------------------------------------------------------- /napalm/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Spotify AB. All rights reserved. 2 | # 3 | # The contents of this file are licensed under the Apache License, Version 2.0 4 | # (the "License"); you may not use this file except in compliance with the 5 | # License. You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | # License for the specific language governing permissions and limitations under 13 | # the License. 14 | 15 | from napalm_base import get_network_driver 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | 5 | # C extensions 6 | *.so 7 | 8 | # Distribution / packaging 9 | .Python 10 | env/ 11 | bin/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | eggs/ 16 | lib/ 17 | lib64/ 18 | parts/ 19 | sdist/ 20 | var/ 21 | *.egg-info/ 22 | .installed.cfg 23 | *.egg 24 | 25 | # Installer logs 26 | pip-log.txt 27 | pip-delete-this-directory.txt 28 | 29 | # Unit test / coverage reports 30 | htmlcov/ 31 | .tox/ 32 | .coverage 33 | .cache 34 | nosetests.xml 35 | coverage.xml 36 | 37 | # Translations 38 | *.mo 39 | 40 | # Mr Developer 41 | .mr.developer.cfg 42 | .project 43 | .pydevproject 44 | 45 | # Rope 46 | .ropeproject 47 | 48 | # Django stuff: 49 | *.log 50 | *.pot 51 | 52 | # Sphinx documentation 53 | docs/_build/ 54 | 55 | .idea 56 | .DS_Store 57 | 58 | env 59 | *.swp 60 | 61 | test/unit/test_devices.py 62 | 63 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import uuid 2 | 3 | __author__ = 'David Barroso ' 4 | from setuptools import setup, find_packages 5 | from pip.req import parse_requirements 6 | 7 | 8 | install_reqs = parse_requirements('requirements.txt', session=uuid.uuid1()) 9 | reqs = [str(ir.req) for ir in install_reqs] 10 | 11 | setup( 12 | name="napalm", 13 | version="1.1.0", 14 | packages=find_packages(), 15 | author="David Barroso", 16 | author_email="dbarrosop@dravetech.com", 17 | description="Network Automation and Programmability Abstraction Layer with Multivendor support", 18 | classifiers=[ 19 | 'Topic :: Utilities', 20 | 'Programming Language :: Python', 21 | 'Programming Language :: Python :: 2', 22 | 'Programming Language :: Python :: 2.7', 23 | 'Operating System :: POSIX :: Linux', 24 | 'Operating System :: MacOS', 25 | ], 26 | url="https://github.com/napalm-automation/napalm", 27 | include_package_data=True, 28 | install_requires=reqs 29 | ) 30 | -------------------------------------------------------------------------------- /docs/support/panos.rst: -------------------------------------------------------------------------------- 1 | PANOS 2 | ----- 3 | 4 | 5 | Prerequisites 6 | _____________ 7 | 8 | PANOS has a Python interface called `pan-python`. Anyway, for some feature like sending multiple commands, `Netmiko` would be a best choice. 9 | That's why having Netmiko installed in your working box is a prerequisite. 10 | 11 | netmiko >= 0.5.0 12 | 13 | 14 | Replacing Configuration 15 | ________________________ 16 | 17 | Only configuration files are supported with `load_replace_candidate`. It must be a full XML file. 18 | Due to the OS nature, at this time we don't support a replace using a configuration string. 19 | 20 | 21 | Merging Configuration 22 | ________________________ 23 | 24 | Only configuration strings/lists are supported with `load_merge_candidate`. It can be a string or a list of strings in set-format. 25 | Due to the OS nature and the NAPALM structure, at this time we don't support a merge using a configuration file because it'd need additional parameters. This may be supported in the future. 26 | 27 | 28 | Atomic Changes 29 | ______________ 30 | 31 | Changes are atomic only when performing a configuration replace, since it's done with a single command. 32 | 33 | -------------------------------------------------------------------------------- /docs/support/ibm.rst: -------------------------------------------------------------------------------- 1 | IBM Networking Operating System 2 | ------------------------------- 3 | 4 | Rollback 5 | ~~~~~~~~ 6 | 7 | Rollback is simply implemented by reading current running configuration before any load actions. Rollback function executes load replace and commit. 8 | 9 | 10 | Atomic Changes 11 | ~~~~~~~~~~~~~~ 12 | 13 | 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 recommended for device in production. 14 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE: -------------------------------------------------------------------------------- 1 | 17 | 18 | ### Description of Issue/Question 19 | -------------------------------------------------------------------------------- /docs/tutorials/context_manager.rst: -------------------------------------------------------------------------------- 1 | Context Manager 2 | =============== 3 | 4 | In the previous tutorial we used the methods ``open()`` to connect to the device and ``close()`` to disconnect. 5 | Using those methods are useful if you want to do complex or asynchronous code. However, for most situations you should 6 | try to stick with the context manager. It handles opening and closing the session automatically and it's the 7 | pythonic way: 8 | 9 | .. code-block:: python 10 | 11 | >>> from napalm import get_network_driver 12 | >>> driver = get_network_driver('eos') 13 | >>> with driver('localhost', 'vagrant', 'vagrant', optional_args={'port': 12443}) as device: 14 | ... print device.get_facts() 15 | ... print device.get_interfaces_counters() 16 | ... 17 | {'os_version': u'4.15.2.1F-2759627.41521F', 'uptime': 2010, 'interface_list': [u'Ethernet1', u'Ethernet2', u'Management1'], 'vendor': u'Arista', 'serial_number': u'', 'model': u'vEOS', 'hostname': u'NEWHOSTNAME', 'fqdn': u'NEWHOSTNAME'} 18 | {u'Ethernet2': {'tx_multicast_packets': 1028, 'tx_discards': 0, 'tx_octets': 130744, 'tx_errors': 0, 'rx_octets': 0, 'tx_unicast_packets': 0, 'rx_errors': 0, 'tx_broadcast_packets': 0, 'rx_multicast_packets': 0, 'rx_broadcast_packets': 0, 'rx_discards': 0, 'rx_unicast_packets': 0}, u'Management1': {'tx_multicast_packets': 0, 'tx_discards': 0, 'tx_octets': 99664, 'tx_errors': 0, 'rx_octets': 105000, 'tx_unicast_packets': 773, 'rx_errors': 0, 'tx_broadcast_packets': 0, 'rx_multicast_packets': 0, 'rx_broadcast_packets': 0, 'rx_discards': 0, 'rx_unicast_packets': 0}, u'Ethernet1': {'tx_multicast_packets': 1027, 'tx_discards': 0, 'tx_octets': 130077, 'tx_errors': 0, 'rx_octets': 0, 'tx_unicast_packets': 0, 'rx_errors': 0, 'tx_broadcast_packets': 0, 'rx_multicast_packets': 0, 'rx_broadcast_packets': 0, 'rx_discards': 0, 'rx_unicast_packets': 0}} 19 | -------------------------------------------------------------------------------- /docs/support/ios.rst: -------------------------------------------------------------------------------- 1 | IOS 2 | --- 3 | 4 | 5 | Prerequisites 6 | _____________ 7 | 8 | IOS has no native API to play with, that's the reason why we used the Netmiko library to interact with it. 9 | Having Netmiko installed in your working box is a prerequisite. 10 | 11 | netmiko >= 0.3.0 12 | 13 | Full ios driver support requires configuration rollback on error:: 14 | 15 | Cisco IOS requirements for 'Configuration Rollback Confirmed Change' feature. 16 | 12.2(33)SRC 17 | 12.2(33)SB 18 | 12.4(20)T 19 | 12.2(33)SXI 20 | 21 | 22 | Downgraded ios driver support (i.e. no auto rollback on configuration error for replace operation):: 23 | 24 | Cisco IOS requirements for 'Configuration Replace and Configuration Rollback' feature. 25 | 12.3(7)T 26 | 12.2(25)S 27 | 12.3(14)T 28 | 12.2(27)SBC 29 | 12.2(31)SB2 30 | 12.2(33)SRA 31 | 12.2(33)SXH 32 | 12.2(33)SB 33 | 34 | 35 | Note, to disable auto rollback you must add the `auto_rollback_on_error=False` optional argument. 36 | 37 | 38 | 39 | Archive 40 | _______ 41 | 42 | IOSDriver requires that the `archive` functionality be enabled to perform auto-rollback on error. Make sure it's enabled and set to local on device flash/hdd:: 43 | 44 | archive 45 | path bootflash:archive 46 | write-memory 47 | 48 | 49 | Configuration file 50 | ------------------ 51 | 52 | IOS requires config file to begin with a `version` eg. `15.0` and `end` marker at the end of the file. Otherwise IOS will reject `configure replace` operation. 53 | 54 | 55 | Notes 56 | _______ 57 | 58 | * Will automatically enable secure copy ('ip scp server enable') on the network device. This is a configuration change. 59 | 60 | * During various operations, NAPALM ios driver will turn off the prompting for confirmations (`file prompt quiet`). It should re-enable prompting before exiting the device (`no file prompt quiet`). 61 | 62 | * `write mem` is not performed on the device. Consequently, commit() commits the config to running-config, but does not save it to start-config. 63 | 64 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | .. napalm documentation master file, created by 2 | sphinx-quickstart on Tue March 26 12:11:44 2015. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Welcome to NAPALM's documentation! 7 | ================================== 8 | 9 | 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. 10 | 11 | NAPALM supports several methods to connect to the devices, to manipulate configurations or to retrieve data. 12 | 13 | Supported Network Operating Systems: 14 | ------------------------------------ 15 | 16 | * eos 17 | * junos 18 | * iosxr 19 | * fortios 20 | * ibm 21 | * nxos 22 | * ios 23 | * pluribus 24 | * panos 25 | 26 | You can select the driver you need by doing the following: 27 | 28 | .. code-block:: python 29 | 30 | >>> from napalm import get_network_driver 31 | >>> get_network_driver('eos') 32 | 33 | >>> get_network_driver('iosxr') 34 | 35 | >>> get_network_driver('junos') 36 | 37 | >>> get_network_driver('fortios') 38 | 39 | >>> get_network_driver('ibm') 40 | 41 | >>> get_network_driver('nxos') 42 | 43 | >>> get_network_driver('ios') 44 | 45 | >>> get_network_driver('pluribus') 46 | 47 | 48 | 49 | Check the tutorials to see how to use the library in more detail, Supported Devices will provide you with detailed support information and caveats and the NetworkDriver section explains which methods are available for you to use. 50 | 51 | Documentation 52 | ============= 53 | 54 | .. toctree:: 55 | :maxdepth: 2 56 | 57 | tutorials/index 58 | support/index 59 | cli 60 | base 61 | -------------------------------------------------------------------------------- /docs/support/nxos.rst: -------------------------------------------------------------------------------- 1 | NXOS 2 | ---- 3 | 4 | Notes on configuration replacement 5 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 6 | 7 | 8 | 9 | Config files aren't aren't normal config files but special "checkpoint" files. 10 | That's because on NXOS the only way to replace a config without reboot is to rollback to a checkpoint (which could be a file). 11 | These files explicitly list a lot of normally implicit config lines, some of them starting with ``!#``. 12 | The ``!#`` part isn't necessary for the rollback to work, but leaving these lines out can cause erratic behavior. 13 | See the "Known gotchas" section below. 14 | 15 | Prerequisites 16 | _____________ 17 | 18 | Your device must be running NXOS 6.1. The features ``nxapi`` server ``scp-server`` must be enabled. 19 | On the device and any checkpoint file you push, you must have the lines:: 20 | 21 | feature scp-server 22 | feature nxapi 23 | 24 | 25 | Getting a base checkpoint file 26 | ______________________________ 27 | 28 | An example of a checkpoint file can be seen in ``test/unit/nxos/new_good.conf``. 29 | You can get a checkpoint file representing your device's current config by running the ``get_checkpoint_file()`` 30 | function in the ``napalm.nxos`` driver. 31 | 32 | Known gotchas 33 | _____________ 34 | 35 | - Leaving out a ``shutdown`` or ``no shutdown`` line will cause the switch to toggle the up/down state of an interface, depending on it's current state. 36 | 37 | - ``!#switchport trunk allowed vlan 1-4094`` is required even if the switchport is in ``switchport mode access``. However if ``!#switchport trunk allowed vlan 1-4094`` is included with ``no switchport``, the configuration replacement will fail. 38 | 39 | - Vlans are listed vertically. For example ``vlan 1, 10, 20, 30`` will fail. To succeed, you need: 40 | :: 41 | 42 | vlan 1 43 | vlan 10 44 | vlan 20 45 | vlan 30 46 | 47 | Diffs 48 | _____ 49 | 50 | Diffs for config replacement are a list of commands that would be needed to take the device from it's current state 51 | to the desired config state. See ``test/unit/nxos/new_good.diff`` as an example. 52 | 53 | Notes on configuration merging 54 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 55 | 56 | Merges are currently implemented by simply applying the the merge config line by line. 57 | This doesn't use the checkpoint/rollback functionality. 58 | As a result, merges are **not atomic**. 59 | 60 | Diffs 61 | _____ 62 | 63 | Diffs for merges are simply the lines in the merge candidate config. 64 | -------------------------------------------------------------------------------- /docs/tutorials/first_steps_config.rst: -------------------------------------------------------------------------------- 1 | First Steps Manipulating Config 2 | =============================== 3 | 4 | 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 `_, which in turn allows you to manage a set of devices independent of their network OS. 5 | 6 | Connecting to the Device 7 | ------------------------ 8 | 9 | Use the appropriate network driver to connect to the device:: 10 | 11 | >>> from napalm import get_network_driver 12 | >>> driver = get_network_driver('eos') 13 | >>> device = driver('192.168.76.10', 'dbarroso', 'this_is_not_a_secure_password') 14 | >>> device.open() 15 | 16 | Configurations can be replaced entirely or merged into the existing device config. 17 | You can load configuration either from a string or from a file. 18 | 19 | Replacing the Configuration 20 | --------------------------- 21 | 22 | To replace the configuration do the following:: 23 | 24 | >>> device.load_replace_candidate(filename='test/unit/eos/new_good.conf') 25 | 26 | Note that the changes have not been applied yet. Before applying the configuration you can check the changes:: 27 | 28 | >>> print device.compare_config() 29 | + hostname pyeos-unittest-changed 30 | - hostname pyeos-unittest 31 | router bgp 65000 32 | vrf test 33 | + neighbor 1.1.1.2 maximum-routes 12000 34 | + neighbor 1.1.1.2 remote-as 1 35 | - neighbor 1.1.1.1 remote-as 1 36 | - neighbor 1.1.1.1 maximum-routes 12000 37 | vrf test2 38 | + neighbor 2.2.2.3 remote-as 2 39 | + neighbor 2.2.2.3 maximum-routes 12000 40 | - neighbor 2.2.2.2 remote-as 2 41 | - neighbor 2.2.2.2 maximum-routes 12000 42 | interface Ethernet2 43 | + description ble 44 | - description bla 45 | 46 | If you are happy with the changes you can commit them:: 47 | 48 | >>> device.commit_config() 49 | 50 | On the contrary, if you don't want the changes you can discard them:: 51 | 52 | >>> device.discard_config() 53 | 54 | Merging Configuration 55 | --------------------- 56 | 57 | Merging configuration is similar, but you need to load the configuration with the merge method:: 58 | 59 | >>> device.load_merge_candidate(config='hostname test\ninterface Ethernet2\ndescription bla') 60 | >>> print device.compare_config() 61 | configure 62 | hostname test 63 | interface Ethernet2 64 | description bla 65 | end 66 | 67 | If you are happy with the changes you can commit them:: 68 | 69 | >>> device.commit_config() 70 | 71 | On the contrary, if you don't want the changes you can discard them:: 72 | 73 | >>> device.discard_config() 74 | 75 | Rollback Changes 76 | ---------------- 77 | 78 | If for some reason you committed the changes and you want to rollback:: 79 | 80 | >>> device.rollback() 81 | 82 | Disconnecting 83 | ------------- 84 | 85 | To close the session with the device just do:: 86 | 87 | >>> device.close() 88 | -------------------------------------------------------------------------------- /docs/cli.rst: -------------------------------------------------------------------------------- 1 | Command Line Tool 2 | ================= 3 | 4 | NAPALM ships with a simple CLI tool to help you deploying configuration to your devices directly from the shell. 5 | It might be convenient for simple bash scripts or provisioning tools that rely on a shell. 6 | 7 | The usage is very simple. For example, let's do a dry run (changes will not be applied) and check the changes between 8 | my current configuration and a new candidate configuration: 9 | 10 | .. code-block:: diff 11 | 12 | # cl_napalm_configure --user vagrant --vendor eos --strategy replace --optional_args 'port=12443' --dry-run new_good.conf localhost 13 | Enter password: 14 | @@ -2,30 +2,38 @@ 15 | ! 16 | ! boot system flash:/vEOS-lab.swi 17 | ! 18 | -event-handler dhclient 19 | - trigger on-boot 20 | - action bash sudo /mnt/flash/initialize_ma1.sh 21 | +transceiver qsfp default-mode 4x10G 22 | ! 23 | -transceiver qsfp default-mode 4x10G 24 | +hostname pyeos-unittest-changed 25 | ! 26 | spanning-tree mode mstp 27 | ! 28 | aaa authorization exec default local 29 | ! 30 | -aaa root secret 5 $1$b4KXboe4$yeTwqHOKscsF07WGoOnZ0. 31 | +no aaa root 32 | ! 33 | -username admin privilege 15 role network-admin secret 5 $1$nT3t1LkI$1f.SG5YaRo6h4LlhIKgTK. 34 | -username vagrant privilege 15 role network-admin secret 5 $1$589CDTZ0$9S4LGAiCpxHCOC17jECxt1 35 | +username admin privilege 15 role network-admin secret 5 $1$RT/92Zg9$J8wD1qPAdQBcOhv4fefyt. 36 | +username vagrant privilege 15 role network-admin secret 5 $1$Lw2STh4k$bPEDVVTY2e7lf.vNlnNEO0 37 | ! 38 | interface Ethernet1 39 | ! 40 | interface Ethernet2 41 | + description ble 42 | ! 43 | interface Management1 44 | ip address 10.0.2.15/24 45 | ! 46 | no ip routing 47 | ! 48 | +router bgp 65000 49 | + vrf test 50 | + neighbor 1.1.1.2 remote-as 1 51 | + neighbor 1.1.1.2 maximum-routes 12000 52 | + ! 53 | + vrf test2 54 | + neighbor 2.2.2.3 remote-as 2 55 | + neighbor 2.2.2.3 maximum-routes 12000 56 | +! 57 | management api http-commands 58 | no shutdown 59 | ! 60 | # 61 | 62 | We got the diff back. Now let's try a partial configuration instead. However, this time we will directly apply the 63 | configuration and we will also be passing the password directly as an argument: 64 | 65 | .. code-block:: diff 66 | 67 | # cl_napalm_configure --user vagrant --password vagrant --vendor eos --strategy merge --optional_args 'port=12443' merge_good.conf localhost 68 | @@ -7,6 +7,8 @@ 69 | action bash sudo /mnt/flash/initialize_ma1.sh 70 | ! 71 | transceiver qsfp default-mode 4x10G 72 | +! 73 | +hostname NEWHOSTNAME 74 | ! 75 | spanning-tree mode mstp 76 | ! 77 | @@ -20,6 +22,7 @@ 78 | interface Ethernet1 79 | ! 80 | interface Ethernet2 81 | + description BLALALAL 82 | ! 83 | interface Management1 84 | ip address 10.0.2.15/24 85 | # 86 | 87 | We got the diff back in the stdout. If we try to run the command we should get an empty string: 88 | 89 | .. code-block:: diff 90 | 91 | # cl_napalm_configure --user vagrant --password vagrant --vendor eos --strategy merge --optional_args 'port=12443' merge_good.conf localhost 92 | # 93 | 94 | Errors are detected as well:: 95 | 96 | # cl_napalm_configure --user vagrant --password vagrant --vendor eos --strategy merge --optional_args 'port=12443' merge_typo.conf localhost 97 | Traceback (most recent call last): 98 | File "/Users/dbarroso/.virtualenvs/test/bin/cl_napalm_configure", line 9, in 99 | load_entry_point('napalm==0.50.3', 'console_scripts', 'cl_napalm_configure')() 100 | File "/Users/dbarroso/.virtualenvs/test/lib/python2.7/site-packages/napalm-0.50.3-py2.7.egg/napalm/clitools/cl_napalm_configure.py", line 139, in main 101 | args.optional_args, args.config_file, args.dry_run)) 102 | File "/Users/dbarroso/.virtualenvs/test/lib/python2.7/site-packages/napalm-0.50.3-py2.7.egg/napalm/clitools/cl_napalm_configure.py", line 131, in run 103 | return diff 104 | File "/Users/dbarroso/.virtualenvs/test/lib/python2.7/site-packages/napalm-0.50.3-py2.7.egg/napalm/base.py", line 46, in __exit__ 105 | self.__raise_clean_exception(exc_type, exc_value, exc_traceback) 106 | File "/Users/dbarroso/.virtualenvs/test/lib/python2.7/site-packages/napalm-0.50.3-py2.7.egg/napalm/clitools/cl_napalm_configure.py", line 119, in run 107 | strategy_method(filename=config_file) 108 | File "/Users/dbarroso/.virtualenvs/test/lib/python2.7/site-packages/napalm-0.50.3-py2.7.egg/napalm/eos.py", line 95, in load_merge_candidate 109 | self._load_config(filename, config, False) 110 | File "/Users/dbarroso/.virtualenvs/test/lib/python2.7/site-packages/napalm-0.50.3-py2.7.egg/napalm/eos.py", line 89, in _load_config 111 | raise MergeConfigException(e.message) 112 | napalm.exceptions.MergeConfigException: Error [1002]: CLI command 5 of 5 'descriptin BLALALAL' failed: invalid command 113 | 114 | For more information, run ``cl_napalm_configure --help``. 115 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | PAPER = 8 | BUILDDIR = _build 9 | 10 | # User-friendly check for sphinx-build 11 | ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) 12 | $(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) 13 | endif 14 | 15 | # Internal variables. 16 | PAPEROPT_a4 = -D latex_paper_size=a4 17 | PAPEROPT_letter = -D latex_paper_size=letter 18 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 19 | # the i18n builder cannot share the environment and doctrees with the others 20 | I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 21 | 22 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext 23 | 24 | help: 25 | @echo "Please use \`make ' where is one of" 26 | @echo " html to make standalone HTML files" 27 | @echo " dirhtml to make HTML files named index.html in directories" 28 | @echo " singlehtml to make a single large HTML file" 29 | @echo " pickle to make pickle files" 30 | @echo " json to make JSON files" 31 | @echo " htmlhelp to make HTML files and a HTML help project" 32 | @echo " qthelp to make HTML files and a qthelp project" 33 | @echo " devhelp to make HTML files and a Devhelp project" 34 | @echo " epub to make an epub" 35 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 36 | @echo " latexpdf to make LaTeX files and run them through pdflatex" 37 | @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" 38 | @echo " text to make text files" 39 | @echo " man to make manual pages" 40 | @echo " texinfo to make Texinfo files" 41 | @echo " info to make Texinfo files and run them through makeinfo" 42 | @echo " gettext to make PO message catalogs" 43 | @echo " changes to make an overview of all changed/added/deprecated items" 44 | @echo " xml to make Docutils-native XML files" 45 | @echo " pseudoxml to make pseudoxml-XML files for display purposes" 46 | @echo " linkcheck to check all external links for integrity" 47 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 48 | 49 | clean: 50 | rm -rf $(BUILDDIR)/* 51 | 52 | html: 53 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 54 | @echo 55 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 56 | 57 | dirhtml: 58 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml 59 | @echo 60 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." 61 | 62 | singlehtml: 63 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml 64 | @echo 65 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." 66 | 67 | pickle: 68 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle 69 | @echo 70 | @echo "Build finished; now you can process the pickle files." 71 | 72 | json: 73 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json 74 | @echo 75 | @echo "Build finished; now you can process the JSON files." 76 | 77 | htmlhelp: 78 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp 79 | @echo 80 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 81 | ".hhp project file in $(BUILDDIR)/htmlhelp." 82 | 83 | qthelp: 84 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp 85 | @echo 86 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 87 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:" 88 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/napalm.qhcp" 89 | @echo "To view the help file:" 90 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/napalm.qhc" 91 | 92 | devhelp: 93 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp 94 | @echo 95 | @echo "Build finished." 96 | @echo "To view the help file:" 97 | @echo "# mkdir -p $$HOME/.local/share/devhelp/napalm" 98 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/napalm" 99 | @echo "# devhelp" 100 | 101 | epub: 102 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub 103 | @echo 104 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub." 105 | 106 | latex: 107 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 108 | @echo 109 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." 110 | @echo "Run \`make' in that directory to run these through (pdf)latex" \ 111 | "(use \`make latexpdf' here to do that automatically)." 112 | 113 | latexpdf: 114 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 115 | @echo "Running LaTeX files through pdflatex..." 116 | $(MAKE) -C $(BUILDDIR)/latex all-pdf 117 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 118 | 119 | latexpdfja: 120 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 121 | @echo "Running LaTeX files through platex and dvipdfmx..." 122 | $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja 123 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 124 | 125 | text: 126 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text 127 | @echo 128 | @echo "Build finished. The text files are in $(BUILDDIR)/text." 129 | 130 | man: 131 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man 132 | @echo 133 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man." 134 | 135 | texinfo: 136 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 137 | @echo 138 | @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." 139 | @echo "Run \`make' in that directory to run these through makeinfo" \ 140 | "(use \`make info' here to do that automatically)." 141 | 142 | info: 143 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 144 | @echo "Running Texinfo files through makeinfo..." 145 | make -C $(BUILDDIR)/texinfo info 146 | @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." 147 | 148 | gettext: 149 | $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale 150 | @echo 151 | @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." 152 | 153 | changes: 154 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes 155 | @echo 156 | @echo "The overview file is in $(BUILDDIR)/changes." 157 | 158 | linkcheck: 159 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck 160 | @echo 161 | @echo "Link check complete; look for any errors in the above output " \ 162 | "or in $(BUILDDIR)/linkcheck/output.txt." 163 | 164 | doctest: 165 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest 166 | @echo "Testing of doctests in the sources finished, look at the " \ 167 | "results in $(BUILDDIR)/doctest/output.txt." 168 | 169 | xml: 170 | $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml 171 | @echo 172 | @echo "Build finished. The XML files are in $(BUILDDIR)/xml." 173 | 174 | pseudoxml: 175 | $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml 176 | @echo 177 | @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." 178 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![PyPI](https://img.shields.io/pypi/v/napalm.svg)](https://pypi.python.org/pypi/napalm) 2 | [![PyPI](https://img.shields.io/pypi/dm/napalm.svg)](https://pypi.python.org/pypi/napalm) 3 | [![Build Status](https://travis-ci.org/napalm-automation/napalm.svg?branch=master)](https://travis-ci.org/napalm-automation/napalm) 4 | 5 | 6 | NAPALM 7 | ====== 8 | 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. 9 | 10 | ![NAPALM logo](static/logo.png?raw=true "NAPALM logo") 11 | 12 | NAPALM supports several methods to connect to the devices, to manipulate configurations or to retrieve data. 13 | 14 | Supported Network Operating Systems 15 | ----------------------------------- 16 | 17 | Please check the following [link](https://napalm.readthedocs.io/en/latest/support/index.html) to see which devices are supported. Make sure you understand the [caveats](https://napalm.readthedocs.io/en/latest/support/index.html#caveats). 18 | 19 | Documentation 20 | ============= 21 | 22 | Before using the library, please read the documentation at: [Read the Docs](https://napalm.readthedocs.io) 23 | 24 | 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. 25 | 26 | Install 27 | ======= 28 | 29 | Full installation 30 | ----------------- 31 | 32 | If you want to fully install NAPALM you can do it by executing: 33 | 34 | ``` 35 | pip install napalm 36 | ``` 37 | 38 | That will install all the drivers currently available. 39 | 40 | 41 | Partial Installation 42 | -------------------- 43 | 44 | If you want to install just a subset of the available modules you can just pick them as follows: 45 | 46 | ``` 47 | pip install napalm-eos napalm-junos 48 | ``` 49 | 50 | That will install only the `eos` and the `junos` drivers. If you want to remove or add a module later on you can just use `pip` to do it: 51 | 52 | ``` 53 | pip uninstall napalm-junos 54 | pip install napalm-ios 55 | ``` 56 | 57 | Check the ['Supported Network Operating Systems'](#supported-network-operating-systems) section for more information about supported modules. 58 | 59 | Upgrading 60 | ========= 61 | 62 | We plan to upgrade napalm as fast as possible. Adding new methods and bugfixes. To upgrade napalm it's a simple as repeating the steps you performed while installing but adding the `-U` flag. For example: 63 | 64 | ``` 65 | pip install napalm -U 66 | ``` 67 | 68 | or: 69 | 70 | ``` 71 | pip install napalm-eos napalm-junos -U 72 | ``` 73 | 74 | We will be posting news on our slack channel and on Twitter (more details soon). 75 | 76 | Automation Frameworks 77 | ====================== 78 | 79 | Due to its flexibility, NAPALM can be integrated in widely used automation frameworks. 80 | 81 | Ansible 82 | ------- 83 | 84 | Please check [napalm-ansible](https://github.com/napalm-automation/napalm-ansible) for existing Ansible modules leveraging the NAPALM API. Make sure you read the documentation and you understand how it works before trying to use it. 85 | 86 | Salt 87 | ---- 88 | 89 | NAPALM will be completely integrated in [Salt](https://saltstack.com/) beginning with the release code named `Carbon`. For usage examples, please check [naplam-salt](https://github.com/napalm-automation/napalm-salt). 90 | 91 | 92 | Contact 93 | ======= 94 | 95 | Mailing List 96 | ------------ 97 | 98 | 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) 99 | 100 | Slack 101 | ----- 102 | 103 | Slack is probably the easiest way to get help with NAPALM. You can find us in the channel `napalm` on the [network.toCode()](https://networktocode.herokuapp.com/) team. 104 | 105 | FAQ 106 | --- 107 | 108 | If you have any issues using NAPALM or encounter any errors, before submitting any questions (directly by email or on Slack), please go through the following checklist: 109 | 110 | - Double or triple check if you indeed are able to access the device using the credentials provided. 111 | - Does your device meet the minimum [requrirements](http://napalm.readthedocs.io/en/latest/support/index.html#general-support-matrix)? 112 | - Some operating systems have some specific [constraints](http://napalm.readthedocs.io/en/latest/support/index.html#caveats). (e.g. have you enabled the XML agent on IOS-XR, or the NXAPI feature on NXOS?) 113 | - Are you able to connect to the device using NAPALM? Check using the CLI test tool: 114 | 115 | ```bash 116 | $ cl_napalm_test --vendor VENDOR --user USERNAME --password PASSWORD --optional_args OPTIONAL_ARGS HOSTNAME 117 | ``` 118 | 119 | Where vendor, username, password and hostname are mandatory. [Optional arguments](http://napalm.readthedocs.io/en/latest/support/index.html#optional-arguments) are specified as comma separated values. 120 | 121 | Example: 122 | 123 | ```bash 124 | $ cl_napalm_test --vendor junos --user napalm --password dbejmujz --optional_args 'port=12202, config_lock=False' edge01.bjm01 125 | ``` 126 | 127 | In case you have any errors, please review the steps above - this looks like a problem with your environment setup. 128 | 129 | In order to get help faster, when submitting a bug/error make sure to include all the details requested. 130 | 131 | News 132 | ==== 133 | 134 | Blog Posts 135 | ---------- 136 | 137 | * [NAPALM, Ansible, and Cisco IOS](https://pynet.twb-tech.com/blog/automation/napalm-ios.html) by Kirk Byers 138 | * [Adding Cisco IOS support to NAPALM (Network Automation and Programmability Abstraction Layer with Multivendor support)](https://projectme10.wordpress.com/2015/12/07/adding-cisco-ios-support-to-napalm-network-automation-and-programmability-abstraction-layer-with-multivendor-support/) by Gabriele Gerbino 139 | 140 | Presentations 141 | ------------- 142 | 143 | * [NANOG 64 Presentation & Demo](https://youtu.be/93q-dHC0u0I) by David Barroso and Elisa Jasinska 144 | * [Netnod Autumn Meeting 2015 Presentation](https://www.netnod.se/sites/default/files/NAPALM-david_barroso-Netnodautumnmeeting2015.pdf) by David Barroso 145 | * [Automating IXP Device Configurations with Ansible at the Euro-IX Forum](https://www.euro-ix.net/m/uploads/2015/10/26/euroix-berlin-v2.pdf) by Elisa Jasinska 146 | * [Network Automation with Salt and NAPALM at RIPE 72](https://ripe72.ripe.net/presentations/58-RIPE72-Network-Automation-with-Salt-and-NAPALM-Mircea-Ulinic-CloudFlare.pdf); [video](https://ripe72.ripe.net/archives/video/121/) by Mircea Ulinic 147 | 148 | Podcasts 149 | -------- 150 | 151 | * [NAPALM: Integrating Ansible with Network Devices on Software Gone Wild](http://blog.ipspace.net/2015/06/napalm-integrating-ansible-with-network.html) with David Barroso and Elisa Jasinska 152 | 153 | Authors 154 | ======= 155 | * David Barroso ([dbarrosop@dravetech.com](mailto:dbarroso@dravetech.com)) 156 | * Elisa Jasinska ([elisa@bigwaveit.org](mailto:elisa@bigwaveit.org)) 157 | * Many others, check the [contributors](https://github.com/napalm-automation/napalm/graphs/contributors) page for details. 158 | 159 | 160 | Thanks 161 | ====== 162 | 163 | This project was founded by David Barroso as part of [Spotify][spotify] and Elisa Jasinska as part of [BigWave IT][bigwave]. Originally it was hosted by the [Spotify][spotify] organization but due to the many contributions received by third parties we agreed creating a dedicated organization for NAPALM and give a big thanks to [Spotify][spotify] for the support. 164 | 165 | [spotify]: http://www.spotify.com 166 | [bigwave]: http://bigwaveit.org/ 167 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # napalm documentation build configuration file, created by 4 | # sphinx-quickstart on Tue Dec 16 13:17:14 2014. 5 | # 6 | # This file is execfile()d with the current directory set to its 7 | # containing dir. 8 | # 9 | # Note that not all possible configuration values are present in this 10 | # autogenerated file. 11 | # 12 | # All configuration values have a default; values that are commented out 13 | # serve to show the default. 14 | 15 | import sys 16 | import os 17 | 18 | # If extensions (or modules to document with autodoc) are in another directory, 19 | # add these directories to sys.path here. If the directory is relative to the 20 | # documentation root, use os.path.abspath to make it absolute, like shown here. 21 | sys.path.insert(0, os.path.abspath('../')) 22 | 23 | # -- General configuration ------------------------------------------------ 24 | 25 | # If your documentation needs a minimal Sphinx version, state it here. 26 | #needs_sphinx = '1.0' 27 | 28 | autoclass_content = 'both' 29 | 30 | # Add any Sphinx extension module names here, as strings. They can be 31 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 32 | # ones. 33 | extensions = [ 34 | 'sphinx.ext.autodoc', 35 | ] 36 | 37 | # Add any paths that contain templates here, relative to this directory. 38 | templates_path = ['_templates'] 39 | 40 | # The suffix of source filenames. 41 | source_suffix = '.rst' 42 | 43 | # The encoding of source files. 44 | #source_encoding = 'utf-8-sig' 45 | 46 | # The master toctree document. 47 | master_doc = 'index' 48 | 49 | # General information about the project. 50 | project = u'NAPALM' 51 | copyright = u'2016, David Barroso' 52 | 53 | # The version info for the project you're documenting, acts as replacement for 54 | # |version| and |release|, also used in various other places throughout the 55 | # built documents. 56 | # 57 | # The short X.Y version. 58 | version = '0' 59 | # The full version, including alpha/beta/rc tags. 60 | release = '1' 61 | 62 | # The language for content autogenerated by Sphinx. Refer to documentation 63 | # for a list of supported languages. 64 | #language = None 65 | 66 | # There are two options for replacing |today|: either, you set today to some 67 | # non-false value, then it is used: 68 | #today = '' 69 | # Else, today_fmt is used as the format for a strftime call. 70 | #today_fmt = '%B %d, %Y' 71 | 72 | # List of patterns, relative to source directory, that match files and 73 | # directories to ignore when looking for source files. 74 | exclude_patterns = ['_build'] 75 | 76 | # The reST default role (used for this markup: `text`) to use for all 77 | # documents. 78 | #default_role = None 79 | 80 | # If true, '()' will be appended to :func: etc. cross-reference text. 81 | #add_function_parentheses = True 82 | 83 | # If true, the current module name will be prepended to all description 84 | # unit titles (such as .. function::). 85 | #add_module_names = True 86 | 87 | # If true, sectionauthor and moduleauthor directives will be shown in the 88 | # output. They are ignored by default. 89 | #show_authors = False 90 | 91 | # The name of the Pygments (syntax highlighting) style to use. 92 | pygments_style = 'sphinx' 93 | 94 | # A list of ignored prefixes for module index sorting. 95 | #modindex_common_prefix = [] 96 | 97 | # If true, keep warnings as "system message" paragraphs in the built documents. 98 | #keep_warnings = False 99 | 100 | 101 | # -- Options for HTML output ---------------------------------------------- 102 | 103 | # The theme to use for HTML and HTML Help pages. See the documentation for 104 | # a list of builtin themes. 105 | on_rtd = os.environ.get('READTHEDOCS', None) == 'True' 106 | 107 | if not on_rtd: # only import and set the theme if we're building docs locally 108 | import sphinx_rtd_theme 109 | html_theme = 'sphinx_rtd_theme' 110 | html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] 111 | else: 112 | html_theme = 'default' 113 | 114 | # Theme options are theme-specific and customize the look and feel of a theme 115 | # further. For a list of options available for each theme, see the 116 | # documentation. 117 | #html_theme_options = {} 118 | 119 | # Add any paths that contain custom themes here, relative to this directory. 120 | #html_theme_path = [] 121 | 122 | # The name for this set of Sphinx documents. If None, it defaults to 123 | # " v documentation". 124 | #html_title = None 125 | 126 | # A shorter title for the navigation bar. Default is the same as html_title. 127 | #html_short_title = None 128 | 129 | # The name of an image file (relative to this directory) to place at the top 130 | # of the sidebar. 131 | #html_logo = None 132 | 133 | # The name of an image file (within the static path) to use as favicon of the 134 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 135 | # pixels large. 136 | #html_favicon = None 137 | 138 | # Add any paths that contain custom static files (such as style sheets) here, 139 | # relative to this directory. They are copied after the builtin static files, 140 | # so a file named "default.css" will overwrite the builtin "default.css". 141 | html_static_path = ['_static'] 142 | 143 | # Add any extra paths that contain custom files (such as robots.txt or 144 | # .htaccess) here, relative to this directory. These files are copied 145 | # directly to the root of the documentation. 146 | #html_extra_path = [] 147 | 148 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, 149 | # using the given strftime format. 150 | #html_last_updated_fmt = '%b %d, %Y' 151 | 152 | # If true, SmartyPants will be used to convert quotes and dashes to 153 | # typographically correct entities. 154 | #html_use_smartypants = True 155 | 156 | # Custom sidebar templates, maps document names to template names. 157 | #html_sidebars = {} 158 | 159 | # Additional templates that should be rendered to pages, maps page names to 160 | # template names. 161 | #html_additional_pages = {} 162 | 163 | # If false, no module index is generated. 164 | #html_domain_indices = True 165 | 166 | # If false, no index is generated. 167 | #html_use_index = True 168 | 169 | # If true, the index is split into individual pages for each letter. 170 | #html_split_index = False 171 | 172 | # If true, links to the reST sources are added to the pages. 173 | #html_show_sourcelink = True 174 | 175 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. 176 | #html_show_sphinx = True 177 | 178 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. 179 | #html_show_copyright = True 180 | 181 | # If true, an OpenSearch description file will be output, and all pages will 182 | # contain a tag referring to it. The value of this option must be the 183 | # base URL from which the finished HTML is served. 184 | #html_use_opensearch = '' 185 | 186 | # This is the file name suffix for HTML files (e.g. ".xhtml"). 187 | #html_file_suffix = None 188 | 189 | # Output file base name for HTML help builder. 190 | htmlhelp_basename = 'napalmdoc' 191 | 192 | 193 | # -- Options for LaTeX output --------------------------------------------- 194 | 195 | latex_elements = { 196 | # The paper size ('letterpaper' or 'a4paper'). 197 | #'papersize': 'letterpaper', 198 | 199 | # The font size ('10pt', '11pt' or '12pt'). 200 | #'pointsize': '10pt', 201 | 202 | # Additional stuff for the LaTeX preamble. 203 | #'preamble': '', 204 | } 205 | 206 | # Grouping the document tree into LaTeX files. List of tuples 207 | # (source start file, target name, title, 208 | # author, documentclass [howto, manual, or own class]). 209 | latex_documents = [ 210 | ('index', 'napalm.tex', u'NAPALM Documentation', 211 | u'David Barroso', 'manual'), 212 | ] 213 | 214 | # The name of an image file (relative to this directory) to place at the top of 215 | # the title page. 216 | #latex_logo = None 217 | 218 | # For "manual" documents, if this is true, then toplevel headings are parts, 219 | # not chapters. 220 | #latex_use_parts = False 221 | 222 | # If true, show page references after internal links. 223 | #latex_show_pagerefs = False 224 | 225 | # If true, show URL addresses after external links. 226 | #latex_show_urls = False 227 | 228 | # Documents to append as an appendix to all manuals. 229 | #latex_appendices = [] 230 | 231 | # If false, no module index is generated. 232 | #latex_domain_indices = True 233 | 234 | 235 | # -- Options for manual page output --------------------------------------- 236 | 237 | # One entry per manual page. List of tuples 238 | # (source start file, name, description, authors, manual section). 239 | man_pages = [ 240 | ('index', 'napalm', u'NAPALM Documentation', 241 | [u'David Barroso'], 1) 242 | ] 243 | 244 | # If true, show URL addresses after external links. 245 | #man_show_urls = False 246 | 247 | 248 | # -- Options for Texinfo output ------------------------------------------- 249 | 250 | # Grouping the document tree into Texinfo files. List of tuples 251 | # (source start file, target name, title, author, 252 | # dir menu entry, description, category) 253 | texinfo_documents = [ 254 | ('index', 'napalm', u'NAPALM Documentation', 255 | u'David Barroso', 'napalm', 'One line description of project.', 256 | 'Miscellaneous'), 257 | ] 258 | 259 | # Documents to append as an appendix to all manuals. 260 | #texinfo_appendices = [] 261 | 262 | # If false, no module index is generated. 263 | #texinfo_domain_indices = True 264 | 265 | # How to display URL addresses: 'footnote', 'no', or 'inline'. 266 | #texinfo_show_urls = 'footnote' 267 | 268 | # If true, do not generate a @detailmenu in the "Top" node's menu. 269 | #texinfo_no_detailmenu = False 270 | 271 | # Disable pdf and epub generation 272 | enable_pdf_build = False 273 | enable_epub_build = False 274 | -------------------------------------------------------------------------------- /docs/support/index.rst: -------------------------------------------------------------------------------- 1 | Supported Devices 2 | ================= 3 | 4 | General support matrix 5 | ---------------------- 6 | 7 | 8 | ===================== ========== ============= ============ ============== ============= ============ ============ =============== ======================== 9 | _ EOS JunOS IOS-XR FortiOS IBM NXOS IOS Pluribus PANOS 10 | ===================== ========== ============= ============ ============== ============= ============ ============ =============== ======================== 11 | **Module Name** napalm-eos napalm-junos napalm-iosxr napalm-fortios napalm-ibm napalm-nxos napalm-ios napalm-pluribus napalm-panos 12 | **Driver Name** eos junos iosxr fortios ibm nxos ios pluribus panos 13 | **Structured data** Yes Yes No No Yes Yes No No Yes 14 | **Minimum version** 4.15.0F 12.1 5.1.0 5.2.0 ??? 6.1 [#g1]_ 12.4(20)T N/A 7.0 15 | **Backend library** `pyeapi`_ `junos-eznc`_ `pyIOSXR`_ `pyFG`_ `bnclient`_ `pycsco`_ `netmiko`_ `pyPluribus`_ `netmiko`_, `pan-python`_ 16 | **Caveats** :doc:`eos` :doc:`fortios` :doc:`ibm` :doc:`nxos` :doc:`ios` :doc:`panos` 17 | ===================== ========== ============= ============ ============== ============= ============ ============ =============== ======================== 18 | 19 | .. _pyeapi: https://github.com/arista-eosplus/pyeapi 20 | .. _junos-eznc: https://github.com/Juniper/py-junos-eznc 21 | .. _pyIOSXR: https://github.com/fooelisa/pyiosxr 22 | .. _pyFG: https://github.com/spotify/pyfg 23 | .. _bnclient: https://github.com/kderynski/blade-netconf-python-client 24 | .. _pycsco: https://github.com/jedelman8/pycsco 25 | .. _netmiko: https://github.com/ktbyers/netmiko 26 | .. _pyPluribus: https://github.com/mirceaulinic/pypluribus 27 | .. _pan-python: https://github.com/kevinsteves/pan-python 28 | 29 | .. [#g1] NX-API support on the Nexus 5k, 6k and 7k families was introduced in version 7.2 30 | 31 | .. warning:: Please, make sure you understand the caveats for your particular platforms before using the library. 32 | 33 | 34 | Configuration support matrix 35 | ---------------------------- 36 | 37 | ===================== ========== ===== ========== ============== ============= ============== ============== ============== ============== 38 | _ EOS JunOS IOS-XR FortiOS IBM NXOS IOS Pluribus PANOS 39 | ===================== ========== ===== ========== ============== ============= ============== ============== ============== ============== 40 | **Config. replace** Yes Yes Yes Yes Yes [#c3]_ Yes Yes No Yes 41 | **Config. merge** Yes Yes Yes Yes Yes Yes Yes No Yes 42 | **Compare config** Yes Yes Yes [#c1]_ Yes [#c1]_ Yes [#c1]_ Yes [#c4]_ Yes No Yes 43 | **Atomic Changes** Yes Yes Yes No [#c2]_ No [#c2]_ Yes/No [#c5]_ Yes Yes Yes/No [#c5]_ 44 | **Rollback** Yes [#c2]_ Yes Yes Yes Yes [#c2]_ Yes/No [#c5]_ Yes No Yes 45 | ===================== ========== ===== ========== ============== ============= ============== ============== ============== ============== 46 | 47 | .. [#c1] Hand-crafted by the API as the device doesn't support the feature. 48 | .. [#c2] Not supported but emulated. Check caveats. 49 | .. [#c3] Check the caveats, this is a dangerous operation in this device. 50 | .. [#c4] For merges, the diff is simply the merge config itself. See caveats. 51 | .. [#c5] No for merges. See caveats. 52 | 53 | .. warning:: Before building a workflow to deploy configuration it is important you understand what the table above means; 54 | what are atomic changes and which devices support it, what does replacing or merging configuration mean, etc. 55 | The key to success is to test your workflow and to try to break things on a lab first. 56 | 57 | Getters support matrix 58 | ---------------------- 59 | 60 | .. |yes| unicode:: U+02705 .. Yes 61 | .. |no| unicode:: U+0274C .. No 62 | 63 | ============================== ===== ===== ====== ======= ====== ====== ===== ========= ========= 64 | _ EOS JunOS IOS-XR FortiOS IBM NXOS IOS Pluribus PANOS 65 | ============================== ===== ===== ====== ======= ====== ====== ===== ========= ========= 66 | **cli** |yes| |yes| |yes| |no| |no| |yes| |yes| |yes| |no| 67 | **get_facts** |yes| |yes| |yes| |yes| |no| |yes| |yes| |yes| |yes| 68 | **get_environment** |yes| |yes| |yes| |yes| |no| |no| |yes| |no| |no| 69 | **get_snmp_information** |yes| |yes| |yes| |no| |no| |yes| |yes| |yes| |no| 70 | **get_ntp_peers** |yes| |yes| |yes| |no| |no| |yes| |no| |yes| |no| 71 | **get_ntp_stats** |yes| |yes| |yes| |no| |no| |yes| |yes| |yes| |no| 72 | **get_mac_address_table** |yes| |yes| |yes| |no| |no| |yes| |yes| |yes| |no| 73 | **get_arp_table** |yes| |yes| |yes| |no| |no| |yes| |yes| |no| |no| 74 | **get_interfaces** |yes| |yes| |yes| |yes| |no| |yes| |yes| |yes| |yes| 75 | **get_interfaces_ip** |yes| |yes| |yes| |no| |no| |yes| |yes| |no| |no| 76 | **get_lldp_neighbors** |yes| |yes| |yes| |yes| |no| |no| |yes| |yes| |no| 77 | **get_lldp_neighbors_detail** |yes| |yes| |yes| |no| |no| |yes| |yes| |yes| |no| 78 | **get_bgp_neighbors** |yes| |yes| |yes| |yes| |no| |no| |yes| |no| |no| 79 | **get_bgp_neighbors_detail** |yes| |yes| |yes| |no| |no| |no| |no| |no| |no| 80 | **get_bgp_config** |yes| |yes| |yes| |no| |no| |no| |no| |no| |no| 81 | **get_route_to** |yes| |yes| |yes| |no| |no| |no| |no| |no| |no| 82 | **get_probes_config** |no| |yes| |yes| |no| |no| |no| |no| |no| |no| 83 | **get_probes_results** |no| |yes| |yes| |no| |no| |no| |no| |no| |no| 84 | **get_users** |yes| |yes| |yes| |no| |no| |yes| |no| |yes| |no| 85 | **get_optics** |yes| |yes| |yes| |no| |no| |no| |no| |no| |no| 86 | ============================== ===== ===== ====== ======= ====== ====== ===== ========= ========= 87 | 88 | Other methods 89 | ------------- 90 | 91 | .. |yes| unicode:: U+02705 .. Yes 92 | .. |no| unicode:: U+0274C .. No 93 | 94 | ============================== ===== ===== ====== ======= ====== ====== ===== ========= ========= 95 | _ EOS JunOS IOS-XR FortiOS IBM NXOS IOS Pluribus PANOS 96 | ============================== ===== ===== ====== ======= ====== ====== ===== ========= ========= 97 | **load_template** |yes| |yes| |yes| |yes| |yes| |yes| |yes| |yes| |yes| 98 | **ping** |no| |no| |no| |no| |no| |no| |yes| |no| |no| 99 | **traceroute** |yes| |yes| |yes| |no| |no| |yes| |no| |yes| |no| 100 | ============================== ===== ===== ====== ======= ====== ====== ===== ========= ========= 101 | 102 | Available configuration templates 103 | --------------------------------- 104 | 105 | * :code:`set_hostname` (JunOS, IOS-XR, IOS, PANOS) - Configures the hostname of the device. 106 | * :code:`set_ntp_peers` (JunOS, IOS-XR, EOS, NXOS, IOS) - Configures NTP peers of the device. 107 | * :code:`delete_ntp_peers` (JunOS, IOS-XR, EOS, NXOS, IOS): Removes NTP peers form device's configuration. 108 | * :code:`set_probes` (JunOS, IOS-XR): Configures RPM/SLA probes. 109 | * :code:`schedule_probes` (IOS-XR): On Cisco devices, after defining the SLA probes, it is mandatory to schedule them. Defined also for JunOS as empty template, for consistency reasons. 110 | * :code:`delete_probes` (JunOS, IOS-XR): Removes RPM/SLA probes. 111 | 112 | Caveats 113 | ------- 114 | 115 | .. toctree:: 116 | :maxdepth: 1 117 | 118 | eos 119 | fortios 120 | ibm 121 | nxos 122 | ios 123 | panos 124 | 125 | Optional arguments 126 | ------------------ 127 | 128 | NAPALM supports passing certain optional arguments to some drivers. To do that you have to pass a dictionary via the 129 | :code:`optional_args` parameter when creating the object:: 130 | 131 | >>> from napalm import get_network_driver 132 | >>> driver = get_network_driver('eos') 133 | >>> optional_args = {'my_optional_arg1': 'my_value1', 'my_optional_arg2': 'my_value2'} 134 | >>> device = driver('192.168.76.10', 'dbarroso', 'this_is_not_a_secure_password', optional_args=optional_args) 135 | >>> device.open() 136 | 137 | List of supported optional arguments 138 | ____________________________________ 139 | 140 | * :code:`fortios_vdom` (fortios) - VDOM to connect to. 141 | * :code:`port` (eos, iosxr, junos, ios) - Allows you to specify a port other than the default. 142 | * :code:`config_lock` (iosxr, junos) - Lock the config during open() (default: True). 143 | * :code:`dest_file_system` (ios) - Destination file system for SCP transfers (default: 'flash:'). 144 | * :code:`auto_rollback_on_error` (ios) - Disable automatic rollback (certain versions of IOS support configure replace, but not rollback on error) (default: True). 145 | * :code:`global_delay_factor` (ios) - Allow for additional delay in command execution (default: .5). 146 | * :code:`nxos_protocol` (nxos) - Protocol to connect with. Only 'https' and 'http' allowed (default: 'http'). 147 | 148 | 149 | Adding optional arguments to NAPALM drivers 150 | ___________________________________________ 151 | 152 | If you are a developer and want to add an optional argument to a driver, please, follow this pattern when naming the 153 | argument; :code:`$driver_name-$usage` if the argument applies only to a particular driver. For example, the optional 154 | argument :code:`fortios_vdom` is used only by the FortiOS driver to select a particular vdom. Otherwise, just name it 155 | :code:`$driver_name-$usage`. For example the :code:`port` optional argument. 156 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | --------------------------------------------------------------------------------