Skip to content

Commit

Permalink
[show/config]: combine feature and container feature cli (sonic-net#1015
Browse files Browse the repository at this point in the history
)

merge container feature cli into feature cli

config command:
```
admin@vlab-01:~$ sudo config feature
Usage: config feature [OPTIONS] COMMAND [ARGS]...

  Modify configuration of features

Options:
  -?, -h, --help  Show this message and exit.

Commands:
  autorestart  Configure autorestart status for a feature
  state        Configure status of feature
```

show command:
```
admin@vlab-01:~$ show feature
Usage: show feature [OPTIONS] COMMAND [ARGS]...

  Show feature status

Options:
  -?, -h, --help  Show this message and exit.

Commands:
  autorestart  Show auto-restart status for a feature
  status       Show feature status
```

output:

```
admin@vlab-01:~$ show feature status
Feature     Status    AutoRestart
----------  --------  -------------
lldp        enabled   enabled
pmon        enabled   enabled
sflow       disabled  enabled
database    enabled   disabled
restapi     disabled  enabled
telemetry   enabled   enabled
snmp        enabled   enabled
bgp         enabled   enabled
radv        enabled   enabled
dhcp_relay  enabled   enabled
nat         enabled   enabled
teamd       enabled   enabled
syncd       enabled   enabled
swss        enabled   enabled
admin@vlab-01:~$ show feature autorestart
Feature     AutoRestart
----------  -------------
lldp        enabled
pmon        enabled
sflow       enabled
database    disabled
restapi     enabled
telemetry   enabled
snmp        enabled
bgp         enabled
radv        enabled
dhcp_relay  enabled
nat         enabled
teamd       enabled
syncd       enabled
swss        enabled
```

Signed-off-by: Guohan Lu <lguohan@gmail.com>
  • Loading branch information
lguohan authored Aug 3, 2020
1 parent c9d3550 commit 9700e45
Show file tree
Hide file tree
Showing 4 changed files with 356 additions and 120 deletions.
144 changes: 70 additions & 74 deletions config/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@
CFG_LOOPBACK_NAME_TOTAL_LEN_MAX = 11
CFG_LOOPBACK_ID_MAX_VAL = 999
CFG_LOOPBACK_NO="<0-999>"

asic_type = None
config_db = None

# ========================== Syslog wrappers ==========================

def log_debug(msg):
Expand Down Expand Up @@ -112,17 +116,6 @@ def get_command(self, ctx, cmd_name):

ctx.fail('Too many matches: %s' % ', '.join(sorted(matches)))


#
# Load asic_type for further use
#

try:
version_info = sonic_device_util.get_sonic_version_info()
asic_type = version_info['asic_type']
except (KeyError, TypeError):
raise click.Abort()

#
# Load breakout config file for Dynamic Port Breakout
#
Expand Down Expand Up @@ -552,7 +545,7 @@ def _is_neighbor_ipaddress(config_db, ipaddress):

def _get_all_neighbor_ipaddresses(config_db, ignore_local_hosts=False):
"""Returns list of strings containing IP addresses of all BGP neighbors
if the flag ignore_local_hosts is set to True, additional check to see if
if the flag ignore_local_hosts is set to True, additional check to see if
if the BGP neighbor AS number is same as local BGP AS number, if so ignore that neigbor.
"""
addrs = []
Expand Down Expand Up @@ -692,12 +685,12 @@ def _get_disabled_services_list():
log_warning("Feature is None")
continue

status = feature_table[feature_name]['status']
if not status:
log_warning("Status of feature '{}' is None".format(feature_name))
state = feature_table[feature_name]['state']
if not state:
log_warning("Enable state of feature '{}' is None".format(feature_name))
continue

