Skip to content

Commit

Permalink
Add portchannel mac-addr set command
Browse files Browse the repository at this point in the history
  • Loading branch information
dpolishchukgl committed Jul 10, 2024
1 parent fb2e5cd commit 81f25d0
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 6 deletions.
40 changes: 38 additions & 2 deletions config/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -2435,6 +2435,7 @@ def remove_portchannel(ctx, portchannel_name):
ctx.fail("Error: Portchannel {} contains members. Remove members before deleting Portchannel!".format(portchannel_name))

try:
db.set_entry('PORTCHANNEL_INTERFACE', portchannel_name, None)
db.set_entry('PORTCHANNEL', portchannel_name, None)
except JsonPatchConflict:
ctx.fail("{} is not present.".format(portchannel_name))
Expand Down Expand Up @@ -2673,6 +2674,38 @@ def set_portchannel_retry_count(ctx, portchannel_name, retry_count):
ctx.fail("Unable to set the retry count: {}".format(e))


@portchannel.group(cls=clicommon.AbbreviationGroup, name='mac-addr')
@click.pass_context
def portchannel_mac_addr(ctx):
pass


@portchannel_mac_addr.command('set')
@click.argument('portchannel_name', metavar='<portchannel_name>', required=True)
@click.argument('mac_addr', metavar='<mac_addr>', required=True)
@click.pass_context
def set_portchannel_mac_addr(ctx, portchannel_name, mac_addr):
"""Set the mac address for a port channel"""
db = ValidatedConfigDBConnector(ctx.obj['db'])

# Don't proceed if the port channel name is not valid
if is_portchannel_name_valid(portchannel_name) is False:
ctx.fail("{} is invalid!, name should have prefix '{}' and suffix '{}'"
.format(portchannel_name, CFG_PORTCHANNEL_PREFIX, CFG_PORTCHANNEL_NO))

# Don't proceed if the port channel does not exist
if is_portchannel_present_in_db(db, portchannel_name) is False:
ctx.fail("{} is not present.".format(portchannel_name))

if not re.match("^[0-9a-f]{2}([-:]?)[0-9a-f]{2}(\\1[0-9a-f]{2}){4}$", mac_addr.lower()):
ctx.fail("Provided mac address is not valid")

try:
db.set_entry("PORTCHANNEL_INTERFACE", portchannel_name, {"mac_addr": mac_addr})
except ValueError:
ctx.fail("Portchannel name is invalid or nonexistent")


#
# 'mirror_session' group ('config mirror_session ...')
#
Expand Down Expand Up @@ -4975,9 +5008,12 @@ def remove(ctx, interface_name, ip_addr):
clicommon.run_command(command)
remove_router_interface_ip_address(config_db, interface_name, ip_address)
interface_addresses = get_interface_ipaddresses(config_db, interface_name)
if len(interface_addresses) == 0 and is_interface_bind_to_vrf(config_db, interface_name) is False and get_intf_ipv6_link_local_mode(ctx, interface_name, table_name) != "enable":
if len(interface_addresses) == 0 and is_interface_bind_to_vrf(config_db, interface_name) is False and \
get_intf_ipv6_link_local_mode(ctx, interface_name, table_name) != "enable":
if table_name != "VLAN_SUB_INTERFACE":
config_db.set_entry(table_name, interface_name, None)
interface_entry = config_db.get_entry(table_name, interface_name)
if len(interface_entry) == 0:
config_db.set_entry(table_name, interface_name, None)

#
# 'loopback-action' subcommand
Expand Down
33 changes: 33 additions & 0 deletions tests/portchannel_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,39 @@ def test_set_non_existing_portchannel_retry_count(self):
assert result.exit_code != 0
assert "Error: PortChannel0005 is not present." in result.output

def test_set_invalid_portchannel_mac_addr(self):
runner = CliRunner()
db = Db()
obj = {'db':db.cfgdb}

result = runner.invoke(config.config.commands["portchannel"].commands["mac-addr"].commands["set"], ["Ethernet48", "00:11:22:33:44:55"], obj=obj)
print(result.exit_code)
print(result.output)
assert result.exit_code != 0
assert "Error: Ethernet48 is invalid!" in result.output

def test_set_non_existing_portchannel_mac_addr(self):
runner = CliRunner()
db = Db()
obj = {'db':db.cfgdb}

result = runner.invoke(config.config.commands["portchannel"].commands["mac-addr"].commands["set"], ["PortChannel0005", "00:11:22:33:44:55"], obj=obj)
print(result.exit_code)
print(result.output)
assert result.exit_code != 0
assert "Error: PortChannel0005 is not present." in result.output

def test_set_portchannel_mac_addr(self):
runner = CliRunner()
db = Db()
obj = {'db':db.cfgdb}

result = runner.invoke(config.config.commands["portchannel"].commands["mac-addr"].commands["set"], ["PortChannel1001", "00:11:22:33:44:55"], obj=obj)
print(result.exit_code)
print(result.output)
assert result.exit_code == 0
assert result.output == ""

originalSubprocessPopen = subprocess.Popen

class SubprocessMock:
Expand Down
16 changes: 12 additions & 4 deletions utilities_common/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -415,21 +415,29 @@ def is_port_router_interface(config_db, port):
"""Check if port is a router interface"""

interface_table = config_db.get_table('INTERFACE')
for intf in interface_table:
if port == intf:
for intf in interface_table.keys():
if is_ip_prefix_in_key(intf) and port == intf[0]:
return True

entry = config_db.get_entry('INTERFACE', port)
if entry.get('ipv6_use_link_local_only') == 'enable':
return True

return False


def is_pc_router_interface(config_db, pc):
"""Check if portchannel is a router interface"""

pc_interface_table = config_db.get_table('PORTCHANNEL_INTERFACE')
for intf in pc_interface_table:
if pc == intf:
for intf in pc_interface_table.keys():
if is_ip_prefix_in_key(intf) and pc == intf[0]:
return True

entry = config_db.get_entry('PORTCHANNEL_INTERFACE', pc)
if entry.get('ipv6_use_link_local_only') == 'enable':
return True

return False


Expand Down

0 comments on commit 81f25d0

Please sign in to comment.