Merge "image-builder refactor"

This commit is contained in:
Zuul 2021-02-17 20:20:51 +00:00 committed by Gerrit Code Review
commit d2039c609c
36 changed files with 464 additions and 412 deletions

View File

@ -43,7 +43,8 @@
- job:
name: airship-images-build
nodeset: airship-images-single-node
timeout: 3600
timeout: 7200
post-timeout: 7200
pre-run: playbooks/airship-images-deploy-docker.yaml
run: playbooks/airship-images-build.yaml
post-run: playbooks/airship-collect-logs.yaml
@ -74,7 +75,7 @@
name: airship-images-single-node
nodes:
- name: primary
label: ubuntu-bionic
label: ubuntu-bionic-32GB
- secret:
name: images_airshipit_github_secret

View File

@ -10,92 +10,21 @@ LABEL org.opencontainers.image.authors='airship-discuss@lists.airshipit.org, irc
SHELL ["bash", "-exc"]
ENV DEBIAN_FRONTEND noninteractive
# Update distro and install ansible
RUN apt-get update ;\
apt-get dist-upgrade -y ;\
apt-get install -y --no-install-recommends \
python3-minimal \
python3-pip \
python3-apt \
python3-setuptools ;\
pip3 install --upgrade wheel ;\
pip3 install --upgrade ansible ;\
rm -rf /var/lib/apt/lists/*
FROM base-image as rootfs-builder
# install requirements for building chroot
RUN apt-get update ;\
apt-get install -y --no-install-recommends \
ca-certificates \
multistrap \
equivs \
curl \
ca-certificates \
build-essential \
gnupg2 \
dosfstools;\
rm -rf /var/lib/apt/lists/*
COPY assets/playbooks/inventory.yaml /opt/assets/playbooks/inventory.yaml
COPY assets/playbooks/base-chroot.yaml /opt/assets/playbooks/base-chroot.yaml
COPY assets/playbooks/roles/multistrap /opt/assets/playbooks/roles/multistrap
RUN ansible-playbook -i /opt/assets/playbooks/inventory.yaml /opt/assets/playbooks/base-chroot.yaml
COPY assets/playbooks/base-osconfig.yaml /opt/assets/playbooks/base-osconfig.yaml
COPY assets/playbooks/roles/osconfig /opt/assets/playbooks/roles/osconfig
RUN ansible-playbook -i /opt/assets/playbooks/inventory.yaml /opt/assets/playbooks/base-osconfig.yaml --tags "pre_install"
FROM base-image as squashfs-builder
ENV root_chroot /mnt/rootfs
ENV root_image /mnt/image
ENV boot_src="/opt/grub"
RUN apt-get update ;\
apt-get install -y --no-install-recommends \
dosfstools \
mtools \
squashfs-tools \
grub-common \
grub2-common \
grub-pc-bin \
grub-efi-amd64-signed;\
rm -rf /var/lib/apt/lists/*
COPY --from=rootfs-builder ${root_chroot} ${root_chroot}
COPY assets/playbooks/inventory.yaml /opt/assets/playbooks/inventory.yaml
COPY assets/playbooks/base-livecdcontent.yaml /opt/assets/playbooks/base-livecdcontent.yaml
COPY assets/playbooks/roles/livecdcontent /opt/assets/playbooks/roles/livecdcontent
RUN ansible-playbook -i /opt/assets/playbooks/inventory.yaml /opt/assets/playbooks/base-livecdcontent.yaml
FROM base-image as image-builder
ENV boot_src="/opt/grub"
ENV root_image /mnt/image
RUN apt-get update ;\
apt-get install -y --no-install-recommends \
xorriso \
grub-pc-bin \
python3-minimal \
python3-yaml ;\
rm -rf /var/lib/apt/lists/*
COPY --from=squashfs-builder ${root_image} ${root_image}
COPY assets/playbooks/inventory.yaml /opt/assets/playbooks/inventory.yaml
COPY assets/playbooks/iso.yaml /opt/assets/playbooks/iso.yaml
COPY assets/playbooks/roles/iso /opt/assets/playbooks/roles/iso
RUN apt-get update ;\
apt-get install -y --no-install-recommends \
python3-yaml \
python3-pip \
python3-setuptools \
python3-apt \
grub-pc-bin \
coreutils \
curl \
qemu-utils \
@ -107,19 +36,30 @@ RUN apt-get update ;\
vim \
kmod \
efivar \
rsync \
dosfstools ;\
pip3 install --upgrade pip ;\
pip3 install --upgrade wheel ;\
pip3 install --upgrade ansible ;\
rm -rf /var/lib/apt/lists/*
COPY assets/playbooks/base-osconfig.yaml /opt/assets/playbooks/base-osconfig.yaml
COPY assets/playbooks/roles/osconfig /opt/assets/playbooks/roles/osconfig
COPY assets/playbooks/qcow.yaml /opt/assets/playbooks/qcow.yaml
COPY assets/playbooks/roles/qcow /opt/assets/playbooks/roles/qcow
RUN curl -L https://github.com/mikefarah/yq/releases/download/2.4.0/yq_linux_amd64 -o /bin/yq \
&& chmod +x /bin/yq
COPY assets/playbooks/inventory.yaml /opt/assets/playbooks/inventory.yaml
COPY assets/playbooks/base-chroot.yaml /opt/assets/playbooks/base-chroot.yaml
COPY assets/playbooks/roles/multistrap /opt/assets/playbooks/roles/multistrap
COPY assets/playbooks/base-osconfig.yaml /opt/assets/playbooks/base-osconfig.yaml
COPY assets/playbooks/roles/osconfig /opt/assets/playbooks/roles/osconfig
COPY assets/playbooks/base-livecdcontent.yaml /opt/assets/playbooks/base-livecdcontent.yaml
COPY assets/playbooks/roles/livecdcontent /opt/assets/playbooks/roles/livecdcontent
COPY assets/playbooks/iso.yaml /opt/assets/playbooks/iso.yaml
COPY assets/playbooks/roles/iso /opt/assets/playbooks/roles/iso
COPY assets/playbooks/qcow.yaml /opt/assets/playbooks/qcow.yaml
COPY assets/playbooks/roles/qcow /opt/assets/playbooks/roles/qcow
COPY assets/playbooks/build /build
COPY assets/*.sh /usr/bin/local/
COPY assets/*.json /usr/bin/local/
CMD /usr/bin/local/entrypoint.sh

View File

@ -24,11 +24,10 @@ PUSH_IMAGE ?= false
DISTRO ?= ubuntu_focal
IMAGE ?= ${DOCKER_REGISTRY}/${IMAGE_PREFIX}/${IMAGE_NAME}:${IMAGE_TAG}-${DISTRO}
IMAGE_ALIAS ?= $(DOCKER_REGISTRY)-$(IMAGE_NAME)-$(IMAGE_TAG)-${DISTRO}-${IMAGE_TYPE}
UEFI_BOOT ?= true
PROXY ?=
NO_PROXY ?= localhost,127.0.0.1
.PHONY: help build images install_prereqs cut_image run
.PHONY: help build images cut_image run clean
.ONESHELL:
@ -38,17 +37,6 @@ help: ## This help.
# Make target name that zuul expects for each project in this repo
images: build
install_prereqs:
ifneq ($(PROXY), )
export http_proxy=$(PROXY)
export https_proxy=$(PROXY)
export no_proxy=$(NO_PROXY)
export HTTP_PROXY=$(PROXY)
export HTTPS_PROXY=$(PROXY)
export NO_PROXY=$(NO_PROXY)
endif
sudo -E tools/install_prereqs.$(DISTRO)
build:
ifneq ($(PROXY), )
sudo -E ./tools/docker_proxy.sh $(PROXY) $(NO_PROXY)
@ -58,7 +46,8 @@ ifneq ($(PROXY), )
export HTTP_PROXY=$(PROXY)
export HTTPS_PROXY=$(PROXY)
export NO_PROXY=$(NO_PROXY)
sudo -E docker build --tag $(IMAGE) -f Dockerfile.$(DISTRO) . \
sudo -E ./tools/multistrap.sh
sudo -E docker -D -l debug build --tag $(IMAGE) -f Dockerfile.$(DISTRO) . \
--label $(LABEL) \
--label "org.opencontainers.image.revision=$(COMMIT)" \
--label "org.opencontainers.image.created=\
@ -69,22 +58,21 @@ ifneq ($(PROXY), )
--build-arg HTTP_PROXY=$(PROXY) \
--build-arg HTTPS_PROXY=$(PROXY) \
--build-arg no_proxy=$(NO_PROXY) \
--build-arg NO_PROXY=$(NO_PROXY) \
--build-arg UEFI_BOOT=$(UEFI_BOOT) || exit 1
--build-arg NO_PROXY=$(NO_PROXY) || exit 1
else
sudo -E docker build --tag $(IMAGE) -f Dockerfile.$(DISTRO) . \
sudo -E ./tools/multistrap.sh
sudo -E docker -D -l debug build --tag $(IMAGE) -f Dockerfile.$(DISTRO) . \
--label $(LABEL) \
--label "org.opencontainers.image.revision=$(COMMIT)" \
--label "org.opencontainers.image.created=\
$(shell date --rfc-3339=seconds --utc)" \
--label "org.opencontainers.image.title=$(IMAGE_NAME)" \
--build-arg UEFI_BOOT=$(UEFI_BOOT) || exit 1
--label "org.opencontainers.image.title=$(IMAGE_NAME)" || exit 1
endif
ifeq ($(PUSH_IMAGE), true)
sudo -E docker push $(IMAGE)
endif
cut_image: install_prereqs
cut_image:
ifneq ($(PROXY), )
sudo -E ./tools/docker_proxy.sh $(PROXY) $(NO_PROXY)
export http_proxy=$(PROXY)
@ -94,7 +82,7 @@ ifneq ($(PROXY), )
export HTTPS_PROXY=$(PROXY)
export NO_PROXY=$(NO_PROXY)
endif
sudo -E tools/cut_image.sh $(IMAGE_TYPE) ./examples $(IMAGE) $(IMAGE_ALIAS) "$(UEFI_BOOT)" "$(PROXY)" "$(NO_PROXY)"
sudo -E tools/cut_image.sh $(IMAGE_TYPE) ./examples $(IMAGE) $(IMAGE_ALIAS) "$(PROXY)" "$(NO_PROXY)"
run: ## Run the iso in kvm for testing
virsh start $(IMAGE_ALIAS)
@ -102,3 +90,5 @@ run: ## Run the iso in kvm for testing
tests:
true
clean:
sudo -E tools/multistrap.sh clean

View File

@ -13,12 +13,6 @@ cd "$BASEDIR"
BASEDIR="$(dirname "$(realpath "$0")")"
source "${BASEDIR}/functions.sh"
: "${uefi_boot:=}"
if [[ -n $uefi_boot ]]; then
extra_vars="uefi=$uefi_boot"
fi
export http_proxy
export https_proxy
export HTTP_PROXY
@ -26,6 +20,10 @@ export HTTPS_PROXY
export no_proxy
export NO_PROXY
if [ ! -e build ]; then
ln -s /chroot build
fi
# Instruct ansible to output the image artifact to the container's host mount
extra_vars="$extra_vars img_output_dir=${VOLUME}"
@ -37,7 +35,7 @@ if [[ "${IMAGE_TYPE}" == "iso" ]]; then
extra_vars="$extra_vars img_name=${IMG_NAME}"
echo "Executing Step 1"
ansible-playbook -i /opt/assets/playbooks/inventory.yaml /opt/assets/playbooks/iso.yaml --extra-vars "$extra_vars" -vvvv
ansible-playbook -i /opt/assets/playbooks/inventory.yaml /opt/assets/playbooks/iso.yaml --extra-vars "$extra_vars" -vv
elif [[ "${IMAGE_TYPE}" == "qcow" ]]; then
_process_input_data_set_vars_qcow
_process_input_data_set_vars_osconfig
@ -46,13 +44,14 @@ elif [[ "${IMAGE_TYPE}" == "qcow" ]]; then
extra_vars="$extra_vars img_name=${IMG_NAME}"
echo "Executing Step 1: Create qcow2 partitions and filesystems"
ansible-playbook -i /opt/assets/playbooks/inventory.yaml /opt/assets/playbooks/qcow.yaml --extra-vars "$extra_vars" --tags "prep_img" -vvvv
ansible-playbook -i /opt/assets/playbooks/inventory.yaml /opt/assets/playbooks/qcow.yaml --extra-vars "$extra_vars" --tags "prep_img" -vv
echo "Executing Step 2: Applying changes from base-osconfig playbook"
ansible-playbook -i /opt/assets/playbooks/inventory.yaml /opt/assets/playbooks/base-osconfig.yaml --extra-vars "$extra_vars" -vvvv
ansible-playbook -i /opt/assets/playbooks/inventory.yaml /opt/assets/playbooks/base-osconfig.yaml --extra-vars "$extra_vars" --tags "runtime_and_buildtime" -vv
ansible-playbook -i /opt/assets/playbooks/inventory.yaml /opt/assets/playbooks/base-osconfig.yaml --extra-vars "$extra_vars" --tags "runtime_only" -vv
echo "Executing Step 3: Close image and write qcow2"
ansible-playbook -i /opt/assets/playbooks/inventory.yaml /opt/assets/playbooks/qcow.yaml --extra-vars "$extra_vars" --tags "close_img" -vvvv
ansible-playbook -i /opt/assets/playbooks/inventory.yaml /opt/assets/playbooks/qcow.yaml --extra-vars "$extra_vars" --tags "close_img" -vv
else
echo "\${IMAGE_TYPE} value '${IMAGE_TYPE}' does not match an expected value: [ 'iso', 'qcow' ]"
exit 1

View File

@ -1,5 +1,5 @@
---
- hosts: /mnt/rootfs
- hosts: build
gather_facts: false
roles:
- osconfig

View File

@ -5,6 +5,6 @@ all:
ansible_python_interpreter: /usr/bin/python3
chroots:
hosts:
/mnt/rootfs:
build:
ansible_connection: chroot
ansible_python_interpreter: /usr/bin/python3

View File

@ -1,6 +1,6 @@
img_output_dir: /config
img_name: ephemeral.iso
root_image: /mnt/image
root_image: /build
meta_data_file: /config/meta_data.json
user_data_file: /config/user_data

View File

@ -1,3 +1,28 @@
- name: "ISO | Reduce image size"
file:
state: absent
path: "{{ root_image }}/lib"
- name: "ISO | Reduce image size"
file:
state: absent
path: "{{ root_image }}/usr"
- name: "ISO | Reduce image size"
file:
state: absent
path: "{{ root_image }}/bin"
- name: "ISO | Reduce image size"
file:
state: absent
path: "{{ root_image }}/sbin"
- name: "ISO | Reduce image size"
file:
state: absent
path: "{{ root_image }}/var"
- name: "ISO | Reduce image size"
file:
state: absent
path: "{{ root_image }}/opt"
- name: "ISO | Ensure any old iso image at target location is removed"
file:
state: absent

View File

@ -1,3 +1,2 @@
root_chroot: /mnt/rootfs
root_image: /mnt/image
boot_src: /opt/grub
root_chroot: build
root_image: build

View File

@ -1,29 +1,7 @@
- name: ansible copy file locally - vmlinuz.
copy:
src: "{{ item }}"
dest: "{{ root_image }}/vmlinuz"
remote_src: yes
with_fileglob: "{{ root_chroot }}/boot/vmlinuz-*"
- name: ansible copy file locally - initrd.
copy:
src: "{{ item }}"
dest: "{{ root_image }}/initrd"
remote_src: yes
with_fileglob: "{{ root_chroot }}/boot/initrd.img-*"
- name: ansible copy file locally - config.
copy:
src: "{{ item }}"
dest: "{{ root_image }}/config"
remote_src: yes
with_fileglob: "{{ root_chroot }}/boot/config-*"
- name: "Stamp out a marker file for grub to use when identifying the desired boot volume"
copy:
#TODO: populate this with meaningful content
content: "{{ ansible_date_time.date }}"
dest: "{{ root_image }}/AIRSHIP_EPHEMERAL"
dest: "{{ root_image }}/AIRSHIP"
- name: "create directory for boot image assembly"
tempfile:
@ -77,4 +55,4 @@
shell:
cmd: |
cat /usr/lib/grub/i386-pc/cdboot.img {{ bootimg_builddir.path }}/core.img > {{ root_image }}/boot/grub/bios.img
cp {{ bootimg_builddir.path }}/efiboot.img {{ root_image }}/boot/grub/
cp {{ bootimg_builddir.path }}/efiboot.img {{ root_image }}/boot/grub/efiboot.img

View File

@ -4,6 +4,11 @@
state: directory
mode: '0755'
- name: "ensure no previous squashfs file"
file:
path: "{{ root_image }}/live/filesystem.squashfs"
state: absent
- name: "Building squashfs"
shell:
cmd: |

View File

@ -1,4 +1,4 @@
search --set=root --file /AIRSHIP_EPHEMERAL
search --set=root --file /AIRSHIP
insmod all_video
@ -6,6 +6,6 @@ set default="0"
set timeout=1
menuentry "Airship Ephemeral" {
linux /vmlinuz boot=live quiet nomodeset overlay-size=70% systemd.unified_cgroup_hierarchy=0 ds=ConfigDrive
initrd /initrd
linux /boot/vmlinuz boot=live quiet nomodeset overlay-size=70% systemd.unified_cgroup_hierarchy=0 ds=ConfigDrive
initrd /boot/initrd.img
}

View File

@ -1,7 +1,10 @@
rootfs_root: /mnt/rootfs
rootfs_root: build
rootfs_arch: amd64
k8s_version: 1.18.6-00
kernel_base_pkg: linux-image-generic
kernel_headers_pkg: linux-headers-generic
ubuntu_packages:
- apparmor
- apt-file
- apt-utils
- apt-transport-https
@ -13,15 +16,19 @@ ubuntu_packages:
- cloud-init
- conntrack
- curl
- dbus
- dnsutils
- dosfstools
- e2fsprogs
- ebtables
- efivar
- ethtool
- file
- gawk
- gettext-base
- gnupg2
#- grub2 # cannot install until after boot partition is available
- grub2
- grub-efi-amd64-signed
- ifenslave
- isc-dhcp-client
- iproute2
@ -30,14 +37,19 @@ ubuntu_packages:
- iputils-ping
- iputils-tracepath
- ipvsadm
- kdump-tools
- "{{ kernel_base_pkg }}"
- "{{ kernel_headers_pkg }}"
- kmod
- less
- linux-image-generic # this will be reinstalled later when the boot partition is available
- live-boot
- locales
- locales-all
- logrotate
- lsb-release
- lsof
- man-db
- mawk
- mbr
- netplan.io
- net-tools
@ -46,6 +58,7 @@ ubuntu_packages:
- passwd
- python3
- python3-apt
- rsyslog
- socat
- systemd
- systemd-sysv

View File

@ -35,30 +35,36 @@
include_tasks: apt-key-install.yaml
loop: "{{ repos }}"
- name: "ensuring directory {{ rootfs_root }}/dev exists for chroot"
file:
path: "{{ rootfs_root }}/dev"
state: directory
mode: '0755'
- name: "Setting up devices for chroot"
# kdump-tools does not install properly in multistrap environment. This fix allows kdump-tools
# installation to succeed.
- name: "kdump-tools fix - create directory"
shell: |
mknod "{{ rootfs_root }}/dev/random" c 1 8
chmod 640 "{{ rootfs_root }}/dev/random"
chown 0:0 "{{ rootfs_root }}/dev/random"
mknod "{{ rootfs_root }}/dev/urandom" c 1 9
chmod 640 "{{ rootfs_root }}/dev/urandom"
chown 0:0 "{{ rootfs_root }}/dev/urandom"
mknod "{{ rootfs_root }}/dev/null" c 1 3
chmod 666 "{{ rootfs_root }}/dev/null"
chown 0:0 "{{ rootfs_root }}/dev/null"
set -e
mkdir -p "{{ rootfs_root }}/etc/kernel/postinst.d"
- name: "kdump-tools fix - deploy build script"
template:
src: kdump-tools.j2
dest: "{{ rootfs_root }}/etc/kernel/postinst.d/kdump-tools"
mode: '0755'
# kdump-tools deb package will overwrite script without write protection enabled
- name: "kdump-tools fix - lock build script"
shell: |
set -e
chattr +i "{{ rootfs_root }}/etc/kernel/postinst.d/kdump-tools"
- name: "Running multistrap"
shell:
cmd: "multistrap -f {{ multistrap_tempdir.path }}/multistrap.conf"
#- name: "create grub.cfg"
# shell:
# cmd: |
# chroot {{ rootfs_root }} update-grub
- name: "Lock sources.list to prevent conflict and duplicates with multistrap repo list"
shell: |
set -e
if [ -f {{ rootfs_root }}/etc/apt/sources.list ]; then rm {{ rootfs_root }}/etc/apt/sources.list; fi
ln -s /dev/null {{ rootfs_root }}/etc/apt/sources.list
if [ -f {{ rootfs_root }}/etc/apt/sources.list ] && [ ! -h {{ rootfs_root }}/etc/apt/sources.list ]; then
rm {{ rootfs_root }}/etc/apt/sources.list
ln -s /dev/null {{ rootfs_root }}/etc/apt/sources.list
fi

View File

@ -0,0 +1,75 @@
#!/bin/sh -e
version="$1"
kdumpdir="/var/lib/kdump"
[ -x /usr/sbin/mkinitramfs ] || exit 0
# passing the kernel version is required
if [ -z "${version}" ]; then
echo >&2 "W: kdump-tools: ${DPKG_MAINTSCRIPT_PACKAGE:-kdump-tools package} did not pass a version number"
exit 2
fi
if ! linux-version list | grep "${version}" > /dev/null ; then
exit 0
fi
# exit if kernel does not need an initramfs
if [ "$INITRD" = 'No' ]; then
exit 0
fi
# avoid running multiple times
if [ -n "$DEB_MAINT_PARAMS" ]; then
eval set -- "$DEB_MAINT_PARAMS"
if [ -z "$1" ] || [ "$1" != "configure" ]; then
exit 0
fi
fi
# We need a modified copy of initramfs-tools directory
# with MODULES=dep in initramfs.conf
if [ ! -d "$kdumpdir" ];then
mkdir "$kdumpdir" || true
fi
# Force re-creation of $kdumpdir/initramfs-tools
# in case the source has changed since last time
# we ran
if [ -d "$kdumpdir/initramfs-tools" ];then
rm -Rf $kdumpdir/initramfs-tools || true
fi
cp -pr /etc/initramfs-tools "$kdumpdir" || true
initramfsdir="$kdumpdir/initramfs-tools"
# Add scsi_dh_* modules if in use otherwise
# kexec reboot on multipath will fail
# (LP: #1635597)
for I in $(lsmod | grep scsi_dh | cut -d" " -f1);do
echo "${I}" >> $initramfsdir/modules
done
# canderson: This line needs to be commented out for kdump-tools to install with multistrap
#sed -e 's/MODULES=.*/MODULES=dep/' /etc/initramfs-tools/initramfs.conf > "$initramfsdir/initramfs.conf" || true
if ! [ -e "$initramfsdir/initramfs.conf" ];then
echo >&2 "W: kdump-tools: Unable to create $initramfsdir/initramfs.conf"
exit 2
fi
# Cleaning up existing initramfs with same version
# as mkinitramfs do not have a force option
if [ -e "$kdumpdir/initrd.img-${version}" ];then
rm -f "$kdumpdir/initrd.img-${version}" || true
fi
# we're good - create initramfs.
echo "kdump-tools: Generating $kdumpdir/initrd.img-${version}"
if mkinitramfs -d "$initramfsdir" -o "$kdumpdir/initrd.img-${version}.new" "${version}";then
mv "$kdumpdir/initrd.img-${version}.new" "$kdumpdir/initrd.img-${version}"
else
mkinitramfs_return="$?"
rm -f "${initramfs}.new"
echo "update-initramfs: failed for ${initramfs} with $mkinitramfs_return." >&2
exit $mkinitramfs_return
fi

