From 1d7c13b3a4c52278641bd8d20017bef12130fab5 Mon Sep 17 00:00:00 2001 From: Christian Pointner Date: Tue, 29 Jun 2021 17:40:42 +0200 Subject: add autoinstall role for ubuntu/installer --- .../installer/ubuntu/autoinstall/defaults/main.yml | 36 +++++ .../ubuntu/autoinstall/files/early-command.py | 25 +++ roles/installer/ubuntu/autoinstall/tasks/main.yml | 20 +++ .../autoinstall/templates/autoinstall.yml.j2 | 172 +++++++++++++++++++++ 4 files changed, 253 insertions(+) create mode 100644 roles/installer/ubuntu/autoinstall/defaults/main.yml create mode 100644 roles/installer/ubuntu/autoinstall/files/early-command.py create mode 100644 roles/installer/ubuntu/autoinstall/tasks/main.yml create mode 100644 roles/installer/ubuntu/autoinstall/templates/autoinstall.yml.j2 (limited to 'roles/installer/ubuntu') diff --git a/roles/installer/ubuntu/autoinstall/defaults/main.yml b/roles/installer/ubuntu/autoinstall/defaults/main.yml new file mode 100644 index 00000000..1a4fd3ed --- /dev/null +++ b/roles/installer/ubuntu/autoinstall/defaults/main.yml @@ -0,0 +1,36 @@ +--- +# ubuntu_autoinstall_tmpdir: + +ubuntu_autoinstall_locale: en_US + +ubuntu_autoinstall_keyboard_layout: de +ubuntu_autoinstall_keyboard_variant: nodeadkeys + +ubuntu_autoinstall_timezone: Europe/Vienna + +# ubuntu_autoinstall_kernel_image: +ubuntu_autoinstall_virtual_machine: no + +ubuntu_autoinstall_efi_esp_size: 128M + +ubuntu_autoinstall_system_lvm_size_default: all +ubuntu_autoinstall_system_lvm_volumes_default: + - name: root + size: 2.5G + filesystem: ext4 + mountpoint: / + - name: var + size: 1280M + filesystem: ext4 + mountpoint: /var + - name: var+log + size: 768M + filesystem: ext4 + mountpoint: /var/log + mount_options: + - nodev + - noatime + - noexec + + +ubuntu_autoinstall_install_tasks: [] diff --git a/roles/installer/ubuntu/autoinstall/files/early-command.py b/roles/installer/ubuntu/autoinstall/files/early-command.py new file mode 100644 index 00000000..93d72b2d --- /dev/null +++ b/roles/installer/ubuntu/autoinstall/files/early-command.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 + +import os +from shutil import copyfile +import yaml + +os.umask(0o077) +copyfile('/autoinstall.yaml', '/autoinstall.yaml_before-early-command') + +config = {} +with open('/autoinstall.yaml', 'r') as file: + config = yaml.safe_load(file) + +try: + for c in config['storage']['config']: + if 'type' not in c or c['type'] != 'disk' or 'path' not in c: + continue + + c['path'] = os.path.realpath(c['path']) + + with open('/autoinstall.yaml', 'w') as file: + yaml.dump(config, file, default_flow_style=False) + +except KeyError: + pass diff --git a/roles/installer/ubuntu/autoinstall/tasks/main.yml b/roles/installer/ubuntu/autoinstall/tasks/main.yml new file mode 100644 index 00000000..4a3034d0 --- /dev/null +++ b/roles/installer/ubuntu/autoinstall/tasks/main.yml @@ -0,0 +1,20 @@ +--- +- name: create autoinstall sub-directory + file: + path: "{{ ubuntu_autoinstall_tmpdir }}/autoinstall" + state: directory + +- name: create empty meta-data file + copy: + content: "" + dest: "{{ ubuntu_autoinstall_tmpdir }}/autoinstall/meta-data" + +- name: copy early-command script + copy: + src: early-command.py + dest: "{{ ubuntu_autoinstall_tmpdir }}/autoinstall/early-command.py" + +- name: generate autoinstall.yml as user-data + template: + src: autoinstall.yml.j2 + dest: "{{ ubuntu_autoinstall_tmpdir }}/autoinstall/user-data" diff --git a/roles/installer/ubuntu/autoinstall/templates/autoinstall.yml.j2 b/roles/installer/ubuntu/autoinstall/templates/autoinstall.yml.j2 new file mode 100644 index 00000000..97b54b0a --- /dev/null +++ b/roles/installer/ubuntu/autoinstall/templates/autoinstall.yml.j2 @@ -0,0 +1,172 @@ +#cloud-config +autoinstall: + version: 1 + early-commands: + - python3 /cdrom/autoinstall/early-command.py + + locale: "{{ ubuntu_autoinstall_locale }}" + keyboard: + layout: "{{ ubuntu_autoinstall_keyboard_layout }}" + variant: "{{ ubuntu_autoinstall_keyboard_variant }}" + toggle: null + + network: + version: 2 + ethernets: + {{ install_interface | default(network_cooked.primary.name) }}: +{% if install_dhcp | default(false) %} + dhcp4: yes +{% else %} + addresses: + - {{ network_cooked.primary.address }} + gateway4: {{ network_cooked.primary.gateway }} +{% if (network_cooked.nameservers | default([]) | length) > 0 %} + nameservers: + search: [ {{ host_domain }} ] + addresses: [ {{ network_cooked.nameservers | join(', ') }} ] +{% endif %} +{% endif %} + + storage: + config: + - id: disk-primary + type: disk + path: {{ install_cooked.disks.primary }} +{% if install_cooked.efi | default(false) %} + ptable: gpt +{% else %} + ptable: msdos + grub_device: true +{% endif %} + wipe: superblock-recursive + +{% if install_cooked.efi | default(false) %} +{% set part_offset = 1 %} + - id: partition-esp + type: partition + device: disk-primary + flag: boot + number: 1 + size: {{ ubuntu_autoinstall_efi_esp_size | human_to_bytes }} + grub_device: true + - id: format-esp + type: format + volume: partition-esp + label: efi + fstype: fat32 + - id: mount-esp + type: mount + device: format-esp + path: /boot/efi + +{% else %} +{% set part_offset = 0 %} + +{% endif %} +{% set system_lvm_size = install_cooked.system_lvm.size | default(ubuntu_autoinstall_system_lvm_size_default) %} +{% set system_lvm_volumes = install_cooked.system_lvm.volumes | default(ubuntu_autoinstall_system_lvm_volumes_default) %} + - id: partition-lvm + type: partition + device: disk-primary + flag: linux + number: {{ part_offset + 1 }} +{% if system_lvm_size != 'all' %} + size: {{ system_lvm_size | human_to_bytes }} + - id: partition-unused + type: partition + device: disk-primary + flag: linux + number: {{ part_offset + 2 }} +{% endif %} + size: -1 + + - id: lvm-vg-system + type: lvm_volgroup + devices: + - partition-lvm + name: {{ host_name }} + +{% for volume in system_lvm_volumes %} + - id: lvm-lv-{{ volume.name }} + type: lvm_partition + volgroup: lvm-vg-system + name: {{ volume.name }} + size: {{ volume.size | human_to_bytes }} + - id: format-{{ volume.name }} + type: format + fstype: {{ volume.filesystem }} + volume: lvm-lv-{{ volume.name }} + - id: mount-{{ volume.name }} + type: mount + device: format-{{ volume.name }} + path: {{ volume.mountpoint }} +{% if 'mount_options' in volume and (volume.mount_options | length) > 0 %} + options: '{{ volume.mount_options | join(",") }}' +{% endif %} + +{% endfor %} + apt: + primary: + - uri: http://{{ apt_repo_providers[apt_repo_provider].ubuntu.host }}{{ apt_repo_providers[apt_repo_provider].ubuntu.path }} + arches: + - amd64 + + user-data: + hostname: "{{ host_name }}" + timezone: "{{ ubuntu_autoinstall_timezone }}" + disable_root: false + users: + - name: root + ssh_authorized_keys: +{% for key in ssh_keys_root %} + - {{ key }} +{% endfor %} + runcmd: + - [ apt-get, -y, -q, purge, snapd, cloud-init, cloud-guest-utils, cloud-initramfs-copymods, cloud-initramfs-dyn-netconf, python3-cryptography, gpg, sosreport, update-notifier-common, ssh-import-id ] + - [ rm, -rf, /etc/cloud, /var/lib/cloud ] + - [ apt-get, -y, -q, auto-remove ] + - [ bash, -c, 'dpkg -l | grep "^rc" | awk "{ print(\$2) }" | xargs dpkg -P' ] +{% if ubuntu_autoinstall_virtual_machine %} + - [ poweroff ] +{% endif %} + + ssh: + install-server: true + + packages: + - python3 + - python3-apt +{% for task in ubuntu_autoinstall_install_tasks %} + - {{ task }}^ +{% endfor %} + + late-commands: + - curtin in-target --target=/target -- swapoff -a; sed -e '/^\/swapfile/d' -i /etc/fstab; rm -f /swapfile +{% if ansible_port is defined %} + - curtin in-target --target=/target -- sed -e 's/^\(\s*#*\s*Port.*\)/Port {{ ansible_port }}/' -i /etc/ssh/sshd_config +{% endif %} + - curtin in-target --target=/target -- apt-mark manual iputils-ping isc-dhcp-client netcat-openbsd netplan.io sudo + - curtin in-target --target=/target -- apt-get -y -q purge policykit-1 multipath-tools ubuntu-minimal unattended-upgrades sound-theme-freedesktop thin-provisioning-tools cryptsetup mdadm byobu open-iscsi btrfs-progs pollinate lxd-agent-loader +{% if not ubuntu_autoinstall_virtual_machine %} + - curtin in-target --target=/target -- apt-get -y -q purge open-vm-tools +{% endif %} + - curtin in-target --target=/target -- env SUDO_FORCE_REMOVE=yes apt-get -y -q purge sudo + - curtin in-target --target=/target -- apt-get -y -q autoremove + - curtin in-target --target=/target -- bash -c 'dpkg -l | grep "^rc" | awk "{ print(\$2) }" | xargs dpkg -P' +{# purging the snapd package here would trigger a bug in den postrm script because some filesystems in /run/ can not be unmounted... #} +{# to workadound this issue we only remove the package here and rely on cloud-init to fully purge it on first boot (see user-data: above) #} + - curtin in-target --target=/target -- apt-get -y -q remove snapd + - curtin in-target --target=/target -- bash -c 'apt-get update -q && apt-get full-upgrade -y -q' +{% if ubuntu_autoinstall_kernel_image is defined or ubuntu_autoinstall_virtual_machine %} + +write_files: + - path: /run/kernel-meta-package + content: | +{% if ubuntu_autoinstall_kernel_image is defined %} + {{ ubuntu_autoinstall_kernel_image }} +{% else %} + linux-virtual +{% endif %} + owner: root:root + permissions: "0644" +{% endif %} -- cgit v1.2.3