From 566efe3596b1e353aac26c1356f4ffd59420d58a Mon Sep 17 00:00:00 2001 From: Pim van Pelt Date: Sun, 3 Apr 2022 09:49:27 +0000 Subject: [PATCH] Add a CLI output emitter (either to stdout or to filename), based on plan --output/-o flag --- vpp/reconciler.py | 40 ++++++++++++++++++++++++++++++++-------- vppcfg | 4 ++++ 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/vpp/reconciler.py b/vpp/reconciler.py index f351076..46a7621 100644 --- a/vpp/reconciler.py +++ b/vpp/reconciler.py @@ -13,6 +13,7 @@ # limitations under the License. # # -*- coding: utf-8 -*- +import sys import logging import config.loopback as loopback import config.interface as interface @@ -103,10 +104,6 @@ class Reconciler(): if not self.prune_phys(): self.logger.warning("Could not prune PHYs from VPP") ret = False - - for cli in self.cli['prune']: - print(cli) - return ret def prune_addresses(self, ifname, address_list): @@ -561,8 +558,6 @@ class Reconciler(): if not self.create_lcps(): self.logger.warning("Could not create LCPs in VPP") ret = False - for cli in self.cli['create']: - print(cli) return ret def create_loopbacks(self): @@ -684,8 +679,6 @@ class Reconciler(): if not self.sync_admin_state(): self.logger.warning("Could not sync interface adminstate in VPP") ret = False - for cli in self.cli['sync']: - print(cli) return ret def sync_bondethernets(self): @@ -937,3 +930,34 @@ class Reconciler(): cli="set interface state %s %s" % (vpp_ifname, state) self.cli['sync'].append(cli); return True + + def write(self, outfile, ok=False): + """ Emit the CLI contents to stdout (if outfile=='-') or a named file otherwise. + If the 'ok' flag is False, emit a warning at the top and bottom of the file. + """ + # Assemble the intended output into a list + output = [] + if not ok: + output.append("comment { vppcfg: Planning failed, be careful with this output! }") + + for phase in [ "prune", "create", "sync" ]: + n = len(self.cli[phase]) + if n > 0: + output.append("comment { vppcfg %s: %d CLI statement(s) follow }" % (phase, n)) + output.extend(self.cli[phase]) + + if not ok: + output.append("comment { vppcfg: Planning failed, be careful with this output! }") + + # Emit the output list to stdout or a file + if outfile and outfile == '-': + fh = sys.stdout + outfile = "(stdout)" + else: + fh = open(outfile, 'w') + if len(output) > 0: + print('\n'.join(output), file=fh) + if fh is not sys.stdout: + fh.close() + + self.logger.info("Wrote %d lines to %s" % (len(output), outfile)) diff --git a/vppcfg b/vppcfg index c28625a..f7239af 100755 --- a/vppcfg +++ b/vppcfg @@ -50,6 +50,8 @@ def main(): if args.quiet: level = logging.WARNING logging.basicConfig(format='[%(levelname)-8s] %(name)s.%(funcName)s: %(message)s', level=level) + if not args.command: + args.command="check" ## Default check-only try: with open(args.config, "r") as f: @@ -106,6 +108,8 @@ def main(): failed = True logging.warning("Planning sync failure, continuing due to --force") + r.write(args.outfile, ok=not failed) + if failed: logging.error("Planning failed") sys.exit(-40)