20 Commits
0.1.3 ... 0.1.6

Author SHA1 Message Date
Piotr Pieprzycki
1d11f45e68 Merge pull request #30 from napalm-automation-community/develop
Fix installation fails with the pip > 10  dev->master
2019-02-15 09:30:44 +01:00
Piotr Pieprzycki
df1d827038 Merge pull request #29 from ppieprzycki/issue28
Fix installation fails with the pip > 10
2019-02-15 09:19:34 +01:00
Pieprzycki Piotr
0175531bbb add additional parameters 2019-02-14 23:55:18 +01:00
Pieprzycki Piotr
42953c84ae add additional parameters 2019-02-14 23:43:56 +01:00
Pieprzycki Piotr
57b6110f13 fix pip issue 2019-02-14 07:03:57 +01:00
Piotr Pieprzycki
f1549d8af3 Merge pull request #25 from napalm-automation-community/master
Update develop branch
2018-04-08 18:26:36 +02:00
Piotr Pieprzycki
2278bddd3a Merge pull request #24 from ppieprzycki/master
Support for salt
2018-04-08 18:19:57 +02:00
Pieprzycki Piotr
55a6b15c3e Update docs 2018-04-08 18:15:28 +02:00
Pieprzycki Piotr
580da0edeb Update docs 2018-04-08 18:12:07 +02:00
Pieprzycki Piotr
23fe045167 Update docs 2018-04-08 18:09:21 +02:00
Pieprzycki Piotr
b8ec1396f7 Update docs 2018-04-08 17:56:49 +02:00
Pieprzycki Piotr
5c3492f13c Update docs 2018-04-08 11:28:15 +02:00
Pieprzycki Piotr
47227d1cf0 handle config as text in load and merge functions 2018-04-08 00:23:04 +02:00
Piotr Pieprzycki
06f9fc28d3 Merge pull request #23 from napalm-automation-community/develop
Merge develop branch with master
2018-02-22 21:30:01 +01:00
Piotr Pieprzycki
6e68dba692 Merge pull request #22 from ppieprzycki/master
Fix travis status and set new version 0.1.4
2018-02-22 20:36:50 +01:00
Piotr Pieprzycki
7d0e30fdba Merge pull request #20 from thomseddon/fix/use-napalm-base
Use napalm instead of napalm_base
2018-02-22 20:29:11 +01:00
Pieprzycki Piotr
4d52216866 Fix travis status and set new version 0.1.4 2018-02-22 20:28:24 +01:00
Piotr Pieprzycki
5c440b3df9 Merge pull request #21 from ppieprzycki/master
Fix imports to napalm2
2018-02-22 20:19:15 +01:00
Pieprzycki Piotr
69c8c66652 napalm 2 2018-02-22 20:00:24 +01:00
Thom Seddon
b9bcbbc7bc Use napalm instead of napalm_base 2018-02-22 10:16:54 +00:00
8 changed files with 211 additions and 63 deletions

107
README.md
View File

