Skip to content

Commit

Permalink
Make compatible with Napalm 3
Browse files Browse the repository at this point in the history
- Add MTU field to the get_interfaces
- Add sanitized=False to the get_config (but don't implement it)
- Add VRF argument to the get_arp_table (but don't implement it)
- Update Copyright

Signed-off-by: tang hao <thddaniel92@gmail.com>
  • Loading branch information
thddaniel committed Feb 16, 2021
1 parent f451371 commit 70ba634
Show file tree
Hide file tree
Showing 16 changed files with 246 additions and 207 deletions.
17 changes: 6 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
[![PyPI](https://img.shields.io/pypi/v/napalm-ce.svg)](https://pypi.org/project/napalm-ce/)

# napalm-ce

This is a [NAPALM](https://github.com/napalm-automation/napalm) community driver for the Huawei CloudEngine Switch.

## Requirements

Python 3.6+, napalm 3+

## Quick start

```shell
pip install napalm-ce
pip install -i https://test.pypi.org/simple/ napalm-ce
```

```python
Expand All @@ -30,8 +31,8 @@ Check the full [NAPALM Docs](https://napalm.readthedocs.io/en/latest/index.html)
* commit_config()
* compare_config()
* discard_config()
* get_arp_table()
* get_config(retrieve=u'all')
* get_arp_table(vrf='')
* get_config(retrieve='all', full=False, sanitized=False)
* get_environment()
* get_facts()
* get_interfaces()
Expand All @@ -47,9 +48,3 @@ Check the full [NAPALM Docs](https://napalm.readthedocs.io/en/latest/index.html)
* ping(destination, source=u'', ttl=255, timeout=2, size=100, count=5, vrf=u'')
* rollback()


## Setting up a Lab Environment

You can download Huawei eNSP simulator for free from [Huawei website](http://support.huawei.com/enterprise/wn/network-management/ensp-pid-9017384/software) after make an account. You can learn how to install it by this [tutorial](https://www.youtube.com/watch?v=Yw8HPPwrzZU).


2 changes: 1 addition & 1 deletion napalm_ce/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright 2016 Dravetech AB. All rights reserved.
# Copyright 2018 Hao Tang. All rights reserved.
#
# The contents of this file are licensed under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with the
Expand Down
53 changes: 34 additions & 19 deletions napalm_ce/ce.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright 2016 Dravetech AB. All rights reserved.
# Copyright 2018 Hao Tang. All rights reserved.
#
# The contents of this file are licensed under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with the
Expand Down Expand Up @@ -56,7 +56,7 @@ class CEDriver(NetworkDriver):
"""Napalm driver for HUAWEI CloudEngine."""

def __init__(self, hostname, username, password, timeout=60, optional_args=None):
"""Constructor."""
"""NAPALM Huawei CloudEngine Handler."""
self.device = None
self.hostname = hostname
self.username = username
Expand Down Expand Up @@ -121,7 +121,7 @@ def open(self):

def close(self):
"""Close the connection to the device."""
if self.changed and self.backup_file is not "":
if self.changed and self.backup_file != "":
self._delete_file(self.backup_file)
self.device.disconnect()
self.device = None
Expand Down Expand Up @@ -278,19 +278,21 @@ def get_interfaces(self):
{
"Vlanif3000": {
"is_enabled": false,
"description": "Route Port,The Maximum Transmit Unit is 1500",
"description": "",
"last_flapped": -1.0,
"is_up": false,
"mac_address": "0C:45:BA:7D:83:E6",
"speed": -1
"speed": 1000,
'mtu': 1500
},
"Vlanif100": {
"is_enabled": false,
"description": "Route Port,The Maximum Transmit Unit is 1500",
"description": "",
"last_flapped": -1.0,
"is_up": false,
"mac_address": "0C:45:BA:7D:83:E4",
"speed": -1
"speed": 1000,
'mtu': 1500
}
}
"""
Expand All @@ -304,7 +306,8 @@ def get_interfaces(self):
re_protocol = r"Line protocol current state\W+(?P<protocol>.+)$"
re_mac = r"Hardware address is\W+(?P<mac_address>\S+)"
re_speed = r"^Speed\W+(?P<speed>\d+|\w+)"
re_description = r"^Description\W+(?P<description>.*)$"
re_description = r"^Description:(?P<description>.*)$"
re_mtu = r"(Maximum Transmit Unit|Maximum Frame Length) is (?P<mtu>\d+)"

new_interfaces = self._separate_section(separator, output)
for interface in new_interfaces:
Expand All @@ -329,17 +332,23 @@ def get_interfaces(self):
else:
mac_address = ""

speed = -1
speed = mtu = 0
match_speed = re.search(re_speed, interface, flags=re.M)
if match_speed:
speed = match_speed.group('speed')
if speed.isdigit():
speed = int(speed)

match_mtu = re.search(re_mtu, interface, flags=re.M)
if match_mtu:
mtu = match_mtu.group('mtu')
if mtu.isdigit():
mtu = int(mtu)

description = ''
match = re.search(re_description, interface, flags=re.M)
if match:
description = match.group('description')
description = match.group('description').strip()

interfaces.update({
intf_name: {
Expand All @@ -348,7 +357,9 @@ def get_interfaces(self):
'is_up': is_up,
'last_flapped': -1.0,
'mac_address': mac_address,
'speed': speed}
'speed': speed,
'mtu': mtu
}
})
return interfaces

Expand Down Expand Up @@ -620,15 +631,15 @@ def get_environment(self):
environment['memory']['used_ram'] = int(match.group("used_ram"))
return environment

def get_arp_table(self):
def get_arp_table(self, vrf=""):
"""
Get arp table information.
Return a list of dictionaries having the following set of keys:
* interface (string)
* mac (string)
* ip (string)
* age (float) (not support)
* age (float)
Sample output:
[
Expand All @@ -646,28 +657,32 @@ def get_arp_table(self):
}
]
"""
if vrf:
msg = "VRF support has not been implemented."
raise NotImplementedError(msg)

arp_table = []
output = self.device.send_command('display arp')
re_arp = r"(?P<ip_address>\d+\.\d+\.\d+\.\d+)\s+(?P<mac>\S+)\s+(?P<exp>\d+|)\s+" \
r"(?P<type>I|D|S|O)\s+(?P<interface>\S+)"
match = re.findall(re_arp, output, flags=re.M)

for arp in match:
# if arp[2].isdigit():
# exp = float(arp[2]) * 60
# else:
# exp = 0
if arp[2].isdigit():
exp = round(float(arp[2]) * 60, 1)
else:
exp = -1.0

entry = {
'interface': arp[4],
'mac': napalm.base.helpers.mac(arp[1]),
'ip': arp[0],
'age': -1.0,
'age': exp
}
arp_table.append(entry)
return arp_table

def get_config(self, retrieve='all'):
def get_config(self, retrieve="all", full=False, sanitized=False):
"""
Get config from device.
Expand Down
21 changes: 11 additions & 10 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
coveralls
ddt
flake8-import-order
pytest
pytest-cov
pytest-json
pytest-pythonpath
pylama
mock
tox
coveralls==3.0.0
ddt==1.4.1
flake8-import-order==0.18.1
pytest==5.4.3
pytest==5.4.3
pytest-cov==2.11.1
pytest-json==0.4.0
pytest-pythonpath==0.7.3
pylama==7.7.1
mock==4.0.3
tox==3.21.4
10 changes: 7 additions & 3 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
napalm>=2.0.0
netmiko>=1.4.2
future
napalm>=3.0.0
setuptools>=38.4.0
netmiko>=3.1.0
paramiko>=2.6.0
requests>=2.7.0
future
jinja2
18 changes: 10 additions & 8 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -1,30 +1,32 @@
[bdist_wheel]
universal = 1

[metadata]
license_file = LICENSE

[pylama]
linters = mccabe,pep8,pyflakes
ignore = D203,C901
skip = build/*,.tox/*
skip = build/*,.tox/*,.env/*,.venv/*

[pylama:pep8]
max_line_length = 100

[tool:pytest]
norecursedirs =
.git
.git
.tox
.env
.venv
dist
build
south_migraitons
migrations
napalm/base/test
napalm_ce/test
python_files =
test_*.py
*_test.py
tests.py
addopts =
--cov=napalm
--cov-report term-missing
-vs
--pylama
json_report = report.json
jsonapi = true

Expand Down
35 changes: 18 additions & 17 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,31 +1,32 @@
"""setup.py file."""

import uuid

from setuptools import setup, find_packages
try: # for pip >= 10
from pip._internal.req import parse_requirements
except ImportError: # for pip <= 9.0.3
from pip.req import parse_requirements

__author__ = 'Hao Tang <thddaniel92@gmail.com>'

install_reqs = parse_requirements('requirements.txt', session=uuid.uuid1())
reqs = [str(ir.req) for ir in install_reqs]
with open("requirements.txt", "r") as fs:
reqs = [r for r in fs.read().splitlines() if (len(r) > 0 and not r.startswith("#"))]

with open("README.md", "r") as fs:
long_description = fs.read()

setup(
name="napalm-ce",
version="0.1.1",
packages=find_packages(),
version="0.2.0",
packages=find_packages(exclude=("test*",)),
author="Hao Tang",
author_email="thddaniel92@gmail.com",
description="Network Automation and Programmability Abstraction Layer with Multivendor support",
description="NAPALM driver for Huawei CloudEngine switches",
license="Apache 2.0",
long_description=long_description,
long_description_content_type="text/markdown",
classifiers=[
'Topic :: Utilities',
'Programming Language :: Python',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3.6',
"Topic :: Utilities",
"License :: OSI Approved :: Apache Software License",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
'Operating System :: POSIX :: Linux',
'Operating System :: MacOS',
],
Expand Down
2 changes: 1 addition & 1 deletion test/unit/TestCEDriver.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright 2016 Dravetech AB. All rights reserved.
# Copyright 2018 Hao Tang. All rights reserved.
#
# The contents of this file are licensed under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with the
Expand Down
2 changes: 1 addition & 1 deletion test/unit/TestDriver.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright 2016 Dravetech AB. All rights reserved.
# Copyright 2018 Hao Tang. All rights reserved.
#
# The contents of this file are licensed under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with the
Expand Down
Loading

0 comments on commit 70ba634

Please sign in to comment.