Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update interface_counters from develop #96

Merged
merged 40 commits into from
Apr 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
c74e972
adding read_timeout_override netmiko option
davama Jan 30, 2023
a0b28c9
adding netmiko option session_log
davama Feb 16, 2023
5da4d3d
Merge pull request #84 from davama/develop
qaxi Aug 28, 2023
7206990
Bump black from 20.8b1 to 24.3.0
dependabot[bot] Mar 20, 2024
593f998
remove demjson - blocking tests
qaxi Mar 26, 2024
7023c59
FIX minor formating fixes raised by pylama
qaxi Mar 26, 2024
9787347
FIX limit napalm and netmiko o version 3.*, soften version requirements
qaxi Mar 26, 2024
5049dcd
FIX minor formating fixes raised by pylama
qaxi Mar 26, 2024
7a32595
Allow testing on all supported Py versions
qaxi Mar 26, 2024
751126a
FIX add platform name to driver s350
qaxi Mar 26, 2024
7929c64
FIX force interface speed as a float
qaxi Mar 26, 2024
d1b960a
Merge pull request #85 from napalm-automation-community/dependabot/pi…
qaxi Mar 26, 2024
de857ba
Update information about required versions to Py3.8+ and napalm 3
qaxi Mar 26, 2024
7e1d345
Add scheduled check on develop branch
qaxi Mar 26, 2024
b4fd77d
Merge pull request #86 from napalm-automation-community/develop
qaxi Mar 26, 2024
e939d9e
Update pkg version in setup.py
qaxi Mar 26, 2024
5a9bff8
Update PublishToPIP.yml for manual run
qaxi Mar 26, 2024
f3d13a5
Napalm 4 compatibility, newer dependencies
qaxi Mar 26, 2024
cfd1169
Full tox testing on "develop" and "master" branch.
qaxi Mar 26, 2024
7009fc9
Remove Py13 - too early
qaxi Mar 26, 2024
62f6ab4
Do not test on PyPy, local test with local Py version only
qaxi Mar 26, 2024
a4f0473
CI ThoroughTest for branches develop and master
qaxi Mar 26, 2024
7a8fbac
CI FastTest for all other branches.
qaxi Mar 26, 2024
d6dd81e
CI rename legacy jobs
qaxi Mar 26, 2024
9025b0f
CI renaname job
qaxi Mar 26, 2024
fc9e83c
Updata docs
qaxi Mar 27, 2024
08d9a45
Shorten name of publish workflow
qaxi Mar 27, 2024
3a63056
Check syntax for Py3.12
qaxi Mar 27, 2024
6e6b38b
Merge branch 'master' into develop
qaxi Mar 27, 2024
86a7689
use netmiko_args
davama Mar 28, 2024
9b76a86
Use napalm supplied netmiko_args instead of my own
qaxi Mar 29, 2024
c4a3623
Add changes for 4.1.0 (#89)
qaxi Mar 29, 2024
971310b
Remove s350_base_interfaces custom map - it is allready in napalm base
qaxi Mar 29, 2024
cf47f5e
Adapt Unit tests to canonical_interface_name()
qaxi Mar 29, 2024
d371559
Add format parameter to get_config()
qaxi Apr 22, 2024
3f6c8f8
Add badges
qaxi Apr 22, 2024
f1e0aad
Tests for push are enought
qaxi Apr 22, 2024
a906c1b
update CD actions
qaxi Apr 23, 2024
0807157
add tests for device SG500-52
qaxi Apr 23, 2024
112320f
Merge CI to develop (#95)
qaxi Apr 23, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions .github/workflows/FastTest.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# This workflows will upload a Python Package using Twine when a release is created
# For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries

name: Fast Test

on:
push:
branches-ignore:
- develop
- master

jobs:

tox_test:

runs-on: ubuntu-latest
strategy:
matrix:
python-version: [ "3.11" ]

steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
if [ -f requirements-dev.txt ]; then pip install -r requirements-dev.txt; fi

- name: Test with tox
run: |
tox
7 changes: 4 additions & 3 deletions .github/workflows/PublishToPIP.yml
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
# This workflows will upload a Python Package using Twine when a release is created
# For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries

name: Publish Python Package to PyPi.org
name: Publish To PyPi.org

on:
release:
types: [created]
workflow_dispatch:

jobs:
deploy:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v2
uses: actions/setup-python@v5
with:
python-version: '3.x'
- name: Install dependencies
Expand Down
35 changes: 0 additions & 35 deletions .github/workflows/TestBeforePush.yml

This file was deleted.

38 changes: 38 additions & 0 deletions .github/workflows/ThoroughTest.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# This workflows will upload a Python Package using Twine when a release is created
# For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries

name: Thorough Test

on:
push:
branches:
- develop
- master
# check every 14 days
schedule:
- cron: '0 6 5,20 * *'
jobs:

tox_test:

runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]

steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
if [ -f requirements-dev.txt ]; then pip install -r requirements-dev.txt; fi

- name: Test with tox
run: |
tox
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@
NAPALM driver for Cisco SMB switches (SF3xx, SF5xx, SG3xx, SG5xx, CBS35x).

## Status
Master: ![Build](https://github.com/napalm-automation-community/napalm-s350/workflows/Test%20before%20push/badge.svg?branch=master&event=push)

Develop: ![Build](https://github.com/napalm-automation-community/napalm-s350/workflows/Test%20before%20push/badge.svg?branch=develop&event=push)
Master: [![Thorough Test](https://github.com/napalm-automation-community/napalm-s350/actions/workflows/ThoroughTest.yml/badge.svg?branch=master)](https://github.com/napalm-automation-community/napalm-s350/actions/workflows/ThoroughTest.yml)

PyPi: [![Upload](https://github.com/napalm-automation-community/napalm-s350/workflows/Upload%20Python%20Package%20to%20PyPi.org/badge.svg)](https://github.com/napalm-automation-community/napalm-s350/actions?query=workflow%3A%22Upload+Python+Package+to+PyPi.org%22)
Develop: [![Thorough Test](https://github.com/napalm-automation-community/napalm-s350/actions/workflows/ThoroughTest.yml/badge.svg?branch=develop)](https://github.com/napalm-automation-community/napalm-s350/actions/workflows/ThoroughTest.yml)

PyPi.org: [![Publish To PyPi.org](https://github.com/napalm-automation-community/napalm-s350/actions/workflows/PublishToPIP.yml/badge.svg?branch=master)](https://github.com/napalm-automation-community/napalm-s350/actions/workflows/PublishToPIP.yml)

## Requirements

Python 3.6+, napalm 3+
Python 3.8+, napalm 4

## Installation

Expand Down
85 changes: 28 additions & 57 deletions napalm_s350/s350.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,12 @@
ConnectionClosedException,
)
from napalm.base.helpers import canonical_interface_name
from napalm.base.netmiko_helpers import netmiko_args

import napalm.base.constants as C
import napalm.base.canonical_map

# make may own base_interfaces for s350
s350_base_interfaces = {
**napalm.base.canonical_map.base_interfaces,
"fa": "FastEthernet",
"gi": "GigabitEthernet",
"te": "TengigabitEthernet",
}
from typing import List


class S350Driver(NetworkDriver):
Expand All @@ -63,30 +58,9 @@ def __init__(self, hostname, username, password, timeout=60, optional_args=None)
self._dest_file_system = optional_args.get("dest_file_system", None)

# Netmiko possible arguments
netmiko_argument_map = {
"port": None,
"secret": "",
"verbose": False,
"keepalive": 30,
"global_delay_factor": 1,
"use_keys": False,
"key_file": None,
"ssh_strict": False,
"system_host_keys": False,
"alt_host_keys": False,
"alt_key_file": "",
"ssh_config_file": None,
"allow_agent": False,
}

# Allow for passing additional Netmiko arguments
self.netmiko_optional_args = {}
for k, v in netmiko_argument_map.items():
try:
self.netmiko_optional_args[k] = optional_args[k]
except KeyError:
pass
self.netmiko_optional_args = netmiko_args(optional_args)

self.platform = "s350"
self.port = optional_args.get("port", 22)
self.device = None
self.force_no_enable = optional_args.get("force_no_enable", False)
Expand Down Expand Up @@ -118,16 +92,6 @@ def close(self):
"""Close the connection to the device."""
self.device.disconnect()

def cli(self, commands):
output = {}
try:
for cmd in commands:
output[cmd] = self.device.send_command(cmd)

return output
except (socket.error, EOFError) as e:
raise ConnectionClosedException(str(e))

def _send_command(self, command):
"""Wrapper for self.device.send.command().

Expand Down Expand Up @@ -180,7 +144,7 @@ def get_arp_table(self, vrf=""):
else:
raise ValueError("Unexpected output: {}".format(line.split()))

interface = canonical_interface_name(interface, s350_base_interfaces)
interface = canonical_interface_name(interface)

entry = {
"interface": interface,
Expand All @@ -193,7 +157,13 @@ def get_arp_table(self, vrf=""):

return arp_table

def get_config(self, retrieve="all", full=False, sanitized=False):
def get_config(
self,
retrieve="all",
full=False,
sanitized=False,
format: str = "text",
):
"""
get_config for S350. Since this firmware doesn't support a candidate
configuration we leave it empty.
Expand Down Expand Up @@ -288,7 +258,8 @@ def get_facts(self):
fqdn = "{0}.{1}".format(hostname, domainname)

# interface_list
interfaces = []

interfaces: List[str] = []
show_int_st = show_int_st.strip()
# remove the header information
show_int_st = re.sub(
Expand All @@ -298,7 +269,7 @@ def get_facts(self):
if not line:
continue
interface = line.split()[0]
interface = canonical_interface_name(interface, s350_base_interfaces)
interface = canonical_interface_name(interface)

interfaces.append(str(interface))

Expand All @@ -309,7 +280,7 @@ def get_facts(self):
"model": str(model),
"os_version": str(os_version),
"serial_number": str(serial_number),
"uptime": uptime,
"uptime": float(uptime),
"vendor": "Cisco",
}

Expand Down Expand Up @@ -364,7 +335,7 @@ def _get_facts_uptime(self, show_sys):
return uptime_str

def _get_facts_parse_inventory(self, show_inventory):
""" inventory can list more modules/devices """
"""inventory can list more modules/devices"""
# make 1 module 1 line
show_inventory = re.sub(r"\nPID", " PID", show_inventory, re.M)
# delete empty lines
Expand Down Expand Up @@ -471,14 +442,14 @@ def get_interfaces(self):
entry = {
"is_up": is_up,
"is_enabled": is_enabled,
"speed": speed,
"speed": float(speed),
"mtu": mtu,
"last_flapped": -1.0,
"description": description,
"mac_address": napalm.base.helpers.mac(mac),
}

interface = canonical_interface_name(interface, s350_base_interfaces)
interface = canonical_interface_name(interface)

interfaces[interface] = entry

Expand Down Expand Up @@ -516,14 +487,14 @@ def get_interfaces_ip(self):
ip = netaddr.IPNetwork(cidr)
family = "ipv{0}".format(ip.version)

interface = canonical_interface_name(interface, s350_base_interfaces)
interface = canonical_interface_name(interface)

interfaces[interface] = {family: {str(ip.ip): {"prefix_length": ip.prefixlen}}}

return interfaces

def _get_ip_int_line_to_fields(self, line, fields_end):
""" dynamic fields lenghts """
"""dynamic fields lenghts"""
line_elems = {}
index = 0
f_start = 0
Expand All @@ -534,7 +505,7 @@ def _get_ip_int_line_to_fields(self, line, fields_end):
return line_elems

def _get_ip_int_fields_end(self, dashline):
""" fields length are diferent device to device, detect them on horizontal lin """
"""fields length are diferent device to device, detect them on horizontal line"""

fields_end = [m.start() for m in re.finditer(" ", dashline.strip())]
# fields_position.insert(0,0)
Expand Down Expand Up @@ -574,7 +545,7 @@ def get_lldp_neighbors(self):
remote_port = line_elems[2]
remote_name = line_elems[3]

local_port = canonical_interface_name(local_port, s350_base_interfaces)
local_port = canonical_interface_name(local_port)

neighbor = {
"hostname": remote_name,
Expand All @@ -588,7 +559,7 @@ def get_lldp_neighbors(self):
return neighbors

def _get_lldp_neighbors_line_to_fields(self, line, fields_end):
""" dynamic fields lenghts """
"""dynamic fields lenghts"""
line_elems = {}
index = 0
f_start = 0
Expand All @@ -599,7 +570,7 @@ def _get_lldp_neighbors_line_to_fields(self, line, fields_end):
return line_elems

def _get_lldp_neighbors_fields_end(self, dashline):
""" fields length are diferent device to device, detect them on horizontal lin """
"""fields length are diferent device to device, detect them on horizontal line"""

fields_end = [m.start() for m in re.finditer(" ", dashline)]
fields_end.append(len(dashline))
Expand Down Expand Up @@ -628,14 +599,14 @@ def get_lldp_neighbors_detail(self, interface=""):
if interface:
if interface == local_port:
entry = self._get_lldp_neighbors_detail_parse(local_port)
local_port = canonical_interface_name(local_port, s350_base_interfaces)
local_port = canonical_interface_name(local_port)
details[local_port] = [
entry,
]

else:
entry = self._get_lldp_neighbors_detail_parse(local_port)
local_port = canonical_interface_name(local_port, s350_base_interfaces)
local_port = canonical_interface_name(local_port)
details[local_port] = [
entry,
]
Expand Down Expand Up @@ -670,7 +641,7 @@ def _get_lldp_neighbors_detail_parse(self, local_port):
elif line.startswith("Capabilities"):
caps = self._get_lldp_neighbors_detail_capabilities_parse(line)

remote_port_id = canonical_interface_name(remote_port_id, s350_base_interfaces)
remote_port_id = canonical_interface_name(remote_port_id)

entry = {
"parent_interface": "N/A",
Expand Down
Loading