#!/bin/sh # This script generates CentOS images for OpenNebula. # Depends on the following packages (as of CentOS 8): # qemu-img util-linux coreutils dnf curl e2fsprogs cryptsetup # Run locally (without network) with: # qemu-system-x86_64 -enable-kvm -m 1G -drive file=$IMAGE,format=raw set -e set -x RELEASE=7 ARCH=x86_64 IMAGE_PATH=centos-luks-$RELEASE-$(date --iso-8601).img IMAGE_SIZE=10G LOOPBACK_DEVICE=/dev/loop0 LUKS_PASSPHRASE=secret LUKS_DEVICE_NAME=cryptroot LUKS_DEVICE="/dev/mapper/$LUKS_DEVICE_NAME" ONE_CONTEXT_RPM_URL="https://github.com/OpenNebula/addon-context-linux/releases/download/v5.10.0/one-context-5.10.0-1.el$RELEASE.noarch.rpm" ONE_CONTEXT_RPM_PATH=/root/one-context.rpm cleanup() { # The order here is important. umount /mnt/dev/pts 2>/dev/null || true umount /mnt/dev/shm 2>/dev/null || true umount /mnt/dev 2>/dev/null || true umount /mnt/proc 2>/dev/null || true umount /mnt/run 2>/dev/null || true umount /mnt/sys 2>/dev/null || true umount /mnt/boot 2>/dev/null || true umount /mnt 2>/dev/null || true losetup -d "$LOOPBACK_DEVICE" } run_root() { chroot /mnt /usr/bin/env \ PATH=/sbin:/usr/sbin:/bin:/usr/bin \ sh -c "$*" } if [ "$(whoami)" != 'root' ]; then echo "This script must be run as root." >&2 exit 1 fi if [ ! -f '/etc/centos-release' ]; then echo "WARNING: this script has been designed to run on a CentOS system." >&2 echo "WARNING: Not running CentOS. Giving you 5 seconds to abort." >&2 sleep 5 fi # Create base RAW image (no LOOPBACK support in RHEL/CentOS). qemu-img create -f raw "$IMAGE_PATH" "$IMAGE_SIZE" losetup "$LOOPBACK_DEVICE" "$IMAGE_PATH" # Don't forget to cleanup, even if the script crash. trap cleanup EXIT # Create partition table, format partitions. parted --script "$LOOPBACK_DEVICE" \ mklabel msdos \ mkpart primary ext4 1M 500M \ mkpart primary ext4 500M 100% partprobe "$LOOPBACK_DEVICE" mkfs.ext4 "${LOOPBACK_DEVICE}p1" echo -n "$LUKS_PASSPHRASE" | cryptsetup luksFormat -v -d - "${LOOPBACK_DEVICE}p2" echo -n "$LUKS_PASSPHRASE" | cryptsetup open -v -d - "${LOOPBACK_DEVICE}p2" "$LUKS_DEVICE_NAME" mkfs.ext4 "$LUKS_DEVICE" # Mount partitions, install base OS. mount "${LUKS_DEVICE}" /mnt mkdir /mnt/boot mount "${LOOPBACK_DEVICE}p1" /mnt/boot # AppStream landed in CentOS 8. if [ $RELEASE -ge 8 ]; then enabled_repos="--enablerepo=BaseOS --enablerepo=AppStream --enablerepo=extras" release_specific_packages="systemd-udev" else enabled_repos="--enablerepo=base --enablerepo=extras" release_specific_packages="dnf" fi dnf -y \ --releasever=$RELEASE \ --installroot=/mnt \ --disablerepo='*' \ $enabled_repos \ --setopt=install_weak_deps=False install \ --setopt=reposdir=rpm-repositories \ bash basesystem systemd dnf centos-release cryptsetup $release_specific_packages mount --bind /dev /mnt/dev mount --bind /dev/pts /mnt/dev/pts mount --bind /dev/shm /mnt/dev/shm mount --bind /proc /mnt/proc mount --bind /run /mnt/run mount --bind /sys /mnt/sys # Guest networking is to be handled by the one-context package. # See https://github.com/OpenNebula/addon-context-linux for details. # Note: as of writing, one-context does not support NetworkManager or # systemd-networkd. # Required to resolve package mirror in chroot. cp /etc/resolv.conf /mnt/etc/resolv.conf # Initialize /etc/hosts. cat > /mnt/etc/hosts << EOF 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 EOF # See https://github.com/OpenNebula/addon-context-linux/issues/121 for details. # network-scripts.x86_64 : Legacy scripts for manipulating of network devices if [ $RELEASE -ge 8 ]; then run_root dnf -y install network-scripts fi # Install (magic?) one-context RPM and hope things works as expected. curl -L "$ONE_CONTEXT_RPM_URL" > "/mnt$ONE_CONTEXT_RPM_PATH" run_root dnf -y install "$ONE_CONTEXT_RPM_PATH" run_root rm "$ONE_CONTEXT_RPM_PATH" # Install resize2fs, which is required to resize the root file-system. run_root dnf -y install e2fsprogs # Initalize base services. run_root systemd-machine-id-setup run_root ln -sf /usr/share/zoneinfo/UTC /etc/localtime # Install and configure NTP client. run_root dnf install -y chrony run_root systemctl enable chronyd.service # Install kernel and bootloader. # Note: linux-firmware is not required our environment and takes almost 200M # uncompressed but is a direct dependency of kernel-core... run_root dnf -y install kernel grub2 # Add support for virtio block devices at boot time, configure bootloader. cat > /mnt/etc/dracut.conf.d/virtio-blk.conf <> /mnt/etc/crypttab run_root dracut -v --force --kver $kernel_version run_root grub2-install --target=i386-pc "${LOOPBACK_DEVICE}" run_root grub2-mkconfig -o /boot/grub2/grub.cfg # Install en configure SSH daemon. run_root dnf -y install openssh-server run_root systemctl enable sshd # Generate fstab file. boot_uuid=$(blkid --match-tag UUID --output value "${LOOPBACK_DEVICE}p1") root_uuid=$(blkid --match-tag UUID --output value "$LUKS_DEVICE") cat >>/mnt/etc/fstab <