Check for the existence of LCP config statements, and if so, require linux-cp or lcpng plugins are enabled in VPP

This commit is contained in:
Pim van Pelt
2022-04-02 20:16:51 +00:00
parent 240fcebbcf
commit f786a00e9a
3 changed files with 65 additions and 18 deletions

View File

@ -36,6 +36,13 @@ class Reconciler():
def __del__(self): def __del__(self):
self.vpp.disconnect() self.vpp.disconnect()
def lcps_exist_with_lcp_enabled(self):
""" Returns False if there are LCPs defined in the configuration, but LinuxCP
functionality is not enabled in VPP. """
if not lcp.get_lcps(self.cfg):
return True
return self.vpp.lcp_enabled
def phys_exist_in_vpp(self): def phys_exist_in_vpp(self):
""" Return True if all PHYs in the config exist as physical interface names """ Return True if all PHYs in the config exist as physical interface names
in VPP. Return False otherwise.""" in VPP. Return False otherwise."""

View File

@ -20,12 +20,14 @@ class VPPApi():
self.vpp = None self.vpp = None
self.config = self.clearconfig() self.config = self.clearconfig()
self.config_read = False self.config_read = False
self.lcp_enabled = False
def connect(self): def connect(self):
if self.connected: if self.connected:
return True return True
vpp_json_dir = '/usr/share/vpp/api/' vpp_json_dir = '/usr/share/vpp/api/'
## vpp_json_dir = "/home/pim/src/vpp/build-root/build-vpp_debug-native/vpp/CMakeFiles/"
# construct a list of all the json api files # construct a list of all the json api files
jsonfiles = [] jsonfiles = []
@ -141,11 +143,32 @@ class VPPApi():
return False return False
self.config_read = False self.config_read = False
self.logger.debug("Retrieving LCPs")
## Workaround LCPng and linux-cp, in order.
self.lcp_enabled = False
if not self.lcp_enabled:
try:
self.logger.debug("Retrieving LCPs (lcpng)")
r = self.vpp.api.lcpng_itf_pair_get()
if isinstance(r, tuple) and r[0].retval == 0:
for lcp in r[1]:
self.config['lcps'][lcp.phy_sw_if_index] = lcp
self.lcp_enabled = True
except:
self.logger.warning("lcpng not found, trying linux-cp")
if not self.lcp_enabled:
try:
self.logger.debug("Retrieving LCPs (linux-cp)")
r = self.vpp.api.lcp_itf_pair_get() r = self.vpp.api.lcp_itf_pair_get()
if isinstance(r, tuple) and r[0].retval == 0: if isinstance(r, tuple) and r[0].retval == 0:
for lcp in r[1]: for lcp in r[1]:
self.config['lcps'][lcp.phy_sw_if_index] = lcp self.config['lcps'][lcp.phy_sw_if_index] = lcp
self.lcp_enabled = True
except:
pass
if not self.lcp_enabled:
self.logger.warning("lcpng nor linux-cp found, will not reconcile Linux Control Plane")
self.logger.debug("Retrieving interfaces") self.logger.debug("Retrieving interfaces")
r = self.vpp.api.sw_interface_dump() r = self.vpp.api.sw_interface_dump()

41
vppcfg
View File

@ -29,14 +29,21 @@ except ImportError:
def main(): def main():
parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter) parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter)
parser.add_argument('-c', '--config', dest='config', required=True, type=str, help="""YAML configuration file for VPP""")
parser.add_argument('-s', '--schema', dest='schema', type=str, default='./schema.yaml', help="""YAML schema validation file""") parser.add_argument('-s', '--schema', dest='schema', type=str, default='./schema.yaml', help="""YAML schema validation file""")
parser.add_argument('-d', '--debug', dest='debug', action='store_true', help="""Enable debug, default False""") parser.add_argument('-d', '--debug', dest='debug', action='store_true', help="""Enable debug logging, default False""")
parser.add_argument('-q', '--quiet', dest='quiet', action='store_true', help="""Be quiet (only log warnings/errors), default False""") parser.add_argument('-q', '--quiet', dest='quiet', action='store_true', help="""Be quiet (only warnings/errors), default False""")
parser.add_argument('-f', '--force', dest='force', action='store_true', help="""Force progress despite warnings, default False""") parser.add_argument('-f', '--force', dest='force', action='store_true', help="""Force progress despite warnings, default False""")
parser.add_argument('-c', '--config', dest='config', required=True, type=str, help="""YAML configuration file for vppcfg""")
subparsers = parser.add_subparsers(dest='command')
check_p = subparsers.add_parser('check')
plan_p = subparsers.add_parser('plan')
plan_p.add_argument('-o', '--output', dest='outfile', required=False, default='-', type=str, help="""Output file for VPP CLI commands, default stdout""")
apply_p = subparsers.add_parser('apply')
args = parser.parse_args() args = parser.parse_args()
level = logging.INFO level = logging.INFO
if args.debug: if args.debug:
level = logging.DEBUG level = logging.DEBUG
@ -57,6 +64,9 @@ def main():
if not v.valid_config(cfg): if not v.valid_config(cfg):
logging.error("Configuration is not valid, bailing") logging.error("Configuration is not valid, bailing")
sys.exit(-2) sys.exit(-2)
logging.info("Configuration is valid")
if args.command=="check":
sys.exit(0)
r = Reconciler(cfg) r = Reconciler(cfg)
if not r.vpp_readconfig(): if not r.vpp_readconfig():
@ -70,33 +80,40 @@ def main():
logging.error("Not all PHYs in VPP exist in the config") logging.error("Not all PHYs in VPP exist in the config")
sys.exit(-5) sys.exit(-5)
if not r.lcps_exist_with_lcp_enabled():
logging.error("Linux Control Plane is needed, but neither lcpng nor linux-cp are available")
sys.exit(-6)
failed = False failed = False
if not r.prune(): if not r.prune():
if not args.force: if not args.force:
logging.error("Reconciliation prune failure") logging.error("Planning prune failure")
sys.exit(-10) sys.exit(-10)
failed = True failed = True
logging.warning("Reconciliation prune failure, continuing due to --force") logging.warning("Planning prune failure, continuing due to --force")
if not r.create(): if not r.create():
if not args.force: if not args.force:
logging.error("Reconciliation create failure") logging.error("Planning create failure")
sys.exit(-20) sys.exit(-20)
failed = True failed = True
logging.warning("Reconciliation create failure, continuing due to --force") logging.warning("Planning create failure, continuing due to --force")
if not r.sync(): if not r.sync():
if not args.force: if not args.force:
logging.error("Reconciliation sync failure") logging.error("Planning sync failure")
sys.exit(-30) sys.exit(-30)
failed = True failed = True
logging.warning("Reconciliation sync failure, continuing due to --force") logging.warning("Planning sync failure, continuing due to --force")
if failed: if failed:
logging.error("Reconciliation failed") logging.error("Planning failed")
sys.exit(-40) sys.exit(-40)
logging.info("Reconciliation succeeded") logging.info("Planning succeeded")
if args.command=="plan":
sys.exit(0)
sys.exit(0) sys.exit(0)
if __name__ == "__main__": if __name__ == "__main__":
main() main()