From nobody Mon Feb 9 18:18:28 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=linaro.org ARC-Seal: i=1; a=rsa-sha256; t=1582131020; cv=none; d=zohomail.com; s=zohoarc; b=hC+pUB4cCSX/QI+caAiTTkK8O8VTi2cEzujNLJeatBrVZisyKFVdX7vdiwxDDFPWw/dKLdfKIPvWLFdh6vxmGXS8Cwvjggj7VvQDvB5JdhPTaFWPBgEItnhu/sVCLwGHTjafF0bZqt0fpFPtZN38WrALJkZ5TDqpnXEu4W5ci4Q= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1582131020; h=Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:Message-ID:References:Sender:Subject:To; bh=36Q8JSf0N/o+sezmkSBG9jdKzoyNhca6OBIv/UTtZJ4=; b=bXRF56IowHfv6IpOguIKkauqbooxPcuCQkPGDDysA+WCXJ1jzhOMdBP2Qgu/A7qWPUTeLAk7IBlNCEl5vuTj3GLmYyaamvr96sds2Azson7Qs+5jpC8ouDhoZHsOX4r/N1TdmSTHnrMRrtOuVxJ3AU06Ytf9+9vAftP9QYgqWcc= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1582131020085855.8384548023964; Wed, 19 Feb 2020 08:50:20 -0800 (PST) Received: from localhost ([::1]:56330 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1j4SYE-0008Un-TK for importer@patchew.org; Wed, 19 Feb 2020 11:50:18 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:41972) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1j4SOH-00037m-DC for qemu-devel@nongnu.org; Wed, 19 Feb 2020 11:40:03 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1j4SOF-00083t-MV for qemu-devel@nongnu.org; Wed, 19 Feb 2020 11:40:01 -0500 Received: from mail-pf1-x42b.google.com ([2607:f8b0:4864:20::42b]:33699) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1j4SOF-00083K-Dl for qemu-devel@nongnu.org; Wed, 19 Feb 2020 11:39:59 -0500 Received: by mail-pf1-x42b.google.com with SMTP id n7so341497pfn.0 for ; Wed, 19 Feb 2020 08:39:59 -0800 (PST) Received: from Rfoley-MA01.hsd1.ma.comcast.net ([2601:199:4480:60c0:3cc2:5eb7:e248:ad23]) by smtp.gmail.com with ESMTPSA id a69sm112362pfa.129.2020.02.19.08.39.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 19 Feb 2020 08:39:57 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=36Q8JSf0N/o+sezmkSBG9jdKzoyNhca6OBIv/UTtZJ4=; b=AA8aXCXtJGNvVvQcMNARMLwDKoF7WNKiyp5laffKcMfqz7AlPPsLg4Zn0I7LMB0xOj QAnDAqttd/JdhrFrd4RWUcdgqxRCBZFEZ+fUOgOc4zq35Tfp/zkC1oiJ+7sLwjReyk1K alzBQ3UjvhySvbTWvhXezRGwprqxOgWJZdFDe4qL1g3Zpv4ntWRcfpa9DxmBGFbF+WgA 2NMUK5+uuKuG2hb7qI+SvBON9LvZikvJ445tDJBC2v4EuJRyJppxDdczCztgzn7jJTW/ JSsT0emWW3CP6EvjB4gCXHNhIe0NrsMeompRItWCu3KU3FqShsmqdwicH+GNadGcT/Ry Hqvw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=36Q8JSf0N/o+sezmkSBG9jdKzoyNhca6OBIv/UTtZJ4=; b=aXnf8ekBJa9LDHuy/mevXzwBEYoyoe5mhnJ5D6PclyMBdyQyiw2y1k4O/Igypj9tFa fpA0/fd9K/6qTwa+f9zdj7YkiWSAZKWNAbByPKJBKCuQN7DTpWjbk8hHrptG/Ip5H7Eg fGH2I/wjpnzgGj3Ftywf/HhnTjfiKKEXLXZbElJ5DnjYREnWN5Ss6ki9GYDcn/eK085P nkcZIWfMujROZPoX0JZ1/weyDRe0H1KOyvk84ooUGJiG90DWmmXayTH0UYh5WJrEpfFg SBnfB+tRdm9R40IRk/i93Dj7Kff0c2BWsIBmDkvr/EAQg/Cjqe5HLro9pWZk7CnpZh6s D7WA== X-Gm-Message-State: APjAAAVNpvxuZ6o0YB+Ec6o8rexrqxwXRsoyQnFavTBtPBx1lM1Xzy0d VB5YbzR7i+a8rvqpm6zGKqn1dSgMozg= X-Google-Smtp-Source: APXvYqyTTarftHIdBCC+plxvIQh3Vr81ShWTGLcEF3ba5ZGUpqJL85Wa3nLd1qRJT9j2qS8qkuKLtw== X-Received: by 2002:a63:d94d:: with SMTP id e13mr28064012pgj.240.1582130397876; Wed, 19 Feb 2020 08:39:57 -0800 (PST) From: Robert Foley To: qemu-devel@nongnu.org Subject: [PATCH v2 07/14] tests/vm: Add configuration to basevm.py Date: Wed, 19 Feb 2020 11:35:30 -0500 Message-Id: <20200219163537.22098-8-robert.foley@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200219163537.22098-1-robert.foley@linaro.org> References: <20200219163537.22098-1-robert.foley@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:4864:20::42b X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: philmd@redhat.com, alex.bennee@linaro.org, robert.foley@linaro.org, peter.puhov@linaro.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Added use of a configuration to tests/vm/basevm.py. The configuration provides parameters used to configure a VM. This allows for providing alternate configurations to the VM being created/launched. cpu, machine, memory, and NUMA configuration are all examples of configuration which we might want to vary on the VM being creat= ed or launched. This will for example allow for creating an aarch64 vm. Signed-off-by: Robert Foley --- tests/vm/basevm.py | 143 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 112 insertions(+), 31 deletions(-) diff --git a/tests/vm/basevm.py b/tests/vm/basevm.py index a22b59b23c..ed1b56bcea 100644 --- a/tests/vm/basevm.py +++ b/tests/vm/basevm.py @@ -30,15 +30,39 @@ import shutil import multiprocessing import traceback =20 -SSH_KEY =3D open(os.path.join(os.path.dirname(__file__), - "..", "keys", "id_rsa")).read() -SSH_PUB_KEY =3D open(os.path.join(os.path.dirname(__file__), - "..", "keys", "id_rsa.pub")).read() - +SSH_KEY_FILE =3D os.path.join(os.path.dirname(__file__), + "..", "keys", "id_rsa") +SSH_PUB_KEY_FILE =3D os.path.join(os.path.dirname(__file__), + "..", "keys", "id_rsa.pub") + +# This is the standard configuration. +# Any or all of these can be overridden by +# passing in a config argument to the VM constructor. +DEFAULT_CONFIG =3D { + 'cpu' : "max", + 'machine' : 'pc', + 'guest_user' : "qemu", + 'guest_pass' : "qemupass", + 'root_pass' : "qemupass", + 'ssh_key_file' : SSH_KEY_FILE, + 'ssh_pub_key_file': SSH_PUB_KEY_FILE, + 'memory' : "4G", + 'extra_args' : [], + 'qemu_args' : "", + 'dns' : "", + 'ssh_port' : 0, + 'install_cmds' : "", + 'boot_dev_type' : "block", + 'ssh_timeout' : 1, +} +BOOT_DEVICE =3D { + 'block' : "-drive file=3D{},if=3Dnone,id=3Ddrive0,cache=3Dwriteback "\ + "-device virtio-blk,drive=3Ddrive0,bootindex=3D0", + 'scsi' : "-device virtio-scsi-device,id=3Dscsi "\ + "-drive file=3D{},format=3Draw,if=3Dnone,id=3Dhd0 "\ + "-device scsi-hd,drive=3Dhd0,bootindex=3D0", +} class BaseVM(object): - GUEST_USER =3D "qemu" - GUEST_PASS =3D "qemupass" - ROOT_PASS =3D "qemupass" =20 envvars =3D [ "https_proxy", @@ -63,20 +87,31 @@ class BaseVM(object): # 4 is arbitrary, but greater than 2, # since we found we need to wait more than twice as long. tcg_ssh_timeout_multiplier =3D 4 - def __init__(self, debug=3DFalse, vcpus=3DNone, + def __init__(self, debug=3DFalse, vcpus=3DNone, config=3DNone, log_console=3DFalse): self._guest =3D None + # Allow input config to override defaults. + self._config =3D DEFAULT_CONFIG.copy() + if config !=3D None: + self._config.update(config) + self.validate_ssh_keys() self._tmpdir =3D os.path.realpath(tempfile.mkdtemp(prefix=3D"vm-te= st-", suffix=3D".tmp", dir=3D".")) atexit.register(shutil.rmtree, self._tmpdir) - - self._ssh_key_file =3D os.path.join(self._tmpdir, "id_rsa") - open(self._ssh_key_file, "w").write(SSH_KEY) - subprocess.check_call(["chmod", "600", self._ssh_key_file]) - - self._ssh_pub_key_file =3D os.path.join(self._tmpdir, "id_rsa.pub") - open(self._ssh_pub_key_file, "w").write(SSH_PUB_KEY) + # Copy the key files to a temporary directory. + # Also chmod the key file to agree with ssh requirements. + self._config['ssh_key'] =3D \ + open(self._config['ssh_key_file']).read().rstrip() + self._config['ssh_pub_key'] =3D \ + open(self._config['ssh_pub_key_file']).read().rstrip() + self._ssh_tmp_key_file =3D os.path.join(self._tmpdir, "id_rsa") + open(self._ssh_tmp_key_file, "w").write(self._config['ssh_key']) + subprocess.check_call(["chmod", "600", self._ssh_tmp_key_file]) + + self._ssh_tmp_pub_key_file =3D os.path.join(self._tmpdir, "id_rsa.= pub") + open(self._ssh_tmp_pub_key_file, + "w").write(self._config['ssh_pub_key']) =20 self._console_log_path =3D None if log_console: @@ -90,11 +125,14 @@ class BaseVM(object): self._stdout =3D sys.stdout else: self._stdout =3D self._devnull + netdev =3D "user,id=3Dvnet,hostfwd=3D:127.0.0.1:{}-:22" self._args =3D [ \ - "-nodefaults", "-m", "4G", - "-cpu", "max", - "-netdev", "user,id=3Dvnet,hostfwd=3D:127.0.0.1:0-:22" + - (",ipv6=3Dno" if not self.ipv6 else ""), + "-nodefaults", "-m", self._config['memory'], + "-cpu", self._config['cpu'], + "-netdev", + netdev.format(self._config['ssh_port']) + + (",ipv6=3Dno" if not self.ipv6 else "") + + (",dns=3D" + self._config['dns'] if self._config['dns'] else "= "), "-device", "virtio-net-pci,netdev=3Dvnet", "-vnc", "127.0.0.1:0,to=3D20"] if vcpus and vcpus > 1: @@ -105,6 +143,45 @@ class BaseVM(object): logging.info("KVM not available, not using -enable-kvm") self._data_args =3D [] =20 + if self._config['qemu_args'] !=3D None: + qemu_args =3D self._config['qemu_args'] + qemu_args =3D qemu_args.replace('\n',' ').replace('\r','') + # Remove any empty strings from list. + self._config['extra_args'] =3D [x for x in qemu_args.split(' '= ) if x] + + def validate_ssh_keys(self): + """Check to see if the ssh key files exist.""" + if 'ssh_key_file' not in self._config or\ + not os.path.exists(self._config['ssh_key_file']): + raise Exception("ssh key file not found.") + if 'ssh_pub_key_file' not in self._config or\ + not os.path.exists(self._config['ssh_pub_key_file']): + raise Exception("ssh pub key file not found.") + + def wait_boot(self, wait_string=3DNone): + """Wait for the standard string we expect + on completion of a normal boot. + The user can also choose to override with an + alternate string to wait for.""" + if wait_string is None: + if self.login_prompt is None: + raise Exception("self.login_prompt not defined") + wait_string =3D self.login_prompt + # Intentionally bump up the default timeout under TCG, + # since the console wait below takes longer. + timeout =3D self.socket_timeout + if not kvm_available(self.arch): + timeout *=3D 8 + self.console_init(timeout=3Dtimeout) + self.console_wait(wait_string) + + def __getattr__(self, name): + # Support direct access to config by key. + # for example, access self._config['cpu'] by self.cpu + if name.lower() in self._config.keys(): + return self._config[name.lower()] + return object.__getattribute__(self, name) + def _download_with_cache(self, url, sha256sum=3DNone, sha512sum=3DNone= ): def check_sha256sum(fname): if not sha256sum: @@ -136,8 +213,9 @@ class BaseVM(object): "-t", "-o", "StrictHostKeyChecking=3Dno", "-o", "UserKnownHostsFile=3D" + os.devnull, - "-o", "ConnectTimeout=3D1", - "-p", self.ssh_port, "-i", self._ssh_key_file] + "-o", + "ConnectTimeout=3D{}".format(self._config["ssh_timeout"= ]), + "-p", self.ssh_port, "-i", self._ssh_tmp_key_file] # If not in debug mode, set ssh to quiet mode to # avoid printing the results of commands. if not self.debug: @@ -186,16 +264,16 @@ class BaseVM(object): "virtio-blk,drive=3D%s,serial=3D%s,bootindex= =3D1" % (name, name)] =20 def boot(self, img, extra_args=3D[]): - args =3D self._args + [ - "-device", "VGA", - "-drive", "file=3D%s,if=3Dnone,id=3Ddrive0,cache=3Dwriteback" = % img, - "-device", "virtio-blk,drive=3Ddrive0,bootindex=3D0"] - args +=3D self._data_args + extra_args + boot_dev =3D BOOT_DEVICE[self._config['boot_dev_type']] + boot_params =3D boot_dev.format(img) + args =3D self._args + boot_params.split(' ') + args +=3D self._data_args + extra_args + self._config['extra_args'] + args +=3D ["-device", "VGA"] logging.debug("QEMU args: %s", " ".join(args)) qemu_bin =3D os.environ.get("QEMU", "qemu-system-" + self.arch) guest =3D QEMUMachine(binary=3Dqemu_bin, args=3Dargs, console_log=3Dself._console_log_path) - guest.set_machine('pc') + guest.set_machine(self._config['machine']) guest.set_console() try: guest.launch() @@ -307,7 +385,8 @@ class BaseVM(object): self.console_send(command) =20 def console_ssh_init(self, prompt, user, pw): - sshkey_cmd =3D "echo '%s' > .ssh/authorized_keys\n" % SSH_PUB_KEY.= rstrip() + sshkey_cmd =3D "echo '%s' > .ssh/authorized_keys\n" \ + % self._config['ssh_pub_key'].rstrip() self.console_wait_send("login:", "%s\n" % user) self.console_wait_send("Password:", "%s\n" % pw) self.console_wait_send(prompt, "mkdir .ssh\n") @@ -437,15 +516,17 @@ def parse_args(vmcls): parser.disable_interspersed_args() return parser.parse_args() =20 -def main(vmcls): +def main(vmcls, config=3DNone): try: + if config =3D=3D None: + config =3D {} args, argv =3D parse_args(vmcls) if not argv and not args.build_qemu and not args.build_image: print("Nothing to do?") return 1 logging.basicConfig(level=3D(logging.DEBUG if args.debug else logging.WARN)) - vm =3D vmcls(debug=3Dargs.debug, vcpus=3Dargs.jobs, + vm =3D vmcls(debug=3Dargs.debug, vcpus=3Dargs.jobs, config=3Dconfi= g, log_console=3Dargs.log_console) if args.build_image: if os.path.exists(args.image) and not args.force: --=20 2.17.1