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

Release 2.0.1 #314

Merged
merged 8 commits into from
Sep 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 8 additions & 0 deletions docs/admin/release_notes/version_2_0.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,11 @@
- [308](https://github.com/networktocode/pyntc/pull/308) Deprecated netmiko argument `delay_factor` in favor of `read_timeout` as per changes in Netmiko 4.0.

Refer to this blog post for more info about changes in netmiko 4.0: https://pynet.twb-tech.com/blog/netmiko-read-timeout.html


## [2.0.1] 09-2024
### Added
- [311](https://github.com/networktocode/pyntc/pull/311) Extend cisco_ios set_boot_options method.

### Fixed
- [312](https://github.com/networktocode/pyntc/pull/312) Fix Arista EOS file copy issues.
1,211 changes: 645 additions & 566 deletions poetry.lock

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions pyntc/devices/asa_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ def _get_ipv4_addresses(self, host: str) -> Dict[str, List[IPv4Address]]:
elif host == "peer":
command = "failover exec mate show ip address"

show_ip_address = self.show(command)
show_ip_address = self.show(command) # pylint: disable=possibly-used-before-assignment
re_ip_addresses = RE_SHOW_IP_ADDRESS.findall(show_ip_address)

results = {
Expand Down Expand Up @@ -188,7 +188,7 @@ def _get_ipv6_addresses(self, host: str) -> Dict[str, List[IPv6Address]]:
elif host == "peer":
command = "failover exec mate show ipv6 interface"

show_ipv6_interface = self.show(command)
show_ipv6_interface = self.show(command) # pylint: disable=possibly-used-before-assignment
show_ipv6_interface_lines: List[str] = show_ipv6_interface.strip().splitlines()
first_line = show_ipv6_interface_lines.pop(0)
interface: str = first_line.split()[0]
Expand Down
9 changes: 6 additions & 3 deletions pyntc/devices/eos_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,10 @@ def __init__(self, host, username, password, transport="http", port=None, timeou
self._connected = False
log.init(host=host)

def _file_copy_instance(self, src, dest=None, file_system="flash:"):
def _file_copy_instance(self, src, dest=None, file_system="/mnt/flash"):
# "flash:" is only valid locally, "/mnt/flash" is used externally
if file_system == "flash:":
file_system = "/mnt/flash"
if dest is None:
dest = os.path.basename(src)

Expand Down Expand Up @@ -175,7 +178,7 @@ def boot_options(self):
dict: Key is ``sys`` with value being the image on the device.
"""
image = self.show("show boot-config")["softwareImage"]
image = image.replace("flash:", "")
image = image.replace("flash:/", "")
log.debug("Host %s: the boot options are %s", self.host, {"sys": image})
return {"sys": image}

Expand Down Expand Up @@ -375,7 +378,7 @@ def file_copy(self, src, dest=None, file_system=None):
file_copy = self._file_copy_instance(src, dest, file_system=file_system)

try:
file_copy.enable_scp()
# file_copy.enable_scp()
file_copy.establish_scp_conn()
file_copy.transfer_file()
log.info("Host %s: File %s transferred successfully.", self.host, src)
Expand Down
5 changes: 5 additions & 0 deletions pyntc/devices/ios_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -1029,6 +1029,11 @@ def set_boot_options(self, image_name, **vendor_specifics):
): # TODO: Update to CommandError when deprecating config_list
command = f"boot system switch all {file_system}{image_name}"
self.config(["no boot system", command])

# If boot system is not found in the running config, but it exists in show boot or show bootvar
elif self.boot_options["sys"]:
command = f"boot system {file_system}/{image_name}"
self.config(command)
else:
raise CommandError(
command=command,
Expand Down
1 change: 1 addition & 0 deletions pyntc/devices/iosxewlc_device.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Module for using a Cisco IOSXE WLC device over SSH."""

import time

from pyntc import log
Expand Down
1 change: 1 addition & 0 deletions pyntc/devices/jnpr_device.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Module for using a Juniper junOS device."""

import hashlib
import os
import re
Expand Down
1 change: 1 addition & 0 deletions pyntc/devices/nxos_device.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Module for using an NXOS device over NX-API."""

import os
import re
import time
Expand Down
1 change: 1 addition & 0 deletions pyntc/devices/system_features/vlans/base_vlans.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Base Vlan checks."""

from pyntc.errors import NTCError

from ..base_feature import BaseFeature
Expand Down
1 change: 1 addition & 0 deletions pyntc/errors.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""pyntc custom exceptions."""

import warnings


Expand Down
1 change: 1 addition & 0 deletions pyntc/log.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Logging utilities for Pyntc."""

import os
import logging

Expand Down
1 change: 1 addition & 0 deletions pyntc/utils/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""PyNTC Utilities."""

from .templates import get_structured_data
from .converters import convert_dict_by_key, convert_list_by_key, recursive_key_lookup

Expand Down
1 change: 1 addition & 0 deletions pyntc/utils/templates/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Module to use NTC_TEMPLATES."""

import os
import textfsm

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "pyntc"
version = "2.0.0"
version = "2.0.1"
description = "SDK to simplify common workflows for Network Devices."
authors = ["Network to Code, LLC <[email protected]>"]
readme = "README.md"
Expand Down
1 change: 1 addition & 0 deletions tasks.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Tasks for use with Invoke."""

import os
import sys
from distutils.util import strtobool
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"command": "show boot-config",
"result": {
"memTestIterations": 0,
"softwareImage": "flash:EOS.swi",
"softwareImage": "EOS.swi",
"abootPassword": "(not set)"
},
"encoding": "json"
Expand Down
4 changes: 2 additions & 2 deletions tests/unit/test_devices/test_asa_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@


class TestASADevice:
def setup(self, api):
def setup_method(self, api):
with mock.patch("pyntc.devices.asa_device.ConnectHandler") as api:
if not getattr(self, "device", None):
self.device = ASADevice("host", "user", "password")
Expand All @@ -60,7 +60,7 @@ def setup(self, api):
self.device.native = api
self.count_setup += 1

def teardown(self):
def teardown_method(self):
# Reset the mock so we don't have transient test effects
self.device.native.reset_mock()
self.count_teardown += 1
Expand Down
12 changes: 7 additions & 5 deletions tests/unit/test_devices/test_eos_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,8 +237,10 @@ def test_file_copy(self, mock_open, mock_close, mock_ssh, mock_ft):
mock_ft_instance.check_file_exists.side_effect = [False, True]
self.device.file_copy("path/to/source_file")

mock_ft.assert_called_with(self.device.native_ssh, "path/to/source_file", "source_file", file_system="flash:")
mock_ft_instance.enable_scp.assert_any_call()
mock_ft.assert_called_with(
self.device.native_ssh, "path/to/source_file", "source_file", file_system="/mnt/flash"
)
# mock_ft_instance.enable_scp.assert_any_call()
mock_ft_instance.establish_scp_conn.assert_any_call()
mock_ft_instance.transfer_file.assert_any_call()

Expand All @@ -255,8 +257,8 @@ def test_file_copy_different_dest(self, mock_open, mock_close, mock_ssh, mock_ft
mock_ft_instance.check_file_exists.side_effect = [False, True]
self.device.file_copy("source_file", "dest_file")

mock_ft.assert_called_with(self.device.native_ssh, "source_file", "dest_file", file_system="flash:")
mock_ft_instance.enable_scp.assert_any_call()
mock_ft.assert_called_with(self.device.native_ssh, "source_file", "dest_file", file_system="/mnt/flash")
# mock_ft_instance.enable_scp.assert_any_call()
mock_ft_instance.establish_scp_conn.assert_any_call()
mock_ft_instance.transfer_file.assert_any_call()

Expand Down Expand Up @@ -289,7 +291,7 @@ def test_set_boot_options(self):
[{"result": {"output": "flash:"}}],
[{"result": {"output": "new_image.swi"}}],
[{"result": {}}],
[{"result": {"softwareImage": "flash:new_image.swi"}}],
[{"result": {"softwareImage": "flash:/new_image.swi"}}],
]
calls = [
mock.call(["dir"], encoding="text"),
Expand Down
4 changes: 2 additions & 2 deletions tests/unit/test_devices/test_f5_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def __init__(self, fullPath, version, build):


class TestF5Device:
def setup(self):
def setup_method(self):
with mock.patch("pyntc.devices.f5_device.ManagementRoot") as big_ip:
self.device = F5Device("host", "user", "password")
self.device.api_handler = big_ip
Expand All @@ -40,7 +40,7 @@ def setup(self):

self.count_setup += 1

def teardown(self):
def teardown_method(self):
self.device.api_handler.reset_mock()
self.count_teardown += 1

Expand Down
2 changes: 1 addition & 1 deletion tests/unit/test_devices/test_ios_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -898,7 +898,7 @@ def test_set_boot_options_pass_with_switch_all(mock_save, mock_boot_options, moc

@mock.patch.object(IOSDevice, "_get_file_system")
@mock.patch.object(IOSDevice, "config")
@mock.patch.object(IOSDevice, "boot_options", new_callable=mock.PropertyMock)
@mock.patch.object(IOSDevice, "boot_options", new_callable=lambda: {"sys": None})
@mock.patch.object(IOSDevice, "save")
def test_set_boot_options_raise_commanderror(mock_save, mock_boot_options, mock_config, mock_file_system, ios_show):
device = ios_show(["dir_flash:.txt", "boot flash:c3560-advipservicesk9-mz.122-44.SE.bin"])
Expand Down
Loading