From 0a534554f1b5e5213e8daeab707d4d143b0136c4 Mon Sep 17 00:00:00 2001 From: Vadym Hlushko Date: Tue, 2 Nov 2021 14:32:19 +0000 Subject: [PATCH 01/12] Added raw generated CLI plugins Signed-off-by: Vadym Hlushko --- config/plugins/sonic-nvgre-tunnel_yang.py | 485 ++++++++++++++++++++++ show/plugins/sonic-nvgre-tunnel_yang.py | 171 ++++++++ 2 files changed, 656 insertions(+) create mode 100644 config/plugins/sonic-nvgre-tunnel_yang.py create mode 100644 show/plugins/sonic-nvgre-tunnel_yang.py diff --git a/config/plugins/sonic-nvgre-tunnel_yang.py b/config/plugins/sonic-nvgre-tunnel_yang.py new file mode 100644 index 0000000000..2b45bab862 --- /dev/null +++ b/config/plugins/sonic-nvgre-tunnel_yang.py @@ -0,0 +1,485 @@ +""" +Autogenerated config CLI plugin. + + +""" + +import click +import utilities_common.cli as clicommon +import utilities_common.general as general +from config import config_mgmt + + +# Load sonic-cfggen from source since /usr/local/bin/sonic-cfggen does not have .py extension. +sonic_cfggen = general.load_module_from_source('sonic_cfggen', '/usr/local/bin/sonic-cfggen') + + +def exit_with_error(*args, **kwargs): + """ Print a message with click.secho and abort CLI. + + Args: + args: Positional arguments to pass to click.secho + kwargs: Keyword arguments to pass to click.secho + """ + + click.secho(*args, **kwargs) + raise click.Abort() + + +def validate_config_or_raise(cfg): + """ Validate config db data using ConfigMgmt. + + Args: + cfg (Dict): Config DB data to validate. + Raises: + Exception: when cfg does not satisfy YANG schema. + """ + + try: + cfg = sonic_cfggen.FormatConverter.to_serialized(cfg) + config_mgmt.ConfigMgmt().loadData(cfg) + except Exception as err: + raise Exception('Failed to validate configuration: {}'.format(err)) + + +def add_entry_validated(db, table, key, data): + """ Add new entry in table and validate configuration. + + Args: + db (swsscommon.ConfigDBConnector): Config DB connector obect. + table (str): Table name to add new entry to. + key (Union[str, Tuple]): Key name in the table. + data (Dict): Entry data. + Raises: + Exception: when cfg does not satisfy YANG schema. + """ + + cfg = db.get_config() + cfg.setdefault(table, {}) + if key in cfg[table]: + raise Exception(f"{key} already exists") + + cfg[table][key] = data + + validate_config_or_raise(cfg) + db.set_entry(table, key, data) + + +def update_entry_validated(db, table, key, data, create_if_not_exists=False): + """ Update entry in table and validate configuration. + If attribute value in data is None, the attribute is deleted. + + Args: + db (swsscommon.ConfigDBConnector): Config DB connector obect. + table (str): Table name to add new entry to. + key (Union[str, Tuple]): Key name in the table. + data (Dict): Entry data. + create_if_not_exists (bool): + In case entry does not exists already a new entry + is not created if this flag is set to False and + creates a new entry if flag is set to True. + Raises: + Exception: when cfg does not satisfy YANG schema. + """ + + cfg = db.get_config() + cfg.setdefault(table, {}) + + if not data: + raise Exception(f"No field/values to update {key}") + + if create_if_not_exists: + cfg[table].setdefault(key, {}) + + if key not in cfg[table]: + raise Exception(f"{key} does not exist") + + for attr, value in data.items(): + if value is None: + cfg[table][key].pop(attr, None) + else: + cfg[table][key][attr] = value + + validate_config_or_raise(cfg) + db.set_entry(table, key, cfg[table][key]) + + +def del_entry_validated(db, table, key): + """ Delete entry in table and validate configuration. + + Args: + db (swsscommon.ConfigDBConnector): Config DB connector obect. + table (str): Table name to add new entry to. + key (Union[str, Tuple]): Key name in the table. + Raises: + Exception: when cfg does not satisfy YANG schema. + """ + + cfg = db.get_config() + cfg.setdefault(table, {}) + if key not in cfg[table]: + raise Exception(f"{key} does not exist") + + cfg[table].pop(key) + + validate_config_or_raise(cfg) + db.set_entry(table, key, None) + + +def add_list_entry_validated(db, table, key, attr, data): + """ Add new entry into list in table and validate configuration. + + Args: + db (swsscommon.ConfigDBConnector): Config DB connector obect. + table (str): Table name to add data to. + key (Union[str, Tuple]): Key name in the table. + attr (str): Attribute name which represents a list the data needs to be added to. + data (List): Data list to add to config DB. + Raises: + Exception: when cfg does not satisfy YANG schema. + """ + + cfg = db.get_config() + cfg.setdefault(table, {}) + if key not in cfg[table]: + raise Exception(f"{key} does not exist") + cfg[table][key].setdefault(attr, []) + for entry in data: + if entry in cfg[table][key][attr]: + raise Exception(f"{entry} already exists") + cfg[table][key][attr].append(entry) + + validate_config_or_raise(cfg) + db.set_entry(table, key, cfg[table][key]) + + +def del_list_entry_validated(db, table, key, attr, data): + """ Delete entry from list in table and validate configuration. + + Args: + db (swsscommon.ConfigDBConnector): Config DB connector obect. + table (str): Table name to remove data from. + key (Union[str, Tuple]): Key name in the table. + attr (str): Attribute name which represents a list the data needs to be removed from. + data (Dict): Data list to remove from config DB. + Raises: + Exception: when cfg does not satisfy YANG schema. + """ + + cfg = db.get_config() + cfg.setdefault(table, {}) + if key not in cfg[table]: + raise Exception(f"{key} does not exist") + cfg[table][key].setdefault(attr, []) + for entry in data: + if entry not in cfg[table][key][attr]: + raise Exception(f"{entry} does not exist") + cfg[table][key][attr].remove(entry) + if not cfg[table][key][attr]: + cfg[table][key].pop(attr) + + validate_config_or_raise(cfg) + db.set_entry(table, key, cfg[table][key]) + + +def clear_list_entry_validated(db, table, key, attr): + """ Clear list in object and validate configuration. + + Args: + db (swsscommon.ConfigDBConnector): Config DB connector obect. + table (str): Table name to remove the list attribute from. + key (Union[str, Tuple]): Key name in the table. + attr (str): Attribute name which represents a list that needs to be removed. + Raises: + Exception: when cfg does not satisfy YANG schema. + """ + + update_entry_validated(db, table, key, {attr: None}) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@click.group(name="nvgre-tunnel", + cls=clicommon.AliasedGroup) +def NVGRE_TUNNEL(): + """ NVGRE_TUNNEL part of config_db.json """ + + pass + + + + + + + + + + + + +@NVGRE_TUNNEL.command(name="add") + +@click.argument( + "tunnel-name", + nargs=1, + required=True, +) + +@click.option( + "--src-ip", + help="[mandatory]", +) +@clicommon.pass_db +def NVGRE_TUNNEL_add(db, tunnel_name, src_ip): + """ Add object in NVGRE_TUNNEL. """ + + table = "NVGRE_TUNNEL" + key = tunnel_name + data = {} + if src_ip is not None: + data["src_ip"] = src_ip + + try: + add_entry_validated(db.cfgdb, table, key, data) + except Exception as err: + exit_with_error(f"Error: {err}", fg="red") + + +@NVGRE_TUNNEL.command(name="update") + +@click.argument( + "tunnel-name", + nargs=1, + required=True, +) + +@click.option( + "--src-ip", + help="[mandatory]", +) +@clicommon.pass_db +def NVGRE_TUNNEL_update(db, tunnel_name, src_ip): + """ Add object in NVGRE_TUNNEL. """ + + table = "NVGRE_TUNNEL" + key = tunnel_name + data = {} + if src_ip is not None: + data["src_ip"] = src_ip + + try: + update_entry_validated(db.cfgdb, table, key, data) + except Exception as err: + exit_with_error(f"Error: {err}", fg="red") + + +@NVGRE_TUNNEL.command(name="delete") + +@click.argument( + "tunnel-name", + nargs=1, + required=True, +) +@clicommon.pass_db +def NVGRE_TUNNEL_delete(db, tunnel_name): + """ Delete object in NVGRE_TUNNEL. """ + + table = "NVGRE_TUNNEL" + key = tunnel_name + try: + del_entry_validated(db.cfgdb, table, key) + except Exception as err: + exit_with_error(f"Error: {err}", fg="red") + + + + + + + + + + + +@click.group(name="nvgre-tunnel-map", + cls=clicommon.AliasedGroup) +def NVGRE_TUNNEL_MAP(): + """ NVGRE_TUNNEL part of config_db.json """ + + pass + + + + + + + + + + + + +@NVGRE_TUNNEL_MAP.command(name="add") + +@click.argument( + "tunnel-name", + nargs=1, + required=True, +) +@click.argument( + "vlan-name", + nargs=1, + required=True, +) + +@click.option( + "--vlan-id", + help="", +) +@click.option( + "--vsid", + help="", +) +@clicommon.pass_db +def NVGRE_TUNNEL_MAP_add(db, tunnel_name, vlan_name, vlan_id, vsid): + """ Add object in NVGRE_TUNNEL_MAP. """ + + table = "NVGRE_TUNNEL_MAP" + key = tunnel_name, vlan_name + data = {} + if vlan_id is not None: + data["vlan_id"] = vlan_id + if vsid is not None: + data["vsid"] = vsid + + try: + add_entry_validated(db.cfgdb, table, key, data) + except Exception as err: + exit_with_error(f"Error: {err}", fg="red") + + +@NVGRE_TUNNEL_MAP.command(name="update") + +@click.argument( + "tunnel-name", + nargs=1, + required=True, +) +@click.argument( + "vlan-name", + nargs=1, + required=True, +) + +@click.option( + "--vlan-id", + help="", +) +@click.option( + "--vsid", + help="", +) +@clicommon.pass_db +def NVGRE_TUNNEL_MAP_update(db, tunnel_name, vlan_name, vlan_id, vsid): + """ Add object in NVGRE_TUNNEL_MAP. """ + + table = "NVGRE_TUNNEL_MAP" + key = tunnel_name, vlan_name + data = {} + if vlan_id is not None: + data["vlan_id"] = vlan_id + if vsid is not None: + data["vsid"] = vsid + + try: + update_entry_validated(db.cfgdb, table, key, data) + except Exception as err: + exit_with_error(f"Error: {err}", fg="red") + + +@NVGRE_TUNNEL_MAP.command(name="delete") + +@click.argument( + "tunnel-name", + nargs=1, + required=True, +) +@click.argument( + "vlan-name", + nargs=1, + required=True, +) +@clicommon.pass_db +def NVGRE_TUNNEL_MAP_delete(db, tunnel_name, vlan_name): + """ Delete object in NVGRE_TUNNEL_MAP. """ + + table = "NVGRE_TUNNEL_MAP" + key = tunnel_name, vlan_name + try: + del_entry_validated(db.cfgdb, table, key) + except Exception as err: + exit_with_error(f"Error: {err}", fg="red") + + + + + + + + + + + + + + +def register(cli): + """ Register new CLI nodes in root CLI. + + Args: + cli: Root CLI node. + Raises: + Exception: when root CLI already has a command + we are trying to register. + """ + cli_node = NVGRE_TUNNEL + if cli_node.name in cli.commands: + raise Exception(f"{cli_node.name} already exists in CLI") + cli.add_command(NVGRE_TUNNEL) + cli_node = NVGRE_TUNNEL_MAP + if cli_node.name in cli.commands: + raise Exception(f"{cli_node.name} already exists in CLI") + cli.add_command(NVGRE_TUNNEL_MAP) \ No newline at end of file diff --git a/show/plugins/sonic-nvgre-tunnel_yang.py b/show/plugins/sonic-nvgre-tunnel_yang.py new file mode 100644 index 0000000000..64119eb854 --- /dev/null +++ b/show/plugins/sonic-nvgre-tunnel_yang.py @@ -0,0 +1,171 @@ +""" +Auto-generated show CLI plugin. + + +""" + +import click +import tabulate +import natsort +import utilities_common.cli as clicommon + + + + + +def format_attr_value(entry, attr): + """ Helper that formats attribute to be presented in the table output. + + Args: + entry (Dict[str, str]): CONFIG DB entry configuration. + attr (Dict): Attribute metadata. + + Returns: + str: fomatted attribute value. + """ + + if attr["is-leaf-list"]: + return "\n".join(entry.get(attr["name"], [])) + return entry.get(attr["name"], "N/A") + + +def format_group_value(entry, attrs): + """ Helper that formats grouped attribute to be presented in the table output. + + Args: + entry (Dict[str, str]): CONFIG DB entry configuration. + attrs (List[Dict]): Attributes metadata that belongs to the same group. + + Returns: + str: fomatted group attributes. + """ + + data = [] + for attr in attrs: + if entry.get(attr["name"]): + data.append((attr["name"] + ":", format_attr_value(entry, attr))) + return tabulate.tabulate(data, tablefmt="plain") + + + + + + + + + + + + + + + + + + + + +@click.group(name="nvgre-tunnel", + cls=clicommon.AliasedGroup, + invoke_without_command=True) +@clicommon.pass_db +def NVGRE_TUNNEL(db): + """ [Callable command group] """ + + header = [ +"TUNNEL NAME", + +"SRC IP", + +] + + body = [] + + table = db.cfgdb.get_table("NVGRE_TUNNEL") + for key in natsort.natsorted(table): + entry = table[key] + if not isinstance(key, tuple): + key = (key,) + + row = [*key] + [ + format_attr_value( + entry, + {'name': 'src_ip', 'description': '', 'is-leaf-list': False, 'is-mandatory': True, 'group': ''} + ), +] + + body.append(row) + + click.echo(tabulate.tabulate(body, header)) + + + + + + + + + + + + + +@click.group(name="nvgre-tunnel-map", + cls=clicommon.AliasedGroup, + invoke_without_command=True) +@clicommon.pass_db +def NVGRE_TUNNEL_MAP(db): + """ [Callable command group] """ + + header = [ +"TUNNEL NAME", +"VLAN NAME", + +"VLAN ID", +"VSID", + +] + + body = [] + + table = db.cfgdb.get_table("NVGRE_TUNNEL_MAP") + for key in natsort.natsorted(table): + entry = table[key] + if not isinstance(key, tuple): + key = (key,) + + row = [*key] + [ + format_attr_value( + entry, + {'name': 'vlan_id', 'description': '', 'is-leaf-list': False, 'is-mandatory': False, 'group': ''} + ), + format_attr_value( + entry, + {'name': 'vsid', 'description': '', 'is-leaf-list': False, 'is-mandatory': False, 'group': ''} + ), +] + + body.append(row) + + click.echo(tabulate.tabulate(body, header)) + + + + +def register(cli): + """ Register new CLI nodes in root CLI. + + Args: + cli (click.core.Command): Root CLI node. + Raises: + Exception: when root CLI already has a command + we are trying to register. + """ + cli_node = NVGRE_TUNNEL + if cli_node.name in cli.commands: + raise Exception(f"{cli_node.name} already exists in CLI") + cli.add_command(NVGRE_TUNNEL) + cli_node = NVGRE_TUNNEL_MAP + if cli_node.name in cli.commands: + raise Exception(f"{cli_node.name} already exists in CLI") + cli.add_command(NVGRE_TUNNEL_MAP) \ No newline at end of file From bc739254aa8e7f6cbf1ae885371db558c55465b1 Mon Sep 17 00:00:00 2001 From: Vadym Hlushko Date: Tue, 2 Nov 2021 14:59:56 +0000 Subject: [PATCH 02/12] Fixed codestyle Signed-off-by: Vadym Hlushko --- config/plugins/sonic-nvgre-tunnel_yang.py | 94 +----------------- show/plugins/sonic-nvgre-tunnel_yang.py | 116 +++++++++------------- 2 files changed, 49 insertions(+), 161 deletions(-) diff --git a/config/plugins/sonic-nvgre-tunnel_yang.py b/config/plugins/sonic-nvgre-tunnel_yang.py index 2b45bab862..3c760f92ee 100644 --- a/config/plugins/sonic-nvgre-tunnel_yang.py +++ b/config/plugins/sonic-nvgre-tunnel_yang.py @@ -1,7 +1,5 @@ """ Autogenerated config CLI plugin. - - """ import click @@ -197,67 +195,21 @@ def clear_list_entry_validated(db, table, key, attr): update_entry_validated(db, table, key, {attr: None}) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -@click.group(name="nvgre-tunnel", - cls=clicommon.AliasedGroup) +@click.group( + name="nvgre-tunnel", + cls=clicommon.AliasedGroup) def NVGRE_TUNNEL(): """ NVGRE_TUNNEL part of config_db.json """ pass - - - - - - - - - - @NVGRE_TUNNEL.command(name="add") - @click.argument( "tunnel-name", nargs=1, required=True, ) - @click.option( "--src-ip", help="[mandatory]", @@ -279,13 +231,11 @@ def NVGRE_TUNNEL_add(db, tunnel_name, src_ip): @NVGRE_TUNNEL.command(name="update") - @click.argument( "tunnel-name", nargs=1, required=True, ) - @click.option( "--src-ip", help="[mandatory]", @@ -307,7 +257,6 @@ def NVGRE_TUNNEL_update(db, tunnel_name, src_ip): @NVGRE_TUNNEL.command(name="delete") - @click.argument( "tunnel-name", nargs=1, @@ -325,15 +274,6 @@ def NVGRE_TUNNEL_delete(db, tunnel_name): exit_with_error(f"Error: {err}", fg="red") - - - - - - - - - @click.group(name="nvgre-tunnel-map", cls=clicommon.AliasedGroup) def NVGRE_TUNNEL_MAP(): @@ -342,18 +282,7 @@ def NVGRE_TUNNEL_MAP(): pass - - - - - - - - - - @NVGRE_TUNNEL_MAP.command(name="add") - @click.argument( "tunnel-name", nargs=1, @@ -364,7 +293,6 @@ def NVGRE_TUNNEL_MAP(): nargs=1, required=True, ) - @click.option( "--vlan-id", help="", @@ -403,7 +331,6 @@ def NVGRE_TUNNEL_MAP_add(db, tunnel_name, vlan_name, vlan_id, vsid): nargs=1, required=True, ) - @click.option( "--vlan-id", help="", @@ -431,7 +358,6 @@ def NVGRE_TUNNEL_MAP_update(db, tunnel_name, vlan_name, vlan_id, vsid): @NVGRE_TUNNEL_MAP.command(name="delete") - @click.argument( "tunnel-name", nargs=1, @@ -454,18 +380,6 @@ def NVGRE_TUNNEL_MAP_delete(db, tunnel_name, vlan_name): exit_with_error(f"Error: {err}", fg="red") - - - - - - - - - - - - def register(cli): """ Register new CLI nodes in root CLI. @@ -482,4 +396,4 @@ def register(cli): cli_node = NVGRE_TUNNEL_MAP if cli_node.name in cli.commands: raise Exception(f"{cli_node.name} already exists in CLI") - cli.add_command(NVGRE_TUNNEL_MAP) \ No newline at end of file + cli.add_command(NVGRE_TUNNEL_MAP) diff --git a/show/plugins/sonic-nvgre-tunnel_yang.py b/show/plugins/sonic-nvgre-tunnel_yang.py index 64119eb854..6e698d1da6 100644 --- a/show/plugins/sonic-nvgre-tunnel_yang.py +++ b/show/plugins/sonic-nvgre-tunnel_yang.py @@ -1,7 +1,5 @@ """ Auto-generated show CLI plugin. - - """ import click @@ -10,9 +8,6 @@ import utilities_common.cli as clicommon - - - def format_attr_value(entry, attr): """ Helper that formats attribute to be presented in the table output. @@ -44,40 +39,19 @@ def format_group_value(entry, attrs): for attr in attrs: if entry.get(attr["name"]): data.append((attr["name"] + ":", format_attr_value(entry, attr))) - return tabulate.tabulate(data, tablefmt="plain") - - - - - - - - - - - - - - - - - + return tabulate.tabulate(data, tablefmt="plain") -@click.group(name="nvgre-tunnel", - cls=clicommon.AliasedGroup, - invoke_without_command=True) +@click.group( + name="nvgre-tunnel", + cls=clicommon.AliasedGroup, + invoke_without_command=True) @clicommon.pass_db def NVGRE_TUNNEL(db): """ [Callable command group] """ - header = [ -"TUNNEL NAME", - -"SRC IP", - -] + header = [ "TUNNEL NAME", "SRC IP" ] body = [] @@ -88,43 +62,32 @@ def NVGRE_TUNNEL(db): key = (key,) row = [*key] + [ - format_attr_value( - entry, - {'name': 'src_ip', 'description': '', 'is-leaf-list': False, 'is-mandatory': True, 'group': ''} - ), -] + format_attr_value( + entry, + { + 'name': 'src_ip', + 'description': '', + 'is-leaf-list': False, + 'is-mandatory': True, + 'group': '' + } + ) + ] body.append(row) click.echo(tabulate.tabulate(body, header)) - - - - - - - - - - - -@click.group(name="nvgre-tunnel-map", - cls=clicommon.AliasedGroup, - invoke_without_command=True) +@click.group( + name="nvgre-tunnel-map", + cls=clicommon.AliasedGroup, + invoke_without_command=True) @clicommon.pass_db def NVGRE_TUNNEL_MAP(db): """ [Callable command group] """ - header = [ -"TUNNEL NAME", -"VLAN NAME", - -"VLAN ID", -"VSID", - -] + header = [ "TUNNEL NAME", "VLAN NAME", "VLAN ID", "VSID" ] body = [] @@ -135,23 +98,33 @@ def NVGRE_TUNNEL_MAP(db): key = (key,) row = [*key] + [ - format_attr_value( - entry, - {'name': 'vlan_id', 'description': '', 'is-leaf-list': False, 'is-mandatory': False, 'group': ''} - ), - format_attr_value( - entry, - {'name': 'vsid', 'description': '', 'is-leaf-list': False, 'is-mandatory': False, 'group': ''} - ), -] + format_attr_value( + entry, + { + 'name': 'vlan_id', + 'description': '', + 'is-leaf-list': False, + 'is-mandatory': False, + 'group': '' + } + ), + format_attr_value( + entry, + { + 'name': 'vsid', + 'description': '', + 'is-leaf-list': False, + 'is-mandatory': False, + 'group': '' + } + ) + ] body.append(row) click.echo(tabulate.tabulate(body, header)) - - def register(cli): """ Register new CLI nodes in root CLI. @@ -168,4 +141,5 @@ def register(cli): cli_node = NVGRE_TUNNEL_MAP if cli_node.name in cli.commands: raise Exception(f"{cli_node.name} already exists in CLI") - cli.add_command(NVGRE_TUNNEL_MAP) \ No newline at end of file + cli.add_command(NVGRE_TUNNEL_MAP) + From c1b65efb07c02b22174558242002d310a122ec04 Mon Sep 17 00:00:00 2001 From: Vadym Hlushko Date: Wed, 3 Nov 2021 14:37:35 +0000 Subject: [PATCH 03/12] Added nvgre-tunnel test cases Signed-off-by: Vadym Hlushko --- .../nvgre_tunnel_input/assert_show_output.py | 33 +++ tests/nvgre_tunnel_input/nvgre_tunnel.json | 11 + .../nvgre_tunnel_input/nvgre_tunnel_map.json | 11 + tests/nvgre_tunnel_test.py | 220 ++++++++++++++++++ 4 files changed, 275 insertions(+) create mode 100644 tests/nvgre_tunnel_input/assert_show_output.py create mode 100644 tests/nvgre_tunnel_input/nvgre_tunnel.json create mode 100644 tests/nvgre_tunnel_input/nvgre_tunnel_map.json create mode 100644 tests/nvgre_tunnel_test.py diff --git a/tests/nvgre_tunnel_input/assert_show_output.py b/tests/nvgre_tunnel_input/assert_show_output.py new file mode 100644 index 0000000000..fe6787d19e --- /dev/null +++ b/tests/nvgre_tunnel_input/assert_show_output.py @@ -0,0 +1,33 @@ +""" +Module holding the correct values for show CLI command outputs for the nvgre_tunnel_test.py +""" + + +show_nvgre_tunnel="""\ +TUNNEL NAME SRC IP +------------- -------- +tunnel_1 10.0.0.1 +""" + + +show_nvgre_tunnels="""\ +TUNNEL NAME SRC IP +------------- -------- +tunnel_1 10.0.0.1 +tunnel_2 10.0.0.2 +""" + + +show_nvgre_tunnel_maps="""\ +TUNNEL NAME VLAN NAME VLAN ID VSID +------------- ----------- --------- ------ +tunnel_1 Vlan1000 1000 5000 +tunnel_1 Vlan2000 2000 6000 +""" + + +show_nvgre_tunnel_updated="""\ +TUNNEL NAME SRC IP +------------- -------- +tunnel_1 10.0.0.2 +""" diff --git a/tests/nvgre_tunnel_input/nvgre_tunnel.json b/tests/nvgre_tunnel_input/nvgre_tunnel.json new file mode 100644 index 0000000000..8a1696fca9 --- /dev/null +++ b/tests/nvgre_tunnel_input/nvgre_tunnel.json @@ -0,0 +1,11 @@ +{ + "NVGRE_TUNNEL|tunnel_1": { + "src_ip": "10.0.0.1" + }, + "VLAN|Vlan1000": { + "vlanid": "1000" + }, + "VLAN|Vlan2000": { + "vlanid": "2000" + } +} \ No newline at end of file diff --git a/tests/nvgre_tunnel_input/nvgre_tunnel_map.json b/tests/nvgre_tunnel_input/nvgre_tunnel_map.json new file mode 100644 index 0000000000..8a1696fca9 --- /dev/null +++ b/tests/nvgre_tunnel_input/nvgre_tunnel_map.json @@ -0,0 +1,11 @@ +{ + "NVGRE_TUNNEL|tunnel_1": { + "src_ip": "10.0.0.1" + }, + "VLAN|Vlan1000": { + "vlanid": "1000" + }, + "VLAN|Vlan2000": { + "vlanid": "2000" + } +} \ No newline at end of file diff --git a/tests/nvgre_tunnel_test.py b/tests/nvgre_tunnel_test.py new file mode 100644 index 0000000000..897b8d22a6 --- /dev/null +++ b/tests/nvgre_tunnel_test.py @@ -0,0 +1,220 @@ +#!/usr/bin/env python + +import pytest +import os +import logging +import show.main as show +import config.main as config + +from .nvgre_tunnel_input import assert_show_output +from utilities_common.db import Db +from click.testing import CliRunner +from .mock_tables import dbconnector +from .mock_tables import mock_single_asic + +logger = logging.getLogger(__name__) +test_path = os.path.dirname(os.path.abspath(__file__)) +mock_db_path = os.path.join(test_path, "nvgre_tunnel_input") + +SUCCESS = 0 +ERROR = 1 +ERROR2 = 2 + +INVALID_VALUE = 'INVALID' + + +class TestPBH: + @classmethod + def setup_class(cls): + logger.info("SETUP") + os.environ['UTILITIES_UNIT_TESTING'] = "1" + + + @classmethod + def teardown_class(cls): + logger.info("TEARDOWN") + os.environ['UTILITIES_UNIT_TESTING'] = "0" + os.environ["UTILITIES_UNIT_TESTING_TOPOLOGY"] = "" + dbconnector.dedicated_dbs['CONFIG_DB'] = None + + + ######### NVGRE-TUNNEL ######### + + + def test_nvgre_tunnel_add_del(self): + db = Db() + runner = CliRunner() + + # add + result = runner.invoke( + config.config.commands["nvgre-tunnel"].commands["add"], + ["tunnel_1", "--src-ip", "10.0.0.1"], obj=db + ) + + logger.debug("\n" + result.output) + logger.debug(result.exit_code) + assert result.exit_code == SUCCESS + + # verify + result = runner.invoke(show.cli.commands["nvgre-tunnel"], [], obj=db) + + logger.debug("\n" + result.output) + logger.debug(result.exit_code) + assert result.exit_code == SUCCESS + assert result.output == assert_show_output.show_nvgre_tunnel + + # delete + result = runner.invoke( + config.config.commands["nvgre-tunnel"].commands["delete"], + ["tunnel_1"], obj=db + ) + + logger.debug("\n" + result.output) + logger.debug(result.exit_code) + assert result.exit_code == SUCCESS + + + def test_nvgre_tunnels_add_del(self): + db = Db() + runner = CliRunner() + + # add + result = runner.invoke( + config.config.commands["nvgre-tunnel"].commands["add"], + ["tunnel_1", "--src-ip", "10.0.0.1"], obj=db + ) + + logger.debug("\n" + result.output) + logger.debug(result.exit_code) + assert result.exit_code == SUCCESS + + result = runner.invoke( + config.config.commands["nvgre-tunnel"].commands["add"], + ["tunnel_2", "--src-ip", "10.0.0.2"], obj=db + ) + + logger.debug("\n" + result.output) + logger.debug(result.exit_code) + assert result.exit_code == SUCCESS + + # verify + result = runner.invoke(show.cli.commands["nvgre-tunnel"], [], obj=db) + + logger.debug("\n" + result.output) + logger.debug(result.exit_code) + assert result.exit_code == SUCCESS + assert result.output == assert_show_output.show_nvgre_tunnels + + # delete + result = runner.invoke( + config.config.commands["nvgre-tunnel"].commands["delete"], + ["tunnel_1"], obj=db + ) + + logger.debug("\n" + result.output) + logger.debug(result.exit_code) + assert result.exit_code == SUCCESS + + result = runner.invoke( + config.config.commands["nvgre-tunnel"].commands["delete"], + ["tunnel_2"], obj=db + ) + + logger.debug("\n" + result.output) + logger.debug(result.exit_code) + assert result.exit_code == SUCCESS + + + def test_nvgre_tunnel_update(self): + dbconnector.dedicated_dbs['CONFIG_DB'] = os.path.join(mock_db_path, 'nvgre_tunnel') + db = Db() + runner = CliRunner() + + # update + result = runner.invoke( + config.config.commands["nvgre-tunnel"].commands["update"], + ["tunnel_1", "--src-ip", "10.0.0.2"], obj=db + ) + + logger.debug("\n" + result.output) + logger.debug(result.exit_code) + assert result.exit_code == SUCCESS + + # verify + result = runner.invoke(show.cli.commands["nvgre-tunnel"], [], obj=db) + + logger.debug("\n" + result.output) + logger.debug(result.exit_code) + assert result.exit_code == SUCCESS + assert result.output == assert_show_output.show_nvgre_tunnel_updated + + + def test_nvgre_tunnel_add_invalid(self): + db = Db() + runner = CliRunner() + + # add + result = runner.invoke( + config.config.commands["nvgre-tunnel"].commands["add"], + ["tunnel_1", "--src-ip", INVALID_VALUE], obj=db + ) + + logger.debug("\n" + result.output) + logger.debug(result.exit_code) + assert result.exit_code == ERROR + + + ######### NVGRE-TUNNEL-MAP ######### + + + def test_nvgre_tunnel_maps_add_del(self): + dbconnector.dedicated_dbs['CONFIG_DB'] = os.path.join(mock_db_path, 'nvgre_tunnel') + db = Db() + runner = CliRunner() + + # add + result = runner.invoke( + config.config.commands["nvgre-tunnel-map"].commands["add"], + ["tunnel_1", "Vlan1000", "--vlan-id", "1000", "--vsid", "5000"], obj=db + ) + + logger.debug("\n" + result.output) + logger.debug(result.exit_code) + assert result.exit_code == SUCCESS + + result = runner.invoke( + config.config.commands["nvgre-tunnel-map"].commands["add"], + ["tunnel_1", "Vlan2000", "--vlan-id", "2000", "--vsid", "6000"], obj=db + ) + + logger.debug("\n" + result.output) + logger.debug(result.exit_code) + assert result.exit_code == SUCCESS + + # verify + result = runner.invoke(show.cli.commands["nvgre-tunnel-map"], [], obj=db) + + logger.debug("\n" + result.output) + logger.debug(result.exit_code) + assert result.exit_code == SUCCESS + assert result.output == assert_show_output.show_nvgre_tunnel_maps + + # delete + result = runner.invoke( + config.config.commands["nvgre-tunnel-map"].commands["delete"], + ["tunnel_1", "Vlan1000"], obj=db + ) + + logger.debug("\n" + result.output) + logger.debug(result.exit_code) + assert result.exit_code == SUCCESS + + result = runner.invoke( + config.config.commands["nvgre-tunnel-map"].commands["delete"], + ["tunnel_1", "Vlan2000"], obj=db + ) + + logger.debug("\n" + result.output) + logger.debug(result.exit_code) + assert result.exit_code == SUCCESS + From aaee9564f497fdea961a29467a37620be5c4d9b8 Mon Sep 17 00:00:00 2001 From: Vadym Hlushko Date: Thu, 4 Nov 2021 08:08:52 +0000 Subject: [PATCH 04/12] Added nvgre-tunnel-map test cases, removed unused code Signed-off-by: Vadym Hlushko --- .../nvgre_tunnel_input/nvgre_tunnel_map.json | 5 +- tests/nvgre_tunnel_test.py | 65 +++++++++++++++++-- 2 files changed, 62 insertions(+), 8 deletions(-) diff --git a/tests/nvgre_tunnel_input/nvgre_tunnel_map.json b/tests/nvgre_tunnel_input/nvgre_tunnel_map.json index 8a1696fca9..a95fb08592 100644 --- a/tests/nvgre_tunnel_input/nvgre_tunnel_map.json +++ b/tests/nvgre_tunnel_input/nvgre_tunnel_map.json @@ -5,7 +5,8 @@ "VLAN|Vlan1000": { "vlanid": "1000" }, - "VLAN|Vlan2000": { - "vlanid": "2000" + "NVGRE_TUNNEL_MAP|tunnel_1|Vlan1000": { + "vlan_id": "1000", + "vsid": "5000" } } \ No newline at end of file diff --git a/tests/nvgre_tunnel_test.py b/tests/nvgre_tunnel_test.py index 897b8d22a6..e2359de852 100644 --- a/tests/nvgre_tunnel_test.py +++ b/tests/nvgre_tunnel_test.py @@ -1,6 +1,5 @@ #!/usr/bin/env python -import pytest import os import logging import show.main as show @@ -10,7 +9,6 @@ from utilities_common.db import Db from click.testing import CliRunner from .mock_tables import dbconnector -from .mock_tables import mock_single_asic logger = logging.getLogger(__name__) test_path = os.path.dirname(os.path.abspath(__file__)) @@ -18,16 +16,15 @@ SUCCESS = 0 ERROR = 1 -ERROR2 = 2 INVALID_VALUE = 'INVALID' -class TestPBH: +class TestNvgreTunnel: @classmethod def setup_class(cls): logger.info("SETUP") - os.environ['UTILITIES_UNIT_TESTING'] = "1" + os.environ['UTILITIES_UNIT_TESTING'] = "2" @classmethod @@ -166,7 +163,7 @@ def test_nvgre_tunnel_add_invalid(self): ######### NVGRE-TUNNEL-MAP ######### - + def test_nvgre_tunnel_maps_add_del(self): dbconnector.dedicated_dbs['CONFIG_DB'] = os.path.join(mock_db_path, 'nvgre_tunnel') db = Db() @@ -217,4 +214,60 @@ def test_nvgre_tunnel_maps_add_del(self): logger.debug("\n" + result.output) logger.debug(result.exit_code) assert result.exit_code == SUCCESS + + + def test_nvgre_tunnel_map_add_invalid_vlan(self): + db = Db() + runner = CliRunner() + + # add + result = runner.invoke( + config.config.commands["nvgre-tunnel-map"].commands["add"], + ["tunnel_1", "Vlan1500", "--vlan-id", "1500", "--vsid", "5000"], obj=db + ) + + logger.debug("\n" + result.output) + logger.debug(result.exit_code) + assert result.exit_code == ERROR + + + def test_nvgre_tunnel_map_add_invalid_vsid(self): + dbconnector.dedicated_dbs['CONFIG_DB'] = os.path.join(mock_db_path, 'nvgre_tunnel') + db = Db() + runner = CliRunner() + + # add + result = runner.invoke( + config.config.commands["nvgre-tunnel-map"].commands["add"], + ["tunnel_1", "Vlan1000", "--vlan-id", "1000", "--vsid", "1"], obj=db + ) + + logger.debug("\n" + result.output) + logger.debug(result.exit_code) + assert result.exit_code == ERROR + + + # bug + #def test_nvgre_tunnel_map_update(self): + # dbconnector.dedicated_dbs['CONFIG_DB'] = os.path.join(mock_db_path, 'nvgre_tunnel_map') + # db = Db() + # runner = CliRunner() + + # # add + # result = runner.invoke( + # config.config.commands["nvgre-tunnel-map"].commands["update"], + # ["tunnel_1", "Vlan1000", "--vsid", "6000"], obj=db + # ) + + # logger.debug("\n" + result.output) + # logger.debug(result.exit_code) + # assert result.exit_code == SUCCESS + + # # verify + # result = runner.invoke(show.cli.commands["nvgre-tunnel-map"], [], obj=db) + + # logger.debug("\n" + result.output) + # logger.debug(result.exit_code) + # assert result.exit_code == SUCCESS + # #assert result.output == assert_show_output.show_nvgre_tunnel_maps From 4b6bfa4f9c6c0ff8804f0afab567b9c61a33585f Mon Sep 17 00:00:00 2001 From: Vadym Hlushko Date: Thu, 4 Nov 2021 10:14:11 +0000 Subject: [PATCH 05/12] Added mock of empty Config DB Signed-off-by: Vadym Hlushko --- tests/nvgre_tunnel_input/empty_config_db.json | 3 +++ tests/nvgre_tunnel_test.py | 2 ++ 2 files changed, 5 insertions(+) create mode 100644 tests/nvgre_tunnel_input/empty_config_db.json diff --git a/tests/nvgre_tunnel_input/empty_config_db.json b/tests/nvgre_tunnel_input/empty_config_db.json new file mode 100644 index 0000000000..0e0dcd235c --- /dev/null +++ b/tests/nvgre_tunnel_input/empty_config_db.json @@ -0,0 +1,3 @@ +{ + +} \ No newline at end of file diff --git a/tests/nvgre_tunnel_test.py b/tests/nvgre_tunnel_test.py index e2359de852..605f8ce9a9 100644 --- a/tests/nvgre_tunnel_test.py +++ b/tests/nvgre_tunnel_test.py @@ -39,6 +39,7 @@ def teardown_class(cls): def test_nvgre_tunnel_add_del(self): + dbconnector.dedicated_dbs['CONFIG_DB'] = os.path.join(mock_db_path, 'empty_config_db') db = Db() runner = CliRunner() @@ -72,6 +73,7 @@ def test_nvgre_tunnel_add_del(self): def test_nvgre_tunnels_add_del(self): + dbconnector.dedicated_dbs['CONFIG_DB'] = os.path.join(mock_db_path, 'empty_config_db') db = Db() runner = CliRunner() From a4d08654a72acb7ce7361ae57651386e5f74f493 Mon Sep 17 00:00:00 2001 From: Vadym Hlushko Date: Thu, 4 Nov 2021 10:18:56 +0000 Subject: [PATCH 06/12] Changed name of generated CLI plugins Signed-off-by: Vadym Hlushko --- config/plugins/{sonic-nvgre-tunnel_yang.py => nvgre_tunnel.py} | 0 show/plugins/{sonic-nvgre-tunnel_yang.py => nvgre_tunnel.py} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename config/plugins/{sonic-nvgre-tunnel_yang.py => nvgre_tunnel.py} (100%) rename show/plugins/{sonic-nvgre-tunnel_yang.py => nvgre_tunnel.py} (100%) diff --git a/config/plugins/sonic-nvgre-tunnel_yang.py b/config/plugins/nvgre_tunnel.py similarity index 100% rename from config/plugins/sonic-nvgre-tunnel_yang.py rename to config/plugins/nvgre_tunnel.py diff --git a/show/plugins/sonic-nvgre-tunnel_yang.py b/show/plugins/nvgre_tunnel.py similarity index 100% rename from show/plugins/sonic-nvgre-tunnel_yang.py rename to show/plugins/nvgre_tunnel.py From b4359b95e12d84f3dcb1217edb8e5ad4351a68a9 Mon Sep 17 00:00:00 2001 From: Vadym Hlushko Date: Thu, 4 Nov 2021 14:49:42 +0000 Subject: [PATCH 07/12] fixed bug with update command Signed-off-by: Vadym Hlushko --- config/plugins/nvgre_tunnel.py | 3 +- .../nvgre_tunnel_input/assert_show_output.py | 7 +++ tests/nvgre_tunnel_test.py | 44 +++++++++---------- 3 files changed, 31 insertions(+), 23 deletions(-) diff --git a/config/plugins/nvgre_tunnel.py b/config/plugins/nvgre_tunnel.py index 3c760f92ee..bf0ba370fe 100644 --- a/config/plugins/nvgre_tunnel.py +++ b/config/plugins/nvgre_tunnel.py @@ -3,6 +3,7 @@ """ import click +import copy import utilities_common.cli as clicommon import utilities_common.general as general from config import config_mgmt @@ -34,7 +35,7 @@ def validate_config_or_raise(cfg): """ try: - cfg = sonic_cfggen.FormatConverter.to_serialized(cfg) + cfg = sonic_cfggen.FormatConverter.to_serialized(copy.deepcopy(cfg)) config_mgmt.ConfigMgmt().loadData(cfg) except Exception as err: raise Exception('Failed to validate configuration: {}'.format(err)) diff --git a/tests/nvgre_tunnel_input/assert_show_output.py b/tests/nvgre_tunnel_input/assert_show_output.py index fe6787d19e..53aeacfd93 100644 --- a/tests/nvgre_tunnel_input/assert_show_output.py +++ b/tests/nvgre_tunnel_input/assert_show_output.py @@ -31,3 +31,10 @@ ------------- -------- tunnel_1 10.0.0.2 """ + + +show_nvgre_tunnel_map_updated="""\ +TUNNEL NAME VLAN NAME VLAN ID VSID +------------- ----------- --------- ------ +tunnel_1 Vlan1000 1000 6000 +""" diff --git a/tests/nvgre_tunnel_test.py b/tests/nvgre_tunnel_test.py index 605f8ce9a9..8c5fc34f4f 100644 --- a/tests/nvgre_tunnel_test.py +++ b/tests/nvgre_tunnel_test.py @@ -250,26 +250,26 @@ def test_nvgre_tunnel_map_add_invalid_vsid(self): # bug - #def test_nvgre_tunnel_map_update(self): - # dbconnector.dedicated_dbs['CONFIG_DB'] = os.path.join(mock_db_path, 'nvgre_tunnel_map') - # db = Db() - # runner = CliRunner() - - # # add - # result = runner.invoke( - # config.config.commands["nvgre-tunnel-map"].commands["update"], - # ["tunnel_1", "Vlan1000", "--vsid", "6000"], obj=db - # ) - - # logger.debug("\n" + result.output) - # logger.debug(result.exit_code) - # assert result.exit_code == SUCCESS - - # # verify - # result = runner.invoke(show.cli.commands["nvgre-tunnel-map"], [], obj=db) - - # logger.debug("\n" + result.output) - # logger.debug(result.exit_code) - # assert result.exit_code == SUCCESS - # #assert result.output == assert_show_output.show_nvgre_tunnel_maps + def test_nvgre_tunnel_map_update(self): + dbconnector.dedicated_dbs['CONFIG_DB'] = os.path.join(mock_db_path, 'nvgre_tunnel_map') + db = Db() + runner = CliRunner() + + # add + result = runner.invoke( + config.config.commands["nvgre-tunnel-map"].commands["update"], + ["tunnel_1", "Vlan1000", "--vsid", "6000"], obj=db + ) + + logger.debug("\n" + result.output) + logger.debug(result.exit_code) + assert result.exit_code == SUCCESS + + # verify + result = runner.invoke(show.cli.commands["nvgre-tunnel-map"], [], obj=db) + + logger.debug("\n" + result.output) + logger.debug(result.exit_code) + assert result.exit_code == SUCCESS + assert result.output == assert_show_output.show_nvgre_tunnel_map_updated From e4c040a95aef9dfc7b73ea3bd2d53c676eedd104 Mon Sep 17 00:00:00 2001 From: Vadym Hlushko Date: Thu, 4 Nov 2021 16:01:54 +0000 Subject: [PATCH 08/12] Remove comment Signed-off-by: Vadym Hlushko --- tests/nvgre_tunnel_test.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/nvgre_tunnel_test.py b/tests/nvgre_tunnel_test.py index 8c5fc34f4f..579ff71cd7 100644 --- a/tests/nvgre_tunnel_test.py +++ b/tests/nvgre_tunnel_test.py @@ -249,7 +249,6 @@ def test_nvgre_tunnel_map_add_invalid_vsid(self): assert result.exit_code == ERROR - # bug def test_nvgre_tunnel_map_update(self): dbconnector.dedicated_dbs['CONFIG_DB'] = os.path.join(mock_db_path, 'nvgre_tunnel_map') db = Db() From 04b4c444374c1390366e9d5a6222c168bb12c5b6 Mon Sep 17 00:00:00 2001 From: Vadym Hlushko Date: Fri, 5 Nov 2021 14:19:50 +0000 Subject: [PATCH 09/12] fixed comments, generated new cli according to fixed YANG model Signed-off-by: Vadym Hlushko --- config/plugins/nvgre_tunnel.py | 93 +++++-------------- show/plugins/nvgre_tunnel.py | 48 +++++----- .../nvgre_tunnel_input/assert_show_output.py | 25 +++-- tests/nvgre_tunnel_test.py | 90 ++++++------------ 4 files changed, 86 insertions(+), 170 deletions(-) diff --git a/config/plugins/nvgre_tunnel.py b/config/plugins/nvgre_tunnel.py index bf0ba370fe..4dc876bc8c 100644 --- a/config/plugins/nvgre_tunnel.py +++ b/config/plugins/nvgre_tunnel.py @@ -1,9 +1,9 @@ """ -Autogenerated config CLI plugin. +Autogenerated config CLI plugin for NVGRE Tunnel feature. """ -import click import copy +import click import utilities_common.cli as clicommon import utilities_common.general as general from config import config_mgmt @@ -93,12 +93,19 @@ def update_entry_validated(db, table, key, data, create_if_not_exists=False): if key not in cfg[table]: raise Exception(f"{key} does not exist") + entry_changed = False for attr, value in data.items(): + if value == cfg[table][key][attr]: + continue + entry_changed = True if value is None: cfg[table][key].pop(attr, None) else: cfg[table][key][attr] = value + if not entry_changed: + return + validate_config_or_raise(cfg) db.set_entry(table, key, cfg[table][key]) @@ -213,7 +220,8 @@ def NVGRE_TUNNEL(): ) @click.option( "--src-ip", - help="[mandatory]", + required=True, + help="Source IP address[mandatory]", ) @clicommon.pass_db def NVGRE_TUNNEL_add(db, tunnel_name, src_ip): @@ -231,32 +239,6 @@ def NVGRE_TUNNEL_add(db, tunnel_name, src_ip): exit_with_error(f"Error: {err}", fg="red") -@NVGRE_TUNNEL.command(name="update") -@click.argument( - "tunnel-name", - nargs=1, - required=True, -) -@click.option( - "--src-ip", - help="[mandatory]", -) -@clicommon.pass_db -def NVGRE_TUNNEL_update(db, tunnel_name, src_ip): - """ Add object in NVGRE_TUNNEL. """ - - table = "NVGRE_TUNNEL" - key = tunnel_name - data = {} - if src_ip is not None: - data["src_ip"] = src_ip - - try: - update_entry_validated(db.cfgdb, table, key, data) - except Exception as err: - exit_with_error(f"Error: {err}", fg="red") - - @NVGRE_TUNNEL.command(name="delete") @click.argument( "tunnel-name", @@ -275,10 +257,11 @@ def NVGRE_TUNNEL_delete(db, tunnel_name): exit_with_error(f"Error: {err}", fg="red") -@click.group(name="nvgre-tunnel-map", - cls=clicommon.AliasedGroup) +@click.group( + name="nvgre-tunnel-map", + cls=clicommon.AliasedGroup) def NVGRE_TUNNEL_MAP(): - """ NVGRE_TUNNEL part of config_db.json """ + """ NVGRE_TUNNEL_MAP part of config_db.json """ pass @@ -294,13 +277,16 @@ def NVGRE_TUNNEL_MAP(): nargs=1, required=True, ) + @click.option( "--vlan-id", - help="", + required=True, + help="VLAN identifier[mandatory]", ) @click.option( "--vsid", - help="", + required=True, + help="Virtual Subnet Identifier[mandatory]", ) @clicommon.pass_db def NVGRE_TUNNEL_MAP_add(db, tunnel_name, vlan_name, vlan_id, vsid): @@ -320,44 +306,6 @@ def NVGRE_TUNNEL_MAP_add(db, tunnel_name, vlan_name, vlan_id, vsid): exit_with_error(f"Error: {err}", fg="red") -@NVGRE_TUNNEL_MAP.command(name="update") - -@click.argument( - "tunnel-name", - nargs=1, - required=True, -) -@click.argument( - "vlan-name", - nargs=1, - required=True, -) -@click.option( - "--vlan-id", - help="", -) -@click.option( - "--vsid", - help="", -) -@clicommon.pass_db -def NVGRE_TUNNEL_MAP_update(db, tunnel_name, vlan_name, vlan_id, vsid): - """ Add object in NVGRE_TUNNEL_MAP. """ - - table = "NVGRE_TUNNEL_MAP" - key = tunnel_name, vlan_name - data = {} - if vlan_id is not None: - data["vlan_id"] = vlan_id - if vsid is not None: - data["vsid"] = vsid - - try: - update_entry_validated(db.cfgdb, table, key, data) - except Exception as err: - exit_with_error(f"Error: {err}", fg="red") - - @NVGRE_TUNNEL_MAP.command(name="delete") @click.argument( "tunnel-name", @@ -398,3 +346,4 @@ def register(cli): if cli_node.name in cli.commands: raise Exception(f"{cli_node.name} already exists in CLI") cli.add_command(NVGRE_TUNNEL_MAP) + diff --git a/show/plugins/nvgre_tunnel.py b/show/plugins/nvgre_tunnel.py index 6e698d1da6..6e38cca714 100644 --- a/show/plugins/nvgre_tunnel.py +++ b/show/plugins/nvgre_tunnel.py @@ -1,5 +1,5 @@ """ -Auto-generated show CLI plugin. +Auto-generated show CLI plugin for NVGRE Tunnel feature. """ import click @@ -39,8 +39,7 @@ def format_group_value(entry, attrs): for attr in attrs: if entry.get(attr["name"]): data.append((attr["name"] + ":", format_attr_value(entry, attr))) - - return tabulate.tabulate(data, tablefmt="plain") + return tabulate.tabulate(data, tablefmt="plain", numalign="left") @click.group( @@ -61,22 +60,22 @@ def NVGRE_TUNNEL(db): if not isinstance(key, tuple): key = (key,) - row = [*key] + [ - format_attr_value( - entry, - { - 'name': 'src_ip', - 'description': '', - 'is-leaf-list': False, - 'is-mandatory': True, - 'group': '' - } - ) - ] + row = [*key] + [ + format_attr_value( + entry, + { + 'name': 'src_ip', + 'description': 'Source IP address', + 'is-leaf-list': False, + 'is-mandatory': True, + 'group': '' + } + ) + ] body.append(row) - click.echo(tabulate.tabulate(body, header)) + click.echo(tabulate.tabulate(body, header, numalign="left")) @click.group( @@ -87,7 +86,12 @@ def NVGRE_TUNNEL(db): def NVGRE_TUNNEL_MAP(db): """ [Callable command group] """ - header = [ "TUNNEL NAME", "VLAN NAME", "VLAN ID", "VSID" ] + header = [ + "TUNNEL NAME", + "VLAN NAME", + "VLAN ID", + "VSID" + ] body = [] @@ -102,9 +106,9 @@ def NVGRE_TUNNEL_MAP(db): entry, { 'name': 'vlan_id', - 'description': '', + 'description': 'VLAN identifier', 'is-leaf-list': False, - 'is-mandatory': False, + 'is-mandatory': True, 'group': '' } ), @@ -112,9 +116,9 @@ def NVGRE_TUNNEL_MAP(db): entry, { 'name': 'vsid', - 'description': '', + 'description': 'Virtual Subnet Identifier', 'is-leaf-list': False, - 'is-mandatory': False, + 'is-mandatory': True, 'group': '' } ) @@ -122,7 +126,7 @@ def NVGRE_TUNNEL_MAP(db): body.append(row) - click.echo(tabulate.tabulate(body, header)) + click.echo(tabulate.tabulate(body, header, numalign="left")) def register(cli): diff --git a/tests/nvgre_tunnel_input/assert_show_output.py b/tests/nvgre_tunnel_input/assert_show_output.py index 53aeacfd93..0e376eedea 100644 --- a/tests/nvgre_tunnel_input/assert_show_output.py +++ b/tests/nvgre_tunnel_input/assert_show_output.py @@ -10,6 +10,12 @@ """ +show_nvgre_tunnel_empty="""\ +TUNNEL NAME SRC IP +------------- -------- +""" + + show_nvgre_tunnels="""\ TUNNEL NAME SRC IP ------------- -------- @@ -19,22 +25,15 @@ show_nvgre_tunnel_maps="""\ -TUNNEL NAME VLAN NAME VLAN ID VSID +TUNNEL NAME VLAN NAME VLAN ID VSID ------------- ----------- --------- ------ -tunnel_1 Vlan1000 1000 5000 -tunnel_1 Vlan2000 2000 6000 +tunnel_1 Vlan1000 1000 5000 +tunnel_1 Vlan2000 2000 6000 """ -show_nvgre_tunnel_updated="""\ -TUNNEL NAME SRC IP -------------- -------- -tunnel_1 10.0.0.2 -""" - - -show_nvgre_tunnel_map_updated="""\ -TUNNEL NAME VLAN NAME VLAN ID VSID +show_nvgre_tunnel_map_empty="""\ +TUNNEL NAME VLAN NAME VLAN ID VSID ------------- ----------- --------- ------ -tunnel_1 Vlan1000 1000 6000 """ + diff --git a/tests/nvgre_tunnel_test.py b/tests/nvgre_tunnel_test.py index 579ff71cd7..925d900107 100644 --- a/tests/nvgre_tunnel_test.py +++ b/tests/nvgre_tunnel_test.py @@ -35,6 +35,15 @@ def teardown_class(cls): dbconnector.dedicated_dbs['CONFIG_DB'] = None + def verify_output(self, db, runner, cmd, output): + result = runner.invoke(show.cli.commands[cmd], [], obj=db) + + logger.debug("\n" + result.output) + logger.debug(result.exit_code) + assert result.exit_code == SUCCESS + assert result.output == output + + ######### NVGRE-TUNNEL ######### @@ -54,12 +63,7 @@ def test_nvgre_tunnel_add_del(self): assert result.exit_code == SUCCESS # verify - result = runner.invoke(show.cli.commands["nvgre-tunnel"], [], obj=db) - - logger.debug("\n" + result.output) - logger.debug(result.exit_code) - assert result.exit_code == SUCCESS - assert result.output == assert_show_output.show_nvgre_tunnel + self.verify_output(db, runner, "nvgre-tunnel", assert_show_output.show_nvgre_tunnel) # delete result = runner.invoke( @@ -71,6 +75,9 @@ def test_nvgre_tunnel_add_del(self): logger.debug(result.exit_code) assert result.exit_code == SUCCESS + # verify + self.verify_output(db, runner, "nvgre-tunnel", assert_show_output.show_nvgre_tunnel_empty) + def test_nvgre_tunnels_add_del(self): dbconnector.dedicated_dbs['CONFIG_DB'] = os.path.join(mock_db_path, 'empty_config_db') @@ -97,12 +104,7 @@ def test_nvgre_tunnels_add_del(self): assert result.exit_code == SUCCESS # verify - result = runner.invoke(show.cli.commands["nvgre-tunnel"], [], obj=db) - - logger.debug("\n" + result.output) - logger.debug(result.exit_code) - assert result.exit_code == SUCCESS - assert result.output == assert_show_output.show_nvgre_tunnels + self.verify_output(db, runner, "nvgre-tunnel", assert_show_output.show_nvgre_tunnels) # delete result = runner.invoke( @@ -123,31 +125,10 @@ def test_nvgre_tunnels_add_del(self): logger.debug(result.exit_code) assert result.exit_code == SUCCESS - - def test_nvgre_tunnel_update(self): - dbconnector.dedicated_dbs['CONFIG_DB'] = os.path.join(mock_db_path, 'nvgre_tunnel') - db = Db() - runner = CliRunner() - - # update - result = runner.invoke( - config.config.commands["nvgre-tunnel"].commands["update"], - ["tunnel_1", "--src-ip", "10.0.0.2"], obj=db - ) - - logger.debug("\n" + result.output) - logger.debug(result.exit_code) - assert result.exit_code == SUCCESS - # verify - result = runner.invoke(show.cli.commands["nvgre-tunnel"], [], obj=db) + self.verify_output(db, runner, "nvgre-tunnel", assert_show_output.show_nvgre_tunnel_empty) - logger.debug("\n" + result.output) - logger.debug(result.exit_code) - assert result.exit_code == SUCCESS - assert result.output == assert_show_output.show_nvgre_tunnel_updated - def test_nvgre_tunnel_add_invalid(self): db = Db() runner = CliRunner() @@ -162,6 +143,9 @@ def test_nvgre_tunnel_add_invalid(self): logger.debug(result.exit_code) assert result.exit_code == ERROR + # verify + self.verify_output(db, runner, "nvgre-tunnel", assert_show_output.show_nvgre_tunnel_empty) + ######### NVGRE-TUNNEL-MAP ######### @@ -191,12 +175,7 @@ def test_nvgre_tunnel_maps_add_del(self): assert result.exit_code == SUCCESS # verify - result = runner.invoke(show.cli.commands["nvgre-tunnel-map"], [], obj=db) - - logger.debug("\n" + result.output) - logger.debug(result.exit_code) - assert result.exit_code == SUCCESS - assert result.output == assert_show_output.show_nvgre_tunnel_maps + self.verify_output(db, runner, "nvgre-tunnel-map", assert_show_output.show_nvgre_tunnel_maps) # delete result = runner.invoke( @@ -217,6 +196,9 @@ def test_nvgre_tunnel_maps_add_del(self): logger.debug(result.exit_code) assert result.exit_code == SUCCESS + # verify + self.verify_output(db, runner, "nvgre-tunnel-map", assert_show_output.show_nvgre_tunnel_map_empty) + def test_nvgre_tunnel_map_add_invalid_vlan(self): db = Db() @@ -232,6 +214,9 @@ def test_nvgre_tunnel_map_add_invalid_vlan(self): logger.debug(result.exit_code) assert result.exit_code == ERROR + # verify + self.verify_output(db, runner, "nvgre-tunnel-map", assert_show_output.show_nvgre_tunnel_map_empty) + def test_nvgre_tunnel_map_add_invalid_vsid(self): dbconnector.dedicated_dbs['CONFIG_DB'] = os.path.join(mock_db_path, 'nvgre_tunnel') @@ -241,34 +226,13 @@ def test_nvgre_tunnel_map_add_invalid_vsid(self): # add result = runner.invoke( config.config.commands["nvgre-tunnel-map"].commands["add"], - ["tunnel_1", "Vlan1000", "--vlan-id", "1000", "--vsid", "1"], obj=db + ["tunnel_1", "Vlan1000", "--vlan-id", "1000", "--vsid", "999999999"], obj=db ) logger.debug("\n" + result.output) logger.debug(result.exit_code) assert result.exit_code == ERROR - - def test_nvgre_tunnel_map_update(self): - dbconnector.dedicated_dbs['CONFIG_DB'] = os.path.join(mock_db_path, 'nvgre_tunnel_map') - db = Db() - runner = CliRunner() - - # add - result = runner.invoke( - config.config.commands["nvgre-tunnel-map"].commands["update"], - ["tunnel_1", "Vlan1000", "--vsid", "6000"], obj=db - ) - - logger.debug("\n" + result.output) - logger.debug(result.exit_code) - assert result.exit_code == SUCCESS - # verify - result = runner.invoke(show.cli.commands["nvgre-tunnel-map"], [], obj=db) + self.verify_output(db, runner, "nvgre-tunnel-map", assert_show_output.show_nvgre_tunnel_map_empty) - logger.debug("\n" + result.output) - logger.debug(result.exit_code) - assert result.exit_code == SUCCESS - assert result.output == assert_show_output.show_nvgre_tunnel_map_updated - From ac7379124d4be157cee9e902f50f6a0f5fd12fdb Mon Sep 17 00:00:00 2001 From: Vadym Hlushko Date: Thu, 2 Dec 2021 12:25:05 +0000 Subject: [PATCH 10/12] Fixed a tunnel map name key Signed-off-by: Vadym Hlushko --- config/plugins/nvgre_tunnel.py | 12 ++++++------ show/plugins/nvgre_tunnel.py | 2 +- tests/nvgre_tunnel_input/assert_show_output.py | 12 ++++++------ 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/config/plugins/nvgre_tunnel.py b/config/plugins/nvgre_tunnel.py index 4dc876bc8c..cbb4ce2d73 100644 --- a/config/plugins/nvgre_tunnel.py +++ b/config/plugins/nvgre_tunnel.py @@ -273,7 +273,7 @@ def NVGRE_TUNNEL_MAP(): required=True, ) @click.argument( - "vlan-name", + "tunnel-map-name", nargs=1, required=True, ) @@ -289,11 +289,11 @@ def NVGRE_TUNNEL_MAP(): help="Virtual Subnet Identifier[mandatory]", ) @clicommon.pass_db -def NVGRE_TUNNEL_MAP_add(db, tunnel_name, vlan_name, vlan_id, vsid): +def NVGRE_TUNNEL_MAP_add(db, tunnel_name, tunnel_map_name, vlan_id, vsid): """ Add object in NVGRE_TUNNEL_MAP. """ table = "NVGRE_TUNNEL_MAP" - key = tunnel_name, vlan_name + key = tunnel_name, tunnel_map_name data = {} if vlan_id is not None: data["vlan_id"] = vlan_id @@ -313,16 +313,16 @@ def NVGRE_TUNNEL_MAP_add(db, tunnel_name, vlan_name, vlan_id, vsid): required=True, ) @click.argument( - "vlan-name", + "tunnel-map-name", nargs=1, required=True, ) @clicommon.pass_db -def NVGRE_TUNNEL_MAP_delete(db, tunnel_name, vlan_name): +def NVGRE_TUNNEL_MAP_delete(db, tunnel_name, tunnel_map_name): """ Delete object in NVGRE_TUNNEL_MAP. """ table = "NVGRE_TUNNEL_MAP" - key = tunnel_name, vlan_name + key = tunnel_name, tunnel_map_name try: del_entry_validated(db.cfgdb, table, key) except Exception as err: diff --git a/show/plugins/nvgre_tunnel.py b/show/plugins/nvgre_tunnel.py index 6e38cca714..bd6d86c04c 100644 --- a/show/plugins/nvgre_tunnel.py +++ b/show/plugins/nvgre_tunnel.py @@ -88,7 +88,7 @@ def NVGRE_TUNNEL_MAP(db): header = [ "TUNNEL NAME", - "VLAN NAME", + "TUNNEL MAP NAME", "VLAN ID", "VSID" ] diff --git a/tests/nvgre_tunnel_input/assert_show_output.py b/tests/nvgre_tunnel_input/assert_show_output.py index 0e376eedea..4517eac119 100644 --- a/tests/nvgre_tunnel_input/assert_show_output.py +++ b/tests/nvgre_tunnel_input/assert_show_output.py @@ -25,15 +25,15 @@ show_nvgre_tunnel_maps="""\ -TUNNEL NAME VLAN NAME VLAN ID VSID -------------- ----------- --------- ------ -tunnel_1 Vlan1000 1000 5000 -tunnel_1 Vlan2000 2000 6000 +TUNNEL NAME TUNNEL MAP NAME VLAN ID VSID +------------- ----------------- --------- ------ +tunnel_1 Vlan1000 1000 5000 +tunnel_1 Vlan2000 2000 6000 """ show_nvgre_tunnel_map_empty="""\ -TUNNEL NAME VLAN NAME VLAN ID VSID -------------- ----------- --------- ------ +TUNNEL NAME TUNNEL MAP NAME VLAN ID VSID +------------- ----------------- --------- ------ """ From 74dad09acc2ba3bd2d881c77c1493401da950e40 Mon Sep 17 00:00:00 2001 From: Vadym Hlushko Date: Tue, 8 Mar 2022 14:17:21 +0000 Subject: [PATCH 11/12] Fixed UT Signed-off-by: Vadym Hlushko --- tests/nvgre_tunnel_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/nvgre_tunnel_test.py b/tests/nvgre_tunnel_test.py index 925d900107..c63baeee41 100644 --- a/tests/nvgre_tunnel_test.py +++ b/tests/nvgre_tunnel_test.py @@ -207,7 +207,7 @@ def test_nvgre_tunnel_map_add_invalid_vlan(self): # add result = runner.invoke( config.config.commands["nvgre-tunnel-map"].commands["add"], - ["tunnel_1", "Vlan1500", "--vlan-id", "1500", "--vsid", "5000"], obj=db + ["tunnel_1", "Vlan5000", "--vlan-id", "5000", "--vsid", "5000"], obj=db ) logger.debug("\n" + result.output) From c117cf5cc51d6c5bf9443cb8fa26dd1891592895 Mon Sep 17 00:00:00 2001 From: Vadym Hlushko Date: Thu, 17 Mar 2022 18:13:35 +0000 Subject: [PATCH 12/12] NVGRE command reference Signed-off-by: Vadym Hlushko --- doc/Command-Reference.md | 94 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/doc/Command-Reference.md b/doc/Command-Reference.md index b1846d1551..20f0e0b86b 100644 --- a/doc/Command-Reference.md +++ b/doc/Command-Reference.md @@ -110,6 +110,9 @@ * [NTP](#ntp) * [NTP show commands](#ntp-show-commands) * [NTP config commands](#ntp-config-commands) +* [NVGRE](#nvgre) + * [NVGRE show commands](#nvgre-show-commands) + * [NVGRE config commands](#nvgre-config-commands) * [PBH](#pbh) * [PBH show commands](#pbh-show-commands) * [PBH config commands](#pbh-config-commands) @@ -6767,6 +6770,97 @@ This command adds or deletes a member port to/from the already created portchann Go Back To [Beginning of the document](#) or [Beginning of this section](#portchannels) +## NVGRE + +This section explains the various show commands and configuration commands available for users. + +### NVGRE show commands + +This subsection explains how to display the NVGRE configuration. + +**show nvgre-tunnel** + +This command displays the NVGRE tunnel configuration. + +- Usage: +```bash +show nvgre-tunnel +``` + +- Example: +```bash +admin@sonic:~$ show nvgre-tunnel +TUNNEL NAME SRC IP +------------- -------- +tunnel_1 10.0.0.1 +``` + +**show nvgre-tunnel-map** + +This command displays the NVGRE tunnel map configuration. + +- Usage: +```bash +show nvgre-tunnel-map +``` + +- Example: +```bash +admin@sonic:~$ show nvgre-tunnel-map +TUNNEL NAME TUNNEL MAP NAME VLAN ID VSID +------------- ----------------- --------- ------ +tunnel_1 Vlan1000 1000 5000 +tunnel_1 Vlan2000 2000 6000 +``` + +### NVGRE config commands + +This subsection explains how to configure the NVGRE. + +**config nvgre-tunnel** + +This command is used to manage the NVGRE tunnel objects. +It supports add/delete operations. + +- Usage: +```bash +config nvgre-tunnel add --src-ip +config nvgre-tunnel delete +``` + +- Parameters: + - _tunnel-name_: the name of the NVGRE tunnel + - _src-ip_: source ip address + +- Examples: +```bash +config nvgre-tunnel add 'tunnel_1' --src-ip '10.0.0.1' +config nvgre-tunnel delete 'tunnel_1' +``` + +**config nvgre-tunnel-map** + +This command is used to manage the NVGRE tunnel map objects. +It supports add/delete operations. + +- Usage: +```bash +config nvgre-tunnel-map add --vlan-id --vsid +config nvgre-tunnel-map delete +``` + +- Parameters: + - _tunnel-name_: the name of the NVGRE tunnel + - _tunnel-map-name_: the name of the NVGRE tunnel map + - _vlan-id_: VLAN identifier + - _vsid_: Virtual Subnet Identifier + +- Examples: +```bash +config nvgre-tunnel-map add 'tunnel_1' 'Vlan2000' --vlan-id '2000' --vsid '6000' +config nvgre-tunnel-map delete 'tunnel_1' 'Vlan2000' +``` + ## PBH This section explains the various show commands and configuration commands available for users.