if status == "disabled":
if state == "disabled":
disabled_services_list.append(feature_name)
else:
log_warning("Unable to retreive FEATURE table")
Expand Down Expand Up @@ -890,6 +883,19 @@ def validate_mirror_session_config(config_db, session_name, dst_port, src_port,
@click.group(cls=AbbreviationGroup, context_settings=CONTEXT_SETTINGS)
def config():
"""SONiC command line - 'config' command"""
#
# Load asic_type for further use
#
global asic_type

try:
version_info = sonic_device_util.get_sonic_version_info()
asic_type = version_info['asic_type']
except KeyError, TypeError:
raise click.Abort()

if asic_type == 'mellanox':
platform.add_command(mlnx.mlnx)

# Load the global config file database_global.json once.
SonicDBConfig.load_sonic_global_db_config()
Expand All @@ -899,6 +905,10 @@ def config():

SonicDBConfig.load_sonic_global_db_config()

global config_db

config_db = ConfigDBConnector()
config_db.connect()

config.add_command(aaa.aaa)
config.add_command(aaa.tacacs)
Expand Down Expand Up @@ -1007,7 +1017,7 @@ def load(filename, yes):
# if any of the config files in linux host OR namespace is not present, return
if not os.path.isfile(file):
click.echo("The config_db file {} doesn't exist".format(file))
return
return

if namespace is None:
command = "{} -j {} --write-to-db".format(SONIC_CFGGEN_PATH, file)
Expand Down Expand Up @@ -1225,7 +1235,7 @@ def load_minigraph(no_service_restart):

if os.path.isfile('/etc/sonic/acl.json'):
run_command("acl-loader update full /etc/sonic/acl.json", display_cmd=True)

# Write latest db version string into db
db_migrator='/usr/bin/db_migrator.py'
if os.path.isfile(db_migrator) and os.access(db_migrator, os.X_OK):
Expand All @@ -1235,7 +1245,7 @@ def load_minigraph(no_service_restart):
else:
cfggen_namespace_option = " -n {}".format(namespace)
run_command(db_migrator + ' -o set_version' + cfggen_namespace_option)

# We first run "systemctl reset-failed" to remove the "failed"
# status from all services before we attempt to restart them
if not no_service_restart:
Expand Down Expand Up @@ -1891,7 +1901,7 @@ def add_snmp_agent_address(ctx, agentip, port, vrf):
#Construct SNMP_AGENT_ADDRESS_CONFIG table key in the format ip|<port>|<vrf>
key = agentip+'|'
if port:
key = key+port
key = key+port
key = key+'|'
if vrf:
key = key+vrf
Expand All @@ -1912,7 +1922,7 @@ def del_snmp_agent_address(ctx, agentip, port, vrf):

key = agentip+'|'
if port:
key = key+port
key = key+port
key = key+'|'
if vrf:
key = key+vrf
Expand Down Expand Up @@ -2174,7 +2184,7 @@ def all(verbose):
config_db = ConfigDBConnector(use_unix_socket_path=True, namespace=namespace)
config_db.connect()
bgp_neighbor_ip_list = _get_all_neighbor_ipaddresses(config_db, ignore_local_hosts)
for ipaddress in bgp_neighbor_ip_list:
for ipaddress in bgp_neighbor_ip_list:
_change_bgp_session_status_by_addr(config_db, ipaddress, 'up', verbose)

# 'neighbor' subcommand
Expand Down Expand Up @@ -2463,7 +2473,7 @@ def breakout(ctx, interface_name, mode, verbose, force_remove_dependencies, load
sys.exit(0)

def _get_all_mgmtinterface_keys():
"""Returns list of strings containing mgmt interface keys
"""Returns list of strings containing mgmt interface keys
"""
config_db = ConfigDBConnector()
config_db.connect()
Expand Down Expand Up @@ -3191,9 +3201,9 @@ def priority(ctx, interface_name, priority, status):
interface_name = interface_alias_to_name(interface_name)
if interface_name is None:
ctx.fail("'interface_name' is None!")

run_command("pfc config priority {0} {1} {2}".format(status, interface_name, priority))

#
# 'platform' group ('config platform ...')
#
Expand All @@ -3202,9 +3212,6 @@ def priority(ctx, interface_name, priority, status):
def platform():
"""Platform-related configuration tasks"""

if asic_type == 'mellanox':
platform.add_command(mlnx.mlnx)

# 'firmware' subgroup ("config platform firmware ...")
@platform.group(cls=AbbreviationGroup)
def firmware():
Expand Down Expand Up @@ -3292,10 +3299,10 @@ def naming_mode_alias():
def is_loopback_name_valid(loopback_name):
"""Loopback name validation
"""

if loopback_name[:CFG_LOOPBACK_PREFIX_LEN] != CFG_LOOPBACK_PREFIX :
return False
if (loopback_name[CFG_LOOPBACK_PREFIX_LEN:].isdigit() is False or
if (loopback_name[CFG_LOOPBACK_PREFIX_LEN:].isdigit() is False or
int(loopback_name[CFG_LOOPBACK_PREFIX_LEN:]) > CFG_LOOPBACK_ID_MAX_VAL) :
return False
if len(loopback_name) > CFG_LOOPBACK_NAME_TOTAL_LEN_MAX:
Expand Down Expand Up @@ -3462,7 +3469,7 @@ def add_ntp_server(ctx, ntp_ip_address):
if ntp_ip_address in ntp_servers:
click.echo("NTP server {} is already configured".format(ntp_ip_address))
return
else:
else:
db.set_entry('NTP_SERVER', ntp_ip_address, {'NULL': 'NULL'})
click.echo("NTP server {} added to configuration".format(ntp_ip_address))
try:
Expand All @@ -3483,7 +3490,7 @@ def del_ntp_server(ctx, ntp_ip_address):
if ntp_ip_address in ntp_servers:
db.set_entry('NTP_SERVER', '{}'.format(ntp_ip_address), None)
click.echo("NTP server {} removed from configuration".format(ntp_ip_address))
else:
else:
ctx.fail("NTP server {} is not configured.".format(ntp_ip_address))
try:
click.echo("Restarting ntp-config service...")
Expand Down Expand Up @@ -3770,58 +3777,47 @@ def delete(ctx):
config_db.set_entry('SFLOW', 'global', sflow_tbl['global'])

#
# 'feature' command ('config feature name state')
#
@config.command('feature')
@click.argument('name', metavar='<feature-name>', required=True)
@click.argument('state', metavar='<feature-state>', required=True, type=click.Choice(["enabled", "disabled"]))
def feature_status(name, state):
""" Configure status of feature"""
config_db = ConfigDBConnector()
config_db.connect()
status_data = config_db.get_entry('FEATURE', name)

if not status_data:
click.echo(" Feature '{}' doesn't exist".format(name))
return

config_db.mod_entry('FEATURE', name, {'status': state})

#
# 'container' group ('config container ...')
# 'feature' group ('config feature ...')
#
@config.group(cls=AbbreviationGroup, name='container', invoke_without_command=False)
def container():
"""Modify configuration of containers"""
@config.group(cls=AbbreviationGroup, name='feature', invoke_without_command=False)
def feature():
"""Modify configuration of features"""
pass

#
# 'feature' group ('config container feature ...')
# 'state' command ('config feature state ...')
#
@container.group(cls=AbbreviationGroup, name='feature', invoke_without_command=False)
def feature():
"""Modify configuration of container features"""
pass
@feature.command('state', short_help="Enable/disable a feature")
@click.argument('name', metavar='<feature-name>', required=True)
@click.argument('state', metavar='<state>', required=True, type=click.Choice(["enabled", "disabled"]))
def feature_state(name, state):
"""Enable/disable a feature"""
state_data = config_db.get_entry('FEATURE', name)

if not state_data:
click.echo("Feature '{}' doesn't exist".format(name))
sys.exit(1)

config_db.mod_entry('FEATURE', name, {'state': state})

#
# 'autorestart' subcommand ('config container feature autorestart ...')
# 'autorestart' command ('config feature autorestart ...')
#
@feature.command(name='autorestart', short_help="Configure the status of autorestart feature for specific container")
@click.argument('container_name', metavar='<container_name>', required=True)
@click.argument('autorestart_status', metavar='<autorestart_status>', required=True, type=click.Choice(["enabled", "disabled"]))
def autorestart(container_name, autorestart_status):
config_db = ConfigDBConnector()
config_db.connect()
container_feature_table = config_db.get_table('CONTAINER_FEATURE')
if not container_feature_table:
click.echo("Unable to retrieve container feature table from Config DB.")
return
@feature.command(name='autorestart', short_help="Enable/disable autosrestart of a feature")
@click.argument('name', metavar='<feature-name>', required=True)
@click.argument('autorestart', metavar='<autorestart>', required=True, type=click.Choice(["enabled", "disabled"]))
def feature_autorestart(name, autorestart):
"""Enable/disable autorestart of a feature"""
feature_table = config_db.get_table('FEATURE')
if not feature_table:
click.echo("Unable to retrieve feature table from Config DB.")
sys.exit(1)

if not container_feature_table.has_key(container_name):
click.echo("Unable to retrieve features for container '{}'".format(container_name))
return
if not feature_table.has_key(name):
click.echo("Unable to retrieve feature '{}'".format(name))
sys.exit(1)

config_db.mod_entry('CONTAINER_FEATURE', container_name, {'auto_restart': autorestart_status})
config_db.mod_entry('FEATURE', name, {'auto_restart': autorestart})

if __name__ == '__main__':
config()
Loading

0 comments on commit 9700e45

Please sign in to comment.