forked from sonic-net/sonic-buildimage
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[config/show]: split vlan into separate file (sonic-net#1038)
- add vlan.py in config and show - add extensive unit tests for vlan Signed-off-by: Guohan Lu <[email protected]>
- Loading branch information
Showing
16 changed files
with
1,748 additions
and
827 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
from sonic_py_common import logger | ||
|
||
SYSLOG_IDENTIFIER = "config" | ||
|
||
# Global logger instance | ||
log = logger.Logger(SYSLOG_IDENTIFIER) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,203 @@ | ||
import click | ||
|
||
import utilities_common.cli as clicommon | ||
from .utils import log | ||
|
||
# | ||
# 'vlan' group ('config vlan ...') | ||
# | ||
@click.group(cls=clicommon.AbbreviationGroup, name='vlan') | ||
def vlan(): | ||
"""VLAN-related configuration tasks""" | ||
pass | ||
|
||
@vlan.command('add') | ||
@click.argument('vid', metavar='<vid>', required=True, type=int) | ||
@clicommon.pass_db | ||
def add_vlan(db, vid): | ||
"""Add VLAN""" | ||
|
||
ctx = click.get_current_context() | ||
|
||
if not clicommon.is_vlanid_in_range(vid): | ||
ctx.fail("Invalid VLAN ID {} (1-4094)".format(vid)) | ||
|
||
vlan = 'Vlan{}'.format(vid) | ||
if clicommon.check_if_vlanid_exist(db.cfgdb, vlan): | ||
ctx.fail("{} already exists".format(vlan)) | ||
|
||
db.cfgdb.set_entry('VLAN', vlan, {'vlanid': vid}) | ||
|
||
@vlan.command('del') | ||
@click.argument('vid', metavar='<vid>', required=True, type=int) | ||
@clicommon.pass_db | ||
def del_vlan(db, vid): | ||
"""Delete VLAN""" | ||
|
||
log.log_info("'vlan del {}' executing...".format(vid)) | ||
|
||
ctx = click.get_current_context() | ||
|
||
if not clicommon.is_vlanid_in_range(vid): | ||
ctx.fail("Invalid VLAN ID {} (1-4094)".format(vid)) | ||
|
||
vlan = 'Vlan{}'.format(vid) | ||
if clicommon.check_if_vlanid_exist(db.cfgdb, vlan) == False: | ||
ctx.fail("{} does not exist".format(vlan)) | ||
|
||
keys = [ (k, v) for k, v in db.cfgdb.get_table('VLAN_MEMBER') if k == 'Vlan{}'.format(vid) ] | ||
for k in keys: | ||
db.cfgdb.set_entry('VLAN_MEMBER', k, None) | ||
db.cfgdb.set_entry('VLAN', 'Vlan{}'.format(vid), None) | ||
|
||
# | ||
# 'member' group ('config vlan member ...') | ||
# | ||
@vlan.group(cls=clicommon.AbbreviationGroup, name='member') | ||
def vlan_member(): | ||
pass | ||
|
||
@vlan_member.command('add') | ||
@click.argument('vid', metavar='<vid>', required=True, type=int) | ||
@click.argument('port', metavar='port', required=True) | ||
@click.option('-u', '--untagged', is_flag=True) | ||
@clicommon.pass_db | ||
def add_vlan_member(db, vid, port, untagged): | ||
"""Add VLAN member""" | ||
|
||
ctx = click.get_current_context() | ||
|
||
log.log_info("'vlan member add {} {}' executing...".format(vid, port)) | ||
|
||
if not clicommon.is_vlanid_in_range(vid): | ||
ctx.fail("Invalid VLAN ID {} (1-4094)".format(vid)) | ||
|
||
vlan = 'Vlan{}'.format(vid) | ||
if clicommon.check_if_vlanid_exist(db.cfgdb, vlan) == False: | ||
ctx.fail("{} does not exist".format(vlan)) | ||
|
||
if clicommon.get_interface_naming_mode() == "alias": | ||
alias = port | ||
iface_alias_converter = clicommon.InterfaceAliasConverter(db) | ||
port = iface_alias_converter.alias_to_name(alias) | ||
if port is None: | ||
ctx.fail("cannot find port name for alias {}".format(alias)) | ||
|
||
if clicommon.is_port_mirror_dst_port(db.cfgdb, port): | ||
ctx.fail("{} is configured as mirror destination port".format(port)) | ||
|
||
if clicommon.is_port_vlan_member(db.cfgdb, port, vlan): | ||
ctx.fail("{} is already a member of {}".format(port, vlan)) | ||
|
||
if clicommon.is_valid_port(db.cfgdb, port): | ||
is_port = True | ||
elif clicommon.is_valid_portchannel(db.cfgdb, port): | ||
is_port = False | ||
else: | ||
ctx.fail("{} does not exist".format(port)) | ||
|
||
if (is_port and clicommon.is_port_router_interface(db.cfgdb, port)) or \ | ||
(not is_port and clicommon.is_pc_router_interface(db.cfgdb, port)): | ||
ctx.fail("{} is a router interface!".format(port)) | ||
|
||
db.cfgdb.set_entry('VLAN_MEMBER', (vlan, port), {'tagging_mode': "untagged" if untagged else "tagged" }) | ||
|
||
@vlan_member.command('del') | ||
@click.argument('vid', metavar='<vid>', required=True, type=int) | ||
@click.argument('port', metavar='<port>', required=True) | ||
@clicommon.pass_db | ||
def del_vlan_member(db, vid, port): | ||
"""Delete VLAN member""" | ||
|
||
ctx = click.get_current_context() | ||
|
||
log.log_info("'vlan member del {} {}' executing...".format(vid, port)) | ||
|
||
if not clicommon.is_vlanid_in_range(vid): | ||
ctx.fail("Invalid VLAN ID {} (1-4094)".format(vid)) | ||
|
||
vlan = 'Vlan{}'.format(vid) | ||
if clicommon.check_if_vlanid_exist(db.cfgdb, vlan) == False: | ||
ctx.fail("{} does not exist".format(vlan)) | ||
|
||
if clicommon.get_interface_naming_mode() == "alias": | ||
alias = port | ||
iface_alias_converter = clicommon.InterfaceAliasConverter(db) | ||
port = iface_alias_converter.alias_to_name(alias) | ||
if port is None: | ||
ctx.fail("cannot find port name for alias {}".format(alias)) | ||
|
||
if not clicommon.is_port_vlan_member(db.cfgdb, port, vlan): | ||
ctx.fail("{} is not a member of {}".format(port, vlan)) | ||
|
||
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='<vid>', required=True, type=int) | ||
@click.argument('dhcp_relay_destination_ip', metavar='<dhcp_relay_destination_ip>', 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 restart 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='<vid>', required=True, type=int) | ||
@click.argument('dhcp_relay_destination_ip', metavar='<dhcp_relay_destination_ip>', 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 restart dhcp_relay", display_cmd=False) | ||
except SystemExit as e: | ||
ctx.fail("Restart service dhcp_relay failed with error {}".format(e)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.