All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v1 00/14] tests/vm: Add support for aarch64 VMs
@ 2020-02-05 21:29 Robert Foley
  2020-02-05 21:29 ` [PATCH v1 01/14] tests/vm: use $(PYTHON) consistently Robert Foley
                   ` (14 more replies)
  0 siblings, 15 replies; 25+ messages in thread
From: Robert Foley @ 2020-02-05 21:29 UTC (permalink / raw)
  To: qemu-devel; +Cc: fam, philmd, alex.bennee, robert.foley, peter.puhov

This is version 1 of the patch series to 
add support for 2 aarch64 VMs.  
 - Ubuntu 18.04 aarch64 VM
 - CentOS 8 aarch64 VM
 
Changes in version 1
- Added environment variable QEMU_LOCAL=1 which means
  use the appropriate QEMU binary from the current build.
- Improved support of aarch64 VMs to be backwards compatible
  by default with older versions of QEMU.
- Fixed a locale issue with ubuntu.aarch64 VM.
  The issue here was that we were not waiting for the cloud-init to finish,
  prior to rebooting the VM.
- Workaround of issue where the test hangs as QEMU is waiting for
  the consumption of character device data.  Workaround adds a 
  thread to the test framework to consume these characters and dump them
  to a file. The test then consumes these characters from the file instead of
  from the character device as it did previously.
  One advantage of this change is that there is now a log file which 
  contains the console output for debug.
- Change creation of aarch64 flash files to be in temp directory.
- Added changes to convert existing scripts to using self._config for
  SSH_KEY_PUB, GUEST_USER, GUEST_PASS, ROOT_PASS.
- Created example config file for x86, renamed existing 
  example file to aarch64.
- Make gen_cloud_init_iso() common to basevm.
- Updated wait_ssh() to only extend time when we are under TCG.
- Changed wait_ssh() to wait for root or wait for guest user, not both.
- Removed SSH_KEY global as it is no longer needed.
- Clarified use of ssh_key_file and ssh_pub_key_file,
  added tmp to the names to clarify, and added a comment to explain use here.
- Cleaned up handling of the boot_console option.
- Moved tweak to Makefile.include to a separate patch.
- Removed setting of tcg,thread=multi in aarch64 VMs.
- Moved the validation of ssh keys to a common location.
- Reworked the handling of the config file yaml to
  simply set the values into the config dictionary in one step.

More details on the patch in general:
In order to add support for the two new aarch64 VMs, we
generalized and parameterized basevm.py.  
We added a new concept of a configuration, which is really just a 
set of parameters which define how to configure the VM.  
Some examples of parameters are "machine", "memory" and "cpu".
We preserved current default parameters.
Current configuration of pre-existing VMs is supported by default
without need to override default parameters.
 
For example, previously only the 'pc' machine was supported in basevm.py. 
The new aarch64 VMs will override machine to use virt. 
There are a few other examples where we needed to add parameters 
in order to add support for these aarch64 VMs.
In some other cases we added parameters that we thought would be useful
in general, for example username/password, ssh keys, 

In the case of the aarch64 VMs, they override certain parameters
by default.  However, it is also of value to be able to 
dynamically specify other values for these parameters.
Take the case where you create a new VM using vm-build,
but then want to test it using various hardware configurations
such as for example different NUMA topologies. 
Or maybe you want to use a different amount of memory or a different cpu type.

In order to support these use cases we added support
for a configuration .yml file, which allows the user to
specify certain values dynamically such as:
 - machine
 - cpu
 - memory size
 - other qemu args, which allow configuring alternate
   hardware topologies such as NUMA nodes.
 - username, password
 - ssh keys
 For an example of a .yml file, see the included config_example.yml
 
The main use case for using this config.yml file is for where we
are testing/debugging with qemu (vm-build), and need to configure
the VM differently.  However, there is another use case we have
developed, which is a project called lisa-qemu 
(https://github.com/rf972/lisa-qemu).  
This project is an integration between the LISA tool and QEMU.  
This project uses the VMs created by
QEMU's vm-build scripts for use in testing with LISA.  
This use case is similar to the vm-build case in that,
the VM gets created once, and we want to launch the VM with different
configurations (memory, cpu, etc.).
 
As part of developing the scripts for these VMs, we implemented
a few enhancements to help with testing.
For example, we added support for allowing debug mode to
show the ssh output.
We also added support for a new --boot-console option which
will show the boot console as the VM boots up to aid in 
debugging problems during VM boot.

Robert Foley (14):
  tests/vm: use $(PYTHON) consistently
  tests/vm: Debug mode shows ssh output.
  tests/vm: increased max timeout for vm boot.
  tests/vm: give wait_ssh() option to wait for root
  tests/vm: Added gen_cloud_init_iso() to basevm.py
  tests/vm: Add logging of console to file.
  tests/vm: Add configuration to basevm.py
  tests/vm: Added configuration file support
  tests/vm: add --boot-console switch
  tests/vm: Add ability to select QEMU from current build.
  tests/vm: allow wait_ssh() to specify command
  tests/vm: Added a new script for ubuntu.aarch64.
  tests/vm: Added a new script for centos.aarch64.
  tests/vm: change scripts to use self._config

 tests/vm/Makefile.include         |  16 +-
 tests/vm/aarch64vm.py             | 100 +++++++++
 tests/vm/basevm.py                | 324 +++++++++++++++++++++++++-----
 tests/vm/centos                   |  33 +--
 tests/vm/centos-8-aarch64.ks      |  51 +++++
 tests/vm/centos.aarch64           | 221 ++++++++++++++++++++
 tests/vm/conf_example_aarch64.yml |  51 +++++
 tests/vm/conf_example_x86.yml     |  50 +++++
 tests/vm/fedora                   |  17 +-
 tests/vm/freebsd                  |  16 +-
 tests/vm/netbsd                   |  19 +-
 tests/vm/openbsd                  |  17 +-
 tests/vm/socket_thread.py         |  73 +++++++
 tests/vm/ubuntu.aarch64           | 113 +++++++++++
 tests/vm/ubuntu.i386              |  37 +---
 15 files changed, 987 insertions(+), 151 deletions(-)
 create mode 100644 tests/vm/aarch64vm.py
 create mode 100644 tests/vm/centos-8-aarch64.ks
 create mode 100755 tests/vm/centos.aarch64
 create mode 100644 tests/vm/conf_example_aarch64.yml
 create mode 100644 tests/vm/conf_example_x86.yml
 create mode 100644 tests/vm/socket_thread.py
 create mode 100755 tests/vm/ubuntu.aarch64

-- 
2.17.1



^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH v1 01/14] tests/vm: use $(PYTHON) consistently
  2020-02-05 21:29 [PATCH v1 00/14] tests/vm: Add support for aarch64 VMs Robert Foley
@ 2020-02-05 21:29 ` Robert Foley
  2020-02-07 11:42   ` Alex Bennée
  2020-02-05 21:29 ` [PATCH v1 02/14] tests/vm: Debug mode shows ssh output Robert Foley
                   ` (13 subsequent siblings)
  14 siblings, 1 reply; 25+ messages in thread
From: Robert Foley @ 2020-02-05 21:29 UTC (permalink / raw)
  To: qemu-devel; +Cc: fam, philmd, alex.bennee, robert.foley, peter.puhov

Change Makefile.include to use $(PYTHON) so for vm-boot-ssh to be
consistent with other cases like vm-build.

Signed-off-by: Robert Foley <robert.foley@linaro.org>
---
 tests/vm/Makefile.include | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/vm/Makefile.include b/tests/vm/Makefile.include
index 9e7c46a473..778e506755 100644
--- a/tests/vm/Makefile.include
+++ b/tests/vm/Makefile.include
@@ -80,7 +80,7 @@ vm-boot-serial-%: $(IMAGES_DIR)/%.img
 
 vm-boot-ssh-%: $(IMAGES_DIR)/%.img
 	$(call quiet-command, \
-		$(SRC_PATH)/tests/vm/$* \
+		$(PYTHON) $(SRC_PATH)/tests/vm/$* \
 		$(if $(J),--jobs $(J)) \
 		--image "$<" \
 		--interactive \
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v1 02/14] tests/vm: Debug mode shows ssh output.
  2020-02-05 21:29 [PATCH v1 00/14] tests/vm: Add support for aarch64 VMs Robert Foley
  2020-02-05 21:29 ` [PATCH v1 01/14] tests/vm: use $(PYTHON) consistently Robert Foley
@ 2020-02-05 21:29 ` Robert Foley
  2020-02-05 21:29 ` [PATCH v1 03/14] tests/vm: increased max timeout for vm boot Robert Foley
                   ` (12 subsequent siblings)
  14 siblings, 0 replies; 25+ messages in thread
From: Robert Foley @ 2020-02-05 21:29 UTC (permalink / raw)
  To: qemu-devel; +Cc: fam, philmd, alex.bennee, robert.foley, peter.puhov

Add changes to tests/vm/basevm.py so that during debug mode we show ssh output.

Signed-off-by: Robert Foley <robert.foley@linaro.org>
Reviewed-by: Peter Puhov <peter.puhov@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
---
 tests/vm/basevm.py | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/tests/vm/basevm.py b/tests/vm/basevm.py
index ed5dd4f3d0..991115e44b 100755
--- a/tests/vm/basevm.py
+++ b/tests/vm/basevm.py
@@ -122,11 +122,16 @@ class BaseVM(object):
         return fname
 
     def _ssh_do(self, user, cmd, check):
-        ssh_cmd = ["ssh", "-q", "-t",
+        ssh_cmd = ["ssh",
+                   "-t",
                    "-o", "StrictHostKeyChecking=no",
                    "-o", "UserKnownHostsFile=" + os.devnull,
                    "-o", "ConnectTimeout=1",
                    "-p", self.ssh_port, "-i", self._ssh_key_file]
+        # If not in debug mode, set ssh to quiet mode to
+        # avoid printing the results of commands.
+        if not self.debug:
+            ssh_cmd.append("-q")
         for var in self.envvars:
             ssh_cmd += ['-o', "SendEnv=%s" % var ]
         assert not isinstance(cmd, str)
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v1 03/14] tests/vm: increased max timeout for vm boot.
  2020-02-05 21:29 [PATCH v1 00/14] tests/vm: Add support for aarch64 VMs Robert Foley
  2020-02-05 21:29 ` [PATCH v1 01/14] tests/vm: use $(PYTHON) consistently Robert Foley
  2020-02-05 21:29 ` [PATCH v1 02/14] tests/vm: Debug mode shows ssh output Robert Foley
@ 2020-02-05 21:29 ` Robert Foley
  2020-02-07 12:01   ` Alex Bennée
  2020-02-05 21:29 ` [PATCH v1 04/14] tests/vm: give wait_ssh() option to wait for root Robert Foley
                   ` (11 subsequent siblings)
  14 siblings, 1 reply; 25+ messages in thread
From: Robert Foley @ 2020-02-05 21:29 UTC (permalink / raw)
  To: qemu-devel; +Cc: fam, philmd, alex.bennee, robert.foley, peter.puhov

Add change to increase timeout waiting for VM to boot.
Needed for some emulation cases where it can take longer
than 5 minutes to boot.

Signed-off-by: Robert Foley <robert.foley@linaro.org>
---
 tests/vm/basevm.py | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/tests/vm/basevm.py b/tests/vm/basevm.py
index 991115e44b..4de358ae22 100755
--- a/tests/vm/basevm.py
+++ b/tests/vm/basevm.py
@@ -59,6 +59,10 @@ class BaseVM(object):
     poweroff = "poweroff"
     # enable IPv6 networking
     ipv6 = True
+    # Scale up some timeouts under TCG.
+    # 4 is arbitrary, but greater than 2,
+    # since we found we need to wait more than twice as long.
+    tcg_ssh_timeout_multiplier = 4
     def __init__(self, debug=False, vcpus=None):
         self._guest = None
         self._tmpdir = os.path.realpath(tempfile.mkdtemp(prefix="vm-test-",
@@ -311,6 +315,9 @@ class BaseVM(object):
         sys.stderr.write("### %s ...\n" % text)
 
     def wait_ssh(self, seconds=300):
+        # Allow more time for VM to boot under TCG.
+        if not kvm_available(self.arch):
+            seconds *= self.tcg_ssh_timeout_multiplier
         starttime = datetime.datetime.now()
         endtime = starttime + datetime.timedelta(seconds=seconds)
         guest_up = False
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v1 04/14] tests/vm: give wait_ssh() option to wait for root
  2020-02-05 21:29 [PATCH v1 00/14] tests/vm: Add support for aarch64 VMs Robert Foley
                   ` (2 preceding siblings ...)
  2020-02-05 21:29 ` [PATCH v1 03/14] tests/vm: increased max timeout for vm boot Robert Foley
@ 2020-02-05 21:29 ` Robert Foley
  2020-02-07 12:01   ` Alex Bennée
  2020-02-05 21:29 ` [PATCH v1 05/14] tests/vm: Added gen_cloud_init_iso() to basevm.py Robert Foley
                   ` (10 subsequent siblings)
  14 siblings, 1 reply; 25+ messages in thread
From: Robert Foley @ 2020-02-05 21:29 UTC (permalink / raw)
  To: qemu-devel; +Cc: fam, philmd, alex.bennee, robert.foley, peter.puhov

Allow wait_ssh to wait for root user to be ready.
This solves the issue where we perform a wait_ssh()
successfully, but the root user is not yet ready
to be logged in.

Signed-off-by: Robert Foley <robert.foley@linaro.org>
---
 tests/vm/basevm.py | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/tests/vm/basevm.py b/tests/vm/basevm.py
index 4de358ae22..a29099f6f1 100755
--- a/tests/vm/basevm.py
+++ b/tests/vm/basevm.py
@@ -314,7 +314,7 @@ class BaseVM(object):
     def print_step(self, text):
         sys.stderr.write("### %s ...\n" % text)
 
-    def wait_ssh(self, seconds=300):
+    def wait_ssh(self, wait_root=False, seconds=300):
         # Allow more time for VM to boot under TCG.
         if not kvm_available(self.arch):
             seconds *= self.tcg_ssh_timeout_multiplier
@@ -322,7 +322,10 @@ class BaseVM(object):
         endtime = starttime + datetime.timedelta(seconds=seconds)
         guest_up = False
         while datetime.datetime.now() < endtime:
-            if self.ssh("exit 0") == 0:
+            if wait_root and self.ssh_root("exit 0") == 0:
+                guest_up = True
+                break
+            elif self.ssh("exit 0") == 0:
                 guest_up = True
                 break
             seconds = (endtime - datetime.datetime.now()).total_seconds()
@@ -333,7 +336,6 @@ class BaseVM(object):
 
     def shutdown(self):
         self._guest.shutdown()
-
     def wait(self):
         self._guest.wait()
 
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v1 05/14] tests/vm: Added gen_cloud_init_iso() to basevm.py
  2020-02-05 21:29 [PATCH v1 00/14] tests/vm: Add support for aarch64 VMs Robert Foley
                   ` (3 preceding siblings ...)
  2020-02-05 21:29 ` [PATCH v1 04/14] tests/vm: give wait_ssh() option to wait for root Robert Foley
@ 2020-02-05 21:29 ` Robert Foley
  2020-02-07 12:22   ` Alex Bennée
  2020-02-05 21:29 ` [PATCH v1 06/14] tests/vm: Add logging of console to file Robert Foley
                   ` (9 subsequent siblings)
  14 siblings, 1 reply; 25+ messages in thread
From: Robert Foley @ 2020-02-05 21:29 UTC (permalink / raw)
  To: qemu-devel; +Cc: fam, philmd, alex.bennee, robert.foley, peter.puhov

This method was located in both centos and ubuntu.i386.

Signed-off-by: Robert Foley <robert.foley@linaro.org>
---
 tests/vm/basevm.py   | 40 ++++++++++++++++++++++++++++++++++++++++
 tests/vm/centos      | 33 +--------------------------------
 tests/vm/ubuntu.i386 | 37 +------------------------------------
 3 files changed, 42 insertions(+), 68 deletions(-)

diff --git a/tests/vm/basevm.py b/tests/vm/basevm.py
index a29099f6f1..a926211da8 100755
--- a/tests/vm/basevm.py
+++ b/tests/vm/basevm.py
@@ -346,6 +346,46 @@ class BaseVM(object):
     def qmp(self, *args, **kwargs):
         return self._guest.qmp(*args, **kwargs)
 
+    def gen_cloud_init_iso(self):
+        cidir = self._tmpdir
+        mdata = open(os.path.join(cidir, "meta-data"), "w")
+        name = self.name.replace(".","-")
+        mdata.writelines(["instance-id: {}-vm-0\n".format(name),
+                          "local-hostname: {}-guest\n".format(name)])
+        mdata.close()
+        udata = open(os.path.join(cidir, "user-data"), "w")
+        print("guest user:pw {}:{}".format(self._config['guest_user'],
+                                           self._config['guest_pass']))
+        udata.writelines(["#cloud-config\n",
+                          "chpasswd:\n",
+                          "  list: |\n",
+                          "    root:%s\n" % self._config['root_pass'],
+                          "    %s:%s\n" % (self._config['guest_user'],
+                                           self._config['guest_pass']),
+                          "  expire: False\n",
+                          "users:\n",
+                          "  - name: %s\n" % self._config['guest_user'],
+                          "    sudo: ALL=(ALL) NOPASSWD:ALL\n",
+                          "    ssh-authorized-keys:\n",
+                          "    - %s\n" % self._config['ssh_pub_key'],
+                          "  - name: root\n",
+                          "    ssh-authorized-keys:\n",
+                          "    - %s\n" % self._config['ssh_pub_key'],
+                          "locale: en_US.UTF-8\n"])
+        proxy = os.environ.get("http_proxy")
+        if not proxy is None:
+            udata.writelines(["apt:\n",
+                              "  proxy: %s" % proxy])
+        udata.close()
+        subprocess.check_call(["genisoimage", "-output", "cloud-init.iso",
+                               "-volid", "cidata", "-joliet", "-rock",
+                               "user-data", "meta-data"],
+                               cwd=cidir,
+                               stdin=self._devnull, stdout=self._stdout,
+                               stderr=self._stdout)
+
+        return os.path.join(cidir, "cloud-init.iso")
+
 def parse_args(vmcls):
 
     def get_default_jobs():