@@ -1,5 +1,110 @@
[![PyPI](https://img.shields.io/pypi/v/napalm-vyos.svg)](https://pypi.python.org/pypi/napalm-vyos)
[![PyPI](https://img.shields.io/pypi/dm/napalm-vyos.svg)](https://pypi.python.org/pypi/napalm-vyos)
[![Build Status](https://travis-ci.org/napalm-automation/napalm-vyos.svg?branch=master)](https://travis-ci.org/napalm-automation/napalm-vyos)
[![Build Status](https://travis-ci.org/napalm-automation-community/napalm-vyos.svg?branch=master)](https://travis-ci.org/napalm-automation-community/napalm-vyos)
# napalm-vyos
Community NAPALM driver for the VyOS. https://vyos.io/
Also it can be used for other similar systems: Vyatta or EdgeOS
General support matrix
----------------------
| | VyOS |
|--------------------|--------------|
|**Module Name** | napalm-vyos |
|**Driver Name** | vyos |
|**Structured data** | Yes |
|**Minimum version** | 1.1.6 |
|**Backend library** | netmiko |
Configuration support matrix
----------------------------
| | VyOS |
| ------------------- | ----- |
| **Config. replace** | Yes |
| **Config. merge** | Yes |
|**Compare config** | Yes |
| **Atomic Changes** | Yes |
| **Rollback** | Yes |
Optional arguments
------------------
NAPALM supports passing certain optional arguments to some drivers. To do that you have to pass a dictionary via the
:code:`optional_args` parameter when creating the object::
>>> from napalm import get_network_driver
>>> driver = get_network_driver('vyos')
>>> optional_args = {'my_optional_arg1': 'my_value1', 'my_optional_arg2': 'my_value2'}
>>> device = driver('192.168.76.10', 'vagrant', 'this_is_not_a_secure_password', optional_args=optional_args)
>>> device.open()
List of supported optional arguments
____________________________________
* :code:`port` (vyos) - Allows you to specify a port other than the default.
* :code:`key_file` (vyos) - Netmiko/Paramiko argument, path to a private key file (default: 'False').
Prerequisites
-------------
VyOS has no native HTTP API or NETCONF capability.
We are using Netmiko for ssh connections and scp file transfers.
Having Netmiko installed in your working box is a prerequisite.
VyOS in version 1.1.x (tested 1.1.7)
napalm==2.*
paramiko
netmiko>=1.1.0
vyattaconfparser
Configuration file
------------------
Currently VyOS driver supports two different configuration formats:
* load_replace_candidate - Full config file (with brackets) like in /config/config.boot
Due to the OS nature, we do not support a replace using
a set-style configuration format.
* load_merge_candidate - Currently driver supports set-style configuration format.
Example
`set system login banner pre-login "test"`
Vyos require configuration file (load_replace) to contain comment like following
`/* Warning: Do not remove the following line. */
/* === vyatta-config-version: "cluster@1:config-management@1:conntrack-sync@1:conntrack@1:cron@1:dhcp-relay@1:dhcp-server@4:firewall@5:ipsec@4:nat@4:qos@1:quagga@2:system@6:vrrp@1:wanloadbalance@3:webgui@1:webproxy@1:zone-policy@1" === */
/* Release version: VyOS 1.1.7 */`
Otherwise VyOS reject `load` operation
Notes
------------------
* The NAPALM-vyos driver supports all Netmiko arguments as either standard arguments (hostname, username, password, timeout) or as optional_args (everything else).
* The NAPALM-vyos driver supports authentication with ssh key. Please specify path to a key in optional_args
`'optional_args': {'key_file': '/home/user/ssh_private_key'}`
Configuration Examples
----------------------
* Vyos as IPSec VPN endpoint and BGP router - https://github.com/DreamLab/ansible-vyos
* CI Demo for vyos+junos (Polish only) https://github.com/ppieprzycki/plnog2016
VyOS Community
------------------
Slack Channel https://slack.vyos.io

View File

@@ -22,6 +22,7 @@ Read napalm.readthedocs.org for more information.
import re
import os
import tempfile
import vyattaconfparser
@@ -30,11 +31,12 @@ from netmiko import ConnectHandler
from netmiko import SCPConn
# NAPALM base
import napalm_base.constants as C
from napalm_base.utils import py23_compat
from napalm_base.base import NetworkDriver
from napalm_base.exceptions import ConnectionException, \
MergeConfigException, ReplaceConfigException
import napalm.base.constants as C
from napalm.base.utils import py23_compat
from napalm.base.base import NetworkDriver
from napalm.base.exceptions import ConnectionException, MergeConfigException, \
ReplaceConfigException, CommitError, \
CommandErrorException
class VyOSDriver(NetworkDriver):
@@ -121,53 +123,73 @@ class VyOSDriver(NetworkDriver):
Due to the OS nature, we do not
support a replace using a configuration string.
"""
if filename is not None:
if os.path.exists(filename) is True:
self._scp_client.scp_transfer_file(filename, self._DEST_FILENAME)
self.device.send_command("cp "+self._BOOT_FILENAME+" "+self._BACKUP_FILENAME)
output_loadcmd = self.device.send_config_set(['load '+self._DEST_FILENAME])
match_loaded = re.findall("Load complete.", output_loadcmd)
match_notchanged = re.findall("No configuration changes to commit", output_loadcmd)
match_failed = re.findall("Failed to parse specified config file", output_loadcmd)
if not filename and not config:
raise ReplaceConfigException('filename or config param must be provided.')
if match_failed:
if filename is None:
temp_file = tempfile.NamedTemporaryFile()
temp_file.write(config)
temp_file.flush()
cfg_filename = temp_file.name
else:
cfg_filename = filename
if os.path.exists(cfg_filename) is True:
self._scp_client.scp_transfer_file(cfg_filename, self._DEST_FILENAME)
self.device.send_command("cp "+self._BOOT_FILENAME+" "+self._BACKUP_FILENAME)
output_loadcmd = self.device.send_config_set(['load '+self._DEST_FILENAME])
match_loaded = re.findall("Load complete.", output_loadcmd)
match_notchanged = re.findall("No configuration changes to commit", output_loadcmd)
match_failed = re.findall("Failed to parse specified config file", output_loadcmd)
if match_failed:
raise ReplaceConfigException("Failed replace config: "
+ output_loadcmd)
if not match_loaded:
if not match_notchanged:
raise ReplaceConfigException("Failed replace config: "
+ output_loadcmd)
if not match_loaded:
if not match_notchanged:
raise ReplaceConfigException("Failed replace config: "
+ output_loadcmd)
else:
raise ReplaceConfigException("config file is not found")
else:
raise ReplaceConfigException("no configuration found")
raise ReplaceConfigException("config file is not found")
def load_merge_candidate(self, filename=None, config=None):
"""
Only configuration in set-format is supported with load_merge_candidate.
"""
if filename is not None:
if os.path.exists(filename) is True:
with open(filename) as f:
self.device.send_command("cp "+self._BOOT_FILENAME+" "
+ self._BACKUP_FILENAME)
self._new_config = f.read()
cfg = [x for x in self._new_config.split("\n") if x is not ""]
output_loadcmd = self.device.send_config_set(cfg)
match_setfailed = re.findall("Delete failed", output_loadcmd)
match_delfailed = re.findall("Set failed", output_loadcmd)
if match_setfailed or match_delfailed:
raise MergeConfigException("Failed merge config: "
+ output_loadcmd)
else:
raise MergeConfigException("config file is not found")
elif config is not None:
self._new_config = config
if not filename and not config:
raise MergeConfigException('filename or config param must be provided.')
if filename is None:
temp_file = tempfile.NamedTemporaryFile()
temp_file.write(config)
temp_file.flush()
cfg_filename = temp_file.name
else:
raise MergeConfigException("no configuration found")
cfg_filename = filename
if os.path.exists(cfg_filename) is True:
with open(cfg_filename) as f:
self.device.send_command("cp "+self._BOOT_FILENAME+" "
+ self._BACKUP_FILENAME)
self._new_config = f.read()
cfg = [x for x in self._new_config.split("\n") if x is not ""]
output_loadcmd = self.device.send_config_set(cfg)
match_setfailed = re.findall("Delete failed", output_loadcmd)
match_delfailed = re.findall("Set failed", output_loadcmd)
if match_setfailed or match_delfailed:
raise MergeConfigException("Failed merge config: "
+ output_loadcmd)
else:
raise MergeConfigException("config file is not found")
def discard_config(self):
self.device.exit_config_mode()
@@ -182,9 +204,18 @@ class VyOSDriver(NetworkDriver):
diff = ''.join(output_compare.splitlines(True)[1:-1])
return diff
def commit_config(self):
if self.device.commit():
self.device.send_config_set(['save'])
def commit_config(self, message=""):
if message:
raise NotImplementedError(
"Commit message not implemented for this platform"
)
try:
self.device.commit()
except ValueError:
raise CommitError("Failed to commit config on the device")
self.device.send_config_set(['save'])
self.device.exit_config_mode()
def rollback(self):
@@ -332,7 +363,7 @@ class VyOSDriver(NetworkDriver):
else:
return None
def get_arp_table(self):
def get_arp_table(self, vrf=""):
# 'age' is not implemented yet
"""
@@ -344,6 +375,12 @@ class VyOSDriver(NetworkDriver):
10.129.2.97 ether 00:50:56:9f:64:09 C eth0
192.168.1.3 ether 00:50:56:86:7b:06 C eth1
"""
if vrf:
raise NotImplementedError(
"VRF support has not been added for this getter on this platform."
)
output = self.device.send_command("show arp")
output = output.split("\n")
@@ -478,6 +515,8 @@ class VyOSDriver(NetworkDriver):
received_prefixes = int(state_prefix)
is_up = True
except ValueError:
state_prefix = -1
received_prefixes = -1
is_up = False
if bgp_version == "4":

View File

@@ -1,4 +1,4 @@
napalm_base
napalm==2.*
paramiko
netmiko>=1.1.0
vyattaconfparser

View File

@@ -1,30 +1,34 @@
"""setup.py file."""
import uuid
from setuptools import setup, find_packages
from pip.req import parse_requirements
with open("requirements.txt", "r") as fs:
reqs = [r for r in fs.read().splitlines()
if (len(r) > 0 and not r.startswith("#"))]
__author__ = 'Piotr Pieprzycki <piotr.pieprzycki@dreamlab.pl>'
install_reqs = parse_requirements('requirements.txt', session=uuid.uuid1())
reqs = [str(ir.req) for ir in install_reqs]
setup(
name="napalm-vyos",
version="0.1.3",
version="0.1.6",
packages=find_packages(),
author="Piotr Pieprzycki",
author_email="piotr.pieprzycki@dreamlab.pl",
description="Network Automation and Programmability Abstraction Layer with Multivendor support",
classifiers=[
'Topic :: Utilities',
'Programming Language :: Python',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7',
'Operating System :: POSIX :: Linux',
'Operating System :: MacOS',
'Programming Language :: Python',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Operating System :: POSIX :: Linux',
'Operating System :: MacOS',
],
url="https://github.com/napalm-automation-community/napalm-vyos",
include_package_data=True,
install_requires=reqs,
)

View File

@@ -15,7 +15,7 @@
import unittest
from napalm_vyos import vyos
from napalm_base.test.base import TestConfigNetworkDriver
from napalm.base.test.base import TestConfigNetworkDriver
class TestConfigVyOSDriver(unittest.TestCase, TestConfigNetworkDriver):

View File

@@ -2,10 +2,10 @@
from builtins import super
import pytest
from napalm_base.test import conftest as parent_conftest
from napalm.base.test import conftest as parent_conftest
from napalm_base.test.double import BaseTestDouble
from napalm_base.utils import py23_compat
from napalm.base.test.double import BaseTestDouble
from napalm.base.utils import py23_compat
from napalm_vyos import vyos

View File

@@ -1,6 +1,6 @@
"""Tests for getters."""
from napalm_base.test.getters import BaseTestGetters
from napalm.base.test.getters import BaseTestGetters
import pytest

View File

@@ -1,5 +1,5 @@
[tox]
envlist = py27,py34,py35
envlist = py27,py35
[testenv]
deps =