diff --git a/config/main.py b/config/main.py index 500718e2b8..41a9f48121 100644 --- a/config/main.py +++ b/config/main.py @@ -4630,12 +4630,14 @@ def validate_vlan_exists(db,text): # 'add' subcommand # -@ip.command() + +@ip.command('add') @click.argument('interface_name', metavar='', required=True) @click.argument("ip_addr", metavar="", required=True) @click.argument('gw', metavar='', required=False) +@click.option('--secondary', "-s", is_flag=True, default=False) @click.pass_context -def add(ctx, interface_name, ip_addr, gw): +def add_interface_ip(ctx, interface_name, ip_addr, gw, secondary): """Add an IP address towards the interface""" # Get the config_db connector config_db = ValidatedConfigDBConnector(ctx.obj['config_db']) @@ -4720,7 +4722,25 @@ def add(ctx, interface_name, ip_addr, gw): config_db.set_entry(table_name, interface_name, {"admin_status": "up"}) else: config_db.set_entry(table_name, interface_name, {"NULL": "NULL"}) - config_db.set_entry(table_name, (interface_name, str(ip_address)), {"NULL": "NULL"}) + + if secondary: + # We update the secondary flag only in case of VLAN Interface. + if table_name == "VLAN_INTERFACE": + vlan_interface_table = config_db.get_table(table_name) + contains_primary = False + for key, value in vlan_interface_table.items(): + if not isinstance(key, tuple): + continue + name, prefix = key + if name == interface_name and "secondary" not in value: + contains_primary = True + if contains_primary: + config_db.set_entry(table_name, (interface_name, str(ip_address)), {"secondary": "true"}) + else: + ctx.fail("Primary for the interface {} is not set, so skipping adding the interface" + .format(interface_name)) + else: + config_db.set_entry(table_name, (interface_name, str(ip_address)), {"NULL": "NULL"}) # # 'del' subcommand diff --git a/tests/ip_config_test.py b/tests/ip_config_test.py index ffa2931093..9338d341e4 100644 --- a/tests/ip_config_test.py +++ b/tests/ip_config_test.py @@ -130,6 +130,35 @@ def test_add_del_interface_valid_ipv4(self): assert mock_run_command.call_count == 1 assert ('Eth36.10', '32.11.10.1/24') not in db.cfgdb.get_table('VLAN_SUB_INTERFACE') + # config int ip add vlan1000 10.21.20.1/24 as secondary + result = runner.invoke(config.config.commands["interface"].commands["ip"].commands["add"], + ["Vlan1000", "10.11.20.1/24", "--secondary"], obj=obj) + assert result.exit_code == 0 + assert ('Vlan1000', '10.11.20.1/24') in db.cfgdb.get_table('VLAN_INTERFACE') + assert db.cfgdb.get_table('VLAN_INTERFACE')[('Vlan1000', '10.11.20.1/24')]['secondary'] == "true" + + # config int ip add vlan2000 10.21.20.1/24 as secondary + result = runner.invoke(config.config.commands["interface"].commands["ip"].commands["add"], + ["Vlan2000", "10.21.20.1/24", "-s"], obj=obj) + assert result.exit_code == 0 + assert ('Vlan2000', '10.21.20.1/24') in db.cfgdb.get_table('VLAN_INTERFACE') + assert db.cfgdb.get_table('VLAN_INTERFACE')[('Vlan2000', '10.21.20.1/24')]['secondary'] == "true" + + # config int ip add vlan4000 10.16.20.1/24 as primary and make sure secondary is not present in table + result = runner.invoke(config.config.commands["interface"].commands["ip"].commands["add"], + ["Vlan4000", "10.16.20.1/24"], obj=obj) + assert result.exit_code == 0 + assert ('Vlan4000', '10.16.20.1/24') in db.cfgdb.get_table('VLAN_INTERFACE') + assert 'secondary' not in db.cfgdb.get_table('VLAN_INTERFACE')[('Vlan4000', '10.16.20.1/24')] + + # create vlan 500 + result = runner.invoke(config.config.commands["vlan"].commands["add"], ["500"], obj=db) + # config int ip add vlan500 10.21.20.1/24 as secondary - should fail as vlan500 is not added in table + ERR_MSG = "Error: Primary for the interface Vlan500 is not set, so skipping adding the interface" + result = runner.invoke(config.config.commands["interface"].commands["ip"].commands["add"], + ["Vlan500", "10.21.20.1/24", "--secondary"], obj=obj) + assert result.exit_code != 0 + assert ERR_MSG in result.output def test_add_interface_invalid_ipv4(self): db = Db()