diff --git a/doc/Command-Reference.md b/doc/Command-Reference.md index 0709b6d4f1..d518824721 100644 --- a/doc/Command-Reference.md +++ b/doc/Command-Reference.md @@ -1113,26 +1113,30 @@ This command displays information for all the interfaces for the transceiver req - Example (Display performance monitoring info of SFP transceiver connected to Ethernet100): ``` - admin@sonic:~$ show interfaces transceiver pm Ethernet100 + admin@sonic:~$ show interfaces transceiver pm current 60sec Ethernet100 + Wed Jul 31 17:13:51 UTC 2023 + PM window: 60sec Ethernet100: + PM window start time: Mon Jul 31 17:12:49 UTC 2023 + PM window end time: Mon Jul 31 17:13:50 UTC 2023 Parameter Unit Min Avg Max Threshold Threshold Threshold Threshold Threshold Threshold - High High Crossing Low Low Crossing - Alarm Warning Alert-High Alarm Warning Alert-Low + High High Crossing Low Low Crossing + Alarm Warning Alert-High Alarm Warning Alert-Low --------------- ------ -------- -------- -------- ----------- ----------- ------------ ----------- ----------- ----------- - Tx Power dBm -8.22 -8.23 -8.24 -5.0 -6.0 False -16.99 -16.003 False - Rx Total Power dBm -10.61 -10.62 -10.62 2.0 0.0 False -21.0 -18.0 False - Rx Signal Power dBm -40.0 0.0 40.0 13.0 10.0 True -18.0 -15.0 True - CD-short link ps/nm 0.0 0.0 0.0 1000.0 500.0 False -1000.0 -500.0 False - PDL dB 0.5 0.6 0.6 4.0 4.0 False 0.0 0.0 False - OSNR dB 36.5 36.5 36.5 99.0 99.0 False 0.0 0.0 False - eSNR dB 30.5 30.5 30.5 99.0 99.0 False 0.0 0.0 False - CFO MHz 54.0 70.0 121.0 3800.0 3800.0 False -3800.0 -3800.0 False - DGD ps 5.37 5.56 5.81 7.0 7.0 False 0.0 0.0 False - SOPMD ps^2 0.0 0.0 0.0 655.35 655.35 False 0.0 0.0 False - SOP ROC krad/s 1.0 1.0 2.0 N/A N/A N/A N/A N/A N/A - Pre-FEC BER N/A 4.58E-04 4.66E-04 5.76E-04 1.25E-02 1.10E-02 0.0 0.0 0.0 0.0 - Post-FEC BER N/A 0.0 0.0 0.0 1000.0 1.0 False 0.0 0.0 False - EVM % 100.0 100.0 100.0 N/A N/A N/A N/A N/A N/A + Tx Power dBm -8.19 -8.17 -8.15 -5 -6 False -16.99 -16.003 False + Rx Total Power dBm -8.61 -8.56 -8.51 2 0 False -21 -18 False + Rx Signal Power dBm -9.12 -9.09 -9.07 13 10 False -18 -15 False + CD-short link ps/nm -2 -1 0 1000 500 False -1000 -500 False + PDL dB 0.3 0.3 0.4 4 4 False 0 0 False + OSNR dB 36.4 36.4 36.4 99 99 False 0 0 False + eSNR dB 17.9 18 18.2 99 99 False 0 0 False + CFO MHz -776 -659 -546 3800 3800 False -3800 -3800 False + DGD ps 2 2 2 7 7 False 0 0 False + SOPMD ps^2 26 34 44 655.35 655.35 False 0 0 False + SOP ROC krad/s 0 0 0 N/A N/A N/A N/A N/A N/A + Pre-FEC BER N/A 5.37E-04 5.55E-04 5.80E-04 1.25E-02 1.10E-02 False 0 0 False + Post-FEC BER N/A 0 0 0 1.00E+03 1.00E+00 False 0 0 False + EVM % 0 0 0 N/A N/A N/A N/A N/A N/A ``` - Example (Display status info of SFP transceiver connected to Ethernet100): diff --git a/scripts/sfpshow b/scripts/sfpshow index 85e8d8a1f1..0d2f4e99cf 100755 --- a/scripts/sfpshow +++ b/scripts/sfpshow @@ -10,7 +10,9 @@ import ast import os import re import sys +import time from typing import Dict +from datetime import datetime import click from natsort import natsorted @@ -237,6 +239,9 @@ ZR_PM_INFO_MAP = { 'EVM': ['%', 'evm'] } +ZR_PM_NOT_AVAILABLE_STR = \ +'Transceiver performance monitoring data not available for the requested window' + ZR_PM_NOT_APPLICABLE_STR = 'Transceiver performance monitoring not applicable' QSFP_STATUS_NOT_APPLICABLE_STR = 'Transceiver status info not applicable' @@ -262,7 +267,12 @@ def display_invalid_intf_status(intf_name): click.echo(output) class SFPShow(object): - def __init__(self, intf_name, namespace_option, dump_dom=False): + PM_WINDOW_NUM_IN_DB = {'60sec': 15, '15min': 12, '24hrs': 2} + PM_WINDOW_START_INDEX_IN_DB = {'60sec': 1, '15min': 16, '24hrs': 28} + PM_TABLE_NAME_IN_DB = 'TRANSCEIVER_PM_WINDOW_STATS' + + def __init__(self, intf_name, namespace_option, dump_dom=False, + pm_window_size=None, pm_window_index=None): super(SFPShow, self).__init__() self.db = None self.intf_name = intf_name @@ -272,6 +282,8 @@ class SFPShow(object): self.intf_pm: Dict[str, str] = {} self.intf_status: Dict[str, str] = {} self.multi_asic = multi_asic_util.MultiAsic(namespace_option=namespace_option) + self.pm_window_size = pm_window_size + self.pm_window_index = pm_window_index # Convert dict values to cli output string def format_dict_value_to_string(self, sorted_key_table, @@ -490,19 +502,106 @@ class SFPShow(object): else: return pm_prefix.replace('_', '') + def beautify_number_with_max_decimal_places(self, number, max_num_decimal_places): + ''' + Format a number to have no more than the specified number of decimal places. + + Args: + - number: A float or integer to be formatted. + - max_num_decimal_places: An integer representing the maximum number of decimal places allowed. + + Returns: + - A string representation of the formatted number. + + Example: + - beautify_number_with_max_decimal_places(3.14159, 3) returns "3.142" + ''' + # Convert the number to a string and split it into whole and decimal + # parts + str_number = str(number).split('.') + + # Check if the number has a decimal part + if len(str_number) == 1: + # If no decimal part, return the number as-is + return str_number + + decimal_part = str_number[1] + if decimal_part == '0': + # If the decimal part is zero, return the whole part only + return str_number[0] + + # Determine the number of decimal places to use based on the length of + # the decimal part + actual_num_decimal_places = len(decimal_part) + num_decimal_places = min(actual_num_decimal_places, max_num_decimal_places) + + # Apply the formatting + format_specifier = "{:." + str(num_decimal_places) + "f}" + return format_specifier.format(number) + def beautify_pm_field(self, prefix, field): if field is None: return 'N/A' - elif prefix in {'prefec_ber'}: - return "{:.2E}".format(field) if field != 0 else '0.0' + elif prefix in {'prefec_ber', 'uncorr_frames'} and isinstance(field, float): + return "{:.2E}".format(field) if field != 0 else '0' + elif isinstance(field, float): + return self.beautify_number_with_max_decimal_places(field, 3) else: return str(field) - def convert_interface_sfp_pm_to_cli_output_string(self, state_db, interface_name): - sfp_pm_dict = state_db.get_all( - self.db.STATE_DB, 'TRANSCEIVER_PM|{}'.format(interface_name)) - sfp_threshold_dict = state_db.get_all( - state_db.STATE_DB, 'TRANSCEIVER_DOM_THRESHOLD|{}'.format(interface_name)) + def beautify_pm_timestamp(self, secs_since_epoch): + if secs_since_epoch is None: + return 'N/A' + dt_object = datetime.utcfromtimestamp(secs_since_epoch) + formatted_time = dt_object.strftime("%a %b %d %H:%M:%S UTC %Y") + return formatted_time + + def get_pm_dict_for_specified_window(self, db, interface_name, + window_size, window_index): + """ + Get PM dict for specified window size and index + + Returns: + dict: PM dict for specified window size and index. + return None if PM data is not applicable for this interface; + return {} if PM data is applicable for this interface, + but not avaiable for this specified window. + """ + pm_windows_dict = db.get_all( + db.STATE_DB, '{}|{}'.format(self.PM_TABLE_NAME_IN_DB, interface_name)) + if not pm_windows_dict: + return None + window_num = self.PM_WINDOW_NUM_IN_DB[window_size] + start_win_idx_in_db = self.PM_WINDOW_START_INDEX_IN_DB[window_size] + end_win_idx_in_db = start_win_idx_in_db + window_num - 1 + pm_windows_for_win_size = [] + cur_win_idx = -1 + for i in range(start_win_idx_in_db, end_win_idx_in_db + 1): + win_name = 'window' + str(i) + if (win_name not in pm_windows_dict or + pm_windows_dict[win_name] == 'N/A'): + pm_dict = {} + else: + # Convert string to dict + pm_dict = ast.literal_eval(pm_windows_dict[win_name]) + pm_windows_for_win_size.append(pm_dict) + if (pm_dict is not None and + 'pm_win_current' in pm_dict and + pm_dict['pm_win_current'] == 'true'): + cur_win_idx = i + if cur_win_idx == -1: + return {} + return pm_windows_for_win_size[(cur_win_idx - + start_win_idx_in_db - + window_index + + window_num) % window_num] + + def convert_interface_sfp_pm_to_cli_output_string(self, db, interface_name, + window_size, window_index): + sfp_pm_dict = self.get_pm_dict_for_specified_window( + db, interface_name, window_size, window_index) + sfp_threshold_dict = db.get_all( + db.STATE_DB, 'TRANSCEIVER_DOM_THRESHOLD|{}'.format(interface_name)) table = [] indent_num = 4 indent = ' ' * indent_num @@ -539,10 +638,18 @@ class SFPShow(object): output += tabulate(table, ZR_PM_HEADER, disable_numparse=True).replace('\n', '\n' + indent) - output += '\n' + start_timestamp = self.beautify_pm_timestamp( + float(sfp_pm_dict.get('pm_win_start_time', None))) + end_timestamp = self.beautify_pm_timestamp( + float(sfp_pm_dict.get('pm_win_end_time', None))) + start_timestamp_output = '\n{}PM window start time: {}'.format(indent, start_timestamp) + end_timestamp_output = '\n{}PM window end time: {}'.format(indent, end_timestamp) + output = start_timestamp_output + end_timestamp_output + output + elif sfp_pm_dict is None: + output = ZR_PM_NOT_APPLICABLE_STR else: - output = ZR_PM_NOT_APPLICABLE_STR + '\n' - return output + output = ZR_PM_NOT_AVAILABLE_STR + return output + '\n' @multi_asic_util.run_on_multi_asic def get_eeprom(self): @@ -587,14 +694,14 @@ class SFPShow(object): def get_pm(self): if self.intf_name is not None: self.intf_pm[self.intf_name] = self.convert_interface_sfp_pm_to_cli_output_string( - self.db, self.intf_name) + self.db, self.intf_name, self.pm_window_size, self.pm_window_index) else: port_table_keys = self.db.keys(self.db.APPL_DB, "PORT_TABLE:*") for i in port_table_keys: interface = re.split(':', i, maxsplit=1)[-1].strip() if interface and interface.startswith(front_panel_prefix()) and not interface.startswith((backplane_prefix(), inband_prefix(), recirc_prefix())): self.intf_pm[interface] = self.convert_interface_sfp_pm_to_cli_output_string( - self.db, interface) + self.db, interface, self.pm_window_size, self.pm_window_index) @multi_asic_util.run_on_multi_asic def get_status(self): @@ -618,8 +725,10 @@ class SFPShow(object): click.echo(tabulate(sorted_port_table, header)) def display_pm(self): - click.echo( - "\n".join([f"{k}: {v}" for k, v in natsorted(self.intf_pm.items())])) + output = self.beautify_pm_timestamp(time.time()) + '\n' + output += 'PM window: {}\n'.format(self.pm_window_size) + output += "\n".join([f"{k}: {v}" for k, v in natsorted(self.intf_pm.items())]) + click.echo(output) def display_status(self): click.echo( @@ -689,10 +798,26 @@ def presence(port, namespace): # 'pm' subcommand -@cli.command() -@click.option('-p', '--port', metavar='', help="Display SFP PM for port only") +@cli.command(help="Display performance monitoring information") +@click.option('-s', '--window_size', + type=click.Choice(['60sec', '15min', '24hrs']), + required=True, + help="Display data for the specified window size") +@click.option('-i', '--window_index', + type=int, + required=True, + help="Display data for the specified window index") +@click.option('-p', '--port', metavar='', help="Display data for port only") @click.option('-n', '--namespace', default=None, help="Display interfaces for specific namespace") -def pm(port, namespace): +def pm(window_size, window_index, port, namespace): + # Validate window_index based on window_size + if window_size == '60sec' and not 0 <= window_index <= 14: + raise click.BadArgumentUsage("For 60sec window size, window_index should be between 0 and 14.") + elif window_size == '15min' and not 0 <= window_index <= 11: + raise click.BadArgumentUsage("For 15min window size, window_index should be between 0 and 11.") + elif window_size == '24hrs' and not 0 <= window_index <= 1: + raise click.BadArgumentUsage("For 24hrs window size, window_index should be between 0 and 1.") + if port and multi_asic.is_multi_asic() and namespace is None: try: namespace = multi_asic.get_namespace_for_port(port) @@ -700,7 +825,7 @@ def pm(port, namespace): display_invalid_intf_pm(port) sys.exit(1) - sfp = SFPShow(port, namespace) + sfp = SFPShow(port, namespace, False, window_size, window_index) sfp.get_pm() sfp.display_pm() diff --git a/show/interfaces/__init__.py b/show/interfaces/__init__.py index a5a3734664..0f2cf4b517 100644 --- a/show/interfaces/__init__.py +++ b/show/interfaces/__init__.py @@ -446,16 +446,25 @@ def eeprom(interfacename, dump_dom, namespace, verbose): clicommon.run_command(cmd, display_cmd=verbose) -@transceiver.command() -@click.argument('interfacename', required=False) -@click.option('--namespace', '-n', 'namespace', default=None, show_default=True, - type=click.Choice(multi_asic_util.multi_asic_ns_choices()), help='Namespace name or all') -@click.option('--verbose', is_flag=True, help="Enable verbose output") -def pm(interfacename, namespace, verbose): +@transceiver.group(help="Display performance monitoring information") +def pm(): """Show interface transceiver performance monitoring information""" + pass - ctx = click.get_current_context() - +def cli_pm_helper(window_size, window_index, interfacename, namespace, verbose, ctx): + """ + Helper function for pm subcommand + + Parameters: + interfacename (str): Name of the port to retrieve PM information for. + namespace (str): Name of the namespace in which the port resides. + window_size (str): Size of the window to consider for PM information. + window_index (int): Index of the window to consider for PM information. + Starts from 0, which typically denotes the most + recent window. + verbose (bool): Whether to display verbose output. + ctx (click.Context): Click context object. + """ cmd = ['sfpshow', 'pm'] if interfacename is not None: @@ -467,8 +476,48 @@ def pm(interfacename, namespace, verbose): if namespace is not None: cmd += ['-n', str(namespace)] + cmd += ['-s', window_size, '-i', str(window_index)] clicommon.run_command(cmd, display_cmd=verbose) +@pm.command(help="Show PM stats of progressing window for the given window size") +@click.argument('window_size', type=click.Choice(['60sec', '15min', '24hrs'])) +@click.argument('interfacename', required=False) +@click.option('--namespace', '-n', 'namespace', default=None, show_default=True, + type=click.Choice(multi_asic_util.multi_asic_ns_choices()), + help='Namespace name or all') +@click.option('--verbose', is_flag=True, help="Enable verbose output") +def current(window_size, interfacename, namespace, verbose): + """Show interface transceiver pm current subcommand""" + ctx = click.get_current_context() + cli_pm_helper(window_size, 0, interfacename, namespace, verbose, ctx) + +@pm.group(help="Show PM stats of a given window number for the given window size") +@click.argument('window_size', type=click.Choice(['60sec', '15min', '24hrs'])) +def history(window_size): + """Show interface transceiver pm history subcommand """ + ctx = click.get_current_context() + ctx.obj = {'window_size': window_size} + +@history.command(help="PM window number; 60sec: (1 to 14), 15min: (1 to 11), 24hrs: (1)") +@click.argument('window_index', type=int) +@click.argument('interfacename', required=False) +@click.option('--namespace', '-n', 'namespace', default=None, show_default=True, + type=click.Choice(multi_asic_util.multi_asic_ns_choices()), + help='Namespace name or all') +@click.option('--verbose', is_flag=True, help="Enable verbose output") +def window(window_index, interfacename, namespace, verbose): + """Show interface transceiver pm history window subcommand""" + ctx = click.get_current_context() + window_size = ctx.obj['window_size'] + if window_size == '60sec' and not 1 <= window_index <= 14: + raise click.BadArgumentUsage("For 60sec window size, window_index should be between 1 and 14.") + elif window_size == '15min' and not 1 <= window_index <= 11: + raise click.BadArgumentUsage("For 15min window size, window_index should be between 1 and 11.") + elif window_size == '24hrs' and window_index != 1: + raise click.BadArgumentUsage("For 24hrs window size, window_index should be 1.") + cli_pm_helper(window_size, window_index, interfacename, namespace, verbose, ctx) + + @transceiver.command('status') # 'status' is the actual sub-command name under 'transceiver' command @click.argument('interfacename', required=False) @click.option('--namespace', '-n', 'namespace', default=None, show_default=True, diff --git a/tests/mock_tables/state_db.json b/tests/mock_tables/state_db.json index b622705be1..e8a277cca2 100644 --- a/tests/mock_tables/state_db.json +++ b/tests/mock_tables/state_db.json @@ -329,49 +329,36 @@ "rxsigpowerhighwarning": "10.0", "rxsigpowerlowwarning": "-15.0" }, - "TRANSCEIVER_PM|Ethernet44":{ - "prefec_ber_avg": "0.00046578129838019075", - "prefec_ber_min": "0.00045750117895600233", - "prefec_ber_max": "0.000575639239547097", - "uncorr_frames_avg": "0.0", - "uncorr_frames_min": "0.0", - "uncorr_frames_max": "0.0", - "cd_avg": "0", - "cd_min": "0", - "cd_max": "0", - "dgd_avg": "5.56", - "dgd_min": "5.37", - "dgd_max": "5.81", - "sopmd_avg": "0.0", - "sopmd_min": "0.0", - "sopmd_max": "0.0", - "pdl_avg": "0.6", - "pdl_min": "0.5", - "pdl_max": "0.6", - "osnr_avg": "36.5", - "osnr_min": "36.5", - "osnr_max": "36.5", - "esnr_avg": "30.5", - "esnr_min": "30.5", - "esnr_max": "30.5", - "cfo_avg": "70", - "cfo_min": "54", - "cfo_max": "121", - "evm_avg": "100.0", - "evm_min": "100.0", - "evm_max": "100.0", - "soproc_avg": "1", - "soproc_min": "1", - "soproc_max": "2", - "tx_power_avg": "-8.23", - "tx_power_min": "-8.22", - "tx_power_max": "-8.24", - "rx_tot_power_avg": "-10.62", - "rx_tot_power_min": "-10.61", - "rx_tot_power_max": "-10.62", - "rx_sig_power_avg": "0", - "rx_sig_power_min": "-40", - "rx_sig_power_max": "40" + "TRANSCEIVER_PM_WINDOW_STATS|Ethernet44":{ + "window1": "{'pm_win_end_time': '1690822962.5852993', 'prefec_ber_avg': '0.000548070353733367', 'prefec_ber_min': '0.000542574355738485', 'prefec_ber_max': '0.0005597849519218932', 'uncorr_frames_avg': '0.0', 'uncorr_frames_min': '0.0', 'uncorr_frames_max': '0.0', 'cd_avg': '-1', 'cd_min': '-3', 'cd_max': '-1', 'dgd_avg': '2.0', 'dgd_min': '2.0', 'dgd_max': '2.0', 'sopmd_avg': '33.0', 'sopmd_min': '26.0', 'sopmd_max': '42.0', 'pdl_avg': '0.3', 'pdl_min': '0.2', 'pdl_max': '0.4', 'osnr_avg': '36.4', 'osnr_min': '36.4', 'osnr_max': '36.4', 'esnr_avg': '18.1', 'esnr_min': '18.0', 'esnr_max': '18.2', 'cfo_avg': '-659', 'cfo_min': '-732', 'cfo_max': '-584', 'evm_avg': '0.0', 'evm_min': '0.0', 'evm_max': '0.0', 'soproc_avg': '0', 'soproc_min': '0', 'soproc_max': '0', 'tx_power_avg': '-8.16', 'tx_power_min': '-8.18', 'tx_power_max': '-8.15', 'rx_tot_power_avg': '-8.56', 'rx_tot_power_min': '-8.6', 'rx_tot_power_max': '-8.52', 'rx_sig_power_avg': '-9.09', 'rx_sig_power_min': '-9.1', 'rx_sig_power_max': '-9.07', 'pm_win_current': 'false', 'pm_win_start_time': '1690822901.7858174'}", + "window2": "{'pm_win_end_time': '1690823023.3755682', 'prefec_ber_avg': '0.0005490729807171806', 'prefec_ber_min': '0.0005398401672651294', 'prefec_ber_max': '0.0005670807444342315', 'uncorr_frames_avg': '0.0', 'uncorr_frames_min': '0.0', 'uncorr_frames_max': '0.0', 'cd_avg': '-1', 'cd_min': '-3', 'cd_max': '0', 'dgd_avg': '2.0', 'dgd_min': '2.0', 'dgd_max': '2.0', 'sopmd_avg': '34.0', 'sopmd_min': '25.0', 'sopmd_max': '46.0', 'pdl_avg': '0.3', 'pdl_min': '0.3', 'pdl_max': '0.4', 'osnr_avg': '36.4', 'osnr_min': '36.4', 'osnr_max': '36.4', 'esnr_avg': '18.1', 'esnr_min': '18.0', 'esnr_max': '18.2', 'cfo_avg': '-662', 'cfo_min': '-757', 'cfo_max': '-571', 'evm_avg': '0.0', 'evm_min': '0.0', 'evm_max': '0.0', 'soproc_avg': '0', 'soproc_min': '0', 'soproc_max': '0', 'tx_power_avg': '-8.17', 'tx_power_min': '-8.18', 'tx_power_max': '-8.16', 'rx_tot_power_avg': '-8.55', 'rx_tot_power_min': '-8.6', 'rx_tot_power_max': '-8.51', 'rx_sig_power_avg': '-9.08', 'rx_sig_power_min': '-9.1', 'rx_sig_power_max': '-9.07', 'pm_win_current': 'false', 'pm_win_start_time': '1690822962.5852993'}", + "window3": "{'pm_win_end_time': '1690823084.1438315', 'prefec_ber_avg': '0.000551609691224808', 'prefec_ber_min': '0.0005420884108310196', 'prefec_ber_max': '0.0005623290684454906', 'uncorr_frames_avg': '0.0', 'uncorr_frames_min': '0.0', 'uncorr_frames_max': '0.0', 'cd_avg': '-1', 'cd_min': '-2', 'cd_max': '0', 'dgd_avg': '2.0', 'dgd_min': '2.0', 'dgd_max': '2.0', 'sopmd_avg': '34.0', 'sopmd_min': '26.0', 'sopmd_max': '50.0', 'pdl_avg': '0.3', 'pdl_min': '0.3', 'pdl_max': '0.4', 'osnr_avg': '36.4', 'osnr_min': '36.4', 'osnr_max': '36.4', 'esnr_avg': '18.1', 'esnr_min': '18.0', 'esnr_max': '18.2', 'cfo_avg': '-664', 'cfo_min': '-752', 'cfo_max': '-572', 'evm_avg': '0.0', 'evm_min': '0.0', 'evm_max': '0.0', 'soproc_avg': '0', 'soproc_min': '0', 'soproc_max': '0', 'tx_power_avg': '-8.17', 'tx_power_min': '-8.18', 'tx_power_max': '-8.16', 'rx_tot_power_avg': '-8.54', 'rx_tot_power_min': '-8.59', 'rx_tot_power_max': '-8.5', 'rx_sig_power_avg': '-9.07', 'rx_sig_power_min': '-9.09', 'rx_sig_power_max': '-9.05', 'pm_win_current': 'false', 'pm_win_start_time': '1690823023.3755682'}", + "window4": "{'pm_win_end_time': '1690823144.929027', 'prefec_ber_avg': '0.0005460809980718409', 'prefec_ber_min': '0.0005364384698061918', 'prefec_ber_max': '0.0005600176429893303', 'uncorr_frames_avg': '0.0', 'uncorr_frames_min': '0.0', 'uncorr_frames_max': '0.0', 'cd_avg': '-2', 'cd_min': '-4', 'cd_max': '-1', 'dgd_avg': '2.0', 'dgd_min': '2.0', 'dgd_max': '2.0', 'sopmd_avg': '32.0', 'sopmd_min': '22.0', 'sopmd_max': '42.0', 'pdl_avg': '0.3', 'pdl_min': '0.3', 'pdl_max': '0.4', 'osnr_avg': '36.4', 'osnr_min': '36.4', 'osnr_max': '36.4', 'esnr_avg': '18.1', 'esnr_min': '17.9', 'esnr_max': '18.2', 'cfo_avg': '-661', 'cfo_min': '-754', 'cfo_max': '-565', 'evm_avg': '0.0', 'evm_min': '0.0', 'evm_max': '0.0', 'soproc_avg': '0', 'soproc_min': '0', 'soproc_max': '0', 'tx_power_avg': '-8.17', 'tx_power_min': '-8.18', 'tx_power_max': '-8.15', 'rx_tot_power_avg': '-8.55', 'rx_tot_power_min': '-8.59', 'rx_tot_power_max': '-8.49', 'rx_sig_power_avg': '-9.07', 'rx_sig_power_min': '-9.09', 'rx_sig_power_max': '-9.05', 'pm_win_current': 'false', 'pm_win_start_time': '1690823084.1438315'}", + "window5": "{'pm_win_end_time': '1690823204.9854808', 'prefec_ber_avg': '0.0005467649343493634', 'prefec_ber_min': '0.0005330388455605484', 'prefec_ber_max': '0.0005671307840324009', 'uncorr_frames_avg': '0.0', 'uncorr_frames_min': '0.0', 'uncorr_frames_max': '0.0', 'cd_avg': '-2', 'cd_min': '-4', 'cd_max': '0', 'dgd_avg': '1.0', 'dgd_min': '1.0', 'dgd_max': '2.0', 'sopmd_avg': '36.0', 'sopmd_min': '27.0', 'sopmd_max': '59.0', 'pdl_avg': '0.3', 'pdl_min': '0.3', 'pdl_max': '0.4', 'osnr_avg': '36.4', 'osnr_min': '36.4', 'osnr_max': '36.4', 'esnr_avg': '18.1', 'esnr_min': '18.0', 'esnr_max': '18.2', 'cfo_avg': '-661', 'cfo_min': '-755', 'cfo_max': '-563', 'evm_avg': '0.0', 'evm_min': '0.0', 'evm_max': '0.0', 'soproc_avg': '0', 'soproc_min': '0', 'soproc_max': '0', 'tx_power_avg': '-8.17', 'tx_power_min': '-8.18', 'tx_power_max': '-8.15', 'rx_tot_power_avg': '-8.55', 'rx_tot_power_min': '-8.6', 'rx_tot_power_max': '-8.5', 'rx_sig_power_avg': '-9.08', 'rx_sig_power_min': '-9.1', 'rx_sig_power_max': '-9.06', 'pm_win_current': 'false', 'pm_win_start_time': '1690823144.929027'}", + "window6": "{'pm_win_end_time': '1690823265.795125', 'prefec_ber_avg': '0.0005617032728485978', 'prefec_ber_min': '0.0005574800554008606', 'prefec_ber_max': '0.0005693705950362027', 'uncorr_frames_avg': '0.0', 'uncorr_frames_min': '0.0', 'uncorr_frames_max': '0.0', 'cd_avg': '-2', 'cd_min': '-3', 'cd_max': '-1', 'dgd_avg': '2.0', 'dgd_min': '2.0', 'dgd_max': '2.0', 'sopmd_avg': '34.0', 'sopmd_min': '26.0', 'sopmd_max': '45.0', 'pdl_avg': '0.3', 'pdl_min': '0.3', 'pdl_max': '0.4', 'osnr_avg': '36.4', 'osnr_min': '36.4', 'osnr_max': '36.4', 'esnr_avg': '18.0', 'esnr_min': '18.0', 'esnr_max': '18.1', 'cfo_avg': '-662', 'cfo_min': '-755', 'cfo_max': '-576', 'evm_avg': '0.0', 'evm_min': '0.0', 'evm_max': '0.0', 'soproc_avg': '0', 'soproc_min': '0', 'soproc_max': '0', 'tx_power_avg': '-8.17', 'tx_power_min': '-8.18', 'tx_power_max': '-8.16', 'rx_tot_power_avg': '-8.57', 'rx_tot_power_min': '-8.62', 'rx_tot_power_max': '-8.55', 'rx_sig_power_avg': '-9.1', 'rx_sig_power_min': '-9.12', 'rx_sig_power_max': '-9.08', 'pm_win_current': 'false', 'pm_win_start_time': '1690823204.9854808'}", + "window7": "{'pm_win_end_time': '1690823326.622992', 'prefec_ber_avg': '0.000558112513751316', 'prefec_ber_min': '0.0005377171299644129', 'prefec_ber_max': '0.0005903322622027038', 'uncorr_frames_avg': '0.0', 'uncorr_frames_min': '0.0', 'uncorr_frames_max': '0.0', 'cd_avg': '-1', 'cd_min': '-3', 'cd_max': '0', 'dgd_avg': '2.0', 'dgd_min': '2.0', 'dgd_max': '2.0', 'sopmd_avg': '34.0', 'sopmd_min': '23.0', 'sopmd_max': '45.0', 'pdl_avg': '0.3', 'pdl_min': '0.3', 'pdl_max': '0.4', 'osnr_avg': '36.4', 'osnr_min': '36.4', 'osnr_max': '36.4', 'esnr_avg': '18.1', 'esnr_min': '17.9', 'esnr_max': '18.2', 'cfo_avg': '-657', 'cfo_min': '-753', 'cfo_max': '-557', 'evm_avg': '0.0', 'evm_min': '0.0', 'evm_max': '0.0', 'soproc_avg': '0', 'soproc_min': '0', 'soproc_max': '0', 'tx_power_avg': '-8.15', 'tx_power_min': '-8.17', 'tx_power_max': '-8.12', 'rx_tot_power_avg': '-8.59', 'rx_tot_power_min': '-8.66', 'rx_tot_power_max': '-8.55', 'rx_sig_power_avg': '-9.1', 'rx_sig_power_min': '-9.12', 'rx_sig_power_max': '-9.07', 'pm_win_current': 'false', 'pm_win_start_time': '1690823265.795125'}", + "window8": "{'pm_win_end_time': '1690823387.3946505', 'prefec_ber_avg': '0.0005695416961796929', 'prefec_ber_min': '0.0005528711741763882', 'prefec_ber_max': '0.0005903292147787306', 'uncorr_frames_avg': '0.0', 'uncorr_frames_min': '0.0', 'uncorr_frames_max': '0.0', 'cd_avg': '-2', 'cd_min': '-4', 'cd_max': '0', 'dgd_avg': '2.0', 'dgd_min': '2.0', 'dgd_max': '2.0', 'sopmd_avg': '34.0', 'sopmd_min': '26.0', 'sopmd_max': '53.0', 'pdl_avg': '0.3', 'pdl_min': '0.3', 'pdl_max': '0.4', 'osnr_avg': '36.4', 'osnr_min': '36.4', 'osnr_max': '36.4', 'esnr_avg': '18.0', 'esnr_min': '17.9', 'esnr_max': '18.1', 'cfo_avg': '-664', 'cfo_min': '-762', 'cfo_max': '-561', 'evm_avg': '0.0', 'evm_min': '0.0', 'evm_max': '0.0', 'soproc_avg': '0', 'soproc_min': '0', 'soproc_max': '0', 'tx_power_avg': '-8.11', 'tx_power_min': '-8.12', 'tx_power_max': '-8.09', 'rx_tot_power_avg': '-8.59', 'rx_tot_power_min': '-8.64', 'rx_tot_power_max': '-8.54', 'rx_sig_power_avg': '-9.03', 'rx_sig_power_min': '-9.06', 'rx_sig_power_max': '-9.01', 'pm_win_current': 'false', 'pm_win_start_time': '1690823326.622992'}", + "window9": "{'pm_win_end_time': '1690823448.175453', 'prefec_ber_avg': '0.000557183891723572', 'prefec_ber_min': '0.0005411534959718172', 'prefec_ber_max': '0.0005796007580802109', 'uncorr_frames_avg': '0.0', 'uncorr_frames_min': '0.0', 'uncorr_frames_max': '0.0', 'cd_avg': '-1', 'cd_min': '-4', 'cd_max': '0', 'dgd_avg': '2.0', 'dgd_min': '2.0', 'dgd_max': '2.0', 'sopmd_avg': '33.0', 'sopmd_min': '26.0', 'sopmd_max': '45.0', 'pdl_avg': '0.3', 'pdl_min': '0.3', 'pdl_max': '0.4', 'osnr_avg': '36.4', 'osnr_min': '36.4', 'osnr_max': '36.4', 'esnr_avg': '18.1', 'esnr_min': '17.9', 'esnr_max': '18.3', 'cfo_avg': '-662', 'cfo_min': '-760', 'cfo_max': '-543', 'evm_avg': '0.0', 'evm_min': '0.0', 'evm_max': '0.0', 'soproc_avg': '0', 'soproc_min': '0', 'soproc_max': '0', 'tx_power_avg': '-8.12', 'tx_power_min': '-8.13', 'tx_power_max': '-8.1', 'rx_tot_power_avg': '-8.58', 'rx_tot_power_min': '-8.64', 'rx_tot_power_max': '-8.54', 'rx_sig_power_avg': '-9.03', 'rx_sig_power_min': '-9.05', 'rx_sig_power_max': '-9.0', 'pm_win_current': 'false', 'pm_win_start_time': '1690823387.3946505'}", + "window10": "{'pm_win_end_time': '1690823508.9491587', 'prefec_ber_avg': '0.0005522093254315777', 'prefec_ber_min': '0.0005306165155543086', 'prefec_ber_max': '0.0005642566298575693', 'uncorr_frames_avg': '0.0', 'uncorr_frames_min': '0.0', 'uncorr_frames_max': '0.0', 'cd_avg': '-1', 'cd_min': '-3', 'cd_max': '0', 'dgd_avg': '2.0', 'dgd_min': '2.0', 'dgd_max': '2.0', 'sopmd_avg': '34.0', 'sopmd_min': '25.0', 'sopmd_max': '46.0', 'pdl_avg': '0.3', 'pdl_min': '0.3', 'pdl_max': '0.4', 'osnr_avg': '36.4', 'osnr_min': '36.4', 'osnr_max': '36.4', 'esnr_avg': '18.1', 'esnr_min': '18.0', 'esnr_max': '18.3', 'cfo_avg': '-658', 'cfo_min': '-761', 'cfo_max': '-560', 'evm_avg': '0.0', 'evm_min': '0.0', 'evm_max': '0.0', 'soproc_avg': '0', 'soproc_min': '0', 'soproc_max': '0', 'tx_power_avg': '-8.15', 'tx_power_min': '-8.17', 'tx_power_max': '-8.12', 'rx_tot_power_avg': '-8.6', 'rx_tot_power_min': '-8.65', 'rx_tot_power_max': '-8.56', 'rx_sig_power_avg': '-9.11', 'rx_sig_power_min': '-9.14', 'rx_sig_power_max': '-9.08', 'pm_win_current': 'false', 'pm_win_start_time': '1690823448.175453'}", + "window11": "{'pm_win_end_time': '1690823569.7866094', 'prefec_ber_avg': '0.0005494577328078859', 'prefec_ber_min': '0.000530020737552282', 'prefec_ber_max': '0.0005823412098783816', 'uncorr_frames_avg': '0.0', 'uncorr_frames_min': '0.0', 'uncorr_frames_max': '0.0', 'cd_avg': '0', 'cd_min': '-2', 'cd_max': '2', 'dgd_avg': '2.0', 'dgd_min': '2.0', 'dgd_max': '2.0', 'sopmd_avg': '34.0', 'sopmd_min': '26.0', 'sopmd_max': '42.0', 'pdl_avg': '0.3', 'pdl_min': '0.3', 'pdl_max': '0.4', 'osnr_avg': '36.4', 'osnr_min': '36.4', 'osnr_max': '36.4', 'esnr_avg': '18.1', 'esnr_min': '17.9', 'esnr_max': '18.2', 'cfo_avg': '-660', 'cfo_min': '-768', 'cfo_max': '-561', 'evm_avg': '0.0', 'evm_min': '0.0', 'evm_max': '0.0', 'soproc_avg': '0', 'soproc_min': '0', 'soproc_max': '0', 'tx_power_avg': '-8.16', 'tx_power_min': '-8.17', 'tx_power_max': '-8.15', 'rx_tot_power_avg': '-8.6', 'rx_tot_power_min': '-8.66', 'rx_tot_power_max': '-8.53', 'rx_sig_power_avg': '-9.12', 'rx_sig_power_min': '-9.15', 'rx_sig_power_max': '-9.07', 'pm_win_current': 'false', 'pm_win_start_time': '1690823508.9491587'}", + "window12": "{'pm_win_end_time': '1690823630.6387875', 'prefec_ber_avg': '0.0005548573092147051', 'prefec_ber_min': '0.0005370189698676633', 'prefec_ber_max': '0.0005803686232873935', 'uncorr_frames_avg': '0.0', 'uncorr_frames_min': '0.0', 'uncorr_frames_max': '0.0', 'cd_avg': '-1', 'cd_min': '-2', 'cd_max': '0', 'dgd_avg': '2.0', 'dgd_min': '2.0', 'dgd_max': '2.0', 'sopmd_avg': '34.0', 'sopmd_min': '26.0', 'sopmd_max': '44.0', 'pdl_avg': '0.3', 'pdl_min': '0.3', 'pdl_max': '0.4', 'osnr_avg': '36.4', 'osnr_min': '36.4', 'osnr_max': '36.4', 'esnr_avg': '18.0', 'esnr_min': '17.9', 'esnr_max': '18.2', 'cfo_avg': '-659', 'cfo_min': '-776', 'cfo_max': '-546', 'evm_avg': '0.0', 'evm_min': '0.0', 'evm_max': '0.0', 'soproc_avg': '0', 'soproc_min': '0', 'soproc_max': '0', 'tx_power_avg': '-8.17', 'tx_power_min': '-8.19', 'tx_power_max': '-8.15', 'rx_tot_power_avg': '-8.56', 'rx_tot_power_min': '-8.61', 'rx_tot_power_max': '-8.51', 'rx_sig_power_avg': '-9.09', 'rx_sig_power_min': '-9.12', 'rx_sig_power_max': '-9.07', 'pm_win_current': 'true', 'pm_win_start_time': '1690823569.7866094'}", + "window13": "{'pm_win_end_time': '1690822780.6406388', 'prefec_ber_avg': '0.0005569325357743887', 'prefec_ber_min': '0.0005410772623474288', 'prefec_ber_max': '0.000578569502155946', 'uncorr_frames_avg': '0.0', 'uncorr_frames_min': '0.0', 'uncorr_frames_max': '0.0', 'cd_avg': '-2', 'cd_min': '-4', 'cd_max': '-2', 'dgd_avg': '2.0', 'dgd_min': '2.0', 'dgd_max': '2.0', 'sopmd_avg': '35.0', 'sopmd_min': '24.0', 'sopmd_max': '52.0', 'pdl_avg': '0.3', 'pdl_min': '0.3', 'pdl_max': '0.4', 'osnr_avg': '36.4', 'osnr_min': '36.4', 'osnr_max': '36.4', 'esnr_avg': '18.1', 'esnr_min': '17.9', 'esnr_max': '18.2', 'cfo_avg': '-663', 'cfo_min': '-757', 'cfo_max': '-589', 'evm_avg': '0.0', 'evm_min': '0.0', 'evm_max': '0.0', 'soproc_avg': '0', 'soproc_min': '0', 'soproc_max': '0', 'tx_power_avg': '-8.17', 'tx_power_min': '-8.18', 'tx_power_max': '-8.15', 'rx_tot_power_avg': '-8.56', 'rx_tot_power_min': '-8.62', 'rx_tot_power_max': '-8.51', 'rx_sig_power_avg': '-9.09', 'rx_sig_power_min': '-9.12', 'rx_sig_power_max': '-9.06', 'pm_win_current': 'false', 'pm_win_start_time': '1690822719.8197284'}", + "window14": "{'pm_win_end_time': '1690822841.476784', 'prefec_ber_avg': '0.0005582178456202325', 'prefec_ber_min': '0.0005497676881490136', 'prefec_ber_max': '0.0005644590942403557', 'uncorr_frames_avg': '0.0', 'uncorr_frames_min': '0.0', 'uncorr_frames_max': '0.0', 'cd_avg': '-2', 'cd_min': '-3', 'cd_max': '-1', 'dgd_avg': '2.0', 'dgd_min': '2.0', 'dgd_max': '2.0', 'sopmd_avg': '31.0', 'sopmd_min': '26.0', 'sopmd_max': '40.0', 'pdl_avg': '0.3', 'pdl_min': '0.2', 'pdl_max': '0.3', 'osnr_avg': '36.4', 'osnr_min': '36.4', 'osnr_max': '36.4', 'esnr_avg': '18.0', 'esnr_min': '18.0', 'esnr_max': '18.1', 'cfo_avg': '-660', 'cfo_min': '-743', 'cfo_max': '-574', 'evm_avg': '0.0', 'evm_min': '0.0', 'evm_max': '0.0', 'soproc_avg': '0', 'soproc_min': '0', 'soproc_max': '0', 'tx_power_avg': '-8.16', 'tx_power_min': '-8.17', 'tx_power_max': '-8.15', 'rx_tot_power_avg': '-8.58', 'rx_tot_power_min': '-8.62', 'rx_tot_power_max': '-8.55', 'rx_sig_power_avg': '-9.1', 'rx_sig_power_min': '-9.11', 'rx_sig_power_max': '-9.08', 'pm_win_current': 'false', 'pm_win_start_time': '1690822780.6406388'}", + "window15": "{'pm_win_end_time': '1690822901.7858174', 'prefec_ber_avg': '0.0005490888025131974', 'prefec_ber_min': '0.0005350611103256851', 'prefec_ber_max': '0.000567247658264438', 'uncorr_frames_avg': '0.0', 'uncorr_frames_min': '0.0', 'uncorr_frames_max': '0.0', 'cd_avg': '-2', 'cd_min': '-4', 'cd_max': '-1', 'dgd_avg': '2.0', 'dgd_min': '2.0', 'dgd_max': '2.0', 'sopmd_avg': '33.0', 'sopmd_min': '23.0', 'sopmd_max': '45.0', 'pdl_avg': '0.3', 'pdl_min': '0.3', 'pdl_max': '0.4', 'osnr_avg': '36.4', 'osnr_min': '36.4', 'osnr_max': '36.4', 'esnr_avg': '18.1', 'esnr_min': '17.9', 'esnr_max': '18.2', 'cfo_avg': '-664', 'cfo_min': '-747', 'cfo_max': '-574', 'evm_avg': '0.0', 'evm_min': '0.0', 'evm_max': '0.0', 'soproc_avg': '0', 'soproc_min': '0', 'soproc_max': '0', 'tx_power_avg': '-8.16', 'tx_power_min': '-8.18', 'tx_power_max': '-8.15', 'rx_tot_power_avg': '-8.56', 'rx_tot_power_min': '-8.61', 'rx_tot_power_max': '-8.5', 'rx_sig_power_avg': '-9.08', 'rx_sig_power_min': '-9.11', 'rx_sig_power_max': '-9.07', 'pm_win_current': 'false', 'pm_win_start_time': '1690822841.476784'}", + "window16": "{'prefec_ber_avg': 0.000574758736774799, 'prefec_ber_min': 0.0005563780924479431, 'prefec_ber_max': 0.0006146760530794246, 'uncorr_frames_avg': 0.0, 'uncorr_frames_min': 0.0, 'uncorr_frames_max': 0.0, 'cd_avg': -1.998779296875, 'cd_min': -5.0, 'cd_max': 1.0, 'dgd_avg': 2.0, 'dgd_min': 2.0, 'dgd_max': 2.0, 'sopmd_avg': 34.16009521484375, 'sopmd_min': 22.0, 'sopmd_max': 53.0, 'pdl_avg': 0.3, 'pdl_min': 0.2, 'pdl_max': 0.4, 'osnr_avg': 36.4, 'osnr_min': 36.4, 'osnr_max': 36.4, 'esnr_avg': 18.005474853515626, 'esnr_min': 17.9, 'esnr_max': 18.3, 'cfo_avg': -667.95263671875, 'cfo_min': -788.0, 'cfo_max': -550.0, 'evm_avg': 0.0, 'evm_min': 0.0, 'evm_max': 0.0, 'soproc_avg': 0.0, 'soproc_min': 0.0, 'soproc_max': 0.0, 'tx_power_avg': -8.1125146484375, 'tx_power_min': -8.14, 'tx_power_max': -8.1, 'rx_tot_power_avg': -8.625844726562502, 'rx_tot_power_min': -8.69, 'rx_tot_power_max': -8.56, 'rx_sig_power_avg': -9.083184814453126, 'rx_sig_power_min': -9.12, 'rx_sig_power_max': -9.05, 'pm_win_end_time': '1690814524.5551326', 'pm_win_start_time': '1690813615.06098', 'pm_win_current': 'false'}", + "window17": "{'prefec_ber_avg': 0.000610004597547906, 'prefec_ber_min': 0.0005673958565312257, 'prefec_ber_max': 0.0006521827211881103, 'uncorr_frames_avg': 0.0, 'uncorr_frames_min': 0.0, 'uncorr_frames_max': 0.0, 'cd_avg': -1.61480712890625, 'cd_min': -5.0, 'cd_max': 1.0, 'dgd_avg': 1.9998779296875, 'dgd_min': 1.0, 'dgd_max': 2.0, 'sopmd_avg': 33.04058837890625, 'sopmd_min': 21.0, 'sopmd_max': 54.0, 'pdl_avg': 0.30018920898437496, 'pdl_min': 0.2, 'pdl_max': 0.4, 'osnr_avg': 36.4, 'osnr_min': 36.4, 'osnr_max': 36.4, 'esnr_avg': 18.000006103515624, 'esnr_min': 17.8, 'esnr_max': 18.2, 'cfo_avg': -671.9801635742188, 'cfo_min': -786.0, 'cfo_max': -565.0, 'evm_avg': 0.0, 'evm_min': 0.0, 'evm_max': 0.0, 'soproc_avg': 0.0, 'soproc_min': 0.0, 'soproc_max': 0.0, 'tx_power_avg': -8.106870727539063, 'tx_power_min': -8.13, 'tx_power_max': -8.09, 'rx_tot_power_avg': -8.608399658203124, 'rx_tot_power_min': -8.68, 'rx_tot_power_max': -8.56, 'rx_sig_power_avg': -9.070253295898437, 'rx_sig_power_min': -9.1, 'rx_sig_power_max': -9.04, 'pm_win_end_time': '1690815434.8638942', 'pm_win_start_time': '1690814524.5551326', 'pm_win_current': 'false'}", + "window18": "{'prefec_ber_avg': 0.0005871845268972655, 'prefec_ber_min': 0.0005764593455379774, 'prefec_ber_max': 0.0006388098297567807, 'uncorr_frames_avg': 0.0, 'uncorr_frames_min': 0.0, 'uncorr_frames_max': 0.0, 'cd_avg': -1.265380859375, 'cd_min': -5.0, 'cd_max': 0.0, 'dgd_avg': 1.7490234375, 'dgd_min': 1.0, 'dgd_max': 2.0, 'sopmd_avg': 33.60064697265625, 'sopmd_min': 24.0, 'sopmd_max': 53.0, 'pdl_avg': 0.30156249999999996, 'pdl_min': 0.2, 'pdl_max': 0.4, 'osnr_avg': 36.4, 'osnr_min': 36.4, 'osnr_max': 36.4, 'esnr_avg': 18.050384521484375, 'esnr_min': 17.8, 'esnr_max': 18.2, 'cfo_avg': -670.5070190429688, 'cfo_min': -752.0, 'cfo_max': -579.0, 'evm_avg': 0.0, 'evm_min': 0.0, 'evm_max': 0.0, 'soproc_avg': 0.0, 'soproc_min': 0.0, 'soproc_max': 0.0, 'tx_power_avg': -8.10552734375, 'tx_power_min': -8.12, 'tx_power_max': -8.08, 'rx_tot_power_avg': -8.631520385742188, 'rx_tot_power_min': -8.68, 'rx_tot_power_max': -8.57, 'rx_sig_power_avg': -9.082770385742187, 'rx_sig_power_min': -9.11, 'rx_sig_power_max': -9.05, 'pm_win_end_time': '1690816344.4574778', 'pm_win_start_time': '1690815434.8638942', 'pm_win_current': 'false'}", + "window19": "{'prefec_ber_avg': 0.0005794682154044914, 'prefec_ber_min': 0.0005605294557151076, 'prefec_ber_max': 0.0006061797504489041, 'uncorr_frames_avg': 0.0, 'uncorr_frames_min': 0.0, 'uncorr_frames_max': 0.0, 'cd_avg': -0.8017578125, 'cd_min': -4.0, 'cd_max': 2.0, 'dgd_avg': 1.99981689453125, 'dgd_min': 1.0, 'dgd_max': 2.0, 'sopmd_avg': 33.51287841796875, 'sopmd_min': 24.0, 'sopmd_max': 57.0, 'pdl_avg': 0.3, 'pdl_min': 0.2, 'pdl_max': 0.5, 'osnr_avg': 36.4, 'osnr_min': 36.4, 'osnr_max': 36.4, 'esnr_avg': 18.038092041015624, 'esnr_min': 17.9, 'esnr_max': 18.3, 'cfo_avg': -667.9934692382812, 'cfo_min': -791.0, 'cfo_max': -562.0, 'evm_avg': 0.0, 'evm_min': 0.0, 'evm_max': 0.0, 'soproc_avg': 0.0, 'soproc_min': 0.0, 'soproc_max': 0.0, 'tx_power_avg': -8.111309204101563, 'tx_power_min': -8.13, 'tx_power_max': -8.09, 'rx_tot_power_avg': -8.624464721679686, 'rx_tot_power_min': -8.68, 'rx_tot_power_max': -8.57, 'rx_sig_power_avg': -9.08374755859375, 'rx_sig_power_min': -9.11, 'rx_sig_power_max': -9.05, 'pm_win_end_time': '1690817254.0749803', 'pm_win_start_time': '1690816344.4574778', 'pm_win_current': 'false'}", + "window20": "{'prefec_ber_avg': 0.0005697987386091452, 'prefec_ber_min': 0.0005576783719892889, 'prefec_ber_max': 0.0006109256492026531, 'uncorr_frames_avg': 0.0, 'uncorr_frames_min': 0.0, 'uncorr_frames_max': 0.0, 'cd_avg': -1.44403076171875, 'cd_min': -4.0, 'cd_max': 2.0, 'dgd_avg': 1.96875, 'dgd_min': 1.0, 'dgd_max': 2.0, 'sopmd_avg': 34.124267578125, 'sopmd_min': 22.0, 'sopmd_max': 59.0, 'pdl_avg': 0.3, 'pdl_min': 0.2, 'pdl_max': 0.4, 'osnr_avg': 36.4, 'osnr_min': 36.4, 'osnr_max': 36.4, 'esnr_avg': 18.01331787109375, 'esnr_min': 17.9, 'esnr_max': 18.2, 'cfo_avg': -670.490478515625, 'cfo_min': -790.0, 'cfo_max': -553.0, 'evm_avg': 0.0, 'evm_min': 0.0, 'evm_max': 0.0, 'soproc_avg': 0.0, 'soproc_min': 0.0, 'soproc_max': 0.0, 'tx_power_avg': -8.113789672851562, 'tx_power_min': -8.13, 'tx_power_max': -8.09, 'rx_tot_power_avg': -8.62999938964844, 'rx_tot_power_min': -8.69, 'rx_tot_power_max': -8.56, 'rx_sig_power_avg': -9.087481079101563, 'rx_sig_power_min': -9.11, 'rx_sig_power_max': -9.06, 'pm_win_end_time': '1690818163.9258842', 'pm_win_start_time': '1690817254.0749803', 'pm_win_current': 'false'}", + "window21": "{'prefec_ber_avg': 0.0005793179652138064, 'prefec_ber_min': 0.0005505202086509793, 'prefec_ber_max': 0.0006047684079962505, 'uncorr_frames_avg': 0.0, 'uncorr_frames_min': 0.0, 'uncorr_frames_max': 0.0, 'cd_avg': -1.30279541015625, 'cd_min': -4.0, 'cd_max': 1.0, 'dgd_avg': 1.999267578125, 'dgd_min': 1.0, 'dgd_max': 2.0, 'sopmd_avg': 33.234375, 'sopmd_min': 24.0, 'sopmd_max': 56.0, 'pdl_avg': 0.3, 'pdl_min': 0.2, 'pdl_max': 0.4, 'osnr_avg': 36.4, 'osnr_min': 36.4, 'osnr_max': 36.4, 'esnr_avg': 18.0249267578125, 'esnr_min': 17.9, 'esnr_max': 18.3, 'cfo_avg': -669.649169921875, 'cfo_min': -771.0, 'cfo_max': -563.0, 'evm_avg': 0.0, 'evm_min': 0.0, 'evm_max': 0.0, 'soproc_avg': 0.0, 'soproc_min': 0.0, 'soproc_max': 0.0, 'tx_power_avg': -8.110969848632813, 'tx_power_min': -8.16, 'tx_power_max': -8.09, 'rx_tot_power_avg': -8.6298095703125, 'rx_tot_power_min': -8.68, 'rx_tot_power_max': -8.56, 'rx_sig_power_avg': -9.08233642578125, 'rx_sig_power_min': -9.14, 'rx_sig_power_max': -9.06, 'pm_win_end_time': '1690819074.7969182', 'pm_win_start_time': '1690818163.9258842', 'pm_win_current': 'false'}", + "window22": "{'prefec_ber_avg': 0.0006099884638973447, 'prefec_ber_min': 0.0005811117121762265, 'prefec_ber_max': 0.0006310701752850946, 'uncorr_frames_avg': 0.0, 'uncorr_frames_min': 0.0, 'uncorr_frames_max': 0.0, 'cd_avg': -0.8709716796875, 'cd_min': -4.0, 'cd_max': 2.0, 'dgd_avg': 2.0, 'dgd_min': 2.0, 'dgd_max': 2.0, 'sopmd_avg': 34.7919921875, 'sopmd_min': 23.0, 'sopmd_max': 50.0, 'pdl_avg': 0.3750244140625, 'pdl_min': 0.3, 'pdl_max': 0.4, 'osnr_avg': 36.4, 'osnr_min': 36.4, 'osnr_max': 36.4, 'esnr_avg': 18.00625, 'esnr_min': 17.8, 'esnr_max': 18.2, 'cfo_avg': -665.9595947265625, 'cfo_min': -758.0, 'cfo_max': -591.0, 'evm_avg': 0.0, 'evm_min': 0.0, 'evm_max': 0.0, 'soproc_avg': 0.0, 'soproc_min': 0.0, 'soproc_max': 0.0, 'tx_power_avg': -8.10879638671875, 'tx_power_min': -8.12, 'tx_power_max': -8.08, 'rx_tot_power_avg': -8.618426513671874, 'rx_tot_power_min': -8.7, 'rx_tot_power_max': -8.56, 'rx_sig_power_avg': -9.089598388671874, 'rx_sig_power_min': -9.12, 'rx_sig_power_max': -9.05, 'pm_win_end_time': '1690819986.144761', 'pm_win_start_time': '1690819074.7969182', 'pm_win_current': 'false'}", + "window23": "{'prefec_ber_avg': 0.0005949791903081605, 'prefec_ber_min': 0.0005848295093911224, 'prefec_ber_max': 0.0006369572755686266, 'uncorr_frames_avg': 0.0, 'uncorr_frames_min': 0.0, 'uncorr_frames_max': 0.0, 'cd_avg': -0.94580078125, 'cd_min': -4.0, 'cd_max': 2.0, 'dgd_avg': 1.99884033203125, 'dgd_min': 1.0, 'dgd_max': 2.0, 'sopmd_avg': 33.96734619140625, 'sopmd_min': 23.0, 'sopmd_max': 51.0, 'pdl_avg': 0.30001220703125, 'pdl_min': 0.2, 'pdl_max': 0.4, 'osnr_avg': 36.4, 'osnr_min': 36.4, 'osnr_max': 36.4, 'esnr_avg': 18.0, 'esnr_min': 17.8, 'esnr_max': 18.2, 'cfo_avg': -669.6018676757812, 'cfo_min': -787.0, 'cfo_max': -555.0, 'evm_avg': 0.0, 'evm_min': 0.0, 'evm_max': 0.0, 'soproc_avg': 0.0, 'soproc_min': 0.0, 'soproc_max': 0.0, 'tx_power_avg': -8.100039062499999, 'tx_power_min': -8.12, 'tx_power_max': -8.09, 'rx_tot_power_avg': -8.6301123046875, 'rx_tot_power_min': -8.69, 'rx_tot_power_max': -8.56, 'rx_sig_power_avg': -9.091400756835938, 'rx_sig_power_min': -9.13, 'rx_sig_power_max': -9.07, 'pm_win_end_time': '1690820897.1694677', 'pm_win_start_time': '1690819986.144761', 'pm_win_current': 'false'}", + "window24": "{'prefec_ber_avg': 0.0005535850879515502, 'prefec_ber_min': 0.0005330224884164094, 'prefec_ber_max': 0.0006205342078723378, 'uncorr_frames_avg': 0.0, 'uncorr_frames_min': 0.0, 'uncorr_frames_max': 0.0, 'cd_avg': -1.7574462890625, 'cd_min': -5.0, 'cd_max': 2.0, 'dgd_avg': 1.999755859375, 'dgd_min': 1.0, 'dgd_max': 2.0, 'sopmd_avg': 33.16912841796875, 'sopmd_min': 23.0, 'sopmd_max': 57.0, 'pdl_avg': 0.3, 'pdl_min': 0.2, 'pdl_max': 0.4, 'osnr_avg': 36.4, 'osnr_min': 36.4, 'osnr_max': 36.4, 'esnr_avg': 18.085986328125003, 'esnr_min': 17.9, 'esnr_max': 18.3, 'cfo_avg': -663.1802368164062, 'cfo_min': -779.0, 'cfo_max': -548.0, 'evm_avg': 0.0, 'evm_min': 0.0, 'evm_max': 0.0, 'soproc_avg': 0.0, 'soproc_min': 0.0, 'soproc_max': 0.0, 'tx_power_avg': -8.162421264648437, 'tx_power_min': -8.18, 'tx_power_max': -8.08, 'rx_tot_power_avg': -8.561621704101563, 'rx_tot_power_min': -8.7, 'rx_tot_power_max': -8.5, 'rx_sig_power_avg': -9.083337402343751, 'rx_sig_power_min': -9.14, 'rx_sig_power_max': -9.0, 'pm_win_end_time': '1690821808.533936', 'pm_win_start_time': '1690820897.1694677', 'pm_win_current': 'false'}", + "window25": "{'prefec_ber_avg': 0.0005471769763859454, 'prefec_ber_min': 0.0005214000558421364, 'prefec_ber_max': 0.0005744582628403274, 'uncorr_frames_avg': 0.0, 'uncorr_frames_min': 0.0, 'uncorr_frames_max': 0.0, 'cd_avg': -1.9393310546875, 'cd_min': -4.0, 'cd_max': 0.0, 'dgd_avg': 1.9970703125, 'dgd_min': 1.0, 'dgd_max': 2.0, 'sopmd_avg': 33.144775390625, 'sopmd_min': 21.0, 'sopmd_max': 51.0, 'pdl_avg': 0.300384521484375, 'pdl_min': 0.2, 'pdl_max': 0.4, 'osnr_avg': 36.4, 'osnr_min': 36.4, 'osnr_max': 36.4, 'esnr_avg': 18.071868896484375, 'esnr_min': 17.9, 'esnr_max': 18.3, 'cfo_avg': -662.2525634765625, 'cfo_min': -746.0, 'cfo_max': -584.0, 'evm_avg': 0.0, 'evm_min': 0.0, 'evm_max': 0.0, 'soproc_avg': 0.0, 'soproc_min': 0.0, 'soproc_max': 0.0, 'tx_power_avg': -8.170205078125, 'tx_power_min': -8.19, 'tx_power_max': -8.14, 'rx_tot_power_avg': -8.55127136230469, 'rx_tot_power_min': -8.62, 'rx_tot_power_max': -8.51, 'rx_sig_power_avg': -9.077971191406249, 'rx_sig_power_min': -9.12, 'rx_sig_power_max': -9.05, 'pm_win_end_time': '1690822719.8197284', 'pm_win_start_time': '1690821808.533936', 'pm_win_current': 'false'}", + "window26": "{'prefec_ber_avg': 0.0005538282849859059, 'prefec_ber_min': 0.000530020737552282, 'prefec_ber_max': 0.0005903322622027038, 'uncorr_frames_avg': 0.0, 'uncorr_frames_min': 0.0, 'uncorr_frames_max': 0.0, 'cd_avg': -0.795166015625, 'cd_min': -4.0, 'cd_max': 2.0, 'dgd_avg': 1.99609375, 'dgd_min': 1.0, 'dgd_max': 2.0, 'sopmd_avg': 33.94091796875, 'sopmd_min': 22.0, 'sopmd_max': 59.0, 'pdl_avg': 0.3, 'pdl_min': 0.2, 'pdl_max': 0.4, 'osnr_avg': 36.4, 'osnr_min': 36.4, 'osnr_max': 36.4, 'esnr_avg': 18.046087646484374, 'esnr_min': 17.9, 'esnr_max': 18.3, 'cfo_avg': -659.4799194335938, 'cfo_min': -776.0, 'cfo_max': -543.0, 'evm_avg': 0.0, 'evm_min': 0.0, 'evm_max': 0.0, 'soproc_avg': 0.0, 'soproc_min': 0.0, 'soproc_max': 0.0, 'tx_power_avg': -8.159683227539062, 'tx_power_min': -8.19, 'tx_power_max': -8.09, 'rx_tot_power_avg': -8.577652587890626, 'rx_tot_power_min': -8.66, 'rx_tot_power_max': -8.49, 'rx_sig_power_avg': -9.094506225585937, 'rx_sig_power_min': -9.15, 'rx_sig_power_max': -9.0, 'pm_win_end_time': '1690823630.6387875', 'pm_win_start_time': '1690822719.8197284', 'pm_win_current': 'true'}", + "window27": "{'prefec_ber_avg': 0.0005733483547289238, 'prefec_ber_min': 0.0005556889275623451, 'prefec_ber_max': 0.0006165195363694851, 'uncorr_frames_avg': 0.0, 'uncorr_frames_min': 0.0, 'uncorr_frames_max': 0.0, 'cd_avg': -1.02813720703125, 'cd_min': -4.0, 'cd_max': 0.0, 'dgd_avg': 1.875, 'dgd_min': 1.0, 'dgd_max': 2.0, 'sopmd_avg': 33.8795166015625, 'sopmd_min': 22.0, 'sopmd_max': 54.0, 'pdl_avg': 0.3, 'pdl_min': 0.3, 'pdl_max': 0.4, 'osnr_avg': 36.4, 'osnr_min': 36.4, 'osnr_max': 36.4, 'esnr_avg': 18.0551513671875, 'esnr_min': 17.9, 'esnr_max': 18.2, 'cfo_avg': -671.4701538085938, 'cfo_min': -774.0, 'cfo_max': -575.0, 'evm_avg': 0.0, 'evm_min': 0.0, 'evm_max': 0.0, 'soproc_avg': 0.0, 'soproc_min': 0.0, 'soproc_max': 0.0, 'tx_power_avg': -8.1154638671875, 'tx_power_min': -8.13, 'tx_power_max': -8.08, 'rx_tot_power_avg': -8.624521484374998, 'rx_tot_power_min': -8.68, 'rx_tot_power_max': -8.55, 'rx_sig_power_avg': -9.080003051757814, 'rx_sig_power_min': -9.11, 'rx_sig_power_max': -9.05, 'pm_win_end_time': '1690813615.06098', 'pm_win_start_time': '1690812703.182413', 'pm_win_current': 'false'}", + "window28": "{'prefec_ber_avg': 0.0005538279872774187, 'prefec_ber_min': 0.0005214000558421364, 'prefec_ber_max': 0.0006753250511519025, 'uncorr_frames_avg': 0.0, 'uncorr_frames_min': 0.0, 'uncorr_frames_max': 0.0, 'cd_avg': -0.7951641648611754, 'cd_min': -6.0, 'cd_max': 2.0, 'dgd_avg': 1.9960936605928055, 'dgd_min': 1.0, 'dgd_max': 2.0, 'sopmd_avg': 33.94086135101429, 'sopmd_min': 19.0, 'sopmd_max': 61.0, 'pdl_avg': 0.3000000117346644, 'pdl_min': 0.2, 'pdl_max': 0.5, 'osnr_avg': 36.4, 'osnr_min': 36.4, 'osnr_max': 36.4, 'esnr_avg': 18.046086788071307, 'esnr_min': 17.8, 'esnr_max': 18.3, 'cfo_avg': -659.4798966200838, 'cfo_min': -795.0, 'cfo_max': -537.0, 'evm_avg': 0.0, 'evm_min': 0.0, 'evm_max': 0.0, 'soproc_avg': 0.0, 'soproc_min': 0.0, 'soproc_max': 0.0, 'tx_power_avg': -8.159683233790492, 'tx_power_min': -8.19, 'tx_power_max': -8.08, 'rx_tot_power_avg': -8.577652321496625, 'rx_tot_power_min': -8.7, 'rx_tot_power_max': -8.49, 'rx_sig_power_avg': -9.094505858480312, 'rx_sig_power_min': -9.15, 'rx_sig_power_max': -9.0, 'pm_win_end_time': '1690823630.6387875', 'pm_win_start_time': '1690757034.4068897', 'pm_win_current': 'true'}", + "window29": "{'prefec_ber_avg': 0.0006281245811956536, 'prefec_ber_min': 0.0005365406426360099, 'prefec_ber_max': 0.0006680605638445678, 'uncorr_frames_avg': 0.0, 'uncorr_frames_min': 0.0, 'uncorr_frames_max': 0.0, 'cd_avg': -0.7504892342165151, 'cd_min': -6.0, 'cd_max': 2.0, 'dgd_avg': 1.937370531202753, 'dgd_min': 1.0, 'dgd_max': 3.0, 'sopmd_avg': 33.14757245751743, 'sopmd_min': 19.0, 'sopmd_max': 61.0, 'pdl_avg': 0.3498075113750104, 'pdl_min': 0.2, 'pdl_max': 0.5, 'osnr_avg': 36.4, 'osnr_min': 36.4, 'osnr_max': 36.4, 'esnr_avg': 18.00010386405879, 'esnr_min': 17.8, 'esnr_max': 18.3, 'cfo_avg': -670.6894597763727, 'cfo_min': -799.0, 'cfo_max': -541.0, 'evm_avg': 0.0, 'evm_min': 0.0, 'evm_max': 0.0, 'soproc_avg': 0.0, 'soproc_min': 0.0, 'soproc_max': 0.0, 'tx_power_avg': -8.10992188638861, 'tx_power_min': -8.19, 'tx_power_max': -8.08, 'rx_tot_power_avg': -8.560338993568784, 'rx_tot_power_min': -8.65, 'rx_tot_power_max': -8.46, 'rx_sig_power_avg': -9.032818310875726, 'rx_sig_power_min': -9.12, 'rx_sig_power_max': -8.99, 'pm_win_end_time': '1690757034.4068897', 'pm_win_start_time': '1690670590.1528366', 'pm_win_current': 'false'}" }, "TRANSCEIVER_STATUS|Ethernet44":{ "cmis_state": "READY", diff --git a/tests/sfp_test.py b/tests/sfp_test.py index 22eda401e5..999ca7445d 100644 --- a/tests/sfp_test.py +++ b/tests/sfp_test.py @@ -264,25 +264,53 @@ """ test_qsfp_dd_pm_output = """\ +PM window: 60sec Ethernet44: + PM window start time: Mon Jul 31 17:12:49 UTC 2023 + PM window end time: Mon Jul 31 17:13:50 UTC 2023 Parameter Unit Min Avg Max Threshold Threshold Threshold Threshold Threshold Threshold High High Crossing Low Low Crossing Alarm Warning Alert-High Alarm Warning Alert-Low --------------- ------ -------- -------- -------- ----------- ----------- ------------ ----------- ----------- ----------- - Tx Power dBm -8.22 -8.23 -8.24 -5.0 -6.0 False -16.99 -16.003 False - Rx Total Power dBm -10.61 -10.62 -10.62 2.0 0.0 False -21.0 -18.0 False - Rx Signal Power dBm -40.0 0.0 40.0 13.0 10.0 True -18.0 -15.0 True - CD-short link ps/nm 0.0 0.0 0.0 1000.0 500.0 False -1000.0 -500.0 False - PDL dB 0.5 0.6 0.6 4.0 4.0 False 0.0 0.0 False - OSNR dB 36.5 36.5 36.5 99.0 99.0 False 0.0 0.0 False - eSNR dB 30.5 30.5 30.5 99.0 99.0 False 0.0 0.0 False - CFO MHz 54.0 70.0 121.0 3800.0 3800.0 False -3800.0 -3800.0 False - DGD ps 5.37 5.56 5.81 7.0 7.0 False 0.0 0.0 False - SOPMD ps^2 0.0 0.0 0.0 655.35 655.35 False 0.0 0.0 False - SOP ROC krad/s 1.0 1.0 2.0 N/A N/A N/A N/A N/A N/A - Pre-FEC BER N/A 4.58E-04 4.66E-04 5.76E-04 1.25E-02 1.10E-02 0.0 0.0 0.0 0.0 - Post-FEC BER N/A 0.0 0.0 0.0 1000.0 1.0 False 0.0 0.0 False - EVM % 100.0 100.0 100.0 N/A N/A N/A N/A N/A N/A + Tx Power dBm -8.19 -8.17 -8.15 -5 -6 False -16.99 -16.003 False + Rx Total Power dBm -8.61 -8.56 -8.51 2 0 False -21 -18 False + Rx Signal Power dBm -9.12 -9.09 -9.07 13 10 False -18 -15 False + CD-short link ps/nm -2 -1 0 1000 500 False -1000 -500 False + PDL dB 0.3 0.3 0.4 4 4 False 0 0 False + OSNR dB 36.4 36.4 36.4 99 99 False 0 0 False + eSNR dB 17.9 18 18.2 99 99 False 0 0 False + CFO MHz -776 -659 -546 3800 3800 False -3800 -3800 False + DGD ps 2 2 2 7 7 False 0 0 False + SOPMD ps^2 26 34 44 655.35 655.35 False 0 0 False + SOP ROC krad/s 0 0 0 N/A N/A N/A N/A N/A N/A + Pre-FEC BER N/A 5.37E-04 5.55E-04 5.80E-04 1.25E-02 1.10E-02 False 0 0 False + Post-FEC BER N/A 0 0 0 1.00E+03 1.00E+00 False 0 0 False + EVM % 0 0 0 N/A N/A N/A N/A N/A N/A +""" + +test_qsfp_dd_pm_hist_60s_win1_output = """\ +PM window: 60sec +Ethernet44: + PM window start time: Mon Jul 31 17:11:48 UTC 2023 + PM window end time: Mon Jul 31 17:12:49 UTC 2023 + Parameter Unit Min Avg Max Threshold Threshold Threshold Threshold Threshold Threshold + High High Crossing Low Low Crossing + Alarm Warning Alert-High Alarm Warning Alert-Low + --------------- ------ -------- -------- -------- ----------- ----------- ------------ ----------- ----------- ----------- + Tx Power dBm -8.17 -8.16 -8.15 -5 -6 False -16.99 -16.003 False + Rx Total Power dBm -8.66 -8.6 -8.53 2 0 False -21 -18 False + Rx Signal Power dBm -9.15 -9.12 -9.07 13 10 False -18 -15 False + CD-short link ps/nm -2 0 2 1000 500 False -1000 -500 False + PDL dB 0.3 0.3 0.4 4 4 False 0 0 False + OSNR dB 36.4 36.4 36.4 99 99 False 0 0 False + eSNR dB 17.9 18.1 18.2 99 99 False 0 0 False + CFO MHz -768 -660 -561 3800 3800 False -3800 -3800 False + DGD ps 2 2 2 7 7 False 0 0 False + SOPMD ps^2 26 34 42 655.35 655.35 False 0 0 False + SOP ROC krad/s 0 0 0 N/A N/A N/A N/A N/A N/A + Pre-FEC BER N/A 5.30E-04 5.49E-04 5.82E-04 1.25E-02 1.10E-02 False 0 0 False + Post-FEC BER N/A 0 0 0 1.00E+03 1.00E+00 False 0 0 False + EVM % 0 0 0 N/A N/A N/A N/A N/A N/A """ test_qsfp_status_output = """\ @@ -813,6 +841,7 @@ """ test_qsfp_dd_pm_all_output = """\ +PM window: 60sec Ethernet0: Transceiver performance monitoring not applicable Ethernet4: Transceiver performance monitoring not applicable @@ -942,13 +971,35 @@ def test_rj45_eeprom(self): def test_qsfp_dd_pm(self): runner = CliRunner() - result = runner.invoke(show.cli.commands["interfaces"].commands["transceiver"].commands["pm"], ["Ethernet44"]) + result = runner.invoke( + show.cli.commands["interfaces"] + .commands["transceiver"] + .commands["pm"] + .commands["current"], + ["60sec", "Ethernet44"] + ) assert result.exit_code == 0 - assert "\n".join([ l.rstrip() for l in result.output.split('\n')]) == test_qsfp_dd_pm_output + assert "\n".join([ l.rstrip() for l in result.output.split('\n')][1:]) == test_qsfp_dd_pm_output - result = runner.invoke(show.cli.commands["interfaces"].commands["transceiver"].commands["pm"], ["Ethernet200"]) - result_lines = result.output.strip('\n') - expected = "Ethernet200: Transceiver performance monitoring not applicable" + result = runner.invoke( + show.cli.commands["interfaces"] + .commands["transceiver"] + .commands["pm"] + .commands["history"], + ["60sec", "window", "1", "Ethernet44"] + ) + assert result.exit_code == 0 + assert "\n".join([ l.rstrip() for l in result.output.split('\n')][1:]) == test_qsfp_dd_pm_hist_60s_win1_output + + result = runner.invoke( + show.cli.commands["interfaces"] + .commands["transceiver"] + .commands["pm"] + .commands["current"], + ["15min", "Ethernet200"] + ) + result_lines = result.output.strip('\n')[result.output.find('\n'):].strip('\n') + expected = "PM window: 15min\nEthernet200: Transceiver performance monitoring not applicable" assert result_lines == expected def test_qsfp_status(self): @@ -975,6 +1026,11 @@ def teardown_class(cls): os.environ["UTILITIES_UNIT_TESTING"] = "0" os.environ["UTILITIES_UNIT_TESTING_TOPOLOGY"] = "" +def mocked_click_convert_method(*args, **kwargs): + """Mock click.Choice.convert method to return the value passed in""" + value = args[1] + return value + class Test_multiAsic_SFP(object): @classmethod def setup_class(cls): @@ -1027,12 +1083,19 @@ def test_sfp_eeprom_with_ns(self): expected = "Ethernet200: SFP EEPROM Not detected" assert result_lines == expected - @patch.object(show_module.interfaces.click.Choice, 'convert', MagicMock(return_value='asic0')) + @patch.object(show_module.interfaces.click.Choice, 'convert', new=mocked_click_convert_method) def test_qsfp_dd_pm_with_ns(self): runner = CliRunner() - result = runner.invoke(show.cli.commands["interfaces"].commands["transceiver"].commands["pm"], ['Ethernet0', '-n', 'asic0']) - result_lines = result.output.strip('\n') - expected = "Ethernet0: Transceiver performance monitoring not applicable" + result = runner.invoke( + show.cli.commands["interfaces"] + .commands["transceiver"] + .commands["pm"] + .commands["current"], + ["60sec", "Ethernet0", "-n", "asic0"] + ) + result_lines = result.output.strip('\n')[result.output.find('\n'):].strip('\n') + expected = "PM window: 60sec\nEthernet0: Transceiver performance monitoring not applicable" + assert result.exit_code == 0 assert result_lines == expected @patch.object(show_module.interfaces.click.Choice, 'convert', MagicMock(return_value='asic0')) @@ -1077,9 +1140,15 @@ def test_is_rj45_port(self): def test_qsfp_dd_pm_all(self): runner = CliRunner() - result = runner.invoke(show.cli.commands["interfaces"].commands["transceiver"].commands["pm"]) + result = runner.invoke( + show.cli.commands["interfaces"] + .commands["transceiver"] + .commands["pm"] + .commands["current"], + ["60sec"] + ) assert result.exit_code == 0 - assert "\n".join([ l.rstrip() for l in result.output.split('\n')]) == test_qsfp_dd_pm_all_output + assert "\n".join([ l.rstrip() for l in result.output.split('\n')][1:]) == test_qsfp_dd_pm_all_output def test_qsfp_dd_status_all(self): runner = CliRunner()