# Virtualization

Some notes on setting up Docker build hosts using emulation. Specifically using qemu to setup arm32v7 and arm64v8 environments for Docker builds.

Handy if you need are using an SBC that's too 'small' for building searx/gogs but *can* run the final Docker image.

## Inspiration / Further Reading

- [https://resin.io/blog/building-arm-containers-on-any-x86-machine-even-dockerhub/](https://resin.io/blog/building-arm-containers-on-any-x86-machine-even-dockerhub/)
- [https://github.com/petrosagg/armv7hf-python-dockerhub/blob/master/Dockerfile](https://github.com/petrosagg/armv7hf-python-dockerhub/blob/master/Dockerfile)
- [https://github.com/ViViDboarder/docker-rpi-homebridge/blob/master/Dockerfile](https://github.com/ViViDboarder/docker-rpi-homebridge/blob/master/Dockerfile)
  - This BREAKS when not cross building so you can't easily run docker build / up on a docker file w/ these in it
- [https://wiki.qemu.org/Documentation/Platforms/ARM](https://wiki.qemu.org/Documentation/Platforms/ARM)
- [https://translatedcode.wordpress.com/2016/11/03/installing-debian-on-qemus-32-bit-arm-virt-board/](https://translatedcode.wordpress.com/2016/11/03/installing-debian-on-qemus-32-bit-arm-virt-board/)
- [https://translatedcode.wordpress.com/2017/07/24/installing-debian-on-qemus-64-bit-arm-virt-board/](https://translatedcode.wordpress.com/2017/07/24/installing-debian-on-qemus-64-bit-arm-virt-board/)
- [https://www.raymii.org/s/articles/virt-install_introduction_and_copy_paste_distro_install_commands.html](https://www.raymii.org/s/articles/virt-install_introduction_and_copy_paste_distro_install_commands.html)
- [http://ftp.nl.debian.org/debian/dists/stretch/main/](http://ftp.nl.debian.org/debian/dists/stretch/main/)
- [https://www.collabora.com/news-and-blog/blog/2017/06/20/debian-armhf-vm-on-arm64-server/](https://www.collabora.com/news-and-blog/blog/2017/06/20/debian-armhf-vm-on-arm64-server/)
- [http://blog.system76.com/post/139138591598/howto-qemu-w-ubuntu-xenial-host-uefi-guest](http://blog.system76.com/post/139138591598/howto-qemu-w-ubuntu-xenial-host-uefi-guest)

## Minor notes

- Use arm64 for arm64v8
- Use armhf for arm32v

## Prep

``` bash

apt install qemu-system-arm libguestfs-tools qemu-efi qemu-efi-aarch64 qemu-efi-arm

```

## Plain QEMU

These processes will let you bootstrap a virtual machine for later import into libvirt management engines.

### 64bit arm v8

``` bash

# Probably should have this in a dedicated dir, no?
mkdir arm64v8
cd arm64v8
# Pull installer
wget http://ports.ubuntu.com/ubuntu-ports/dists/xenial/main/installer-arm64/current/images/netboot/mini.iso
mv mini.iso net-install.iso
# Create storage for VM
qemu-img create -f qcow2 arm64v8-xenial.qcow2 16G
# Prep EFI boot
cp /usr/share/AAVMF/AAVMF_VARS.fd AAVMF_VARS.fd
# Install
#     WARNING: YOU MUST TWEAK THE GRUB KERNEL CONSOLE LINE TO HAVE 'console=ttyAMA0' IMMEDIATELY FOLLOWING THE KERNEL IMAGE OR YOU WON'T GET OUTPUT
#     NOTE: Use CTRL-H for backspace and CTRL-X to boot
#     NOTE: virtio-blk-device and virtio-net-device are necessary as the mini.iso (renamed to net-install.iso) doesn't support PCI (fixed post-install)
qemu-system-aarch64 -M virt -m 2048 -smp 4 -cpu cortex-a53 \
  -drive if=pflash,format=raw,readonly,file=/usr/share/AAVMF/AAVMF_CODE.fd \
  -drive if=pflash,format=raw,file=AAVMF_VARS.fd \
  -cdrom net-install.iso \
  -drive if=none,file=arm64v8-xenial.qcow2,format=qcow2,id=hd \
  -device virtio-blk-device,drive=hd \
  -netdev user,id=arm0 -device virtio-net-device,netdev=arm0 \
  -nographic -no-reboot
# Backup base install (just in case)
cp arm64v8-xenial.qcow2 arm64v8-xenial-base-install.qcow2
# Run the VM with the necessary parms/infos
qemu-system-aarch64 -M virt -m 2048 -smp 4 -cpu cortex-a53 \
  -drive if=pflash,format=raw,readonly,file=/usr/share/AAVMF/AAVMF_CODE.fd \
  -drive if=pflash,format=raw,file=AAVMF_VARS.fd \
  -drive if=none,file=arm64v8-xenial.qcow2,format=qcow2,id=hd \
  -device virtio-blk-device,drive=hd \
  -netdev user,id=arm0 -device virtio-net-device,netdev=arm0 \
  -nographic -no-reboot

```

### 32bit arm v7

``` bash

# Probably should have this in a dedicated dir, no?
mkdir arm32v7
cd arm32v7
# Get netbook kernel/initrd
wget -O installer-vmlinuz http://ports.ubuntu.com/ubuntu-ports/dists/xenial/main/installer-armhf/current/images/generic-lpae/netboot/vmlinuz
wget -O installer-initrd.gz http://ports.ubuntu.com/ubuntu-ports/dists/xenial/main/installer-armhf/current/images/generic-lpae/netboot/initrd.gz
# Create storage for VM
qemu-img create -f qcow2 arm32v7-xenial.qcow2 16G
# Prep EFI boot
cp /usr/share/AAVMF/AAVMF32_VARS.fd AAVMF32_VARS.fd
# Install
qemu-system-arm -M virt -m 2048 -smp 4 -cpu cortex-a15 \
  -kernel installer-vmlinuz \
  -initrd installer-initrd.gz \
  -drive if=none,file=arm32v7-xenial.qcow2,format=qcow2,id=hd \
  -device virtio-blk-pci,drive=hd \
  -netdev user,id=arm0 -device virtio-net-pci,netdev=arm0 \
  -nographic -no-reboot
# Backup base install (just in case)
cp arm32v7-xenial.qcow2 arm32v7-xenial-base-install.qcow2
# Copy vmlinuz/initrd from root filesystem for final boot
virt-filesystems -a arm32v7-xenial.qcow2
virt-ls -a arm32v7-xenial.qcow2 /boot/
virt-copy-out -a arm32v7-xenial.qcow2 /boot/vmlinuz-4.4.0-127-generic-lpae /boot/initrd.img-4.4.0-127-generic-lpae .
# Boot!
qemu-system-arm -M virt -m 2048 -smp 4 -cpu cortex-a15 \
  -kernel vmlinuz-4.4.0-127-generic-lpae \
  -initrd initrd.img-4.4.0-127-generic-lpae \
  -drive if=none,file=arm32v7-xenial.qcow2,format=qcow2,id=hd \
  -device virtio-blk-pci,drive=hd \
  -netdev user,id=arm0 -device virtio-net-pci,netdev=arm0 \
  -nographic -no-reboot

```

## virsh/virt-install

This section is very much a work in progress. Based on further research / reading you'll need to bootstrap the VM with raw qemu and then import to virsh.

``` bash

virt-install --name ubuntu-16.04-arm64v8 \
  --import \
  --virt-type qemu \
  --arch aarch64 \
  --machine virt \
  --memory 2048 \
  --vcpus 4 \
  --noacpi \
  --os-type linux \
  --os-variant ubuntu16.04 \
  --disk path=template-ubuntu-16.04-arm64v8.qcow2,size=25,bus=virtio \
  --network default \
  --graphics none \

```

## Useful virsh commands

For post install usage

``` bash

virsh list --all # List all VMs
virsh dumpxml --domain VM_NAME # Dump the XML for the VM
virsh destroy --domain VM_NAME # Force shutdown VM
virsh undefine --domain VM_NAME # Remove/Delete VM
virsh console VM_NAME
virsh edit VM_NAME
rm DISK_IMAGE_PATH

```

## First Boot

``` bash

vim /etc/default/grub
update-grub
apt update && apt install sudo vim tmux screen wget curl htop git nano rsync iotop nload unzip
ufw allow ssh
ufw enable

```

## rclone

``` bash

curl https://rclone.org/install.sh | sudo bash

```

## Docker

``` bash

apt remove docker docker-engine docker.io
apt install apt-transport-https ca-certificates curl gnupg2 software-properties-common

echo "deb [arch=arm64] https://download.docker.com/linux/ubuntu \
     $(lsb_release -cs) stable" | \
    sudo tee /etc/apt/sources.list.d/docker.list

echo "deb [arch=armhf] https://download.docker.com/linux/ubuntu \
     $(lsb_release -cs) stable" | \
    sudo tee /etc/apt/sources.list.d/docker.list

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
apt update
apt install docker-ce python3 python3-pip
pip3 install docker-compose
poweroff

```

## Export Docker Container Images

``` bash

for repo in `docker image ls --format "{{.Repository}}"`; do
    outfile=`echo $repo | sed 's+/+_+g'`
    echo "$repo -> $outfile"
    docker save -o ${outfile}.tar $repo
done

```

