Message ID | 20200124165335.422-8-robert.foley@linaro.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | tests/vm: Add support for aarch64 VMs | expand |
Robert Foley <robert.foley@linaro.org> writes: > 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> > Reviewed-by: Peter Puhov <peter.puhov@linaro.org> > --- > tests/vm/Makefile.include | 7 +- > tests/vm/aarch64vm.py | 41 +++++++++++ > tests/vm/ubuntu.aarch64 | 144 ++++++++++++++++++++++++++++++++++++++ > 3 files changed, 190 insertions(+), 2 deletions(-) > 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 9e7c46a473..966b417ba7 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" > @@ -35,6 +36,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 config_example.yml for file format details." > > vm-build-all: $(addprefix vm-build-, $(IMAGES)) > > @@ -80,7 +83,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/$* \ This seems like it should be in a different patch. > $(if $(J),--jobs $(J)) \ > --image "$<" \ > --interactive \ > diff --git a/tests/vm/aarch64vm.py b/tests/vm/aarch64vm.py > new file mode 100644 > index 0000000000..43f841571f > --- /dev/null > +++ b/tests/vm/aarch64vm.py > @@ -0,0 +1,41 @@ > +#!/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 > + > + > +def create_flash_images(): > + """Creates the appropriate pflash files > + for an aarch64 VM.""" > + subprocess.check_call(["dd", "if=/dev/zero", "of=flash0.img", > + "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=flash0.img", "conv=notrunc"]) > + subprocess.check_call(["dd", "if=/dev/zero", > + "of=flash1.img", "bs=1M", "count=64"]) > + > +def get_pflash_args(): > + """Returns a string that can be used to > + boot qemu using the appropriate pflash files > + for aarch64.""" > + pflash_args = "-drive file=flash0.img,format=raw,if=pflash "\ > + "-drive file=flash1.img,format=raw,if=pflash" > + return pflash_args.split(" ") > diff --git a/tests/vm/ubuntu.aarch64 b/tests/vm/ubuntu.aarch64 > new file mode 100755 > index 0000000000..941f7f5166 > --- /dev/null > +++ b/tests/vm/ubuntu.aarch64 > @@ -0,0 +1,144 @@ > +#!/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 > +import time > +import aarch64vm > + > +DEFAULT_CONFIG = { > + 'cpu' : "max", > + 'machine' : "virt,gic-version=max", According to virt.c: Valid values are 2, 3 and host but max should work on TCG. However we need a more recent QEMU than my system one for it to work. Otherwise you see: DEBUG:qemu.machine:Error launching VM DEBUG:qemu.machine:Command: 'qemu-system-aarch64 -display none -vga none -chardev socket,id=mon,path=/var/tmp/qemu-18443-monitor.sock -mon chardev=mon,mode=control -machine virt,gic-version=max -chardev socket,id=console,path=/var/tmp/qemu-18443-console.sock,server,nowait -serial chardev:console -nodefaults -m 4G -cpu max -netdev user,id=vnet,hostfwd=:127.0.0.1:0-:22 -device virtio-net-pci,netdev=vnet -vnc 127.0.0.1:0,to=20 -drive file=/home/alex.bennee/.cache/qemu-vm/images/ubuntu.aarch64.img.tmp,if=none,id=drive0,cache=writeback -device virtio-blk,drive=drive0,bootindex=0 -cdrom /home/alex.bennee/lsrc/qemu.git/builds/all/vm-test-v8jttvl3.tmp/cloud-init.iso -drive file=flash0.img,format=raw,if=pflash -drive file=flash1.img,format=raw,if=pflash -accel tcg,thread=multi -smp 8 -device VGA' DEBUG:qemu.machine:Output: 'qemu-system-aarch64: Invalid gic-version value\nValid values are 3, 2, host.\n' ERROR:root:Failed to launch QEMU, command line: ERROR:root:qemu-system-aarch64 -nodefaults -m 4G -cpu max -netdev user,id=vnet,hostfwd=:127.0.0.1:0-:22 -device virtio-net-pci,netdev=vnet -vnc 127.0.0.1:0,to=20 -drive file=/home/alex.bennee/.cache/qemu-vm/images/ubuntu.aarch64.img.tmp,if=none,id=drive0,cache=writeback -device virtio-blk,drive=drive0,bootindex=0 -cdrom /home/alex.bennee/lsrc/qemu.git/builds/all/vm-test-v8jttvl3.tmp/cloud-init.iso -drive file=flash0.img,format=raw,if=pflash -drive file=flash1.img,format=raw,if=pflash -accel tcg,thread=multi -smp 8 -device VGA ERROR:root:Log: ERROR:root:qemu-system-aarch64: Invalid gic-version value Valid values are 3, 2, host. ERROR:root:QEMU version >= 2.10 is required Failed to prepare guest environment Traceback (most recent call last): File "/home/alex.bennee/lsrc/qemu.git/tests/vm/basevm.py", line 514, in main return vm.build_image(args.image) File "/home/alex.bennee/lsrc/qemu.git/tests/vm/ubuntu.aarch64", line 114, in build_image self.boot(img_tmp, extra_args = ["-cdrom", ci_img]) File "/home/alex.bennee/lsrc/qemu.git/tests/vm/ubuntu.aarch64", line 105, in boot super(UbuntuAarch64VM, self).boot(img, extra_args=extra_args) File "/home/alex.bennee/lsrc/qemu.git/tests/vm/basevm.py", line 246, in boot guest.launch() File "/home/alex.bennee/lsrc/qemu.git/tests/vm/../../python/qemu/machine.py", line 302, in launch self._launch() File "/home/alex.bennee/lsrc/qemu.git/tests/vm/../../python/qemu/machine.py", line 329, in _launch self._post_launch() File "/home/alex.bennee/lsrc/qemu.git/tests/vm/../../python/qemu/machine.py", line 274, in _post_launch self._qmp.accept() File "/home/alex.bennee/lsrc/qemu.git/tests/vm/../../python/qemu/qmp.py", line 157, in accept return self.__negotiate_capabilities() File "/home/alex.bennee/lsrc/qemu.git/tests/vm/../../python/qemu/qmp.py", line 73, in __negotiate_capabilities raise QMPConnectError qemu.qmp.QMPConnectError /home/alex.bennee/lsrc/qemu.git/tests/vm/Makefile.include:51: recipe for target '/home/alex.bennee/.cache/qemu-vm/images/ubuntu.aarch64.img' failed make: *** [/home/alex.bennee/.cache/qemu-vm/images/ubuntu.aarch64.img] Error 2 > + '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-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 _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") > + print("guest user:pw {}:{}".format(self.GUEST_USER, self.GUEST_PASS)) > + 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" % self.ssh_pub_key, > + " - name: root\n", > + " ssh-authorized-keys:\n", > + " - %s\n" % self.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") It seems this function is proliferating. It certainly seems common enough to be basevm functionality. > + > + def boot(self, img, extra_args=None): > + aarch64vm.create_flash_images() > + default_args = aarch64vm.get_pflash_args() > + 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 os.geteuid() != 0: > + extra_args.extend(["-accel", "tcg,thread=multi"]) Hmmm thread=multi should already be enabled by default where it is safe to do so. Also what has it to do with euid? > + 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]) > + self.wait_ssh(wait_root=True) > + # Fix for slow ssh login. > + self.ssh_root("chmod -x /etc/update-motd.d/*") > + 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") > + > + self.wait_ssh(wait_root=True) > + # 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__": > + sys.exit(basevm.main(UbuntuAarch64VM, DEFAULT_CONFIG))
On Mon, 27 Jan 2020 at 10:01, Alex Bennée <alex.bennee@linaro.org> wrote: > > vm-boot-ssh-%: $(IMAGES_DIR)/%.img > > $(call quiet-command, \ > > - $(SRC_PATH)/tests/vm/$* \ > > + $(PYTHON) $(SRC_PATH)/tests/vm/$* \ > > This seems like it should be in a different patch. Good point, will move it to a different patch. > > + > > +DEFAULT_CONFIG = { > > + 'cpu' : "max", > > + 'machine' : "virt,gic-version=max", > > According to virt.c: > > Valid values are 2, 3 and host > > but max should work on TCG. However we need a more recent QEMU than my > system one for it to work. Otherwise you see: > > DEBUG:qemu.machine:Error launching VM Good point. We were trying to avoid having different values for KVM vs TCG, which we could do with the latest QEMU. We will update this to make sure this works with older versions of QEMU as well. On my system I have qemu 2.11.1 installed by default. It seems that we will need the following defaults based on our environment. For KVM we end up with the below args since max cpu and max gic-version is not available. kvm: -cpu host -machine virt,gic-version=host For TCG max cpu is also not available: qemu-system-aarch64: unable to find CPU model 'max', so we pick cortex-a57. TCG: -cpu cortex-a57 -machine virt,gic-version=3 I suppose we could check the version of QEMU and use the above defaults only for earlier versions of QEMU. This is something we will probably move to aarch64vm.py since it is common. > > +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-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 _gen_cloud_init_iso(self): __snip__ > > + > > + return os.path.join(cidir, "cloud-init.iso") > > It seems this function is proliferating. It certainly seems common > enough to be basevm functionality. Makes sense. Will look at making this common to basevm. > > > + > > + def boot(self, img, extra_args=None): > > + aarch64vm.create_flash_images() > > + default_args = aarch64vm.get_pflash_args() > > + 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 os.geteuid() != 0: > > + extra_args.extend(["-accel", "tcg,thread=multi"]) > > Hmmm thread=multi should already be enabled by default where it is safe > to do so. Also what has it to do with euid? OK. Will look into removing this. We were trying to check for KVM, to only add this under KVM. I see now, we need to use kvm_available() instead of euid. Thanks & Regards, -Rob > > > + 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]) > > + self.wait_ssh(wait_root=True) > > + # Fix for slow ssh login. > > + self.ssh_root("chmod -x /etc/update-motd.d/*") > > + 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") > > + > > + self.wait_ssh(wait_root=True) > > + # 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__": > > + sys.exit(basevm.main(UbuntuAarch64VM, DEFAULT_CONFIG)) > > > -- > Alex Bennée
On Mon, Jan 27, 2020 at 11:47:35AM -0500, Robert Foley wrote: > On Mon, 27 Jan 2020 at 10:01, Alex Bennée <alex.bennee@linaro.org> wrote: > > > vm-boot-ssh-%: $(IMAGES_DIR)/%.img > > > $(call quiet-command, \ > > > - $(SRC_PATH)/tests/vm/$* \ > > > + $(PYTHON) $(SRC_PATH)/tests/vm/$* \ > > > > This seems like it should be in a different patch. > > Good point, will move it to a different patch. > > > > + > > > +DEFAULT_CONFIG = { > > > + 'cpu' : "max", > > > + 'machine' : "virt,gic-version=max", > > > > According to virt.c: > > > > Valid values are 2, 3 and host > > > > but max should work on TCG. However we need a more recent QEMU than my > > system one for it to work. Otherwise you see: > > > > DEBUG:qemu.machine:Error launching VM > > Good point. We were trying to avoid having different values for KVM > vs TCG, which we > could do with the latest QEMU. > We will update this to make sure this works with older versions of QEMU as well. > > On my system I have qemu 2.11.1 installed by default. > It seems that we will need the following defaults based on our environment. > > For KVM we end up with the below args since max cpu and max > gic-version is not available. > kvm: -cpu host -machine virt,gic-version=host > > For TCG max cpu is also not available: qemu-system-aarch64: unable to > find CPU model 'max', > so we pick cortex-a57. > TCG: -cpu cortex-a57 -machine virt,gic-version=3 > > I suppose we could check the version of QEMU and use the above > defaults only for earlier versions of QEMU. > This is something we will probably move to aarch64vm.py since it is common. What versions of QEMU do these tests *have* to support? Because we could just skip the tests for QEMU that doesn't support cpu=max,gic-version=max. 'max' is indeed the nicest selection for using the same command line on KVM (gicv2 and gicv3 hosts) and TCG. Thanks, drew
Hi Drew, On Mon, 27 Jan 2020 at 12:27, Andrew Jones <drjones@redhat.com> wrote: > > > > I suppose we could check the version of QEMU and use the above > > defaults only for earlier versions of QEMU. > > This is something we will probably move to aarch64vm.py since it is common. > > What versions of QEMU do these tests *have* to support? Because we could > just skip the tests for QEMU that doesn't support cpu=max,gic-version=max. > 'max' is indeed the nicest selection for using the same command line on > KVM (gicv2 and gicv3 hosts) and TCG. I believe these test scripts which build/launch the VM have to support the older version of QEMU since this is the version of QEMU currently used when these VMs are launched. I don't know the history on this, but it seems intentional that we use one older/different version of QEMU to launch the VM, while we test the 'current' build of QEMU inside the VM. It also seems like a 'nice to have' to automatically support the latest version where we could use max as you pointed out. Thanks & Regards, -Rob
Robert Foley <robert.foley@linaro.org> writes: > Hi Drew, > > On Mon, 27 Jan 2020 at 12:27, Andrew Jones <drjones@redhat.com> wrote: > >> > >> > I suppose we could check the version of QEMU and use the above >> > defaults only for earlier versions of QEMU. >> > This is something we will probably move to aarch64vm.py since it is common. >> >> What versions of QEMU do these tests *have* to support? Because we could >> just skip the tests for QEMU that doesn't support cpu=max,gic-version=max. >> 'max' is indeed the nicest selection for using the same command line on >> KVM (gicv2 and gicv3 hosts) and TCG. > > I believe these test scripts which build/launch the VM have to support > the older version of QEMU since > this is the version of QEMU currently used when these VMs are > launched. I don't know the history on > this, but it seems intentional that we use one older/different version > of QEMU to launch the VM, Well we defer to the system QEMU as it should be stable. It can be overridden with the QEMU environment variable which worked well enough when we only had VMs of one architecture. Perhaps we needs a new way to say "use the appropriate QEMU from this build"? > while we test the 'current' build of QEMU inside the VM. > It also seems like a 'nice to have' to automatically support the > latest version where we could > use max as you pointed out. > > Thanks & Regards, > -Rob -- Alex Bennée
On Mon, 27 Jan 2020 at 15:07, Alex Bennée <alex.bennee@linaro.org> wrote: > Robert Foley <robert.foley@linaro.org> writes: > > > Hi Drew, > > > > On Mon, 27 Jan 2020 at 12:27, Andrew Jones <drjones@redhat.com> wrote: > > > >> > > >> > I suppose we could check the version of QEMU and use the above > >> > defaults only for earlier versions of QEMU. > >> > This is something we will probably move to aarch64vm.py since it is common. > >> > >> What versions of QEMU do these tests *have* to support? Because we could > >> just skip the tests for QEMU that doesn't support cpu=max,gic-version=max. > >> 'max' is indeed the nicest selection for using the same command line on > >> KVM (gicv2 and gicv3 hosts) and TCG. > > > > I believe these test scripts which build/launch the VM have to support > > the older version of QEMU since > > this is the version of QEMU currently used when these VMs are > > launched. I don't know the history on > > this, but it seems intentional that we use one older/different version > > of QEMU to launch the VM, > > Well we defer to the system QEMU as it should be stable. It can be > overridden with the QEMU environment variable which worked well enough > when we only had VMs of one architecture. Perhaps we needs a new way to > say "use the appropriate QEMU from this build"? Good idea. This is a pretty common use case and it makes sense to make it easy to use. I will add some support for this in my patch series. Thanks & Regards, -Rob > > > while we test the 'current' build of QEMU inside the VM. > > It also seems like a 'nice to have' to automatically support the > > latest version where we could > > use max as you pointed out. > > > > Thanks & Regards, > > -Rob > > > -- > Alex Bennée
diff --git a/tests/vm/Makefile.include b/tests/vm/Makefile.include index 9e7c46a473..966b417ba7 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" @@ -35,6 +36,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 config_example.yml for file format details." vm-build-all: $(addprefix vm-build-, $(IMAGES)) @@ -80,7 +83,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 \ diff --git a/tests/vm/aarch64vm.py b/tests/vm/aarch64vm.py new file mode 100644 index 0000000000..43f841571f --- /dev/null +++ b/tests/vm/aarch64vm.py @@ -0,0 +1,41 @@ +#!/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 + + +def create_flash_images(): + """Creates the appropriate pflash files + for an aarch64 VM.""" + subprocess.check_call(["dd", "if=/dev/zero", "of=flash0.img", + "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=flash0.img", "conv=notrunc"]) + subprocess.check_call(["dd", "if=/dev/zero", + "of=flash1.img", "bs=1M", "count=64"]) + +def get_pflash_args(): + """Returns a string that can be used to + boot qemu using the appropriate pflash files + for aarch64.""" + pflash_args = "-drive file=flash0.img,format=raw,if=pflash "\ + "-drive file=flash1.img,format=raw,if=pflash" + return pflash_args.split(" ") diff --git a/tests/vm/ubuntu.aarch64 b/tests/vm/ubuntu.aarch64 new file mode 100755 index 0000000000..941f7f5166 --- /dev/null +++ b/tests/vm/ubuntu.aarch64 @@ -0,0 +1,144 @@ +#!/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 +import time +import aarch64vm + +DEFAULT_CONFIG = { + 'cpu' : "max", + 'machine' : "virt,gic-version=max", + '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-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 _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") + print("guest user:pw {}:{}".format(self.GUEST_USER, self.GUEST_PASS)) + 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" % self.ssh_pub_key, + " - name: root\n", + " ssh-authorized-keys:\n", + " - %s\n" % self.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 boot(self, img, extra_args=None): + aarch64vm.create_flash_images() + default_args = aarch64vm.get_pflash_args() + 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 os.geteuid() != 0: + extra_args.extend(["-accel", "tcg,thread=multi"]) + 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]) + self.wait_ssh(wait_root=True) + # Fix for slow ssh login. + self.ssh_root("chmod -x /etc/update-motd.d/*") + 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") + + self.wait_ssh(wait_root=True) + # 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__": + sys.exit(basevm.main(UbuntuAarch64VM, DEFAULT_CONFIG))