diff --git a/tests/vm/centos b/tests/vm/centos
index f2f0befd84..c108bd6799 100755
--- a/tests/vm/centos
+++ b/tests/vm/centos
@@ -31,37 +31,6 @@ class CentosVM(basevm.BaseVM):
         make docker-test-mingw@fedora  {verbose} J={jobs} NETWORK=1;
     """
 
-    def _gen_cloud_init_iso(self):
-        cidir = self._tmpdir
-        mdata = open(os.path.join(cidir, "meta-data"), "w")
-        mdata.writelines(["instance-id: centos-vm-0\n",
-                          "local-hostname: centos-guest\n"])
-        mdata.close()
-        udata = open(os.path.join(cidir, "user-data"), "w")
-        udata.writelines(["#cloud-config\n",
-                          "chpasswd:\n",
-                          "  list: |\n",
-                          "    root:%s\n" % self.ROOT_PASS,
-                          "    %s:%s\n" % (self.GUEST_USER, self.GUEST_PASS),
-                          "  expire: False\n",
-                          "users:\n",
-                          "  - name: %s\n" % self.GUEST_USER,
-                          "    sudo: ALL=(ALL) NOPASSWD:ALL\n",
-                          "    ssh-authorized-keys:\n",
-                          "    - %s\n" % basevm.SSH_PUB_KEY,
-                          "  - name: root\n",
-                          "    ssh-authorized-keys:\n",
-                          "    - %s\n" % basevm.SSH_PUB_KEY,
-                          "locale: en_US.UTF-8\n"])
-        udata.close()
-        subprocess.check_call(["genisoimage", "-output", "cloud-init.iso",
-                               "-volid", "cidata", "-joliet", "-rock",
-                               "user-data", "meta-data"],
-                               cwd=cidir,
-                               stdin=self._devnull, stdout=self._stdout,
-                               stderr=self._stdout)
-        return os.path.join(cidir, "cloud-init.iso")
-
     def build_image(self, img):
         cimg = self._download_with_cache("https://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud-1802.qcow2.xz")
         img_tmp = img + ".tmp"
@@ -69,7 +38,7 @@ class CentosVM(basevm.BaseVM):
         subprocess.check_call(["ln", "-f", cimg, img_tmp + ".xz"])
         subprocess.check_call(["xz", "--keep", "-dvf", img_tmp + ".xz"])
         self.exec_qemu_img("resize", img_tmp, "50G")
-        self.boot(img_tmp, extra_args = ["-cdrom", self._gen_cloud_init_iso()])
+        self.boot(img_tmp, extra_args = ["-cdrom", self.gen_cloud_init_iso()])
         self.wait_ssh()
         self.ssh_root_check("touch /etc/cloud/cloud-init.disabled")
         self.ssh_root_check("yum update -y")
diff --git a/tests/vm/ubuntu.i386 b/tests/vm/ubuntu.i386
index 3834cd7a8d..7df54ae094 100755
--- a/tests/vm/ubuntu.i386
+++ b/tests/vm/ubuntu.i386
@@ -29,41 +29,6 @@ class UbuntuX86VM(basevm.BaseVM):
         make --output-sync {target} -j{jobs} {verbose};
     """
 
-    def _gen_cloud_init_iso(self):
-        cidir = self._tmpdir
-        mdata = open(os.path.join(cidir, "meta-data"), "w")
-        mdata.writelines(["instance-id: ubuntu-vm-0\n",
-                          "local-hostname: ubuntu-guest\n"])
-        mdata.close()
-        udata = open(os.path.join(cidir, "user-data"), "w")
-        udata.writelines(["#cloud-config\n",
-                          "chpasswd:\n",
-                          "  list: |\n",
-                          "    root:%s\n" % self.ROOT_PASS,
-                          "    %s:%s\n" % (self.GUEST_USER, self.GUEST_PASS),
-                          "  expire: False\n",
-                          "users:\n",
-                          "  - name: %s\n" % self.GUEST_USER,
-                          "    sudo: ALL=(ALL) NOPASSWD:ALL\n",
-                          "    ssh-authorized-keys:\n",
-                          "    - %s\n" % basevm.SSH_PUB_KEY,
-                          "  - name: root\n",
-                          "    ssh-authorized-keys:\n",
-                          "    - %s\n" % basevm.SSH_PUB_KEY,
-                          "locale: en_US.UTF-8\n"])
-        proxy = os.environ.get("http_proxy")
-        if not proxy is None:
-            udata.writelines(["apt:\n",
-                              "  proxy: %s" % proxy])
-        udata.close()
-        subprocess.check_call(["genisoimage", "-output", "cloud-init.iso",
-                               "-volid", "cidata", "-joliet", "-rock",
-                               "user-data", "meta-data"],
-                               cwd=cidir,
-                               stdin=self._devnull, stdout=self._stdout,
-                               stderr=self._stdout)
-        return os.path.join(cidir, "cloud-init.iso")
-
     def build_image(self, img):
         cimg = self._download_with_cache(
             "https://cloud-images.ubuntu.com/releases/bionic/release-20191114/ubuntu-18.04-server-cloudimg-i386.img",
@@ -71,7 +36,7 @@ class UbuntuX86VM(basevm.BaseVM):
         img_tmp = img + ".tmp"
         subprocess.check_call(["cp", "-f", cimg, img_tmp])
         self.exec_qemu_img("resize", img_tmp, "50G")
-        self.boot(img_tmp, extra_args = ["-cdrom", self._gen_cloud_init_iso()])
+        self.boot(img_tmp, extra_args = ["-cdrom", self.gen_cloud_init_iso()])
         self.wait_ssh()
         self.ssh_root_check("touch /etc/cloud/cloud-init.disabled")
         self.ssh_root_check("apt-get update")
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v1 06/14] tests/vm: Add logging of console to file.
  2020-02-05 21:29 [PATCH v1 00/14] tests/vm: Add support for aarch64 VMs Robert Foley
                   ` (4 preceding siblings ...)
  2020-02-05 21:29 ` [PATCH v1 05/14] tests/vm: Added gen_cloud_init_iso() to basevm.py Robert Foley
@ 2020-02-05 21:29 ` Robert Foley
  2020-02-07 17:12   ` Alex Bennée
  2020-02-05 21:29 ` [PATCH v1 07/14] tests/vm: Add configuration to basevm.py Robert Foley
                   ` (8 subsequent siblings)
  14 siblings, 1 reply; 25+ messages in thread
From: Robert Foley @ 2020-02-05 21:29 UTC (permalink / raw)
  To: qemu-devel; +Cc: fam, philmd, alex.bennee, robert.foley, peter.puhov

This adds logging of the char device used by the console
to a file.  The basevm.py then uses this file to read
chars from the console.
One reason to add this is to aid with debugging.
But another is because there is an issue where the QEMU
might hang if the characters from the character device
are not consumed by the script.

Signed-off-by: Robert Foley <robert.foley@linaro.org>
---
 tests/vm/basevm.py        | 48 ++++++++++++++++++++++---
 tests/vm/socket_thread.py | 73 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 116 insertions(+), 5 deletions(-)
 create mode 100644 tests/vm/socket_thread.py

diff --git a/tests/vm/basevm.py b/tests/vm/basevm.py
index a926211da8..87a484c55c 100755
--- a/tests/vm/basevm.py
+++ b/tests/vm/basevm.py
@@ -31,12 +31,17 @@ import tempfile
 import shutil
 import multiprocessing
 import traceback
+from socket_thread import SocketThread
 
 SSH_KEY = open(os.path.join(os.path.dirname(__file__),
                "..", "keys", "id_rsa")).read()
 SSH_PUB_KEY = open(os.path.join(os.path.dirname(__file__),
                    "..", "keys", "id_rsa.pub")).read()
 
+class ConsoleTimeoutException(Exception):
+    """Raise this exception when read from console times out."""
+    pass
+
 class BaseVM(object):
     GUEST_USER = "qemu"
     GUEST_PASS = "qemupass"
@@ -59,12 +64,18 @@ class BaseVM(object):
     poweroff = "poweroff"
     # enable IPv6 networking
     ipv6 = True
+    # This is the timeout on the wait for console bytes.
+    socket_timeout = 120
     # Scale up some timeouts under TCG.
     # 4 is arbitrary, but greater than 2,
     # since we found we need to wait more than twice as long.
     tcg_ssh_timeout_multiplier = 4
+    console_logfile = "console.log"
     def __init__(self, debug=False, vcpus=None):
         self._guest = None
+        self._console_fd = None
+        self._socket_thread = None
+        self._console_timeout_sec = self.socket_timeout
         self._tmpdir = os.path.realpath(tempfile.mkdtemp(prefix="vm-test-",
                                                          suffix=".tmp",
                                                          dir="."))
@@ -179,6 +190,15 @@ class BaseVM(object):
                             "-device",
                             "virtio-blk,drive=%s,serial=%s,bootindex=1" % (name, name)]
 
+    def init_console(self, socket):
+        """Init the thread to dump console to a file.
+           Also open the file descriptor we will use to
+           read from the console."""
+        self._socket_thread = SocketThread(socket, self.console_logfile)
+        self._console_fd = open(self.console_logfile, "r")
+        self._socket_thread.start()
+        print("console logfile is: {}".format(self.console_logfile))
+
     def boot(self, img, extra_args=[]):
         args = self._args + [
             "-device", "VGA",
@@ -201,6 +221,7 @@ class BaseVM(object):
             raise
         atexit.register(self.shutdown)
         self._guest = guest
+        self.init_console(guest.console_socket)
         usernet_info = guest.qmp("human-monitor-command",
                                  command_line="info usernet")
         self.ssh_port = None
@@ -212,9 +233,10 @@ class BaseVM(object):
             raise Exception("Cannot find ssh port from 'info usernet':\n%s" % \
                             usernet_info)
 
-    def console_init(self, timeout = 120):
-        vm = self._guest
-        vm.console_socket.settimeout(timeout)
+    def console_init(self, timeout = None):
+        if timeout == None:
+            timeout = self.socket_timeout
+        self._console_timeout_sec = timeout
 
     def console_log(self, text):
         for line in re.split("[\r\n]", text):
@@ -230,13 +252,27 @@ class BaseVM(object):
             # log console line
             sys.stderr.write("con recv: %s\n" % line)
 
+    def console_recv(self, n):
+        """Read n chars from the console_logfile being dumped to
+           by the socket thread we created earlier."""
+        start_time = time.time()
+        while True:
+            data = self._console_fd.read(1)
+            if data != "":
+                break
+            time.sleep(0.1)
+            elapsed_sec = time.time() - start_time
+            if elapsed_sec > self._console_timeout_sec:
+                raise ConsoleTimeoutException
+        return data.encode('latin1')
+
     def console_wait(self, expect, expectalt = None):
         vm = self._guest
         output = ""
         while True:
             try:
-                chars = vm.console_socket.recv(1)
-            except socket.timeout:
+                chars = self.console_recv(1)
+            except ConsoleTimeoutException:
                 sys.stderr.write("console: *** read timeout ***\n")
                 sys.stderr.write("console: waiting for: '%s'\n" % expect)
                 if not expectalt is None:
@@ -335,6 +371,8 @@ class BaseVM(object):
             raise Exception("Timeout while waiting for guest ssh")
 
     def shutdown(self):
+        self._socket_thread.join()
+        self._console_fd.close()
         self._guest.shutdown()
     def wait(self):
         self._guest.wait()
diff --git a/tests/vm/socket_thread.py b/tests/vm/socket_thread.py
new file mode 100644
index 0000000000..6160e9163d
--- /dev/null
+++ b/tests/vm/socket_thread.py
@@ -0,0 +1,73 @@
+#!/usr/bin/env python
+#
+# This python module defines a thread object which
+# reads from a socket and dumps it to a file.
+#
+# The main use case is for reading QEMU console char dev and
+# dumping them to a file either for debugging or for
+# parsing by QEMU itself.
+#
+# Copyright 2020 Linaro
+#
+# Authors:
+#  Robert Foley <robert.foley@linaro.org>
+#
+# This code is licensed under the GPL version 2 or later.  See
+# the COPYING file in the top-level directory.
+#
+import sys
+import re
+import threading
+import time
+import traceback
+import gettext
+
+class SocketThread(threading.Thread):
+    """ Implements the standard threading.Thread API.(start, join, etc.).
+        dumps all characters received on socket into a file.
+    """
+    def __init__(self, socket, filename):
+        super(SocketThread, self).__init__()
+        self.alive = threading.Event()
+        self.alive.set()
+        self.socket = socket
+        self.log_file = open(filename, "w")
+        self.debug = True
+
+    def receive(self):
+        """Until the user calls join, we will read chars from
+           the socket and dump them as is to the file."""
+        self.socket.setblocking(0)
+        self.socket.settimeout(1.0)
+        while self.alive.isSet():
+            try:
+                chars = self.socket.recv(1)
+            except:
+                continue
+            output = chars.decode("latin1")
+            self.log_file.write("{}".format(output))
+            # Flush the file since we need the characters to be
+            # always up to date in case someone is reading the file
+            # waiting for some characters to show up.
+            self.log_file.flush()
+        self.socket.setblocking(1)
+
+    def run(self):
+        """This is the main loop of the socket thread.
+           Simply receive from the file until the user
+           calls join."""
+        while self.alive.isSet():
+            try:
+                self.receive()
+            except Exception as e:
+                sys.stderr.write("Exception encountered\n")
+                traceback.print_exc()
+                continue
+
+    def join(self, timeout=None):
+        """Time to destroy the thread.
+           Clear the event to stop the thread, and wait for
+           it to complete."""
+        self.alive.clear()
+        threading.Thread.join(self, timeout)
+        self.log_file.close()
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v1 07/14] tests/vm: Add configuration to basevm.py
  2020-02-05 21:29 [PATCH v1 00/14] tests/vm: Add support for aarch64 VMs Robert Foley
                   ` (5 preceding siblings ...)
  2020-02-05 21:29 ` [PATCH v1 06/14] tests/vm: Add logging of console to file Robert Foley
@ 2020-02-05 21:29 ` Robert Foley
  2020-02-05 21:29 ` [PATCH v1 08/14] tests/vm: Added configuration file support Robert Foley
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 25+ messages in thread
From: Robert Foley @ 2020-02-05 21:29 UTC (permalink / raw)
  To: qemu-devel; +Cc: fam, philmd, alex.bennee, robert.foley, peter.puhov

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 created
or launched.
This will for example allow for creating an aarch64 vm.

Signed-off-by: Robert Foley <robert.foley@linaro.org>
---
 tests/vm/basevm.py | 141 +++++++++++++++++++++++++++++++++++----------
 1 file changed, 111 insertions(+), 30 deletions(-)

diff --git a/tests/vm/basevm.py b/tests/vm/basevm.py
index 87a484c55c..33004934af 100755
--- a/tests/vm/basevm.py
+++ b/tests/vm/basevm.py
@@ -33,19 +33,43 @@ import multiprocessing
 import traceback
 from socket_thread import SocketThread
 
-SSH_KEY = open(os.path.join(os.path.dirname(__file__),
-               "..", "keys", "id_rsa")).read()
-SSH_PUB_KEY = open(os.path.join(os.path.dirname(__file__),
-                   "..", "keys", "id_rsa.pub")).read()
+SSH_KEY_FILE = os.path.join(os.path.dirname(__file__),
+               "..", "keys", "id_rsa")
+SSH_PUB_KEY_FILE = os.path.join(os.path.dirname(__file__),
+                   "..", "keys", "id_rsa.pub")
 
 class ConsoleTimeoutException(Exception):
     """Raise this exception when read from console times out."""
     pass
 
+# 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 = {
+    '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 = {
+    'block' :  "-drive file={},if=none,id=drive0,cache=writeback "\
+               "-device virtio-blk,drive=drive0,bootindex=0",
+    'scsi'  :  "-device virtio-scsi-device,id=scsi "\
+               "-drive file={},format=raw,if=none,id=hd0 "\
+               "-device scsi-hd,drive=hd0,bootindex=0",
+}
 class BaseVM(object):
