def load_merge_candidate(self, filename=None, config=None): """ Only configuration in set-format is supported with load_merge_candidate. """ if not filename and not config: raise MergeConfigException( 'filename or config param must be provided.') if filename is None: temp_file = tempfile.NamedTemporaryFile() temp_file.write(config) temp_file.flush() cfg_filename = temp_file.name else: cfg_filename = filename if os.path.exists(cfg_filename) is True: with open(cfg_filename) as f: self.device.send_command("cp " + self._BOOT_FILENAME + " " + self._BACKUP_FILENAME) self._new_config = f.read() cfg = [x for x in self._new_config.split("\n") if x is not ""] output_loadcmd = self.device.send_config_set(cfg) match_setfailed = re.findall("Delete failed", output_loadcmd) match_delfailed = re.findall("Set failed", output_loadcmd) if match_setfailed or match_delfailed: raise MergeConfigException("Failed merge config: " + output_loadcmd) else: raise MergeConfigException("config file is not found")
def _commit_merge(self): commands = [ command for command in self.merge_candidate.splitlines() if command ] output = '' try: output += self.device.send_command('system-view', expect_string=r'\[.+\]') for command in commands: output += self.device.send_command(command, expect_string=r'\[.+\]') if self.device.check_config_mode(): check_error = re.search("error", output, re.IGNORECASE) if check_error is not None: return_log = self.device.send_command( 'return', expect_string=r'[<\[].+[>\]]') if 'Uncommitted configurations' in return_log: # Discard uncommitted configuration return_log += self.device.send_command( 'n', expect_string=r'<.+>') output += return_log raise MergeConfigException('Error while applying config!') output += self.device.send_command('commit', expect_string=r'\[.+\]') output += self.device.send_command('return', expect_string=r'<.+>') else: raise MergeConfigException('Not in configuration mode.') except Exception as e: msg = str(e) + '\nconfiguration output: ' + output raise MergeConfigException(msg)
def load_merge_candidate(self, filename=None, config=None): if not filename and not config: raise MergeConfigException('filename or config param must be provided.') self._send_command('cp /etc/config/config.xml /etc/config/config-napalm.bak') if filename is not None: with open(filename, 'r') as f: candidate = [line.strip() for line in f if line.strip()] # strip blanks else: candidate = config.splitlines() if not isinstance(candidate, list): candidate = [candidate] candidate = ["=".join(line.split(" ", 1)) for line in candidate if line] command = 'sudo config' for line in candidate: if line.strip(): # skip blank lines from creating a `config -d ""` if '=' not in line: # assignment via `=` means set a vaule command += ' -d "{0}"'.format(line.strip()) else: # no assignment, means delete the value command += " -s '{0}'".format(line.strip()) output = self._send_command(command) if "error" in output or "not found" in output: raise MergeConfigException("Command '{0}' cannot be applied.".format(command)) self.loaded = True
def load_merge_candidate(self, filename=None, config=None): if not filename and not config: raise MergeConfigException( 'filename or config param must be provided.') self._send_command( 'cp /etc/config/config.xml /etc/config/config-napalm.bak') if filename is not None: with open(filename, 'r') as f: candidate = f.readlines() else: candidate = config if not isinstance(candidate, list): candidate = [candidate] candidate = [ "=".join(line.split(" ", 1)) for line in candidate if line ] for command in candidate: if 'sudo config -s' not in command: command = 'sudo config -s {0}'.format(command) print(command) output = self._send_command(command) if "error" in output or "not found" in output: raise MergeConfigException( "Command '{0}' cannot be applied.".format(command)) self.loaded = True
def _commit_merge(self): try: output = self._send_config(self.merge_candidate) if output and 'Invalid command' in output: raise MergeConfigException('Error while applying config!') except Exception as e: self.changed = True self.rollback() raise MergeConfigException(str(e)) self.changed = True # clear the merge buffer self.merge_candidate = ''
def _commit_merge(self): try: commands = [ command for command in self.merge_candidate.splitlines() if command ] output = self.device.send_config_set(commands) except Exception as e: raise MergeConfigException(str(e)) if 'Invalid command' in output: raise MergeConfigException('Error while applying config!') # clear the merge buffer self.merge_candidate = ''
def _get_file_content(self, filename): try: with open(filename, 'r') as f: content = f.read() except IOError: raise MergeConfigException('Error while opening {0}. Make sure ' 'filename is correct.'.format(filename)) return content
def _commit_merge(self): commands = [ command for command in self.merge_candidate.splitlines() if command ] output = '' ####TESTING#### print("INSIDE ce.py line: 1089") ##TESTING for command in commands: ##TESTING print(command, flush=True) ##TESTING try: output += self.device.send_command('system-view', expect_string=r'\[.+\]') #commands = ['interface GigabitEthernet0/0/10', 'description :r=qt200-eslvs-1:q=e0:t=access:p=ttt:i=OGHP1113:ci=ADO3:sev=5:x=123'] #:r=qt200-eslvs-1:q=e0:t=access:p=ttt:i=OGHP1113:ci=ADO3:sev=5:x=123 for command in commands: print("INSIDE ce.py line: 1096") ##TESTING print(type(command), flush=True) ##TESTING print(command, flush=True) ##TESTING output += self.device.send_command(command, expect_string=r'\[.+\]') print("THE CURRENT OUTPUT IS:" + output, flush=True) ##TESTING if self.device.check_config_mode(): check_error = re.search("error", output, re.IGNORECASE) print("Inside ce.py line:1106 (commands have been pushed)", flush=True) ##TESTING if check_error is not None: return_log = self.device.send_command( 'return', expect_string=r'[<\[].+[>\]]') if 'Uncommitted configurations' in return_log: # Discard uncommitted configuration return_log += self.device.send_command( 'n', expect_string=r'<.+>') output += return_log raise MergeConfigException('Error while applying config!') output += self.device.send_command('commit', expect_string=r'\[.+\]') output += self.device.send_command('return', expect_string=r'<.+>') else: raise MergeConfigException('Not in configuration mode.') except Exception as e: msg = str(e) + '\nconfiguration output: ' + output raise MergeConfigException(msg)
def _commit_merge(self): try: commands = [ command for command in self.merge_candidate.splitlines() if command ] self.device.config_list(commands) except Exception as e: raise MergeConfigException(str(e)) # clear the merge buffer self.merge_candidate = ''
def commit_config(self): """Implementation of NAPALM method commit_config.""" if self.loaded: if self.replace: try: self.device.commit_replace_config() except Exception as e: self.device.rollback() raise ReplaceConfigException(str(e)) else: try: self.device.commit_config() except Exception as e: self.device.rollback() raise MergeConfigException(str(e)) else: raise MergeConfigException('No config loaded.') self.changed = True self.loaded = False
def load_merge_candidate(self, filename=None, config=None): """ Populates the candidate configuration. You can populate it from a file or from a string. If you send both a filename and a string containing the configuration, the file takes precedence. If you use this method the existing configuration will be merged with the candidate configuration once you commit the changes. This method will not change the configuration by itself. :param filename: Path to the file containing the desired configuration. By default is None. :param config: String containing the desired configuration. :raise MergeConfigException: If there is an error on the configuration sent. """ file_content = "" if filename is None and config is None: # if nothing is entered returns none print("No filename or config was entered") return None if filename is not None: try: file_content = open(filename, "r") # attempts to open file temp = file_content.read() # stores file content self.config_merge = FastIronDriver.__creates_list_of_nlines( temp) self.merge_config = True # file opened successfully return except ValueError: raise MergeConfigException("Configuration error") if config is not None: try: self.config_merge = FastIronDriver.__creates_list_of_nlines( config) self.merge_config = True # string successfully saved return except ValueError: raise MergeConfigException("Configuration error") raise MergeConfigException("Configuration error")
def load_merge_candidate(self, filename=None, config=None): if not filename and not config: raise MergeConfigException('filename or config param must be provided.') self.merge_candidate += '\n' # insert one extra line if filename is not None: with open(filename, "r") as f: self.merge_candidate += f.read() else: self.merge_candidate += config self.replace = False self.loaded = True
def load_merge_candidate(self, filename=None, config=None): if not filename and not config: raise MergeConfigException("filename or config param must be provided.") self.loaded = True if filename is not None: with open(filename, "r") as f: candidate = f.readlines() else: candidate = config if not isinstance(candidate, list): candidate = [candidate] candidate = [line for line in candidate if line] for command in candidate: output = self._send_command(command) if "error" in output or "not found" in output: raise MergeConfigException( "Command '{0}' cannot be applied.".format(command) )
def load_merge_candidate(self, filename=None, config=None): if filename: file_config = True content = self._get_file_content(filename) config = content.splitlines() self._send_merge_commands(config, file_config) elif config: file_config = False self._send_merge_commands(config, file_config) else: raise MergeConfigException('You must provide either a file ' 'or a set-format string')
def load_merge_candidate(self, filename=None, config=None): """ SCP file to remote device. Merge configuration in: copy <file> running-config """ self.config_replace = False return_status, msg = self._load_candidate_wrapper( source_file=filename, source_config=config, dest_file=self.merge_cfg, ) if not return_status: raise MergeConfigException(msg)
def commit_config(self): if self.loaded: self.backup_file = 'config_' + str(datetime.now()).replace( ' ', '_') self._save_config(self.backup_file) if self.replace: if self._load_config() is False: raise ReplaceConfigException else: try: self._commit_merge() self.merge_candidate = '' # clear the merge buffer except Exception as e: raise MergeConfigException(str(e)) self.changed = True self.loaded = False else: raise ReplaceConfigException('No config loaded.')
def commit_config(self): """ Netmiko is being used to commit the configuration because it takes a better care of results compared to pan-python. """ if self.loaded: if self.ssh_connection is False: self._open_ssh() try: self.ssh_device.commit() time.sleep(3) self.loaded = False self.changed = True except: # noqa if self.merge_config: raise MergeConfigException('Error while commiting config') else: raise ReplaceConfigException( 'Error while commiting config') else: raise ReplaceConfigException('No config loaded.')
def _send_merge_commands(self, config, file_config): """ Netmiko is being used to push set commands. """ if self.loaded is False: if self._save_backup() is False: raise MergeConfigException('Error while storing backup ' 'config.') if self.ssh_connection is False: self._open_ssh() if file_config: if isinstance(config, str): config = config.splitlines() else: if isinstance(config, str): config = str(config).split() self.ssh_device.send_config_set(config) self.loaded = True self.merge_config = True
def load_merge_candidate(self, filename=None, config=None): """Merge candidate configuration with the running one.""" """ Imperative config change: Merge new config with existing one. There's no config validation nor atomic commit!. Only configuration commands are supported, "configure terminal" is not required. Use with caution. """ if filename is not None: config = self._read_candidate(filename) if config is not None: if isinstance(config, str): config = config.split('\n') if not self._config_batch(cmd_list=config): raise MergeConfigException("Configuration merge failed") # mimic load_replace_candidate behaviour, by making sure candidate # config exactly matches our merged configuration self._backup_config(destination='REST_Payload_Backup')