diff --git a/.gitignore b/.gitignore index 07b09ada..05b3ccd0 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,5 @@ packer_cache *.*.swp *.gz *.xz +ubuntu/OVMF_VARS.fd +ubuntu/seeds.iso diff --git a/ubuntu/Makefile b/ubuntu/Makefile new file mode 100644 index 00000000..755aaba4 --- /dev/null +++ b/ubuntu/Makefile @@ -0,0 +1,22 @@ +PACKER ?= packer + +.PHONY: all clean + +all: custom-ubuntu-efi.dd.gz + +seeds.iso: user-data meta-data + cloud-localds $@ $^ + +OVMF_VARS.fd: /usr/share/OVMF/OVMF_VARS.fd + cp -v $< $@ + +custom-ubuntu.dd.gz: clean seeds.iso + sudo PACKER_LOG=1 ${PACKER} build ubuntu.json && reset + +custom-ubuntu-efi.dd.gz: clean seeds.iso OVMF_VARS.fd + sudo PACKER_LOG=1 ${PACKER} build ubuntu-efi.json && reset + +clean: + sudo ${RM} -rf output-qemu ubuntu*.tar.gz + +.VOLATILE: OVMF_VARS.fd diff --git a/ubuntu/README.md b/ubuntu/README.md new file mode 100644 index 00000000..1cdc0211 --- /dev/null +++ b/ubuntu/README.md @@ -0,0 +1,63 @@ +# Ubuntu Packer Template for MAAS + +## Introduction +The Packer template in this directory creates a Ubuntu AMD64 image for use with MAAS. + +## Prerequisites (to create the image) + +* A machine running Ubuntu 18.04+ with the ability to run KVM virtual machines. +* qemu-utils +* ovmf +* cloud-image-utils +* [Packer.](https://www.packer.io/intro/getting-started/install.html) + +## Requirements (to deploy the image) + +* [MAAS](https://maas.io) 3.0+ +* [Curtin](https://launchpad.net/curtin) 21.0+ + +## Customizing the Image + +TODO + +## Building the image using a proxy +The Packer template downloads the Ubuntu +net installer from the Internet. To tell Packer to use a proxy set the +HTTP_PROXY environment variable to your proxy server. Alternatively you may +redefine iso_url to a local file, set iso_checksum_type to none to disable +checksuming, and remove iso_checksum_url. + +## Building an image +You can easily build the image using the Makefile: + +``` +$ make +``` + +Alternatively you can manually run packer. Your current working directory must +be in packer-maas/ubuntu, where this file is located. Once in +packer-maas/ubuntu you can generate an image with: + +``` +$ sudo PACKER_LOG=1 packer build ubuntu-efi.json +``` + +Note: ubuntu-efi.json is configured to run Packer in headless mode. Only Packer +output will be seen. If you wish to see the installation output connect to the +VNC port given in the Packer output or change the value of headless to false in +ubuntu.json. + +Installation is non-interactive. + +## Uploading an image to MAAS +``` +$ maas admin boot-resources create \ + name='custom/myubuntu' \ + title='Ubuntu Custom' \ + architecture='amd64/generic' \ + filetype='ddgz' \ + content@=custom-ubuntu-efi.dd.gz +``` + +## Default Username +The default username is ```ubuntu``` diff --git a/ubuntu/meta-data b/ubuntu/meta-data new file mode 100644 index 00000000..e69de29b diff --git a/ubuntu/scripts/cleanup.sh b/ubuntu/scripts/cleanup.sh new file mode 100644 index 00000000..b1bb3a78 --- /dev/null +++ b/ubuntu/scripts/cleanup.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +apt-get autoremove --purge -yq +apt-get clean -yq diff --git a/ubuntu/scripts/curtin-hooks b/ubuntu/scripts/curtin-hooks new file mode 100644 index 00000000..6b0b5356 --- /dev/null +++ b/ubuntu/scripts/curtin-hooks @@ -0,0 +1,13 @@ +#!/bin/sh + +# ENV variables available +# +# OUTPUT_NETWORK_CONFIG: +# This is a path to the file created during network discovery stage. +# OUTPUT_FSTAB: +# This is a path to the file created during partitioning stage. +# CONFIG: +# This is a path to the curtin config file. +# WORKING_DIR: +# This is a path to a temporary directory where curtin stores state and configuration files. + diff --git a/ubuntu/scripts/curtin.sh b/ubuntu/scripts/curtin.sh new file mode 100644 index 00000000..328e2c30 --- /dev/null +++ b/ubuntu/scripts/curtin.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +apt-get install -y jq +mkdir -p /curtin + +mv /tmp/curtin-hooks /curtin/curtin-hooks +chmod 755 /curtin/curtin-hooks diff --git a/ubuntu/scripts/networking.sh b/ubuntu/scripts/networking.sh new file mode 100644 index 00000000..265acc4a --- /dev/null +++ b/ubuntu/scripts/networking.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +apt-get install -qy netplan.io cloud-init + diff --git a/ubuntu/ubuntu-efi.json b/ubuntu/ubuntu-efi.json new file mode 100644 index 00000000..3bfe0707 --- /dev/null +++ b/ubuntu/ubuntu-efi.json @@ -0,0 +1,77 @@ +{ + "variables": { + "name": "ubuntu-20.04", + "http_directory": "http", + "http_proxy": "{{env `http_proxy`}}", + "https_proxy": "{{env `https_proxy`}}", + "no_proxy": "{{env `no_proxy`}}", + "ssh_username": "ubuntu", + "ssh_password": "ubuntu" + }, + "builders": [ + { + "boot_command": [ + "e", + "", + "autoinstall ---" + ], + "boot_wait": "2s", + "cpus": 2, + "disk_size": "4G", + "headless": true, + "http_directory": "{{user `http_directory`}}", + "iso_checksum": "file:http://releases.ubuntu.com/20.04/SHA256SUMS", + "iso_url": "https://releases.ubuntu.com/focal/ubuntu-20.04.3-live-server-amd64.iso", + "iso_target_path": "packer_cache/ubuntu.iso", + "memory": 1024, + "type": "qemu", + "format": "raw", + "qemuargs": [ + [ "-vga", "qxl"], + [ "-device", "virtio-blk-pci,drive=drive0,bootindex=0" ], + [ "-device", "virtio-blk-pci,drive=cdrom0,bootindex=1" ], + [ "-device", "virtio-blk-pci,drive=drive1,bootindex=2" ], + [ "-drive", "if=pflash,format=raw,readonly=on,file=/usr/share/OVMF/OVMF_CODE.fd"], + [ "-drive", "if=pflash,format=raw,file=OVMF_VARS.fd"], + [ "-drive", "file=output-qemu/packer-qemu,if=none,id=drive0,cache=writeback,discard=ignore,format=raw"], + [ "-drive", "file=seeds.iso,format=raw,cache=none,if=none,id=drive1"], + [ "-drive", "file=packer_cache/ubuntu.iso,if=none,id=cdrom0,media=cdrom" ] + ], + "shutdown_command": "sudo -S shutdown -P now", + "ssh_username": "{{user `ssh_username`}}", + "ssh_password": "{{user `ssh_password`}}", + "ssh_handshake_attempts": 500, + "ssh_wait_timeout": "45m", + "ssh_timeout": "45m" + } + ], + "provisioners": [ + { + "type": "file", + "source": "{{template_dir}}/scripts/curtin-hooks", + "destination": "/tmp/curtin-hooks" + }, + { + "environment_vars": [ + "HOME_DIR=/home/ubuntu", + "http_proxy={{user `http_proxy`}}", + "https_proxy={{user `https_proxy`}}", + "no_proxy={{user `no_proxy`}}" + ], + "execute_command": "echo 'ubuntu' | {{.Vars}} sudo -S -E sh -eux '{{.Path}}'", + "expect_disconnect": true, + "scripts": [ + "{{template_dir}}/scripts/curtin.sh", + "{{template_dir}}/scripts/networking.sh", + "{{template_dir}}/scripts/cleanup.sh" + ], + "type": "shell" + } + ], + "post-processors": [ + { + "type": "compress", + "output": "custom-ubuntu-efi.dd.gz" + } + ] +} \ No newline at end of file diff --git a/ubuntu/ubuntu.json b/ubuntu/ubuntu.json new file mode 100644 index 00000000..fc2881dd --- /dev/null +++ b/ubuntu/ubuntu.json @@ -0,0 +1,70 @@ +{ + "variables": { + "name": "ubuntu-20.04", + "http_directory": "http", + "http_proxy": "{{env `http_proxy`}}", + "https_proxy": "{{env `https_proxy`}}", + "no_proxy": "{{env `no_proxy`}}", + "ssh_username": "ubuntu", + "ssh_password": "ubuntu" + }, + "builders": [ + { + "boot_command": [ + "yes" + ], + "boot_wait": "60s", + "cpus": 2, + "disk_size": "4G", + "headless": true, + "http_directory": "{{user `http_directory`}}", + "iso_checksum": "file:http://releases.ubuntu.com/20.04/SHA256SUMS", + "iso_url": "https://releases.ubuntu.com/focal/ubuntu-20.04.3-live-server-amd64.iso", + "iso_target_path": "packer_cache/ubuntu.iso", + "memory": 1024, + "type": "qemu", + "format": "raw", + "qemuargs": [ + [ "-vga", "qxl"], + [ "-drive", "file=output-qemu/packer-qemu,if=virtio,cache=writeback,discard=ignore,format=raw"], + [ "-drive", "file=seeds.iso,format=raw,cache=none,if=virtio"], + [ "-cdrom", "packer_cache/ubuntu.iso" ] + ], + "shutdown_command": "sudo -S shutdown -P now", + "ssh_username": "{{user `ssh_username`}}", + "ssh_password": "{{user `ssh_password`}}", + "ssh_handshake_attempts": 500, + "ssh_wait_timeout": "45m", + "ssh_timeout": "45m" + } + ], + "provisioners": [ + { + "type": "file", + "source": "{{template_dir}}/scripts/curtin-hooks", + "destination": "/tmp/curtin-hooks" + }, + { + "environment_vars": [ + "HOME_DIR=/home/ubuntu", + "http_proxy={{user `http_proxy`}}", + "https_proxy={{user `https_proxy`}}", + "no_proxy={{user `no_proxy`}}" + ], + "execute_command": "echo 'ubuntu' | {{.Vars}} sudo -S -E sh -eux '{{.Path}}'", + "expect_disconnect": true, + "scripts": [ + "{{template_dir}}/scripts/curtin.sh", + "{{template_dir}}/scripts/networking.sh", + "{{template_dir}}/scripts/cleanup.sh" + ], + "type": "shell" + } + ], + "post-processors": [ + { + "type": "compress", + "output": "custom-ubuntu.dd.gz" + } + ] +} \ No newline at end of file diff --git a/ubuntu/user-data b/ubuntu/user-data new file mode 100644 index 00000000..1df9d5aa --- /dev/null +++ b/ubuntu/user-data @@ -0,0 +1,26 @@ +#cloud-config +autoinstall: + version: 1 + identity: + hostname: ubuntu + username: ubuntu + password: "$6$canonical.$0zWaW71A9ke9ASsaOcFTdQ2tx1gSmLxMPrsH0rF0Yb.2AEKNPV1lrF94n6YuPJmnUy2K2/JSDtxuiBDey6Lpa/" + keyboard: + layout: en + variant: us + ssh: + install-server: true + + storage: + grub: + update_nvram: true + swap: + size: 0 + layout: + name: direct + + late-commands: + - echo 'ubuntu ALL=(ALL) NOPASSWD:ALL' > /target/etc/sudoers.d/ubuntu + + package_update: true + package_upgrade: true