From c9b06ffdb2f35beda40105135d37391679708ec5 Mon Sep 17 00:00:00 2001 From: "Joshua M. Boniface" Date: Thu, 10 Aug 2023 00:58:36 -0400 Subject: [PATCH] Add network formatters --- cli-client-new/pvc/cli/cli.py | 121 +++++++++++++++++---------- cli-client-new/pvc/cli/formatters.py | 71 ++++++++++++++++ cli-client-new/pvc/lib/network.py | 26 ++++-- 3 files changed, 167 insertions(+), 51 deletions(-) diff --git a/cli-client-new/pvc/cli/cli.py b/cli-client-new/pvc/cli/cli.py index 9dca8b86..9777c7e9 100644 --- a/cli-client-new/pvc/cli/cli.py +++ b/cli-client-new/pvc/cli/cli.py @@ -2527,45 +2527,49 @@ def cli_network_remove(net): ############################################################################### -# > pvc network info TODO:formatter +# > pvc network info ############################################################################### @click.command(name="info", short_help="Show details of a network.") @connection_req @click.argument("vni") -@click.option( - "-l", - "--long", - "long_output", - is_flag=True, - default=False, - help="Display more detailed information.", +@format_opt( + { + "pretty": cli_network_info_format_pretty, + "long": cli_network_info_format_long, + "json": lambda d: jdumps(d), + "json-pretty": lambda d: jdumps(d, indent=2), + } ) -def cli_network_info(vni, long_output): +def cli_network_info(vni, format_function): """ Show information about virtual network VNI. """ retcode, retdata = pvc.lib.network.net_info(CLI_CONFIG, vni) - if retcode: - retdata = pvc.lib.network.format_info(CLI_CONFIG, retdata, long_output) - finish(retcode, retdata) + finish(retcode, retdata, format_function) ############################################################################### -# > pvc network list TODO:formatter +# > pvc network list ############################################################################### @click.command(name="list", short_help="List all VM objects.") @connection_req @click.argument("limit", default=None, required=False) -def cli_network_list(limit): +@format_opt( + { + "pretty": cli_network_list_format_pretty, + "raw": lambda d: "\n".join([f"{n['vni']}" for n in d]), + "json": lambda d: jdumps(d), + "json-pretty": lambda d: jdumps(d, indent=2), + } +) +def cli_network_list(limit, format_function): """ List all virtual networks; optionally only match VNIs or Descriptions matching regex LIMIT. """ retcode, retdata = pvc.lib.network.net_list(CLI_CONFIG, limit) - if retcode: - retdata = pvc.lib.network.format_list(CLI_CONFIG, retdata) - finish(retcode, retdata) + finish(retcode, retdata, format_function) ############################################################################### @@ -2621,7 +2625,7 @@ def cli_network_dhcp_remove(net, macaddr): ############################################################################### -# > pvc network dhcp list TODO:formatter +# > pvc network dhcp list ############################################################################### @click.command(name="list", short_help="List active DHCP leases.") @connection_req @@ -2635,7 +2639,17 @@ def cli_network_dhcp_remove(net, macaddr): default=False, help="Show only static leases.", ) -def cli_network_dhcp_list(net, limit, only_static): +@format_opt( + { + "pretty": cli_network_dhcp_list_format_pretty, + "raw": lambda d: "\n".join( + [f"{n['mac_address']}|{n['ip4_address']}|{n['hostname']}" for n in d] + ), + "json": lambda d: jdumps(d), + "json-pretty": lambda d: jdumps(d, indent=2), + } +) +def cli_network_dhcp_list(net, limit, only_static, format_function): """ List all DHCP leases in virtual network NET; optionally only match elements matching regex LIMIT; NET must be a VNI. """ @@ -2643,9 +2657,7 @@ def cli_network_dhcp_list(net, limit, only_static): retcode, retdata = pvc.lib.network.net_dhcp_list( CLI_CONFIG, net, limit, only_static ) - if retcode: - retdata = pvc.lib.network.format_list_dhcp(retdata) - finish(retcode, retdata) + finish(retcode, retdata, format_function) ############################################################################### @@ -2736,7 +2748,7 @@ def cli_network_acl_remove(net, rule): ############################################################################### -# > pvc network acl list TODO:formatter +# > pvc network acl list ############################################################################### @click.command(name="list", short_help="List firewall ACLs.") @connection_req @@ -2750,7 +2762,17 @@ def cli_network_acl_remove(net, rule): ) @click.argument("net") @click.argument("limit", default=None, required=False) -def cli_network_acl_list(net, limit, direction): +@format_opt( + { + "pretty": cli_network_acl_list_format_pretty, + "raw": lambda d: "\n".join( + [f"{n['direction']}|{n['order']}|{n['rule']}" for n in d] + ), + "json": lambda d: jdumps(d), + "json-pretty": lambda d: jdumps(d, indent=2), + } +) +def cli_network_acl_list(net, limit, direction, format_function): """ List all NFT firewall rules in network NET; optionally only match elements matching description regex LIMIT; NET can be either a VNI or description. """ @@ -2761,9 +2783,7 @@ def cli_network_acl_list(net, limit, direction): direction = "out" retcode, retdata = pvc.lib.network.net_acl_list(CLI_CONFIG, net, limit, direction) - if retcode: - retdata = pvc.lib.network.format_list_acl(retdata) - finish(retcode, retdata) + finish(retcode, retdata, format_function) ############################################################################### @@ -2795,19 +2815,25 @@ def cli_network_sriov_pf(): ############################################################################### -# > pvc network sriov pf list TODO:formatter +# > pvc network sriov pf list TODO:formatter-raw ############################################################################### @click.command(name="list", short_help="List PF devices.") @connection_req @click.argument("node") -def cli_network_sriov_pf_list(node): +@format_opt( + { + "pretty": cli_network_sriov_pf_list_format_pretty, + # "raw": lambda d: "\n".join([f"{n['mac_address']}|{n['ip4_address']}|{n['hostname']}" for n in d]), + "json": lambda d: jdumps(d), + "json-pretty": lambda d: jdumps(d, indent=2), + } +) +def cli_network_sriov_pf_list(node, format_function): """ List all SR-IOV PFs on NODE. """ retcode, retdata = pvc.lib.network.net_sriov_pf_list(CLI_CONFIG, node) - if retcode: - retdata = pvc.lib.network.format_list_sriov_pf(retdata) - finish(retcode, retdata) + finish(retcode, retdata, format_function) ############################################################################### @@ -2936,37 +2962,48 @@ def net_sriov_vf_set( ############################################################################### -# > pvc network sriov vf info TODO:formatter +# > pvc network sriov vf info ############################################################################### @click.command(name="info", short_help="Show details of VF devices.") @connection_req @click.argument("node") @click.argument("vf") -def cli_network_sriov_vf_info(node, vf): +@format_opt( + { + "pretty": cli_network_sriov_vf_info_format_pretty, + "json": lambda d: jdumps(d), + "json-pretty": lambda d: jdumps(d, indent=2), + } +) +def cli_network_sriov_vf_info(node, vf, format_function): """ Show details of the SR-IOV VF on NODE. """ retcode, retdata = pvc.lib.network.net_sriov_vf_info(CLI_CONFIG, node, vf) - if retcode: - retdata = pvc.lib.network.format_info_sriov_vf(CLI_CONFIG, retdata, node) - finish(retcode, retdata) + finish(retcode, retdata, format_function) ############################################################################### -# > pvc network sriov vf list TODO:formatter +# > pvc network sriov vf list TODO:formatter-raw ############################################################################### @click.command(name="list", short_help="List VF devices.") @connection_req @click.argument("node") @click.argument("pf", default=None, required=False) -def cli_network_sriov_vf_list(node, pf): +@format_opt( + { + "pretty": cli_network_sriov_vf_list_format_pretty, + # "raw": lambda d: "\n".join([f"{n['mac_address']}|{n['ip4_address']}|{n['hostname']}" for n in d]), + "json": lambda d: jdumps(d), + "json-pretty": lambda d: jdumps(d, indent=2), + } +) +def cli_network_sriov_vf_list(node, pf, format_function): """ List all SR-IOV VFs on NODE, optionally limited to device PF. """ retcode, retdata = pvc.lib.network.net_sriov_vf_list(CLI_CONFIG, node, pf) - if retcode: - retdata = pvc.lib.network.format_list_sriov_vf(retdata) - finish(retcode, retdata) + finish(retcode, retdata, format_function) ############################################################################### diff --git a/cli-client-new/pvc/cli/formatters.py b/cli-client-new/pvc/cli/formatters.py index ef7e999f..f4d92394 100644 --- a/cli-client-new/pvc/cli/formatters.py +++ b/cli-client-new/pvc/cli/formatters.py @@ -28,6 +28,13 @@ from pvc.lib.vm import format_vm_networks as vm_format_networks from pvc.lib.vm import format_vm_volumes as vm_format_volumes from pvc.lib.vm import format_info as vm_format_info from pvc.lib.vm import format_list as vm_format_list +from pvc.lib.network import format_info as network_format_info +from pvc.lib.network import format_list as network_format_list +from pvc.lib.network import format_list_dhcp as network_format_dhcp_list +from pvc.lib.network import format_list_acl as network_format_acl_list +from pvc.lib.network import format_list_sriov_pf as network_format_sriov_pf_list +from pvc.lib.network import format_info_sriov_vf as network_format_sriov_vf_info +from pvc.lib.network import format_list_sriov_vf as network_format_sriov_vf_list # Define colour values for use in formatters @@ -518,3 +525,67 @@ def cli_vm_list_format_pretty(CLI_CONFIG, data): """ return vm_format_list(CLI_CONFIG, data) + + +def cli_network_info_format_pretty(CLI_CONFIG, data): + """ + Pretty format the full output of cli_network_info + """ + + return network_format_info(CLI_CONFIG, data, long_output=True) + + +def cli_network_info_format_long(CLI_CONFIG, data): + """ + Pretty format the full output of cli_network_info + """ + + return network_format_info(CLI_CONFIG, data, long_output=True) + + +def cli_network_list_format_pretty(CLI_CONFIG, data): + """ + Pretty format the output of cli_network_list + """ + + return network_format_list(CLI_CONFIG, data) + + +def cli_network_dhcp_list_format_pretty(CLI_CONFIG, data): + """ + Pretty format the output of cli_network_dhcp_list + """ + + return network_format_dhcp_list(CLI_CONFIG, data) + + +def cli_network_acl_list_format_pretty(CLI_CONFIG, data): + """ + Pretty format the output of cli_network_acl_list + """ + + return network_format_acl_list(CLI_CONFIG, data) + + +def cli_network_sriov_pf_list_format_pretty(CLI_CONFIG, data): + """ + Pretty format the output of cli_network_sriov_pf_list + """ + + return network_format_sriov_pf_list(CLI_CONFIG, data) + + +def cli_network_sriov_vf_info_format_pretty(CLI_CONFIG, data): + """ + Pretty format the output of cli_network_sriov_vf_info + """ + + return network_format_sriov_vf_info(CLI_CONFIG, data) + + +def cli_network_sriov_vf_list_format_pretty(CLI_CONFIG, data): + """ + Pretty format the output of cli_network_sriov_vf_list + """ + + return network_format_sriov_vf_list(CLI_CONFIG, data) diff --git a/cli-client-new/pvc/lib/network.py b/cli-client-new/pvc/lib/network.py index 8b07960f..15180fc2 100644 --- a/cli-client-new/pvc/lib/network.py +++ b/cli-client-new/pvc/lib/network.py @@ -542,11 +542,16 @@ def net_sriov_vf_info(config, node, vf): return False, "VF not found." else: # Return a single instance if the response is a list + data = dict() + data["node"] = node if isinstance(response.json(), list): - return True, response.json()[0] + data = dict() + data["vf_information"] = response.json()[0] + return True, data # This shouldn't happen, but is here just in case else: - return True, response.json() + data["vf_information"] = response.json() + return True, data else: return False, response.json().get("message", "") @@ -714,7 +719,7 @@ def format_info(config, network_information, long_output): ) ainformation.append("") if retcode: - firewall_rules_string = format_list_acl(firewall_rules_list) + firewall_rules_string = format_list_acl(config, firewall_rules_list) for line in firewall_rules_string.split("\n"): ainformation.append(line) else: @@ -888,7 +893,7 @@ def format_list(config, network_list): return "\n".join(network_list_output) -def format_list_dhcp(dhcp_lease_list): +def format_list_dhcp(config, dhcp_lease_list): dhcp_lease_list_output = [] # Determine optimal column widths @@ -987,7 +992,7 @@ def format_list_dhcp(dhcp_lease_list): return "\n".join(dhcp_lease_list_output) -def format_list_acl(acl_list): +def format_list_acl(config, acl_list): # Handle when we get an empty entry if not acl_list: acl_list = list() @@ -1086,7 +1091,7 @@ def format_list_acl(acl_list): return "\n".join(acl_list_output) -def format_list_sriov_pf(pf_list): +def format_list_sriov_pf(config, pf_list): # The maximum column width of the VFs column max_vfs_length = 70 @@ -1206,7 +1211,7 @@ def format_list_sriov_pf(pf_list): return "\n".join(pf_list_output) -def format_list_sriov_vf(vf_list): +def format_list_sriov_vf(config, vf_list): # Handle when we get an empty entry if not vf_list: vf_list = list() @@ -1338,10 +1343,13 @@ def format_list_sriov_vf(vf_list): return "\n".join(vf_list_output) -def format_info_sriov_vf(config, vf_information, node): - if not vf_information: +def format_info_sriov_vf(config, data): + if not data or not data["vf_information"]: return "No VF found" + node = data["node"] + vf_information = data["vf_information"] + # Get information on the using VM if applicable if vf_information["usage"]["used"] == "True" and vf_information["usage"]["domain"]: vm_information = call_api(