diff --git a/config/vlan.py b/config/vlan.py index 7587e024a4..e0b7474aec 100644 --- a/config/vlan.py +++ b/config/vlan.py @@ -1,5 +1,6 @@ import click import utilities_common.cli as clicommon +import utilities_common.dhcp_relay_util as dhcp_relay_util from jsonpatch import JsonPatchConflict from time import sleep @@ -16,6 +17,11 @@ def vlan(): """VLAN-related configuration tasks""" pass + +def set_dhcp_relay_table(table, config_db, vlan_name, value): + config_db.set_entry(table, vlan_name, value) + + @vlan.command('add') @click.argument('vid', metavar='', required=True, type=int) @clicommon.pass_db @@ -24,7 +30,7 @@ def add_vlan(db, vid): ctx = click.get_current_context() vlan = 'Vlan{}'.format(vid) - + config_db = ValidatedConfigDBConnector(db.cfgdb) if ADHOC_VALIDATION: if not clicommon.is_vlanid_in_range(vid): @@ -32,14 +38,15 @@ def add_vlan(db, vid): if vid == 1: ctx.fail("{} is default VLAN".format(vlan)) # TODO: MISSING CONSTRAINT IN YANG MODEL - + if clicommon.check_if_vlanid_exist(db.cfgdb, vlan): # TODO: MISSING CONSTRAINT IN YANG MODEL ctx.fail("{} already exists".format(vlan)) - - try: - config_db.set_entry('VLAN', vlan, {'vlanid': str(vid)}) - except ValueError: - ctx.fail("Invalid VLAN ID {} (1-4094)".format(vid)) + # set dhcpv4_relay table + set_dhcp_relay_table('VLAN', config_db, vlan, {'vlanid': str(vid)}) + + # set dhcpv6_relay table + set_dhcp_relay_table('DHCP_RELAY', config_db, vlan, {'vlanid': str(vid)}) + @vlan.command('del') @click.argument('vid', metavar='', required=True, type=int) @@ -67,19 +74,23 @@ def del_vlan(db, vid): ctx.fail("{} can not be removed. First remove IP addresses assigned to this VLAN".format(vlan)) keys = [ (k, v) for k, v in db.cfgdb.get_table('VLAN_MEMBER') if k == 'Vlan{}'.format(vid) ] - + if keys: # TODO: MISSING CONSTRAINT IN YANG MODEL ctx.fail("VLAN ID {} can not be removed. First remove all members assigned to this VLAN.".format(vid)) - + vxlan_table = db.cfgdb.get_table('VXLAN_TUNNEL_MAP') for vxmap_key, vxmap_data in vxlan_table.items(): if vxmap_data['vlan'] == 'Vlan{}'.format(vid): ctx.fail("vlan: {} can not be removed. First remove vxlan mapping '{}' assigned to VLAN".format(vid, '|'.join(vxmap_key)) ) - - try: - config_db.set_entry('VLAN', 'Vlan{}'.format(vid), None) - except JsonPatchConflict: - ctx.fail("{} does not exist".format(vlan)) + + # set dhcpv4_relay table + set_dhcp_relay_table('VLAN', config_db, vlan, None) + + # set dhcpv6_relay table + set_dhcp_relay_table('DHCP_RELAY', config_db, vlan, None) + # We need to restart dhcp_relay service after dhcpv6_relay config change + dhcp_relay_util.handle_restart_dhcp_relay_service() + def restart_ndppd(): verify_swss_running_cmd = "docker container inspect -f '{{.State.Status}}' swss" diff --git a/tests/vlan_test.py b/tests/vlan_test.py deleted file mode 100644 index 66ec3606cf..0000000000 --- a/tests/vlan_test.py +++ /dev/null @@ -1,591 +0,0 @@ -import os -import traceback -from unittest import mock - -from click.testing import CliRunner - -import config.main as config -import show.main as show -from utilities_common.db import Db -from importlib import reload -import utilities_common.bgp_util as bgp_util - -show_vlan_brief_output="""\ -+-----------+-----------------+-----------------+----------------+-------------+ -| 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 | 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 | 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 | 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="""\ -Name VID Member Mode --------- ----- --------------- -------- -Vlan1000 1000 Ethernet4 untagged -Vlan1000 1000 Ethernet8 untagged -Vlan1000 1000 Ethernet12 untagged -Vlan1000 1000 Ethernet16 untagged -Vlan2000 2000 Ethernet24 untagged -Vlan2000 2000 Ethernet28 untagged -Vlan3000 3000 -Vlan4000 4000 PortChannel1001 tagged -""" - -show_vlan_config_in_alias_mode_output="""\ -Name VID Member Mode --------- ----- --------------- -------- -Vlan1000 1000 etp2 untagged -Vlan1000 1000 etp3 untagged -Vlan1000 1000 etp4 untagged -Vlan1000 1000 etp5 untagged -Vlan2000 2000 etp7 untagged -Vlan2000 2000 etp8 untagged -Vlan3000 3000 -Vlan4000 4000 PortChannel1001 tagged -""" - -config_add_del_vlan_and_vlan_member_output="""\ -+-----------+-----------------+-----------------+----------------+-------------+ -| 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 | 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): - _old_run_bgp_command = None - @classmethod - def setup_class(cls): - os.environ['UTILITIES_UNIT_TESTING'] = "1" - # ensure that we are working with single asic config - cls._old_run_bgp_command = bgp_util.run_bgp_command - bgp_util.run_bgp_command = mock.MagicMock( - return_value=cls.mock_run_bgp_command()) - from .mock_tables import dbconnector - from .mock_tables import mock_single_asic - reload(mock_single_asic) - dbconnector.load_namespace_config() - print("SETUP") - - def mock_run_bgp_command(): - return "" - - def test_show_vlan(self): - runner = CliRunner() - result = runner.invoke(show.cli.commands["vlan"], []) - print(result.exit_code) - print(result.output) - assert result.exit_code == 0 - - def test_show_vlan_brief(self): - runner = CliRunner() - result = runner.invoke(show.cli.commands["vlan"].commands["brief"], []) - print(result.exit_code) - print(result.output) - assert result.exit_code == 0 - assert result.output == show_vlan_brief_output - - def test_show_vlan_brief_verbose(self): - runner = CliRunner() - result = runner.invoke(show.cli.commands["vlan"].commands["brief"], ["--verbose"]) - print(result.exit_code) - print(result.output) - assert result.exit_code == 0 - assert result.output == show_vlan_brief_output - - def test_show_vlan_brief_in_alias_mode(self): - runner = CliRunner() - os.environ['SONIC_CLI_IFACE_MODE'] = "alias" - result = runner.invoke(show.cli.commands["vlan"].commands["brief"]) - os.environ['SONIC_CLI_IFACE_MODE'] = "default" - print(result.exit_code) - print(result.output) - assert result.exit_code == 0 - assert result.output == show_vlan_brief_in_alias_mode_output - - def test_show_vlan_brief_explicit_proxy_arp_disable(self): - runner = CliRunner() - db = Db() - - db.cfgdb.set_entry("VLAN_INTERFACE", "Vlan1000", {"proxy_arp": "disabled"}) - - def test_show_vlan_config(self): - runner = CliRunner() - result = runner.invoke(show.cli.commands["vlan"].commands["config"], []) - print(result.exit_code) - print(result.output) - assert result.exit_code == 0 - assert result.output == show_vlan_config_output - - def test_show_vlan_config_in_alias_mode(self): - runner = CliRunner() - os.environ['SONIC_CLI_IFACE_MODE'] = "alias" - result = runner.invoke(show.cli.commands["vlan"].commands["config"], []) - os.environ['SONIC_CLI_IFACE_MODE'] = "default" - print(result.exit_code) - print(result.output) - assert result.exit_code == 0 - assert result.output == show_vlan_config_in_alias_mode_output - - def test_config_vlan_add_vlan_with_invalid_vlanid(self): - runner = CliRunner() - result = runner.invoke(config.config.commands["vlan"].commands["add"], ["4096"]) - print(result.exit_code) - print(result.output) - assert result.exit_code != 0 - assert "Error: Invalid VLAN ID 4096 (1-4094)" in result.output - - def test_config_vlan_add_vlan_with_exist_vlanid(self): - runner = CliRunner() - result = runner.invoke(config.config.commands["vlan"].commands["add"], ["1000"]) - print(result.exit_code) - print(result.output) - assert result.exit_code != 0 - assert "Error: Vlan1000 already exists" in result.output - - def test_config_vlan_del_vlan_with_invalid_vlanid(self): - runner = CliRunner() - result = runner.invoke(config.config.commands["vlan"].commands["del"], ["4096"]) - print(result.exit_code) - print(result.output) - assert result.exit_code != 0 - assert "Error: Invalid VLAN ID 4096 (1-4094)" in result.output - - def test_config_vlan_del_vlan_with_nonexist_vlanid(self): - runner = CliRunner() - result = runner.invoke(config.config.commands["vlan"].commands["del"], ["1001"]) - print(result.exit_code) - print(result.output) - assert result.exit_code != 0 - assert "Error: Vlan1001 does not exist" in result.output - - def test_config_vlan_add_member_with_invalid_vlanid(self): - runner = CliRunner() - result = runner.invoke(config.config.commands["vlan"].commands["member"].commands["add"], ["4096", "Ethernet4"]) - print(result.exit_code) - print(result.output) - assert result.exit_code != 0 - assert "Error: Invalid VLAN ID 4096 (1-4094)" in result.output - - def test_config_vlan_add_member_with_nonexist_vlanid(self): - runner = CliRunner() - result = runner.invoke(config.config.commands["vlan"].commands["member"].commands["add"], ["1001", "Ethernet4"]) - print(result.exit_code) - print(result.output) - assert result.exit_code != 0 - assert "Error: Vlan1001 does not exist" in result.output - - def test_config_vlan_add_exist_port_member(self): - runner = CliRunner() - result = runner.invoke(config.config.commands["vlan"].commands["member"].commands["add"], ["1000", "Ethernet4"]) - print(result.exit_code) - print(result.output) - assert result.exit_code != 0 - assert "Error: Ethernet4 is already a member of Vlan1000" in result.output - - def test_config_vlan_add_nonexist_port_member(self): - runner = CliRunner() - result = runner.invoke(config.config.commands["vlan"].commands["member"].commands["add"], ["1000", "Ethernet3"]) - print(result.exit_code) - print(result.output) - assert result.exit_code != 0 - assert "Error: Ethernet3 does not exist" in result.output - - def test_config_vlan_add_nonexist_portchannel_member(self): - runner = CliRunner() - result = runner.invoke(config.config.commands["vlan"].commands["member"].commands["add"], \ - ["1000", "PortChannel1011"]) - print(result.exit_code) - print(result.output) - assert result.exit_code != 0 - assert "Error: PortChannel1011 does not exist" in result.output - - def test_config_vlan_add_portchannel_member(self): - runner = CliRunner() - db = Db() - - result = runner.invoke(config.config.commands["vlan"].commands["member"].commands["add"], \ - ["1000", "PortChannel1001", "--untagged"], obj=db) - print(result.exit_code) - print(result.output) - assert result.exit_code == 0 - - # show output - result = runner.invoke(show.cli.commands["vlan"].commands["brief"], [], obj=db) - print(result.exit_code) - print(result.output) - assert result.exit_code == 0 - assert result.output == show_vlan_brief_with_portchannel_output - - def test_config_vlan_add_rif_portchannel_member(self): - runner = CliRunner() - db = Db() - - result = runner.invoke(config.config.commands["vlan"].commands["member"].commands["add"], \ - ["1000", "PortChannel0001", "--untagged"], obj=db) - print(result.exit_code) - print(result.output) - assert result.exit_code != 0 - assert "Error: PortChannel0001 is a router interface!" in result.output - - def test_config_vlan_with_vxlanmap_del_vlan(self): - runner = CliRunner() - db = Db() - obj = {'config_db': db.cfgdb} - - # create vlan - result = runner.invoke(config.config.commands["vlan"].commands["add"], ["1027"], obj=db) - print(result.exit_code) - print(result.output) - assert result.exit_code == 0 - - # create vxlan map - result = runner.invoke(config.config.commands["vxlan"].commands["map"].commands["add"], ["vtep1", "1027", "11027"], obj=db) - print(result.exit_code) - print(result.output) - assert result.exit_code == 0 - - # attempt to del vlan with vxlan map, should fail - result = runner.invoke(config.config.commands["vlan"].commands["del"], ["1027"], obj=db) - print(result.exit_code) - print(result.output) - assert result.exit_code != 0 - assert "Error: vlan: 1027 can not be removed. First remove vxlan mapping" in result.output - - def test_config_vlan_del_vlan(self): - runner = CliRunner() - db = Db() - obj = {'config_db':db.cfgdb} - - # del vlan with IP - result = runner.invoke(config.config.commands["vlan"].commands["del"], ["1000"], obj=db) - print(result.exit_code) - print(result.output) - assert result.exit_code != 0 - assert "Error: Vlan1000 can not be removed. First remove IP addresses assigned to this VLAN" in result.output - - # remove vlan IP`s - result = runner.invoke(config.config.commands["interface"].commands["ip"].commands["remove"], ["Vlan1000", "192.168.0.1/21"], obj=obj) - print(result.exit_code, result.output) - assert result.exit_code != 0 - - result = runner.invoke(config.config.commands["interface"].commands["ip"].commands["remove"], ["Vlan1000", "fc02:1000::1/64"], obj=obj) - print(result.exit_code, result.output) - assert result.exit_code != 0 - - # del vlan with IP - result = runner.invoke(config.config.commands["vlan"].commands["del"], ["1000"], obj=db) - print(result.exit_code) - print(result.output) - assert result.exit_code != 0 - assert "Error: VLAN ID 1000 can not be removed. First remove all members assigned to this VLAN." in result.output - - vlan_member = db.cfgdb.get_table('VLAN_MEMBER') - keys = [ (k, v) for k, v in vlan_member if k == 'Vlan{}'.format(1000) ] - for k,v in keys: - result = runner.invoke(config.config.commands["vlan"].commands["member"].commands["del"], ["1000", v], obj=db) - print(result.exit_code) - print(result.output) - assert result.exit_code == 0 - - result = runner.invoke(config.config.commands["vlan"].commands["del"], ["1000"], obj=db) - print(result.exit_code) - print(result.output) - assert result.exit_code == 0 - - # show output - result = runner.invoke(show.cli.commands["vlan"].commands["brief"], [], obj=db) - print(result.exit_code) - print(result.output) - assert result.exit_code == 0 - assert result.output == show_vlan_brief_empty_output - - def test_config_vlan_del_nonexist_vlan_member(self): - runner = CliRunner() - - result = runner.invoke(config.config.commands["vlan"].commands["member"].commands["del"], \ - ["1000", "Ethernet0"]) - print(result.exit_code) - print(result.output) - assert result.exit_code != 0 - assert "Error: Ethernet0 is not a member of Vlan1000" in result.output - - def test_config_add_del_vlan_and_vlan_member(self): - runner = CliRunner() - db = Db() - - # add vlan 1001 - result = runner.invoke(config.config.commands["vlan"].commands["add"], ["1001"], obj=db) - print(result.exit_code) - print(result.output) - assert result.exit_code == 0 - - # add Ethernet20 to vlan 1001 - result = runner.invoke(config.config.commands["vlan"].commands["member"].commands["add"], - ["1001", "Ethernet20", "--untagged"], obj=db) - print(result.exit_code) - print(result.output) - traceback.print_tb(result.exc_info[2]) - assert result.exit_code == 0 - - # show output - result = runner.invoke(show.cli.commands["vlan"].commands["brief"], [], obj=db) - print(result.output) - assert result.output == config_add_del_vlan_and_vlan_member_output - - # remove vlan member - result = runner.invoke(config.config.commands["vlan"].commands["member"].commands["del"], - ["1001", "Ethernet20"], obj=db) - print(result.exit_code) - print(result.output) - assert result.exit_code == 0 - - # add del 1001 - result = runner.invoke(config.config.commands["vlan"].commands["del"], ["1001"], obj=db) - print(result.exit_code) - print(result.output) - assert result.exit_code == 0 - - # show output - result = runner.invoke(show.cli.commands["vlan"].commands["brief"], [], obj=db) - print(result.exit_code) - print(result.output) - assert result.exit_code == 0 - assert result.output == show_vlan_brief_output - - def test_config_add_del_vlan_and_vlan_member_in_alias_mode(self): - runner = CliRunner() - db = Db() - - os.environ['SONIC_CLI_IFACE_MODE'] = "alias" - - # add vlan 1001 - result = runner.invoke(config.config.commands["vlan"].commands["add"], ["1001"], obj=db) - print(result.exit_code) - print(result.output) - assert result.exit_code == 0 - - # add etp6 to vlan 1001 - result = runner.invoke(config.config.commands["vlan"].commands["member"].commands["add"], - ["1001", "etp6", "--untagged"], obj=db) - print(result.exit_code) - print(result.output) - traceback.print_tb(result.exc_info[2]) - assert result.exit_code == 0 - - # show output - result = runner.invoke(show.cli.commands["vlan"].commands["brief"], [], obj=db) - print(result.exit_code) - print(result.output) - assert result.output == config_add_del_vlan_and_vlan_member_in_alias_mode_output - - # remove vlan member - result = runner.invoke(config.config.commands["vlan"].commands["member"].commands["del"], - ["1001", "etp6"], obj=db) - print(result.exit_code) - print(result.output) - assert result.exit_code == 0 - - # add del 1001 - result = runner.invoke(config.config.commands["vlan"].commands["del"], ["1001"], obj=db) - print(result.exit_code) - print(result.output) - assert result.exit_code == 0 - - # show output - result = runner.invoke(show.cli.commands["vlan"].commands["brief"], [], obj=db) - print(result.exit_code) - print(result.output) - assert result.exit_code == 0 - assert result.output == show_vlan_brief_in_alias_mode_output - - os.environ['SONIC_CLI_IFACE_MODE'] = "default" - - def test_config_vlan_proxy_arp_with_nonexist_vlan_intf_table(self): - modes = ["enabled", "disabled"] - runner = CliRunner() - db = Db() - db.cfgdb.delete_table("VLAN_INTERFACE") - - for mode in modes: - result = runner.invoke(config.config.commands["vlan"].commands["proxy_arp"], ["1000", mode], obj=db) - - print(result.exit_code) - print(result.output) - - assert result.exit_code != 0 - assert "Interface Vlan1000 does not exist" in result.output - - def test_config_vlan_proxy_arp_with_nonexist_vlan_intf(self): - modes = ["enabled", "disabled"] - runner = CliRunner() - db = Db() - - for mode in modes: - result = runner.invoke(config.config.commands["vlan"].commands["proxy_arp"], ["1001", mode], obj=db) - - print(result.exit_code) - print(result.output) - - assert result.exit_code != 0 - assert "Interface Vlan1001 does not exist" in result.output - - def test_config_vlan_proxy_arp_enable(self): - runner = CliRunner() - db = Db() - - result = runner.invoke(config.config.commands["vlan"].commands["proxy_arp"], ["1000", "enabled"], obj=db) - - print(result.exit_code) - print(result.output) - - assert result.exit_code == 0 - assert db.cfgdb.get_entry("VLAN_INTERFACE", "Vlan1000") == {"proxy_arp": "enabled"} - - def test_config_vlan_proxy_arp_disable(self): - runner = CliRunner() - db = Db() - - result = runner.invoke(config.config.commands["vlan"].commands["proxy_arp"], ["2000", "disabled"], obj=db) - - print(result.exit_code) - print(result.output) - - assert result.exit_code == 0 - assert db.cfgdb.get_entry("VLAN_INTERFACE", "Vlan2000") == {"proxy_arp": "disabled"} - - def test_config_2_untagged_vlan_on_same_interface(self): - runner = CliRunner() - db = Db() - - # add Ethernet4 to vlan 2000 as untagged - should fail as ethrnet4 is already untagged member in 1000 - result = runner.invoke(config.config.commands["vlan"].commands["member"].commands["add"], - ["2000", "Ethernet4", "--untagged"], obj=db) - print(result.exit_code) - assert result.exit_code != 0 - - # add Ethernet4 to vlan 2000 as tagged - should succeed - result = runner.invoke(config.config.commands["vlan"].commands["member"].commands["add"], - ["2000", "Ethernet4" ], obj=db) - print(result.exit_code) - assert result.exit_code == 0 - - def test_config_set_router_port_on_member_interface(self): - db = Db() - runner = CliRunner() - obj = {'config_db':db.cfgdb} - - # intf enable - result = runner.invoke(config.config.commands["interface"].commands["ip"].commands["add"], - ["Ethernet4", "10.10.10.1/24"], obj=obj) - print(result.exit_code, result.output) - assert result.exit_code == 0 - assert 'Interface Ethernet4 is a member of vlan' in result.output - - def test_config_vlan_add_member_of_portchannel(self): - runner = CliRunner() - db = Db() - - result = runner.invoke(config.config.commands["vlan"].commands["member"].commands["add"], \ - ["1000", "Ethernet32", "--untagged"], obj=db) - print(result.exit_code) - print(result.output) - assert result.exit_code != 0 - assert "Error: Ethernet32 is part of portchannel!" in result.output - - @classmethod - def teardown_class(cls): - os.environ['UTILITIES_UNIT_TESTING'] = "0" - bgp_util.run_bgp_command = cls._old_run_bgp_command - print("TEARDOWN") diff --git a/utilities_common/dhcp_relay_util.py b/utilities_common/dhcp_relay_util.py new file mode 100644 index 0000000000..b9c0b4e20f --- /dev/null +++ b/utilities_common/dhcp_relay_util.py @@ -0,0 +1,20 @@ +import click +import utilities_common.cli as clicommon + + +def restart_dhcp_relay_service(): + """ + Restart dhcp_relay service + """ + 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) + + +def handle_restart_dhcp_relay_service(): + try: + restart_dhcp_relay_service() + except SystemExit as e: + ctx = click.get_current_context() + ctx.fail("Restart service dhcp_relay failed with error {}".format(e))