From afcfc4b484313c7461aa31234345004164c08d60 Mon Sep 17 00:00:00 2001 From: Harish Venkatraman Date: Sun, 17 Feb 2019 15:26:53 -0800 Subject: [PATCH 01/10] [sonic-utilities] managementVRF cli support(l3mdev) This commit adds CLI support for management VRF using l3dev. mVRF can be enabled using config vrf add mgmt and deleted using config vrf del mgmt. Show commands for management VRF are added which displays the linux command output, will update show command display after concluding what would be the output for the show commands. Added cli to configure management interface(eth0), config interface ip eth0 add can be used to configure eth0 ip and config ip eth0 remove is used to remove eth0 ip. New cli config/show commands: config vrf add mgmt config vrf del mgmt config interface eth0 ip add ip/mask gatewayIP config interface eth0 ip remove ip/mask show mgmt-vrf show mgmt-vrf route show mgmt-vrf addresses show mgmt-vrf interfaces Signed-off-by: Harish Venkatraman --- config/main.py | 127 ++++++++++++++++++++++++++++++++++++++++++++++++- show/main.py | 98 +++++++++++++++++++++++++++++++++++++- 2 files changed, 221 insertions(+), 4 deletions(-) diff --git a/config/main.py b/config/main.py index ed071c6887..389714dcae 100755 --- a/config/main.py +++ b/config/main.py @@ -6,6 +6,8 @@ import json import subprocess import netaddr +import logging +import logging.handlers import re import syslog @@ -789,6 +791,86 @@ def del_vlan_member(ctx, vid, interface_name): db.set_entry('VLAN_MEMBER', (vlan_name, interface_name), None) + +def vrf_add_management_vrf(): + """Enable management vrf""" + + config_db = ConfigDBConnector() + config_db.connect() + entry = config_db.get_entry('MGMT_VRF_CONFIG', "vrf_global") + if entry and entry['mgmtVrfEnabled'] == 'true' : + click.echo("ManagementVRF is already Enabled.") + return None + config_db.mod_entry('MGMT_VRF_CONFIG',"vrf_global",{"mgmtVrfEnabled": "true"}) + cmd="service ntp stop" + os.system (cmd) + cmd="systemctl restart interfaces-config" + os.system (cmd) + cmd="service ntp start" + os.system (cmd) + + +def vrf_delete_management_vrf(): + """Disable management vrf""" + + config_db = ConfigDBConnector() + config_db.connect() + entry = config_db.get_entry('MGMT_VRF_CONFIG', "vrf_global") + if not entry or entry['mgmtVrfEnabled'] == 'false' : + click.echo("ManagementVRF is already Disabled.") + return None + config_db.mod_entry('MGMT_VRF_CONFIG',"vrf_global",{"mgmtVrfEnabled": "false"}) + cmd="service ntp stop" + os.system (cmd) + cmd="systemctl restart interfaces-config" + os.system (cmd) + cmd="service ntp start" + os.system (cmd) + + +# +# 'vrf' group ('config vrf ...') +# + +@config.group('vrf') +def vrf(): + """VRF-related configuration tasks""" + pass + + +@vrf.command('add') +@click.argument('vrfname', metavar='. Type mgmt for management VRF', required=True) +@click.pass_context +def vrf_add (ctx, vrfname): + """VRF ADD""" + if vrfname == 'mgmt' or vrfname == 'management': + vrf_add_management_vrf() + else: + click.echo("Creation of data vrf={} is not yet supported".format(vrfname)) + + +@vrf.command('del') +@click.argument('vrfname', metavar='. Type mgmt for management VRF', required=False) +@click.pass_context +def vrf_del (ctx, vrfname): + """VRF Delete""" + if vrfname == 'mgmt' or vrfname == 'management': + vrf_delete_management_vrf() + else: + click.echo("Deletion of data vrf={} is not yet supported".format(vrfname)) + + +@config.command('clear_mgmt') +@click.pass_context +def clear_mgmt(ctx): + MGMT_TABLE_NAMES = [ + 'MGMT_INTERFACE', + 'MGMT_VRF_CONFIG'] + config_db = ConfigDBConnector() + config_db.connect() + for mgmt_table in MGMT_TABLE_NAMES: + config_db.delete_table(mgmt_table) + # # 'bgp' group ('config bgp ...') # @@ -925,6 +1007,14 @@ def speed(ctx, interface_name, interface_speed, verbose): command += " -vv" run_command(command, display_cmd=verbose) +def _get_all_mgmtinterface_keys(): + """Returns list of strings containing mgmt interface keys + """ + config_db = ConfigDBConnector() + config_db.connect() + return config_db.get_table('MGMT_INTERFACE').keys() + + # # 'ip' subgroup ('config interface ip ...') # @@ -942,8 +1032,9 @@ def ip(ctx): @ip.command() @click.argument('interface_name', metavar='', required=True) @click.argument("ip_addr", metavar="", required=True) +@click.argument('gw', metavar='', required=False) @click.pass_context -def add(ctx, interface_name, ip_addr): +def add(ctx, interface_name, ip_addr, gw): """Add an IP address towards the interface""" config_db = ctx.obj["config_db"] if get_interface_naming_mode() == "alias": @@ -956,6 +1047,32 @@ def add(ctx, interface_name, ip_addr): if interface_name.startswith("Ethernet"): config_db.set_entry("INTERFACE", (interface_name, ip_addr), {"NULL": "NULL"}) config_db.set_entry("INTERFACE", interface_name, {"NULL": "NULL"}) + elif interface_name == 'eth0': + + # Configuring more than 1 IPv4 or more than 1 IPv6 address fails. + # Allow only one IPv4 and only one IPv6 address to be configured for IPv6. + # If a row already exist, overwrite it (by doing delete and add). + mgmtintf_key_list = _get_all_mgmtinterface_keys() + + for key in mgmtintf_key_list: + # For loop runs for max 2 rows, once for IPv4 and once for IPv6. + if ':' in ip_addr and ':' in key[1]: + # If user has configured IPv6 address and the already available row is also IPv6, delete it here. + config_db.set_entry("MGMT_INTERFACE", ("eth0", key[1]), None) + elif ':' not in ip_addr and ':' not in key[1]: + # If user has configured IPv4 address and the already available row is also IPv6, delete it here. + config_db.set_entry("MGMT_INTERFACE", ("eth0", key[1]), None) + + # Set the new row with new value + if not gw: + config_db.set_entry("MGMT_INTERFACE", (interface_name, ip_addr), {"NULL": "NULL"}) + else: + config_db.set_entry("MGMT_INTERFACE", (interface_name, ip_addr), {"gwaddr": gw}) + cmd="systemctl restart interfaces-config" + os.system (cmd) + cmd="systemctl restart ntp-config" + os.system (cmd) + elif interface_name.startswith("PortChannel"): config_db.set_entry("PORTCHANNEL_INTERFACE", (interface_name, ip_addr), {"NULL": "NULL"}) config_db.set_entry("PORTCHANNEL_INTERFACE", interface_name, {"NULL": "NULL"}) @@ -991,6 +1108,12 @@ def remove(ctx, interface_name, ip_addr): if interface_name.startswith("Ethernet"): config_db.set_entry("INTERFACE", (interface_name, ip_addr), None) if_table = "INTERFACE" + elif interface_name == 'eth0': + config_db.set_entry("MGMT_INTERFACE", (interface_name, ip_addr), None) + cmd="systemctl restart interfaces-config" + os.system (cmd) + cmd="systemctl restart ntp-config" + os.system (cmd) elif interface_name.startswith("PortChannel"): config_db.set_entry("PORTCHANNEL_INTERFACE", (interface_name, ip_addr), None) if_table = "PORTCHANNEL_INTERFACE" @@ -1003,7 +1126,7 @@ def remove(ctx, interface_name, ip_addr): ctx.fail("'interface_name' is not valid. Valid names [Ethernet/PortChannel/Vlan/Loopback]") except ValueError: ctx.fail("'ip_addr' is not valid.") - + exists = False if if_table: interfaces = config_db.get_table(if_table) diff --git a/show/main.py b/show/main.py index 9f5631d038..cd1640082b 100755 --- a/show/main.py +++ b/show/main.py @@ -418,6 +418,93 @@ def ndp(ip6address, iface, verbose): run_command(cmd, display_cmd=verbose) +# +# 'mgmt-vrf' group ("show mgmt-vrf ...") +# + +@cli.group('mgmt-vrf', invoke_without_command=True) +@click.pass_context +def mgmt_vrf(ctx): + + """Show management VRF attributes""" + + if ctx.invoked_subcommand is None: + cmd = 'sonic-cfggen -d --var-json "MGMT_VRF_CONFIG"' + + p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + res = p.communicate() + if p.returncode == 0 : + p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + mvrf_dict = json.loads(p.stdout.read()) + + # if the mgmtVrfEnabled attribute is configured, check the value + # and print Enabled or Disabled accordingly. + if 'mgmtVrfEnabled' in mvrf_dict['vrf_global']: + if (mvrf_dict['vrf_global']['mgmtVrfEnabled'] == "true"): + click.echo("\nManagementVRF : Enabled") + else: + click.echo("\nManagementVRF : Disabled") + + click.echo("\nManagement VRF in Linux:") + cmd = "sudo ip link show type vrf" + run_command(cmd) + +@mgmt_vrf.command('interfaces') +def mgmt_vrf_interfaces (): + """Show management VRF attributes""" + + click.echo("\neth0 Interfaces in Management VRF:") + cmd = "sudo ifconfig eth0" + run_command(cmd) + return None + +@mgmt_vrf.command('route') +def mgmt_vrf_route (): + """Show management VRF routes""" + + click.echo("\nRoutes in Management VRF Routing Table:") + cmd = "sudo ip route show table 1001" + run_command(cmd) + return None + + +@mgmt_vrf.command('addresses') +def mgmt_vrf_addresses (): + """Show management VRF addresses""" + + click.echo("\nIP Addresses for interfaces in Management VRF:") + cmd = "sudo ip address show mgmt" + run_command(cmd) + return None + + + +# +# 'management_interface' group ("show management_interface ...") +# + +@cli.group(cls=AliasedGroup, default_if_no_args=False) +def management_interface(): + """Show management interface parameters""" + pass + +# 'address' subcommand ("show management_interface address") +@management_interface.command() +def address (): + """Show IP address configured for management interface""" + + config_db = ConfigDBConnector() + config_db.connect() + header = ['IFNAME', 'IP Address', 'PrefixLen',] + body = [] + + # Fetching data from config_db for MGMT_INTERFACE + mgmt_ip_data = config_db.get_table('MGMT_INTERFACE') + for key in natsorted(mgmt_ip_data.keys()): + click.echo("Management IP address = {0}".format(key[1])) + click.echo("Management NetWork Default Gateway = {0}".format(mgmt_ip_data[key]['gwaddr'])) + + # # 'interfaces' group ("show interfaces ...") # @@ -1443,8 +1530,15 @@ def bgp(verbose): @click.option('--verbose', is_flag=True, help="Enable verbose output") def ntp(verbose): """Show NTP information""" - cmd = "ntpq -p -n" - run_command(cmd, display_cmd=verbose) + config_db = ConfigDBConnector() + config_db.connect() + entry = config_db.get_entry('MGMT_VRF_CONFIG', "vrf_global") + if entry and entry['mgmtVrfEnabled'] == 'true' : + cmd = "mgmtvrf_ntpq -p -n" + run_command(cmd, display_cmd=verbose) + else: + cmd = "ntpq -p -n" + run_command(cmd, display_cmd=verbose) # From f83b4629d963cd38df36a1927badfdf15f6a541a Mon Sep 17 00:00:00 2001 From: kannankvs Date: Wed, 11 Sep 2019 13:11:39 +0530 Subject: [PATCH 02/10] updated to resolve the conflict on show/main.py --- show/main.py | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/show/main.py b/show/main.py index cd1640082b..76247b3157 100755 --- a/show/main.py +++ b/show/main.py @@ -1530,15 +1530,23 @@ def bgp(verbose): @click.option('--verbose', is_flag=True, help="Enable verbose output") def ntp(verbose): """Show NTP information""" - config_db = ConfigDBConnector() - config_db.connect() - entry = config_db.get_entry('MGMT_VRF_CONFIG', "vrf_global") - if entry and entry['mgmtVrfEnabled'] == 'true' : - cmd = "mgmtvrf_ntpq -p -n" - run_command(cmd, display_cmd=verbose) - else: - cmd = "ntpq -p -n" - run_command(cmd, display_cmd=verbose) + ntpcmd = "ntpq -p -n" + if ctx.invoked_subcommand is None: + cmd = 'sonic-cfggen -d --var-json "MGMT_VRF_CONFIG"' + + p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + res = p.communicate() + if p.returncode == 0 : + p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + mvrf_dict = json.loads(p.stdout.read()) + + # if the mgmtVrfEnabled attribute is configured, check the value + # and print Enabled or Disabled accordingly. + if 'mgmtVrfEnabled' in mvrf_dict['vrf_global']: + if (mvrf_dict['vrf_global']['mgmtVrfEnabled'] == "true"): + #ManagementVRF is enabled. Call ntpq using cgexec + ntpcmd = "cgexec -g l3mdev:mgmt ntpq -p -n" + run_command(ntpcmd, display_cmd=verbose) # From 14cc90f909f4389beb60e46fc3a5abb01f4a44af Mon Sep 17 00:00:00 2001 From: kannankvs Date: Wed, 11 Sep 2019 13:16:08 +0530 Subject: [PATCH 03/10] missing empty line w.r.t conflict added. --- show/main.py | 1 + 1 file changed, 1 insertion(+) diff --git a/show/main.py b/show/main.py index 76247b3157..6a952abc08 100755 --- a/show/main.py +++ b/show/main.py @@ -1549,6 +1549,7 @@ def ntp(verbose): run_command(ntpcmd, display_cmd=verbose) + # # 'uptime' command ("show uptime") # From 4152cf34bfedfa0e93558319c2e7d756cccf17a1 Mon Sep 17 00:00:00 2001 From: kannankvs Date: Wed, 11 Sep 2019 17:13:50 +0530 Subject: [PATCH 04/10] table number corrected. --- show/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/show/main.py b/show/main.py index 6a952abc08..354710236a 100755 --- a/show/main.py +++ b/show/main.py @@ -463,7 +463,7 @@ def mgmt_vrf_route (): """Show management VRF routes""" click.echo("\nRoutes in Management VRF Routing Table:") - cmd = "sudo ip route show table 1001" + cmd = "sudo ip route show table 5000" run_command(cmd) return None From ac1a3c12ad07b407930a1134caddda27e572ff42 Mon Sep 17 00:00:00 2001 From: Kannan KVS Date: Thu, 3 Oct 2019 14:18:48 -0700 Subject: [PATCH 05/10] addressed review comments --- config/main.py | 136 ++++++++++++++++++++++++++++--------------------- 1 file changed, 77 insertions(+), 59 deletions(-) diff --git a/config/main.py b/config/main.py index 389714dcae..b0ca455026 100755 --- a/config/main.py +++ b/config/main.py @@ -790,43 +790,49 @@ def del_vlan_member(ctx, vid, interface_name): db.set_entry('VLAN', vlan_name, vlan) db.set_entry('VLAN_MEMBER', (vlan_name, interface_name), None) - +def mvrf_restart_interfaces_config_ntp(): + """Restart interfaces-config service and NTP service""" + cmd="service ntp stop" + os.system (cmd) + cmd="systemctl restart interfaces-config" + os.system (cmd) + cmd="service ntp start" + os.system (cmd) def vrf_add_management_vrf(): - """Enable management vrf""" - - config_db = ConfigDBConnector() - config_db.connect() - entry = config_db.get_entry('MGMT_VRF_CONFIG', "vrf_global") - if entry and entry['mgmtVrfEnabled'] == 'true' : - click.echo("ManagementVRF is already Enabled.") - return None - config_db.mod_entry('MGMT_VRF_CONFIG',"vrf_global",{"mgmtVrfEnabled": "true"}) - cmd="service ntp stop" - os.system (cmd) - cmd="systemctl restart interfaces-config" - os.system (cmd) - cmd="service ntp start" - os.system (cmd) + """Enable management vrf""" + config_db = ConfigDBConnector() + config_db.connect() + entry = config_db.get_entry('MGMT_VRF_CONFIG', "vrf_global") + if entry and entry['mgmtVrfEnabled'] == 'true' : + click.echo("ManagementVRF is already Enabled.") + return None + config_db.mod_entry('MGMT_VRF_CONFIG',"vrf_global",{"mgmtVrfEnabled": "true"}) + # To move eth0 to management VRF, interfaces-config service has be to be + # restarted. /etc/network/interfaces file is recreated and the networking + # service is restarted which moves the eth0 to management VRF. + # NTP service should also be restarted to rerun the NTP service inside + # mvrf using cgexec. When the NTP service is restarted, service init + # file /etc/init.d/ntp takes care of using cgexec. + mvrf_restart_interfaces_config_ntp() def vrf_delete_management_vrf(): - """Disable management vrf""" - - config_db = ConfigDBConnector() - config_db.connect() - entry = config_db.get_entry('MGMT_VRF_CONFIG', "vrf_global") - if not entry or entry['mgmtVrfEnabled'] == 'false' : - click.echo("ManagementVRF is already Disabled.") - return None - config_db.mod_entry('MGMT_VRF_CONFIG',"vrf_global",{"mgmtVrfEnabled": "false"}) - cmd="service ntp stop" - os.system (cmd) - cmd="systemctl restart interfaces-config" - os.system (cmd) - cmd="service ntp start" - os.system (cmd) + """Disable management vrf""" + config_db = ConfigDBConnector() + config_db.connect() + entry = config_db.get_entry('MGMT_VRF_CONFIG', "vrf_global") + if not entry or entry['mgmtVrfEnabled'] == 'false' : + click.echo("ManagementVRF is already Disabled.") + return None + config_db.mod_entry('MGMT_VRF_CONFIG',"vrf_global",{"mgmtVrfEnabled": "false"}) + # To move back eth0 to default VRF, interfaces-config service has be to be + # restarted. /etc/network/interfaces file is recreated and the networking + # service is restarted which moves the eth0 to default VRF. + # NTP service should also be restarted to rerun the NTP service inside + # default VRF without cgexec. + mvrf_restart_interfaces_config_ntp() # # 'vrf' group ('config vrf ...') @@ -837,7 +843,6 @@ def vrf(): """VRF-related configuration tasks""" pass - @vrf.command('add') @click.argument('vrfname', metavar='. Type mgmt for management VRF', required=True) @click.pass_context @@ -848,7 +853,6 @@ def vrf_add (ctx, vrfname): else: click.echo("Creation of data vrf={} is not yet supported".format(vrfname)) - @vrf.command('del') @click.argument('vrfname', metavar='. Type mgmt for management VRF', required=False) @click.pass_context @@ -860,17 +864,6 @@ def vrf_del (ctx, vrfname): click.echo("Deletion of data vrf={} is not yet supported".format(vrfname)) -@config.command('clear_mgmt') -@click.pass_context -def clear_mgmt(ctx): - MGMT_TABLE_NAMES = [ - 'MGMT_INTERFACE', - 'MGMT_VRF_CONFIG'] - config_db = ConfigDBConnector() - config_db.connect() - for mgmt_table in MGMT_TABLE_NAMES: - config_db.delete_table(mgmt_table) - # # 'bgp' group ('config bgp ...') # @@ -1015,6 +1008,13 @@ def _get_all_mgmtinterface_keys(): return config_db.get_table('MGMT_INTERFACE').keys() +def restart_interfaces_config_ntp_config(): + """Add or remove IP address""" + cmd="systemctl restart interfaces-config" + os.system (cmd) + cmd="systemctl restart ntp-config" + os.system (cmd) + # # 'ip' subgroup ('config interface ip ...') # @@ -1045,8 +1045,12 @@ def add(ctx, interface_name, ip_addr, gw): try: ipaddress.ip_network(unicode(ip_addr), strict=False) if interface_name.startswith("Ethernet"): - config_db.set_entry("INTERFACE", (interface_name, ip_addr), {"NULL": "NULL"}) - config_db.set_entry("INTERFACE", interface_name, {"NULL": "NULL"}) + if VLAN_SUB_INTERFACE_SEPARATOR in interface_name: + config_db.set_entry("VLAN_SUB_INTERFACE", interface_name, {"admin_status": "up"}) + config_db.set_entry("VLAN_SUB_INTERFACE", (interface_name, ip_addr), {"NULL": "NULL"}) + else: + config_db.set_entry("INTERFACE", (interface_name, ip_addr), {"NULL": "NULL"}) + config_db.set_entry("INTERFACE", interface_name, {"NULL": "NULL"}) elif interface_name == 'eth0': # Configuring more than 1 IPv4 or more than 1 IPv6 address fails. @@ -1056,11 +1060,15 @@ def add(ctx, interface_name, ip_addr, gw): for key in mgmtintf_key_list: # For loop runs for max 2 rows, once for IPv4 and once for IPv6. - if ':' in ip_addr and ':' in key[1]: + # No need to capture the exception since the ip_addr is already validated earlier + ip_input = ipaddress.ip_interface(ip_addr) + current_ip = ip = ipaddress.ip_interface(key[1]) + if (ip_input.version == 6) and (current_ip.version == 6): +# if (ipaddress.version(unicode(ip_addr)) == 6) and (ipaddress.version(unicode(key[1])) == 6): # If user has configured IPv6 address and the already available row is also IPv6, delete it here. config_db.set_entry("MGMT_INTERFACE", ("eth0", key[1]), None) - elif ':' not in ip_addr and ':' not in key[1]: - # If user has configured IPv4 address and the already available row is also IPv6, delete it here. + elif (ip_input.version != 6) and (current_ip.version != 6): + # If user has configured IPv4 address and the already available row is also IPv4, delete it here. config_db.set_entry("MGMT_INTERFACE", ("eth0", key[1]), None) # Set the new row with new value @@ -1068,10 +1076,13 @@ def add(ctx, interface_name, ip_addr, gw): config_db.set_entry("MGMT_INTERFACE", (interface_name, ip_addr), {"NULL": "NULL"}) else: config_db.set_entry("MGMT_INTERFACE", (interface_name, ip_addr), {"gwaddr": gw}) - cmd="systemctl restart interfaces-config" - os.system (cmd) - cmd="systemctl restart ntp-config" - os.system (cmd) + # Restart the interfaces-config service which regenerates the + # /etc/network/interfaces file and restarts the networking service + # to make the new IP address effective for eth0. + # "ntp-config" service should also be restarted based on the new + # eth0 IP address since the ntp.conf (generated from ntp.conf.j2) is + # made to listen on specific eth0 IP address. + restart_interfaces_config_ntp_config() elif interface_name.startswith("PortChannel"): config_db.set_entry("PORTCHANNEL_INTERFACE", (interface_name, ip_addr), {"NULL": "NULL"}) @@ -1106,14 +1117,21 @@ def remove(ctx, interface_name, ip_addr): try: ipaddress.ip_network(unicode(ip_addr), strict=False) if interface_name.startswith("Ethernet"): - config_db.set_entry("INTERFACE", (interface_name, ip_addr), None) - if_table = "INTERFACE" + if VLAN_SUB_INTERFACE_SEPARATOR in interface_name: + config_db.set_entry("VLAN_SUB_INTERFACE", (interface_name, ip_addr), None) + if_table = "VLAN_SUB_INTERFACE" + else: + config_db.set_entry("INTERFACE", (interface_name, ip_addr), None) + if_table = "INTERFACE" elif interface_name == 'eth0': config_db.set_entry("MGMT_INTERFACE", (interface_name, ip_addr), None) - cmd="systemctl restart interfaces-config" - os.system (cmd) - cmd="systemctl restart ntp-config" - os.system (cmd) + # Restart the interfaces-config service which regenerates the + # /etc/network/interfaces file and restarts the networking service + # to remove it from the system. + # "ntp-config" service should also be restarted since the ntp.conf + # (generated from ntp.conf.j2) had earlier been made to listen on + # previously configured eth0 IP address. Reset it back. + restart_interfaces_config_ntp_config() elif interface_name.startswith("PortChannel"): config_db.set_entry("PORTCHANNEL_INTERFACE", (interface_name, ip_addr), None) if_table = "PORTCHANNEL_INTERFACE" From ad030ff96ee2d081161ac4d0017c56df7b837fe6 Mon Sep 17 00:00:00 2001 From: Kannan KVS Date: Thu, 3 Oct 2019 15:18:57 -0700 Subject: [PATCH 06/10] resolving conflict3 --- show/main.py | 91 +++++++++++++++++++++------------------------------- 1 file changed, 37 insertions(+), 54 deletions(-) diff --git a/show/main.py b/show/main.py index 7eead017cc..28383ae6cd 100755 --- a/show/main.py +++ b/show/main.py @@ -433,66 +433,50 @@ def ndp(ip6address, iface, verbose): run_command(cmd, display_cmd=verbose) +def is_mgmt_vrf_enabled(ctx): + """Check if management VRF is enabled""" + if ctx.invoked_subcommand is None: + cmd = 'sonic-cfggen -d --var-json "MGMT_VRF_CONFIG"' + + p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + res = p.communicate() + if p.returncode == 0 : + p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + mvrf_dict = json.loads(p.stdout.read()) + + # if the mgmtVrfEnabled attribute is configured, check the value + # and print Enabled or Disabled accordingly. + if 'mgmtVrfEnabled' in mvrf_dict['vrf_global']: + if (mvrf_dict['vrf_global']['mgmtVrfEnabled'] == "true"): + #ManagementVRF is enabled. Return True. + return True + return False + # # 'mgmt-vrf' group ("show mgmt-vrf ...") # @cli.group('mgmt-vrf', invoke_without_command=True) +@click.argument('routes', required=False) @click.pass_context -def mgmt_vrf(ctx): - - """Show management VRF attributes""" - - if ctx.invoked_subcommand is None: - cmd = 'sonic-cfggen -d --var-json "MGMT_VRF_CONFIG"' - - p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - res = p.communicate() - if p.returncode == 0 : - p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - mvrf_dict = json.loads(p.stdout.read()) - - # if the mgmtVrfEnabled attribute is configured, check the value - # and print Enabled or Disabled accordingly. - if 'mgmtVrfEnabled' in mvrf_dict['vrf_global']: - if (mvrf_dict['vrf_global']['mgmtVrfEnabled'] == "true"): - click.echo("\nManagementVRF : Enabled") - else: - click.echo("\nManagementVRF : Disabled") - - click.echo("\nManagement VRF in Linux:") - cmd = "sudo ip link show type vrf" - run_command(cmd) - -@mgmt_vrf.command('interfaces') -def mgmt_vrf_interfaces (): - """Show management VRF attributes""" - - click.echo("\neth0 Interfaces in Management VRF:") - cmd = "sudo ifconfig eth0" - run_command(cmd) - return None - -@mgmt_vrf.command('route') -def mgmt_vrf_route (): - """Show management VRF routes""" - - click.echo("\nRoutes in Management VRF Routing Table:") - cmd = "sudo ip route show table 5000" - run_command(cmd) - return None - - -@mgmt_vrf.command('addresses') -def mgmt_vrf_addresses (): - """Show management VRF addresses""" - - click.echo("\nIP Addresses for interfaces in Management VRF:") - cmd = "sudo ip address show mgmt" - run_command(cmd) - return None - +def mgmt_vrf(ctx,routes): + """Show management VRF attributes""" + if is_mgmt_vrf_enabled(ctx) is False: + click.echo("\nKVSK:ManagementVRF : Disabled") + return + else: + if routes is None: + click.echo("\nManagementVRF : Enabled") + click.echo("\nManagement VRF interfaces in Linux:") + cmd = "ip -d link show mgmt" + run_command(cmd) + cmd = "ip link show vrf mgmt" + run_command(cmd) + else: + click.echo("\nRoutes in Management VRF Routing Table:") + cmd = "ip route show table 5000" + run_command(cmd) # # 'management_interface' group ("show management_interface ...") @@ -519,7 +503,6 @@ def address (): click.echo("Management IP address = {0}".format(key[1])) click.echo("Management NetWork Default Gateway = {0}".format(mgmt_ip_data[key]['gwaddr'])) - # # 'interfaces' group ("show interfaces ...") # From 30fea2e4f6ad846fbe7382086e057ce404fe97ba Mon Sep 17 00:00:00 2001 From: Kannan KVS Date: Fri, 4 Oct 2019 00:59:02 -0700 Subject: [PATCH 07/10] addressed the comments2 --- config/main.py | 49 +++++++++++++++++++------------------------------ show/main.py | 26 +++++++------------------- 2 files changed, 26 insertions(+), 49 deletions(-) diff --git a/config/main.py b/config/main.py index 67161e9869..68fc7b4f27 100755 --- a/config/main.py +++ b/config/main.py @@ -893,6 +893,14 @@ def del_vlan_member(ctx, vid, interface_name): def mvrf_restart_interfaces_config_ntp(): """Restart interfaces-config service and NTP service""" + """ + When mvrf is enabled, eth0 should be moved to mvrf; when it is disabled, + move it back to default vrf. Restarting the "interfaces-config" service + will recreate the /etc/network/interfaces file and restart the + "networking" service that takes care of the eth0 movement. + NTP service should also be restarted to rerun the NTP service with or + without "cgexec" accordingly. + """ cmd="service ntp stop" os.system (cmd) cmd="systemctl restart interfaces-config" @@ -910,12 +918,6 @@ def vrf_add_management_vrf(): click.echo("ManagementVRF is already Enabled.") return None config_db.mod_entry('MGMT_VRF_CONFIG',"vrf_global",{"mgmtVrfEnabled": "true"}) - # To move eth0 to management VRF, interfaces-config service has be to be - # restarted. /etc/network/interfaces file is recreated and the networking - # service is restarted which moves the eth0 to management VRF. - # NTP service should also be restarted to rerun the NTP service inside - # mvrf using cgexec. When the NTP service is restarted, service init - # file /etc/init.d/ntp takes care of using cgexec. mvrf_restart_interfaces_config_ntp() def vrf_delete_management_vrf(): @@ -928,11 +930,6 @@ def vrf_delete_management_vrf(): click.echo("ManagementVRF is already Disabled.") return None config_db.mod_entry('MGMT_VRF_CONFIG',"vrf_global",{"mgmtVrfEnabled": "false"}) - # To move back eth0 to default VRF, interfaces-config service has be to be - # restarted. /etc/network/interfaces file is recreated and the networking - # service is restarted which moves the eth0 to default VRF. - # NTP service should also be restarted to rerun the NTP service inside - # default VRF without cgexec. mvrf_restart_interfaces_config_ntp() # @@ -1194,9 +1191,16 @@ def _get_all_mgmtinterface_keys(): config_db.connect() return config_db.get_table('MGMT_INTERFACE').keys() - def restart_interfaces_config_ntp_config(): """Add or remove IP address""" + """ + Whenever the eth0 IP address is changed, restart the "interfaces-config" + service which regenerates the /etc/network/interfaces file and restarts + the networking service to make the new/null IP address effective for eth0. + "ntp-config" service should also be restarted based on the new + eth0 IP address since the ntp.conf (generated from ntp.conf.j2) is + made to listen on that particular eth0 IP address or reset it back. + """ cmd="systemctl restart interfaces-config" os.system (cmd) cmd="systemctl restart ntp-config" @@ -1249,12 +1253,9 @@ def add(ctx, interface_name, ip_addr, gw): # For loop runs for max 2 rows, once for IPv4 and once for IPv6. # No need to capture the exception since the ip_addr is already validated earlier ip_input = ipaddress.ip_interface(ip_addr) - current_ip = ip = ipaddress.ip_interface(key[1]) - if (ip_input.version == 6) and (current_ip.version == 6): - # If user has configured IPv6 address and the already available row is also IPv6, delete it here. - config_db.set_entry("MGMT_INTERFACE", ("eth0", key[1]), None) - elif (ip_input.version != 6) and (current_ip.version != 6): - # If user has configured IPv4 address and the already available row is also IPv4, delete it here. + current_ip = ipaddress.ip_interface(key[1]) + if (ip_input.version == current_ip.version): + # If user has configured IPv4/v6 address and the already available row is also IPv4/v6, delete it here. config_db.set_entry("MGMT_INTERFACE", ("eth0", key[1]), None) # Set the new row with new value @@ -1262,12 +1263,6 @@ def add(ctx, interface_name, ip_addr, gw): config_db.set_entry("MGMT_INTERFACE", (interface_name, ip_addr), {"NULL": "NULL"}) else: config_db.set_entry("MGMT_INTERFACE", (interface_name, ip_addr), {"gwaddr": gw}) - # Restart the interfaces-config service which regenerates the - # /etc/network/interfaces file and restarts the networking service - # to make the new IP address effective for eth0. - # "ntp-config" service should also be restarted based on the new - # eth0 IP address since the ntp.conf (generated from ntp.conf.j2) is - # made to listen on specific eth0 IP address. restart_interfaces_config_ntp_config() elif interface_name.startswith("PortChannel"): @@ -1315,12 +1310,6 @@ def remove(ctx, interface_name, ip_addr): if_table = "INTERFACE" elif interface_name == 'eth0': config_db.set_entry("MGMT_INTERFACE", (interface_name, ip_addr), None) - # Restart the interfaces-config service which regenerates the - # /etc/network/interfaces file and restarts the networking service - # to remove it from the system. - # "ntp-config" service should also be restarted since the ntp.conf - # (generated from ntp.conf.j2) had earlier been made to listen on - # previously configured eth0 IP address. Reset it back. restart_interfaces_config_ntp_config() elif interface_name.startswith("PortChannel"): if VLAN_SUB_INTERFACE_SEPARATOR in interface_name: diff --git a/show/main.py b/show/main.py index 28383ae6cd..b2f6c9f60d 100755 --- a/show/main.py +++ b/show/main.py @@ -440,12 +440,12 @@ def is_mgmt_vrf_enabled(ctx): p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) res = p.communicate() - if p.returncode == 0 : + if p.returncode == 0: p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) mvrf_dict = json.loads(p.stdout.read()) # if the mgmtVrfEnabled attribute is configured, check the value - # and print Enabled or Disabled accordingly. + # and return True accordingly. if 'mgmtVrfEnabled' in mvrf_dict['vrf_global']: if (mvrf_dict['vrf_global']['mgmtVrfEnabled'] == "true"): #ManagementVRF is enabled. Return True. @@ -463,7 +463,7 @@ def mgmt_vrf(ctx,routes): """Show management VRF attributes""" if is_mgmt_vrf_enabled(ctx) is False: - click.echo("\nKVSK:ManagementVRF : Disabled") + click.echo("\nManagementVRF : Disabled") return else: if routes is None: @@ -501,7 +501,7 @@ def address (): mgmt_ip_data = config_db.get_table('MGMT_INTERFACE') for key in natsorted(mgmt_ip_data.keys()): click.echo("Management IP address = {0}".format(key[1])) - click.echo("Management NetWork Default Gateway = {0}".format(mgmt_ip_data[key]['gwaddr'])) + click.echo("Management Network Default Gateway = {0}".format(mgmt_ip_data[key]['gwaddr'])) # # 'interfaces' group ("show interfaces ...") @@ -1643,21 +1643,9 @@ def bgp(verbose): def ntp(ctx, verbose): """Show NTP information""" ntpcmd = "ntpq -p -n" - if ctx.invoked_subcommand is None: - cmd = 'sonic-cfggen -d --var-json "MGMT_VRF_CONFIG"' - - p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - res = p.communicate() - if p.returncode == 0 : - p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - mvrf_dict = json.loads(p.stdout.read()) - - # if the mgmtVrfEnabled attribute is configured, check the value - # and print Enabled or Disabled accordingly. - if 'mgmtVrfEnabled' in mvrf_dict['vrf_global']: - if (mvrf_dict['vrf_global']['mgmtVrfEnabled'] == "true"): - #ManagementVRF is enabled. Call ntpq using cgexec - ntpcmd = "cgexec -g l3mdev:mgmt ntpq -p -n" + if is_mgmt_vrf_enabled(ctx) is True: + #ManagementVRF is enabled. Call ntpq using cgexec + ntpcmd = "cgexec -g l3mdev:mgmt ntpq -p -n" run_command(ntpcmd, display_cmd=verbose) From c4c0124e9f51688b4bce514d450bafaf05041228 Mon Sep 17 00:00:00 2001 From: Kannan KVS Date: Fri, 4 Oct 2019 01:11:25 -0700 Subject: [PATCH 08/10] renamed functions --- config/main.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/config/main.py b/config/main.py index 68fc7b4f27..f5ddaaceea 100755 --- a/config/main.py +++ b/config/main.py @@ -891,7 +891,7 @@ def del_vlan_member(ctx, vid, interface_name): db.set_entry('VLAN', vlan_name, vlan) db.set_entry('VLAN_MEMBER', (vlan_name, interface_name), None) -def mvrf_restart_interfaces_config_ntp(): +def mvrf_restart_services(): """Restart interfaces-config service and NTP service""" """ When mvrf is enabled, eth0 should be moved to mvrf; when it is disabled, @@ -918,7 +918,7 @@ def vrf_add_management_vrf(): click.echo("ManagementVRF is already Enabled.") return None config_db.mod_entry('MGMT_VRF_CONFIG',"vrf_global",{"mgmtVrfEnabled": "true"}) - mvrf_restart_interfaces_config_ntp() + mvrf_restart_services() def vrf_delete_management_vrf(): """Disable management vrf""" @@ -930,7 +930,7 @@ def vrf_delete_management_vrf(): click.echo("ManagementVRF is already Disabled.") return None config_db.mod_entry('MGMT_VRF_CONFIG',"vrf_global",{"mgmtVrfEnabled": "false"}) - mvrf_restart_interfaces_config_ntp() + mvrf_restart_services() # # 'vrf' group ('config vrf ...') @@ -1191,7 +1191,7 @@ def _get_all_mgmtinterface_keys(): config_db.connect() return config_db.get_table('MGMT_INTERFACE').keys() -def restart_interfaces_config_ntp_config(): +def eth0_ip_change_restart_services(): """Add or remove IP address""" """ Whenever the eth0 IP address is changed, restart the "interfaces-config" @@ -1263,7 +1263,7 @@ def add(ctx, interface_name, ip_addr, gw): config_db.set_entry("MGMT_INTERFACE", (interface_name, ip_addr), {"NULL": "NULL"}) else: config_db.set_entry("MGMT_INTERFACE", (interface_name, ip_addr), {"gwaddr": gw}) - restart_interfaces_config_ntp_config() + eth0_ip_change_restart_services() elif interface_name.startswith("PortChannel"): if VLAN_SUB_INTERFACE_SEPARATOR in interface_name: @@ -1310,7 +1310,7 @@ def remove(ctx, interface_name, ip_addr): if_table = "INTERFACE" elif interface_name == 'eth0': config_db.set_entry("MGMT_INTERFACE", (interface_name, ip_addr), None) - restart_interfaces_config_ntp_config() + eth0_ip_change_restart_services() elif interface_name.startswith("PortChannel"): if VLAN_SUB_INTERFACE_SEPARATOR in interface_name: config_db.set_entry("VLAN_SUB_INTERFACE", (interface_name, ip_addr), None) From f65c733ff85ac4ba488014763802c07bf0dc95dc Mon Sep 17 00:00:00 2001 From: Kannan KVS Date: Fri, 4 Oct 2019 09:41:27 -0700 Subject: [PATCH 09/10] renamed eth0_ip to mgmt_ip --- config/main.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config/main.py b/config/main.py index f5ddaaceea..9abd56a9c5 100755 --- a/config/main.py +++ b/config/main.py @@ -1191,7 +1191,7 @@ def _get_all_mgmtinterface_keys(): config_db.connect() return config_db.get_table('MGMT_INTERFACE').keys() -def eth0_ip_change_restart_services(): +def mgmt_ip_restart_services(): """Add or remove IP address""" """ Whenever the eth0 IP address is changed, restart the "interfaces-config" @@ -1263,7 +1263,7 @@ def add(ctx, interface_name, ip_addr, gw): config_db.set_entry("MGMT_INTERFACE", (interface_name, ip_addr), {"NULL": "NULL"}) else: config_db.set_entry("MGMT_INTERFACE", (interface_name, ip_addr), {"gwaddr": gw}) - eth0_ip_change_restart_services() + mgmt_ip_restart_services() elif interface_name.startswith("PortChannel"): if VLAN_SUB_INTERFACE_SEPARATOR in interface_name: @@ -1310,7 +1310,7 @@ def remove(ctx, interface_name, ip_addr): if_table = "INTERFACE" elif interface_name == 'eth0': config_db.set_entry("MGMT_INTERFACE", (interface_name, ip_addr), None) - eth0_ip_change_restart_services() + mgmt_ip_restart_services() elif interface_name.startswith("PortChannel"): if VLAN_SUB_INTERFACE_SEPARATOR in interface_name: config_db.set_entry("VLAN_SUB_INTERFACE", (interface_name, ip_addr), None) From ea811a5c172a8c321ee2711bbce7ee72590f6365 Mon Sep 17 00:00:00 2001 From: Kannan KVS Date: Fri, 4 Oct 2019 11:02:26 -0700 Subject: [PATCH 10/10] modified few comments for Docstring and remove unwanted import --- config/main.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/config/main.py b/config/main.py index 9abd56a9c5..bca80c95ae 100755 --- a/config/main.py +++ b/config/main.py @@ -6,8 +6,6 @@ import json import subprocess import netaddr -import logging -import logging.handlers import re import syslog @@ -892,7 +890,7 @@ def del_vlan_member(ctx, vid, interface_name): db.set_entry('VLAN_MEMBER', (vlan_name, interface_name), None) def mvrf_restart_services(): - """Restart interfaces-config service and NTP service""" + """Restart interfaces-config service and NTP service when mvrf is changed""" """ When mvrf is enabled, eth0 should be moved to mvrf; when it is disabled, move it back to default vrf. Restarting the "interfaces-config" service @@ -909,7 +907,7 @@ def mvrf_restart_services(): os.system (cmd) def vrf_add_management_vrf(): - """Enable management vrf""" + """Enable management vrf in config DB""" config_db = ConfigDBConnector() config_db.connect() @@ -921,7 +919,7 @@ def vrf_add_management_vrf(): mvrf_restart_services() def vrf_delete_management_vrf(): - """Disable management vrf""" + """Disable management vrf in config DB""" config_db = ConfigDBConnector() config_db.connect() @@ -945,7 +943,7 @@ def vrf(): @click.argument('vrfname', metavar='. Type mgmt for management VRF', required=True) @click.pass_context def vrf_add (ctx, vrfname): - """VRF ADD""" + """Create management VRF and move eth0 into it""" if vrfname == 'mgmt' or vrfname == 'management': vrf_add_management_vrf() else: @@ -955,7 +953,7 @@ def vrf_add (ctx, vrfname): @click.argument('vrfname', metavar='. Type mgmt for management VRF', required=False) @click.pass_context def vrf_del (ctx, vrfname): - """VRF Delete""" + """Delete management VRF and move back eth0 to default VRF""" if vrfname == 'mgmt' or vrfname == 'management': vrf_delete_management_vrf() else: @@ -1192,7 +1190,7 @@ def _get_all_mgmtinterface_keys(): return config_db.get_table('MGMT_INTERFACE').keys() def mgmt_ip_restart_services(): - """Add or remove IP address""" + """Restart the required services when mgmt inteface IP address is changed""" """ Whenever the eth0 IP address is changed, restart the "interfaces-config" service which regenerates the /etc/network/interfaces file and restarts