View File

@ -1,11 +1,6 @@
rootfs_root: /mnt/rootfs
cni_version: v0.8.2
k8s_version: v1.18.6
rootfs_root: build
kernel:
base_pkg: linux-image-generic
headers_pkg: linux-headers-generic
modules:
load:
- name: 8021q
@ -136,26 +131,19 @@ systemd:
# Use only if you are intenting to overwrite an existing systemd unit
force: no
# Note: You are encouraged to build your own image-builder container, where your desired
# package list can be supplied to multistrap during the container build. However, this
# option will allow you to layer additional packages (installed during container runtime,
# instead of during the container build) where a customized container build is not possible
# or not desired.
# This is also needed for a specific subset of packages that fail to install successfully
# with multistrap (e.g., kdump-tools).
post_install_package_list:
- kdump-tools
- apparmor
- dbus
- rsyslog
- logrotate
# If any other custom shell scripts are needed for bare-metal provisioning, they can be
# added here.
post_install_scripts:
# If any custom shell scripts are needed for qcow building for image building,
# they can be added here.
buildtime_user_scripts:
- file_content: |
#!/bin/bash
echo "custom post-install script"
echo "custom container buildtime script"
# Custom user shell scripts to be run during container execution, right before
# final QCOW image is created.
runtime_user_scripts:
- file_content: |
#!/bin/bash
echo "custom container buildtime script"
# Any other adjustments to file or directory permissions, for files that already exist.
file_permissions:

