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

Make AireOS FileTransferErrors more granular #161

Merged
merged 2 commits into from
Nov 17, 2020
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
31 changes: 20 additions & 11 deletions pyntc/devices/aireos_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@
from netmiko import ConnectHandler

from .base_device import BaseDevice, fix_docs
from .system_features.file_copy.base_file_copy import FileTransferError
from pyntc.errors import (
NTCError,
CommandError,
OSInstallError,
WLANEnableError,
CommandListError,
WLANDisableError,
FileTransferError,
RebootTimeoutError,
NTCFileNotFoundError,
)
Expand Down Expand Up @@ -133,14 +133,17 @@ def _image_booted(self, image_name, **vendor_specifics):

return False

def _send_command(self, command, expect_string=None):
def _send_command(self, command, expect_string=None, **kwargs):
"""
Send single command to device.

Args:
command (str): The command to send to the device.
expect_string (str): The expected prompt after running the command.

Kwargs:
Any argument supported by Netmiko's ``send_command_timing`` method.

Returns:
str: The response from the device after issuing the ``command``.

Expand All @@ -157,9 +160,9 @@ def _send_command(self, command, expect_string=None):
>>>
"""
if expect_string is None:
response = self.native.send_command_timing(command)
response = self.native.send_command_timing(command, **kwargs)
else:
response = self.native.send_command(command, expect_string=expect_string)
response = self.native.send_command(command, expect_string=expect_string, **kwargs)

if "Incorrect usage" in response or "Error:" in response:
raise CommandError(command, response)
Expand Down Expand Up @@ -676,12 +679,15 @@ def file_copy(
f"transfer download filename {filename}",
]
)
response = self.native.send_command_timing("transfer download start")
if "Are you sure you want to start? (y/N)" in response:
response = self.native.send_command(
"y", expect_string="File transfer is successful.", delay_factor=delay_factor
)
except CommandListError as error:
raise FileTransferError(error.message)

try:
response = self.show("transfer download start")
if "Are you sure you want to start? (y/N)" in response:
response = self.show("y", expect_string="File transfer is successful.", delay_factor=delay_factor)
except CommandError as error:
raise FileTransferError(message=f"{FileTransferError.default_message}\n\n{error.message}")
except: # noqa E722
raise FileTransferError

Expand Down Expand Up @@ -974,14 +980,17 @@ def set_boot_options(self, image_name, **vendor_specifics):
message="Setting boot command did not yield expected results",
)

def show(self, command, expect_string=None):
def show(self, command, expect_string=None, **kwargs):
"""
Send an operational command to the device.

Args:
command (str): The command to send to the device.
expect_string (str): The expected prompt after running the command.

Kwargs:
Any argument supported by Netmiko's ``send_command_timing`` method.

Returns:
str: The data returned from the device

Expand All @@ -998,7 +1007,7 @@ def show(self, command, expect_string=None):
>>>
"""
self.enable()
return self._send_command(command, expect_string=expect_string)
return self._send_command(command, expect_string=expect_string, **kwargs)