-    GUEST_USER = "qemu"
-    GUEST_PASS = "qemupass"
-    ROOT_PASS = "qemupass"
 
     envvars = [
         "https_proxy",
@@ -71,22 +95,33 @@ class BaseVM(object):
     # since we found we need to wait more than twice as long.
     tcg_ssh_timeout_multiplier = 4
     console_logfile = "console.log"
-    def __init__(self, debug=False, vcpus=None):
+    def __init__(self, debug=False, vcpus=None, config=None):
         self._guest = None
         self._console_fd = None
         self._socket_thread = None
         self._console_timeout_sec = self.socket_timeout
+        # Allow input config to override defaults.
+        self._config = DEFAULT_CONFIG.copy()
+        if config != None:
+            self._config.update(config)
+        self.validate_ssh_keys()
         self._tmpdir = os.path.realpath(tempfile.mkdtemp(prefix="vm-test-",
                                                          suffix=".tmp",
                                                          dir="."))
         atexit.register(shutil.rmtree, self._tmpdir)
-
-        self._ssh_key_file = 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 = 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'] = \
+            open(self._config['ssh_key_file']).read().rstrip()
+        self._config['ssh_pub_key'] = \
+            open(self._config['ssh_pub_key_file']).read().rstrip()
+        self._ssh_tmp_key_file = 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 = os.path.join(self._tmpdir, "id_rsa.pub")
+        open(self._ssh_tmp_pub_key_file,
+             "w").write(self._config['ssh_pub_key'])
 
         self.debug = debug
         self._stderr = sys.stderr
@@ -95,11 +130,14 @@ class BaseVM(object):
             self._stdout = sys.stdout
         else:
             self._stdout = self._devnull
+        netdev = "user,id=vnet,hostfwd=:127.0.0.1:{}-:22"
         self._args = [ \
-            "-nodefaults", "-m", "4G",
-            "-cpu", "max",
-            "-netdev", "user,id=vnet,hostfwd=:127.0.0.1:0-:22" +
-                       (",ipv6=no" if not self.ipv6 else ""),
+            "-nodefaults", "-m", self._config['memory'],
+            "-cpu", self._config['cpu'],
+            "-netdev",
+            netdev.format(self._config['ssh_port']) +
+            (",ipv6=no" if not self.ipv6 else "") +
+            (",dns=" + self._config['dns'] if self._config['dns'] else ""),
             "-device", "virtio-net-pci,netdev=vnet",
             "-vnc", "127.0.0.1:0,to=20"]
         if vcpus and vcpus > 1:
@@ -110,6 +148,45 @@ class BaseVM(object):
             logging.info("KVM not available, not using -enable-kvm")
         self._data_args = []
 
+        if self._config['qemu_args'] != None:
+            qemu_args = self._config['qemu_args']
+            qemu_args = qemu_args.replace('\n',' ').replace('\r','')
+            # Remove any empty strings from list.
+            self._config['extra_args'] = [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=None):
+        """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 = self.login_prompt
+        # Intentionally bump up the default timeout under TCG,
+        # since the console wait below takes longer.
+        timeout = self.socket_timeout
+        if not kvm_available(self.arch):
+            timeout *= 8
+        self.console_init(timeout=timeout)
+        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=None, sha512sum=None):
         def check_sha256sum(fname):
             if not sha256sum:
@@ -141,8 +218,9 @@ class BaseVM(object):
                    "-t",
                    "-o", "StrictHostKeyChecking=no",
                    "-o", "UserKnownHostsFile=" + os.devnull,
-                   "-o", "ConnectTimeout=1",
-                   "-p", self.ssh_port, "-i", self._ssh_key_file]
+                   "-o",
+                   "ConnectTimeout={}".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:
@@ -200,15 +278,15 @@ class BaseVM(object):
         print("console logfile is: {}".format(self.console_logfile))
 
     def boot(self, img, extra_args=[]):
-        args = self._args + [
-            "-device", "VGA",
-            "-drive", "file=%s,if=none,id=drive0,cache=writeback" % img,
-            "-device", "virtio-blk,drive=drive0,bootindex=0"]
-        args += self._data_args + extra_args
+        boot_dev = BOOT_DEVICE[self._config['boot_dev_type']]
+        boot_params = boot_dev.format(img)
+        args = self._args + boot_params.split(' ')
+        args += self._data_args + extra_args + self._config['extra_args']
+        args += ["-device", "VGA"]
         logging.debug("QEMU args: %s", " ".join(args))
         qemu_bin = os.environ.get("QEMU", "qemu-system-" + self.arch)
         guest = QEMUMachine(binary=qemu_bin, args=args)
-        guest.set_machine('pc')
+        guest.set_machine(self._config['machine'])
         guest.set_console()
         try:
             guest.launch()
@@ -332,7 +410,8 @@ class BaseVM(object):
         self.console_send(command)
 
     def console_ssh_init(self, prompt, user, pw):
-        sshkey_cmd = "echo '%s' > .ssh/authorized_keys\n" % SSH_PUB_KEY.rstrip()
+        sshkey_cmd = "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")
@@ -461,15 +540,17 @@ def parse_args(vmcls):
     parser.disable_interspersed_args()
     return parser.parse_args()
 
-def main(vmcls):
+def main(vmcls, config=None):
     try:
+        if config == None:
+            config = {}
         args, argv = 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=(logging.DEBUG if args.debug
                                    else logging.WARN))
-        vm = vmcls(debug=args.debug, vcpus=args.jobs)
+        vm = vmcls(debug=args.debug, vcpus=args.jobs, config=config)
         if args.build_image:
             if os.path.exists(args.image) and not args.force:
                 sys.stderr.writelines(["Image file exists: %s\n" % args.image,
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v1 08/14] tests/vm: Added configuration file support
  2020-02-05 21:29 [PATCH v1 00/14] tests/vm: Add support for aarch64 VMs Robert Foley
                   ` (6 preceding siblings ...)
  2020-02-05 21:29 ` [PATCH v1 07/14] tests/vm: Add configuration to basevm.py Robert Foley
@ 2020-02-05 21:29 ` Robert Foley
  2020-02-14 16:53   ` Alex Bennée
  2020-02-05 21:29 ` [PATCH v1 09/14] tests/vm: add --boot-console switch Robert Foley
                   ` (6 subsequent siblings)
  14 siblings, 1 reply; 25+ messages in thread
From: Robert Foley @ 2020-02-05 21:29 UTC (permalink / raw)
  To: qemu-devel; +Cc: fam, philmd, alex.bennee, robert.foley, peter.puhov

Changes to tests/vm/basevm.py to allow accepting a configuration file
as a parameter. Allows for specifying VM options such as
cpu, machine, memory, and arbitrary qemu arguments for specifying options
such as NUMA configuration.
Also added an example conf_example_aarch64.yml and conf_example_x86.yml.

Signed-off-by: Robert Foley <robert.foley@linaro.org>
---
 tests/vm/Makefile.include         |  2 ++
 tests/vm/basevm.py                | 29 +++++++++++++++++-
 tests/vm/conf_example_aarch64.yml | 51 +++++++++++++++++++++++++++++++
 tests/vm/conf_example_x86.yml     | 50 ++++++++++++++++++++++++++++++
 4 files changed, 131 insertions(+), 1 deletion(-)
 create mode 100644 tests/vm/conf_example_aarch64.yml
 create mode 100644 tests/vm/conf_example_x86.yml

diff --git a/tests/vm/Makefile.include b/tests/vm/Makefile.include
index 778e506755..e9ed33226d 100644
--- a/tests/vm/Makefile.include
+++ b/tests/vm/Makefile.include
@@ -35,6 +35,8 @@ vm-help vm-test:
 	@echo "    V=1				 - Enable verbose ouput on host and guest commands"
 	@echo "    QEMU=/path/to/qemu		 - Change path to QEMU binary"
 	@echo "    QEMU_IMG=/path/to/qemu-img	 - Change path to qemu-img tool"
+	@echo "    QEMU_CONFIG=/path/conf.yml   - Change path to VM configuration .yml file."
+	@echo "                                   See conf_example_*.yml for file format details."
 
 vm-build-all: $(addprefix vm-build-, $(IMAGES))
 
diff --git a/tests/vm/basevm.py b/tests/vm/basevm.py
index 33004934af..f488d4103c 100755
--- a/tests/vm/basevm.py
+++ b/tests/vm/basevm.py
@@ -32,6 +32,7 @@ import shutil
 import multiprocessing
 import traceback
 from socket_thread import SocketThread
+import yaml
 
 SSH_KEY_FILE = os.path.join(os.path.dirname(__file__),
                "..", "keys", "id_rsa")
@@ -500,9 +501,31 @@ class BaseVM(object):
                                cwd=cidir,
                                stdin=self._devnull, stdout=self._stdout,
                                stderr=self._stdout)
-
         return os.path.join(cidir, "cloud-init.iso")
 
+def parse_config(config, args):
+    """ Parse yaml config and populate our config structure.
+        The yaml config allows the user to override the
+        defaults for VM parameters.  In many cases these
+        defaults can be overridden without rebuilding the VM."""
+    if args.config:
+        config_file = args.config
+    elif 'QEMU_CONFIG' in os.environ:
+        config_file = os.environ['QEMU_CONFIG']
+    else:
+        return config
+    if not os.path.exists(config_file):
+        raise Exception("config file {} does not exist".format(config_file))
+    with open(config_file) as f:
+        yaml_dict = yaml.safe_load(f)
+
+    if 'qemu-conf' in yaml_dict:
+        config.update(yaml_dict['qemu-conf'])
+    else:
+        raise Exception("config file {} is not valid"\
+                        " missing qemu-conf".format(config_file))
+    return config
+
 def parse_args(vmcls):
 
     def get_default_jobs():
@@ -537,6 +560,9 @@ def parse_args(vmcls):
                       help="Interactively run command")
     parser.add_option("--snapshot", "-s", action="store_true",
                       help="run tests with a snapshot")
+    parser.add_option("--config", "-c", default=None,
+                      help="Provide config yaml for configuration. "\
+                           "See config_example.yaml for example.")
     parser.disable_interspersed_args()
     return parser.parse_args()
 
@@ -548,6 +574,7 @@ def main(vmcls, config=None):
         if not argv and not args.build_qemu and not args.build_image:
             print("Nothing to do?")
             return 1
+        config = parse_config(config, args)
         logging.basicConfig(level=(logging.DEBUG if args.debug
                                    else logging.WARN))
         vm = vmcls(debug=args.debug, vcpus=args.jobs, config=config)
diff --git a/tests/vm/conf_example_aarch64.yml b/tests/vm/conf_example_aarch64.yml
new file mode 100644
index 0000000000..9d44ae356f
--- /dev/null
+++ b/tests/vm/conf_example_aarch64.yml
@@ -0,0 +1,51 @@
+#
+# Example yaml for use by any of the scripts in tests/vm.
+# Can be provided as an environment variable QEMU_CONFIG
+#
+qemu-conf:
+
+    # If any of the below are not provided, we will just use the qemu defaults.
+
+    # Login username and password(has to be sudo enabled)
+    guest_user: qemu
+    guest_pass: "qemupass"
+
+    # Password for root user can be different from guest.
+    root_pass: "qemupass"
+
+    # If one key is provided, both must be provided.
+    #ssh_key: /complete/path/of/your/keyfile/id_rsa
+    #ssh_pub_key: /complete/path/of/your/keyfile/id_rsa.pub
+
+    cpu: max
+    machine: virt,gic-version=max
+    memory: 16G
+
+    # The below is a example for how to configure NUMA topology with
+    # 4 NUMA nodes and 2 different NUMA distances.
+    qemu_args: "-smp cpus=16,sockets=2,cores=8
+                -numa node,cpus=0-3,nodeid=0 -numa node,cpus=4-7,nodeid=1
+                -numa node,cpus=8-11,nodeid=2 -numa node,cpus=12-15,nodeid=3
+                -numa dist,src=0,dst=1,val=15 -numa dist,src=2,dst=3,val=15
+                -numa dist,src=0,dst=2,val=20 -numa dist,src=0,dst=3,val=20
+                -numa dist,src=1,dst=2,val=20 -numa dist,src=1,dst=3,val=20"
+
+    # By default we do not set the DNS.
+    # You override the defaults by setting the below.
+    #dns: 1.234.567.89
+
+    # By default we will use a "block" device, but
+    # you can also boot from a "scsi" device.
+    # Just keep in mind your scripts might need to change
+    # As you will have /dev/sda instead of /dev/vda (for block device)
+    boot_dev_type: "block"
+
+    # By default the ssh port is not fixed.
+    # A fixed ssh port makes it easier for automated tests.
+    #ssh_port: 5555
+
+    # To install a different set of packages, provide a command to issue
+    #install_cmds: "apt-get update ; apt-get build-dep -y qemu"
+
+    # Or to skip the install entirely, just provide ""
+    #install_cmds: ""
diff --git a/tests/vm/conf_example_x86.yml b/tests/vm/conf_example_x86.yml
new file mode 100644
index 0000000000..78d3f5830f
--- /dev/null
+++ b/tests/vm/conf_example_x86.yml
@@ -0,0 +1,50 @@
+#
+# Example yaml for use by any of the x86 based scripts in tests/vm.
+# Can be provided as an environment variable QEMU_CONFIG
+#
+qemu-conf:
+
+    # If any of the below are not provided, we will just use the qemu defaults.
+
+    # Login username and password(has to be sudo enabled)
+    guest_user: "qemu"
+    guest_pass: "qemupass"
+
+    # Password for root user can be different from guest.
+    root_pass: "qemupass"
+
+    # Provide default ssh keys of current user.
+    # You need to edit the below for your user.
+    #ssh_key_file: /home/<user>/.ssh/id_rsa
+    #ssh_pub_key_file: /home/<user>/.ssh/id_rsa.pub
+
+    cpu: max
+    machine: pc
+    memory: 8G
+
+    # The below is a example for how to configure NUMA topology with
+    # 4 NUMA nodes and 2 different NUMA distances.
+    qemu_args: "-smp cpus=8,sockets=2,cores=4
+                -object memory-backend-ram,size=4G,policy=bind,host-nodes=0,id=ram-node0
+                -object memory-backend-ram,size=4G,policy=bind,host-nodes=0,id=ram-node1
+                -object memory-backend-ram,size=4G,policy=bind,host-nodes=1,id=ram-node2
+                -object memory-backend-ram,size=4G,policy=bind,host-nodes=1,id=ram-node3
+                -numa node,cpus=0-1,nodeid=0 -numa node,cpus=2-3,nodeid=1
+                -numa node,cpus=4-5,nodeid=2 -numa node,cpus=6-7,nodeid=3
+                -numa dist,src=0,dst=1,val=15 -numa dist,src=2,dst=3,val=15
+                -numa dist,src=0,dst=2,val=20 -numa dist,src=0,dst=3,val=20
+                -numa dist,src=1,dst=2,val=20 -numa dist,src=1,dst=3,val=20"
+
+    # By default we do not set the DNS.
+    # You override the defaults by setting the below.
+    #dns: "1.234.567.89"
+
+    # By default we will use a "block" device, but
+    # you can also boot from a "scsi" device.
+    # Just keep in mind your scripts might need to change
+    # As you will have /dev/sda instead of /dev/vda (for block device)
+    boot_dev_type: "block"
+
+    # By default the ssh port is not fixed.
+    # A fixed ssh port makes it easier for automated tests.
+    ssh_port: 5555
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v1 09/14] tests/vm: add --boot-console switch
  2020-02-05 21:29 [PATCH v1 00/14] tests/vm: Add support for aarch64 VMs Robert Foley
                   ` (7 preceding siblings ...)
  2020-02-05 21:29 ` [PATCH v1 08/14] tests/vm: Added configuration file support Robert Foley
@ 2020-02-05 21:29 ` Robert Foley
  2020-02-05 21:29 ` [PATCH v1 10/14] tests/vm: Add ability to select QEMU from current build Robert Foley
                   ` (5 subsequent siblings)
  14 siblings, 0 replies; 25+ messages in thread
From: Robert Foley @ 2020-02-05 21:29 UTC (permalink / raw)
  To: qemu-devel; +Cc: fam, philmd, alex.bennee, robert.foley, peter.puhov

Added ability to view console during boot via
--boot-console switch to basevm.py.  This helps debug issues that occur
during the boot sequence.
Also added a new special variable to vm-build:
BOOT_CONSOLE=1 will cause this new --boot-console switch to be set.
Signed-off-by: Robert Foley <robert.foley@linaro.org>
---
 tests/vm/Makefile.include |  4 ++++
 tests/vm/basevm.py        | 11 +++++++++--
 2 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/tests/vm/Makefile.include b/tests/vm/Makefile.include
index e9ed33226d..d72babd5bf 100644
--- a/tests/vm/Makefile.include
+++ b/tests/vm/Makefile.include
@@ -32,6 +32,7 @@ vm-help vm-test:
 	@echo '    EXTRA_CONFIGURE_OPTS="..."'
 	@echo "    J=[0..9]*            	 - Override the -jN parameter for make commands"
 	@echo "    DEBUG=1              	 - Enable verbose output on host and interactive debugging"
+	@echo "    BOOT_CONSOLE=1        	 - Show the console output at boot time. "
 	@echo "    V=1				 - Enable verbose ouput on host and guest commands"
 	@echo "    QEMU=/path/to/qemu		 - Change path to QEMU binary"
 	@echo "    QEMU_IMG=/path/to/qemu-img	 - Change path to qemu-img tool"
@@ -50,6 +51,7 @@ $(IMAGES_DIR)/%.img:	$(SRC_PATH)/tests/vm/% \
 	$(call quiet-command, \
 		$(PYTHON) $< \
 		$(if $(V)$(DEBUG), --debug) \
+		$(if $(BOOT_CONSOLE),--boot-console) \
 		--image "$@" \
 		--force \
 		--build-image $@, \
@@ -64,6 +66,7 @@ vm-build-%: $(IMAGES_DIR)/%.img
 		$(if $(DEBUG), --interactive) \
 		$(if $(J),--jobs $(J)) \
 		$(if $(V),--verbose) \
+		$(if $(BOOT_CONSOLE),--boot-console) \
 		--image "$<" \
 		$(if $(BUILD_TARGET),--build-target $(BUILD_TARGET)) \
 		--snapshot \
@@ -84,6 +87,7 @@ vm-boot-ssh-%: $(IMAGES_DIR)/%.img
 	$(call quiet-command, \
 		$(PYTHON) $(SRC_PATH)/tests/vm/$* \
 		$(if $(J),--jobs $(J)) \
+		$(if $(BOOT_CONSOLE),--boot-console) \
 		--image "$<" \
 		--interactive \
 		false, \
diff --git a/tests/vm/basevm.py b/tests/vm/basevm.py
index f488d4103c..b99ab0f20a 100755
--- a/tests/vm/basevm.py
+++ b/tests/vm/basevm.py
@@ -96,9 +96,11 @@ class BaseVM(object):
     # since we found we need to wait more than twice as long.
     tcg_ssh_timeout_multiplier = 4
     console_logfile = "console.log"
-    def __init__(self, debug=False, vcpus=None, config=None):
+    def __init__(self, debug=False, vcpus=None, config=None,
+                boot_console=None):
         self._guest = None
         self._console_fd = None
+        self._boot_console = boot_console
         self._socket_thread = None
         self._console_timeout_sec = self.socket_timeout
         # Allow input config to override defaults.
@@ -563,6 +565,8 @@ def parse_args(vmcls):
     parser.add_option("--config", "-c", default=None,
                       help="Provide config yaml for configuration. "\
                            "See config_example.yaml for example.")
+    parser.add_option("--boot-console", action="store_true",
+                      help="Show console during boot. ")
     parser.disable_interspersed_args()
     return parser.parse_args()
 
@@ -577,7 +581,8 @@ def main(vmcls, config=None):
         config = parse_config(config, args)
         logging.basicConfig(level=(logging.DEBUG if args.debug
                                    else logging.WARN))
-        vm = vmcls(debug=args.debug, vcpus=args.jobs, config=config)
+        vm = vmcls(debug=args.debug, vcpus=args.jobs, config=config,
+                   boot_console=args.boot_console)
         if args.build_image:
             if os.path.exists(args.image) and not args.force:
                 sys.stderr.writelines(["Image file exists: %s\n" % args.image,
@@ -597,6 +602,8 @@ def main(vmcls, config=None):
         if args.snapshot:
             img += ",snapshot=on"
         vm.boot(img)
+        if vm._boot_console:
+            vm.wait_boot()
         vm.wait_ssh()
     except Exception as e:
         if isinstance(e, SystemExit) and e.code == 0:
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v1 10/14] tests/vm: Add ability to select QEMU from current build.
  2020-02-05 21:29 [PATCH v1 00/14] tests/vm: Add support for aarch64 VMs Robert Foley
                   ` (8 preceding siblings ...)
  2020-02-05 21:29 ` [PATCH v1 09/14] tests/vm: add --boot-console switch Robert Foley
@ 2020-02-05 21:29 ` Robert Foley
  2020-02-05 21:29 ` [PATCH v1 11/14] tests/vm: allow wait_ssh() to specify command Robert Foley
                   ` (4 subsequent siblings)
  14 siblings, 0 replies; 25+ messages in thread
From: Robert Foley @ 2020-02-05 21:29 UTC (permalink / raw)
  To: qemu-devel; +Cc: fam, philmd, alex.bennee, robert.foley, peter.puhov

Added a new special variable QEMU_LOCAL=1, which
will indicate to take the QEMU binary from the current
build.

Signed-off-by: Robert Foley <robert.foley@linaro.org>
---
 tests/vm/Makefile.include |  4 ++++
 tests/vm/basevm.py        | 28 ++++++++++++++++++++++++----
 2 files changed, 28 insertions(+), 4 deletions(-)

diff --git a/tests/vm/Makefile.include b/tests/vm/Makefile.include
index d72babd5bf..f67438c552 100644
--- a/tests/vm/Makefile.include
+++ b/tests/vm/Makefile.include
@@ -34,6 +34,7 @@ vm-help vm-test:
 	@echo "    DEBUG=1              	 - Enable verbose output on host and interactive debugging"
 	@echo "    BOOT_CONSOLE=1        	 - Show the console output at boot time. "
 	@echo "    V=1				 - Enable verbose ouput on host and guest commands"
+	@echo "    QEMU_LOCAL=1                 - Use QEMU binary local to this build."
 	@echo "    QEMU=/path/to/qemu		 - Change path to QEMU binary"
 	@echo "    QEMU_IMG=/path/to/qemu-img	 - Change path to qemu-img tool"
 	@echo "    QEMU_CONFIG=/path/conf.yml   - Change path to VM configuration .yml file."
@@ -52,6 +53,7 @@ $(IMAGES_DIR)/%.img:	$(SRC_PATH)/tests/vm/% \
 		$(PYTHON) $< \
 		$(if $(V)$(DEBUG), --debug) \
 		$(if $(BOOT_CONSOLE),--boot-console) \
+		--build-path $(BUILD_DIR)\
 		--image "$@" \
 		--force \
 		--build-image $@, \
@@ -67,6 +69,7 @@ vm-build-%: $(IMAGES_DIR)/%.img
 		$(if $(J),--jobs $(J)) \
 		$(if $(V),--verbose) \
 		$(if $(BOOT_CONSOLE),--boot-console) \
+		--build-path $(BUILD_DIR)\
 		--image "$<" \
 		$(if $(BUILD_TARGET),--build-target $(BUILD_TARGET)) \
 		--snapshot \
@@ -88,6 +91,7 @@ vm-boot-ssh-%: $(IMAGES_DIR)/%.img
 		$(PYTHON) $(SRC_PATH)/tests/vm/$* \
 		$(if $(J),--jobs $(J)) \
 		$(if $(BOOT_CONSOLE),--boot-console) \
+		--build-path $(BUILD_DIR)\
 		--image "$<" \
 		--interactive \
 		false, \
diff --git a/tests/vm/basevm.py b/tests/vm/basevm.py
index b99ab0f20a..97d55f8030 100755
--- a/tests/vm/basevm.py
+++ b/tests/vm/basevm.py
@@ -97,9 +97,10 @@ class BaseVM(object):
     tcg_ssh_timeout_multiplier = 4
     console_logfile = "console.log"
     def __init__(self, debug=False, vcpus=None, config=None,
-                boot_console=None):
+                boot_console=None, build_path=None):
         self._guest = None
         self._console_fd = None
+        self._build_path = build_path
         self._boot_console = boot_console
         self._socket_thread = None
         self._console_timeout_sec = self.socket_timeout
@@ -287,8 +288,8 @@ class BaseVM(object):
         args += self._data_args + extra_args + self._config['extra_args']
         args += ["-device", "VGA"]
         logging.debug("QEMU args: %s", " ".join(args))
-        qemu_bin = os.environ.get("QEMU", "qemu-system-" + self.arch)
-        guest = QEMUMachine(binary=qemu_bin, args=args)
+        qemu_path = get_qemu_path(self.arch, self._build_path)
+        guest = QEMUMachine(binary=qemu_path, args=args)
         guest.set_machine(self._config['machine'])
         guest.set_console()
         try:
@@ -505,6 +506,22 @@ class BaseVM(object):
                                stderr=self._stdout)
         return os.path.join(cidir, "cloud-init.iso")
 
+def get_qemu_path(arch, build_path=None):
+    """Fetch the path to the qemu binary."""
+    qemu_local = os.environ.get("QEMU_LOCAL", 0)
+    # If QEMU environment variable set, it takes precedence
+    if "QEMU" in os.environ:
+        qemu_path = os.environ["QEMU"]
+    elif qemu_local:
+        if not build_path:
+            raise Exception("--build-path option required with QEMU_LOCAL")
+        qemu_path = os.path.join(build_path, arch + "-softmmu")
+        qemu_path = os.path.join(qemu_path, "qemu-system-" + arch)
+    else:
+        # Default is to use system path for qemu.
+        qemu_path = "qemu-system-" + arch
+    return qemu_path
+
 def parse_config(config, args):
     """ Parse yaml config and populate our config structure.
         The yaml config allows the user to override the
@@ -567,6 +584,8 @@ def parse_args(vmcls):
                            "See config_example.yaml for example.")
     parser.add_option("--boot-console", action="store_true",
                       help="Show console during boot. ")