View File

@ -0,0 +1,3 @@
- name: "user-scripts | running user-defined scripts"
shell: "{{ item.file_content }}"
with_items: "{{ buildtime_user_scripts }}"

View File

@ -34,8 +34,14 @@
include_tasks: file-permissions.yaml
- name: "finalise rootfs"
include_tasks: finalise-rootfs.yaml
tags: pre_install
tags: runtime_and_buildtime
- block:
- name: "POST-INSTALL | Starting post-install"
include_tasks: post-install.yaml
tags: post_install
- name: "run user-defined scripts"
include_tasks: buildtime-user-scripts.yaml
tags: buildtime_only
- block:
- name: "run system-defined scripts"
include_tasks: runtime-system-scripts.yaml
- name: "run user-defined scripts"
include_tasks: runtime-user-scripts.yaml
tags: runtime_only

View File

@ -1,108 +0,0 @@
- name: "POST-INSTALL | Append any user-defined post-install pkgs to install list"
set_fact:
post_install_package_list: "{{ post_install_package_list + post_install_package_list_append }}"
when: post_install_package_list_append is defined
- name: "POST-INSTALL | DNS sanity check"
shell:
executable: /bin/bash
cmd: |
set -e
proxy="{{ lookup('env', 'HTTP_PROXY') }}"
# Ensure proxy address is resolvable, if supplied as a domain name
if [[ -n $proxy ]]; then
# Extract proxy server address from url
proxy_address="$(echo "$proxy" | awk -F/ '{print $3}' | awk -F: '{print $1}')"
# If first letter of proxy address is a letter, verify that a DNS lookup is possible
if [[ $proxy_address == [a-zA-z]* ]]; then
echo "proxy check for '$proxy_address' ..."
nslookup $proxy_address > /dev/null || (
echo "Failed to resolve proxy '$proxy_address' with dns server '$(cat /etc/resolv.conf)'."
echo "Reconfigure DNS setting provided in the 'qcow' playbook to a DNS server that can resolve '$proxy_address'."
exit 1
)
fi
fi
echo "archive.ubuntu.com DNS check ..."
nslookup archive.ubuntu.com || (
echo "DNS lookup failure for archive.ubuntu.com with '$(cat /etc/resolv.conf)'"
exit 1
)
- name: "POST-INSTALL | update source list"
apt:
update_cache: yes
- name: "POST-INSTALL | generate locales"
shell: |
set -e
locale-gen en_US.UTF-8
- name: "POST-INSTALL | Remove incomplete kernel install by multistrap"
shell: |
set -e
apt-get remove -y '^linux-image-.*'
apt-get remove -y '^linux-modules-.*'
- name: "POST-INSTALL | install grub2 and kernel"
apt:
pkg:
- grub2
- grub-efi-amd64-signed
- efivar
- "{{ kernel.base_pkg }}"
- "{{ kernel.headers_pkg }}"
- kmod
- name: "POST-INSTALL | grub-install LEGACY"
shell: |
set -e
grub-install --target=i386-pc --no-uefi-secure-boot --skip-fs-probe --force "{{ lookup('file', '/tmp/nbd') }}"
grub-install --target=i386-pc --no-uefi-secure-boot --skip-fs-probe --force --recheck "{{ lookup('file', '/tmp/nbd') }}"
when: uefi is not defined
- name: "POST-INSTALL | grub-install UEFI"
shell: |
set -e
grub-install --target=i386-pc --uefi-secure-boot --skip-fs-probe --force "{{ lookup('file', '/tmp/nbd') }}"
grub-install --target=i386-pc --uefi-secure-boot --skip-fs-probe --force --recheck "{{ lookup('file', '/tmp/nbd') }}"
grub-install --target=x86_64-efi --uefi-secure-boot --skip-fs-probe --force "{{ lookup('file', '/tmp/nbd') }}"
grub-install --target=x86_64-efi --uefi-secure-boot --skip-fs-probe --force --recheck "{{ lookup('file', '/tmp/nbd') }}"
when: uefi is defined
- name: "POST-INSTALL | generate grub cfg file"
shell: |
set -e
update-grub
- name: "POST-INSTALL | install other user-requested packages, and kernel-dependent pkgs and ones that fail to install with multistrap"
apt:
pkg: "{{ post_install_package_list }}"
- name: "POST-INSTALL | write root partition UUID to grub.cfg"
shell: |
set -e
cp -r /usr/lib/grub/* /boot/grub
blkid -s UUID -o value $(df -h | grep /$ | awk "{print \$1}") > /tmp/root_uuid
sed -i "s@root=/dev/nbd[0-9]p[0-9]@root=UUID=$(cat /tmp/root_uuid)@g" /boot/grub/grub.cfg
rm /tmp/root_uuid
- name: "POST-INSTALL | write boot partition UUID to UEFI grub.cfg"
shell: |
set -e
blkid -s UUID -o value $(df -h | grep /boot$ | awk "{print \$1}") > /tmp/boot_uuid
echo "search.fs_uuid $(cat /tmp/boot_uuid) root hd0,gpt2" > /boot/efi/EFI/ubuntu/grub.cfg
echo "set prefix=(\$root)'/grub'" >> /boot/efi/EFI/ubuntu/grub.cfg
echo "configfile \$prefix/grub.cfg" >> /boot/efi/EFI/ubuntu/grub.cfg
rm /tmp/boot_uuid
when: uefi is defined
- name: "POST-INSTALL | running user-defined post-scripts"
shell: "{{ item.file_content }}"
with_items: "{{ post_install_scripts }}"
- name: "POST-INSTALL | cleanup deb cache"
shell: |
set -e
rm /var/cache/apt/archives/*.deb

View File

@ -0,0 +1,34 @@
- name: "POST-INSTALL | generate locales"
shell: |
set -e
locale-gen en_US.UTF-8
- name: "POST-INSTALL | grub-install"
shell: |
set -e
grub-install --target=i386-pc --skip-fs-probe --force "{{ lookup('file', '/tmp/nbd') }}"
grub-install --target=i386-pc --skip-fs-probe --force --recheck "{{ lookup('file', '/tmp/nbd') }}"
grub-install --target=x86_64-efi --skip-fs-probe --force "{{ lookup('file', '/tmp/nbd') }}"
grub-install --target=x86_64-efi --skip-fs-probe --force --recheck "{{ lookup('file', '/tmp/nbd') }}"
- name: "POST-INSTALL | generate grub cfg file"
shell: |
set -e
update-grub
- name: "POST-INSTALL | write root partition UUID to grub.cfg"
shell: |
set -e
cp -r /usr/lib/grub/* /boot/grub
blkid -s UUID -o value $(df -h | grep /$ | awk "{print \$1}") > /tmp/root_uuid
sed -i "s@root=/dev/nbd[0-9]p[0-9]@root=UUID=$(cat /tmp/root_uuid)@g" /boot/grub/grub.cfg
rm /tmp/root_uuid
- name: "POST-INSTALL | write boot partition UUID to UEFI grub.cfg"
shell: |
set -e
blkid -s UUID -o value $(df -h | grep /boot$ | awk "{print \$1}") > /tmp/boot_uuid
echo "search.fs_uuid $(cat /tmp/boot_uuid) root hd0,gpt2" > /boot/efi/EFI/ubuntu/grub.cfg
echo "set prefix=(\$root)'/grub'" >> /boot/efi/EFI/ubuntu/grub.cfg
echo "configfile \$prefix/grub.cfg" >> /boot/efi/EFI/ubuntu/grub.cfg
rm /tmp/boot_uuid

View File

@ -0,0 +1,3 @@
- name: "user-scripts | running user-defined scripts"
shell: "{{ item.file_content }}"
with_items: "{{ runtime_user_scripts }}"

View File

@ -1,15 +1 @@
# NOTE: This file will be *overwritten* by the container entrypoint with user-provided vars, if any are defined.
#
# The following are examples that show you how to override variables.
#
# Example 1: The following usage will *overwrite* the list of packages
# defined under defaults/main.yaml with the list here:
#post_install_package_list:
# - package1
# - package2
#
# Example 2: The following usage will *append* to the list of default pkgs
# defined under defaults/main.yaml with the list here:
#post_install_package_list_append:
# - package1
# - package2

View File

@ -1,8 +1,8 @@
root_chroot: /mnt/rootfs
src: /build
dst: /chroot
nbd_build_dir: /tmp/nbd_build_dir
img_output_dir: /config
img_name: airship-ubuntu.qcow2
dns: 8.8.8.8
qcow_capacity: 5G
partitions:
# Partition numbering is according to list ordering.
@ -46,3 +46,12 @@ partitions:
options: "defaults,errors=remount-ro,noatime"
dump: 0
fsck: 2
# If any custom post-install shell scripts are needed for qcow building,
# they can be added here. This should only be used if
# osconfig_container_buildtime_scripts does not work in osconfig playbook.
qcow_container_runtime_scripts:
- file_content: |
#!/bin/bash
echo "custom qcow post-install script"
# This is only needed if you want DNS working when running qcow scripts above
qcow_container_runtime_scripts_dns: 8.8.8.8

View File

@ -1,7 +1,7 @@
- name: "QCOW | Installing extlinux"
shell: |
mkdir -p "{{ root_chroot }}"/boot/syslinux
extlinux --install "{{ root_chroot }}"/boot/syslinux/ --device /dev/disk/by-partlabel/{{ ( partitions | selectattr('mount', 'equalto', '/boot') | list | first ).mount | hash('md5') }}
mkdir -p "{{ dst }}"/boot/syslinux
extlinux --install "{{ dst }}"/boot/syslinux/ --device /dev/disk/by-partlabel/{{ ( partitions | selectattr('mount', 'equalto', '/boot') | list | first ).mount | hash('md5') }}
- name: "QCOW | Writing out syslinux config"
copy:
@ -11,12 +11,12 @@
LABEL linux
KERNEL /vmlinuz
APPEND root=/dev/disk/by-partlabel/{{ ( partitions | selectattr('mount', 'equalto', '/') | list | first ).mount | hash('md5') }} initrd=/initrd.img
dest: ""{{ root_chroot }}/boot/syslinux/syslinux.cfg"
dest: ""{{ dst }}/boot/syslinux/syslinux.cfg"
- name: "QCOW | Installing kernel and init ramdisk"
shell: |
rm -rf "{{ root_chroot }}"/vmlinuz
cp -f /mnt/image/vmlinuz "{{ root_chroot }}"/boot/
rm -rf "{{ dst }}"/vmlinuz
cp -f /mnt/image/vmlinuz "{{ dst }}"/boot/
rm -rf /tmp/mnt/initrd.img
cp -f /mnt/image/initrd "{{ root_chroot }}"/boot/initrd.img
cp -f /mnt/image/initrd "{{ dst }}"/boot/initrd.img

View File

@ -1,16 +1,18 @@
- name: "QCOW | copy ansible playbooks to target image"
shell: |
set -e
cp -r /opt/assets "{{ root_chroot }}"/opt
cp -r /opt/assets "{{ dst }}"/opt
- name: "QCOW | unmount target"
shell: |
set -e
# restore resolv.conf
chroot "{{ root_chroot }}" /bin/bash -c 'rm /etc/resolv.conf; cd /etc; ln -s ../run/systemd/resolve/stub-resolv.conf resolv.conf'
cd "{{ root_chroot }}"
chroot "{{ dst }}" /bin/bash -c 'rm /etc/resolv.conf; cd /etc; ln -s ../run/systemd/resolve/stub-resolv.conf resolv.conf'
cd "{{ dst }}"
mountpoint dev/pts > /dev/null && umount dev/pts
mountpoint dev > /dev/null && umount dev
mountpoint sys/firmware/efi > /dev/null && umount sys/firmware/efi
if [ -d /sys/firmware/efi ]; then
mountpoint sys/firmware/efi > /dev/null && umount sys/firmware/efi
fi
mountpoint sys > /dev/null && umount sys
mountpoint proc > /dev/null && umount proc

View File

@ -1,30 +1,13 @@
- name: "QCOW | mount sys LEGACY"
shell: |
set -e
mkdir -p "{{ root_chroot }}"
cd "{{ root_chroot }}"
mountpoint sys > /dev/null || mount -t sysfs /sys sys
# mount an empty dir to efi directory, otherwise grub will try to configure EFI boot for the target image, **iff** the build node was booted with EFI.
if [ -d sys/firmware/efi ]; then mountpoint sys/firmware/efi > /dev/null || mkdir /dummy; mount -o bind /dummy sys/firmware/efi; fi
when: uefi is not defined
- name: "QCOW | mount sys UEFI"
shell: |
set -e
mkdir -p "{{ root_chroot }}"
cd "{{ root_chroot }}"
mountpoint sys > /dev/null || mount -t sysfs /sys sys
# Required for building UEFI targets
ls /sys/firmware/efi > /dev/null || (echo "efivars not present on build system. Build system must be booted into UEFI mode." && exit 1)
mountpoint sys/firmware/efi > /dev/null || mount -o bind /sys/firmware/efi sys/firmware/efi
when: uefi is defined
- name: "QCOW | Mount remaining targets"
shell: |
set -e
cd "{{ root_chroot }}"
cd "{{ dst }}"
mountpoint sys > /dev/null || mount -t sysfs /sys sys
if [ -d /sys/firmware/efi ]; then
mountpoint sys/firmware/efi > /dev/null || mount -o bind /sys/firmware/efi sys/firmware/efi
fi
mountpoint proc > /dev/null || mount -t proc /proc proc
mountpoint dev > /dev/null || mount -o bind /dev dev
mountpoint dev/pts > /dev/null || mount -t devpts /dev/pts dev/pts
# temporarily override resolv.conf to working dns
chroot "{{ root_chroot }}" /bin/bash -c 'rm /etc/resolv.conf; echo "nameserver {{ dns }}" > /etc/resolv.conf'
chroot "{{ dst }}" /bin/bash -c 'rm /etc/resolv.conf; echo "nameserver {{ qcow_container_runtime_scripts_dns }}" > /etc/resolv.conf'

View File

@ -0,0 +1,5 @@
# Copy files onto partitioned disk
- name: "mount-helper | Copy files onto partition"
shell: |
set -e
rsync -ah {{ src }}/ {{ dst }}/ --exclude 'live'

View File

@ -19,10 +19,14 @@
file: mount-helper.yaml
with_items: "{{ partitions | sort( case_sensitive=True, attribute='mount_order' ) }}"
vars:
mount_offset: "{{ root_chroot }}"
mount_offset: "{{ dst }}"
state: mounted
fstab: /tmp/junkfstab
- name: "QCOW | Copy files to partition"
include_tasks:
file: copy-files.yaml
- name: "QCOW | Writing image content"
include_tasks:
file: writing-image-content.yaml
@ -44,7 +48,7 @@
file: mount-helper.yaml
with_items: "{{ partitions | sort( reverse=True, case_sensitive=True, attribute='mount' ) }}"
vars:
mount_offset: "{{ root_chroot }}"
mount_offset: "{{ dst }}"
state: unmounted
fstab: /tmp/junkfstab

View File

@ -1,16 +1,11 @@
- name: "QCOW | Writing out rootfs from squashfs"
shell: |
unsquashfs -d "{{ root_chroot }}" -f /mnt/image/live/filesystem.squashfs
exit 0
- name: "QCOW | Writing out fstab"
include_tasks: mount-helper.yaml
with_items: "{{ partitions | sort( case_sensitive=True, attribute='mount' ) }}"
vars:
mount_offset: null
state: present
fstab: "{{ root_chroot }}/etc/fstab"
fstab: "{{ dst }}/etc/fstab"
- name: "QCOW | Setting debug password"
shell: |
chroot "{{ root_chroot }}" sh -c "echo \"root:password\" | chpasswd"
chroot "{{ dst }}" sh -c "echo \"root:password\" | chpasswd"

View File

@ -0,0 +1 @@
{{ item.file_content }}

View File

@ -1,11 +1,4 @@
rootfs_root: /mnt/rootfs
cni_version: v0.8.2
k8s_version: v1.18.6
kernel:
base_pkg: linux-image-generic
headers_pkg: linux-headers-generic
modules:
load:
- name: 8021q
@ -155,17 +148,10 @@ systemd:
enabled: yes
force: no
post_install_package_list:
- kdump-tools
- apparmor
- dbus
- rsyslog
- logrotate
post_install_scripts:
buildtime_user_scripts:
- file_content: |
#!/bin/bash
echo "custom post-install script"
echo "custom container buildtime script"
file_permissions:
# Full path to file to create

View File

@ -1,6 +1,3 @@
root_chroot: /mnt/rootfs
nbd_build_dir: /tmp/nbd_build_dir
dns: 8.8.8.8
qcow_capacity: 412G
partitions:
# Partition numbering is according to list ordering.

View File

@ -1,4 +1,3 @@
dns: 8.8.8.8
qcow_capacity: 5G
partitions:
# Partition numbering is according to list ordering.

View File

@ -18,14 +18,10 @@ image="${3:-port/image-builder:latest-ubuntu_focal}"
# Libvirt instance name to use for a new libvirt XML definition that
# will be created to reference the newly created ISO or QCOW2 image.
img_alias="${4:-port-image-builder-latest-ubuntu_focal-$build_type}"
# Whether or not to build the image with UEFI support.
# NOTE: Machines that are not booted with UEFI will be unable to create
# UEFI images.
uefi_boot="$5"
# proxy to use, if applicable
proxy="$6"
proxy="$5"
# noproxy to use, if applicable
noproxy="$7"
noproxy="$6"
if [ -n "$proxy" ]; then
export http_proxy=$proxy
@ -39,8 +35,23 @@ if [ -n "$noproxy" ]; then
export NO_PROXY=$noproxy
fi
if [ -n "$uefi_boot" ]; then
# Install pre-requisites
install_pkg(){
dpkg -l $1 2> /dev/null | grep ^ii > /dev/null || sudo -E apt-get -y install $1
}
sudo -E apt -y update
install_pkg qemu-kvm
install_pkg virtinst
install_pkg libvirt-bin
install_pkg cloud-image-utils
install_pkg ovmf
type docker >& /dev/null || install_pkg docker.io
if [ -d /sys/firmware/efi ]; then
uefi_mount='--volume /sys/firmware/efi:/sys/firmware/efi:rw'
uefi_boot_arg='--boot uefi'
fi
workdir="$(realpath ${host_mount_directory})"
@ -58,9 +69,9 @@ if [[ $build_type = iso ]]; then
--env NO_PROXY=$noproxy \
${image}
disk1="--disk path=${workdir}/ephemeral.iso,device=cdrom"
uefi_boot_arg='--boot uefi'
elif [[ $build_type == qcow ]]; then
sudo -E modprobe nbd
echo "Note: This step can be slow if you don't have an SSD."
sudo -E docker run -t --rm \
--privileged \
--volume /dev:/dev:rw \
@ -78,15 +89,11 @@ elif [[ $build_type == qcow ]]; then
--env HTTPS_PROXY=$proxy \
--env no_proxy=$noproxy \
--env NO_PROXY=$noproxy \
--env uefi_boot=$uefi_boot \
${image}
cloud_init_config_dir='assets/tests/qcow/cloud-init'
sudo -E cloud-localds -v --network-config="${cloud_init_config_dir}/network-config" "${workdir}/airship-ubuntu_config.iso" "${cloud_init_config_dir}/user-data" "${cloud_init_config_dir}/meta-data"
disk1="--disk path=${workdir}/control-plane.qcow2"
disk2="--disk path=${workdir}/airship-ubuntu_config.iso,device=cdrom"
if [ -n "$uefi_boot" ]; then
uefi_boot_arg='--boot uefi'
fi
else
echo Unknown build type: $build_type, exiting.
exit 1

View File

@ -1,15 +0,0 @@
#!/bin/bash
install_pkg(){
dpkg -l $1 >& /dev/null || sudo -E apt-get -y install $1
}
install_pkg qemu-kvm
install_pkg virtinst
install_pkg libvirt-bin
install_pkg cloud-image-utils
install_pkg ovmf
install_pkg efivar
type docker >& /dev/null || install_pkg docker.io
# required for building UEFI image
sudo -E modprobe efivars

136
image-builder/tools/multistrap.sh Executable file
View File

@ -0,0 +1,136 @@
#!/bin/bash
set -e
build_dir=assets/playbooks/build
osconfig_build_dir=$(basename $build_dir)
install_pkg(){
dpkg -l $1 2> /dev/null | grep ^ii > /dev/null || sudo -E apt-get -y install $1
}
setup_chroot(){
# Idempotently setup chroot mounts
mkdir -p $build_dir
mkdir -p $build_dir/sys
mountpoint $build_dir/sys > /dev/null || sudo mount -t sysfs /sys $build_dir/sys
if [ -d /sys/firmware/efi ]; then
mountpoint $build_dir/sys/firmware/efi > /dev/null || sudo mount -o bind /sys/firmware/efi $build_dir/sys/firmware/efi
fi
mkdir -p $build_dir/proc
mountpoint $build_dir/proc > /dev/null || sudo mount -t proc /proc $build_dir/proc
mkdir -p $build_dir/dev
mountpoint $build_dir/dev > /dev/null || sudo mount -o bind /dev $build_dir/dev
mountpoint $build_dir/dev/pts > /dev/null || sudo mount -t devpts /dev/pts $build_dir/dev/pts
mkdir -p $osconfig_build_dir
mountpoint $osconfig_build_dir > /dev/null || sudo mount -o bind $build_dir $osconfig_build_dir
}
umount_helper(){
if [[ -d "$1" ]] && mountpoint "$1" > /devnull; then
sudo umount "$1"
fi
}
umount_chroot(){
# Idempotently teardown chroot mounts
umount_helper $build_dir/dev/pts
umount_helper $build_dir/dev
if [[ -d /sys/firmware/efi ]]; then
umount_helper $build_dir/sys/firmware/efi
fi
umount_helper $build_dir/sys
umount_helper $build_dir/proc
umount_helper $osconfig_build_dir
}
# Install pre-requisites
sudo -E apt -y update
install_pkg efivar
# required for building UEFI image
sudo -E modprobe efivars
type docker >& /dev/null || install_pkg docker.io
install_pkg equivs
install_pkg ca-certificates
install_pkg build-essential
install_pkg gnupg2
install_pkg multistrap
install_pkg curl
install_pkg grub-common
install_pkg grub2-common
install_pkg grub-pc-bin
install_pkg grub-efi-amd64-signed
install_pkg dosfstools
install_pkg mtools
install_pkg squashfs-tools
install_pkg python3-minimal
install_pkg python3-pip
install_pkg python3-apt
install_pkg python3-setuptools
sudo -E pip3 install --upgrade pip
pip3 show wheel >& /dev/null || sudo -E pip3 install --upgrade wheel
pip3 show ansible >& /dev/null || sudo -E pip3 install --upgrade ansible
if [[ $1 = clean ]]; then
umount_chroot
sudo chattr -i $build_dir/etc/kernel/postinst.d/kdump-tools
if [[ -d $build_dir ]]; then
sudo rm -rf $build_dir
fi
if [[ -d $osconfig_build_dir ]]; then
sudo rm -rf $osconfig_build_dir
fi
exit 0
elif [[ $1 = umount ]]; then
umount_chroot
exit 0
elif [[ $1 = mount ]]; then
setup_chroot
exit 0
fi
setup_chroot
# Archive a copy of the ansible used to generate the image in the image itself
mkdir -p $build_dir/opt/assets/playbooks/roles
cp assets/playbooks/inventory.yaml $build_dir/opt/assets/playbooks/inventory.yaml
cp assets/playbooks/base-chroot.yaml $build_dir/opt/assets/playbooks/base-chroot.yaml
cp -r assets/playbooks/roles/multistrap $build_dir/opt/assets/playbooks/roles
# Run multistrap
sudo -E ansible-playbook -i assets/playbooks/inventory.yaml assets/playbooks/base-chroot.yaml -vv
cp assets/playbooks/base-osconfig.yaml $build_dir/opt/assets/playbooks/base-osconfig.yaml
cp -r assets/playbooks/roles/osconfig $build_dir/opt/assets/playbooks/roles
sudo -E ansible-playbook -i assets/playbooks/inventory.yaml assets/playbooks/base-osconfig.yaml --tags "runtime_and_buildtime" -vv
sudo -E ansible-playbook -i assets/playbooks/inventory.yaml assets/playbooks/base-osconfig.yaml --tags "buildtime_only" -vv
umount_chroot
cp assets/playbooks/base-livecdcontent.yaml $build_dir/opt/assets/playbooks/base-livecdcontent.yaml
cp -r assets/playbooks/roles/livecdcontent $build_dir/opt/assets/playbooks/roles
sudo -E ansible-playbook -i assets/playbooks/inventory.yaml assets/playbooks/base-livecdcontent.yaml -vv
cp assets/playbooks/iso.yaml $build_dir/opt/assets/playbooks/iso.yaml
cp -r assets/playbooks/roles/iso $build_dir/opt/assets/playbooks/roles
cp assets/playbooks/qcow.yaml $build_dir/opt/assets/playbooks/qcow.yaml
cp -r assets/playbooks/roles/qcow $build_dir/opt/assets/playbooks/roles
if [ ! -e $build_dir/dev/random ]; then
sudo -E mknod $build_dir/dev/random c 1 8
sudo -E chmod 640 $build_dir/dev/random
sudo -E chown 0:0 $build_dir/dev/random
fi
if [ ! -e $build_dir/dev/urandom ]; then
sudo -E mknod $build_dir/dev/urandom c 1 9
sudo -E chmod 640 $build_Dir/dev/urandom
sudo -E chown 0:0 $build_Dir/dev/urandom
fi
if [ -f $build_dir/dev/null ]; then
sudo rm -f $build_dir/dev/null
fi
if [ ! -e $build_dir/dev/null ]; then
sudo -E mknod $build_dir/dev/null c 1 3
sudo -E chmod 666 $build_dir/dev/null
sudo -E chown 0:0 $build_dir/dev/null
fi