QEMU arm64 cloud server emulation
This is basically a rehash of an original post on CNXSoft - all credit (particularly for the Virtio device arguments used below) belongs to the author of that piece.
Download the latest
uefi1.img image. E.g.
ubuntu-16.04-server-cloudimg-arm64-uefi1.img from https://cloud-images.ubuntu.com/releases/16.04/release/
Download the UEFI firmware image
QEMU_EFI.fd from https://releases.linaro.org/components/kernel/uefi-linaro/latest/release/qemu64/
Determine your current username and get your current ssh public key:
$ whoami ghawkins $ cat ~/.ssh/id_rsa.pub ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC...
Use these values to create a
cloud.txt file replacing the username, here shown as
ghawkins, and the
ssh-rsa value with the values appropriate for you:
$ cat > cloud.txt << EOF #cloud-config users: - name: ghawkins ssh-authorized-keys: - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC... sudo: ['ALL=(ALL) NOPASSWD:ALL'] groups: sudo shell: /bin/bash EOF
#cloud-config line above is not a comment and things will fail silently without it.
Cread a cloud-config disk image:
$ cloud-localds --disk-format qcow2 cloud.img cloud.txt
Note: by default
cloud-localds creates a raw image and QEMU now complains at having to guess about such an image so use
--disk-format qcow2 to specify a well defined format that QEMU can easily consume.
Backup your image:
$ cp ubuntu-16.04-server-cloudimg-arm64-disk1.img ubuntu-16.04-server-cloudimg-arm64-disk1.img.orig
The QEMU launch command is somewhat more complex than for e.g. a fully virtualized, rather than emulated, setup with an x86_64 guest running on an x86_64 host.
Here is the command first:
$ qemu-system-aarch64 \ -smp 2 \ -m 1024 \ -M virt \ -cpu cortex-a57 \ -bios QEMU_EFI.fd \ -nographic \ -device virtio-blk-device,drive=image \ -drive if=none,id=image,file=ubuntu-16.04-server-cloudimg-arm64-uefi1.img \ -device virtio-blk-device,drive=cloud \ -drive if=none,id=cloud,file=cloud.img \ -device virtio-net-device,netdev=user0 \ -netdev user,id=user0 \ -redir tcp:2222::22
You'll have to change
ubuntu-16.04-server-cloudimg-arm64-uefi1.img if you downloaded a later image with a different name.
Now let's look at the arguments that configure our system:
-smp 2- 2 (virtual) cores.
-m 1024- 1024MB of system memory.
-M virt- emulate a generic QEMU ARM machine.
-cpu cortex-a57- the CPU model to emulate.
-bios QEMU_EFI.fd- the BIOS firmware file to use.
-nographic- output goes to the terminal (rather than opening a graphics capable window).
-device virtio-blk-device,drive=image- create a Virtio block device called "image".
-drive if=none,id=image,file=ubuntu-16.04-server-cloudimg-arm64-uefi1.img- create a drive using the "image" device and our cloud server disk image.
-device virtio-blk-device,drive=cloud- create another Virtio block device called "cloud".
-drive if=none,id=cloud,file=cloud.img- create a drive using the "cloud" device and our cloud-config disk image.
-device virtio-net-device,netdev=user0- create a Virtio network device called "user0"
-netdev user,id=user0- create a user mode network stack using device "user0"
-redir tcp:2222::22- map port 2222 on the host to port 22 (the standard ssh port) on the guest.
Here we create a generic QEMU ARM machine. You can see a complete list of possible ARM machines like so:
$ qemu-system-aarch64 -M help akita Sharp SL-C1000 (Akita) PDA (PXA270) ... z2 Zipit Z2 (PXA27x)
This list seems to include all ARM machines, not just 64-bit ones. The latest versions of QEMU (but not the one that currently comes with Ubuntu 16.04 LTS) include the well know Raspberry Pi 2 (but not the 3).
For a given machine you can then see the supported processors:
$ qemu-system-aarch64 -M virt -cpu help arm1026 ... ti925t
Once you run the command up above to launch an emulated ARM64 machine it will take a few minutes to boot and will output something like the following:
error: no suitable video mode found. EFI stub: Booting Linux Kernel... EFI stub: Using DTB from configuration table EFI stub: Exiting boot services and installing virtual address map... [ 0.000000] Booting Linux on physical CPU 0x0 [ 0.000000] Initializing cgroup subsys cpuset
The initial error, about "no suitable video mode found", can be ignored - we specifically set
Eventually a login prompt will appear - which cannot be used as in our cloud-config file we only specified key based ssh login.
Depending on how fast various jobs (kicked off during the boot process) run further output will appear after the login prompt appears.
The first time you launch a given system you should see output confirming that the ssh key specified up above has been installed.
And eventually you should see something like:
[ 220.784509] cloud-init: Cloud-init v. 0.7.8 finished at ...
Now in another terminal you can log in to the newly launched cloud server:
$ ssh -p 2222 ghawkins@localhost
If all goes well you'll log straight in without any username or password.
If you've started previous QEMU images in a similar manner then ssh may issue a dire warning like so (and refuse to login):
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
To resolve this and remove previous details:
$ ssh-keygen -f ~/.ssh/known_hosts -R '[localhost]:2222'
When logged into the cloud server you can...
- Confirm that it's an
$ uname -a Linux ubuntu 4.4.0-59-generic #80-Ubuntu SMP Fri Jan 6 17:37:14 UTC 2017 aarch64 aarch64 aarch64 GNU/Linux
- Has two cores:
$ cat /proc/cpuinfo processor : 0 ... processor : 1 ...
- Shut it down:
$ sudo shutdown now
In the original terminal (where you launched
qemu-system-aarch64) you can follow the shutdown process.
Note: when running
sudo shutdown now the shutdown succeeds but the following error appears:
sudo: unable to resolve host ubuntu
You'll see this anytime you run
sudo - to resolve it (as per Ask Ubuntu) just edit
/etc/hosts and add
ubuntu at the end of the existing line for the address
127.0.0.1 so you end up with something like:
127.0.0.1 localhost ubuntu