+    parser.add_option("--build-path", default=None,
+                      help="Path of build directory. ")
     parser.disable_interspersed_args()
     return parser.parse_args()
 
@@ -582,7 +601,8 @@ def main(vmcls, config=None):
         logging.basicConfig(level=(logging.DEBUG if args.debug
                                    else logging.WARN))
         vm = vmcls(debug=args.debug, vcpus=args.jobs, config=config,
-                   boot_console=args.boot_console)
+                   boot_console=args.boot_console,
+                   build_path=args.build_path)
         if args.build_image:
             if os.path.exists(args.image) and not args.force:
                 sys.stderr.writelines(["Image file exists: %s\n" % args.image,
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v1 11/14] tests/vm: allow wait_ssh() to specify command
  2020-02-05 21:29 [PATCH v1 00/14] tests/vm: Add support for aarch64 VMs Robert Foley
                   ` (9 preceding siblings ...)
  2020-02-05 21:29 ` [PATCH v1 10/14] tests/vm: Add ability to select QEMU from current build Robert Foley
@ 2020-02-05 21:29 ` Robert Foley
  2020-02-05 21:29 ` [PATCH v1 12/14] tests/vm: Added a new script for ubuntu.aarch64 Robert Foley
                   ` (3 subsequent siblings)
  14 siblings, 0 replies; 25+ messages in thread
From: Robert Foley @ 2020-02-05 21:29 UTC (permalink / raw)
  To: qemu-devel; +Cc: fam, philmd, alex.bennee, robert.foley, peter.puhov

This allows for waiting for completion of arbitrary commands.

Signed-off-by: Robert Foley <robert.foley@linaro.org>
---
 tests/vm/basevm.py | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/tests/vm/basevm.py b/tests/vm/basevm.py
index 97d55f8030..ebedbce4ae 100755
--- a/tests/vm/basevm.py
+++ b/tests/vm/basevm.py
@@ -433,24 +433,24 @@ class BaseVM(object):
     def print_step(self, text):
         sys.stderr.write("### %s ...\n" % text)
 
-    def wait_ssh(self, wait_root=False, seconds=300):
+    def wait_ssh(self, wait_root=False, seconds=300, cmd="exit 0"):
         # Allow more time for VM to boot under TCG.
         if not kvm_available(self.arch):
             seconds *= self.tcg_ssh_timeout_multiplier
         starttime = datetime.datetime.now()
         endtime = starttime + datetime.timedelta(seconds=seconds)
-        guest_up = False
+        cmd_success = False
         while datetime.datetime.now() < endtime:
-            if wait_root and self.ssh_root("exit 0") == 0:
-                guest_up = True
+            if wait_root and self.ssh_root(cmd) == 0:
+                cmd_success = True
                 break
-            elif self.ssh("exit 0") == 0:
-                guest_up = True
+            elif self.ssh(cmd) == 0:
+                cmd_success = True
                 break
             seconds = (endtime - datetime.datetime.now()).total_seconds()
             logging.debug("%ds before timeout", seconds)
             time.sleep(1)
-        if not guest_up:
+        if not cmd_success:
             raise Exception("Timeout while waiting for guest ssh")
 
     def shutdown(self):
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v1 12/14] tests/vm: Added a new script for ubuntu.aarch64.
  2020-02-05 21:29 [PATCH v1 00/14] tests/vm: Add support for aarch64 VMs Robert Foley
                   ` (10 preceding siblings ...)
  2020-02-05 21:29 ` [PATCH v1 11/14] tests/vm: allow wait_ssh() to specify command Robert Foley
@ 2020-02-05 21:29 ` Robert Foley
  2020-02-05 21:29 ` [PATCH v1 13/14] tests/vm: Added a new script for centos.aarch64 Robert Foley
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 25+ messages in thread
From: Robert Foley @ 2020-02-05 21:29 UTC (permalink / raw)
  To: qemu-devel; +Cc: fam, philmd, alex.bennee, robert.foley, peter.puhov

ubuntu.aarch64 provides a script to create an Ubuntu 18.04 VM.
Another new file is also added aarch64vm.py, which is a module with
common methods used by aarch64 VMs, such as how to create the
flash images.

Signed-off-by: Robert Foley <robert.foley@linaro.org>
---
 tests/vm/Makefile.include |   3 +-
 tests/vm/aarch64vm.py     | 100 +++++++++++++++++++++++++++++++++
 tests/vm/basevm.py        |   8 +++
 tests/vm/ubuntu.aarch64   | 113 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 223 insertions(+), 1 deletion(-)
 create mode 100644 tests/vm/aarch64vm.py
 create mode 100755 tests/vm/ubuntu.aarch64

diff --git a/tests/vm/Makefile.include b/tests/vm/Makefile.include
index f67438c552..ccafe966cd 100644
--- a/tests/vm/Makefile.include
+++ b/tests/vm/Makefile.include
@@ -2,7 +2,7 @@
 
 .PHONY: vm-build-all vm-clean-all
 
-IMAGES := ubuntu.i386 freebsd netbsd openbsd centos fedora
+IMAGES := ubuntu.i386 freebsd netbsd openbsd centos fedora ubuntu.aarch64
 IMAGES_DIR := $(HOME)/.cache/qemu-vm/images
 IMAGE_FILES := $(patsubst %, $(IMAGES_DIR)/%.img, $(IMAGES))
 
@@ -18,6 +18,7 @@ vm-help vm-test:
 	@echo "  vm-build-openbsd                - Build QEMU in OpenBSD VM"
 	@echo "  vm-build-centos                 - Build QEMU in CentOS VM, with Docker"
 	@echo "  vm-build-fedora                 - Build QEMU in Fedora VM"
+	@echo "  vm-build-ubuntu.aarch64         - Build QEMU in ubuntu aarch64 VM"
 	@echo ""
 	@echo "  vm-build-all                    - Build QEMU in all VMs"
 	@echo "  vm-clean-all                    - Clean up VM images"
diff --git a/tests/vm/aarch64vm.py b/tests/vm/aarch64vm.py
new file mode 100644
index 0000000000..a4c9fea925
--- /dev/null
+++ b/tests/vm/aarch64vm.py
@@ -0,0 +1,100 @@
+#!/usr/bin/env python
+#
+# VM testing aarch64 library
+#
+# Copyright 2020 Linaro
+#
+# Authors:
+#  Robert Foley <robert.foley@linaro.org>
+#
+# This code is licensed under the GPL version 2 or later.  See
+# the COPYING file in the top-level directory.
+#
+import os
+import sys
+import subprocess
+import basevm
+from qemu.accel import kvm_available
+
+# This is the config needed for current version of QEMU.
+# This works for both kvm and tcg.
+CURRENT_CONFIG = {
+    'cpu'          : "max",
+    'machine'      : "virt,gic-version=max",
+}
+
+# The minimum minor version of QEMU we will support with aarch64 VMs is 3.
+# QEMU versions less than 3 have various issues running these VMs.
+QEMU_AARCH64_MIN_VERSION = 3
+
+# The DEFAULT_CONFIG will default to a version of
+# parameters that works for backwards compatibility.
+DEFAULT_CONFIG = {'kvm' : {'cpu'          : "host",
+                           'machine'      : "virt,gic-version=host"},
+                  'tcg' : {'cpu'          : "cortex-a57",
+                           'machine'      : "virt"},
+}
+
+def get_config_defaults(vmcls, default_config):
+    """Fetch the configuration defaults for this VM,
+       taking into consideration the defaults for
+       aarch64 first, followed by the defaults for this VM."""
+    config = default_config
+    config.update(aarch_get_config_defaults(vmcls))
+    return config
+
+def aarch_get_config_defaults(vmcls):
+    # Set the defaults for current version of QEMU.
+    config = CURRENT_CONFIG
+    args, argv = basevm.parse_args(vmcls)
+    qemu_path = basevm.get_qemu_path(vmcls.arch, args.build_path)
+    qemu_version = basevm.get_qemu_version(qemu_path)
+    if qemu_version < QEMU_AARCH64_MIN_VERSION:
+        error = "\nThis major version of QEMU {} is to old for aarch64 VMs.\n"\
+                "The major version must be at least {}.\n"\
+                "To continue with the current build of QEMU, "\
+                "please restart with QEMU_LOCAL=1 .\n"
+        print(error.format(qemu_version, QEMU_AARCH64_MIN_VERSION))
+        exit(1)
+    if qemu_version == QEMU_AARCH64_MIN_VERSION:
+        # We have an older version of QEMU,
+        # set the config values for backwards compatibility.
+        if kvm_available('aarch64'):
+            config.update(DEFAULT_CONFIG['kvm'])
+        else:
+            config.update(DEFAULT_CONFIG['tcg'])
+    return config
+
+def create_flash_images(flash_dir="./"):
+    """Creates the appropriate pflash files
+       for an aarch64 VM."""
+    flash0_path = get_flash_path(flash_dir, "flash0")
+    flash1_path = get_flash_path(flash_dir, "flash1")
+    subprocess.check_call(["dd", "if=/dev/zero", "of={}".format(flash0_path),
+                           "bs=1M", "count=64"])
+    # A reliable way to get the QEMU EFI image is via an installed package.
+    efi_img = "/usr/share/qemu-efi-aarch64/QEMU_EFI.fd"
+    if not os.path.exists(efi_img):
+        sys.stderr.write("*** {} is missing\n".format(efi_img))
+        sys.stderr.write("*** please install qemu-efi-aarch64 package\n")
+        exit(3)
+    subprocess.check_call(["dd", "if={}".format(efi_img),
+                           "of={}".format(flash0_path),
+                           "conv=notrunc"])
+    subprocess.check_call(["dd", "if=/dev/zero",
+                           "of={}".format(flash1_path),
+                           "bs=1M", "count=64"])
+
+def get_pflash_args(flash_dir="./"):
+    """Returns a string that can be used to
+       boot qemu using the appropriate pflash files
+       for aarch64."""
+    flash0_path = get_flash_path(flash_dir, "flash0")
+    flash1_path = get_flash_path(flash_dir, "flash1")
+    pflash_args_str = "-drive file={},format=raw,if=pflash "\
+                      "-drive file={},format=raw,if=pflash"
+    pflash_args = pflash_args_str.format(flash0_path, flash1_path)
+    return pflash_args.split(" ")
+
+def get_flash_path(flash_dir, name):
+    return os.path.join(flash_dir, "{}.img".format(name))
diff --git a/tests/vm/basevm.py b/tests/vm/basevm.py
index ebedbce4ae..dc975d92c7 100755
--- a/tests/vm/basevm.py
+++ b/tests/vm/basevm.py
@@ -522,6 +522,14 @@ def get_qemu_path(arch, build_path=None):
         qemu_path = "qemu-system-" + arch
     return qemu_path
 
+def get_qemu_version(qemu_path):
+    """Get the version number from the current QEMU,
+       and return the major number."""
+    output = subprocess.check_output([qemu_path, '--version'])
+    version_line = output.decode("latin1")
+    version_num = re.split(' |\(', version_line)[3].split('.')[0]
+    return int(version_num)
+
 def parse_config(config, args):
     """ Parse yaml config and populate our config structure.
         The yaml config allows the user to override the
diff --git a/tests/vm/ubuntu.aarch64 b/tests/vm/ubuntu.aarch64
new file mode 100755
index 0000000000..7f204d3879
--- /dev/null
+++ b/tests/vm/ubuntu.aarch64
@@ -0,0 +1,113 @@
+#!/usr/bin/env python
+#
+# Ubuntu aarch64 image
+#
+# Copyright 2020 Linaro
+#
+# Authors:
+#  Robert Foley <robert.foley@linaro.org>
+#  Originally based on ubuntu.i386 Fam Zheng <famz@redhat.com>
+#
+# This code is licensed under the GPL version 2 or later.  See
+# the COPYING file in the top-level directory.
+#
+
+import os
+import sys
+import subprocess
+import basevm
+from qemu.accel import kvm_available
+import time
+import aarch64vm
+
+DEFAULT_CONFIG = {
+    'cpu'          : "cortex-a57",
+    'machine'      : "virt,gic-version=3",
+    'install_cmds' : "apt-get update,"\
+                     "apt-get build-dep -y qemu,"\
+                     "apt-get install -y libfdt-dev flex bison",
+    # We increase beyond the default time since during boot
+    # it can take some time (many seconds) to log into the VM
+    # especially using softmmu.
+    'ssh_timeout'  : 60,
+}
+
+class UbuntuAarch64VM(basevm.BaseVM):
+    name = "ubuntu.aarch64"
+    arch = "aarch64"
+    image_name = "ubuntu-18.04-server-cloudimg-arm64.img"
+    image_link = "https://cloud-images.ubuntu.com/releases/18.04/release/" + image_name
+    login_prompt = "ubuntu-aarch64-guest login:"
+    BUILD_SCRIPT = """
+        set -e;
+        cd $(mktemp -d);
+        sudo chmod a+r /dev/vdb;
+        tar --checkpoint=.10 -xf /dev/vdb;
+        ./configure {configure_opts};
+        make --output-sync {target} -j{jobs} {verbose};
+    """
+    def boot(self, img, extra_args=None):
+        aarch64vm.create_flash_images(self._tmpdir)
+        default_args = aarch64vm.get_pflash_args(self._tmpdir)
+        if extra_args:
+            extra_args.extend(default_args)
+        else:
+            extra_args = default_args
+        # We always add these performance tweaks
+        # because without them, we boot so slowly that we
+        # can time out finding the boot efi device.
+        if '-smp' not in extra_args and \
+           '-smp' not in self._config['extra_args'] and \
+           '-smp' not in self._args:
+            # Only add if not already there to give caller option to change it.
+            extra_args.extend(["-smp", "8"])
+
+        # We have overridden boot() since aarch64 has additional parameters.
+        # Call down to the base class method.
+        super(UbuntuAarch64VM, self).boot(img, extra_args=extra_args)
+
+    def build_image(self, img):
+        os_img = self._download_with_cache(self.image_link)
+        img_tmp = img + ".tmp"
+        subprocess.check_call(["cp", "-f", os_img, img_tmp])
+        subprocess.check_call(["qemu-img", "resize", img_tmp, "+50G"])
+        ci_img = self.gen_cloud_init_iso()
+
+        self.boot(img_tmp, extra_args = ["-cdrom", ci_img])
+        if self._boot_console:
+            self.wait_boot()
+        # First command we issue is fix for slow ssh login.
+        self.wait_ssh(wait_root=True,
+                      cmd="chmod -x /etc/update-motd.d/*")
+        # Wait for cloud init to finish
+        self.wait_ssh(wait_root=True,
+                      cmd="ls /var/lib/cloud/instance/boot-finished")
+        self.ssh_root("touch /etc/cloud/cloud-init.disabled")
+        # Disable auto upgrades.
+        # We want to keep the VM system state stable.
+        self.ssh_root('sed -ie \'s/"1"/"0"/g\' /etc/apt/apt.conf.d/20auto-upgrades')
+        # If the user chooses *not* to do the second phase,
+        # then we will jump right to the graceful shutdown
+        if self._config['install_cmds'] != "":
+            # Don't check the status in case the guest hang up too quickly
+            self.ssh_root("sync && reboot")
+            if self._boot_console:
+                self.wait_boot()
+            self.wait_ssh(wait_root=True)
+            self.ssh_root("locale")
+            # The previous update sometimes doesn't survive a reboot, so do it again
+            self.ssh_root("sed -ie s/^#\ deb-src/deb-src/g /etc/apt/sources.list")
+
+            # Issue the install commands.
+            # This can be overriden by the user in the config .yml.
+            install_cmds = self._config['install_cmds'].split(',')
+            for cmd in install_cmds:
+                self.ssh_root(cmd)
+        self.graceful_shutdown()
+        self.wait()
+        os.rename(img_tmp, img)
+        return 0
+
+if __name__ == "__main__":
+    defaults = aarch64vm.get_config_defaults(UbuntuAarch64VM, DEFAULT_CONFIG)
+    sys.exit(basevm.main(UbuntuAarch64VM, defaults))
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v1 13/14] tests/vm: Added a new script for centos.aarch64.
  2020-02-05 21:29 [PATCH v1 00/14] tests/vm: Add support for aarch64 VMs Robert Foley
                   ` (11 preceding siblings ...)
  2020-02-05 21:29 ` [PATCH v1 12/14] tests/vm: Added a new script for ubuntu.aarch64 Robert Foley
@ 2020-02-05 21:29 ` Robert Foley
  2020-02-05 21:29 ` [PATCH v1 14/14] tests/vm: change scripts to use self._config Robert Foley
  2020-02-07 16:50 ` [PATCH v1 00/14] tests/vm: Add support for aarch64 VMs Alex Bennée
  14 siblings, 0 replies; 25+ messages in thread
From: Robert Foley @ 2020-02-05 21:29 UTC (permalink / raw)
  To: qemu-devel; +Cc: fam, philmd, alex.bennee, robert.foley, peter.puhov

centos.aarch64 creates a CentOS 8 image.
Also added a new kickstart script used to build the centos.aarch64 image.

Signed-off-by: Robert Foley <robert.foley@linaro.org>
---
 tests/vm/Makefile.include    |   3 +-
 tests/vm/centos-8-aarch64.ks |  51 ++++++++
 tests/vm/centos.aarch64      | 221 +++++++++++++++++++++++++++++++++++
 3 files changed, 274 insertions(+), 1 deletion(-)
 create mode 100644 tests/vm/centos-8-aarch64.ks
 create mode 100755 tests/vm/centos.aarch64

diff --git a/tests/vm/Makefile.include b/tests/vm/Makefile.include
index ccafe966cd..7b65958f4d 100644
--- a/tests/vm/Makefile.include
+++ b/tests/vm/Makefile.include
@@ -2,7 +2,7 @@
 
 .PHONY: vm-build-all vm-clean-all
 
-IMAGES := ubuntu.i386 freebsd netbsd openbsd centos fedora ubuntu.aarch64
+IMAGES := ubuntu.i386 freebsd netbsd openbsd centos fedora ubuntu.aarch64 centos.aarch64
 IMAGES_DIR := $(HOME)/.cache/qemu-vm/images
 IMAGE_FILES := $(patsubst %, $(IMAGES_DIR)/%.img, $(IMAGES))
 
@@ -19,6 +19,7 @@ vm-help vm-test:
 	@echo "  vm-build-centos                 - Build QEMU in CentOS VM, with Docker"
 	@echo "  vm-build-fedora                 - Build QEMU in Fedora VM"
 	@echo "  vm-build-ubuntu.aarch64         - Build QEMU in ubuntu aarch64 VM"
+	@echo "  vm-build-centos.aarch64         - Build QEMU in CentOS aarch64 VM"
 	@echo ""
 	@echo "  vm-build-all                    - Build QEMU in all VMs"
 	@echo "  vm-clean-all                    - Clean up VM images"
diff --git a/tests/vm/centos-8-aarch64.ks b/tests/vm/centos-8-aarch64.ks
new file mode 100644
index 0000000000..fd6ebe4d49
--- /dev/null
+++ b/tests/vm/centos-8-aarch64.ks
@@ -0,0 +1,51 @@
+# CentOS aarch64 image kickstart file.
+# This file is used by the CentOS installer to
+# script the generation of the image.
+#
+# Copyright 2020 Linaro
+#
+ignoredisk --only-use=vda
+# System bootloader configuration
+bootloader --append=" crashkernel=auto" --location=mbr --boot-drive=vda
+autopart --type=plain
+# Partition clearing information
+clearpart --linux --initlabel --drives=vda
+# Use text mode install
+text
+repo --name="AppStream" --baseurl=file:///run/install/repo/AppStream
+# Use CDROM installation media
+cdrom
+# Keyboard layouts
+keyboard --vckeymap=us --xlayouts=''
+# System language
+lang en_US.UTF-8
+
+# Network information
+network  --bootproto=dhcp --device=enp0s1 --onboot=off --ipv6=auto --no-activate
+network  --hostname=localhost.localdomain
+# Run the Setup Agent on first boot
+firstboot --enable
+# Do not configure the X Window System
+skipx
+# System services
+services --enabled="chronyd"
+# System timezone
+timezone America/New_York --isUtc
+
+# Shutdown after installation is complete.
+shutdown
+
+%packages
+@^server-product-environment
+kexec-tools
+
+%end
+
+%addon com_redhat_kdump --enable --reserve-mb='auto'
+
+%end
+%anaconda
+pwpolicy root --minlen=6 --minquality=1 --notstrict --nochanges --notempty
+pwpolicy user --minlen=6 --minquality=1 --notstrict --nochanges --emptyok
+pwpolicy luks --minlen=6 --minquality=1 --notstrict --nochanges --notempty
+%end
diff --git a/tests/vm/centos.aarch64 b/tests/vm/centos.aarch64
new file mode 100755
index 0000000000..73bb9c4f86
--- /dev/null
+++ b/tests/vm/centos.aarch64
@@ -0,0 +1,221 @@
+#!/usr/bin/env python
+#
+# Centos aarch64 image
+#
+# Copyright 2020 Linaro
+#
+# Authors:
+#  Robert Foley <robert.foley@linaro.org>
+#  Originally based on ubuntu.aarch64
+#
+# This code is licensed under the GPL version 2 or later.  See
+# the COPYING file in the top-level directory.
+#
+
+import os
+import sys
+import subprocess
+import basevm
+import time
+import traceback
+import aarch64vm
+
+DEFAULT_CONFIG = {
+    'cpu'          : "max",
+    'machine'      : "virt,gic-version=max",
+    'install_cmds' : "yum install -y docker make git python3 gcc, "\
+                     "yum install -y glib2-devel pixman-devel zlib-devel, "\
+                     "yum install -y perl-Test-Harness, "\
+                     "systemctl enable docker",
+    # We increase beyond the default time since during boot
+    # it can take some time (many seconds) to log into the VM.
+    'ssh_timeout'  : 60,
+}
+
+class CentosAarch64VM(basevm.BaseVM):
+    name = "centos.aarch64"
+    arch = "aarch64"
+    login_prompt = "localhost login:"
+    prompt = '[root@localhost ~]#'
+    image_name = "CentOS-8-aarch64-1905-dvd1.iso"
+    image_link = "http://mirrors.usc.edu/pub/linux/distributions/centos/8.0.1905/isos/aarch64/"
+    image_link += image_name
+    BUILD_SCRIPT = """
+        set -e;
+        cd $(mktemp -d);
+        sudo chmod a+r /dev/vdb;
+        tar --checkpoint=.10 -xf /dev/vdb;
+        ./configure {configure_opts};
+        make --output-sync {target} -j{jobs} {verbose};
+    """
+    def set_key_perm(self):
+        """Set permissions properly on certain files to allow
+           ssh access."""
+        self.console_wait_send(self.prompt,
+                               "/usr/sbin/restorecon -R -v /root/.ssh\n")
+        self.console_wait_send(self.prompt,
+                "/usr/sbin/restorecon -R -v "\
+                "/home/{}/.ssh\n".format(self._config["guest_user"]))
+
+    def create_kickstart(self):
+        """Generate the kickstart file used to generate the centos image."""
+        # Start with the template for the kickstart.
+        ks_file = "../tests/vm/centos-8-aarch64.ks"
+        subprocess.check_call("cp {} ./ks.cfg".format(ks_file), shell=True)
+        # Append the ssh keys to the kickstart file
+        # as the post processing phase of installation.
+        with open("ks.cfg", "a") as f:
+            # Add in the root pw and guest user.
+            rootpw = "rootpw --plaintext {}\n"
+            f.write(rootpw.format(self._config["root_pass"]))
+            add_user = "user --groups=wheel --name={} "\
+                       "--password={} --plaintext\n"
+            f.write(add_user.format(self._config["guest_user"],
+                                    self._config["guest_pass"]))
+            # Add the ssh keys.
+            f.write("%post --log=/root/ks-post.log\n")
+            f.write("mkdir -p /root/.ssh\n")
+            addkey = 'echo "{}" >> /root/.ssh/authorized_keys\n'
+            addkey_cmd = addkey.format(self._config["ssh_pub_key"])
+            f.write(addkey_cmd)
+            f.write('mkdir -p /home/{}/.ssh\n'.format(self._config["guest_user"]))
+            addkey = 'echo "{}" >> /home/{}/.ssh/authorized_keys\n'
+            addkey_cmd = addkey.format(self._config["ssh_pub_key"],
+                                       self._config["guest_user"])
+            f.write(addkey_cmd)
+            f.write("%end\n")
+        # Take our kickstart file and create an .iso from it.
+        # The .iso will be provided to qemu as we boot
+        # from the install dvd.
+        # Anaconda will recognize the label "OEMDRV" and will
+        # start the automated installation.
+        gen_iso_img = 'genisoimage -output ks.iso -volid "OEMDRV" ks.cfg'
+        subprocess.check_call(gen_iso_img, shell=True)
+
+    def wait_for_shutdown(self):
+        """We wait for qemu to shutdown the VM and exit.
+           While this happens we display the console view
+           for easier debugging."""
+        # The image creation is essentially done,
+        # so whether or not the wait is successful we want to
+        # wait for qemu to exit (the self.wait()) before we return.
+        try:
+            self.console_wait("reboot: Power down")
+        except Exception as e:
+            sys.stderr.write("Exception hit\n")
+            if isinstance(e, SystemExit) and e.code == 0:
+                return 0
+            traceback.print_exc()
+        finally:
+            self.wait()
+
+    def build_base_image(self, dest_img):
+        """Run through the centos installer to create
+           a base image with name dest_img."""
+        # We create the temp image, and only rename
+        # to destination when we are done.
+        img = dest_img + ".tmp"
+        # Create an empty image.
+        # We will provide this as the install destination.
+        qemu_img_create = "qemu-img create {} 50G".format(img)
+        subprocess.check_call(qemu_img_create, shell=True)
+
+        # Create our kickstart file to be fed to the installer.
+        self.create_kickstart()
+        # Boot the install dvd with the params as our ks.iso
+        os_img = self._download_with_cache(self.image_link)
+        dvd_iso = "centos-8-dvd.iso"
+        subprocess.check_call(["cp", "-f", os_img, dvd_iso])
+        extra_args = "-cdrom ks.iso"
+        extra_args += " -drive file={},if=none,id=drive1,cache=writeback"
+        extra_args += " -device virtio-blk,drive=drive1,bootindex=1"
+        extra_args = extra_args.format(dvd_iso).split(" ")
+        self.boot(img, extra_args=extra_args)
+        self.console_wait_send("change the selection", "\n")
+        # We seem to need to hit esc (chr(27)) twice to abort the
+        # media check, which takes a long time.
+        # Waiting a bit seems to be more reliable before hitting esc.
+        self.console_wait("Checking")
+        time.sleep(5)
+        self.console_wait_send("Checking", chr(27))
+        time.sleep(5)
+        self.console_wait_send("Checking", chr(27))
+        print("Found Checking")
+        self.wait_for_shutdown()
+        os.rename(img, dest_img)
+        print("Done with base image build: {}".format(dest_img))
+
+    def check_create_base_img(self, img_base, img_dest):
+        """Create a base image using the installer.
+           We will use the base image if it exists.
+           This helps cut down on install time in case we
+           need to restart image creation,
+           since the base image creation can take a long time."""
+        if not os.path.exists(img_base):
+            print("Generate new base image: {}".format(img_base))
+            self.build_base_image(img_base);
+        else:
+            print("Use existing base image: {}".format(img_base))
+        # Save a copy of the base image and copy it to dest.
+        # which we will use going forward.
+        subprocess.check_call(["cp", img_base, img_dest])
+
+    def boot(self, img, extra_args=None):
+        aarch64vm.create_flash_images(self._tmpdir)
+        default_args = aarch64vm.get_pflash_args(self._tmpdir)
+        if extra_args:
+            extra_args.extend(default_args)
+        else:
+            extra_args = default_args
+        # We always add these performance tweaks
+        # because without them, we boot so slowly that we
+        # can time out finding the boot efi device.
+        if '-smp' not in extra_args and \
+           '-smp' not in self._config['extra_args'] and \
+           '-smp' not in self._args:
+            # Only add if not already there to give caller option to change it.
+            extra_args.extend(["-smp", "8"])
+        # We have overridden boot() since aarch64 has additional parameters.
+        # Call down to the base class method.
+        super(CentosAarch64VM, self).boot(img, extra_args=extra_args)
+
+    def build_image(self, img):
+        img_tmp = img + ".tmp"
+        self.check_create_base_img(img + ".base", img_tmp)
+
+        # Boot the new image for the first time to finish installation.
+        self.boot(img_tmp)
+        self.console_init()
+        self.console_wait_send(self.login_prompt, "root\n")
+        self.console_wait_send("Password:",
+                               "{}\n".format(self._config["root_pass"]))
+
+        self.set_key_perm()
+        self.console_wait_send(self.prompt, "rpm -q centos-release\n")
+        enable_adapter = "sed -i 's/ONBOOT=no/ONBOOT=yes/g'" \
+                         " /etc/sysconfig/network-scripts/ifcfg-enp0s1\n"
+        self.console_wait_send(self.prompt, enable_adapter)
+        self.console_wait_send(self.prompt, "ifup enp0s1\n")
+        self.console_wait_send(self.prompt,
+                               'echo "qemu  ALL=(ALL) NOPASSWD:ALL" | '\
+                               'sudo tee /etc/sudoers.d/qemu\n')
+        self.console_wait(self.prompt)
+
+        # Rest of the commands we issue through ssh.
+        self.wait_ssh(wait_root=True)
+
+        # If the user chooses *not* to do the second phase,
+        # then we will jump right to the graceful shutdown
+        if self._config['install_cmds'] != "":
+            install_cmds = self._config['install_cmds'].split(',')
+            for cmd in install_cmds:
+                self.ssh_root(cmd)
+        self.ssh_root("poweroff")
+        self.wait_for_shutdown()
+        os.rename(img_tmp, img)
+        print("image creation complete: {}".format(img))
+        return 0
+
+if __name__ == "__main__":
+    defaults = aarch64vm.get_config_defaults(CentosAarch64VM, DEFAULT_CONFIG)
+    sys.exit(basevm.main(CentosAarch64VM, defaults))
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v1 14/14] tests/vm: change scripts to use self._config
  2020-02-05 21:29 [PATCH v1 00/14] tests/vm: Add support for aarch64 VMs Robert Foley
                   ` (12 preceding siblings ...)
  2020-02-05 21:29 ` [PATCH v1 13/14] tests/vm: Added a new script for centos.aarch64 Robert Foley
