From 4e45d9c03d6eefdfa28edf34e16a5d4d583d775a Mon Sep 17 00:00:00 2001 From: Stepan Blyshchak <38952541+stepanblyschak@users.noreply.github.com> Date: Wed, 12 May 2021 19:55:14 +0300 Subject: [PATCH] [vlan] remove dhcp-relay as dhcp-relay commands will come as a plugin (#1378) - What I did Remove dhcp relay commands from sonic-utilities. dhcp-relay commands will come as a plugin with dhcp-relay docker installation. See Azure/SONiC#682 - How I did it Remove dhcp-relay commands from vlan. Make "show vlan brief" command table output extendable. - How to verify it Install dhcp-relay docker as app.ext. Verify that "config vlan dhcp-relay" and "show vlan brief" show dhcp data. --- config/vlan.py | 73 ---------- show/vlan.py | 197 +++++++++++++++----------- tests/vlan_test.py | 335 ++++++++++++--------------------------------- 3 files changed, 207 insertions(+), 398 deletions(-) diff --git a/config/vlan.py b/config/vlan.py index c3c29eb842..9cdb0fc348 100644 --- a/config/vlan.py +++ b/config/vlan.py @@ -185,76 +185,3 @@ def del_vlan_member(db, vid, port): db.cfgdb.set_entry('VLAN_MEMBER', (vlan, port), None) -@vlan.group(cls=clicommon.AbbreviationGroup, name='dhcp_relay') -def vlan_dhcp_relay(): - pass - -@vlan_dhcp_relay.command('add') -@click.argument('vid', metavar='', required=True, type=int) -@click.argument('dhcp_relay_destination_ip', metavar='', required=True) -@clicommon.pass_db -def add_vlan_dhcp_relay_destination(db, vid, dhcp_relay_destination_ip): - """ Add a destination IP address to the VLAN's DHCP relay """ - - ctx = click.get_current_context() - - if not clicommon.is_ipaddress(dhcp_relay_destination_ip): - ctx.fail('{} is invalid IP address'.format(dhcp_relay_destination_ip)) - - vlan_name = 'Vlan{}'.format(vid) - vlan = db.cfgdb.get_entry('VLAN', vlan_name) - if len(vlan) == 0: - ctx.fail("{} doesn't exist".format(vlan_name)) - - dhcp_relay_dests = vlan.get('dhcp_servers', []) - if dhcp_relay_destination_ip in dhcp_relay_dests: - click.echo("{} is already a DHCP relay destination for {}".format(dhcp_relay_destination_ip, vlan_name)) - return - - dhcp_relay_dests.append(dhcp_relay_destination_ip) - vlan['dhcp_servers'] = dhcp_relay_dests - db.cfgdb.set_entry('VLAN', vlan_name, vlan) - click.echo("Added DHCP relay destination address {} to {}".format(dhcp_relay_destination_ip, vlan_name)) - try: - click.echo("Restarting DHCP relay service...") - clicommon.run_command("systemctl stop dhcp_relay", display_cmd=False) - clicommon.run_command("systemctl reset-failed dhcp_relay", display_cmd=False) - clicommon.run_command("systemctl start dhcp_relay", display_cmd=False) - except SystemExit as e: - ctx.fail("Restart service dhcp_relay failed with error {}".format(e)) - -@vlan_dhcp_relay.command('del') -@click.argument('vid', metavar='', required=True, type=int) -@click.argument('dhcp_relay_destination_ip', metavar='', required=True) -@clicommon.pass_db -def del_vlan_dhcp_relay_destination(db, vid, dhcp_relay_destination_ip): - """ Remove a destination IP address from the VLAN's DHCP relay """ - - ctx = click.get_current_context() - - if not clicommon.is_ipaddress(dhcp_relay_destination_ip): - ctx.fail('{} is invalid IP address'.format(dhcp_relay_destination_ip)) - - vlan_name = 'Vlan{}'.format(vid) - vlan = db.cfgdb.get_entry('VLAN', vlan_name) - if len(vlan) == 0: - ctx.fail("{} doesn't exist".format(vlan_name)) - - dhcp_relay_dests = vlan.get('dhcp_servers', []) - if not dhcp_relay_destination_ip in dhcp_relay_dests: - ctx.fail("{} is not a DHCP relay destination for {}".format(dhcp_relay_destination_ip, vlan_name)) - - dhcp_relay_dests.remove(dhcp_relay_destination_ip) - if len(dhcp_relay_dests) == 0: - del vlan['dhcp_servers'] - else: - vlan['dhcp_servers'] = dhcp_relay_dests - db.cfgdb.set_entry('VLAN', vlan_name, vlan) - click.echo("Removed DHCP relay destination address {} from {}".format(dhcp_relay_destination_ip, vlan_name)) - try: - click.echo("Restarting DHCP relay service...") - clicommon.run_command("systemctl stop dhcp_relay", display_cmd=False) - clicommon.run_command("systemctl reset-failed dhcp_relay", display_cmd=False) - clicommon.run_command("systemctl start dhcp_relay", display_cmd=False) - except SystemExit as e: - ctx.fail("Restart service dhcp_relay failed with error {}".format(e)) diff --git a/show/vlan.py b/show/vlan.py index df4149fca9..b27f282a49 100644 --- a/show/vlan.py +++ b/show/vlan.py @@ -4,105 +4,141 @@ import utilities_common.cli as clicommon + @click.group(cls=clicommon.AliasedGroup) def vlan(): """Show VLAN information""" pass + +def get_vlan_id(ctx, vlan): + vlan_prefix, vid = vlan.split('Vlan') + return vid + + +def get_vlan_ip_address(ctx, vlan): + cfg, _ = ctx + _, vlan_ip_data, _ = cfg + ip_address = "" + for key in vlan_ip_data: + if not clicommon.is_ip_prefix_in_key(key): + continue + ifname, address = key + if vlan == ifname: + ip_address += "\n{}".format(address) + + return ip_address + + +def get_vlan_ports(ctx, vlan): + cfg, db = ctx + _, _, vlan_ports_data = cfg + vlan_ports = [] + iface_alias_converter = clicommon.InterfaceAliasConverter(db) + # Here natsorting is important in relation to another + # column which prints port tagging mode. + # If we sort both in the same way using same keys + # we will result in right order in both columns. + # This should be fixed by cli code autogeneration tool + # and we won't need this specific approach with + # VlanBrief.COLUMNS anymore. + for key in natsorted(list(vlan_ports_data.keys())): + ports_key, ports_value = key + if vlan != ports_key: + continue + + if clicommon.get_interface_naming_mode() == "alias": + ports_value = iface_alias_converter.name_to_alias(ports_value) + + vlan_ports.append(ports_value) + + return '\n'.join(vlan_ports) + + +def get_vlan_ports_tagging(ctx, vlan): + cfg, db = ctx + _, _, vlan_ports_data = cfg + vlan_ports_tagging = [] + # Here natsorting is important in relation to another + # column which prints vlan ports. + # If we sort both in the same way using same keys + # we will result in right order in both columns. + # This should be fixed by cli code autogeneration tool + # and we won't need this specific approach with + # VlanBrief.COLUMNS anymore. + for key in natsorted(list(vlan_ports_data.keys())): + ports_key, ports_value = key + if vlan != ports_key: + continue + + tagging_value = vlan_ports_data[key]["tagging_mode"] + vlan_ports_tagging.append(tagging_value) + + return '\n'.join(vlan_ports_tagging) + + +def get_proxy_arp(ctx, vlan): + cfg, _ = ctx + _, vlan_ip_data, _ = cfg + proxy_arp = "disabled" + for key in vlan_ip_data: + if clicommon.is_ip_prefix_in_key(key): + continue + if vlan == key: + proxy_arp = vlan_ip_data[key].get("proxy_arp", "disabled") + + return proxy_arp + + +class VlanBrief: + """ This class is used as a namespace to + define columns for "show vlan brief" command. + The usage of this class is for external plugin + (in this case dhcp-relay) to append new columns + to this list. + """ + + COLUMNS = [ + ("VLAN ID", get_vlan_id), + ("IP Address", get_vlan_ip_address), + ("Ports", get_vlan_ports), + ("Port Tagging", get_vlan_ports_tagging), + ("Proxy ARP", get_proxy_arp) + ] + + @classmethod + def register_column(cls, column_name, callback): + """ Adds a new column to "vlan brief" output. + Expected to be used from plugins code to extend + this command with additional VLAN fields. """ + + cls.COLUMNS.append((column_name, callback)) + + @vlan.command() @click.option('--verbose', is_flag=True, help="Enable verbose output") @clicommon.pass_db def brief(db, verbose): """Show all bridge information""" - header = ['VLAN ID', 'IP Address', 'Ports', 'Port Tagging', 'DHCP Helper Address', 'Proxy ARP'] + header = [colname for colname, getter in VlanBrief.COLUMNS] body = [] # Fetching data from config db for VLAN, VLAN_INTERFACE and VLAN_MEMBER - vlan_dhcp_helper_data = db.cfgdb.get_table('VLAN') + vlan_data = db.cfgdb.get_table('VLAN') vlan_ip_data = db.cfgdb.get_table('VLAN_INTERFACE') vlan_ports_data = db.cfgdb.get_table('VLAN_MEMBER') + vlan_cfg = (vlan_data, vlan_ip_data, vlan_ports_data) - # Defining dictionaries for DHCP Helper address, Interface Gateway IP, - # VLAN ports and port tagging - vlan_dhcp_helper_dict = {} - vlan_ip_dict = {} - vlan_ports_dict = {} - vlan_tagging_dict = {} - vlan_proxy_arp_dict = {} - - # Parsing DHCP Helpers info - for key in natsorted(list(vlan_dhcp_helper_data.keys())): - try: - if vlan_dhcp_helper_data[key]['dhcp_servers']: - vlan_dhcp_helper_dict[key.strip('Vlan')] = vlan_dhcp_helper_data[key]['dhcp_servers'] - except KeyError: - vlan_dhcp_helper_dict[key.strip('Vlan')] = " " - - # Parsing VLAN Gateway info - for key in vlan_ip_data: - if clicommon.is_ip_prefix_in_key(key): - interface_key = key[0].strip("Vlan") - interface_value = key[1] - - if interface_key in vlan_ip_dict: - vlan_ip_dict[interface_key].append(interface_value) - else: - vlan_ip_dict[interface_key] = [interface_value] - else: - interface_key = key.strip("Vlan") - if 'proxy_arp' in vlan_ip_data[key]: - proxy_arp_status = vlan_ip_data[key]['proxy_arp'] - else: - proxy_arp_status = "disabled" - - vlan_proxy_arp_dict[interface_key] = proxy_arp_status - - + for vlan in natsorted(vlan_data): + row = [] + for column in VlanBrief.COLUMNS: + column_name, getter = column + row.append(getter((vlan_cfg, db), vlan)) + body.append(row) - iface_alias_converter = clicommon.InterfaceAliasConverter(db) - - # Parsing VLAN Ports info - for key in natsorted(list(vlan_ports_data.keys())): - ports_key = key[0].strip("Vlan") - ports_value = key[1] - ports_tagging = vlan_ports_data[key]['tagging_mode'] - if ports_key in vlan_ports_dict: - if clicommon.get_interface_naming_mode() == "alias": - ports_value = iface_alias_converter.name_to_alias(ports_value) - vlan_ports_dict[ports_key].append(ports_value) - else: - if clicommon.get_interface_naming_mode() == "alias": - ports_value = iface_alias_converter.name_to_alias(ports_value) - vlan_ports_dict[ports_key] = [ports_value] - if ports_key in vlan_tagging_dict: - vlan_tagging_dict[ports_key].append(ports_tagging) - else: - vlan_tagging_dict[ports_key] = [ports_tagging] - - # Printing the following dictionaries in tablular forms: - # vlan_dhcp_helper_dict={}, vlan_ip_dict = {}, vlan_ports_dict = {} - # vlan_tagging_dict = {} - for key in natsorted(list(vlan_dhcp_helper_dict.keys())): - if key not in vlan_ip_dict: - ip_address = "" - else: - ip_address = ','.replace(',', '\n').join(vlan_ip_dict[key]) - if key not in vlan_ports_dict: - vlan_ports = "" - else: - vlan_ports = ','.replace(',', '\n').join((vlan_ports_dict[key])) - if key not in vlan_dhcp_helper_dict: - dhcp_helpers = "" - else: - dhcp_helpers = ','.replace(',', '\n').join(vlan_dhcp_helper_dict[key]) - if key not in vlan_tagging_dict: - vlan_tagging = "" - else: - vlan_tagging = ','.replace(',', '\n').join((vlan_tagging_dict[key])) - vlan_proxy_arp = vlan_proxy_arp_dict.get(key, "disabled") - body.append([key, ip_address, vlan_ports, vlan_tagging, dhcp_helpers, vlan_proxy_arp]) click.echo(tabulate(body, header, tablefmt="grid")) + @vlan.command() @clicommon.pass_db def config(db): @@ -141,3 +177,4 @@ def tablelize(keys, data): header = ['Name', 'VID', 'Member', 'Mode'] click.echo(tabulate(tablelize(keys, data), header)) + diff --git a/tests/vlan_test.py b/tests/vlan_test.py index ad3ff9fbb4..a7f533a824 100644 --- a/tests/vlan_test.py +++ b/tests/vlan_test.py @@ -10,79 +10,71 @@ from importlib import reload show_vlan_brief_output="""\ -+-----------+-----------------+-----------------+----------------+-----------------------+-------------+ -| VLAN ID | IP Address | Ports | Port Tagging | DHCP Helper Address | Proxy ARP | -+===========+=================+=================+================+=======================+=============+ -| 1000 | 192.168.0.1/21 | Ethernet4 | untagged | 192.0.0.1 | disabled | -| | fc02:1000::1/64 | Ethernet8 | untagged | 192.0.0.2 | | -| | | Ethernet12 | untagged | 192.0.0.3 | | -| | | Ethernet16 | untagged | 192.0.0.4 | | -+-----------+-----------------+-----------------+----------------+-----------------------+-------------+ -| 2000 | 192.168.0.10/21 | Ethernet24 | untagged | 192.0.0.1 | enabled | -| | fc02:1011::1/64 | Ethernet28 | untagged | 192.0.0.2 | | -| | | | | 192.0.0.3 | | -| | | | | 192.0.0.4 | | -+-----------+-----------------+-----------------+----------------+-----------------------+-------------+ -| 3000 | | | | | disabled | -+-----------+-----------------+-----------------+----------------+-----------------------+-------------+ -| 4000 | | PortChannel1001 | tagged | | disabled | -+-----------+-----------------+-----------------+----------------+-----------------------+-------------+ ++-----------+-----------------+-----------------+----------------+-------------+ +| VLAN ID | IP Address | Ports | Port Tagging | Proxy ARP | ++===========+=================+=================+================+=============+ +| 1000 | 192.168.0.1/21 | Ethernet4 | untagged | disabled | +| | fc02:1000::1/64 | Ethernet8 | untagged | | +| | | Ethernet12 | untagged | | +| | | Ethernet16 | untagged | | ++-----------+-----------------+-----------------+----------------+-------------+ +| 2000 | 192.168.0.10/21 | Ethernet24 | untagged | enabled | +| | fc02:1011::1/64 | Ethernet28 | untagged | | ++-----------+-----------------+-----------------+----------------+-------------+ +| 3000 | | | | disabled | ++-----------+-----------------+-----------------+----------------+-------------+ +| 4000 | | PortChannel1001 | tagged | disabled | ++-----------+-----------------+-----------------+----------------+-------------+ """ show_vlan_brief_in_alias_mode_output="""\ -+-----------+-----------------+-----------------+----------------+-----------------------+-------------+ -| VLAN ID | IP Address | Ports | Port Tagging | DHCP Helper Address | Proxy ARP | -+===========+=================+=================+================+=======================+=============+ -| 1000 | 192.168.0.1/21 | etp2 | untagged | 192.0.0.1 | disabled | -| | fc02:1000::1/64 | etp3 | untagged | 192.0.0.2 | | -| | | etp4 | untagged | 192.0.0.3 | | -| | | etp5 | untagged | 192.0.0.4 | | -+-----------+-----------------+-----------------+----------------+-----------------------+-------------+ -| 2000 | 192.168.0.10/21 | etp7 | untagged | 192.0.0.1 | enabled | -| | fc02:1011::1/64 | etp8 | untagged | 192.0.0.2 | | -| | | | | 192.0.0.3 | | -| | | | | 192.0.0.4 | | -+-----------+-----------------+-----------------+----------------+-----------------------+-------------+ -| 3000 | | | | | disabled | -+-----------+-----------------+-----------------+----------------+-----------------------+-------------+ -| 4000 | | PortChannel1001 | tagged | | disabled | -+-----------+-----------------+-----------------+----------------+-----------------------+-------------+ ++-----------+-----------------+-----------------+----------------+-------------+ +| VLAN ID | IP Address | Ports | Port Tagging | Proxy ARP | ++===========+=================+=================+================+=============+ +| 1000 | 192.168.0.1/21 | etp2 | untagged | disabled | +| | fc02:1000::1/64 | etp3 | untagged | | +| | | etp4 | untagged | | +| | | etp5 | untagged | | ++-----------+-----------------+-----------------+----------------+-------------+ +| 2000 | 192.168.0.10/21 | etp7 | untagged | enabled | +| | fc02:1011::1/64 | etp8 | untagged | | ++-----------+-----------------+-----------------+----------------+-------------+ +| 3000 | | | | disabled | ++-----------+-----------------+-----------------+----------------+-------------+ +| 4000 | | PortChannel1001 | tagged | disabled | ++-----------+-----------------+-----------------+----------------+-------------+ """ show_vlan_brief_empty_output="""\ -+-----------+-----------------+-----------------+----------------+-----------------------+-------------+ -| VLAN ID | IP Address | Ports | Port Tagging | DHCP Helper Address | Proxy ARP | -+===========+=================+=================+================+=======================+=============+ -| 2000 | 192.168.0.10/21 | Ethernet24 | untagged | 192.0.0.1 | enabled | -| | fc02:1011::1/64 | Ethernet28 | untagged | 192.0.0.2 | | -| | | | | 192.0.0.3 | | -| | | | | 192.0.0.4 | | -+-----------+-----------------+-----------------+----------------+-----------------------+-------------+ -| 3000 | | | | | disabled | -+-----------+-----------------+-----------------+----------------+-----------------------+-------------+ -| 4000 | | PortChannel1001 | tagged | | disabled | -+-----------+-----------------+-----------------+----------------+-----------------------+-------------+ ++-----------+-----------------+-----------------+----------------+-------------+ +| VLAN ID | IP Address | Ports | Port Tagging | Proxy ARP | ++===========+=================+=================+================+=============+ +| 2000 | 192.168.0.10/21 | Ethernet24 | untagged | enabled | +| | fc02:1011::1/64 | Ethernet28 | untagged | | ++-----------+-----------------+-----------------+----------------+-------------+ +| 3000 | | | | disabled | ++-----------+-----------------+-----------------+----------------+-------------+ +| 4000 | | PortChannel1001 | tagged | disabled | ++-----------+-----------------+-----------------+----------------+-------------+ """ show_vlan_brief_with_portchannel_output="""\ -+-----------+-----------------+-----------------+----------------+-----------------------+-------------+ -| VLAN ID | IP Address | Ports | Port Tagging | DHCP Helper Address | Proxy ARP | -+===========+=================+=================+================+=======================+=============+ -| 1000 | 192.168.0.1/21 | Ethernet4 | untagged | 192.0.0.1 | disabled | -| | fc02:1000::1/64 | Ethernet8 | untagged | 192.0.0.2 | | -| | | Ethernet12 | untagged | 192.0.0.3 | | -| | | Ethernet16 | untagged | 192.0.0.4 | | -| | | PortChannel1001 | untagged | | | -+-----------+-----------------+-----------------+----------------+-----------------------+-------------+ -| 2000 | 192.168.0.10/21 | Ethernet24 | untagged | 192.0.0.1 | enabled | -| | fc02:1011::1/64 | Ethernet28 | untagged | 192.0.0.2 | | -| | | | | 192.0.0.3 | | -| | | | | 192.0.0.4 | | -+-----------+-----------------+-----------------+----------------+-----------------------+-------------+ -| 3000 | | | | | disabled | -+-----------+-----------------+-----------------+----------------+-----------------------+-------------+ -| 4000 | | PortChannel1001 | tagged | | disabled | -+-----------+-----------------+-----------------+----------------+-----------------------+-------------+ ++-----------+-----------------+-----------------+----------------+-------------+ +| VLAN ID | IP Address | Ports | Port Tagging | Proxy ARP | ++===========+=================+=================+================+=============+ +| 1000 | 192.168.0.1/21 | Ethernet4 | untagged | disabled | +| | fc02:1000::1/64 | Ethernet8 | untagged | | +| | | Ethernet12 | untagged | | +| | | Ethernet16 | untagged | | +| | | PortChannel1001 | untagged | | ++-----------+-----------------+-----------------+----------------+-------------+ +| 2000 | 192.168.0.10/21 | Ethernet24 | untagged | enabled | +| | fc02:1011::1/64 | Ethernet28 | untagged | | ++-----------+-----------------+-----------------+----------------+-------------+ +| 3000 | | | | disabled | ++-----------+-----------------+-----------------+----------------+-------------+ +| 4000 | | PortChannel1001 | tagged | disabled | ++-----------+-----------------+-----------------+----------------+-------------+ """ show_vlan_config_output="""\ @@ -111,79 +103,44 @@ Vlan4000 4000 PortChannel1001 tagged """ -config_vlan_add_dhcp_relay_output="""\ -Added DHCP relay destination address 192.0.0.100 to Vlan1000 -Restarting DHCP relay service... -""" - -config_vlan_del_dhcp_relay_output="""\ -Removed DHCP relay destination address 192.0.0.100 from Vlan1000 -Restarting DHCP relay service... -""" - -show_vlan_brief_output_with_new_dhcp_relay_address="""\ -+-----------+-----------------+-----------------+----------------+-----------------------+-------------+ -| VLAN ID | IP Address | Ports | Port Tagging | DHCP Helper Address | Proxy ARP | -+===========+=================+=================+================+=======================+=============+ -| 1000 | 192.168.0.1/21 | Ethernet4 | untagged | 192.0.0.1 | disabled | -| | fc02:1000::1/64 | Ethernet8 | untagged | 192.0.0.2 | | -| | | Ethernet12 | untagged | 192.0.0.3 | | -| | | Ethernet16 | untagged | 192.0.0.4 | | -| | | | | 192.0.0.100 | | -+-----------+-----------------+-----------------+----------------+-----------------------+-------------+ -| 2000 | 192.168.0.10/21 | Ethernet24 | untagged | 192.0.0.1 | enabled | -| | fc02:1011::1/64 | Ethernet28 | untagged | 192.0.0.2 | | -| | | | | 192.0.0.3 | | -| | | | | 192.0.0.4 | | -+-----------+-----------------+-----------------+----------------+-----------------------+-------------+ -| 3000 | | | | | disabled | -+-----------+-----------------+-----------------+----------------+-----------------------+-------------+ -| 4000 | | PortChannel1001 | tagged | | disabled | -+-----------+-----------------+-----------------+----------------+-----------------------+-------------+ -""" - config_add_del_vlan_and_vlan_member_output="""\ -+-----------+-----------------+-----------------+----------------+-----------------------+-------------+ -| VLAN ID | IP Address | Ports | Port Tagging | DHCP Helper Address | Proxy ARP | -+===========+=================+=================+================+=======================+=============+ -| 1000 | 192.168.0.1/21 | Ethernet4 | untagged | 192.0.0.1 | disabled | -| | fc02:1000::1/64 | Ethernet8 | untagged | 192.0.0.2 | | -| | | Ethernet12 | untagged | 192.0.0.3 | | -| | | Ethernet16 | untagged | 192.0.0.4 | | -+-----------+-----------------+-----------------+----------------+-----------------------+-------------+ -| 1001 | | Ethernet20 | untagged | | disabled | -+-----------+-----------------+-----------------+----------------+-----------------------+-------------+ -| 2000 | 192.168.0.10/21 | Ethernet24 | untagged | 192.0.0.1 | enabled | -| | fc02:1011::1/64 | Ethernet28 | untagged | 192.0.0.2 | | -| | | | | 192.0.0.3 | | -| | | | | 192.0.0.4 | | -+-----------+-----------------+-----------------+----------------+-----------------------+-------------+ -| 3000 | | | | | disabled | -+-----------+-----------------+-----------------+----------------+-----------------------+-------------+ -| 4000 | | PortChannel1001 | tagged | | disabled | -+-----------+-----------------+-----------------+----------------+-----------------------+-------------+ ++-----------+-----------------+-----------------+----------------+-------------+ +| VLAN ID | IP Address | Ports | Port Tagging | Proxy ARP | ++===========+=================+=================+================+=============+ +| 1000 | 192.168.0.1/21 | Ethernet4 | untagged | disabled | +| | fc02:1000::1/64 | Ethernet8 | untagged | | +| | | Ethernet12 | untagged | | +| | | Ethernet16 | untagged | | ++-----------+-----------------+-----------------+----------------+-------------+ +| 1001 | | Ethernet20 | untagged | disabled | ++-----------+-----------------+-----------------+----------------+-------------+ +| 2000 | 192.168.0.10/21 | Ethernet24 | untagged | enabled | +| | fc02:1011::1/64 | Ethernet28 | untagged | | ++-----------+-----------------+-----------------+----------------+-------------+ +| 3000 | | | | disabled | ++-----------+-----------------+-----------------+----------------+-------------+ +| 4000 | | PortChannel1001 | tagged | disabled | ++-----------+-----------------+-----------------+----------------+-------------+ """ config_add_del_vlan_and_vlan_member_in_alias_mode_output="""\ -+-----------+-----------------+-----------------+----------------+-----------------------+-------------+ -| VLAN ID | IP Address | Ports | Port Tagging | DHCP Helper Address | Proxy ARP | -+===========+=================+=================+================+=======================+=============+ -| 1000 | 192.168.0.1/21 | etp2 | untagged | 192.0.0.1 | disabled | -| | fc02:1000::1/64 | etp3 | untagged | 192.0.0.2 | | -| | | etp4 | untagged | 192.0.0.3 | | -| | | etp5 | untagged | 192.0.0.4 | | -+-----------+-----------------+-----------------+----------------+-----------------------+-------------+ -| 1001 | | etp6 | untagged | | disabled | -+-----------+-----------------+-----------------+----------------+-----------------------+-------------+ -| 2000 | 192.168.0.10/21 | etp7 | untagged | 192.0.0.1 | enabled | -| | fc02:1011::1/64 | etp8 | untagged | 192.0.0.2 | | -| | | | | 192.0.0.3 | | -| | | | | 192.0.0.4 | | -+-----------+-----------------+-----------------+----------------+-----------------------+-------------+ -| 3000 | | | | | disabled | -+-----------+-----------------+-----------------+----------------+-----------------------+-------------+ -| 4000 | | PortChannel1001 | tagged | | disabled | -+-----------+-----------------+-----------------+----------------+-----------------------+-------------+ ++-----------+-----------------+-----------------+----------------+-------------+ +| VLAN ID | IP Address | Ports | Port Tagging | Proxy ARP | ++===========+=================+=================+================+=============+ +| 1000 | 192.168.0.1/21 | etp2 | untagged | disabled | +| | fc02:1000::1/64 | etp3 | untagged | | +| | | etp4 | untagged | | +| | | etp5 | untagged | | ++-----------+-----------------+-----------------+----------------+-------------+ +| 1001 | | etp6 | untagged | disabled | ++-----------+-----------------+-----------------+----------------+-------------+ +| 2000 | 192.168.0.10/21 | etp7 | untagged | enabled | +| | fc02:1011::1/64 | etp8 | untagged | | ++-----------+-----------------+-----------------+----------------+-------------+ +| 3000 | | | | disabled | ++-----------+-----------------+-----------------+----------------+-------------+ +| 4000 | | PortChannel1001 | tagged | disabled | ++-----------+-----------------+-----------------+----------------+-------------+ """ class TestVlan(object): @classmethod @@ -503,118 +460,6 @@ def test_config_add_del_vlan_and_vlan_member_in_alias_mode(self): os.environ['SONIC_CLI_IFACE_MODE'] = "default" - def test_config_vlan_add_dhcp_relay_with_nonexist_vlanid(self): - runner = CliRunner() - - with mock.patch('utilities_common.cli.run_command') as mock_run_command: - result = runner.invoke(config.config.commands["vlan"].commands["dhcp_relay"].commands["add"], - ["1001", "192.0.0.100"]) - print(result.exit_code) - print(result.output) - # traceback.print_tb(result.exc_info[2]) - assert result.exit_code != 0 - assert "Error: Vlan1001 doesn't exist" in result.output - assert mock_run_command.call_count == 0 - - def test_config_vlan_add_dhcp_relay_with_invalid_vlanid(self): - runner = CliRunner() - - with mock.patch('utilities_common.cli.run_command') as mock_run_command: - result = runner.invoke(config.config.commands["vlan"].commands["dhcp_relay"].commands["add"], - ["4096", "192.0.0.100"]) - print(result.exit_code) - print(result.output) - # traceback.print_tb(result.exc_info[2]) - assert result.exit_code != 0 - assert "Error: Vlan4096 doesn't exist" in result.output - assert mock_run_command.call_count == 0 - - def test_config_vlan_add_dhcp_relay_with_invalid_ip(self): - runner = CliRunner() - - with mock.patch('utilities_common.cli.run_command') as mock_run_command: - result = runner.invoke(config.config.commands["vlan"].commands["dhcp_relay"].commands["add"], - ["1000", "192.0.0.1000"]) - print(result.exit_code) - print(result.output) - # traceback.print_tb(result.exc_info[2]) - assert result.exit_code != 0 - assert "Error: 192.0.0.1000 is invalid IP address" in result.output - assert mock_run_command.call_count == 0 - - def test_config_vlan_add_dhcp_relay_with_exist_ip(self): - runner = CliRunner() - - with mock.patch('utilities_common.cli.run_command') as mock_run_command: - result = runner.invoke(config.config.commands["vlan"].commands["dhcp_relay"].commands["add"], - ["1000", "192.0.0.1"]) - print(result.exit_code) - print(result.output) - # traceback.print_tb(result.exc_info[2]) - assert result.exit_code == 0 - assert "192.0.0.1 is already a DHCP relay destination for Vlan1000" in result.output - assert mock_run_command.call_count == 0 - - def test_config_vlan_add_del_dhcp_relay_dest(self): - runner = CliRunner() - db = Db() - - # add new relay dest - with mock.patch("utilities_common.cli.run_command") as mock_run_command: - result = runner.invoke(config.config.commands["vlan"].commands["dhcp_relay"].commands["add"], - ["1000", "192.0.0.100"], obj=db) - print(result.exit_code) - print(result.output) - assert result.exit_code == 0 - assert result.output == config_vlan_add_dhcp_relay_output - assert mock_run_command.call_count == 3 - - # show output - result = runner.invoke(show.cli.commands["vlan"].commands["brief"], [], obj=db) - print(result.output) - assert result.output == show_vlan_brief_output_with_new_dhcp_relay_address - - # del relay dest - with mock.patch("utilities_common.cli.run_command") as mock_run_command: - result = runner.invoke(config.config.commands["vlan"].commands["dhcp_relay"].commands["del"], - ["1000", "192.0.0.100"], obj=db) - print(result.exit_code) - print(result.output) - assert result.exit_code == 0 - assert result.output == config_vlan_del_dhcp_relay_output - assert mock_run_command.call_count == 3 - - # show output - result = runner.invoke(show.cli.commands["vlan"].commands["brief"], [], obj=db) - print(result.output) - assert result.output == show_vlan_brief_output - - def test_config_vlan_remove_nonexist_dhcp_relay_dest(self): - runner = CliRunner() - - with mock.patch('utilities_common.cli.run_command') as mock_run_command: - result = runner.invoke(config.config.commands["vlan"].commands["dhcp_relay"].commands["del"], - ["1000", "192.0.0.100"]) - print(result.exit_code) - print(result.output) - # traceback.print_tb(result.exc_info[2]) - assert result.exit_code != 0 - assert "Error: 192.0.0.100 is not a DHCP relay destination for Vlan1000" in result.output - assert mock_run_command.call_count == 0 - - def test_config_vlan_remove_dhcp_relay_dest_with_nonexist_vlanid(self): - runner = CliRunner() - - with mock.patch('utilities_common.cli.run_command') as mock_run_command: - result = runner.invoke(config.config.commands["vlan"].commands["dhcp_relay"].commands["del"], - ["1001", "192.0.0.1"]) - print(result.exit_code) - print(result.output) - # traceback.print_tb(result.exc_info[2]) - assert result.exit_code != 0 - assert "Error: Vlan1001 doesn't exist" in result.output - assert mock_run_command.call_count == 0 - def test_config_vlan_proxy_arp_with_nonexist_vlan_intf_table(self): modes = ["enabled", "disabled"] runner = CliRunner()