From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id A9F8BA2EDB for ; Fri, 6 Sep 2019 07:45:30 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 6F2641F109; Fri, 6 Sep 2019 07:45:30 +0200 (CEST) Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by dpdk.org (Postfix) with ESMTP id A02291F0FC for ; Fri, 6 Sep 2019 07:45:28 +0200 (CEST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga102.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 05 Sep 2019 22:45:27 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.64,472,1559545200"; d="scan'208";a="267261764" Received: from fmsmsx105.amr.corp.intel.com ([10.18.124.203]) by orsmga001.jf.intel.com with ESMTP; 05 Sep 2019 22:45:27 -0700 Received: from fmsmsx155.amr.corp.intel.com (10.18.116.71) by FMSMSX105.amr.corp.intel.com (10.18.124.203) with Microsoft SMTP Server (TLS) id 14.3.439.0; Thu, 5 Sep 2019 22:45:27 -0700 Received: from shsmsx102.ccr.corp.intel.com (10.239.4.154) by FMSMSX155.amr.corp.intel.com (10.18.116.71) with Microsoft SMTP Server (TLS) id 14.3.439.0; Thu, 5 Sep 2019 22:45:26 -0700 Received: from shsmsx103.ccr.corp.intel.com ([169.254.4.140]) by shsmsx102.ccr.corp.intel.com ([169.254.2.113]) with mapi id 14.03.0439.000; Fri, 6 Sep 2019 13:45:24 +0800 From: "Wan, Zhe" To: "Mo, YufengX" , "dts@dpdk.org" CC: "Tu, Lijuan" Thread-Topic: [dts][PATCH V1 1/1] tests/telemetry: upload suite script Thread-Index: AQHVYTbgxOiTVQSxukKnYe3Q8FP8AKceKZIQ Date: Fri, 6 Sep 2019 05:45:24 +0000 Message-ID: <861C16A15685B44AA870C0D2A97B60458A2476D5@SHSMSX103.ccr.corp.intel.com> References: <20190902023506.11416-1-yufengx.mo@intel.com> <20190902023506.11416-2-yufengx.mo@intel.com> In-Reply-To: <20190902023506.11416-2-yufengx.mo@intel.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-ctpclassification: CTP_NT x-titus-metadata-40: eyJDYXRlZ29yeUxhYmVscyI6IiIsIk1ldGFkYXRhIjp7Im5zIjoiaHR0cDpcL1wvd3d3LnRpdHVzLmNvbVwvbnNcL0ludGVsMyIsImlkIjoiZmU2NzFhNjktY2Y2My00YzJjLThiMjQtOWY2ZmE5M2Y1MzFhIiwicHJvcHMiOlt7Im4iOiJDVFBDbGFzc2lmaWNhdGlvbiIsInZhbHMiOlt7InZhbHVlIjoiQ1RQX05UIn1dfV19LCJTdWJqZWN0TGFiZWxzIjpbXSwiVE1DVmVyc2lvbiI6IjE3LjEwLjE4MDQuNDkiLCJUcnVzdGVkTGFiZWxIYXNoIjoiVDV3VFFaUUdReGFhdWljekN5MDdrUXlFYzFBcnRJOXZFRmV1T0dtcGlIQ1drZmllbEhjQVZ4aGs3Sm1QZmZRRSJ9 dlp-product: dlpe-windows dlp-version: 11.2.0.6 dlp-reaction: no-action x-originating-ip: [10.239.127.40] Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Subject: Re: [dts] [PATCH V1 1/1] tests/telemetry: upload suite script X-BeenThere: dts@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: test suite reviews and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dts-bounces@dpdk.org Sender: "dts" Acked-by: Zhe Wan -----Original Message----- From: Mo, YufengX=20 Sent: Monday, September 2, 2019 10:35 AM To: dts@dpdk.org; Wan, Zhe Cc: Mo, YufengX Subject: [dts][PATCH V1 1/1] tests/telemetry: upload suite script The telemetry mechanism provides the functionality so that users may query = metrics from incoming port traffic and global stats(application stats). The application which initializes packet forwarding will act as the server,= sending metrics to the requesting application which acts as the client. Signed-off-by: yufengmx --- tests/TestSuite_telemetry.py | 586 +++++++++++++++++++++++++++++++++++ 1 file changed, 586 insertions(+) create mode 100644 tests/TestSuite_telemetry.py diff --git a/tests/TestSuite_telemetry.py b/tests/TestSuite_telemetry.py ne= w file mode 100644 index 0000000..bb2c9e6 --- /dev/null +++ b/tests/TestSuite_telemetry.py @@ -0,0 +1,586 @@ +# BSD LICENSE +# +# Copyright(c) 2010-2019 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without #=20 +modification, are permitted provided that the following conditions #=20 +are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS #=20 +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT #=20 +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR #=20 +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT #=20 +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, #=20 +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT #=20 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, #=20 +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY #=20 +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT #=20 +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE #=20 +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import os +import time +import json +import re +import textwrap +from pprint import pformat + +# import dts libs +from test_case import TestCase +from pmd_output import PmdOutput + + +class TestTelemetry(TestCase): + + def set_compiler_switch(self): + cmd =3D ( + "sed -i -e " + "'s/CONFIG_RTE_LIBRTE_TELEMETRY=3Dn/CONFIG_RTE_LIBRTE_TELEMETR= Y=3Dy/g'" + " {}/config/common_base").format(self.target_dir) + self.d_a_console(cmd) + + def create_query_script(self): + ''' + usertools/dpdk-telemetry-client.py is not user friendly(till 19.05= ). + this method is used to make sure testing robust. + ''' + script_content =3D textwrap.dedent(""" + #! /usr/bin/env python + import argparse + import time + import json + from dpdk_telemetry_client import Client, DEFAULT_FP,=20 + METRICS_REQ, BUFFER_SIZE + + class ClientExd(Client): + def __init__(self, json_file): + super(ClientExd, self).__init__() + self.json_file =3D json_file + def save_date(self, data): + with open(self.json_file, 'w') as fp: + fp.write(data) + def requestMetrics(self): # Requests metrics for given cli= ent + self.socket.client_fd.send(METRICS_REQ) + data =3D self.socket.client_fd.recv(BUFFER_SIZE) + return data + def singleRequestMetrics(self): + data =3D self.requestMetrics() + self.save_date(data) + def repeatedlyRequestMetrics(self, sleep_time=3D1, n_reque= sts=3D2): + data_list =3D {} + for i in range(n_requests): + data_list[i] =3D self.requestMetrics() + time.sleep(sleep_time) + self.save_date(data_list) + parser =3D argparse.ArgumentParser(description=3D'dpdk telemet= ry tool') + parser.add_argument('-c', + '--choice', + nargs=3D'*', + default=3D1, + help=3D'choice option') + parser.add_argument('-n', + '--n_requests', + nargs=3D'*', + default=3D1, + help=3D'n requests option') + parser.add_argument('-j', + '--json_file', + nargs=3D'*', + default=3DNone, + help=3D'json file directory') + print("Options Menu") + args =3D parser.parse_args() + if not args.choice or not len(args.choice): + print("Error - Invalid request choice") + else: + file_path =3D DEFAULT_FP + client =3D ClientExd(args.json_file[0]) + client.getFilepath(file_path) + client.register() + choice =3D int(args.choice[0]) + if choice =3D=3D 1: + print("[1] Send for Metrics for all ports") + client.singleRequestMetrics() + elif choice =3D=3D 2: + print("[2] Send for Metrics for all ports recursively"= ) + client.repeatedlyRequestMetrics(1) + time.sleep(2) + print("Unregister client") + client.unregister() + client.unregistered =3D 1 + print("Get metrics done") + """) + fileName =3D 'query_tool.py' + query_script =3D os.path.join(self.output_path, fileName) + with open(query_script, 'wb') as fp: + fp.write('#! /usr/bin/env python' + os.linesep + script_conten= t) + self.dut.session.copy_file_to(query_script, self.target_dir) + self.query_tool =3D ';'.join([ + 'cd {}'.format(self.target_dir), + 'chmod 777 {}'.format(fileName), + './' + fileName]) + + def rename_dpdk_telemetry_tool(self): + ''' + transfer dpdk-telemetry-client.py to the available python module + ''' + new_name =3D 'dpdk_telemetry_client.py' + old_name =3D 'dpdk-telemetry-client.py' + cmds =3D [ + 'rm -f {0}/{1}', + 'cp -f {0}/usertools/dpdk-telemetry-client.py {0}/{1}', + "sed -i -e 's/class Client:/class Client(object):/g' {0}/{1}"] + cmd =3D ';'.join(cmds).format(self.target_dir, new_name, old_name) + self.d_a_console(cmd) + self.create_query_script() + + @property + def target_dir(self): + # get absolute directory of target source code + target_dir =3D '/root' + self.dut.base_dir[1:] \ + if self.dut.base_dir.startswith('~') else \ + self.dut.base_dir + return target_dir + + @property + def output_path(self): + suiteName =3D self.__class__.__name__[4:].lower() + if self.logger.log_path.startswith(os.sep): + output_path =3D os.path.join(self.logger.log_path, suiteName) + else: + cur_path =3D os.path.dirname( + os.path.dirname(os.path.realpath(__file__))) + output_path =3D os.path.join( + cur_path, self.logger.log_path, suiteName) + if not os.path.exists(output_path): + os.makedirs(output_path) + + return output_path + + def d_console(self, cmds): + return self.execute_cmds(cmds, con_name=3D'dut') + + def d_a_console(self, cmds): + return self.execute_cmds(cmds, con_name=3D'dut_alt') + + def get_console(self, name): + if name =3D=3D 'dut': + console =3D self.dut.send_expect + msg_pipe =3D self.dut.get_session_output + elif name =3D=3D 'dut_alt': + console =3D self.dut.alt_session.send_expect + msg_pipe =3D self.dut.alt_session.session.get_output_all + else: + msg =3D '{} not created'.format(name) + raise Exception(msg) + return console, msg_pipe + + def execute_cmds(self, cmds, con_name=3D'dut'): + console, msg_pipe =3D self.get_console(con_name) + if not cmds: + return + if isinstance(cmds, (str, unicode)): + cmds =3D [cmds, '# ', 5] + if not isinstance(cmds[0], list): + cmds =3D [cmds] + outputs =3D [] if len(cmds) > 1 else '' + for item in cmds: + expected_items =3D item[1] + expected_str =3D expected_items or '# ' + try: + timeout =3D int(item[2]) if len(item) =3D=3D 3 else 5 + output =3D console(item[0], expected_str, timeout) + except Exception as e: + # self.check_process_status() + msg =3D "execute '{0}' timeout".format(item[0]) + raise Exception(msg) + time.sleep(1) + if len(cmds) > 1: + outputs.append(output) + else: + outputs =3D output + return outputs + + def init_test_binary_files(self): + # set_compiler_switch + if not self.dut.skip_setup: + self.set_compiler_switch() + self.dut.build_install_dpdk(self.target) + # initialize testpmd + self.testpmd_status =3D 'close' + self.testpmd =3D PmdOutput(self.dut) + # prepare telemetry tool + self.rename_dpdk_telemetry_tool() + + def get_whitelist(self, num=3D1, nic_types=3D2): + self.used_ports =3D [] + if len(self.dut_ports) < 4 or len(self.nic_grp) < nic_types: + self.used_ports =3D self.dut_ports + return None + pci_addrs =3D [ + pci_addr for pci_addrs in self.nic_grp.values()[:nic_types] + for pci_addr in pci_addrs[:num]] + for index in self.dut_ports: + info =3D self.dut.ports_info[index] + if info['pci'] not in pci_addrs: + continue + self.used_ports.append(index) + white_list =3D ' '.join(['-w ' + pci_addr for pci_addr in pci_addr= s]) + return white_list + + def start_telemetry_server(self, whitelist=3DNone): + if self.testpmd_status !=3D 'close': + return None + # use dut first port's socket + socket =3D self.dut.get_numa_id(0) + config =3D "Default" + eal_option =3D '--telemetry ' + whitelist if whitelist else '--tel= emetry' + output =3D self.testpmd.start_testpmd(config, + eal_param=3Deal_option, + socket=3Dsocket) + self.testpmd_status =3D 'running' + self.testpmd.execute_cmd('start') + return output + + def close_telemetry_server(self): + if self.testpmd_status =3D=3D 'close': + return None + self.testpmd.execute_cmd('stop') + self.testpmd.quit() + self.testpmd_status =3D 'close' + + def get_all_xstat_data(self): + ''' get nic extended statistics ''' + cmd =3D ['show port xstats all', 'testpmd>'] + output =3D self.d_console(cmd) + if "statistics" not in output: + self.logger.error(output) + raise Exception("failed to get port extended statistics data") + data_str =3D output.splitlines() + port_xstat =3D {} + cur_port =3D None + pat =3D r".*extended statistics for port (\d+).*" + for line in data_str: + if not line.strip(): + continue + if "statistics" in line: + result =3D re.findall(pat, line.strip()) + if len(result): + cur_port =3D int(result[0]) + elif cur_port is not None and ": " in line: + if cur_port not in port_xstat: + port_xstat[cur_port] =3D {} + result =3D line.strip().split(": ") + if len(result) =3D=3D 2 and result[0]: + name, value =3D result + port_xstat[cur_port][name] =3D int(value) + else: + raise Exception("invalid data") + + return port_xstat + + def get_metric_data(self): + json_name =3D 'metric.json' + json_file =3D os.path.join(self.target_dir, json_name) + cmd =3D "{0} -c 1 -j {1}".format(self.query_tool, json_file) + output =3D self.d_a_console(cmd) + msg =3D 'faile to query metric data' + self.verify("Get metrics done" in output, msg) + dst_file =3D os.path.join(self.output_path, json_name) + self.dut.session.copy_file_from(json_file, dst_file) + msg =3D 'failed to get {}'.format(json_name) + self.verify(os.path.exists(dst_file), msg) + with open(dst_file, 'r') as fp: + try: + query_data =3D json.load(fp, encoding=3D"utf-8") + except Exception as e: + msg =3D 'failed to load metrics json data' + self.verify(False, msg) + metric_status =3D query_data.get('status_code') + msg =3D 'failed to query metric data, return status <{}>'.format( + metric_status) + self.verify('Status OK' in metric_status, msg) + metric_data =3D {} + for info in query_data.get('data'): + port_index =3D info.get('port') + stats =3D info.get('stats') + metric_data[port_index] =3D {} + for stat in stats: + metric_data[port_index][stat.get('name')] =3D \ + int(stat.get('value')) + self.logger.debug(pformat(metric_data)) + return metric_data + + def check_telemetry_client_script(self): + ''' + check if dpdk-telemetry-client.py is available + ''' + output =3D self.start_telemetry_client() + # check script select items + expected_strs =3D [ + 'Send for Metrics for all ports', + 'Send for Metrics for all ports recursively', + 'Send for global Metrics', + 'Unregister client', ] + msg =3D 'expected select items not existed' + self.verify(all([item in output for item in expected_strs]), msg) + cmd =3D ['1', ':', 10] + output =3D self.dut_s_session.send_expect(*cmd) + output =3D self.dut_s_session.session.get_output_all() + cmd =3D ['4', '#', 5] + output =3D self.dut_s_session.send_expect(*cmd) + + def start_telemetry_client(self): + self.dut_s_session =3D self.dut.new_session() + dpdk_tool =3D os.path.join( + self.target_dir, 'usertools/dpdk-telemetry-client.py') + output =3D self.dut_s_session.send_expect(dpdk_tool, ':', 5) + return output + + def close_telemetry_client(self): + cmd =3D "ps aux | grep -i '%s' | grep -v grep | awk {'print $2'}" = % ( + 'dpdk-telemetry-client.py') + out =3D self.d_a_console([cmd, '# ', 5]) + if out !=3D "" and '[PEXPECT]' not in out: + process_pid =3D out.splitlines()[0] + cmd =3D ['kill -TERM {0}'.format(process_pid), '# '] + self.d_a_console(cmd) + self.dut.close_session(self.dut_s_session) + + def check_metric_data(self): + metric_data =3D self.get_metric_data() + msg =3D "haven't get all ports metric data" + self.verify(len(self.used_ports) =3D=3D len(metric_data), msg) + port_index_list =3D range(len(self.used_ports)) + for port_index in metric_data: + msg =3D '<{}> is not the expected port'.format(port_index) + self.verify( + port_index is not None and port_index in port_index_list, = msg) + output =3D self.dut.get_session_output() + self.verify('failed' not in output, output) + # set rx/tx configuration by testpmd + cmds =3D [ + ['stop', 'testpmd>', 15], + ['clear port xstats all', 'testpmd>', 15]] + self.d_console(cmds) + metric_data =3D self.get_metric_data() + xstats =3D self.get_all_xstat_data() + self.compare_data(metric_data, xstats) + + def compare_data(self, metric, xstat): + error_msg =3D [] + # Ensure # of ports stats being returned =3D=3D # of ports + msg =3D "metric and xstat data are not the same" + self.verify(len(metric) =3D=3D len(xstat), msg) + # check if parameters are the same + for port_id in metric: + if len(metric[0]) =3D=3D len(xstat[0]): + continue + xstat_missed_paras =3D [] + for keyname in metric[0].keys(): + if keyname in xstat[0].keys(): + continue + xstat_missed_paras.append(keyname) + metric_missed_paras =3D [] + for keyname in xstat[0].keys(): + if keyname in metric[0].keys(): + continue + metric_missed_paras.append(keyname) + msg =3D os.linesep.join([ + 'testpmd xstat missed parameters:: ', + pformat(xstat_missed_paras), + 'telemetry metric missed parameters:: ', + pformat(metric_missed_paras), ]) + error_msg.append(msg) + # check if metric parameters and values are the same + if cmp(metric, xstat) !=3D 0: + msg =3D 'telemetry metric data is not the same as testpmd xsta= t data' + error_msg.append(msg) + msg_fmt =3D 'port {} <{}>: metric is <{}>, xstat is is <{}>'.f= ormat + for port_index, info in metric.iteritems(): + for name, value in info.iteritems(): + if value =3D=3D xstat[port_index][str(name)]: + continue + error_msg.append(msg_fmt(port_index, name, + value, xstat[port_index][name= ])) + # check if metric parameters value should be zero + # ensure extended NIC stats are 0 + is_clear =3D any([any(data.values()) for data in metric.values()]) + if is_clear: + msg =3D 'telemetry metric data are not default value' + error_msg.append(msg) + msg_fmt =3D 'port {} <{}>: metric is <{}>'.format + for port_index, info in metric.iteritems(): + for name, value in info.iteritems(): + if not value: + continue + error_msg.append(msg_fmt(port_index, name, value)) + # show exception check content + if error_msg: + self.logger.error(os.linesep.join(error_msg)) + self.verify(False, 'telemetry metric data error') + + def get_ports_by_nic_type(self): + nic_grp =3D {} + for info in self.dut.ports_info: + nic_type =3D info['type'] + if nic_type not in nic_grp: + nic_grp[nic_type] =3D [] + nic_grp[nic_type].append(info['pci']) + return nic_grp + # + # test content + # + + def verify_basic_script(self): + ''' + verify dpdk-telemetry-client.py script + ''' + try: + self.start_telemetry_server() + time.sleep(1) + self.check_telemetry_client_script() + self.close_telemetry_client() + self.close_telemetry_server() + except Exception as e: + self.close_telemetry_client() + self.close_telemetry_server() + raise Exception(e) + + def verify_basic_connection(self): + try: + self.start_telemetry_server() + metric_data =3D self.get_metric_data() + port_index_list =3D range(len(self.dut_ports)) + msg =3D "haven't get all ports metric data" + self.verify(len(self.dut_ports) =3D=3D len(metric_data), msg) + for port_index in metric_data: + msg =3D '<{}> is not the expected port'.format(port_index) + self.verify( + port_index is not None and port_index in port_index_li= st, + msg) + output =3D self.dut.get_session_output() + self.verify('failed' not in output, output) + self.close_telemetry_server() + except Exception as e: + self.close_telemetry_server() + raise Exception(e) + + def verify_same_nic_with_2ports(self): + msg =3D os.linesep.join(['no enough ports', pformat(self.nic_grp)]= ) + self.verify(len(self.nic_grp.values()[0]) >=3D 2, msg) + try: + # check and verify error show on testpmd + whitelist =3D self.get_whitelist(num=3D2, nic_types=3D1) + self.start_telemetry_server(whitelist) + # check telemetry metric data + self.check_metric_data() + self.close_telemetry_server() + except Exception as e: + self.close_telemetry_server() + raise Exception(e) + + def verify_same_nic_with_4ports(self): + msg =3D os.linesep.join(['no enough ports, 4 ports at least', + pformat(self.nic_grp)]) + self.verify(len(self.nic_grp.values()[0]) >=3D 4, msg) + try: + self.used_ports =3D self.dut_ports + self.start_telemetry_server() + # check telemetry metric data + self.check_metric_data() + self.close_telemetry_server() + except Exception as e: + self.close_telemetry_server() + raise Exception(e) + + def verify_different_nic_with_2ports(self): + # check ports total number + msg =3D os.linesep.join(['no enough nic types, 2 nic types at leas= t', + pformat(self.nic_grp)]) + self.verify(len(self.nic_grp.keys()) >=3D 2, msg) + try: + whitelist =3D self.get_whitelist() + self.start_telemetry_server(whitelist) + # check telemetry metric data + self.check_metric_data() + self.close_telemetry_server() + except Exception as e: + self.close_telemetry_server() + raise Exception(e) + + def verify_different_nic_with_4ports(self): + msg =3D os.linesep.join(['no enough nic types, 2 nic types at leas= t', + pformat(self.nic_grp)]) + self.verify(len(self.nic_grp.keys()) >=3D 2, msg) + msg =3D os.linesep.join(['no enough ports, 2 ports/nic type at lea= st', + pformat(self.nic_grp)]) + self.verify( + all([pci_addrs and len(pci_addrs) >=3D 2 + for pci_addrs in self.nic_grp.values()]), + msg) + + try: + self.used_ports =3D self.dut_ports + self.start_telemetry_server() + # check telemetry metric data + self.check_metric_data() + self.close_telemetry_server() + except Exception as e: + self.close_telemetry_server() + raise Exception(e) + # + # Test cases. + # + + def set_up_all(self): + """ + Run before each test suite + """ + # get ports information + self.dut_ports =3D self.dut.get_ports() + self.verify(len(self.dut_ports) >=3D 2, "Insufficient ports") + self.init_test_binary_files() + self.nic_grp =3D self.get_ports_by_nic_type() + self.used_ports =3D [] + + def set_up(self): + """ + Run before each test case. + """ + pass + + def tear_down(self): + """ + Run after each test case. + """ + pass + + def tear_down_all(self): + """ + Run after each test suite. + """ + pass + + def test_basic_connection(self): + ''' + basic connection for testpmd and telemetry client + ''' + self.verify_basic_script() + self.verify_basic_connection() + + def test_same_nic_with_2ports(self): + ''' + Stats of 2 ports for testpmd and telemetry with same type nic + ''' + self.verify_same_nic_with_2ports() -- 2.21.0