@ 2020-02-05 21:29 ` Robert Foley
  2020-02-07 16:50 ` [PATCH v1 00/14] tests/vm: Add support for aarch64 VMs Alex Bennée
  14 siblings, 0 replies; 25+ messages in thread
From: Robert Foley @ 2020-02-05 21:29 UTC (permalink / raw)
  To: qemu-devel; +Cc: fam, philmd, alex.bennee, robert.foley, peter.puhov

This change converts existing scripts to using for example self.ROOT_PASS,
to self._config['root_pass'].
We made similar changes for GUEST_USER, and GUEST_PASS.
This allows us also to remove the change in basevm.py,
which adds __getattr__ for backwards compatibility.

Signed-off-by: Robert Foley <robert.foley@linaro.org>
---
 tests/vm/basevm.py | 11 ++---------
 tests/vm/fedora    | 17 +++++++++--------
 tests/vm/freebsd   | 16 ++++++++--------
 tests/vm/netbsd    | 19 ++++++++++---------
 tests/vm/openbsd   | 17 +++++++++--------
 5 files changed, 38 insertions(+), 42 deletions(-)

diff --git a/tests/vm/basevm.py b/tests/vm/basevm.py
index dc975d92c7..d2c5d32f34 100755
--- a/tests/vm/basevm.py
+++ b/tests/vm/basevm.py
@@ -184,13 +184,6 @@ class BaseVM(object):
         self.console_init(timeout=timeout)
         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=None, sha512sum=None):
         def check_sha256sum(fname):
             if not sha256sum:
