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.
Common functions for show CLI support on multi ASIC (sonic-net#999)
Common changes will be used to support SONiC CLIs for multi ASIC - New MultiAsic class to support not displaying of internal object - Common CLI options which needed for multi ASIC platforms - a new decorator to execute a function on all namespaces Signed-off-by: Arvindsrinivasan Lakshmi Narasimhan <arlakshm@microsoft.com>
- Loading branch information
Showing
2 changed files
with
147 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
#All the constant used in sonic-utilities | ||
|
||
DEFAULT_NAMESPACE = '' | ||
DISPLAY_ALL = 'all' | ||
DISPLAY_EXTERNAL = 'frontend' | ||
BGP_NEIGH_OBJ = 'BGP_NEIGH' | ||
PORT_CHANNEL_OBJ = 'PORT_CHANNEL' | ||
PORT_OBJ = 'PORT' | ||
|
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,138 @@ | ||
import argparse | ||
import functools | ||
|
||
import click | ||
from sonic_py_common import multi_asic | ||
from utilities_common import constants | ||
|
||
|
||
class MultiAsic(object): | ||
|
||
def __init__(self, display_option=constants.DISPLAY_ALL, | ||
namespace_option=None): | ||
self.namespace_option = namespace_option | ||
self.display_option = display_option | ||
self.current_namespace = None | ||
self.is_multi_asic = multi_asic.is_multi_asic() | ||
|
||
def is_object_internal(self, object_type, cli_object): | ||
''' | ||
The function checks if a CLI object is internal and returns true or false. | ||
Internal objects are port or portchannel which are connected to other | ||
ports or portchannels within a multi ASIC device. | ||
For single asic, this function is not applicable | ||
''' | ||
if object_type == constants.PORT_OBJ: | ||
return multi_asic.is_port_internal(cli_object) | ||
elif object_type == constants.PORT_CHANNEL_OBJ: | ||
return multi_asic.is_port_channel_internal(cli_object) | ||
elif object_type == constants.BGP_NEIGH_OBJ: | ||
return multi_asic.is_bgp_session_internal(cli_object) | ||
|
||
def skip_display(self, object_type, cli_object): | ||
''' | ||
The function determines if the passed cli_object has to be displayed or not. | ||
returns true if the display_option is external and the cli object is internal. | ||
returns false, if the cli option is all or if it the platform is single ASIC. | ||
''' | ||
if not self.is_multi_asic: | ||
return False | ||
if self.display_option == constants.DISPLAY_ALL: | ||
return False | ||
return self.is_object_internal(object_type, cli_object) | ||
|
||
def get_ns_list_based_on_options(self): | ||
ns_list = [] | ||
if not self.is_multi_asic: | ||
return [constants.DEFAULT_NAMESPACE] | ||
else: | ||
namespaces = multi_asic.get_all_namespaces() | ||
if self.namespace_option is None: | ||
if self.display_option == constants.DISPLAY_ALL: | ||
ns_list = namespaces['front_ns'] + namespaces['back_ns'] | ||
else: | ||
ns_list = namespaces['front_ns'] | ||
else: | ||
if self.namespace_option not in namespaces['front_ns'] and \ | ||
self.namespace_option not in namespaces['back_ns']: | ||
raise ValueError( | ||
'Unknown Namespace {}'.format(self.namespace_option)) | ||
ns_list = [self.namespace_option] | ||
return ns_list | ||
|
||
|
||
def multi_asic_ns_choices(): | ||
if not multi_asic.is_multi_asic(): | ||
return [constants.DEFAULT_NAMESPACE] | ||
choices = multi_asic.get_namespace_list() | ||
return choices | ||
|
||
|
||
def multi_asic_display_choices(): | ||
if not multi_asic.is_multi_asic(): | ||
return [constants.DISPLAY_ALL] | ||
else: | ||
return [constants.DISPLAY_ALL, constants.DISPLAY_EXTERNAL] | ||
|
||
|
||
def multi_asic_display_default_option(): | ||
if not multi_asic.is_multi_asic(): | ||
return constants.DISPLAY_ALL | ||
else: | ||
return constants.DISPLAY_EXTERNAL | ||
|
||
|
||
_multi_asic_click_options = [ | ||
click.option('--display', | ||
'-d', 'display', | ||
default=multi_asic_display_default_option(), | ||
show_default=True, | ||
type=click.Choice(multi_asic_display_choices()), | ||
help='Show internal interfaces'), | ||
click.option('--namespace', | ||
'-n', 'namespace', | ||
default=None, | ||
type=click.Choice(multi_asic_ns_choices()), | ||
show_default=True, | ||
help='Namespace name or all'), | ||
] | ||
|
||
|
||
def multi_asic_click_options(func): | ||
for option in reversed(_multi_asic_click_options): | ||
func = option(func) | ||
return func | ||
|
||
|
||
def run_on_multi_asic(func): | ||
''' | ||
This decorator is used on the CLI functions which needs to be | ||
run on all the namespaces in the multi ASIC platform | ||
The decorator loops through all the required namespaces, | ||
for every iteration, it connects to all the DBs and provides an handle | ||
to the wrapped function. | ||
''' | ||
@functools.wraps(func) | ||
def wrapped_run_on_all_asics(self, *args, **kwargs): | ||
ns_list = self.multi_asic.get_ns_list_based_on_options() | ||
for ns in ns_list: | ||
self.multi_asic.current_namespace = ns | ||
self.db = multi_asic.connect_to_all_dbs_for_ns(ns) | ||
self.config_db = multi_asic.connect_config_db_for_ns(ns) | ||
func(self, *args, **kwargs) | ||
return wrapped_run_on_all_asics | ||
|
||
|
||
def multi_asic_args(parser=None): | ||
if parser is None: | ||
parser = argparse.ArgumentParser( | ||
formatter_class=argparse.RawTextHelpFormatter) | ||
|
||
parser.add_argument('-d', '--display', default=constants.DISPLAY_EXTERNAL, | ||
help='Display all interfaces or only external interfaces') | ||
parser.add_argument('-n', '--namespace', default=None, | ||
help='Display interfaces for specific namespace') | ||
return parser |