From 26d9f82fefdf38c67101986bbe40c2fd17e1838d Mon Sep 17 00:00:00 2001 From: SeiyaFunaokaJP Date: Thu, 23 Jul 2026 00:31:09 +0900 Subject: [PATCH] feat: support refresh command for latest FITELnet --- netmiko/furukawa/furukawa_fitelnet.py | 52 ++++++++++++++++++--------- 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/netmiko/furukawa/furukawa_fitelnet.py b/netmiko/furukawa/furukawa_fitelnet.py index 631e10e4b..1ccb6d1ea 100644 --- a/netmiko/furukawa/furukawa_fitelnet.py +++ b/netmiko/furukawa/furukawa_fitelnet.py @@ -123,22 +123,16 @@ def exit_enable_mode(self, exit_command: str = "disable") -> str: raise ValueError("Failed to exit enable mode.") return output - def commit( - self, - read_timeout: float = 120.0, - ) -> str: - """ - Commit the candidate configuration on the FITELnet device. + def _apply_config(self, cmd: str, read_timeout: float) -> str: + """Send a configuration-apply command and handle FITELnet's responses. - Applies the working.cfg (candidate) to current.cfg (running). - - commit may prompt with '[y/n]' for confirmation. + Shared by commit() and refresh(). """ output = "" confirmation = r"onfirm|\[y/[nN]\]" pattern = rf"(?:#|{confirmation})" new_data = self._send_command_str( - "commit", + cmd, expect_string=pattern, strip_prompt=False, strip_command=False, @@ -158,22 +152,48 @@ def commit( output += new_data - # FITELnet refuses commit while another session/process is active with - # "Another processing is executing. This command can not be executed." - # The message contains neither "error" nor "failed", so it must be - # detected separately before the generic error check below. + # FITELnet refuses to apply the config while another session/process is + # active with "Another processing is executing. This command can not be + # executed." The message contains neither "error" nor "failed", so it + # must be detected separately before the generic error check below. if "Another processing is executing" in output: raise ValueError( - "Commit failed: another process is executing on the device. " + f"'{cmd}' failed: another process is executing on the device. " "Retry once the other operation completes." ) # FITELnet emits in all caps; match case-insensitively. if re.search(r"error|failed", output, re.IGNORECASE): - raise ValueError(f"Commit failed with the following errors:\n\n{output}") + raise ValueError(f"'{cmd}' failed with the following errors:\n\n{output}") return output + def commit( + self, + read_timeout: float = 120.0, + ) -> str: + """ + Commit the candidate configuration on the FITELnet device. + + Applies the working.cfg (candidate) to current.cfg (running). + + Newer FITELnet models apply the candidate configuration with 'refresh' + instead of 'commit' -- use refresh() on those platforms. + """ + return self._apply_config("commit", read_timeout=read_timeout) + + def refresh( + self, + read_timeout: float = 120.0, + ) -> str: + """ + Apply the candidate configuration using 'refresh'. + + This is the equivalent of commit() on newer FITELnet models, where + 'commit' is not available. + """ + return self._apply_config("refresh", read_timeout=read_timeout) + def save_config( self, cmd: str = "save",