@@ -240,13 +233,13 @@ class BaseVM(object):
         return r
 
     def ssh(self, *cmd):
-        return self._ssh_do(self.GUEST_USER, cmd, False)
+        return self._ssh_do(self._config["guest_user"], cmd, False)
 
     def ssh_root(self, *cmd):
         return self._ssh_do("root", cmd, False)
 
     def ssh_check(self, *cmd):
-        self._ssh_do(self.GUEST_USER, cmd, True)
+        self._ssh_do(self._config["guest_user"], cmd, True)
 
     def ssh_root_check(self, *cmd):
         self._ssh_do("root", cmd, True)
diff --git a/tests/vm/fedora b/tests/vm/fedora
index 8e270fc0f0..4616d16740 100755
--- a/tests/vm/fedora
+++ b/tests/vm/fedora
@@ -105,20 +105,20 @@ class FedoraVM(basevm.BaseVM):
 
         self.console_wait_send("7) [!] Root password",     "7\n")
         self.console_wait("Password:")
-        self.console_send("%s\n" % self.ROOT_PASS)
+        self.console_send("%s\n" % self._config["root_pass"])
         self.console_wait("Password (confirm):")
-        self.console_send("%s\n" % self.ROOT_PASS)
+        self.console_send("%s\n" % self._config["root_pass"])
 
         self.console_wait_send("8) [ ] User creation",     "8\n")
         self.console_wait_send("1) [ ] Create user",       "1\n")
         self.console_wait_send("3) User name",             "3\n")
-        self.console_wait_send("ENTER:", "%s\n" % self.GUEST_USER)
+        self.console_wait_send("ENTER:", "%s\n" % self._config["guest_user"])
         self.console_wait_send("4) [ ] Use password",      "4\n")
         self.console_wait_send("5) Password",              "5\n")
         self.console_wait("Password:")
-        self.console_send("%s\n" % self.GUEST_PASS)
+        self.console_send("%s\n" % self._config["guest_pass"])
         self.console_wait("Password (confirm):")
-        self.console_send("%s\n" % self.GUEST_PASS)
+        self.console_send("%s\n" % self._config["guest_pass"])
         self.console_wait_send("7) Groups",                "c\n")
 
         while True:
@@ -136,7 +136,7 @@ class FedoraVM(basevm.BaseVM):
             if good:
                 break
             time.sleep(10)
-            self.console_send("r\n" % self.GUEST_PASS)
+            self.console_send("r\n" % self._config["guest_pass"])
 
         self.console_wait_send("'b' to begin install",     "b\n")
 
@@ -147,12 +147,13 @@ class FedoraVM(basevm.BaseVM):
 
         # setup qemu user
         prompt = " ~]$"
-        self.console_ssh_init(prompt, self.GUEST_USER, self.GUEST_PASS)
+        self.console_ssh_init(prompt, self._config["guest_user"],
+                                      self._config["guest_pass"])
         self.console_wait_send(prompt, "exit\n")
 
         # setup root user
         prompt = " ~]#"
-        self.console_ssh_init(prompt, "root", self.ROOT_PASS)
+        self.console_ssh_init(prompt, "root", self._config["root_pass"])
         self.console_sshd_config(prompt)
 
         # setup virtio-blk #1 (tarfile)
diff --git a/tests/vm/freebsd b/tests/vm/freebsd
index 33a736298a..fd1f595aa9 100755
--- a/tests/vm/freebsd
+++ b/tests/vm/freebsd
@@ -110,9 +110,9 @@ class FreeBSDVM(basevm.BaseVM):
 
         # post-install configuration
         self.console_wait("New Password:")
-        self.console_send("%s\n" % self.ROOT_PASS)
+        self.console_send("%s\n" % self._config["root_pass"])
         self.console_wait("Retype New Password:")
-        self.console_send("%s\n" % self.ROOT_PASS)
+        self.console_send("%s\n" % self._config["root_pass"])
 
         self.console_wait_send("Network Configuration", "\n")
         self.console_wait_send("IPv4",                  "y")
@@ -131,9 +131,9 @@ class FreeBSDVM(basevm.BaseVM):
         # qemu user
         self.console_wait_send("Add User Accounts", "y")
         self.console_wait("Username")
-        self.console_send("%s\n" % self.GUEST_USER)
+        self.console_send("%s\n" % self._config["guest_user"])
         self.console_wait("Full name")
-        self.console_send("%s\n" % self.GUEST_USER)
+        self.console_send("%s\n" % self._config["guest_user"])
         self.console_wait_send("Uid",                   "\n")
         self.console_wait_send("Login group",           "\n")
         self.console_wait_send("Login group",           "\n")
@@ -145,9 +145,9 @@ class FreeBSDVM(basevm.BaseVM):
         self.console_wait_send("Use an empty password", "\n")
         self.console_wait_send("Use a random password", "\n")
         self.console_wait("Enter password:")
-        self.console_send("%s\n" % self.GUEST_PASS)
+        self.console_send("%s\n" % self._config["guest_pass"])
         self.console_wait("Enter password again:")
-        self.console_send("%s\n" % self.GUEST_PASS)
+        self.console_send("%s\n" % self._config["guest_pass"])
         self.console_wait_send("Lock out",              "\n")
         self.console_wait_send("OK",                    "yes\n")
         self.console_wait_send("Add another user",      "no\n")
@@ -161,12 +161,12 @@ class FreeBSDVM(basevm.BaseVM):
 
         # setup qemu user
         prompt = "$"
-        self.console_ssh_init(prompt, self.GUEST_USER, self.GUEST_PASS)
+        self.console_ssh_init(prompt, self._config["guest_user"], self._config["guest_pass"])
         self.console_wait_send(prompt, "exit\n")
 
         # setup root user
         prompt = "root@freebsd:~ #"
-        self.console_ssh_init(prompt, "root", self.ROOT_PASS)
+        self.console_ssh_init(prompt, "root", self._config["root_pass"])
         self.console_sshd_config(prompt)
 
         # setup serial console
diff --git a/tests/vm/netbsd b/tests/vm/netbsd
index ec6f3563b2..5eaafc27e0 100755
--- a/tests/vm/netbsd
+++ b/tests/vm/netbsd
@@ -128,24 +128,24 @@ class NetBSDVM(basevm.BaseVM):
         self.console_wait_send("d: Change root password",  "d\n")
         self.console_wait_send("a: Yes",                   "a\n")
         self.console_wait("New password:")
-        self.console_send("%s\n" % self.ROOT_PASS)
+        self.console_send("%s\n" % self._config["root_pass"])
         self.console_wait("New password:")
-        self.console_send("%s\n" % self.ROOT_PASS)
+        self.console_send("%s\n" % self._config["root_pass"])
         self.console_wait("Retype new password:")
-        self.console_send("%s\n" % self.ROOT_PASS)
+        self.console_send("%s\n" % self._config["root_pass"])
 
         self.console_wait_send("o: Add a user",            "o\n")
         self.console_wait("username")
-        self.console_send("%s\n" % self.GUEST_USER)
+        self.console_send("%s\n" % self._config["guest_pass"])
         self.console_wait("to group wheel")
         self.console_wait_send("a: Yes",                   "a\n")
         self.console_wait_send("a: /bin/sh",               "a\n")
         self.console_wait("New password:")
-        self.console_send("%s\n" % self.GUEST_PASS)
+        self.console_send("%s\n" % self._config["guest_pass"])
         self.console_wait("New password:")
-        self.console_send("%s\n" % self.GUEST_PASS)
+        self.console_send("%s\n" % self._config["guest_pass"])
         self.console_wait("Retype new password:")
-        self.console_send("%s\n" % self.GUEST_PASS)
+        self.console_send("%s\n" % self._config["guest_pass"])
 
         self.console_wait_send("a: Configure network",     "a\n")
         self.console_wait_send("a: vioif0",                "a\n")
@@ -178,12 +178,13 @@ class NetBSDVM(basevm.BaseVM):
 
         # setup qemu user
         prompt = "localhost$"
-        self.console_ssh_init(prompt, self.GUEST_USER, self.GUEST_PASS)
+        self.console_ssh_init(prompt, self._config["guest_user"],
+                                      self._config["guest_pass"])
         self.console_wait_send(prompt, "exit\n")
 
         # setup root user
         prompt = "localhost#"
-        self.console_ssh_init(prompt, "root", self.ROOT_PASS)
+        self.console_ssh_init(prompt, "root", self._config["root_pass"])
         self.console_sshd_config(prompt)
 
         # setup virtio-blk #1 (tarfile)
diff --git a/tests/vm/openbsd b/tests/vm/openbsd
index d6173506f7..57f1d90bd6 100755
--- a/tests/vm/openbsd
+++ b/tests/vm/openbsd
@@ -95,9 +95,9 @@ class OpenBSDVM(basevm.BaseVM):
         self.console_wait_send("Which network interface", "done\n")
         self.console_wait_send("DNS domain name",         "localnet\n")
         self.console_wait("Password for root account")
-        self.console_send("%s\n" % self.ROOT_PASS)
+        self.console_send("%s\n" % self._config["root_pass"])
         self.console_wait("Password for root account")
-        self.console_send("%s\n" % self.ROOT_PASS)
+        self.console_send("%s\n" % self._config["root_pass"])
         self.console_wait_send("Start sshd(8)",           "yes\n")
         self.console_wait_send("X Window System",         "\n")
         self.console_wait_send("xenodm",                  "\n")
@@ -105,13 +105,13 @@ class OpenBSDVM(basevm.BaseVM):
         self.console_wait_send("Which speed",             "\n")
 
         self.console_wait("Setup a user")
-        self.console_send("%s\n" % self.GUEST_USER)
+        self.console_send("%s\n" % self._config["guest_user"])
         self.console_wait("Full name")
-        self.console_send("%s\n" % self.GUEST_USER)
+        self.console_send("%s\n" % self._config["guest_user"])
         self.console_wait("Password")
-        self.console_send("%s\n" % self.GUEST_PASS)
+        self.console_send("%s\n" % self._config["guest_pass"])
         self.console_wait("Password")
-        self.console_send("%s\n" % self.GUEST_PASS)
+        self.console_send("%s\n" % self._config["guest_pass"])
 
         self.console_wait_send("Allow root ssh login",    "yes\n")
         self.console_wait_send("timezone",                "UTC\n")
@@ -132,12 +132,13 @@ class OpenBSDVM(basevm.BaseVM):
 
         # setup qemu user
         prompt = "$"
-        self.console_ssh_init(prompt, self.GUEST_USER, self.GUEST_PASS)
+        self.console_ssh_init(prompt, self._config["guest_user"],
+                                      self._config["guest_pass"])
         self.console_wait_send(prompt, "exit\n")
 
         # setup root user
         prompt = "openbsd#"
-        self.console_ssh_init(prompt, "root", self.ROOT_PASS)
+        self.console_ssh_init(prompt, "root", self._config["root_pass"])
         self.console_sshd_config(prompt)
 
         # setup virtio-blk #1 (tarfile)
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH v1 01/14] tests/vm: use $(PYTHON) consistently
  2020-02-05 21:29 ` [PATCH v1 01/14] tests/vm: use $(PYTHON) consistently Robert Foley
@ 2020-02-07 11:42   ` Alex Bennée
  0 siblings, 0 replies; 25+ messages in thread
From: Alex Bennée @ 2020-02-07 11:42 UTC (permalink / raw)
  To: Robert Foley; +Cc: fam, peter.puhov, philmd, qemu-devel


Robert Foley <robert.foley@linaro.org> writes:

> Change Makefile.include to use $(PYTHON) so for vm-boot-ssh to be
> consistent with other cases like vm-build.
>
> Signed-off-by: Robert Foley <robert.foley@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

> ---
>  tests/vm/Makefile.include | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/tests/vm/Makefile.include b/tests/vm/Makefile.include
> index 9e7c46a473..778e506755 100644
> --- a/tests/vm/Makefile.include
> +++ b/tests/vm/Makefile.include
> @@ -80,7 +80,7 @@ vm-boot-serial-%: $(IMAGES_DIR)/%.img
>  
>  vm-boot-ssh-%: $(IMAGES_DIR)/%.img
>  	$(call quiet-command, \
> -		$(SRC_PATH)/tests/vm/$* \
> +		$(PYTHON) $(SRC_PATH)/tests/vm/$* \
>  		$(if $(J),--jobs $(J)) \
>  		--image "$<" \
>  		--interactive \


-- 
Alex Bennée


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v1 03/14] tests/vm: increased max timeout for vm boot.
  2020-02-05 21:29 ` [PATCH v1 03/14] tests/vm: increased max timeout for vm boot Robert Foley
@ 2020-02-07 12:01   ` Alex Bennée
  0 siblings, 0 replies; 25+ messages in thread
From: Alex Bennée @ 2020-02-07 12:01 UTC (permalink / raw)
  To: Robert Foley; +Cc: fam, peter.puhov, philmd, qemu-devel


Robert Foley <robert.foley@linaro.org> writes:

> Add change to increase timeout waiting for VM to boot.
> Needed for some emulation cases where it can take longer
> than 5 minutes to boot.
>
> Signed-off-by: Robert Foley <robert.foley@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

> ---
>  tests/vm/basevm.py | 7 +++++++
>  1 file changed, 7 insertions(+)
>
> diff --git a/tests/vm/basevm.py b/tests/vm/basevm.py
> index 991115e44b..4de358ae22 100755
> --- a/tests/vm/basevm.py
> +++ b/tests/vm/basevm.py
> @@ -59,6 +59,10 @@ class BaseVM(object):
>      poweroff = "poweroff"
>      # enable IPv6 networking
>      ipv6 = True
> +    # Scale up some timeouts under TCG.
> +    # 4 is arbitrary, but greater than 2,
> +    # since we found we need to wait more than twice as long.
> +    tcg_ssh_timeout_multiplier = 4
>      def __init__(self, debug=False, vcpus=None):
>          self._guest = None
>          self._tmpdir = os.path.realpath(tempfile.mkdtemp(prefix="vm-test-",
> @@ -311,6 +315,9 @@ class BaseVM(object):
>          sys.stderr.write("### %s ...\n" % text)
>  
>      def wait_ssh(self, seconds=300):
> +        # Allow more time for VM to boot under TCG.
> +        if not kvm_available(self.arch):
> +            seconds *= self.tcg_ssh_timeout_multiplier
>          starttime = datetime.datetime.now()
>          endtime = starttime + datetime.timedelta(seconds=seconds)
>          guest_up = False


-- 
Alex Bennée


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v1 04/14] tests/vm: give wait_ssh() option to wait for root
  2020-02-05 21:29 ` [PATCH v1 04/14] tests/vm: give wait_ssh() option to wait for root Robert Foley
@ 2020-02-07 12:01   ` Alex Bennée
  0 siblings, 0 replies; 25+ messages in thread
From: Alex Bennée @ 2020-02-07 12:01 UTC (permalink / raw)
  To: Robert Foley; +Cc: fam, peter.puhov, philmd, qemu-devel


Robert Foley <robert.foley@linaro.org> writes:

> Allow wait_ssh to wait for root user to be ready.
> This solves the issue where we perform a wait_ssh()
> successfully, but the root user is not yet ready
> to be logged in.
>
> Signed-off-by: Robert Foley <robert.foley@linaro.org>
> ---
>  tests/vm/basevm.py | 8 +++++---
>  1 file changed, 5 insertions(+), 3 deletions(-)
>
> diff --git a/tests/vm/basevm.py b/tests/vm/basevm.py
> index 4de358ae22..a29099f6f1 100755
> --- a/tests/vm/basevm.py
> +++ b/tests/vm/basevm.py
> @@ -314,7 +314,7 @@ class BaseVM(object):
>      def print_step(self, text):
>          sys.stderr.write("### %s ...\n" % text)
>  
> -    def wait_ssh(self, seconds=300):
> +    def wait_ssh(self, wait_root=False, seconds=300):
>          # Allow more time for VM to boot under TCG.
>          if not kvm_available(self.arch):
>              seconds *= self.tcg_ssh_timeout_multiplier
> @@ -322,7 +322,10 @@ class BaseVM(object):
>          endtime = starttime + datetime.timedelta(seconds=seconds)
>          guest_up = False
>          while datetime.datetime.now() < endtime:
> -            if self.ssh("exit 0") == 0:
> +            if wait_root and self.ssh_root("exit 0") == 0:
> +                guest_up = True
> +                break
> +            elif self.ssh("exit 0") == 0:
>                  guest_up = True
>                  break
>              seconds = (endtime - datetime.datetime.now()).total_seconds()
> @@ -333,7 +336,6 @@ class BaseVM(object):
>  
>      def shutdown(self):
>          self._guest.shutdown()
> -

Stray line deletion. Otherwise:

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

-- 
Alex Bennée


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v1 05/14] tests/vm: Added gen_cloud_init_iso() to basevm.py
  2020-02-05 21:29 ` [PATCH v1 05/14] tests/vm: Added gen_cloud_init_iso() to basevm.py Robert Foley
@ 2020-02-07 12:22   ` Alex Bennée
  0 siblings, 0 replies; 25+ messages in thread