def show_list(self, commands):
"""
Expand Down
10 changes: 5 additions & 5 deletions pyntc/devices/asa_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@

from pyntc.utils import get_structured_data
from .base_device import BaseDevice, fix_docs
from .system_features.file_copy.base_file_copy import FileTransferError
from pyntc.errors import (
NTCError,
CommandError,
OSInstallError,
CommandListError,
FileSystemNotFoundError,
NTCError,
NTCFileNotFoundError,
FileTransferError,
RebootTimeoutError,
OSInstallError,
NTCFileNotFoundError,
FileSystemNotFoundError,
)


Expand Down
4 changes: 0 additions & 4 deletions pyntc/devices/base_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -371,10 +371,6 @@ def refresh_facts(self):
return self.facts


class FileTransferError(NTCError):
pass


class RebootTimerError(NTCError):
def __init__(self, device_type):
super().__init__("Reboot timer not supported on %s." % device_type)
Expand Down
10 changes: 5 additions & 5 deletions pyntc/devices/eos_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@
from .system_features.vlans.eos_vlans import EOSVlans
from .base_device import BaseDevice, RollbackError, RebootTimerError, fix_docs
from pyntc.errors import (
NTCError,
CommandError,
OSInstallError,
CommandListError,
FileSystemNotFoundError,
NTCError,
NTCFileNotFoundError,
FileTransferError,
RebootTimeoutError,
OSInstallError,
NTCFileNotFoundError,
FileSystemNotFoundError,
)
from .system_features.file_copy.base_file_copy import FileTransferError


BASIC_FACTS_KM = {"model": "modelName", "os_version": "internalVersion", "serial_number": "serialNumber"}
Expand Down
3 changes: 1 addition & 2 deletions pyntc/devices/f5_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,8 @@
import requests
from f5.bigip import ManagementRoot

from pyntc.errors import NotEnoughFreeSpaceError, OSInstallError, NTCFileNotFoundError
from pyntc.errors import OSInstallError, FileTransferError, NTCFileNotFoundError, NotEnoughFreeSpaceError
from .base_device import BaseDevice
from .system_features.file_copy.base_file_copy import FileTransferError


class F5Device(BaseDevice):
Expand Down
10 changes: 5 additions & 5 deletions pyntc/devices/ios_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,16 @@
from netmiko import FileTransfer

from pyntc.utils import convert_dict_by_key, get_structured_data
from .system_features.file_copy.base_file_copy import FileTransferError
from .base_device import BaseDevice, RollbackError, fix_docs
from pyntc.errors import (
CommandError,
CommandListError,
FileSystemNotFoundError,
NTCError,
NTCFileNotFoundError,
CommandError,
OSInstallError,
CommandListError,
FileTransferError,
RebootTimeoutError,
NTCFileNotFoundError,
FileSystemNotFoundError,
)


Expand Down
3 changes: 1 addition & 2 deletions pyntc/devices/jnpr_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@
from .tables.jnpr.loopback import LoopbackTable
from .base_device import BaseDevice, fix_docs

from pyntc.errors import CommandError, CommandListError, RebootTimeoutError
from .system_features.file_copy.base_file_copy import FileTransferError
from pyntc.errors import CommandError, CommandListError, FileTransferError, RebootTimeoutError


@fix_docs
Expand Down
10 changes: 8 additions & 2 deletions pyntc/devices/nxos_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,15 @@
import re
import time

from .system_features.file_copy.base_file_copy import FileTransferError
from .base_device import BaseDevice, RollbackError, RebootTimerError, fix_docs
from pyntc.errors import CommandError, CommandListError, NTCFileNotFoundError, RebootTimeoutError, OSInstallError
from pyntc.errors import (
CommandError,
OSInstallError,
CommandListError,
FileTransferError,
RebootTimeoutError,
NTCFileNotFoundError,
)

from pynxos.device import Device as NXOSNative
from pynxos.features.file_copy import FileTransferError as NXOSFileTransferError
Expand Down
Empty file.
17 changes: 0 additions & 17 deletions pyntc/devices/system_features/file_copy/base_file_copy.py

This file was deleted.

12 changes: 12 additions & 0 deletions pyntc/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ def __init__(self, filename):

class CommandError(NTCError):
def __init__(self, command, message):
self.command = command
self.cli_error_msg = message
message = "Command %s was not successful: %s" % (command, message)
super().__init__(message)
Expand Down Expand Up @@ -56,6 +57,17 @@ def __init__(self, hostname, command):
super().__init__(message)


class FileTransferError(NTCError):
default_message = (
"An error occurred during transfer. "
"Please make sure the local file exists and "
"that appropriate permissions are set on the remote device."
)

def __init__(self, message=None):
super().__init__(message or self.default_message)


class RebootTimeoutError(NTCError):
def __init__(self, hostname, wait_time):
message = "Unable to reconnect to {0} after {1} seconds".format(hostname, wait_time)
Expand Down
2 changes: 1 addition & 1 deletion test/unit/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ def _mock(side_effects, existing_device=None, device=aireos_device):
device = existing_device
with mock.patch.object(AIREOSDevice, "show_list") as mock_show_list:
mock_show_list.side_effect = get_side_effects(aireos_mock_path, side_effects)
device.show = mock_show_list
device.show_list = mock_show_list
return device

return _mock
Expand Down
Loading