From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 718A542EAA; Tue, 18 Jul 2023 14:08:17 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 06769410D3; Tue, 18 Jul 2023 14:08:17 +0200 (CEST) Received: from mail-lf1-f44.google.com (mail-lf1-f44.google.com [209.85.167.44]) by mails.dpdk.org (Postfix) with ESMTP id 0040A40A84 for ; Tue, 18 Jul 2023 14:08:15 +0200 (CEST) Received: by mail-lf1-f44.google.com with SMTP id 2adb3069b0e04-4fdd14c1fbfso604354e87.1 for ; Tue, 18 Jul 2023 05:08:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pantheon.tech; s=google; t=1689682095; x=1690286895; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=jpiHrovXF6YN2c7+0F27oqPcBJJ69S7r5srqHxECHfE=; b=IwWdpdqWZxcVsmf/orqfUU+1fU8kTZqVA0WxE9BDps7vl/Rr6OvOI+hgYAMmIkq6u7 q5Izc0rDirZTAhWEulqUTjtoCKhG7NRCiHyX3RXOLABABKDd7Z/ERaXKKA8M0mSKh/zR uJufl6Zek6gwUZvTXnv2jSWVDO8jWoa8U/7FqGnSjsfBUz7HP6qDCteztwwAFK8FzOAT 4E6efacfcwI/GXcttSVcK9ORUAl+mGHRxp6euE+muLlXZs8jdf7xyucvDNU86xkiHaQr LGa5igWBrNjmsqC590QQAV5ikJS1e+a0zcndFKEogtetsF2/SmnKMRyhHH9egH9Z4bV4 Y2Pw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1689682095; x=1690286895; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=jpiHrovXF6YN2c7+0F27oqPcBJJ69S7r5srqHxECHfE=; b=iQZ1IuUUrzZy4zZxbjc/2T3yll6QxoI1cUieXQ0qmXdOP59mh3LDAI6VVhgCh+BQCj 0pyDf9WTXPm3tY8tACK6lBfkm2QsFamYeA1DQBmk7UciMjvp7XOLy3s695RXVLBQrH+l dB94EPycN6yqErBMmqT5bGneh20T+iyl1ThDD2ywvDli2VOECmpTRlDU+uq2WN/vY5Zz R3Mei+luRqspymXQydtxqIQWMnFK/ZDN3HWeRQGI60kDpMh3ciCWtV0IyKfRjjq8iiWe iveEXkrF4BbOnHroNx8f1dCUVekOWaeKNSEtLFDiTZtfB0K3lkro5dDSCSF/PcsQcGtW 3HkA== X-Gm-Message-State: ABy/qLbazZNFq69zuhCvcr25cY+EP8RxakwqOtSX8MeaVUUEwHfz0ETU lyLdXK0S1cmWPuV9547rKa9hXQ7uqHDqF0fE5miWxg== X-Google-Smtp-Source: APBJJlGYQ6hp9y/kd+ttKvoJ0RnZSxyjwE0wj5ZIqTeaokI8KtjJBXYq3r9FkmEDgk2VW5EYj4Y/w2IoOoozLEto9pY= X-Received: by 2002:a05:6512:31c6:b0:4f8:d385:41bd with SMTP id j6-20020a05651231c600b004f8d38541bdmr11879562lfe.8.1689682095190; Tue, 18 Jul 2023 05:08:15 -0700 (PDT) MIME-Version: 1.0 References: <20230717193705.26594-2-jspewock@iol.unh.edu> <20230717193705.26594-3-jspewock@iol.unh.edu> In-Reply-To: <20230717193705.26594-3-jspewock@iol.unh.edu> From: =?UTF-8?Q?Juraj_Linke=C5=A1?= Date: Tue, 18 Jul 2023 14:08:04 +0200 Message-ID: Subject: Re: [PATCH v8 1/1] dts: add smoke tests To: jspewock@iol.unh.edu Cc: Honnappa.Nagarahalli@arm.com, thomas@monjalon.net, lijuan.tu@intel.com, wathsala.vithanage@arm.com, probb@iol.unh.edu, dev@dpdk.org Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org A few more things I noticed while running DTS. On Mon, Jul 17, 2023 at 9:37=E2=80=AFPM wrote: > > From: Jeremy Spewock > > Adds a new test suite for running smoke tests that verify general > configuration aspects of the system under test. If any of these tests > fail, the DTS execution terminates as part of a "fail-fast" model. > > Signed-off-by: Jeremy Spewock > --- > dts/conf.yaml | 17 +- > dts/framework/config/__init__.py | 79 ++++++-- > dts/framework/config/conf_yaml_schema.json | 142 ++++++++++++++- > dts/framework/dts.py | 84 ++++++--- > dts/framework/exception.py | 12 ++ > dts/framework/remote_session/__init__.py | 13 +- > dts/framework/remote_session/os_session.py | 48 ++++- > dts/framework/remote_session/posix_session.py | 29 ++- > .../remote_session/remote/__init__.py | 10 ++ > .../remote/interactive_remote_session.py | 82 +++++++++ > .../remote/interactive_shell.py | 98 ++++++++++ > .../remote_session/remote/testpmd_shell.py | 46 +++++ > dts/framework/test_result.py | 24 ++- > dts/framework/test_suite.py | 10 +- > dts/framework/testbed_model/node.py | 43 ++++- > dts/framework/testbed_model/sut_node.py | 169 +++++++++++++----- > dts/framework/utils.py | 3 + > dts/tests/TestSuite_smoke_tests.py | 114 ++++++++++++ > 18 files changed, 931 insertions(+), 92 deletions(-) > create mode 100644 dts/framework/remote_session/remote/interactive_remot= e_session.py > create mode 100644 dts/framework/remote_session/remote/interactive_shell= .py > create mode 100644 dts/framework/remote_session/remote/testpmd_shell.py > create mode 100644 dts/tests/TestSuite_smoke_tests.py > > diff --git a/dts/conf.yaml b/dts/conf.yaml > index 129801d87c..3a5d87cb49 100644 > --- a/dts/conf.yaml > +++ b/dts/conf.yaml > @@ -10,9 +10,13 @@ executions: > compiler_wrapper: ccache > perf: false > func: true > + skip_smoke_tests: false # optional flag that allow you to skip smoke= tests Typo: allows > > test_suites: > - hello_world > - system_under_test: "SUT 1" > + system_under_test: > + node_name: "SUT 1" > + vdevs: # optional; if removed, vdevs won't be used in the executio= n > + - "crypto_openssl" > nodes: > - name: "SUT 1" > hostname: sut1.change.me.localhost > diff --git a/dts/framework/config/conf_yaml_schema.json b/dts/framework/c= onfig/conf_yaml_schema.json > index ca2d4a1ef2..09fcbaf498 100644 > --- a/dts/framework/config/conf_yaml_schema.json > +++ b/dts/framework/config/conf_yaml_schema.json > @@ -6,6 +6,76 @@ > "type": "string", > "description": "A unique identifier for a node" > }, > + "NIC": { > + "type": "string", > + "enum": [ > + "ALL", > + "ConnectX3_MT4103", > + "ConnectX4_LX_MT4117", > + "ConnectX4_MT4115", > + "ConnectX5_MT4119", > + "ConnectX5_MT4121", > + "I40E_10G-10G_BASE_T_BC", > + "I40E_10G-10G_BASE_T_X722", > + "I40E_10G-SFP_X722", > + "I40E_10G-SFP_XL710", > + "I40E_10G-X722_A0", > + "I40E_1G-1G_BASE_T_X722", > + "I40E_25G-25G_SFP28", > + "I40E_40G-QSFP_A", > + "I40E_40G-QSFP_B", > + "IAVF-ADAPTIVE_VF", > + "IAVF-VF", > + "IAVF_10G-X722_VF", > + "ICE_100G-E810C_QSFP", > + "ICE_25G-E810C_SFP", > + "ICE_25G-E810_XXV_SFP", > + "IGB-I350_VF", > + "IGB_1G-82540EM", > + "IGB_1G-82545EM_COPPER", > + "IGB_1G-82571EB_COPPER", > + "IGB_1G-82574L", > + "IGB_1G-82576", > + "IGB_1G-82576_QUAD_COPPER", > + "IGB_1G-82576_QUAD_COPPER_ET2", > + "IGB_1G-82580_COPPER", > + "IGB_1G-I210_COPPER", > + "IGB_1G-I350_COPPER", > + "IGB_1G-I354_SGMII", > + "IGB_1G-PCH_LPTLP_I218_LM", > + "IGB_1G-PCH_LPTLP_I218_V", > + "IGB_1G-PCH_LPT_I217_LM", > + "IGB_1G-PCH_LPT_I217_V", > + "IGB_2.5G-I354_BACKPLANE_2_5GBPS", > + "IGC-I225_LM", > + "IGC-I226_LM", > + "IXGBE_10G-82599_SFP", > + "IXGBE_10G-82599_SFP_SF_QP", > + "IXGBE_10G-82599_T3_LOM", > + "IXGBE_10G-82599_VF", > + "IXGBE_10G-X540T", > + "IXGBE_10G-X540_VF", > + "IXGBE_10G-X550EM_A_SFP", > + "IXGBE_10G-X550EM_X_10G_T", > + "IXGBE_10G-X550EM_X_SFP", > + "IXGBE_10G-X550EM_X_VF", > + "IXGBE_10G-X550T", > + "IXGBE_10G-X550_VF", > + "brcm_57414", > + "brcm_P2100G", > + "cavium_0011", > + "cavium_a034", > + "cavium_a063", > + "cavium_a064", > + "fastlinq_ql41000", > + "fastlinq_ql41000_vf", > + "fastlinq_ql45000", > + "fastlinq_ql45000_vf", > + "hi1822", > + "virtio" > + ] > + }, > + > "ARCH": { > "type": "string", > "enum": [ > @@ -94,6 +164,19 @@ > "amount" > ] > }, > + "pci_address": { > + "type": "string", > + "pattern": "^[\\da-fA-F]{4}:[\\da-fA-F]{2}:[\\da-fA-F]{2}.\\d:?\\w= *$" > + }, > + "port_peer_address": { > + "description": "Peer is a TRex port, and IXIA port or a PCI addres= s", > + "oneOf": [ > + { > + "description": "PCI peer port", > + "$ref": "#/definitions/pci_address" > + } > + ] > + }, > "test_suite": { > "type": "string", > "enum": [ > @@ -165,6 +248,44 @@ > }, > "hugepages": { > "$ref": "#/definitions/hugepages" > + }, > + "ports": { > + "type": "array", > + "items": { > + "type": "object", > + "description": "Each port should be described on both side= s of the connection. This makes configuration slightly more verbose but gre= atly simplifies implementation. If there are an inconsistencies, then DTS w= ill not run until that issue is fixed. An example inconsistency would be po= rt 1, node 1 says it is connected to port 1, node 2, but port 1, node 2 say= s it is connected to port 2, node 1.", Typo: extra an in are an inconsistencies > + "properties": { > + "pci": { > + "$ref": "#/definitions/pci_address", > + "description": "The local PCI address of the port" > + }, > + "os_driver_for_dpdk": { > + "type": "string", > + "description": "The driver that the kernel should bind= this device to for DPDK to use it. (ex: vfio-pci)" > + }, > + "os_driver": { > + "type": "string", > + "description": "The driver normally used by this port = (ex: i40e)" > + }, > + "peer_node": { > + "type": "string", > + "description": "The name of the node the peer port is = on" > + }, > + "peer_pci": { > + "$ref": "#/definitions/pci_address", > + "description": "The PCI address of the peer port" > + } > + }, > + "additionalProperties": false, > + "required": [ > + "pci", > + "os_driver_for_dpdk", > + "os_driver", > + "peer_node", > + "peer_pci" > + ] > + }, > + "minimum": 1 > } > }, > "additionalProperties": false, > diff --git a/dts/framework/remote_session/remote/interactive_shell.py b/d= ts/framework/remote_session/remote/interactive_shell.py > new file mode 100644 > index 0000000000..4d9c7638a5 > --- /dev/null > +++ b/dts/framework/remote_session/remote/interactive_shell.py > @@ -0,0 +1,98 @@ > +# SPDX-License-Identifier: BSD-3-Clause > +# Copyright(c) 2023 University of New Hampshire > + > +from pathlib import PurePath > +from typing import Callable > + > +from paramiko import Channel, SSHClient, channel # type: ignore > + > +from framework.logger import DTSLOG > +from framework.settings import SETTINGS > + > + > +class InteractiveShell: > + > + _interactive_session: SSHClient > + _stdin: channel.ChannelStdinFile > + _stdout: channel.ChannelFile > + _ssh_channel: Channel > + _logger: DTSLOG > + _timeout: float > + _startup_command: str > + _app_args: str > + _default_prompt: str =3D "" > + _privileged: bool > + _get_privileged_command: Callable[[str], str] > + # Allows for app specific extra characters to be appended to command= s > + _command_extra_chars: str =3D "" > + path: PurePath > + dpdk_app: bool =3D False > + > + def __init__( > + self, > + interactive_session: SSHClient, > + logger: DTSLOG, > + startup_command: str, > + privileged: bool, > + _get_privileged_command: Callable[[str], str], > + app_args: str =3D "", > + timeout: float =3D SETTINGS.timeout, > + ) -> None: > + self._interactive_session =3D interactive_session > + self._ssh_channel =3D self._interactive_session.invoke_shell() > + self._stdin =3D self._ssh_channel.makefile_stdin("w") > + self._stdout =3D self._ssh_channel.makefile("r") > + self._ssh_channel.settimeout(timeout) > + self._ssh_channel.set_combine_stderr(True) # combines stdout an= d stderr streams > + self._logger =3D logger > + self._timeout =3D timeout > + self._startup_command =3D startup_command > + self._app_args =3D app_args > + self._get_privileged_command =3D _get_privileged_command # type= : ignore > + self._privileged =3D privileged > + self._start_application() > + > + def _start_application(self) -> None: > + """Starts a new interactive application based on _startup_comman= d. > + > + This method is often overridden by subclasses as their process f= or > + starting may look different. > + """ > + start_command =3D f"{self._startup_command} {self._app_args}" > + if self._privileged: > + start_command =3D self._get_privileged_command(start_command= ) # type: ignore > + self.send_command(start_command) > + > + def send_command(self, command: str, prompt: str | None =3D None) ->= str: > + """Send a command and get all output before the expected ending = string. > + > + Lines that expect input are not included in the stdout buffer so= they cannot be > + used for expect. For example, if you were prompted to log into s= omething > + with a username and password, you cannot expect "username:" beca= use it won't > + yet be in the stdout buffer. A work around for this could be con= suming an > + extra newline character to force the current prompt into the std= out buffer. > + > + Returns: > + All output in the buffer before expected string > + """ > + self._logger.info(f"Sending command {command.strip()}...") Let's unite this log with with remote remote session: self._logger.info( f"Sending: '{command}'" + (f" with env vars: '{env}'" if env else "") ) We don't have env vars, but the rest should be the same. > + if prompt is None: > + prompt =3D self._default_prompt > + self._stdin.write(f"{command}{self._command_extra_chars}\n") > + self._stdin.flush() > + out: str =3D "" > + for line in self._stdout: > + out +=3D line > + if prompt in line and not line.rstrip().endswith( > + command.rstrip() > + ): # ignore line that sent command > + break > + self._logger.debug(f"Got output: {out}") > + return out > + > + def close(self) -> None: > + self._stdin.close() > + self._ssh_channel.close() > + > + def __del__(self) -> None: > + self.close()