diff --git a/tools/frr-reload.py b/tools/frr-reload.py index e182c77c78..56be1b29b1 100755 --- a/tools/frr-reload.py +++ b/tools/frr-reload.py @@ -114,7 +114,7 @@ class Config(object): self.lines = [] self.contexts = OrderedDict() - def load_from_file(self, filename): + def load_from_file(self, filename, bindir, confdir): """ Read configuration from specified file and slurp it into internal memory The internal representation has been marked appropriately by passing it @@ -123,7 +123,7 @@ class Config(object): log.info('Loading Config object from file %s', filename) try: - file_output = subprocess.check_output(['/usr/bin/vtysh', '-m', '-f', filename], + file_output = subprocess.check_output([str(bindir + '/vtysh'), '-m', '-f', filename, '--config_dir', confdir], stderr=subprocess.STDOUT) except subprocess.CalledProcessError as e: ve = VtyshMarkException(e) @@ -144,7 +144,7 @@ class Config(object): self.load_contexts() - def load_from_show_running(self): + def load_from_show_running(self, bindir, confdir): """ Read running configuration and slurp it into internal memory The internal representation has been marked appropriately by passing it @@ -154,7 +154,7 @@ class Config(object): try: config_text = subprocess.check_output( - "/usr/bin/vtysh -c 'show run' | /usr/bin/tail -n +4 | /usr/bin/vtysh -m -f -", + bindir + "/vtysh --config_dir " + confdir + " -c 'show run' | /usr/bin/tail -n +4 | " + bindir + "/vtysh --config_dir " + confdir + " -m -f -", shell=True, stderr=subprocess.STDOUT) except subprocess.CalledProcessError as e: ve = VtyshMarkException(e) @@ -528,13 +528,15 @@ end self.save_contexts(ctx_keys, current_context_lines) -def line_to_vtysh_conft(ctx_keys, line, delete): +def line_to_vtysh_conft(ctx_keys, line, delete, bindir, confdir): """ Return the vtysh command for the specified context line """ cmd = [] - cmd.append('vtysh') + cmd.append(str(bindir + '/vtysh')) + cmd.append('--config_dir') + cmd.append(confdir) cmd.append('-c') cmd.append('conf t') @@ -1074,7 +1076,7 @@ def compare_context_objects(newconf, running): -def vtysh_config_available(): +def vtysh_config_available(bindir, confdir): """ Return False if no frr daemon is running or some other vtysh session is in 'configuration terminal' mode which will prevent us from making any @@ -1082,7 +1084,7 @@ def vtysh_config_available(): """ try: - cmd = ['/usr/bin/vtysh', '-c', 'conf t'] + cmd = [str(bindir + '/vtysh'), '--config_dir', confdir, '-c', 'conf t'] output = subprocess.check_output(cmd, stderr=subprocess.STDOUT).strip() if 'VTY configuration is locked by other VTY' in output.decode('utf-8'): @@ -1110,6 +1112,9 @@ if __name__ == '__main__': parser.add_argument('--stdout', action='store_true', help='Log to STDOUT', default=False) parser.add_argument('filename', help='Location of new frr config file') parser.add_argument('--overwrite', action='store_true', help='Overwrite frr.conf with running config output', default=False) + parser.add_argument('--bindir', help='path to the vtysh executable', default='/usr/bin') + parser.add_argument('--confdir', help='path to the daemon config files', default='/etc/frr') + parser.add_argument('--rundir', help='path for the temp config file', default='/var/run/frr') args = parser.parse_args() # Logging @@ -1149,8 +1154,22 @@ if __name__ == '__main__': log.error(msg) sys.exit(1) + # Verify that confdir is correct + if not os.path.isdir(args.confdir): + msg = "Confdir %s is not a valid path" % args.confdir + print(msg) + log.error(msg) + sys.exit(1) + + # Verify that bindir is correct + if not os.path.isdir(args.bindir) or not os.path.isfile(args.bindir + '/vtysh'): + msg = "Bindir %s is not a valid path to vtysh" % args.bindir + print(msg) + log.error(msg) + sys.exit(1) + # Verify that 'service integrated-vtysh-config' is configured - vtysh_filename = '/etc/frr/vtysh.conf' + vtysh_filename = args.confdir + '/vtysh.conf' service_integrated_vtysh_config = True if os.path.isfile(vtysh_filename): @@ -1175,7 +1194,7 @@ if __name__ == '__main__': # Create a Config object from the config generated by newconf newconf = Config() - newconf.load_from_file(args.filename) + newconf.load_from_file(args.filename, args.bindir, args.confdir) reload_ok = True if args.test: @@ -1184,9 +1203,9 @@ if __name__ == '__main__': running = Config() if args.input: - running.load_from_file(args.input) + running.load_from_file(args.input, args.bindir, args.confdir) else: - running.load_from_show_running() + running.load_from_show_running(args.bindir, args.confdir) (lines_to_add, lines_to_del) = compare_context_objects(newconf, running) lines_to_configure = [] @@ -1220,7 +1239,7 @@ if __name__ == '__main__': elif args.reload: # We will not be able to do anything, go ahead and exit(1) - if not vtysh_config_available(): + if not vtysh_config_available(args.bindir, args.confdir): sys.exit(1) log.debug('New Frr Config\n%s', newconf.get_lines()) @@ -1264,7 +1283,7 @@ if __name__ == '__main__': for x in range(2): running = Config() - running.load_from_show_running() + running.load_from_show_running(args.bindir, args.confdir) log.debug('Running Frr Config (Pass #%d)\n%s', x, running.get_lines()) (lines_to_add, lines_to_del) = compare_context_objects(newconf, running) @@ -1296,7 +1315,7 @@ if __name__ == '__main__': # 'no' commands are tricky, we can't just put them in a file and # vtysh -f that file. See the next comment for an explanation # of their quirks - cmd = line_to_vtysh_conft(ctx_keys, line, True) + cmd = line_to_vtysh_conft(ctx_keys, line, True, args.bindir, args.confdir) original_cmd = cmd # Some commands in frr are picky about taking a "no" of the entire line. @@ -1352,7 +1371,7 @@ if __name__ == '__main__': string.ascii_uppercase + string.digits) for _ in range(6)) - filename = "/var/run/frr/reload-%s.txt" % random_string + filename = args.rundir + "/reload-%s.txt" % random_string log.info("%s content\n%s" % (filename, pformat(lines_to_configure))) with open(filename, 'w') as fh: @@ -1360,15 +1379,15 @@ if __name__ == '__main__': fh.write(line + '\n') try: - subprocess.check_output(['/usr/bin/vtysh', '-f', filename], stderr=subprocess.STDOUT) + subprocess.check_output([str(args.bindir + '/vtysh'), '--config_dir', args.confdir, '-f', filename], stderr=subprocess.STDOUT) except subprocess.CalledProcessError as e: log.warning("frr-reload.py failed due to\n%s" % e.output) reload_ok = False os.unlink(filename) # Make these changes persistent - if args.overwrite or args.filename != '/etc/frr/frr.conf': - subprocess.call(['/usr/bin/vtysh', '-c', 'write']) + if args.overwrite or args.filename != str(args.confdir + '/frr.conf'): + subprocess.call([str(args.bindir + '/vtysh'), '--config_dir', args.confdir, '-c', 'write']) if not reload_ok: sys.exit(1)