From 71383f19e66840e84c90783bc62c61c11ca0c5f9 Mon Sep 17 00:00:00 2001 From: Mircea Ulinic Date: Wed, 15 Mar 2017 13:56:35 +0000 Subject: [PATCH 1/4] Add commit confirmed feature --- napalm_ios/ios.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/napalm_ios/ios.py b/napalm_ios/ios.py index 2d312f2..f0f0127 100644 --- a/napalm_ios/ios.py +++ b/napalm_ios/ios.py @@ -337,7 +337,7 @@ def _commit_hostname_handler(self, cmd): output = '' return output - def commit_config(self): + def commit_config(self, confirmed=0): """ If replacement operation, perform 'configure replace' for the entire config. @@ -354,6 +354,8 @@ def commit_config(self): raise ReplaceConfigException("Candidate config file does not exist") if self.auto_rollback_on_error: cmd = 'configure replace {} force revert trigger error'.format(cfg_file) + elif confirmed: + cmd = 'configure replace {} force time {}'.format(cfg_file, confirmed) else: cmd = 'configure replace {} force'.format(cfg_file) output = self._commit_hostname_handler(cmd) @@ -372,6 +374,13 @@ def commit_config(self): cmd = 'copy {} running-config'.format(cfg_file) self._disable_confirm() output = self._commit_hostname_handler(cmd) + if confirmed: + # Create the candidate config file + cmd = 'copy running-config {}'.format(self.candidate_cfg) + output += self.device.send_command_expect(cmd) + # Replace with the candidate and force rollback if not confirmed + cmd = 'configure replace {} force time {}'.format(self.candidate_cfg, confirmed) + output += self.device.send_command_expect(cmd) self._enable_confirm() if 'Invalid input detected' in output: self.rollback() @@ -381,6 +390,9 @@ def commit_config(self): # Save config to startup (both replace and merge) output += self.device.send_command_expect("write mem") + def commit_confirm(self): + output = self.device.send_command_expect('configure confirm') + def discard_config(self): """Set candidate_cfg to current running-config. Erase the merge_cfg file.""" discard_candidate = 'copy running-config {}'.format(self._gen_full_path(self.candidate_cfg)) From 343eacd54ac3192a7a893c0f66978d7dcdfc46c2 Mon Sep 17 00:00:00 2001 From: Mircea Ulinic Date: Wed, 15 Mar 2017 14:42:15 +0000 Subject: [PATCH 2/4] wr mem only on definitive commit --- napalm_ios/ios.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/napalm_ios/ios.py b/napalm_ios/ios.py index f0f0127..41bd216 100644 --- a/napalm_ios/ios.py +++ b/napalm_ios/ios.py @@ -387,11 +387,15 @@ def commit_config(self, confirmed=0): merge_error = "Configuration merge failed; automatic rollback attempted" raise MergeConfigException(merge_error) - # Save config to startup (both replace and merge) - output += self.device.send_command_expect("write mem") + if not confirmed: + # Save config to startup (both replace and merge) + output += self.device.send_command_expect("write mem") def commit_confirm(self): + # Confirm replacement of running-config with a new config file output = self.device.send_command_expect('configure confirm') + # Save config to startup (both replace and merge) + output += self.device.send_command_expect("write mem") def discard_config(self): """Set candidate_cfg to current running-config. Erase the merge_cfg file.""" From 2e58ecff77bf3a13c7bc46b337c81df746d1ad64 Mon Sep 17 00:00:00 2001 From: Mircea Ulinic Date: Wed, 15 Mar 2017 14:45:49 +0000 Subject: [PATCH 3/4] config replace requires explicit bootflash: --- napalm_ios/ios.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/napalm_ios/ios.py b/napalm_ios/ios.py index 41bd216..73f0eb9 100644 --- a/napalm_ios/ios.py +++ b/napalm_ios/ios.py @@ -355,7 +355,7 @@ def commit_config(self, confirmed=0): if self.auto_rollback_on_error: cmd = 'configure replace {} force revert trigger error'.format(cfg_file) elif confirmed: - cmd = 'configure replace {} force time {}'.format(cfg_file, confirmed) + cmd = 'configure replace bootflash:{} force time {}'.format(cfg_file, confirmed) else: cmd = 'configure replace {} force'.format(cfg_file) output = self._commit_hostname_handler(cmd) @@ -379,7 +379,8 @@ def commit_config(self, confirmed=0): cmd = 'copy running-config {}'.format(self.candidate_cfg) output += self.device.send_command_expect(cmd) # Replace with the candidate and force rollback if not confirmed - cmd = 'configure replace {} force time {}'.format(self.candidate_cfg, confirmed) + cmd = 'configure replace bootflash:{} force time {}'.format(self.candidate_cfg, + confirmed) output += self.device.send_command_expect(cmd) self._enable_confirm() if 'Invalid input detected' in output: From 7920b5315653d7ff341cfb394d70f1bf64ee2513 Mon Sep 17 00:00:00 2001 From: Mircea Ulinic Date: Wed, 15 Mar 2017 15:24:47 +0000 Subject: [PATCH 4/4] Schedule reverting before modifying the running-config --- napalm_ios/ios.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/napalm_ios/ios.py b/napalm_ios/ios.py index 73f0eb9..97355d3 100644 --- a/napalm_ios/ios.py +++ b/napalm_ios/ios.py @@ -371,17 +371,18 @@ def commit_config(self, confirmed=0): cfg_file = self._gen_full_path(filename) if not self._check_file_exists(cfg_file): raise MergeConfigException("Merge source config file does not exist") - cmd = 'copy {} running-config'.format(cfg_file) self._disable_confirm() - output = self._commit_hostname_handler(cmd) if confirmed: - # Create the candidate config file - cmd = 'copy running-config {}'.format(self.candidate_cfg) - output += self.device.send_command_expect(cmd) - # Replace with the candidate and force rollback if not confirmed - cmd = 'configure replace bootflash:{} force time {}'.format(self.candidate_cfg, + # Replace running config with the rollback config + # And schedule the revert time + # If not confirmed, it will go back to the current running-config state + cmd = 'configure replace bootflash:{} force time {}'.format(self.rollback_cfg, confirmed) - output += self.device.send_command_expect(cmd) + output = self.device.send_command_expect(cmd) + # The rest of the commands will be loaded directly through the normal + # merge into the running-config + cmd = 'copy {} running-config'.format(cfg_file) + output = self._commit_hostname_handler(cmd) self._enable_confirm() if 'Invalid input detected' in output: self.rollback() @@ -393,7 +394,7 @@ def commit_config(self, confirmed=0): output += self.device.send_command_expect("write mem") def commit_confirm(self): - # Confirm replacement of running-config with a new config file + # Confirm replacement of running-config output = self.device.send_command_expect('configure confirm') # Save config to startup (both replace and merge) output += self.device.send_command_expect("write mem")