def scp_and_execute_script(self, vat_name, node, timeout=10, json_out=True): """Copy vat_name script to node, execute it and return result. :param vat_name: Name of the vat script file. Full path and name of the script is required. :param node: Node to execute the VAT script on. :param timeout: Seconds to allow the script to run. :param json_out: Require JSON output. :type vat_name: str :type node: dict :type timeout: int :type json_out: bool :returns: Status code, stdout and stderr of executed script :rtype: tuple """ ssh = SSH() ssh.connect(node) ssh.scp(vat_name, vat_name) cmd = "sudo -S {vat} {json} < {input}".format( json="json" if json_out is True else "", vat=Constants.VAT_BIN_NAME, input=vat_name) (ret_code, stdout, stderr) = ssh.exec_command(cmd, timeout) self._ret_code = ret_code self._stdout = stdout self._stderr = stderr logger.trace("Command '{0}' returned {1}'".format(cmd, self._ret_code)) logger.trace("stdout: '{0}'".format(self._stdout)) logger.trace("stderr: '{0}'".format(self._stderr)) self._delete_files(node, vat_name)
def execute_script(self, vat_name, node, timeout=120, json_out=True, copy_on_execute=False): """Execute VAT script on remote node, and store the result. There is an option to copy script from local host to remote host before execution. Path is defined automatically. :param vat_name: Name of the vat script file. Only the file name of the script is required, the resources path is prepended automatically. :param node: Node to execute the VAT script on. :param timeout: Seconds to allow the script to run. :param json_out: Require JSON output. :param copy_on_execute: If true, copy the file from local host to remote before executing. :type vat_name: str :type node: dict :type timeout: int :type json_out: bool :type copy_on_execute: bool :raises SSHException: If cannot open connection for VAT. :raises SSHTimeout: If VAT execution is timed out. :raises RuntimeError: If VAT script execution fails. """ ssh = SSH() try: ssh.connect(node) except: raise SSHException( "Cannot open SSH connection to execute VAT " "command(s) from vat script {name}".format(name=vat_name)) if copy_on_execute: ssh.scp(vat_name, vat_name) remote_file_path = vat_name else: remote_file_path = '{0}/{1}/{2}'.format( Constants.REMOTE_FW_DIR, Constants.RESOURCES_TPL_VAT, vat_name) cmd = "{vat_bin} {json} in {vat_path} script".format( vat_bin=Constants.VAT_BIN_NAME, json="json" if json_out is True else "", vat_path=remote_file_path) try: ret_code, stdout, stderr = ssh.exec_command_sudo(cmd=cmd, timeout=timeout) except SSHTimeout: logger.error("VAT script execution timeout: {0}".format(cmd)) raise except: raise RuntimeError("VAT script execution failed: {0}".format(cmd)) self._ret_code = ret_code self._stdout = stdout self._stderr = stderr self._script_name = vat_name
def get_logs_from_node(dut_node): """ Get logs from node to the test executor machine. :param dut_node: Node to artifact the logs of. :type dut_node: dict """ ssh = SSH() ssh.connect(dut_node) ssh.scp(".", '/var/log/nStack/*.log', get=True, timeout=60, wildcard=True) (ret, _, _) = exec_cmd(dut_node, 'ls -l /var/log/app*.log') if ret == 0: ssh.scp(".", '/var/log/app*.log', get=True, timeout=60, wildcard=True) exec_cmd(dut_node, 'rm -rf /var/log/nStack/*.log', sudo=True) exec_cmd(dut_node, 'rm -rf /var/log/app*.log', sudo=True)
def run_traffic_script_on_dut(node, script, cores, reserved=2, *args, **kwargs): """Copy traffic script over to the specified node and execute with the provided arguments. :param node: Node in topology. :param script: Name of the script to execute. :param cores: Number of processor cores to use. :param reserved: Number of cores reserved for other tasks. Default is 2, one for system tasks and one for VPP main thread. :param args: Sequential arguments for the script. :param kwargs: Named arguments for the script. :type node: dict :type script: str :type cores: int :type reserved: int :type args: list :type kwargs: dict """ path = "resources/traffic_scripts/honeycomb/{0}".format(script) # Assemble arguments for traffic script arguments = "" for arg in args: arguments += "{0} ".format(arg) for key, value in kwargs.items(): arguments += "--{0} {1} ".format(key, value) ssh = SSH() ssh.connect(node) ssh.scp(path, "/tmp") # Use alternate scheduler, Ubuntu's default can't load-balance # over isolcpus scheduler = "chrt -f 99" core_afi = "taskset -c {first}-{last}".format(first=reserved, last=cores - 1) cmd = "{scheduler} {affinity} python /tmp/{script} {args}".format( scheduler=scheduler, affinity=core_afi, script=script, args=arguments) ret_code, stdout, _ = ssh.exec_command_sudo(cmd, timeout=600) ssh.exec_command("sudo pkill python ; rm /tmp/{0}".format(script)) if ret_code != 0: raise HoneycombError("Traffic script failed to execute.") for line in stdout.splitlines(): if "Avg. requests" in line: return line
def copy_tarball_to_node(tarball, node): """Copy tarball file from local host to remote node. :param tarball: Path to tarball to upload. :param node: Node in the topology where the tarball will be copied to. :type tarball: str :type node: dict :returns: nothing """ logger.console('Copying tarball to {0}'.format(node['host'])) ssh = SSH() ssh.connect(node) ssh.scp(tarball, "/tmp/")
def copy_tarball_to_node(tarball, node): """Copy tarball file from local host to remote node. :param tarball: Path to tarball to upload. :param node: Dictionary created from topology. :type tarball: str :type node: dict :returns: nothing """ logger.console('Copying tarball to {0}'.format(node['host'])) ssh = SSH() ssh.connect(node) ssh.scp(tarball, "/tmp/")
def scp_and_execute_cli_script(self, fname, node, timeout=15, json_out=True): """Copy vat_name script to node, execute it and return result. :param fname: Name of the VPP script file. Full path and name of the script is required. :param node: Node to execute the VPP script on. :param timeout: Seconds to allow the script to run. :param json_out: Require JSON output. :type fname: str :type node: dict :type timeout: int :type json_out: bool :returns: Status code, stdout and stderr of executed CLI script. :rtype: tuple :raises RuntimeError: If CLI script execution failed. """ ssh = SSH() try: ssh.connect(node) except: raise SSHException("Cannot open SSH connection to execute CLI " "command(s) from template {0}".format(fname)) ssh.scp(fname, fname) cmd = "{vat} {json}".format(json="json" if json_out is True else "", vat=Constants.VAT_BIN_NAME) cmd_input = "exec exec {0}".format(fname) try: (ret_code, stdout, stderr) = ssh.exec_command_sudo(cmd, cmd_input, timeout) except SSHTimeout: logger.error("CLI script execution timeout: {0}{1}".format( cmd, "<<< " + cmd_input if cmd_input else "")) raise except: raise RuntimeError("CLI script execution failed: {0}{1}".format( cmd, "<<< " + cmd_input if cmd_input else "")) self._ret_code = ret_code self._stdout = stdout self._stderr = stderr self._delete_files(node, fname)
def archive_honeycomb_log(node, perf=False): """Copy honeycomb log file from DUT node to VIRL for archiving. :param node: Honeycomb node. :param perf: Alternate handling, for use with performance test topology. :type node: dict :type perf: bool """ ssh = SSH() ssh.connect(node) if not perf: cmd = "cp /var/log/honeycomb/honeycomb.log /scratch/" ssh.exec_command_sudo(cmd) else: ssh.scp(".", "/var/log/honeycomb/honeycomb.log", get=True)
def execute_script(self, vat_name, node, timeout=120, json_out=True, copy_on_execute=False, history=True): """Execute VAT script on remote node, and store the result. There is an option to copy script from local host to remote host before execution. Path is defined automatically. :param vat_name: Name of the vat script file. Only the file name of the script is required, the resources path is prepended automatically. :param node: Node to execute the VAT script on. :param timeout: Seconds to allow the script to run. :param json_out: Require JSON output. :param copy_on_execute: If true, copy the file from local host to remote before executing. :param history: If true, add command to history. :type vat_name: str :type node: dict :type timeout: int :type json_out: bool :type copy_on_execute: bool :type history: bool :raises SSHException: If cannot open connection for VAT. :raises SSHTimeout: If VAT execution is timed out. :raises RuntimeError: If VAT script execution fails. """ ssh = SSH() try: ssh.connect(node) except: raise SSHException( f"Cannot open SSH connection to execute VAT command(s) " f"from vat script {vat_name}") if copy_on_execute: ssh.scp(vat_name, vat_name) remote_file_path = vat_name if history: with open(vat_name, u"rt") as vat_file: for line in vat_file: PapiHistory.add_to_papi_history(node, line.replace( u"\n", u""), papi=False) else: remote_file_path = f"{Constants.REMOTE_FW_DIR}/" \ f"{Constants.RESOURCES_TPL_VAT}/{vat_name}" cmd = f"{Constants.VAT_BIN_NAME}" \ f"{u' json' if json_out is True else u''} " \ f"in {remote_file_path} script" try: ret_code, stdout, stderr = ssh.exec_command_sudo(cmd=cmd, timeout=timeout) except SSHTimeout: logger.error(f"VAT script execution timeout: {cmd}") raise except Exception: raise RuntimeError(f"VAT script execution failed: {cmd}") self._ret_code = ret_code self._stdout = stdout self._stderr = stderr self._script_name = vat_name
def main(): """Copy and load of Docker image.""" parser = argparse.ArgumentParser() parser.add_argument("-t", "--topo", required=True, help="Topology file") parser.add_argument("-d", "--directory", required=True, help="Destination directory") parser.add_argument("-i", "--images", required=False, nargs='+', help="Images paths to copy") parser.add_argument("-c", "--cancel", help="Cancel all", action="store_true") args = parser.parse_args() topology_file = args.topo images = args.images directory = args.directory cancel_all = args.cancel work_file = open(topology_file) topology = load(work_file.read())['nodes'] ssh = SSH() for node in topology: if topology[node]['type'] == "DUT": print("###TI host: {host}".format(host=topology[node]['host'])) ssh.connect(topology[node]) if cancel_all: # Remove destination directory on DUT cmd = "rm -r {directory}".format(directory=directory) stdout = ssh_ignore_error(ssh, cmd) print("###TI {stdout}".format(stdout=stdout)) else: # Create installation directory on DUT cmd = "rm -r {directory}; mkdir {directory}"\ .format(directory=directory) stdout = ssh_no_error(ssh, cmd) print("###TI {stdout}".format(stdout=stdout)) # Copy images from local path to destination dir for image in images: print("###TI scp: {}".format(image)) ssh.scp(local_path=image, remote_path=directory) # Load image to Docker. cmd = "for f in {directory}/*.tar.gz; do "\ "sudo docker load -i $f; done".format(directory=directory) stdout = ssh_no_error(ssh, cmd) print("###TI {}".format(stdout)) # Remove <none> images from Docker. cmd = "docker rmi $(sudo docker images -f 'dangling=true' -q)" stdout = ssh_no_error(ssh, cmd, sudo=True) print("###TI {}".format(stdout))
def main(): """Copy and installation of VPP packages.""" parser = argparse.ArgumentParser() parser.add_argument("-t", "--topo", required=True, help="Topology file") parser.add_argument("-d", "--directory", required=True, help="Installation directory") parser.add_argument("-p", "--packages", required=False, nargs='+', help="Packages paths to copy") parser.add_argument("-c", "--cancel", help="Cancel installation", action="store_true") args = parser.parse_args() topology_file = args.topo packages = args.packages install_dir = args.directory cancel_installation = args.cancel work_file = open(topology_file) topology = load(work_file.read())['nodes'] ssh = SSH() for node in topology: if topology[node]['type'] == "DUT": print "###TI host: {}".format(topology[node]['host']) ssh.connect(topology[node]) if cancel_installation: # Remove installation directory on DUT cmd = "rm -r {}".format(install_dir) stdout = ssh_ignore_error(ssh, cmd) print "###TI {}".format(stdout) cmd = "dpkg -l | grep vpp" ret, _, _ = ssh.exec_command(cmd) if ret == 0: # Try to fix interrupted installations cmd = 'dpkg --configure -a' stdout = ssh_no_error(ssh, cmd, sudo=True) print "###TI {}".format(stdout) # Try to remove installed vpp.* packages cmd = 'apt-get purge -y "vpp.*"' stdout = ssh_no_error(ssh, cmd, sudo=True) print "###TI {}".format(stdout) else: # Create installation directory on DUT cmd = "rm -r {0}; mkdir {0}".format(install_dir) stdout = ssh_no_error(ssh, cmd) print "###TI {}".format(stdout) # Copy packages from local path to installation dir for deb in packages: print "###TI scp: {}".format(deb) ssh.scp(local_path=deb, remote_path=install_dir) cmd = "dpkg -l | grep vpp" ret, _, _ = ssh.exec_command(cmd) if ret == 0: # Try to fix interrupted installations cmd = 'dpkg --configure -a' stdout = ssh_no_error(ssh, cmd, sudo=True) print "###TI {}".format(stdout) # Try to remove installed vpp.* packages cmd = 'apt-get purge -y "vpp.*"' stdout = ssh_no_error(ssh, cmd, sudo=True) print "###TI {}".format(stdout) # Installation of VPP deb packages cmd = "dpkg -i --force-all {}/*.deb".format(install_dir) stdout = ssh_no_error(ssh, cmd, sudo=True) print "###TI {}".format(stdout)