From mboxrd@z Thu Jan 1 00:00:00 1970 X-GM-THRID: 7268555392064421888 X-Received: by 2002:a19:9112:0:b0:4fd:d517:fbd8 with SMTP id t18-20020a199112000000b004fdd517fbd8mr936704lfd.9.1692342432147; Fri, 18 Aug 2023 00:07:12 -0700 (PDT) X-BeenThere: isar-users@googlegroups.com Received: by 2002:a05:600c:1f19:b0:3fe:cf9d:6bee with SMTP id bd25-20020a05600c1f1900b003fecf9d6beels81004wmb.2.-pod-prod-00-eu-canary; Fri, 18 Aug 2023 00:07:10 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFnVdfJwPV3GmN025DHi/ud42myZxUn3WOzot4kQLoZbbMxamYpUEsF0ra2lZ8z7G5XtE15 X-Received: by 2002:a05:600c:a51:b0:3fe:1f70:9e54 with SMTP id c17-20020a05600c0a5100b003fe1f709e54mr3762444wmq.4.1692342430189; Fri, 18 Aug 2023 00:07:10 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1692342430; cv=none; d=google.com; s=arc-20160816; b=tJjlEA8rhh26hvPD7H0mbeNHhpvdnlKUGZFryMIv6unCpGY+D7IrVWIp9jU/8PSa2/ xfMd3ARFOzszu5gEvwovXf9QMuygVKc4dbYTEIUF8tUtPa2fouohnC55+Esd98yXhqoW RHci/ZIXZguzwq+aeB1mFN9bmaI2Q7idPY0EhNWrzs2Qalvml0JCHJ9VTxiTCHzAutjj WPYe11BP8fP7MYaEepf3zci5foRB9UB4xcIUIg25Ka1xW0/gfThiD09aAySaGgI6CNNB hM6Mh/uIeydF9NYquLbRU+Gr5bTgFvtuNF/D6FuC9wLjKO1NHww7+XgEzQ4s68az4OrA N/2w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from; bh=oQl4Rfo2h+ivvc7OUQs3wlVAhARzTe8pvkefdJGhZeA=; fh=swRs1+OhWjovx1IrvOlKBWsdq9manB5qdcuGoHoh5Ak=; b=EuRuZaNqUca3K+49ByVpJOPNH+NTuMPPRn2I7UO4nJjX2jPHsybSCPa8g4DF5mrFka h2wUnHecclYxgCE0yJkOAZGLA9AncuFdTRaB+wVBi6pXAFNAAdsXXW6I6XmEFOpio3Cs y0dHEs4J3zpDDJFaSxhH7Ey4DPk8FHGYVhxcC3evdyU9YeajOye7wr82abBUvHrRmthj NMOgGxGd72JT/LETJGSFHcaegO1TTd0GEU2DeWlEvmpctkfbElrdZowQ5Gt4WiXdZSJs eZRX8HcJE70ZG9hmgZMiAyaNbX3RfxCfPUxdFpovvuvxJ2Ihony0/cqaaavfU7xPf9RH bdMA== ARC-Authentication-Results: i=1; gmr-mx.google.com; spf=pass (google.com: domain of ubely@ilbers.de designates 85.214.156.166 as permitted sender) smtp.mailfrom=ubely@ilbers.de Return-Path: Received: from shymkent.ilbers.de (shymkent.ilbers.de. [85.214.156.166]) by gmr-mx.google.com with ESMTPS id p36-20020a05600c1da400b003fe16346f74si148048wms.0.2023.08.18.00.07.10 for (version=TLS1_2 cipher=ECDHE-ECDSA-CHACHA20-POLY1305 bits=256/256); Fri, 18 Aug 2023 00:07:10 -0700 (PDT) Received-SPF: pass (google.com: domain of ubely@ilbers.de designates 85.214.156.166 as permitted sender) client-ip=85.214.156.166; Authentication-Results: gmr-mx.google.com; spf=pass (google.com: domain of ubely@ilbers.de designates 85.214.156.166 as permitted sender) smtp.mailfrom=ubely@ilbers.de Received: from baighyz.m.ilbers.de (host-80-81-17-52.static.customer.m-online.net [80.81.17.52]) (authenticated bits=0) by shymkent.ilbers.de (8.15.2/8.15.2/Debian-8+deb9u1) with ESMTPSA id 37I7769n024239 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Fri, 18 Aug 2023 09:07:09 +0200 From: Uladzimir Bely To: isar-users@googlegroups.com Subject: [PATCH 7/8] cibuilder.py: enable output from remote scripts Date: Fri, 18 Aug 2023 09:07:05 +0200 Message-Id: <20230818070706.27913-8-ubely@ilbers.de> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20230818070706.27913-1-ubely@ilbers.de> References: <20230818070706.27913-1-ubely@ilbers.de> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-1.0 required=5.0 tests=ALL_TRUSTED autolearn=unavailable autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on shymkent.ilbers.de X-TUID: buH6cz6VERcS With this patch, `ssh_start()` and `vm_start()` functions become able to return stdout and stderr. Function `remote_send_file()` can be used to deliver files on remote machine. Function `remote_run()` is allowed to just run remote commands and it doesn't fail now when non-zero returncode. This allows to handle any returncode in a testcase, e.g.: ``` def test_custom(self): self.init() self.vm_start('arm64', 'bullseye', image='isar-image-ci') ret = self.remote_run(cmd='`) if ret[0] != 0: self.log.error(ret[2]) self.fail("Failed to run ") ``` Signed-off-by: Uladzimir Bely --- testsuite/cibuilder.py | 128 +++++++++++++++++++++++++---------------- 1 file changed, 80 insertions(+), 48 deletions(-) diff --git a/testsuite/cibuilder.py b/testsuite/cibuilder.py index 73c8ee2c..12f0e193 100755 --- a/testsuite/cibuilder.py +++ b/testsuite/cibuilder.py @@ -243,16 +243,25 @@ class CIBuilder(Test): '-p %s -o IdentityFile=%s %s@%s ' \ % (port, priv_key, user, host) - self.log.debug('Connect command:\n' + cmd_prefix) - return cmd_prefix def exec_cmd(self, cmd, cmd_prefix): - rc = subprocess.call('exec ' + str(cmd_prefix) + ' "' + str(cmd) + '"', shell=True, - stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - return rc + proc = subprocess.run('exec ' + str(cmd_prefix) + ' "' + str(cmd) + '"', shell=True, + stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + + return proc.returncode, proc.stdout, proc.stderr + + + def remote_send_file(self, src, dest, mode): + priv_key = self.prepare_priv_key() + cmd_prefix = self.get_ssh_cmd_prefix(self.ssh_user, self.ssh_host, self.ssh_port, priv_key) + + proc = subprocess.run('cat %s | %s install -m %s /dev/stdin %s' % + (src, cmd_prefix, mode, dest), shell=True, + stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + return proc.returncode, proc.stdout, proc.stderr def run_script(self, script, cmd_prefix): script_dir = self.params.get('test_script_dir', @@ -260,44 +269,45 @@ class CIBuilder(Test): script_path = script_dir + script.split()[0] script_args = ' '.join(script.split()[1:]) - self.log.debug("script_path: '%s'" % (script_path)) - self.log.debug("script args: '%s'" % (script_args)) - if not os.path.exists(script_path): self.log.error('Script not found: ' + script_path) - return 2 + return (2, '', 'Script not found: ' + script_path) + + rc, stdout, stderr = self.remote_send_file(script_path, "./ci.sh", "755") + + if rc != 0: + self.log.error('Failed to deploy the script on target') + return (rc, stdout, stderr) - # Copy the script to the target - rc = subprocess.call('cat %s | %s install -m 755 /dev/stdin ./ci.sh' % (script_path, cmd_prefix), shell=True, - stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) time.sleep(1) - # Run the script remotely with the arguments - if rc == 0: - rc = subprocess.call('%s ./ci.sh %s' % (cmd_prefix, script_args), shell=True, - stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - return rc + proc = subprocess.run('%s ./ci.sh %s' % (cmd_prefix, script_args), shell=True, + stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + return (proc.returncode, proc.stdout, proc.stderr) def wait_connection(self, cmd_prefix, timeout): - self.log.debug('Waiting for SSH server ready...') + self.log.info('Waiting for SSH server ready...') rc = None + stdout = "" + stderr = "" + goodcnt = 0 # Use 3 good SSH ping attempts to consider SSH connection is stable while time.time() < timeout and goodcnt < 3: goodcnt += 1 - rc = self.exec_cmd('/bin/true', cmd_prefix) + rc, stdout, stderr = self.exec_cmd('/bin/true', cmd_prefix) time.sleep(1) if rc != 0: goodcnt = 0 time_left = timeout - time.time() - self.log.debug('SSH ping result: %d, left: %.fs' % (rc, time_left)) + self.log.info('SSH ping result: %d, left: %.fs' % (rc, time_left)) - return rc + return rc, stdout, stderr def prepare_priv_key(self): @@ -310,45 +320,57 @@ class CIBuilder(Test): return priv_key - def remote_run(self, user, host, port, cmd, script, timeout=0): + def remote_run(self, cmd=None, script=None, timeout=0): + if cmd: + self.log.info('Remote command is `%s`' % (cmd)) + if script: + self.log.info('Remote script is `%s`' % (script)) + priv_key = self.prepare_priv_key() - cmd_prefix = self.get_ssh_cmd_prefix(user, host, port, priv_key) + cmd_prefix = self.get_ssh_cmd_prefix(self.ssh_user, self.ssh_host, self.ssh_port, priv_key) - rc = 0 - if timeout: - rc = self.wait_connection(cmd_prefix, timeout) + rc = None + stdout = "" + stderr = "" + + if timeout != 0: + rc, stdout, stderr = self.wait_connection(cmd_prefix, timeout) - if rc == 0: + if rc == 0 or timeout == 0: if cmd is not None: - rc = self.exec_cmd(cmd, cmd_prefix) - self.log.debug('`' + cmd + '` returned ' + str(rc)) + rc, stdout, stderr = self.exec_cmd(cmd, cmd_prefix) + self.log.info('`' + cmd + '` returned ' + str(rc)) elif script is not None: - rc = self.run_script(script, cmd_prefix) - self.log.debug('`' + script + '` returned ' + str(rc)) - else: - return None + rc, stdout, stderr = self.run_script(script, cmd_prefix) + self.log.info('`' + script + '` returned ' + str(rc)) - return rc + return rc, stdout, stderr def ssh_start(self, user='ci', host='localhost', port=22, cmd=None, script=None): self.log.info('===================================================') self.log.info('Running Isar SSH test for `%s@%s:%s`' % (user, host, port)) - self.log.info('Remote command is `%s`' % (cmd)) - self.log.info('Remote script is `%s`' % (script)) self.log.info('Isar build folder is: ' + self.build_dir) self.log.info('===================================================') self.check_init() + self.ssh_user = user + self.ssh_host = host + self.ssh_port = port + + priv_key = self.prepare_priv_key() + cmd_prefix = self.get_ssh_cmd_prefix(self.ssh_user, self.ssh_host, self.ssh_port, priv_key) + self.log.info('Connect command:\n' + cmd_prefix) + if cmd is not None or script is not None: - rc = self.remote_run(user, host, port, cmd, script) + rc, stdout, stderr = self.remote_run(cmd, script) if rc != 0: self.fail('Failed with rc=%s' % rc) - return + return stdout, stderr self.fail('No command to run specified') @@ -378,7 +400,7 @@ class CIBuilder(Test): p1 = subprocess.Popen('exec ' + ' '.join(cmdline), shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) - self.log.debug("Started VM with pid %s" % (p1.pid)) + self.log.info("Started VM with pid %s" % (p1.pid)) return p1, cmdline, boot_log @@ -401,7 +423,7 @@ class CIBuilder(Test): time.sleep(0.01) data = os.read(fd, 1024) if login_prompt in data: - self.log.debug('Got login prompt') + self.log.info('Got login prompt') return 0 if fd == p1.stderr.fileno(): app_log.error(p1.stderr.readline().rstrip()) @@ -456,7 +478,7 @@ class CIBuilder(Test): del(self.vm_dict[vm]) self.vm_dump_dict(vm) - self.log.debug("Stopped VM with pid %s" % (pid)) + self.log.info("Stopped VM with pid %s" % (pid)) def vm_start(self, arch='amd64', distro='buster', @@ -485,6 +507,9 @@ class CIBuilder(Test): run_qemu = True + stdout = "" + stderr = "" + if vm in self.vm_dict: pid, cmdline, boot_log = self.vm_dict[vm] @@ -492,11 +517,11 @@ class CIBuilder(Test): proc = subprocess.run("ps -o cmd= %d" % (pid), shell=True, text=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) if cmdline[0] in proc.stdout: - self.log.debug("Found '%s' process with pid '%d', use it" % (cmdline[0], pid)) + self.log.info("Found '%s' process with pid '%d', use it" % (cmdline[0], pid)) run_qemu = False if run_qemu: - self.log.debug("No qemu-system process for `%s` found, run new VM" % (vm)) + self.log.info("No qemu-system process for `%s` found, run new VM" % (vm)) p1, cmdline, boot_log = self.vm_turn_on(arch, distro, image, enforce_pcbios) self.vm_dict[vm] = p1.pid, cmdline, boot_log @@ -508,15 +533,20 @@ class CIBuilder(Test): self.fail('Failed to boot qemu machine') if cmd is not None or script is not None: - user='ci' - host='localhost' - port = 22 + self.ssh_user='ci' + self.ssh_host='localhost' + self.ssh_port = 22 for arg in cmdline: match = re.match(r".*hostfwd=tcp::(\d*).*", arg) if match: - port = match.group(1) + self.ssh_port = match.group(1) break - rc = self.remote_run(user, host, port, cmd, script, timeout) + + priv_key = self.prepare_priv_key() + cmd_prefix = self.get_ssh_cmd_prefix(self.ssh_user, self.ssh_host, self.ssh_port, priv_key) + self.log.info('Connect command:\n' + cmd_prefix) + + rc, stdout, stderr = self.remote_run(cmd, script, timeout) if rc != 0: if stop_vm: self.vm_turn_off(vm) @@ -531,3 +561,5 @@ class CIBuilder(Test): if stop_vm: self.vm_turn_off(vm) + + return stdout, stderr -- 2.20.1