From d984ea2478bd9627823be807d61f76dc8567748d Mon Sep 17 00:00:00 2001 From: link_chiang Date: Thu, 26 Sep 2024 15:05:17 +0800 Subject: [PATCH] Fix enable ipv6-link-local-only fail on VLAN interface without IP The ipv6-link-local-only function works even if the VLAN interface without IP. Change the condition to be check VLAN exist and has VLAN member joined instead of VLAN interface with IP to enable ipv6-link-local-only on VLAN. --- config/main.py | 16 +++++++++--- tests/ipv6_link_local_test.py | 48 ++++++++++++++++++++++++++++++++++- utilities_common/cli.py | 13 +++++++++- 3 files changed, 71 insertions(+), 6 deletions(-) diff --git a/config/main.py b/config/main.py index f4ea93e53f..605b388710 100644 --- a/config/main.py +++ b/config/main.py @@ -5829,8 +5829,12 @@ def enable_use_link_local_only(ctx, interface_name): ctx.fail("Interface name %s is invalid. Please enter a valid interface name!!" %(interface_name)) if (interface_type == "VLAN_INTERFACE"): - if not clicommon.is_valid_vlan_interface(db, interface_name): - ctx.fail("Interface name %s is invalid. Please enter a valid interface name!!" %(interface_name)) + if not clicommon.check_if_vlanid_exist(db, interface_name): + ctx.fail("{} is nonexistent. Please create vlan first!!" + .format(interface_name)) + if not clicommon.has_vlan_member(db, interface_name): + ctx.fail("{} has no member joined. Please make sure at least one vlan member joined the vlan!!" + .format(interface_name)) portchannel_member_table = db.get_table('PORTCHANNEL_MEMBER') @@ -5882,8 +5886,12 @@ def disable_use_link_local_only(ctx, interface_name): ctx.fail("Interface name %s is invalid. Please enter a valid interface name!!" %(interface_name)) if (interface_type == "VLAN_INTERFACE"): - if not clicommon.is_valid_vlan_interface(db, interface_name): - ctx.fail("Interface name %s is invalid. Please enter a valid interface name!!" %(interface_name)) + if not clicommon.check_if_vlanid_exist(db, interface_name): + ctx.fail("{} is nonexistent. Please create vlan first!!" + .format(interface_name)) + if not clicommon.has_vlan_member(db, interface_name): + ctx.fail("{} has no member joined. Please make sure at least one vlan member joined the vlan!!" + .format(interface_name)) portchannel_member_table = db.get_table('PORTCHANNEL_MEMBER') diff --git a/tests/ipv6_link_local_test.py b/tests/ipv6_link_local_test.py index 50b691be6b..76ed67f73a 100644 --- a/tests/ipv6_link_local_test.py +++ b/tests/ipv6_link_local_test.py @@ -190,7 +190,7 @@ def test_config_enable_disable_ipv6_link_local_on_interface_which_is_member_of_p runner = CliRunner() db = Db() obj = {'db':db.cfgdb} - + # Enable ipv6 link local on Ethernet32 result = runner.invoke(config.config.commands["interface"].commands["ipv6"].commands["enable"].commands["use-link-local-only"], ["Ethernet32"], obj=obj) print(result.exit_code) @@ -234,6 +234,52 @@ def test_vlan_member_add_on_link_local_interface(self): assert result.exit_code != 0 assert 'Error: Ethernet40 is a router interface!' in result.output + def test_config_enable_disable_ipv6_link_local_on_nonexistent_vlan(self): + runner = CliRunner() + db = Db() + obj = {'db': db.cfgdb} + + # Enable ipv6 link local on nonexistent Vlan10 + result = runner.invoke( + config.config.commands["interface"].commands["ipv6"].commands["enable"].commands["use-link-local-only"], + ["Vlan10"], obj=obj) + print(result.exit_code) + print(result.output) + assert result.exit_code != 0 + assert 'Error: Vlan10 is nonexistent. Please create vlan first!!' in result.output + + # Disable ipv6 link local on nonexistent Vlan10 + result = runner.invoke( + config.config.commands["interface"].commands["ipv6"].commands["disable"].commands["use-link-local-only"], + ["Vlan10"], obj=obj) + print(result.exit_code) + print(result.output) + assert result.exit_code != 0 + assert 'Error: Vlan10 is nonexistent. Please create vlan first!!' in result.output + + def test_config_enable_disable_ipv6_link_local_on_vlan_no_member_joined(self): + runner = CliRunner() + db = Db() + obj = {'db': db.cfgdb} + + # Enable ipv6 link local on Vlan3000 no member joined + result = runner.invoke( + config.config.commands["interface"].commands["ipv6"].commands["enable"].commands["use-link-local-only"], + ["Vlan3000"], obj=obj) + print(result.exit_code) + print(result.output) + assert result.exit_code != 0 + assert 'Error: Vlan3000 has no member joined. Please make sure at least one vlan member joined the vlan!!' in result.output + + # Disable ipv6 link local on Vlan3000 no member joined + result = runner.invoke( + config.config.commands["interface"].commands["ipv6"].commands["disable"].commands["use-link-local-only"], + ["Vlan3000"], obj=obj) + print(result.exit_code) + print(result.output) + assert result.exit_code != 0 + assert 'Error: Vlan3000 has no member joined. Please make sure at least one vlan member joined the vlan!!' in result.output + @classmethod def teardown_class(cls): os.environ['UTILITIES_UNIT_TESTING'] = "0" diff --git a/utilities_common/cli.py b/utilities_common/cli.py index c8a314b704..dcfdc66708 100644 --- a/utilities_common/cli.py +++ b/utilities_common/cli.py @@ -262,7 +262,7 @@ def is_vlanid_in_range(vid): def check_if_vlanid_exist(config_db, vlan, table_name='VLAN'): - """Check if vlan id exits in the config db or ot""" + """Check if vlan id exists in the config db or ot""" if len(config_db.get_entry(table_name, vlan)) != 0: return True @@ -270,6 +270,17 @@ def check_if_vlanid_exist(config_db, vlan, table_name='VLAN'): return False +def has_vlan_member(config_db, vlan): + """Check if vlan has any member joined""" + + vlan_ports_data = config_db.get_table('VLAN_MEMBER') + for key in vlan_ports_data: + if key[0] == vlan: + return True + + return False + + def is_port_vlan_member(config_db, port, vlan): """Check if port is a member of vlan"""