From: Alex Bennée @ 2020-02-07 12:22 UTC (permalink / raw)
  To: Robert Foley; +Cc: fam, peter.puhov, philmd, qemu-devel


Robert Foley <robert.foley@linaro.org> writes:

> This method was located in both centos and ubuntu.i386.
>
> Signed-off-by: Robert Foley <robert.foley@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

> ---
>  tests/vm/basevm.py   | 40 ++++++++++++++++++++++++++++++++++++++++
>  tests/vm/centos      | 33 +--------------------------------
>  tests/vm/ubuntu.i386 | 37 +------------------------------------
>  3 files changed, 42 insertions(+), 68 deletions(-)
>
> diff --git a/tests/vm/basevm.py b/tests/vm/basevm.py
> index a29099f6f1..a926211da8 100755
> --- a/tests/vm/basevm.py
> +++ b/tests/vm/basevm.py
> @@ -346,6 +346,46 @@ class BaseVM(object):
>      def qmp(self, *args, **kwargs):
>          return self._guest.qmp(*args, **kwargs)
>  
> +    def gen_cloud_init_iso(self):
> +        cidir = self._tmpdir
> +        mdata = open(os.path.join(cidir, "meta-data"), "w")
> +        name = self.name.replace(".","-")
> +        mdata.writelines(["instance-id: {}-vm-0\n".format(name),
> +                          "local-hostname: {}-guest\n".format(name)])
> +        mdata.close()
> +        udata = open(os.path.join(cidir, "user-data"), "w")
> +        print("guest user:pw {}:{}".format(self._config['guest_user'],
> +                                           self._config['guest_pass']))
> +        udata.writelines(["#cloud-config\n",
> +                          "chpasswd:\n",
> +                          "  list: |\n",
> +                          "    root:%s\n" % self._config['root_pass'],
> +                          "    %s:%s\n" % (self._config['guest_user'],
> +                                           self._config['guest_pass']),
> +                          "  expire: False\n",
> +                          "users:\n",
> +                          "  - name: %s\n" % self._config['guest_user'],
> +                          "    sudo: ALL=(ALL) NOPASSWD:ALL\n",
> +                          "    ssh-authorized-keys:\n",
> +                          "    - %s\n" % self._config['ssh_pub_key'],
> +                          "  - name: root\n",
> +                          "    ssh-authorized-keys:\n",
> +                          "    - %s\n" % self._config['ssh_pub_key'],
> +                          "locale: en_US.UTF-8\n"])
> +        proxy = os.environ.get("http_proxy")
> +        if not proxy is None:
> +            udata.writelines(["apt:\n",
> +                              "  proxy: %s" % proxy])
> +        udata.close()
> +        subprocess.check_call(["genisoimage", "-output", "cloud-init.iso",
> +                               "-volid", "cidata", "-joliet", "-rock",
> +                               "user-data", "meta-data"],
> +                               cwd=cidir,
> +                               stdin=self._devnull, stdout=self._stdout,
> +                               stderr=self._stdout)
> +
> +        return os.path.join(cidir, "cloud-init.iso")
> +
>  def parse_args(vmcls):
>  
>      def get_default_jobs():
> diff --git a/tests/vm/centos b/tests/vm/centos
> index f2f0befd84..c108bd6799 100755
> --- a/tests/vm/centos
> +++ b/tests/vm/centos
> @@ -31,37 +31,6 @@ class CentosVM(basevm.BaseVM):
>          make docker-test-mingw@fedora  {verbose} J={jobs} NETWORK=1;
>      """
>  
> -    def _gen_cloud_init_iso(self):
> -        cidir = self._tmpdir
> -        mdata = open(os.path.join(cidir, "meta-data"), "w")
> -        mdata.writelines(["instance-id: centos-vm-0\n",
> -                          "local-hostname: centos-guest\n"])
> -        mdata.close()
> -        udata = open(os.path.join(cidir, "user-data"), "w")
> -        udata.writelines(["#cloud-config\n",
> -                          "chpasswd:\n",
> -                          "  list: |\n",
> -                          "    root:%s\n" % self.ROOT_PASS,
> -                          "    %s:%s\n" % (self.GUEST_USER, self.GUEST_PASS),
> -                          "  expire: False\n",
> -                          "users:\n",
> -                          "  - name: %s\n" % self.GUEST_USER,
> -                          "    sudo: ALL=(ALL) NOPASSWD:ALL\n",
> -                          "    ssh-authorized-keys:\n",
> -                          "    - %s\n" % basevm.SSH_PUB_KEY,
> -                          "  - name: root\n",
> -                          "    ssh-authorized-keys:\n",
> -                          "    - %s\n" % basevm.SSH_PUB_KEY,
> -                          "locale: en_US.UTF-8\n"])
> -        udata.close()
> -        subprocess.check_call(["genisoimage", "-output", "cloud-init.iso",
> -                               "-volid", "cidata", "-joliet", "-rock",
> -                               "user-data", "meta-data"],
> -                               cwd=cidir,
> -                               stdin=self._devnull, stdout=self._stdout,
> -                               stderr=self._stdout)
> -        return os.path.join(cidir, "cloud-init.iso")
> -
>      def build_image(self, img):
>          cimg = self._download_with_cache("https://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud-1802.qcow2.xz")
>          img_tmp = img + ".tmp"
> @@ -69,7 +38,7 @@ class CentosVM(basevm.BaseVM):
>          subprocess.check_call(["ln", "-f", cimg, img_tmp + ".xz"])
>          subprocess.check_call(["xz", "--keep", "-dvf", img_tmp + ".xz"])
>          self.exec_qemu_img("resize", img_tmp, "50G")
> -        self.boot(img_tmp, extra_args = ["-cdrom", self._gen_cloud_init_iso()])
> +        self.boot(img_tmp, extra_args = ["-cdrom", self.gen_cloud_init_iso()])
>          self.wait_ssh()
>          self.ssh_root_check("touch /etc/cloud/cloud-init.disabled")
>          self.ssh_root_check("yum update -y")
> diff --git a/tests/vm/ubuntu.i386 b/tests/vm/ubuntu.i386
> index 3834cd7a8d..7df54ae094 100755
> --- a/tests/vm/ubuntu.i386
> +++ b/tests/vm/ubuntu.i386
> @@ -29,41 +29,6 @@ class UbuntuX86VM(basevm.BaseVM):
>          make --output-sync {target} -j{jobs} {verbose};
>      """
>  
> -    def _gen_cloud_init_iso(self):
> -        cidir = self._tmpdir
> -        mdata = open(os.path.join(cidir, "meta-data"), "w")
> -        mdata.writelines(["instance-id: ubuntu-vm-0\n",
> -                          "local-hostname: ubuntu-guest\n"])
> -        mdata.close()
> -        udata = open(os.path.join(cidir, "user-data"), "w")
> -        udata.writelines(["#cloud-config\n",
> -                          "chpasswd:\n",
> -                          "  list: |\n",
> -                          "    root:%s\n" % self.ROOT_PASS,
> -                          "    %s:%s\n" % (self.GUEST_USER, self.GUEST_PASS),
> -                          "  expire: False\n",
> -                          "users:\n",
> -                          "  - name: %s\n" % self.GUEST_USER,
> -                          "    sudo: ALL=(ALL) NOPASSWD:ALL\n",
> -                          "    ssh-authorized-keys:\n",
> -                          "    - %s\n" % basevm.SSH_PUB_KEY,
> -                          "  - name: root\n",
> -                          "    ssh-authorized-keys:\n",
> -                          "    - %s\n" % basevm.SSH_PUB_KEY,
> -                          "locale: en_US.UTF-8\n"])
> -        proxy = os.environ.get("http_proxy")
> -        if not proxy is None:
> -            udata.writelines(["apt:\n",
> -                              "  proxy: %s" % proxy])
> -        udata.close()
> -        subprocess.check_call(["genisoimage", "-output", "cloud-init.iso",
> -                               "-volid", "cidata", "-joliet", "-rock",
> -                               "user-data", "meta-data"],
> -                               cwd=cidir,
> -                               stdin=self._devnull, stdout=self._stdout,
> -                               stderr=self._stdout)
> -        return os.path.join(cidir, "cloud-init.iso")
> -
>      def build_image(self, img):
>          cimg = self._download_with_cache(
>              "https://cloud-images.ubuntu.com/releases/bionic/release-20191114/ubuntu-18.04-server-cloudimg-i386.img",
> @@ -71,7 +36,7 @@ class UbuntuX86VM(basevm.BaseVM):
>          img_tmp = img + ".tmp"
>          subprocess.check_call(["cp", "-f", cimg, img_tmp])
>          self.exec_qemu_img("resize", img_tmp, "50G")
> -        self.boot(img_tmp, extra_args = ["-cdrom", self._gen_cloud_init_iso()])
> +        self.boot(img_tmp, extra_args = ["-cdrom", self.gen_cloud_init_iso()])
>          self.wait_ssh()
>          self.ssh_root_check("touch /etc/cloud/cloud-init.disabled")
>          self.ssh_root_check("apt-get update")


-- 
Alex Bennée


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v1 00/14] tests/vm: Add support for aarch64 VMs
  2020-02-05 21:29 [PATCH v1 00/14] tests/vm: Add support for aarch64 VMs Robert Foley
                   ` (13 preceding siblings ...)
  2020-02-05 21:29 ` [PATCH v1 14/14] tests/vm: change scripts to use self._config Robert Foley
@ 2020-02-07 16:50 ` Alex Bennée
  14 siblings, 0 replies; 25+ messages in thread
From: Alex Bennée @ 2020-02-07 16:50 UTC (permalink / raw)
  To: Robert Foley; +Cc: fam, peter.puhov, philmd, qemu-devel


Robert Foley <robert.foley@linaro.org> writes:

> This is version 1 of the patch series to 
> add support for 2 aarch64 VMs.  
>  - Ubuntu 18.04 aarch64 VM
>  - CentOS 8 aarch64 VM

Testing under TCG with:

  make vm-build-ubuntu.aarch64 V=1 QEMU=aarch64-softmmu/qemu-system-aarch64

I'm seeing it hang:

  DEBUG:root:ssh_cmd: ssh -t -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectTimeout=60 -p 37431 -i /home/alex.bennee/lsrc/qemu.git/builds/all/vm-test-xxrw1r36.tmp/id_rsa -o SendEnv=https_proxy -o SendEnv=http_proxy -o SendEnv=ftp_proxy -o SendEnv=no_proxy root@127.0.0.1 sed -ie 's/"1"/"0"/g' /etc/apt/apt.conf.d/20auto-upgrades
  Warning: Permanently added '[127.0.0.1]:37431' (ECDSA) to the list of known hosts.
  bash: warning: setlocale: LC_ALL: cannot change locale (en_GB.UTF-8)
  Connection to 127.0.0.1 closed.
  DEBUG:root:ssh_cmd: ssh -t -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectTimeout=60 -p 37431 -i /home/alex.bennee/lsrc/qemu.git/builds/all/vm-test-xxrw1r36.tmp/id_rsa -o SendEnv=https_proxy -o SendEnv=http_proxy -o SendEnv=ftp_proxy -o SendEnv=no_proxy root@127.0.0.1 sync && reboot
  Warning: Permanently added '[127.0.0.1]:37431' (ECDSA) to the list of known hosts.
  bash: warning: setlocale: LC_ALL: cannot change locale (en_GB.UTF-8)
  Connection to 127.0.0.1 closed by remote host.
  Connection to 127.0.0.1 closed.
  DEBUG:root:ssh_cmd: ssh -t -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectTimeout=60 -p 37431 -i /home/alex.bennee/lsrc/qemu.git/builds/all/vm-test-xxrw1r36.tmp/id_rsa -o SendEnv=https_proxy -o SendEnv=http_proxy -o SendEnv=ftp_proxy -o SendEnv=no_proxy root@127.0.0.1 exit 0
  Warning: Permanently added '[127.0.0.1]:37431' (ECDSA) to the list of known hosts.
  bash: warning: setlocale: LC_ALL: cannot change locale (en_GB.UTF-8)
  Connection to 127.0.0.1 closed.
  DEBUG:root:ssh_cmd: ssh -t -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectTimeout=60 -p 37431 -i /home/alex.bennee/lsrc/qemu.git/builds/all/vm-test-xxrw1r36.tmp/id_rsa -o SendEnv=https_proxy -o SendEnv=http_proxy -o SendEnv=ftp_proxy -o SendEnv=no_proxy root@127.0.0.1 locale
  ssh_exchange_identification: Connection closed by remote host
  DEBUG:root:ssh_cmd: ssh -t -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectTimeout=60 -p 37431 -i /home/alex.bennee/lsrc/qemu.git/builds/all/vm-test-xxrw1r36.tmp/id_rsa -o SendEnv=https_proxy -o SendEnv=http_proxy -o SendEnv=ftp_proxy -o SendEnv=no_proxy root@127.0.0.1 sed -ie s/^#\ deb-src/deb-src/g /etc/apt/sources.list
  ssh_exchange_identification: Connection closed by remote host
  DEBUG:root:ssh_cmd: ssh -t -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectTimeout=60 -p 37431 -i /home/alex.bennee/lsrc/qemu.git/builds/all/vm-test-xxrw1r36.tmp/id_rsa -o SendEnv=https_proxy -o SendEnv=http_proxy -o SendEnv=ftp_proxy -o SendEnv=no_proxy root@127.0.0.1 apt-get update
  ssh_exchange_identification: Connection closed by remote host
  DEBUG:root:ssh_cmd: ssh -t -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectTimeout=60 -p 37431 -i /home/alex.bennee/lsrc/qemu.git/builds/all/vm-test-xxrw1r36.tmp/id_rsa -o SendEnv=https_proxy -o SendEnv=http_proxy -o SendEnv=ftp_proxy -o SendEnv=no_proxy root@127.0.0.1 apt-get build-dep -y qemu
  ssh_exchange_identification: Connection closed by remote host
  DEBUG:root:ssh_cmd: ssh -t -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectTimeout=60 -p 37431 -i /home/alex.bennee/lsrc/qemu.git/builds/all/vm-test-xxrw1r36.tmp/id_rsa -o SendEnv=https_proxy -o SendEnv=http_proxy -o SendEnv=ftp_proxy -o SendEnv=no_proxy root@127.0.0.1 apt-get install -y libfdt-dev flex bison
  ssh_exchange_identification: Connection closed by remote host
  DEBUG:root:ssh_cmd: ssh -t -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectTimeout=60 -p 37431 -i /home/alex.bennee/lsrc/qemu.git/builds/all/vm-test-xxrw1r36.tmp/id_rsa -o SendEnv=https_proxy -o SendEnv=http_proxy -o SendEnv=ftp_proxy -o SendEnv=no_proxy root@127.0.0.1 poweroff
  ssh_exchange_identification: Connection closed by remote host

-- 
Alex Bennée


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v1 06/14] tests/vm: Add logging of console to file.
  2020-02-05 21:29 ` [PATCH v1 06/14] tests/vm: Add logging of console to file Robert Foley
@ 2020-02-07 17:12   ` Alex Bennée
  2020-02-07 22:20     ` Robert Foley
  0 siblings, 1 reply; 25+ messages in thread
From: Alex Bennée @ 2020-02-07 17:12 UTC (permalink / raw)
  To: Robert Foley; +Cc: fam, peter.puhov, philmd, qemu-devel


Robert Foley <robert.foley@linaro.org> writes:

> This adds logging of the char device used by the console
> to a file.  The basevm.py then uses this file to read
> chars from the console.
> One reason to add this is to aid with debugging.

I can certainly see an argument for saving the install log.

> But another is because there is an issue where the QEMU
> might hang if the characters from the character device
> are not consumed by the script.

I'm a little confused by this. Outputting to a file and then parsing the
file seems a bit more janky than injesting the output in the script and
then logging it.

Is this to work around the hang because the socket buffers fill up and
aren't drained?

>
> Signed-off-by: Robert Foley <robert.foley@linaro.org>
> ---
>  tests/vm/basevm.py        | 48 ++++++++++++++++++++++---
>  tests/vm/socket_thread.py | 73 +++++++++++++++++++++++++++++++++++++++
>  2 files changed, 116 insertions(+), 5 deletions(-)
>  create mode 100644 tests/vm/socket_thread.py
>
> diff --git a/tests/vm/basevm.py b/tests/vm/basevm.py
> index a926211da8..87a484c55c 100755
> --- a/tests/vm/basevm.py
> +++ b/tests/vm/basevm.py
> @@ -31,12 +31,17 @@ import tempfile
>  import shutil
>  import multiprocessing
>  import traceback
> +from socket_thread import SocketThread
>  
>  SSH_KEY = open(os.path.join(os.path.dirname(__file__),
>                 "..", "keys", "id_rsa")).read()
>  SSH_PUB_KEY = open(os.path.join(os.path.dirname(__file__),
>                     "..", "keys", "id_rsa.pub")).read()
>  
> +class ConsoleTimeoutException(Exception):
> +    """Raise this exception when read from console times out."""
> +    pass
> +
>  class BaseVM(object):
>      GUEST_USER = "qemu"
>      GUEST_PASS = "qemupass"
> @@ -59,12 +64,18 @@ class BaseVM(object):
>      poweroff = "poweroff"
>      # enable IPv6 networking
>      ipv6 = True
> +    # This is the timeout on the wait for console bytes.
> +    socket_timeout = 120
>      # Scale up some timeouts under TCG.
>      # 4 is arbitrary, but greater than 2,
>      # since we found we need to wait more than twice as long.
>      tcg_ssh_timeout_multiplier = 4
> +    console_logfile = "console.log"

