Skip to content

Commit

Permalink
Make AireOS FileTransferErrors more granular (#161)
Browse files Browse the repository at this point in the history
  • Loading branch information
jmcgill298 authored Nov 17, 2020
1 parent d602426 commit 44078c0
Show file tree
Hide file tree
Showing 15 changed files with 199 additions and 100 deletions.
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

0 comments on commit 44078c0

Please sign in to comment.