X-Git-Url: https://gerrit.fd.io/r/gitweb?p=csit.git;a=blobdiff_plain;f=resources%2Flibraries%2Fpython%2FVPPUtil.py;h=e343d38d2ffbacd2583d97944318fc2faedfa72d;hp=865775f995da9f53f04924f2ddd16119c47e48d2;hb=6962831a1f1905e50a3d663c0cf3ce8c2873ecc9;hpb=3ff919f8eb9fa7eb98887f029be7f817de7a1303 diff --git a/resources/libraries/python/VPPUtil.py b/resources/libraries/python/VPPUtil.py index 865775f995..e343d38d2f 100644 --- a/resources/libraries/python/VPPUtil.py +++ b/resources/libraries/python/VPPUtil.py @@ -1,4 +1,4 @@ -# Copyright (c) 2019 Cisco and/or its affiliates. +# Copyright (c) 2021 Cisco and/or its affiliates. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: @@ -18,7 +18,7 @@ from robot.api import logger from resources.libraries.python.Constants import Constants from resources.libraries.python.DUTSetup import DUTSetup from resources.libraries.python.PapiExecutor import PapiSocketExecutor -from resources.libraries.python.ssh import exec_cmd_no_error +from resources.libraries.python.ssh import exec_cmd_no_error, exec_cmd from resources.libraries.python.topology import Topology, SocketType, NodeType @@ -58,11 +58,15 @@ class VPPUtil: def restart_vpp_service(node, node_key=None): """Restart VPP service on the specified topology node. + Disconnect possibly connected PAPI executor. + :param node: Topology node. :param node_key: Topology node key. :type node: dict :type node_key: str """ + # Containers have a separate lifecycle, but better be safe. + PapiSocketExecutor.disconnect_all_sockets_by_node(node) DUTSetup.restart_service(node, Constants.VPP_UNIT) if node_key: Topology.add_new_socket( @@ -85,11 +89,15 @@ class VPPUtil: def stop_vpp_service(node, node_key=None): """Stop VPP service on the specified topology node. + Disconnect possibly connected PAPI executor. + :param node: Topology node. :param node_key: Topology node key. :type node: dict :type node_key: str """ + # Containers have a separate lifecycle, but better be safe. + PapiSocketExecutor.disconnect_all_sockets_by_node(node) DUTSetup.stop_service(node, Constants.VPP_UNIT) if node_key: Topology.del_node_socket_id(node, SocketType.PAPI, node_key) @@ -113,8 +121,7 @@ class VPPUtil: :param node: Topology node. :type node: dict """ - cmd = u"command -v vpp" - exec_cmd_no_error(node, cmd, message=u"VPP is not installed!") + DUTSetup.verify_program_installed(node, u"vpp") @staticmethod def adjust_privileges(node): @@ -135,17 +142,23 @@ class VPPUtil: :param node: Topology node. :type node: dict """ - cmd = u"echo \"show ver\" | sudo socat - UNIX-CONNECT:/run/vpp/cli.sock" + cmd = u"echo \"show pci\" | sudo socat - UNIX-CONNECT:/run/vpp/cli.sock" exec_cmd_no_error( node, cmd, sudo=False, message=u"VPP failed to start!", retries=120 ) - cmd = u"vppctl show ver 2>&1 | fgrep -v \"Connection refused\" | " \ + cmd = u"vppctl show pci 2>&1 | fgrep -v \"Connection refused\" | " \ u"fgrep -v \"No such file or directory\"" exec_cmd_no_error( node, cmd, sudo=True, message=u"VPP failed to start!", retries=120 ) + # Properly enable cards in case they were disabled. This will be + # followed in https://jira.fd.io/browse/VPP-1934. + cmd = u"for i in $(sudo vppctl sho int | grep Eth | cut -d' ' -f1); do"\ + u" sudo vppctl set int sta $i up; done" + exec_cmd(node, cmd, sudo=False) + @staticmethod def verify_vpp(node): """Verify that VPP is installed and started on the specified topology @@ -155,7 +168,7 @@ class VPPUtil: :type node: dict :raises RuntimeError: If VPP service fails to start. """ - VPPUtil.verify_vpp_installed(node) + DUTSetup.verify_program_installed(node, 'vpp') try: # Verify responsiveness of vppctl. VPPUtil.verify_vpp_started(node) @@ -179,18 +192,28 @@ class VPPUtil: VPPUtil.verify_vpp(node) @staticmethod - def vpp_show_version(node): + def vpp_show_version( + node, remote_vpp_socket=Constants.SOCKSVR_PATH, log=True): """Run "show_version" PAPI command. + Socket is configurable, so VPP inside container can be accessed. + :param node: Node to run command on. + :param remote_vpp_socket: Path to remote socket to target VPP. + :param log: If true, show the result in Robot log. :type node: dict + :type remote_vpp_socket: str + :type log: bool :returns: VPP version. :rtype: str + :raises RuntimeError: If PAPI connection fails. + :raises AssertionError: If PAPI retcode is nonzero. """ cmd = u"show_version" - with PapiSocketExecutor(node) as papi_exec: + with PapiSocketExecutor(node, remote_vpp_socket) as papi_exec: reply = papi_exec.add(cmd).get_reply() - logger.info(f"VPP version: {reply[u'version']}\n") + if log: + logger.info(f"VPP version: {reply[u'version']}\n") return f"{reply[u'version']}" @staticmethod @@ -279,8 +302,13 @@ class VPPUtil: :param node: Topology node. :type node: dict """ - PapiSocketExecutor.run_cli_cmd_on_all_sockets( - node, u"elog trace api cli barrier") + try: + PapiSocketExecutor.run_cli_cmd_on_all_sockets( + node, u"event-logger trace api cli barrier") + except AssertionError: + # Perhaps an older VPP build is tested. + PapiSocketExecutor.run_cli_cmd_on_all_sockets( + node, u"elog trace api cli barrier") @staticmethod def vpp_enable_elog_traces_on_all_duts(nodes): @@ -347,15 +375,30 @@ class VPPUtil: with PapiSocketExecutor(node) as papi_exec: reply = papi_exec.add(cmd).get_reply() - threads_data = list() - for thread in reply[u"thread_data"]: - thread_data = list() - for item in thread: - if isinstance(item, str): - item = item.rstrip('\x00') - thread_data.append(item) - threads_data.append(thread_data) - + threads_data = reply[u"thread_data"] logger.trace(f"show threads:\n{threads_data}") return threads_data + + @staticmethod + def vpp_add_graph_node_next(node, graph_node_name, graph_next_name): + """Set the next node for a given node. + + :param node: Node to run command on. + :param graph_node_name: Graph node to add the next node on. + :param graph_next_name: Graph node to add as the next node. + :type node: dict + :type graph_node_name: str + :type graph_next_name: str + :returns: The index of the next graph node. + :rtype: int + """ + cmd = u"add_node_next" + args = dict( + node_name=graph_node_name, + next_name=graph_next_name + ) + with PapiSocketExecutor(node) as papi_exec: + reply = papi_exec.add(cmd, **args).get_reply() + + return reply[u"next_index"]