commit 2b90d55b0d8bc9eb6f612c9c5a9645f7b9f9e4be Author: Darren Shepherd Date: Sat Jun 5 17:31:50 2021 -0700 Initial commit diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..03f9f89e --- /dev/null +++ b/Dockerfile @@ -0,0 +1,107 @@ +FROM opensuse/leap:15.3 as rancherd +RUN zypper in -y curl docker squashfs xorriso go1.16 git +RUN zypper in -y upx +RUN git clone --depth=1 https://github.com/rancher/rancherd && \ + cd ./rancherd && \ + ./scripts/build && \ + upx bin/rancherd && \ + cp bin/rancherd /usr/bin/ + +FROM opensuse/leap:15.3 as tools +RUN zypper in -y curl docker squashfs xorriso go1.16 git +RUN curl https://get.mocaccino.org/luet/get_luet_root.sh | sh +RUN luet install -y extension/makeiso +COPY tools / + + +FROM opensuse/leap:15.3 +ARG ARCH=amd64 +ENV ARCH=${ARCH} +RUN zypper in -y \ + bash-completion \ + conntrack-tools \ + coreutils \ + curl \ + device-mapper \ + dosfstools \ + dracut \ + e2fsprogs \ + findutils \ + gawk \ + grub2-i386-pc \ + grub2-x86_64-efi \ + haveged \ + iproute2 \ + iptables \ + jq \ + kernel-default \ + kernel-firmware-bnx2 \ + kernel-firmware-i915 \ + kernel-firmware-intel \ + kernel-firmware-iwlwifi \ + kernel-firmware-mellanox \ + kernel-firmware-network \ + kernel-firmware-platform \ + kernel-firmware-realtek \ + less \ + lsscsi \ + lvm2 \ + mdadm \ + multipath-tools \ + nano \ + nfs-utils \ + open-iscsi \ + open-vm-tools \ + parted \ + python-azure-agent \ + qemu-guest-agent \ + rng-tools \ + rsync \ + squashfs \ + strace \ + systemd \ + systemd-sysvinit \ + tar \ + timezone \ + vim \ + which + +RUN curl -L https://github.com/containerd/nerdctl/releases/download/v0.8.3/nerdctl-0.8.3-linux-${ARCH}.tar.gz | tar xvzf - -C /usr/bin nerdctl +RUN if [ "$ARCH" = "amd64" ]; then ARCH=x86_64; fi && \ + curl -L https://github.com/derailed/k9s/releases/download/v0.24.10/k9s_v0.24.10_Linux_${ARCH}.tar.gz | tar xvzf - -C /usr/bin k9s +COPY --from=rancherd /usr/bin/rancherd /usr/bin/rancherd + +RUN zypper ar https://download.opensuse.org/repositories/security:/SELinux/openSUSE_Leap_15.3/security:SELinux.repo +RUN zypper --gpg-auto-import-keys in -y --allow-vendor-change --allow-downgrade container-selinux -libsemanage1 + +RUN mkdir /tmp/rpm && \ + cd /tmp/rpm && \ + curl -L -O https://github.com/k3s-io/k3s-selinux/releases/download/v0.3.testing.0/k3s-selinux-0.3-0.el7.noarch.rpm && \ + curl -L -O https://github.com/rancher/rancher-selinux/releases/download/v0.2-rc1.testing.1/rancher-selinux-0.2.rc1-1.el7.noarch.rpm && \ + mv /var/lib/selinux/targeted/active /var/lib/selinux/targeted/bkp && \ + mv /var/lib/selinux/targeted/bkp /var/lib/selinux/targeted/active && \ + rpm -ivh --nodeps *.rpm && \ + cd / && \ + rm -rf /tmp/rpm + + +COPY files/etc/luet/luet.yaml /etc/luet/luet.yaml +ENV LUET_VERSION 0.16.6 +RUN curl -sfL -o /usr/bin/luet https://github.com/mudler/luet/releases/download/${LUET_VERSION}/luet-${LUET_VERSION}-linux-${ARCH} && \ + chmod +x /usr/bin/luet + +RUN luet install -y \ + toolchain/yip \ + utils/installer \ + system/cos-setup \ + system/immutable-rootfs \ + system/grub-config + +COPY files/ / +RUN mkinitrd + +ARG OS_NAME=RancherOS +ARG OS_VERSION=999 +ARG OS_GIT=dirty +ARG FINALIZE=false +RUN if [ "${FINALIZE}" = "true" ]; then OS_NAME=${OS_NAME} OS_VERSION=${OS_VERSION} OS_GIT=${OS_GIT} /usr/bin/finalize; fi diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..90db3927 --- /dev/null +++ b/Makefile @@ -0,0 +1,28 @@ +.DEFAULT_GOAL := iso +IMAGE=ibuildthecloud/test +TOOLS=${IMAGE}-tools + +.PHONY: build +build: + docker build -t ${IMAGE} . + +.PHONY: final-build +final-build: + docker build --build-arg FINALIZE=true -t ${IMAGE} . + +.PHONY: push +push: build + docker push ${IMAGE} + +.PHONY: tools +tools: + docker build -t ${TOOLS} --target tools . + +.PHONY: iso +iso: tools final-build + mkdir -p build + rm -f build/iso-container + docker run -v /var/run:/var/run -it --cidfile=build/iso-container ${TOOLS} makeiso ${IMAGE} + docker cp $$(cat build/iso-container):/output.iso build/output.iso + docker rm -fv $$(cat build/iso-container) + rm -f build/iso-container diff --git a/files/etc/bash.bashrc.local b/files/etc/bash.bashrc.local new file mode 100644 index 00000000..778ad4f5 --- /dev/null +++ b/files/etc/bash.bashrc.local @@ -0,0 +1,14 @@ +if [ -e /etc/rancher/rke2 ]; then + if [ -z "$KUBECONFIG" ]; then + export KUBECONFIG=/etc/rancher/rke2/rke2.yaml + fi +fi +if [ -d /var/lib/rancher/rke2/bin ]; then + export PATH="${PATH}:/var/lib/rancher/rke2/bin" +fi +if [ -z "$CONTAINER_RUNTIME_ENDPOINT" ]; then + export CONTAINER_RUNTIME_ENDPOINT=unix:///var/run/k3s/containerd/containerd.sock +fi +if [ -z "$IMAGE_SERVICE_ENDPOINT" ]; then + export IMAGE_SERVICE_ENDPOINT=unix:///var/run/k3s/containerd/containerd.sock +fi diff --git a/files/etc/cos/bootargs.cfg b/files/etc/cos/bootargs.cfg new file mode 100644 index 00000000..f10b1eab --- /dev/null +++ b/files/etc/cos/bootargs.cfg @@ -0,0 +1,3 @@ +set kernel=/boot/vmlinuz +set kernelcmd="console=tty1 console=ttyS0 root=LABEL=$label iso-scan/filename=$img panic=5 security=selinux selinux=1" +set initramfs=/boot/initrd diff --git a/files/etc/dracut.conf.d/50-immutable-rootfs.conf b/files/etc/dracut.conf.d/50-immutable-rootfs.conf new file mode 100644 index 00000000..ddf7c12e --- /dev/null +++ b/files/etc/dracut.conf.d/50-immutable-rootfs.conf @@ -0,0 +1,5 @@ +hostonly_cmdline="no" +hostonly="no" +compress="xz" +omit_dracutmodules+=" multipath " +add_dracutmodules+=" dmsquash-live cos-immutable-rootfs " diff --git a/files/etc/luet/luet.yaml b/files/etc/luet/luet.yaml new file mode 100644 index 00000000..4273416a --- /dev/null +++ b/files/etc/luet/luet.yaml @@ -0,0 +1,17 @@ +logging: + color: false + enable_emoji: false +general: + debug: false + spinner_charset: 9 +repositories: +- name: "cos" + description: "cOS official" + type: "docker" + enable: true + cached: true + priority: 1 + verify: false + urls: + - "quay.io/costoolkit/releases-opensuse" + diff --git a/files/etc/selinux/config.enforcing b/files/etc/selinux/config.enforcing new file mode 100644 index 00000000..f4e15123 --- /dev/null +++ b/files/etc/selinux/config.enforcing @@ -0,0 +1,14 @@ +# This file controls the state of SELinux on the system. +# SELinux can be completly disabled with the "selinux=0" kernel +# commandline option. +# +# SELINUX= can take one of these three values: +# enforcing - SELinux security policy is enforced. +# permissive - SELinux prints warnings instead of enforcing. +SELINUX=enforcing +# SELINUXTYPE= can take one of these three values: +# targeted - Targeted processes are protected, +# minimum - Modification of targeted policy. Only selected processes are protected. +# mls - Multi Level Security protection. +SELINUXTYPE=targeted + diff --git a/files/system/oem/00_rootfs.yaml b/files/system/oem/00_rootfs.yaml new file mode 100644 index 00000000..b02d60ab --- /dev/null +++ b/files/system/oem/00_rootfs.yaml @@ -0,0 +1,63 @@ +name: "Rootfs Layout Settings" +stages: + rootfs: + - environment_file: /run/cos/cos-layout.env + environment: + VOLUMES: "LABEL=COS_OEM:/oem LABEL=COS_PERSISTENT:/usr/local" + OVERLAY: "tmpfs:25%" +# DEBUG_RW: "true" + initramfs: + - if: '[ -z "$(blkid -L COS_SYSTEM || true)" ]' + commands: + - | + target=/usr/local/.ros-state + + # Always want the latest update of systemd conf from the image + mkdir -p ${target}/etc/systemd/ + rsync -av /etc/systemd/ ${target}/etc/systemd/ + + # Only populate ssh conf once + if [ ! -e ${target}/etc/ssh ]; then + mkdir -p ${target}/etc/ssh/ + rsync -av /etc/ssh/ ${target}/etc/ssh/ + fi + + # make /tmp tmpfs + cp -f /usr/share/systemd/tmp.mount ${target}/etc/systemd/system/ + + # undo /home /opt mount from cos immutable-rootfs module + sed -i '/overlay \/home /d' /etc/fstab + sed -i '/overlay \/opt /d' /etc/fstab + umount /home + umount /opt + + # setup directories as persistent + for i in root opt home var/lib/rancher var/lib/kubelet etc/systemd etc/rancher etc/ssh usr/libexec; do + mkdir -p ${target}/$i /$i + mount ${target}/$i /$i -t none -o bind + done + + # This is hidden so that if you run some selinux label checking or relabeling the bind + # mount won't screw up things. If you have two files at different paths they will get + # labeled with two different labels. + mkdir -p ${target}/empty + mount ${target}/empty ${target} -o bind,ro + + # persist machine-id + if [ -s /usr/local/etc/machine-id ]; then + cat /usr/local/etc/machine-id > /etc/machine-id + else + mkdir -p /usr/local/etc + cp /etc/machine-id /usr/local/etc + fi + + # ensure /var/log/journal exists so it's labeled correctly + mkdir -p /var/log/journal + initramfs.after: + - if: '[ -z "$(blkid -L COS_SYSTEM || true)" ]' + commands: + - restorecon -R -v /etc /home /opt /var /usr/local /tmp /srv /root + fs.before: + - if: '[ -z "$(blkid -L COS_SYSTEM || true)" ]' + commands: + - restorecon -R -v /etc /home /opt /var /usr/local /tmp /srv /root diff --git a/files/system/oem/01_defaults.yaml b/files/system/oem/01_defaults.yaml new file mode 100644 index 00000000..9cf7832e --- /dev/null +++ b/files/system/oem/01_defaults.yaml @@ -0,0 +1,11 @@ +name: "General settings" +stages: + initramfs: + - name: "Setup distro" + #systemd_firstboot: + #keymap: us + #locale: en_US.UTF-8 + #timezone: UTC + - name: "Remove install default" + commands: + - rm -f /usr/local/cloud-config/90_after_install.yaml diff --git a/files/system/oem/03_branding.yaml b/files/system/oem/03_branding.yaml new file mode 100644 index 00000000..1bca5c47 --- /dev/null +++ b/files/system/oem/03_branding.yaml @@ -0,0 +1,22 @@ +name: "Branding" +stages: + initramfs: + - name: "Branding" + hostname: "rancher" + Xfiles: + - path: /etc/issue + content: | + .-----. + | .-. | + | |.| | + | `-' | + `-----' + + Welcome to \S ! + IP address \4 + Login with user: root, password: cos + Start the installer with "cos-installer " to install it in the local system + permissions: 0644 + owner: 0 + group: 0 + diff --git a/files/system/oem/04_accounting.yaml b/files/system/oem/04_accounting.yaml new file mode 100644 index 00000000..23786e6a --- /dev/null +++ b/files/system/oem/04_accounting.yaml @@ -0,0 +1,46 @@ +name: "Default user" +stages: + initramfs: + - name: "Setup groups" + ensure_entities: + - entity: | + kind: "group" + group_name: "admin" + password: "x" + gid: 900 + - entity: | + kind: "group" + group_name: "rancher" + password: "x" + gid: 1000 + - name: "Setup users" + users: + rancher: + name: "rancher" + passwd: "$6$mL4eOZ/wHV4MtjaZ$ASiwT66Yj9I/61cc7/vzdl6I8p5xK11Yn1EtSEO1CytZszfmP3R5iA05g0voxfZ5Dkj5BYdicE8lLnf3atbzE/" + groups: + - "admin" + - "systemd-journal" + primary_group: "rancher" + shell: /bin/bash + homedir: "/home/rancher" + #ensure_entities: + #- entity: | + # kind: "shadow" + # username: "root" + # password: "$6$g9DDJRDNRS8MEzhH$w6Cn6PNzFnUVnatwRbNoLk6etanvAbcxUzfYlQcj6y/JLGq3Yrl7wXi6SkMzp1/tEM3NheMr5fH8.92NdiaB/0" + - name: "Setup sudo" + files: + - path: "/etc/sudoers" + owner: 0 + group: 0 + permsisions: 0600 + content: | + Defaults always_set_home + Defaults secure_path="/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/bin:/usr/local/sbin" + Defaults env_reset + Defaults env_keep = "LANG LC_ADDRESS LC_CTYPE LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE LC_ATIME LC_ALL LANGUAGE LINGUAS XDG_SESSION_COOKIE" + Defaults !insults + root ALL=(ALL) ALL + %admin ALL=(ALL) NOPASSWD: ALL + @includedir /etc/sudoers.d diff --git a/files/system/oem/05_network.yaml b/files/system/oem/05_network.yaml new file mode 100644 index 00000000..2a990aaf --- /dev/null +++ b/files/system/oem/05_network.yaml @@ -0,0 +1,17 @@ +name: "Default network configuration" +stages: + initramfs: + - name: "Setup network" + dns: + path: /etc/resolv.conf + nameservers: + - 8.8.8.8 + - 1.1.1.1 + files: + - path: /etc/sysconfig/network/ifcfg-eth0 + content: | + BOOTPROTO='dhcp' + STARTMODE='onboot' + permissions: 0600 + owner: 0 + group: 0 diff --git a/files/system/oem/06_recovery.yaml b/files/system/oem/06_recovery.yaml new file mode 100644 index 00000000..4144735a --- /dev/null +++ b/files/system/oem/06_recovery.yaml @@ -0,0 +1,12 @@ +name: "Recovery partition boot setup" +stages: + boot: + - name: "Recovery" + commands: + - | + source /etc/os-release + if [ -n "$(blkid -L COS_SYSTEM || true)" ]; then + echo >> /etc/issue + echo "You are booting from recovery mode. Run 'cos-reset' to reset the system to $VERSION" >> /etc/issue + echo >> /etc/issue + fi diff --git a/files/system/oem/07_cdrom_ds.yaml b/files/system/oem/07_cdrom_ds.yaml new file mode 100644 index 00000000..79a9c664 --- /dev/null +++ b/files/system/oem/07_cdrom_ds.yaml @@ -0,0 +1,8 @@ +name: "Cloud-init cdrom" +stages: + fs: + - name: "cdrom datasource" + datasource: + providers: + - cdrom + path: /oem diff --git a/files/system/oem/08_rancherd.yaml b/files/system/oem/08_rancherd.yaml new file mode 100644 index 00000000..0957f248 --- /dev/null +++ b/files/system/oem/08_rancherd.yaml @@ -0,0 +1,11 @@ +name: "Rancherd" +stages: + initramfs: + - name: "Rancherd" + commands: + - | + if grep -q root=live:CDLABEL=COS_LIVE /proc/cmdline || [ -n "$(blkid -L COS_SYSTEM)" ]; then + systemctl disable rancherd.service + else + systemctl enable rancherd.service + fi diff --git a/files/usr/bin/finalize b/files/usr/bin/finalize new file mode 100755 index 00000000..d5f88496 --- /dev/null +++ b/files/usr/bin/finalize @@ -0,0 +1,50 @@ +#!/bin/bash +set -e -o pipefail + +packages="openSUSE-release-appliance-docker + systemd-presets-branding-MicroOS + dracut + rpm-config-SUSE + openSUSE-release-15.3 + openSUSE-build-key" + +packages="$packages $(zypper rm --details -D -u -y zypper | grep '^[a-z]' | grep -v procps)" + +echo Removing $packages +rpm --nodeps -v -e $packages 2>&1 | grep -v LC_MESSAGES + +echo Removing zypper data +rm -rf /etc/zypp \ + /var/cache/zypp \ + /var/log/zypp \ + /var/lib/zypp + +echo Removing luet metadata +rm -rf /var/cache/luet \ + /var/luet \ + /etc/luet + +echo Removing rpm +rpm --nodeps -v -e rpm 2>&1 | grep -v LC_MESSAGES +rm -rf /usr/lib/rpm \ + /usr/lib/sysimage/rpm \ + /etc/rpm + +echo Removing extra kernel weight +rm -rf /boot/vmlinux* + +if ! command -v man >/dev/null; then + echo Removing man pages + find /usr/share/man -type f -exec rm {} \; +fi + +if [ -e /usr/lib/os-release.tmpl ]; then + echo Setting up /etc/os-release + export OS_NAME=${OS_NAME:-NoNameOS} OS_VERSION="${OS_VERSION:-0.0.0}" OS_GIT="${OS_GIT:-HEAD}" + cat /usr/lib/os-release.tmpl | envsubst > /usr/lib/os-release + rm /usr/lib/os-release.tmpl + ln -sf ../usr/lib/os-release /etc/os-release +fi + +echo Removing self +rm /usr/bin/finalize diff --git a/files/usr/bin/test-upgrade b/files/usr/bin/test-upgrade new file mode 100755 index 00000000..24b42e69 --- /dev/null +++ b/files/usr/bin/test-upgrade @@ -0,0 +1,2 @@ +#!/bin/bash +cos-upgrade --no-verify --docker-image ibuildthecloud/test diff --git a/files/usr/lib/issue.d/10-rancheros.conf b/files/usr/lib/issue.d/10-rancheros.conf new file mode 100644 index 00000000..220c7233 --- /dev/null +++ b/files/usr/lib/issue.d/10-rancheros.conf @@ -0,0 +1,2 @@ +Welcome to \S - Kernel \r (\l). + diff --git a/files/usr/lib/os-release.tmpl b/files/usr/lib/os-release.tmpl new file mode 100644 index 00000000..1f9ead5a --- /dev/null +++ b/files/usr/lib/os-release.tmpl @@ -0,0 +1,9 @@ +NAME="${OS_NAME}" +VERSION="v${OS_VERSION} (${OS_GIT})" +ID="rancheros" +ID_LIKE="suse opensuse" +VERSION_ID="${OS_VERSION}" +PRETTY_NAME="${OS_NAME} v${OS_VERSION} (${OS_GIT})" +ANSI_COLOR="0;32" +BUG_REPORT_URL="https://github.com/rancher/os/issues" +HOME_URL="https://github.com/rancher/os" diff --git a/files/usr/lib/systemd/system/rancherd.service b/files/usr/lib/systemd/system/rancherd.service new file mode 100644 index 00000000..891f3a63 --- /dev/null +++ b/files/usr/lib/systemd/system/rancherd.service @@ -0,0 +1,22 @@ +[Unit] +Description=Rancher Bootstrap +Documentation=https://github.com/rancher/rancherd +Wants=network-online.target +After=network-online.target + +[Install] +WantedBy=multi-user.target + +[Service] +Type=oneshot +EnvironmentFile=-/etc/default/%N +EnvironmentFile=-/etc/sysconfig/%N +KillMode=process +# Having non-zero Limit*s causes performance problems due to accounting overhead +# in the kernel. We recommend using cgroups to do container-local accounting. +LimitNOFILE=1048576 +LimitNPROC=infinity +LimitCORE=infinity +TasksMax=infinity +TimeoutStartSec=0 +ExecStart=/usr/bin/rancherd bootstrap diff --git a/files/usr/libexec/.placeholder b/files/usr/libexec/.placeholder new file mode 100644 index 00000000..e69de29b diff --git a/files/usr/sbin/cos-upgrade b/files/usr/sbin/cos-upgrade new file mode 100755 index 00000000..6ea7a98d --- /dev/null +++ b/files/usr/sbin/cos-upgrade @@ -0,0 +1,355 @@ +#!/bin/bash +set -e + +CHANNEL_UPGRADES="${CHANNEL_UPGRADES:-true}" + +# 1. Identify active/passive partition +# 2. Install upgrade in passive partition +# 3. Invert partition labels + +find_partitions() { + STATE=$(blkid -L COS_STATE || true) + if [ -z "$STATE" ]; then + echo "State partition cannot be found" + exit 1 + fi + + PERSISTENT=$(blkid -L COS_PERSISTENT || true) + if [ -z "$PERSISTENT" ]; then + echo "Persistent partition cannot be found" + exit 1 + fi + + OEM=$(blkid -L COS_OEM || true) + if [ -z "$OEM" ]; then + echo "OEM partition cannot be found" + exit 1 + fi + + COS_ACTIVE=$(blkid -L COS_ACTIVE || true) + if [ -n "$COS_ACTIVE" ]; then + CURRENT=active.img + fi + + COS_PASSIVE=$(blkid -L COS_PASSIVE || true) + if [ -n "$COS_PASSIVE" ]; then + CURRENT=passive.img + fi + + if [ -z "$CURRENT" ]; then + # We booted from an ISO or some else medium. We assume we want to fixup the current label + read -p "Could not determine current partition. Do you want to overwrite your current active partition? (CURRENT=active.img) [y/N] : " -n 1 -r + if [[ ! $REPLY =~ ^[Yy]$ ]] + then + [[ "$0" = "$BASH_SOURCE" ]] && exit 1 || return 1 # handle exits from shell or function but don't exit interactive shell + fi + CURRENT=active.img + echo + fi + + echo "-> Upgrade target: $CURRENT" +} + +find_recovery() { + RECOVERY=$(blkid -L COS_RECOVERY || true) + if [ -z "$RECOVERY" ]; then + echo "COS_RECOVERY partition cannot be found" + exit 1 + fi +} + +# cos-upgrade-image: system/cos +find_upgrade_channel() { + if [ -e "/etc/cos-upgrade-image" ]; then + source /etc/cos-upgrade-image + fi + + if [ -n "$IMAGE" ]; then + UPGRADE_IMAGE=$IMAGE + echo "Upgrading to image $UPGRADE_IMAGE" + fi + + if [ -z "$UPGRADE_IMAGE" ]; then + UPGRADE_IMAGE="system/cos" + fi + + if [ -n "$UPGRADE_RECOVERY" ] && [ $UPGRADE_RECOVERY == true ] && [ -n "$RECOVERY_IMAGE" ]; then + UPGRADE_IMAGE=$RECOVERY_IMAGE + fi +} + +is_squashfs() { + if [ -e "${STATEDIR}/cOS/recovery.squashfs" ]; then + return 0 + else + return 1 + fi +} + +recovery_boot() { + cmdline="$(cat /proc/cmdline)" + if echo $cmdline | grep -q "COS_RECOVERY" || echo $cmdline | grep -q "COS_SYSTEM"; then + return 0 + else + return 1 + fi +} + +prepare_target() { + mkdir -p ${STATEDIR}/cOS || true + rm -rf ${STATEDIR}/cOS/transition.img || true + dd if=/dev/zero of=${STATEDIR}/cOS/transition.img bs=1M count=3240 + mkfs.ext2 ${STATEDIR}/cOS/transition.img + mount -t ext2 -o loop ${STATEDIR}/cOS/transition.img $TARGET +} + +prepare_squashfs_target() { + rm -rf $TARGET || true + TARGET=${STATEDIR}/tmp/target + mkdir -p $TARGET +} + +mount_state() { + STATEDIR=/run/initramfs/state + mkdir -p $STATEDIR + mount ${STATE} ${STATEDIR} +} + +mount_image() { + STATEDIR=/run/initramfs/isoscan + TARGET=/tmp/upgrade + + mkdir -p $TARGET || true + + if [ -d "$STATEDIR" ]; then + if recovery_boot; then + mount_state + else + mount -o remount,rw ${STATE} ${STATEDIR} + fi + else + mount_state + fi + + prepare_target +} + +mount_recovery() { + STATEDIR=/tmp/recovery + TARGET=/tmp/upgrade + + mkdir -p $TARGET || true + mkdir -p $STATEDIR || true + mount $RECOVERY $STATEDIR + if is_squashfs; then + echo "Preparing squashfs target" + prepare_squashfs_target + else + echo "Preparing image target" + prepare_target + fi +} + +mount_persistent() { + mkdir -p ${TARGET}/oem || true + mount ${OEM} ${TARGET}/oem + mkdir -p ${TARGET}/usr/local || true + mount ${PERSISTENT} ${TARGET}/usr/local +} + +upgrade() { + mount_persistent + ensure_dir_structure + + temp_upgrade=$STATEDIR/tmp/upgrade + rm -rf $temp_upgrade || true + mkdir -p $temp_upgrade + + # FIXME: XDG_RUNTIME_DIR is for containerd, by default that points to /run/user/ + # which might not be sufficient to unpack images. Use /usr/local/tmp until we get a separate partition + # for the state + # FIXME: Define default /var/tmp as tmpdir_base in default luet config file + export XDG_RUNTIME_DIR=$temp_upgrade + export TMPDIR=$temp_upgrade + + if [ -n "$CHANNEL_UPGRADES" ] && [ "$CHANNEL_UPGRADES" == true ]; then + if [ -z "$VERIFY" ]; then + args="--plugin image-mtree-check" + fi + luet install $args --system-target $TARGET --system-engine memory -y $UPGRADE_IMAGE + luet cleanup + else + if [ "$DIRECTORY" != true ]; then + args="" + if [ -z "$VERIFY" ]; then + args="--plugin image-mtree-check" + fi + rm -rf /usr/local/tmp/rootfs + luet util unpack $args $UPGRADE_IMAGE /usr/local/tmp/rootfs + rsync -axq --exclude='host' --exclude='mnt' --exclude='proc' --exclude='sys' --exclude='dev' --exclude='tmp' /usr/local/tmp/rootfs/ /tmp/upgrade + else + rsync -axq --exclude='host' --exclude='mnt' --exclude='proc' --exclude='sys' --exclude='dev' --exclude='tmp' ${UPGRADE_IMAGE}/ /tmp/upgrade + fi + rm -rf /usr/local/tmp/rootfs + fi + + SELinux_relabel + chmod 755 /tmp/upgrade + + rm -rf $temp_upgrade + umount $TARGET/oem || true + umount $TARGET/usr/local || true + umount $TARGET || true +} + +SELinux_relabel() +{ + if which setfiles > /dev/null && [ -e ${TARGET}/etc/selinux/targeted/contexts/files/file_contexts ]; then + setfiles -r ${TARGET} ${TARGET}/etc/selinux/targeted/contexts/files/file_contexts ${TARGET} + fi +} + +switch_active() { + if [[ "$CURRENT" == "active.img" ]]; then + mv -f ${STATEDIR}/cOS/$CURRENT ${STATEDIR}/cOS/passive.img + tune2fs -L COS_PASSIVE ${STATEDIR}/cOS/passive.img + fi + + mv -f ${STATEDIR}/cOS/transition.img ${STATEDIR}/cOS/active.img + tune2fs -L COS_ACTIVE ${STATEDIR}/cOS/active.img +} + +switch_recovery() { + if is_squashfs; then + mksquashfs $TARGET ${STATEDIR}/cOS/transition.squashfs -b 1024k -comp xz -Xbcj x86 + mv ${STATEDIR}/cOS/transition.squashfs ${STATEDIR}/cOS/recovery.squashfs + rm -rf $TARGET + else + mv -f ${STATEDIR}/cOS/transition.img ${STATEDIR}/cOS/recovery.img + tune2fs -L COS_SYSTEM ${STATEDIR}/cOS/recovery.img + fi +} + +ensure_dir_structure() { + mkdir ${TARGET}/proc || true + mkdir ${TARGET}/boot || true + mkdir ${TARGET}/dev || true + mkdir ${TARGET}/sys || true + mkdir ${TARGET}/tmp || true +} + +cleanup2() +{ + rm -rf /usr/local/tmp/upgrade || true + mount -o remount,ro ${STATE} ${STATEDIR} || true + if [ -n "${TARGET}" ]; then + umount ${TARGET}/boot/efi || true + umount ${TARGET}/oem || true + umount ${TARGET}/usr/local || true + umount ${TARGET}/ || true + rm -rf ${TARGET} + fi + if [ -n "$UPGRADE_RECOVERY" ] && [ $UPGRADE_RECOVERY == true ]; then + umount ${STATEDIR} || true + fi + if [ "$STATEDIR" == "/run/initramfs/state" ]; then + umount ${STATEDIR} + rm -rf $STATEDIR + fi +} + +cleanup() +{ + EXIT=$? + cleanup2 2>/dev/null || true + return $EXIT +} + +usage() +{ + echo "Usage: cos-upgrade [--no-verify] [--recovery] [--docker-image] IMAGE" + echo "" + echo "Example: cos-upgrade" + echo "" + echo "IMAGE is optional, and upgrades the system to the given specified docker image." + echo "" + echo "" + exit 1 +} + +find_upgrade_channel + +while [ "$#" -gt 0 ]; do + case $1 in + --docker-image) + CHANNEL_UPGRADES=false + ;; + --directory) + CHANNEL_UPGRADES=false + DIRECTORY=true + ;; + --recovery) + UPGRADE_RECOVERY=true + ;; + --no-verify) + VERIFY=false + ;; + -h) + usage + ;; + --help) + usage + ;; + *) + if [ "$#" -gt 2 ]; then + usage + fi + INTERACTIVE=true + UPGRADE_IMAGE=$1 + break + ;; + esac + shift 1 +done + +trap cleanup exit + +if [ -n "$UPGRADE_RECOVERY" ] && [ $UPGRADE_RECOVERY == true ]; then + echo "Upgrading recovery partition.." + + find_partitions + + find_recovery + + mount_recovery + + upgrade + + switch_recovery +else + echo "Upgrading system.." + + find_partitions + + mount_image + + upgrade + + switch_active +fi + +echo "Flush changes to disk" +sync +sync + +if [ -n "$INTERACTIVE" ] && [ $INTERACTIVE == false ]; then + if grep -q 'cos.upgrade.power_off=true' /proc/cmdline; then + poweroff -f + else + echo " * Rebooting system in 5 seconds (CTRL+C to cancel)" + sleep 5 + reboot -f + fi +else + echo "Upgrade done, now you might want to reboot" +fi diff --git a/files/usr/sbin/cos-upgrade.save b/files/usr/sbin/cos-upgrade.save new file mode 100755 index 00000000..5d8a3df6 --- /dev/null +++ b/files/usr/sbin/cos-upgrade.save @@ -0,0 +1,295 @@ +#!/bin/bash +set -e + +CHANNEL_UPGRADES="${CHANNEL_UPGRADES:-true}" + +# 1. Identify active/passive partition +# 2. Install upgrade in passive partition +# 3. Invert partition labels + +find_partitions() { + STATE=$(blkid -L COS_STATE || true) + if [ -z "$STATE" ]; then + echo "State partition cannot be found" + exit 1 + fi + + PERSISTENT=$(blkid -L COS_PERSISTENT || true) + if [ -z "$PERSISTENT" ]; then + echo "Persistent partition cannot be found" + exit 1 + fi + + OEM=$(blkid -L COS_OEM || true) + if [ -z "$OEM" ]; then + echo "OEM partition cannot be found" + exit 1 + fi + + COS_ACTIVE=$(blkid -L COS_ACTIVE || true) + if [ -n "$COS_ACTIVE" ]; then + CURRENT=active.img + fi + + COS_PASSIVE=$(blkid -L COS_PASSIVE || true) + if [ -n "$COS_PASSIVE" ]; then + CURRENT=passive.img + fi + + if [ -z "$CURRENT" ]; then + # We booted from an ISO or some else medium. We assume we want to fixup the current label + read -p "Could not determine current partition. Do you want to overwrite your current active partition? [y/N] : " -n 1 -r + if [[ ! $REPLY =~ ^[Yy]$ ]] + then + [[ "$0" = "$BASH_SOURCE" ]] && exit 1 || return 1 # handle exits from shell or function but don't exit interactive shell + fi + CURRENT=active.img + fi + + echo "-> Booting from: $CURRENT" +} + +find_recovery() { + RECOVERY=$(blkid -L COS_RECOVERY || true) + if [ -z "$RECOVERY" ]; then + echo "COS_RECOVERY partition cannot be found" + exit 1 + fi +} + +# cos-upgrade-image: system/cos +find_upgrade_channel() { + if [ -e "/etc/cos-upgrade-image" ]; then + source /etc/cos-upgrade-image + fi + + if [ -n "$IMAGE" ]; then + UPGRADE_IMAGE=$IMAGE + echo "Upgrading to image $UPGRADE_IMAGE" + fi + + if [ -z "$UPGRADE_IMAGE" ]; then + UPGRADE_IMAGE="system/cos" + fi +} + +prepare_target() { + mkdir -p ${STATEDIR}/cOS || true + rm -rf ${STATEDIR}/cOS/transition.img || true + dd if=/dev/zero of=${STATEDIR}/cOS/transition.img bs=1M count=3240 + mkfs.ext2 ${STATEDIR}/cOS/transition.img + mount -t ext2 -o loop ${STATEDIR}/cOS/transition.img $TARGET +} + +mount_image() { + STATEDIR=/run/initramfs/isoscan + TARGET=/tmp/upgrade + + mkdir -p $TARGET || true + mount -o remount,rw ${STATE} ${STATEDIR} + + prepare_target +} + +mount_recovery() { + STATEDIR=/tmp/recovery + TARGET=/tmp/upgrade + + mkdir -p $TARGET || true + mkdir -p $STATEDIR || true + mount $RECOVERY $STATEDIR + + prepare_target +} + +mount_persistent() { + mkdir -p ${TARGET}/oem || true + mount ${OEM} ${TARGET}/oem + mkdir -p ${TARGET}/usr/local || true + mount ${PERSISTENT} ${TARGET}/usr/local +} + +upgrade() { + mount_persistent + ensure_dir_structure + + mkdir -p /usr/local/tmp/upgrade + + # FIXME: XDG_RUNTIME_DIR is for containerd, by default that points to /run/user/ + # which might not be sufficient to unpack images. Use /usr/local/tmp until we get a separate partition + # for the state + # FIXME: Define default /var/tmp as tmpdir_base in default luet config file + export XDG_RUNTIME_DIR=/usr/local/tmp/upgrade + export TMPDIR=/usr/local/tmp/upgrade + export HOME=/tmp # Docker Content Trust data is stored in $HOME/.docker. We don't need those to persist + + if [ -n "$CHANNEL_UPGRADES" ] && [ "$CHANNEL_UPGRADES" == true ]; then + if [ -z "$VERIFY" ]; then + args="--plugin image-mtree-check" + fi + luet install $args --system-target /tmp/upgrade --system-engine memory -y $UPGRADE_IMAGE + luet cleanup + else + if [ "$DIRECTORY" != true ]; then + args="" + if [ -z "$VERIFY" ]; then + args="--verify" + fi + rm -rf /usr/local/tmp/rootfs + luet util unpack $args $UPGRADE_IMAGE /usr/local/tmp/rootfs + rsync -axq --exclude='host' --exclude='mnt' --exclude='proc' --exclude='sys' --exclude='dev' --exclude='tmp' /usr/local/tmp/rootfs/ /tmp/upgrade + else + rsync -axq --exclude='host' --exclude='mnt' --exclude='proc' --exclude='sys' --exclude='dev' --exclude='tmp' ${UPGRADE_IMAGE}/ /tmp/upgrade + fi + rm -rf /usr/local/tmp/rootfs + fi + + SELinux_relabel + chmod 755 /tmp/upgrade + + rm -rf /usr/local/tmp/upgrade + umount $TARGET/oem + umount $TARGET/usr/local + umount $TARGET +} + +SELinux_relabel() +{ + if which setfiles > /dev/null && [ -e ${TARGET}/etc/selinux/targeted/contexts/files/file_contexts ]; then + setfiles -r ${TARGET} ${TARGET}/etc/selinux/targeted/contexts/files/file_contexts ${TARGET} + fi +} + +switch_active() { + if [[ "$CURRENT" == "active.img" ]]; then + mv -f ${STATEDIR}/cOS/$CURRENT ${STATEDIR}/cOS/passive.img + tune2fs -L COS_PASSIVE ${STATEDIR}/cOS/passive.img + fi + + mv -f ${STATEDIR}/cOS/transition.img ${STATEDIR}/cOS/active.img + tune2fs -L COS_ACTIVE ${STATEDIR}/cOS/active.img +} + +switch_recovery() { + mv -f ${STATEDIR}/cOS/transition.img ${STATEDIR}/cOS/recovery.img + tune2fs -L COS_SYSTEM ${STATEDIR}/cOS/recovery.img +} + +ensure_dir_structure() { + mkdir ${TARGET}/proc || true + mkdir ${TARGET}/boot || true + mkdir ${TARGET}/dev || true + mkdir ${TARGET}/sys || true + mkdir ${TARGET}/tmp || true +} + +cleanup2() +{ + rm -rf /usr/local/tmp/upgrade || true + mount -o remount,ro ${STATE} ${STATEDIR} || true + if [ -n "${TARGET}" ]; then + umount ${TARGET}/boot/efi || true + umount ${TARGET}/oem || true + umount ${TARGET}/usr/local || true + umount ${TARGET}/ || true + fi + if [ -n "$UPGRADE_RECOVERY" ] && [ $UPGRADE_RECOVERY == true ]; then + umount ${STATEDIR} || true + fi +} + +cleanup() +{ + EXIT=$? + cleanup2 2>/dev/null || true + return $EXIT +} + +usage() +{ + echo "Usage: cos-upgrade [--verify] [--recovery] [--docker-image] IMAGE" + echo "" + echo "Example: cos-upgrade" + echo "" + echo "IMAGE is optional, and upgrades the system to the given specified docker image." + echo "" + echo "" + exit 1 +} + +find_upgrade_channel + +while [ "$#" -gt 0 ]; do + case $1 in + --docker-image) + CHANNEL_UPGRADES=false + ;; + --directory) + CHANNEL_UPGRADES=false + DIRECTORY=true + ;; + --recovery) + UPGRADE_RECOVERY=true + ;; + --no-verify) + VERIFY=false + ;; + -h) + usage + ;; + --help) + usage + ;; + *) + if [ "$#" -gt 2 ]; then + usage + fi + INTERACTIVE=true + UPGRADE_IMAGE=$1 + break + ;; + esac + shift 1 +done + +trap cleanup exit + +if [ -n "$UPGRADE_RECOVERY" ] && [ $UPGRADE_RECOVERY == true ]; then + echo "Upgrading recovery partition.." + + find_partitions + + find_recovery + + mount_recovery + + upgrade + + switch_recovery +else + echo "Upgrading system.." + + find_partitions + + mount_image + + upgrade + + switch_active +fi + +echo "Flush changes to disk" +sync +sync + +if [ -n "$INTERACTIVE" ] && [ $INTERACTIVE == false ]; then + if grep -q 'cos.upgrade.power_off=true' /proc/cmdline; then + poweroff -f + else + echo " * Rebooting system in 5 seconds (CTRL+C to cancel)" + sleep 5 + reboot -f + fi +else + echo "Upgrade done, now you might want to reboot" +fi diff --git a/files/usr/sbin/suc-upgrade b/files/usr/sbin/suc-upgrade new file mode 100755 index 00000000..c61fe43d --- /dev/null +++ b/files/usr/sbin/suc-upgrade @@ -0,0 +1,15 @@ +#!/bin/bash +set -x -e + +if [ "$FORCE" != "true" ]; then + if diff /etc/os-release /host/etc/os-release >/dev/null; then + echo Update to date with + cat /etc/os-release + exit 0 + fi +fi +mount --rbind /host/dev /dev +mount --rbind /host/run /run +bash -x cos-upgrade --directory / +nsenter -i -m -t 1 -- reboot +exit 1 diff --git a/files/usr/share/rancher/rancherd/config.yaml.d/50-defaults.yaml b/files/usr/share/rancher/rancherd/config.yaml.d/50-defaults.yaml new file mode 100644 index 00000000..3ad2a547 --- /dev/null +++ b/files/usr/share/rancher/rancherd/config.yaml.d/50-defaults.yaml @@ -0,0 +1,21 @@ +rancherValues: + rancherImagePullPolicy: Always + rancherImage: ibuildthecloud/rancher + rancherImageTag: dev + extraEnv: + - name: CATTLE_SYSTEM_AGENT_UPGRADE_IMAGE + value: ibuildthecloud/suc +rancherInstallerImage: ibuildthecloud/system-agent-installer-rancher:dev +bootstrapResources: +- kind: Deployment + apiVersion: apps/v1 + metadata: + name: rancher-webhook + namespace: cattle-system + spec: + template: + spec: + containers: + - name: rancher-webhook + image: ibuildthecloud/rancher-webhook:dev + imagePullPolicy: Always diff --git a/tools/iso/iso.yaml b/tools/iso/iso.yaml new file mode 100644 index 00000000..cc8e579b --- /dev/null +++ b/tools/iso/iso.yaml @@ -0,0 +1,26 @@ +packages: + rootfs: + - iso/rootfs + uefi: + - live/systemd-boot + - live/boot + isoimage: + - live/syslinux + - live/boot + +initramfs: + kernel_file: "vmlinuz" + rootfs_file: "initrd" + +overlay: true +image_prefix: "distro" +image_date: true +label: "COS_LIVE" + +luet: + repositories: + - name: cOS + enable: true + urls: + - quay.io/costoolkit/releases-opensuse + type: docker diff --git a/tools/iso/package/build.yaml b/tools/iso/package/build.yaml new file mode 100644 index 00000000..46232282 --- /dev/null +++ b/tools/iso/package/build.yaml @@ -0,0 +1,2 @@ +image: "{{.Values.image}}" +unpack: true diff --git a/tools/iso/package/definition.yaml b/tools/iso/package/definition.yaml new file mode 100644 index 00000000..e93af32e --- /dev/null +++ b/tools/iso/package/definition.yaml @@ -0,0 +1,3 @@ +name: "rootfs" +category: "iso" +version: "0" diff --git a/tools/iso/values.yaml.tmpl b/tools/iso/values.yaml.tmpl new file mode 100644 index 00000000..a8d8f3ee --- /dev/null +++ b/tools/iso/values.yaml.tmpl @@ -0,0 +1 @@ +image: "${IMAGE}" diff --git a/tools/usr/bin/makeiso b/tools/usr/bin/makeiso new file mode 100755 index 00000000..3a1cfd30 --- /dev/null +++ b/tools/usr/bin/makeiso @@ -0,0 +1,20 @@ +#!/bin/bash + +IMAGE=$1 + +if [ -z "$IMAGE" ]; then + echo "Image name is required as the first argument" + echo + echo Usage: $0 [DOCKER_IMAGE] + exit 1 +fi + +cd /iso +cat > values.yaml << EOF +image: "$IMAGE" +EOF + +luet build --values values.yaml iso/rootfs +luet create-repo +luet-makeiso iso.yaml --local /iso/build +cp distro*iso /output.iso