From 800e8d70bba48320e970e29ee3c2219d5b7faf01 Mon Sep 17 00:00:00 2001 From: Austin de Coup-Crank <94914780+decoupca@users.noreply.github.com> Date: Mon, 25 Mar 2024 20:55:19 -0500 Subject: [PATCH] Closes #2005: Change rollback behavior (#2006) --- napalm/nxos/nxos.py | 33 +++++++++++++++++++++++++++++---- napalm/nxos_ssh/nxos_ssh.py | 33 ++++++++++++++++++--------------- 2 files changed, 47 insertions(+), 19 deletions(-) diff --git a/napalm/nxos/nxos.py b/napalm/nxos/nxos.py index b975029ef..fbbffc44d 100644 --- a/napalm/nxos/nxos.py +++ b/napalm/nxos/nxos.py @@ -191,6 +191,29 @@ def _send_command( ) -> Dict[str, Union[str, Dict[str, Any]]]: raise NotImplementedError + def _check_file_exists(self, cfg_file: str) -> bool: + """ + Check that the file exists on remote device using full path. + + cfg_file can be a full path, e.g.: bootflash:rollback_config.txt + or just a filename, e.g.: rollback_config.txt + + For example + # dir rollback_config.txt + 71803 Sep 06 14:13:33 2023 rollback_config.txt + + Usage for bootflash://sup-local + 6211682304 bytes used + 110314684416 bytes free + 116526366720 bytes total + """ + cmd = f"dir {cfg_file}" + output = self._send_command(command=cmd, raw_text=True) + if "No such file or directory" in output: + return False + else: + return True + def _commit_merge(self) -> None: try: output = self._send_config(self.merge_candidate) @@ -918,10 +941,12 @@ def _load_cfg_from_checkpoint(self) -> None: def rollback(self) -> None: assert isinstance(self.device, NXOSDevice) - if self.changed: - self.device.rollback(self.rollback_cfg) - self._copy_run_start() - self.changed = False + if not self._check_file_exists(cfg_file=self.rollback_cfg): + msg = f"Rollback file '{self.rollback_cfg}' does not exist on device." + raise ReplaceConfigException(msg) + self.device.rollback(self.rollback_cfg) + self._copy_run_start() + self.changed = False def get_facts(self) -> models.FactsDict: facts: models.FactsDict = {} # type: ignore diff --git a/napalm/nxos_ssh/nxos_ssh.py b/napalm/nxos_ssh/nxos_ssh.py index 04896c9cc..3bfa46ec9 100644 --- a/napalm/nxos_ssh/nxos_ssh.py +++ b/napalm/nxos_ssh/nxos_ssh.py @@ -553,21 +553,24 @@ def _load_cfg_from_checkpoint(self): raise ReplaceConfigException(msg) def rollback(self): - if self.changed: - commands = [ - "terminal dont-ask", - "rollback running-config file {}".format(self.rollback_cfg), - "no terminal dont-ask", - ] - result = self._send_command_list( - commands, expect_string=r"[#>]", read_timeout=90 - ) - if "completed" not in result.lower(): - raise ReplaceConfigException(result) - # If hostname changes ensure Netmiko state is updated properly - self._netmiko_device.set_base_prompt() - self._copy_run_start() - self.changed = False + if not self._check_file_exists(self.rollback_cfg): + msg = f"Rollback file '{self.rollback_cfg}' does not exist on device." + raise ReplaceConfigException(msg) + + commands = [ + "terminal dont-ask", + "rollback running-config file {}".format(self.rollback_cfg), + "no terminal dont-ask", + ] + result = self._send_command_list( + commands, expect_string=r"[#>]", read_timeout=90 + ) + if "completed" not in result.lower(): + raise ReplaceConfigException(result) + # If hostname changes ensure Netmiko state is updated properly + self._netmiko_device.set_base_prompt() + self._copy_run_start() + self.changed = False def _apply_key_map(self, key_map, table): new_dict = {}