From 9d74aa01fad0f9a839e6497ccb7c48782c3911b7 Mon Sep 17 00:00:00 2001 From: paavaanan Date: Wed, 15 Aug 2018 00:20:32 +0530 Subject: [PATCH] [config] Add support for accepting port alias in lieu of port name (#260) --- config/main.py | 155 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 149 insertions(+), 6 deletions(-) diff --git a/config/main.py b/config/main.py index 3ecfe8056b..752717c3d9 100755 --- a/config/main.py +++ b/config/main.py @@ -6,7 +6,9 @@ import json import subprocess import netaddr +import re from swsssdk import ConfigDBConnector +from natsort import natsorted from minigraph import parse_device_desc_xml import aaa @@ -18,6 +20,7 @@ # Helper functions # + def run_command(command, display_cmd=False, ignore_error=False): """Run bash command and print output to stdout """ @@ -33,6 +36,79 @@ def run_command(command, display_cmd=False, ignore_error=False): if proc.returncode != 0 and not ignore_error: sys.exit(proc.returncode) + +def interface_alias_to_name(interface_alias): + """Return default interface name if alias name is given as argument + """ + + cmd = 'sonic-cfggen -d --var-json "PORT"' + p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE) + + port_dict = json.loads(p.stdout.read()) + + if interface_alias is not None: + for port_name in natsorted(port_dict.keys()): + if interface_alias == port_dict[port_name]['alias']: + return port_name + print "Invalid interface {}".format(interface_alias) + + return None + + +def interface_name_to_alias(interface_name): + """Return alias interface name if default name is given as argument + """ + + cmd = 'sonic-cfggen -d --var-json "PORT"' + p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE) + + port_dict = json.loads(p.stdout.read()) + + if interface_name is not None: + for port_name in natsorted(port_dict.keys()): + if interface_name == port_name: + return port_dict[port_name]['alias'] + print "Invalid interface {}".format(interface_alias) + + return None + + +def set_interface_mode(mode): + """Modify SONIC_CLI_IFACE_MODE env variable in user .bashrc + """ + user = os.getenv('SUDO_USER') + bashrc_ifacemode_line = "SONIC_CLI_IFACE_MODE={}".format(mode) + + if not user: + user = os.getenv('USER') + + if user != "root": + bashrc = "/home/{}/.bashrc".format(user) + else: + raise click.Abort() + + f = open(bashrc, 'r') + filedata = f.read() + f.close() + + if "SONIC_CLI_IFACE_MODE" not in filedata: + newdata = filedata + bashrc_ifacemode_line + newdata += "\n" + else: + newdata = re.sub(r"SONIC_CLI_IFACE_MODE=\w+", + bashrc_ifacemode_line, filedata) + f = open(bashrc, 'w') + f.write(newdata) + f.close() + print "Please logout and log back in for changes take effect." + + +def get_interface_mode(): + mode = os.getenv('SONIC_CLI_IFACE_MODE') + if mode is None: + mode = "default" + return mode + def _is_neighbor_ipaddress(ipaddress): """Returns True if a neighbor has the IP address , False if not """ @@ -340,11 +416,13 @@ def del_vlan(ctx, vid): db.set_entry('VLAN_MEMBER', k, None) db.set_entry('VLAN', 'Vlan{}'.format(vid), None) + @vlan.group('member') @click.pass_context def vlan_member(ctx): pass + @vlan_member.command('add') @click.argument('vid', metavar='', required=True, type=int) @click.argument('interface_name', metavar='', required=True) @@ -354,13 +432,27 @@ def add_vlan_member(ctx, vid, interface_name, untagged): db = ctx.obj['db'] vlan_name = 'Vlan{}'.format(vid) vlan = db.get_entry('VLAN', vlan_name) + + if get_interface_mode() == "alias": + interface_name = interface_alias_to_name(interface_name) + if interface_name is None: + raise click.Abort() + if len(vlan) == 0: print "{} doesn't exist".format(vlan_name) - raise click.Abort + raise click.Abort() members = vlan.get('members', []) if interface_name in members: - print "{} is already a member of {}".format(interface_name, vlan_name) - raise click.Abort + if get_interface_mode() == "alias": + interface_name = interface_name_to_alias(interface_name) + if interface_name is None: + raise click.Abort() + print "{} is already a member of {}".format(interface_name, + vlan_name) + else: + print "{} is already a member of {}".format(interface_name, + vlan_name) + raise click.Abort() members.append(interface_name) vlan['members'] = members db.set_entry('VLAN', vlan_name, vlan) @@ -375,13 +467,25 @@ def del_vlan_member(ctx, vid, interface_name): db = ctx.obj['db'] vlan_name = 'Vlan{}'.format(vid) vlan = db.get_entry('VLAN', vlan_name) + + if get_interface_mode() == "alias": + interface_name = interface_alias_to_name(interface_name) + if interface_name is None: + raise click.Abort() + if len(vlan) == 0: print "{} doesn't exist".format(vlan_name) - raise click.Abort + raise click.Abort() members = vlan.get('members', []) if interface_name not in members: - print "{} is not a member of {}".format(interface_name, vlan_name) - raise click.Abort + if get_interface_mode() == "alias": + interface_name = interface_name_to_alias(interface_name) + if interface_name is None: + raise click.Abort() + print "{} is not a member of {}".format(interface_name, vlan_name) + else: + print "{} is not a member of {}".format(interface_name, vlan_name) + raise click.Abort() members.remove(interface_name) if len(members) == 0: del vlan['members'] @@ -466,6 +570,11 @@ def interface(): @click.option('-v', '--verbose', is_flag=True, help="Enable verbose output") def shutdown(interface_name, verbose): """Shut down interface""" + if get_interface_mode() == "alias": + interface_name = interface_alias_to_name(interface_name) + if interface_name is None: + raise click.Abort() + command = "ip link set {} down".format(interface_name) run_command(command, display_cmd=verbose) @@ -478,6 +587,12 @@ def shutdown(interface_name, verbose): @click.option('-v', '--verbose', is_flag=True, help="Enable verbose output") def startup(interface_name, verbose): """Start up interface""" + if get_interface_mode() == "alias": + interface_name = interface_alias_to_name(interface_name) + if interface_name is None: + raise click.Abort() + + command = "ip link set {} up".format(interface_name) run_command(command, display_cmd=verbose) @@ -491,6 +606,11 @@ def startup(interface_name, verbose): @click.option('-v', '--verbose', is_flag=True, help="Enable verbose output") def speed(interface_name, interface_speed, verbose): """Set interface speed""" + if get_interface_mode() == "alias": + interface_name = interface_alias_to_name(interface_name) + if interface_name is None: + raise click.Abort() + command = "portconfig -p {} -s {}".format(interface_name, interface_speed) if verbose: command += " -vv" run_command(command, display_cmd=verbose) @@ -572,5 +692,28 @@ def platform(): platform.add_command(mlnx.mlnx) +# +# 'interface_mode' group +# + +@cli.group() +def interface_naming_mode(): + """Modify interface naming mode for interacting with SONiC CLI""" + pass + + +@interface_naming_mode.command('default') +def interface_mode_default(): + """Set CLI interface naming mode to DEFAULT (SONiC port name)""" + alias_mode = "default" + set_interface_mode(alias_mode) + + +@interface_naming_mode.command('alias') +def interface_mode_alias(): + """Set CLI interface naming mode to ALIAS (Vendor port alias)""" + alias_mode = "alias" + set_interface_mode(alias_mode) + if __name__ == '__main__': cli()