We should probably dump the log somewhere other than cwd. Given we cache
stuff in ~/.cache/qemu-vm maybe something of the form:

  ~/.cache/qemu-vm/ubuntu.aarch64.install.log

?

>      def __init__(self, debug=False, vcpus=None):
>          self._guest = None
> +        self._console_fd = None
> +        self._socket_thread = None
> +        self._console_timeout_sec = self.socket_timeout
>          self._tmpdir = os.path.realpath(tempfile.mkdtemp(prefix="vm-test-",
>                                                           suffix=".tmp",
>                                                           dir="."))
> @@ -179,6 +190,15 @@ class BaseVM(object):
>                              "-device",
>                              "virtio-blk,drive=%s,serial=%s,bootindex=1" % (name, name)]
>  
> +    def init_console(self, socket):
> +        """Init the thread to dump console to a file.
> +           Also open the file descriptor we will use to
> +           read from the console."""
> +        self._socket_thread = SocketThread(socket, self.console_logfile)
> +        self._console_fd = open(self.console_logfile, "r")
> +        self._socket_thread.start()
> +        print("console logfile is: {}".format(self.console_logfile))
> +
>      def boot(self, img, extra_args=[]):
>          args = self._args + [
>              "-device", "VGA",
> @@ -201,6 +221,7 @@ class BaseVM(object):
>              raise
>          atexit.register(self.shutdown)
>          self._guest = guest
> +        self.init_console(guest.console_socket)
>          usernet_info = guest.qmp("human-monitor-command",
>                                   command_line="info usernet")
>          self.ssh_port = None
> @@ -212,9 +233,10 @@ class BaseVM(object):
>              raise Exception("Cannot find ssh port from 'info usernet':\n%s" % \
>                              usernet_info)
>  
> -    def console_init(self, timeout = 120):
> -        vm = self._guest
> -        vm.console_socket.settimeout(timeout)
> +    def console_init(self, timeout = None):
> +        if timeout == None:
> +            timeout = self.socket_timeout
> +        self._console_timeout_sec = timeout
>  
>      def console_log(self, text):
>          for line in re.split("[\r\n]", text):
> @@ -230,13 +252,27 @@ class BaseVM(object):
>              # log console line
>              sys.stderr.write("con recv: %s\n" % line)
>  
> +    def console_recv(self, n):
> +        """Read n chars from the console_logfile being dumped to
> +           by the socket thread we created earlier."""
> +        start_time = time.time()
> +        while True:
> +            data = self._console_fd.read(1)
> +            if data != "":
> +                break
> +            time.sleep(0.1)
> +            elapsed_sec = time.time() - start_time
> +            if elapsed_sec > self._console_timeout_sec:
> +                raise ConsoleTimeoutException
> +        return data.encode('latin1')
> +

Is latin1 really the best choice here? I would expect things to be utf-8 clean.

>      def console_wait(self, expect, expectalt = None):
>          vm = self._guest
>          output = ""
>          while True:
>              try:
> -                chars = vm.console_socket.recv(1)
> -            except socket.timeout:
> +                chars = self.console_recv(1)
> +            except ConsoleTimeoutException:
>                  sys.stderr.write("console: *** read timeout ***\n")
>                  sys.stderr.write("console: waiting for: '%s'\n" % expect)
>                  if not expectalt is None:
> @@ -335,6 +371,8 @@ class BaseVM(object):
>              raise Exception("Timeout while waiting for guest ssh")
>  
>      def shutdown(self):
> +        self._socket_thread.join()
> +        self._console_fd.close()
>          self._guest.shutdown()
>      def wait(self):
>          self._guest.wait()
> diff --git a/tests/vm/socket_thread.py b/tests/vm/socket_thread.py
> new file mode 100644
> index 0000000000..6160e9163d
> --- /dev/null
> +++ b/tests/vm/socket_thread.py
> @@ -0,0 +1,73 @@
> +#!/usr/bin/env python
> +#
> +# This python module defines a thread object which
> +# reads from a socket and dumps it to a file.
> +#
> +# The main use case is for reading QEMU console char dev and
> +# dumping them to a file either for debugging or for
> +# parsing by QEMU itself.
> +#
> +# Copyright 2020 Linaro
> +#
> +# Authors:
> +#  Robert Foley <robert.foley@linaro.org>
> +#
> +# This code is licensed under the GPL version 2 or later.  See
> +# the COPYING file in the top-level directory.
> +#
> +import sys
> +import re
> +import threading
> +import time
> +import traceback
> +import gettext
> +
> +class SocketThread(threading.Thread):
> +    """ Implements the standard threading.Thread API.(start, join, etc.).
> +        dumps all characters received on socket into a file.
> +    """
> +    def __init__(self, socket, filename):
> +        super(SocketThread, self).__init__()
> +        self.alive = threading.Event()
> +        self.alive.set()
> +        self.socket = socket
> +        self.log_file = open(filename, "w")
> +        self.debug = True
> +
> +    def receive(self):
> +        """Until the user calls join, we will read chars from
> +           the socket and dump them as is to the file."""
> +        self.socket.setblocking(0)
> +        self.socket.settimeout(1.0)
> +        while self.alive.isSet():
> +            try:
> +                chars = self.socket.recv(1)
> +            except:
> +                continue
> +            output = chars.decode("latin1")
> +            self.log_file.write("{}".format(output))
> +            # Flush the file since we need the characters to be
> +            # always up to date in case someone is reading the file
> +            # waiting for some characters to show up.
> +            self.log_file.flush()
> +        self.socket.setblocking(1)
> +
> +    def run(self):
> +        """This is the main loop of the socket thread.
> +           Simply receive from the file until the user
> +           calls join."""
> +        while self.alive.isSet():
> +            try:
> +                self.receive()
> +            except Exception as e:
> +                sys.stderr.write("Exception encountered\n")
> +                traceback.print_exc()
> +                continue
> +
> +    def join(self, timeout=None):
> +        """Time to destroy the thread.
> +           Clear the event to stop the thread, and wait for
> +           it to complete."""
> +        self.alive.clear()
> +        threading.Thread.join(self, timeout)
> +        self.log_file.close()

I'm note sure about this - introducing threading into Python seems very
un-pythonic. I wonder if the python experts have any view on a better
way to achieve what we want which I think is:

  - a buffer that properly drains output from QEMU
  - which can optionally be serialised onto disk for logging

What else are we trying to achieve here?

-- 
Alex Bennée


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v1 06/14] tests/vm: Add logging of console to file.
  2020-02-07 17:12   ` Alex Bennée
@ 2020-02-07 22:20     ` Robert Foley
  2020-02-10 18:21       ` Robert Foley
  0 siblings, 1 reply; 25+ messages in thread
From: Robert Foley @ 2020-02-07 22:20 UTC (permalink / raw)
  To: Alex Bennée
  Cc: fam, Peter Puhov, Philippe Mathieu-Daudé, qemu-devel

On Fri, 7 Feb 2020 at 12:12, Alex Bennée <alex.bennee@linaro.org> wrote:
> Robert Foley <robert.foley@linaro.org> writes:
>
> > This adds logging of the char device used by the console
> > to a file.  The basevm.py then uses this file to read
> > chars from the console.
> > One reason to add this is to aid with debugging.
>
> I can certainly see an argument for saving the install log.
>
> > But another is because there is an issue where the QEMU
> > might hang if the characters from the character device
> > are not consumed by the script.
>
> I'm a little confused by this. Outputting to a file and then parsing the
> file seems a bit more janky than injesting the output in the script and
> then logging it.
>
> Is this to work around the hang because the socket buffers fill up and
> aren't drained?

Yes, exactly.  This is to work around the hang we are seeing when we
try to use these new VMs.

> > +    console_logfile = "console.log"
>
> We should probably dump the log somewhere other than cwd. Given we cache
> stuff in ~/.cache/qemu-vm maybe something of the form:
>
>   ~/.cache/qemu-vm/ubuntu.aarch64.install.log
>
> ?

Good point, we will locate the log file there.

> > +            elapsed_sec = time.time() - start_time
> > +            if elapsed_sec > self._console_timeout_sec:
> > +                raise ConsoleTimeoutException
> > +        return data.encode('latin1')
> > +
>
> Is latin1 really the best choice here? I would expect things to be utf-8 clean.

We were trying to follow the existing code, which is using latin1.
For example, console_wait() or console_consume() are using latin1.
However on further inspection we see that console_send() is using utf-8.
We will look at changing these latin1 cases to be utf-8.
I also found a case in get_qemu_version() we will change to utf-8 also.

> > +
> > +    def join(self, timeout=None):
> > +        """Time to destroy the thread.
> > +           Clear the event to stop the thread, and wait for
> > +           it to complete."""
> > +        self.alive.clear()
> > +        threading.Thread.join(self, timeout)
> > +        self.log_file.close()
>
> I'm note sure about this - introducing threading into Python seems very
> un-pythonic. I wonder if the python experts have any view on a better
> way to achieve what we want which I think is:
>
>   - a buffer that properly drains output from QEMU
>   - which can optionally be serialised onto disk for logging
>
> What else are we trying to achieve here?

I think that covers what we are trying to achieve here.
The logging to file is a nice to have, but
the draining of the output from QEMU is the main objective here.
We will do a bit more research here to seek out a cleaner way to achieve this,
but certainly we would also be interested if any python experts have a
view on a cleaner approach.

Thanks & Regards,
-Rob
>
> --
> Alex Bennée


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v1 06/14] tests/vm: Add logging of console to file.
  2020-02-07 22:20     ` Robert Foley
@ 2020-02-10 18:21       ` Robert Foley
  0 siblings, 0 replies; 25+ messages in thread
From: Robert Foley @ 2020-02-10 18:21 UTC (permalink / raw)
  To: Alex Bennée
  Cc: fam, Peter Puhov, Philippe Mathieu-Daudé, qemu-devel

On Fri, 7 Feb 2020 at 17:20, Robert Foley <robert.foley@linaro.org> wrote:
>
> On Fri, 7 Feb 2020 at 12:12, Alex Bennée <alex.bennee@linaro.org> wrote:
> > > +
> > > +    def join(self, timeout=None):
> > > +        """Time to destroy the thread.
> > > +           Clear the event to stop the thread, and wait for
> > > +           it to complete."""
> > > +        self.alive.clear()
> > > +        threading.Thread.join(self, timeout)
> > > +        self.log_file.close()
> >
> > I'm note sure about this - introducing threading into Python seems very
> > un-pythonic. I wonder if the python experts have any view on a better
> > way to achieve what we want which I think is:
> >
> >   - a buffer that properly drains output from QEMU
> >   - which can optionally be serialised onto disk for logging
> >
> > What else are we trying to achieve here?
>
> I think that covers what we are trying to achieve here.
> The logging to file is a nice to have, but
> the draining of the output from QEMU is the main objective here.
> We will do a bit more research here to seek out a cleaner way to achieve this,
> but certainly we would also be interested if any python experts have a
> view on a cleaner approach.
>
We have a few more ideas on how to make this a bit cleaner.

We could create a new class "ConsoleSocket", based on asyncore.dispatcher.
The asyncore python library allows for overriding certain functionality of
an underlying socket.
We could override the handle_read() method in order to get a callback
when data is available to be read from the console.  This is much cleaner
than us simply waiting with a read() on the socket in a thread.
Note that even asyncore requires a thread around asyncore.loop(), but we would
only be responsible for start/stop of the thread and the thread body
is defined for us (literally just asyncore.loop()).
The thread starting/stopping would be completely transparent
to the users of this new ConsoleSocket.  The thread would be created on
initialization of ConsoleSocket, and destroyed upon close() of the socket.

As the console bytes get consumed we can dump them to an in memory stream,
rather than dumping them to a file right away.
We could perhaps use an io.StringIO text stream.  This stream will get
the bytes of the console and the test will consume the bytes directly
from this stream.
In addition, we could optionally dump the bytes to a file as well.

How does this sound?  Just looking for a bit of feedback before we
head in this direction.

Thanks & Regards,
-Rob


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v1 08/14] tests/vm: Added configuration file support
  2020-02-05 21:29 ` [PATCH v1 08/14] tests/vm: Added configuration file support Robert Foley
@ 2020-02-14 16:53   ` Alex Bennée
  2020-02-14 18:00     ` Robert Foley
  0 siblings, 1 reply; 25+ messages in thread
From: Alex Bennée @ 2020-02-14 16:53 UTC (permalink / raw)
  To: Robert Foley; +Cc: fam, peter.puhov, philmd, qemu-devel


Robert Foley <robert.foley@linaro.org> writes:

> Changes to tests/vm/basevm.py to allow accepting a configuration file
> as a parameter. Allows for specifying VM options such as
> cpu, machine, memory, and arbitrary qemu arguments for specifying options
> such as NUMA configuration.
> Also added an example conf_example_aarch64.yml and conf_example_x86.yml.
>
> Signed-off-by: Robert Foley <robert.foley@linaro.org>
> ---
>  tests/vm/Makefile.include         |  2 ++
>  tests/vm/basevm.py                | 29 +++++++++++++++++-
>  tests/vm/conf_example_aarch64.yml | 51 +++++++++++++++++++++++++++++++
>  tests/vm/conf_example_x86.yml     | 50 ++++++++++++++++++++++++++++++
>  4 files changed, 131 insertions(+), 1 deletion(-)
>  create mode 100644 tests/vm/conf_example_aarch64.yml
>  create mode 100644 tests/vm/conf_example_x86.yml
>
> diff --git a/tests/vm/Makefile.include b/tests/vm/Makefile.include
> index 778e506755..e9ed33226d 100644
> --- a/tests/vm/Makefile.include
> +++ b/tests/vm/Makefile.include
> @@ -35,6 +35,8 @@ vm-help vm-test:
>  	@echo "    V=1				 - Enable verbose ouput on host and guest commands"
>  	@echo "    QEMU=/path/to/qemu		 - Change path to QEMU binary"
>  	@echo "    QEMU_IMG=/path/to/qemu-img	 - Change path to qemu-img tool"
> +	@echo "    QEMU_CONFIG=/path/conf.yml   - Change path to VM configuration .yml file."
> +	@echo "                                   See conf_example_*.yml for file format details."
>  
>  vm-build-all: $(addprefix vm-build-, $(IMAGES))
>  
> diff --git a/tests/vm/basevm.py b/tests/vm/basevm.py
> index 33004934af..f488d4103c 100755
> --- a/tests/vm/basevm.py
> +++ b/tests/vm/basevm.py
> @@ -32,6 +32,7 @@ import shutil
>  import multiprocessing
>  import traceback
>  from socket_thread import SocketThread
> +import yaml

So this throws my setup on my Gentoo SynQuacer. Is this meant to be in
the standard library or is this a separate dependency?

-- 
Alex Bennée


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v1 08/14] tests/vm: Added configuration file support
  2020-02-14 16:53   ` Alex Bennée
@ 2020-02-14 18:00     ` Robert Foley
  0 siblings, 0 replies; 25+ messages in thread
From: Robert Foley @ 2020-02-14 18:00 UTC (permalink / raw)
  To: Alex Bennée
  Cc: fam, Peter Puhov, Philippe Mathieu-Daudé, qemu-devel

On Fri, 14 Feb 2020 at 11:54, Alex Bennée <alex.bennee@linaro.org> wrote:
> >  from socket_thread import SocketThread
> > +import yaml
>
> So this throws my setup on my Gentoo SynQuacer. Is this meant to be in
> the standard library or is this a separate dependency?
>
This is a separate dependency.  On Ubuntu the package is python3-yaml.
This brings up an interesting point.
If the yaml dependency is not there, should we expect to gracefully
handle this in the python script, and
simply not allow yaml files?  I suppose we could error out if a yaml
file is supplied
and ask for the dependency to get installed.
Or is there something we should do earlier, maybe in the configure, to
warn or error about the missing
dependency?

Thanks & Regards,
-Rob


> --
> Alex Bennée


^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2020-02-14 18:02 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-02-05 21:29 [PATCH v1 00/14] tests/vm: Add support for aarch64 VMs Robert Foley
2020-02-05 21:29 ` [PATCH v1 01/14] tests/vm: use $(PYTHON) consistently Robert Foley
2020-02-07 11:42   ` Alex Bennée
2020-02-05 21:29 ` [PATCH v1 02/14] tests/vm: Debug mode shows ssh output Robert Foley
2020-02-05 21:29 ` [PATCH v1 03/14] tests/vm: increased max timeout for vm boot Robert Foley
2020-02-07 12:01   ` Alex Bennée
2020-02-05 21:29 ` [PATCH v1 04/14] tests/vm: give wait_ssh() option to wait for root Robert Foley
2020-02-07 12:01   ` Alex Bennée
2020-02-05 21:29 ` [PATCH v1 05/14] tests/vm: Added gen_cloud_init_iso() to basevm.py Robert Foley
2020-02-07 12:22   ` Alex Bennée
2020-02-05 21:29 ` [PATCH v1 06/14] tests/vm: Add logging of console to file Robert Foley
2020-02-07 17:12   ` Alex Bennée
2020-02-07 22:20     ` Robert Foley
2020-02-10 18:21       ` Robert Foley
2020-02-05 21:29 ` [PATCH v1 07/14] tests/vm: Add configuration to basevm.py Robert Foley
2020-02-05 21:29 ` [PATCH v1 08/14] tests/vm: Added configuration file support Robert Foley
2020-02-14 16:53   ` Alex Bennée
2020-02-14 18:00     ` Robert Foley
2020-02-05 21:29 ` [PATCH v1 09/14] tests/vm: add --boot-console switch Robert Foley
2020-02-05 21:29 ` [PATCH v1 10/14] tests/vm: Add ability to select QEMU from current build Robert Foley
2020-02-05 21:29 ` [PATCH v1 11/14] tests/vm: allow wait_ssh() to specify command Robert Foley
2020-02-05 21:29 ` [PATCH v1 12/14] tests/vm: Added a new script for ubuntu.aarch64 Robert Foley
2020-02-05 21:29 ` [PATCH v1 13/14] tests/vm: Added a new script for centos.aarch64 Robert Foley
2020-02-05 21:29 ` [PATCH v1 14/14] tests/vm: change scripts to use self._config Robert Foley
2020-02-07 16:50 ` [PATCH v1 00/14] tests/vm: Add support for aarch64 VMs Alex Bennée

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.