Skip to content

Commit

Permalink
Update interface_counters from develop (#96)
Browse files Browse the repository at this point in the history
* adding read_timeout_override netmiko option

* adding netmiko option session_log

* Bump black from 20.8b1 to 24.3.0

Bumps [black](https://github.com/psf/black) from 20.8b1 to 24.3.0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/commits/24.3.0)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>

* remove demjson - blocking tests

* FIX minor formating fixes raised by pylama

* FIX limit napalm and netmiko o version 3.*, soften version requirements

* FIX minor formating fixes raised by pylama

* Allow testing on all supported Py versions

* FIX add platform name to driver s350

* FIX force interface speed as a float

* Update information about required versions to Py3.8+ and napalm 3

* Add scheduled check on develop branch

* Update pkg version in setup.py

* Update PublishToPIP.yml for manual run

* Napalm 4 compatibility, newer dependencies

* Full tox testing on "develop" and "master" branch.

* Remove Py13 - too early

* Do not test on PyPy, local test with local Py version only

* CI ThoroughTest for branches develop and master

* CI FastTest for all other branches.

* CI rename legacy jobs

* CI renaname job

* Updata docs

* Shorten name of publish workflow

* Check syntax for Py3.12

* use netmiko_args

* Add changes for 4.1.0 (#89)

* Update requirements.txt

* Typpo in requirements

* _send_command has only two parameters

* Adapt to stricter Unit tests

---------

Co-authored-by: Anton Gridnev <anton@gridnev.pro>

* Remove s350_base_interfaces custom map - it is allready in napalm base

* Adapt Unit tests to canonical_interface_name()

* Add format parameter to get_config()

* Add badges

* Tests for push are enought

* update CD actions

* add tests for device SG500-52

* Merge CI to develop (#95)

* Simplify CI

* CI update

* CI update

* Update CI from develop (#94)

* Add format parameter to get_config()

* Add badges

* Tests for push are enought

* update CD actions

* add tests for device SG500-52

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Dave <davama@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Anton Gridnev <anton@gridnev.pro>
  • Loading branch information
4 people authored Apr 23, 2024
1 parent f500ec3 commit 4d86bee
Show file tree
Hide file tree
Showing 46 changed files with 224 additions and 212 deletions.
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

0 comments on commit 4d86bee

Please sign in to comment.