From 52b39e632dc877ba0b5680ed6c1c5ba4c9043c3a Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Wed, 19 May 2021 17:12:56 -0400 Subject: [PATCH] Draft CoreOS support Preliminary work toward supporting CoreOS --- .../systemd/system/confluent-rootfs.service | 1 + .../opt/confluent/bin/initconfluent.sh | 104 ++++++++++++++++++ .../lib/dracut/hooks/cmdline/01-confluent.sh | 10 ++ .../dracut/hooks/pre-pivot/01-confluent.sh | 10 ++ .../systemd/system/confluent-rootfs.service | 19 ++++ .../rhcos/profiles/default/initprofile.sh | 5 + .../rhcos/profiles/default/profile.yaml | 2 + confluent_server/confluent/osimage.py | 16 +++ 8 files changed, 167 insertions(+) create mode 120000 confluent_osdeploy/rhcos/initramfs/etc/systemd/system/confluent-rootfs.service create mode 100644 confluent_osdeploy/rhcos/initramfs/opt/confluent/bin/initconfluent.sh create mode 100644 confluent_osdeploy/rhcos/initramfs/usr/lib/dracut/hooks/cmdline/01-confluent.sh create mode 100644 confluent_osdeploy/rhcos/initramfs/usr/lib/dracut/hooks/pre-pivot/01-confluent.sh create mode 100644 confluent_osdeploy/rhcos/initramfs/usr/lib/systemd/system/confluent-rootfs.service create mode 100644 confluent_osdeploy/rhcos/profiles/default/initprofile.sh create mode 100644 confluent_osdeploy/rhcos/profiles/default/profile.yaml diff --git a/confluent_osdeploy/rhcos/initramfs/etc/systemd/system/confluent-rootfs.service b/confluent_osdeploy/rhcos/initramfs/etc/systemd/system/confluent-rootfs.service new file mode 120000 index 00000000..4391533f --- /dev/null +++ b/confluent_osdeploy/rhcos/initramfs/etc/systemd/system/confluent-rootfs.service @@ -0,0 +1 @@ +/usr/lib/systemd/system/confluent-rootfs.service \ No newline at end of file diff --git a/confluent_osdeploy/rhcos/initramfs/opt/confluent/bin/initconfluent.sh b/confluent_osdeploy/rhcos/initramfs/opt/confluent/bin/initconfluent.sh new file mode 100644 index 00000000..d22c38ba --- /dev/null +++ b/confluent_osdeploy/rhcos/initramfs/opt/confluent/bin/initconfluent.sh @@ -0,0 +1,104 @@ +#!/bin/bash +TRIES=0 +oum=$(umask) +umask 0077 +mkdir -p /etc/confluent +echo -n > /etc/confluent/confluent.info +umask $oum +cd /sys/class/net +while ! grep ^EXTMGRINFO: /etc/confluent/confluent.info | awk -F'|' '{print $3}' | grep 1 >& /dev/null && [ "$TRIES" -lt 60 ]; do + TRIES=$((TRIES + 1)) + for currif in *; do + ip link set $currif up + done + /opt/confluent/bin/copernicus -t > /etc/confluent/confluent.info +done +cd / +grep ^EXTMGRINFO: /etc/confluent/confluent.info || return 0 # Do absolutely nothing if no data at all yet +echo -n "" > /tmp/confluent.initq +# restart cmdline +echo -n "" > /etc/cmdline.d/01-confluent.conf +nodename=$(grep ^NODENAME /etc/confluent/confluent.info|awk '{print $2}') +cat /tls/*.pem > /etc/confluent/ca.pem +confluent_mgr=$(grep ^MANAGER: /etc/confluent/confluent.info|head -n 1 | awk '{print $2}') +if [[ $confluent_mgr == *%* ]]; then + echo $confluent_mgr | awk -F% '{print $2}' > /tmp/confluent.ifidx + ifidx=$(cat /tmp/confluent.ifidx) + ifname=$(ip link |grep ^$ifidx:|awk '{print $2}') + ifname=${ifname%:} +fi +needseal=1 +oldumask=$(umask) +umask 0077 +while [ -z "$confluent_apikey" ]; do + /opt/confluent/bin/clortho $nodename $confluent_mgr > /etc/confluent/confluent.apikey + if grep ^SEALED: /etc/confluent/confluent.apikey > /dev/null; then + needseal=0 + sed -e s/^SEALED:// /etc/confluent/confluent.apikey | clevis-decrypt-tpm2 > /etc/confluent/confluent.apikey.decrypt + mv /etc/confluent/confluent.apikey.decrypt /etc/confluent/confluent.apikey + fi + confluent_apikey=$(cat /etc/confluent/confluent.apikey) + if [ -z "$confluent_apikey" ]; then + echo "Unable to acquire node api key, no TPM2 sealed nor fresh token available, retrying..." + sleep 10 + fi +done +if [[ $confluent_mgr == *:* ]]; then + confluent_mgr="[$confluent_mgr]" +fi +if [ $needseal == 1 ]; then + sealed=$(echo $confluent_apikey | clevis-encrypt-tpm2 {}) + if [ ! -z "$sealed" ]; then + curl -sf -H "CONFLUENT_NODENAME: $nodename" -H "CONFLUENT_APIKEY: $confluent_apikey" -d $sealed https://$confluent_mgr/confluent-api/self/saveapikey + fi +fi +curl -sf -H "CONFLUENT_NODENAME: $nodename" -H "CONFLUENT_APIKEY: $confluent_apikey" https://$confluent_mgr/confluent-api/self/deploycfg > /etc/confluent/confluent.deploycfg +umask $oldumask +autoconfigmethod=$(grep ipv4_method /etc/confluent/confluent.deploycfg) +autoconfigmethod=${autoconfigmethod#ipv4_method: } +confluent_profile=$(grep ^profile: /etc/confluent/confluent.deploycfg) +confluent_profile=${confluent_profile#profile: } + +if [ "$autoconfigmethod" = "dhcp" ]; then + echo ip=$ifname:dhcp >> /etc/cmdline.d/01-confluent.conf +else + v4addr=$(grep ^ipv4_address: /etc/confluent/confluent.deploycfg) + v4addr=${v4addr#ipv4_address: } + v4gw=$(grep ^ipv4_gateway: /etc/confluent/confluent.deploycfg) + v4gw=${v4gw#ipv4_gateway: } + if [ "$v4gw" = "null" ]; then + v4gw="" + fi + v4nm=$(grep ipv4_netmask: /etc/confluent/confluent.deploycfg) + v4nm=${v4nm#ipv4_netmask: } + echo ip=$v4addr::$v4gw:$v4nm:$hostname:$ifname:none >> /etc/cmdline.d/01-confluent.conf +fi +nameserversec=0 +while read -r entry; do + if [ $nameserversec = 1 ]; then + if [[ $entry == "-"* ]] && [[ $entry != "- ''" ]]; then + echo nameserver=${entry#- } >> /etc/cmdline.d/01-confluent.conf + continue + fi + fi + nameserversec=0 + if [ "${entry%:*}" = "nameservers" ]; then + nameserversec=1 + continue + fi +done < /etc/confluent/confluent.deploycfg + +if [ -e /lib/nm-lib.sh ]; then + . /lib/nm-lib.sh + nm_generate_connections + if [[ "$ifname" == ib* ]]; then + sed -i s/type=ethernet/type=infiniband/ /run/NetworkManager/system-connections/$ifname.nmconnection + if ! grep '\[infiniband\]' /run/NetworkManager/system-connections/$ifname.nmconnection > /dev/null; then + echo >> /run/NetworkManager/system-connections/$ifname.nmconnection + echo '[infiniband]' >> /run/NetworkManager/system-connections/$ifname.nmconnection + echo transport-mode=datagram >> /run/NetworkManager/system-connections/$ifname.nmconnection + fi + fi +fi + +curl -sf https://$confluent_mgr/confluent-public/os/$confluent_profile/rootfs.img | rdcore stream-hash /etc/coreos-live-want-rootfs | bsdtar -xf - -C / diff --git a/confluent_osdeploy/rhcos/initramfs/usr/lib/dracut/hooks/cmdline/01-confluent.sh b/confluent_osdeploy/rhcos/initramfs/usr/lib/dracut/hooks/cmdline/01-confluent.sh new file mode 100644 index 00000000..445c68ea --- /dev/null +++ b/confluent_osdeploy/rhcos/initramfs/usr/lib/dracut/hooks/cmdline/01-confluent.sh @@ -0,0 +1,10 @@ +cat /tls/*.0 >> /etc/pki/tls/certs/ca-bundle.crt +if ! grep console= /proc/cmdline >& /dev/null; then + autocons=$(/opt/confluent/bin/autocons) + if [ -n "$autocons" ]; then + echo console=$autocons |sed -e 's!/dev/!!' >> /tmp/01-autocons.conf + autocons=${autocons%,*} + echo $autocons > /tmp/01-autocons.devnode + echo "Detected firmware specified console at $(cat /tmp/01-autocons.conf)" > $autocons + fi +fi diff --git a/confluent_osdeploy/rhcos/initramfs/usr/lib/dracut/hooks/pre-pivot/01-confluent.sh b/confluent_osdeploy/rhcos/initramfs/usr/lib/dracut/hooks/pre-pivot/01-confluent.sh new file mode 100644 index 00000000..855efc8c --- /dev/null +++ b/confluent_osdeploy/rhcos/initramfs/usr/lib/dracut/hooks/pre-pivot/01-confluent.sh @@ -0,0 +1,10 @@ +#!/bin/sh +rootpassword=$(grep ^rootpassword: /etc/confluent/confluent.deploycfg) +rootpassword=${rootpassword#rootpassword: } +if [ "$rootpassword" = "null" ]; then + rootpassword="" +fi + +if [ ! -z "$rootpassword" ]; then + sed -i "s@root:[^:]*:@root:$rootpassword:@" /sysroot/etc/shadow +fi diff --git a/confluent_osdeploy/rhcos/initramfs/usr/lib/systemd/system/confluent-rootfs.service b/confluent_osdeploy/rhcos/initramfs/usr/lib/systemd/system/confluent-rootfs.service new file mode 100644 index 00000000..6e98786c --- /dev/null +++ b/confluent_osdeploy/rhcos/initramfs/usr/lib/systemd/system/confluent-rootfs.service @@ -0,0 +1,19 @@ +[Unit] +Description=Confluent initialization +DefaultDependencies=false + +After=basic.target +# Network is enabled here +After=dracut-initqueue.service +Before=coreos-livepxe-rootfs.service + + +# If we fail, the boot will fail. Be explicit about it. +OnFailure=emergency.target +OnFailureJobMode=isolate + +[Service] +Type=oneshot +RemainAfterExit=yes +ExecStart=/opt/confluent/bin/initconfluent.sh + diff --git a/confluent_osdeploy/rhcos/profiles/default/initprofile.sh b/confluent_osdeploy/rhcos/profiles/default/initprofile.sh new file mode 100644 index 00000000..d48efa79 --- /dev/null +++ b/confluent_osdeploy/rhcos/profiles/default/initprofile.sh @@ -0,0 +1,5 @@ +#!/bin/sh +ln -s $1/images/pxeboot/vmlinuz $2/boot/kernel && \ +ln -s $1/images/pxeboot/initrd.img $2/boot/initramfs/distribution && \ +mkdir -p $2/boot/efi/boot/ && \ +ln -s $1/images/pxeboot/rootfs.img $2/ diff --git a/confluent_osdeploy/rhcos/profiles/default/profile.yaml b/confluent_osdeploy/rhcos/profiles/default/profile.yaml new file mode 100644 index 00000000..caa81bef --- /dev/null +++ b/confluent_osdeploy/rhcos/profiles/default/profile.yaml @@ -0,0 +1,2 @@ +label: RedHat CoreOS %%VERSION%% %%ARCH%% (Default Profile) +kernelargs: quiet diff --git a/confluent_server/confluent/osimage.py b/confluent_server/confluent/osimage.py index 52efacbb..0f2075d8 100644 --- a/confluent_server/confluent/osimage.py +++ b/confluent_server/confluent/osimage.py @@ -23,6 +23,7 @@ READFILES = set([ 'media.2/products', '.DISCINFO', '.discinfo', + 'zipl.prm', ]) HEADERSUMS = set([b'\x85\xeddW\x86\xc5\xbdhx\xbe\x81\x18X\x1e\xb4O\x14\x9d\x11\xb7C8\x9b\x97R\x0c-\xb8Ht\xcb\xb3']) @@ -424,6 +425,21 @@ def _priv_check_oraclelinux(isoinfo): return {'name': 'oraclelinux-{0}-{1}'.format(ver, arch), 'method': EXTRACT, 'category': 'el{0}'.format(major)} + +def check_rhcos(isoinfo): + arch = 'x86_64' # TODO: would check magic of vmlinuz to see which arch + if 'zipl.prm' in isoinfo[1]: + prodinfo = isoinfo[1]['zipl.prm'] + if not isinstance(prodinfo, str): + prodinfo = prodinfo.decode('utf8') + for inf in prodinfo.split(): + if inf.startswith('coreos.liveiso=rhcos-'): + _, ver, _ = inf.split('-') + return {'name': 'rhcos-{0}-{1}'.format(ver, arch), + 'method': EXTRACT, 'category': 'rhcos'} + + + def check_rhel(isoinfo): ver = None arch = None