diff --git a/CLI/actioner/sonic_cli_if.py b/CLI/actioner/sonic_cli_if.py index 46a0a6b33d..dffb8d4796 100644 --- a/CLI/actioner/sonic_cli_if.py +++ b/CLI/actioner/sonic_cli_if.py @@ -21,7 +21,8 @@ from rpipe_utils import pipestr import cli_client as cc from netaddr import * -from scripts.render_cli import show_cli_output +from scripts.render_cli import show_cli_output, show_cli_rendered_output +import os import syslog import traceback from natsort import natsorted @@ -2104,6 +2105,18 @@ def invoke_api(func, args=[]): show_args.append(view_key_str) sonic_cli_show_config.run("show_view", show_args) return + elif func == "showrun_if_range": + if not args[0] in [ 'configure-if', 'configure-lag', 'configure-vlan' ]: + return + iflistStr = args[1].split("=")[1] + iflist = iflistStr.rstrip().split(",") + viewid = 'views=' + args[0] + showrun_list = [] + for intf in iflist: + showrun_list.append(('show_view', viewid, 'view_keys="name={}"'.format(intf))) + rcfgall = sonic_cli_show_config.showconfig_views_to_buffer(showrun_list) + show_cli_rendered_output(rcfgall) + return return api.cli_not_implemented(func) @@ -2274,7 +2287,7 @@ def run(func, args): elif func == "get_sonic_port_table": show_cli_output(args[0], response) return - elif func == "showrun": + elif func == "showrun" or func == "showrun_if_range": return if response.ok(): diff --git a/CLI/actioner/sonic_cli_show_config.py b/CLI/actioner/sonic_cli_show_config.py index 82712c03b5..d852219861 100644 --- a/CLI/actioner/sonic_cli_show_config.py +++ b/CLI/actioner/sonic_cli_show_config.py @@ -1017,9 +1017,14 @@ def parse_command_line(command_line): cli_view.view_cmd_list.append(command_line) -def render_cli_config(view_name="", view_keys={}): +def render_cli_config(view_name="", view_keys={}, cacheAllKeys=False): global CMDS_STRING, CMDS_VIEW, CMDS_VIEW_CHANGED, CMDS_SAVE_BUFFER - context = {"view_name": view_name, "view_keys": view_keys} + + if cacheAllKeys: + # force DB_cache to get all table keys + context = {"view_name": view_name, "view_keys": None} + else: + context = {"view_name": view_name, "view_keys": view_keys} # Call application # set cache @@ -1027,6 +1032,8 @@ def render_cli_config(view_name="", view_keys={}): if view_name: for module_cb in module_startup_cb.get(view_name, []): mod_name = inspect.getmodule(module_cb).__name__ + if cacheAllKeys and DB_Cache.get(mod_name) != None: + continue DB_Cache[mod_name] = {} module_cb(context, DB_Cache[mod_name]) @@ -1098,7 +1105,7 @@ def read_cli_format_file(format_file): parse_command_line(command) -def show_views(func, args=[]): +def show_views(func, args=[], cacheAllKeys=False): showrun_log(logging.DEBUG, "args {}", args) @@ -1137,7 +1144,7 @@ def show_views(func, args=[]): showrun_log(logging.DEBUG, "view-keys {}", viewKV) for view_name in views: - if render_cli_config(view_name, viewKV): + if render_cli_config(view_name, viewKV, cacheAllKeys=cacheAllKeys): # write() returns True if terminated break @@ -1161,8 +1168,27 @@ def showconfig_views_to_buffer(viewlist): if not viewlist: render_cli_config() else: + # check repeating (ie. roughly first 5) show_view for the same viewid + # (used by show config within interface ranges with different keys) + # If repeating, force DB_cache to get all table keys once and use this + # cache to read each key, and not do multiple separate key fetches from DB. + sameviewid = False + viewid0 = viewlist[0][1] + vcnt = 0 + for to_show in viewlist: + if 'show_view' == to_show[0] and viewid0 == to_show[1]: + vcnt += 1 + if vcnt > 5: + sameviewid = True + break + else: + break for to_show in viewlist: - show_views(to_show[0], to_show[1:]) + if sameviewid and (('show_view' != to_show[0]) or + (viewid0 != to_show[1])): + # if nolonger same viewid (it changes) then turn off + sameviewid = False + show_views(to_show[0], to_show[1:], cacheAllKeys=sameviewid) output = CMDS_SAVE_BUFFER diff --git a/CLI/actioner/sonic_cli_vrf.py b/CLI/actioner/sonic_cli_vrf.py index b0bd8fd595..b98215fb95 100644 --- a/CLI/actioner/sonic_cli_vrf.py +++ b/CLI/actioner/sonic_cli_vrf.py @@ -22,7 +22,7 @@ import os from rpipe_utils import pipestr import cli_client as cc -from scripts.render_cli import show_cli_output, write +from scripts.render_cli import show_cli_output, show_cli_rendered_output from sonic_cli_show_config import showconfig_views_to_buffer import sonic_intf_utils as ifutils import collections @@ -430,10 +430,7 @@ def run(func, args): gotSep = False else: vrfcfgs += "\n" + cfgl - full_cmd = os.getenv("USER_COMMAND", None) - if full_cmd is not None: - pipestr().write(full_cmd.split()) - write(vrfcfgs.replace("\t", "\n")) + show_cli_rendered_output(vrfcfgs.replace("\t", "\n")) else: api_response = invoke_api(func, args) diff --git a/CLI/clitree/cli-xml/interface.xml b/CLI/clitree/cli-xml/interface.xml index 9acbeac95d..8360b007cb 100644 --- a/CLI/clitree/cli-xml/interface.xml +++ b/CLI/clitree/cli-xml/interface.xml @@ -2270,6 +2270,7 @@ limitations under the License. + @@ -2310,6 +2311,7 @@ limitations under the License. + @@ -2332,6 +2334,7 @@ limitations under the License. + + + + sonic_cli_if showrun_if_range configure-arg2 iflist=arg1 + + + diff --git a/CLI/renderer/scripts/render_cli.py b/CLI/renderer/scripts/render_cli.py index 2ac0332d08..ef471df37d 100755 --- a/CLI/renderer/scripts/render_cli.py +++ b/CLI/renderer/scripts/render_cli.py @@ -261,6 +261,20 @@ def datetimeformat_ticks(timestring): return ret +def show_cli_rendered_output(output_str, continuation=False, trim=True): + # Show already rendered output string (no jinja2). + if output_str is None: + return 0 + + full_cmd = os.getenv("USER_COMMAND", None) + if full_cmd is not None: + pipestr().write(full_cmd.split()) + + ret = write(output_str, continuation=continuation, trim=trim) + sys.stdout.flush() + return ret + + def register_custom_filters(jinja2_env, filters): if jinja2_env is not None: # Add generic custom filters