1
0
mirror of https://gitlab.alpinelinux.org/alpine/cloud/tiny-cloud.git synced 2025-12-15 11:22:43 +03:00

cloud via cmdline / move autodetect

This commit is contained in:
Jake Buchholz Göktürk 2024-11-14 01:22:48 +00:00
parent 0548b418ec
commit 3ea8b15de0
10 changed files with 100 additions and 74 deletions

View File

@ -84,7 +84,7 @@ _imds_ssh_keys() {
done | sort -u done | sort -u
} }
_imds_nic_index() { cat "/sys/class/net/$1/address"; } _imds_nic_index() { cat "$SYS/class/net/$1/address"; }
### load cloud-specific variables and functions ### load cloud-specific variables and functions

View File

@ -4,8 +4,7 @@
# vim:set filetype=sh: # vim:set filetype=sh:
# shellcheck shell=sh # shellcheck shell=sh
grep -w 'ds=nocloud' "$ROOT"/proc/cmdline 2>/dev/null \ # kernel cmdline & DMI product serial are checked in common
|| grep -w "^ds=nocloud" "$ROOT"/sys/class/dmi/id/product_serial 2>/dev/null \ findfs LABEL=cidata >/dev/null 2>&1 \
|| findfs LABEL=cidata >/dev/null 2>&1 \
|| findfs LABEL=CIDATA >/dev/null 2>&1 \ || findfs LABEL=CIDATA >/dev/null 2>&1 \
&& echo "10 nocloud" && echo "10 nocloud"

View File

@ -8,8 +8,8 @@ is_nocloud_loaded() { [ -f "$TINY_CLOUD_VAR/.nocloud_loaded" ]; }
_load_nocloud_cmdline() { _load_nocloud_cmdline() {
local kopt kv k v data local kopt kv k v data
for kopt in $(cat "$ROOT/proc/cmdline" 2>/dev/null) \ for kopt in $(cat "$PROC/cmdline" 2>/dev/null) \
$(grep '^ds=nocloud' "$ROOT"/sys/class/dmi/id/product_serial 2>/dev/null) ; do $(grep '^ds=nocloud' "$SYS"/class/dmi/id/product_serial 2>/dev/null) ; do
echo "$kopt" | grep -qE '(^|=)ds=nocloud(-net)?;' || continue echo "$kopt" | grep -qE '(^|=)ds=nocloud(-net)?;' || continue
for kv in $(echo "${kopt#*;}" | tr \; ' '); do for kv in $(echo "${kopt#*;}" | tr \; ' '); do
k=$(echo "$kv" | cut -d= -f1) k=$(echo "$kv" | cut -d= -f1)
@ -88,7 +88,6 @@ load_nocloud() {
} }
_imds() { _imds() {
mkdir -p "$TINY_CLOUD_VAR"
local file="$TINY_CLOUD_VAR/$(echo "$1" | cut -d/ -f1)" local file="$TINY_CLOUD_VAR/$(echo "$1" | cut -d/ -f1)"
local keypath="$(echo "$1" | cut -d/ -f2- | tr / ' ')" local keypath="$(echo "$1" | cut -d/ -f2- | tr / ' ')"

View File

@ -9,7 +9,7 @@ set_resolv_conf() {
local nameservers="$(imds meta-data/resolv_conf/nameservers)" local nameservers="$(imds meta-data/resolv_conf/nameservers)"
for i in $nameservers; do for i in $nameservers; do
local server="$(imds meta-data/resolv_conf/nameservers/$i)" local server="$(imds meta-data/resolv_conf/nameservers/$i)"
add_once "$ROOT"/etc/resolv.conf "nameserver $server" add_once "$ETC"/resolv.conf "nameserver $server"
done done
} }
@ -22,8 +22,8 @@ want_ephemeral_network() {
if has_ipv4_address; then if has_ipv4_address; then
return 1 return 1
fi fi
for i in $(cat "$ROOT"/proc/cmdline 2>/dev/null) \ for i in $(cat "$PROC"/cmdline 2>/dev/null) \
$(cat "$ROOT"/sys/class/dmi/id/product_serial 2>/dev/null); do $(cat "$SYS"/class/dmi/id/product_serial 2>/dev/null); do
case "$i" in case "$i" in
"ds=nocloud;"*) "ds=nocloud;"*)
for kv in $(echo "${i#*;}" | tr \; ' '); do for kv in $(echo "${i#*;}" | tr \; ' '); do
@ -45,13 +45,13 @@ want_ephemeral_network() {
init__set_network_interfaces() { init__set_network_interfaces() {
local interfaces="$(imds meta-data/network-interfaces)" local interfaces="$(imds meta-data/network-interfaces)"
mkdir -p "$ROOT"/etc/network mkdir -p "$ETC"/network
if [ -n "$interfaces" ]; then if [ -n "$interfaces" ]; then
printf "%s\n" "$interfaces" > "$ROOT"/etc/network/interfaces printf "%s\n" "$interfaces" > "$ETC"/network/interfaces
elif ! [ -f "$ROOT"/etc/network/interfaces ]; then elif ! [ -f "$ETC"/network/interfaces ]; then
init__set_default_interfaces init__set_default_interfaces
fi fi
if ! grep -q dhcp "$ROOT"/etc/network/interfaces; then if ! grep -q dhcp "$ETC"/network/interfaces; then
set_resolv_conf set_resolv_conf
fi fi
} }

View File

@ -29,7 +29,7 @@ _imds_ssh_keys() { _imds "$IMDS_SSH_KEYS"; }
_imds_nic_index() { _imds_nic_index() {
local m n=0 local m n=0
local mac=$(cat "/sys/class/net/$1/mac") local mac=$(cat "$SYS/class/net/$1/mac")
while m=$(imds "$IMDS_NICS/$n/mac" | tr A-F a-f); do while m=$(imds "$IMDS_NICS/$n/mac" | tr A-F a-f); do
[ "$m" = "$mac" ] && echo $n; return 0 [ "$m" = "$mac" ] && echo $n; return 0
done done

View File

@ -3,11 +3,58 @@
# shellcheck shell=sh # shellcheck shell=sh
# set defaults # set defaults
[ -f "$ROOT/etc/tiny-cloud.conf" ] && . "$ROOT/etc/tiny-cloud.conf" : "${ETC:=$ROOT/etc}"
: "${PROC:=$ROOT/proc}"
: "${SYS:=$ROOT/sys}"
[ -f "$ETC/tiny-cloud.conf" ] && . "$ETC/tiny-cloud.conf"
: "${CLOUD:=auto}" : "${CLOUD:=auto}"
: "${CLOUD_USER:=alpine}" : "${CLOUD_USER:=alpine}"
: "${TINY_CLOUD_LOGS:=$ROOT/var/log}" mkdir -p "${TINY_CLOUD_LOGS:=$ROOT/var/log}"
: "${TINY_CLOUD_VAR:=$ROOT/var/lib/cloud}" mkdir -p "${TINY_CLOUD_VAR:=$ROOT/var/lib/cloud}"
lower() { tr 'A-Z' 'a-z'; }
line_has_k() {
# <key> [<file>] - line(s) in stdin/<file> have <key> defined?
cat "${2:--}" 2>/dev/null | xargs -n1 | cut -d= -f1 | grep -q "^$1$"
}
line_kval() {
# <key> [<file>] [<chars>] - <key> value(s) from stdin/<file> line(s)
# replace output <chars> with spaces (suitable for "sub-kv" situations)
cat "${2:--}" 2>/dev/null | xargs -n1 | grep "^$1=" | cut -d= -f2- | paste -sd' ' | tr "$3" ' '
}
if [ "$CLOUD" = "auto" ]; then
# previously detected?
CLOUD=$(cat "$TINY_CLOUD_VAR"/.autodetect 2>/dev/null) || {
# try kernel cmdline & DMI product serial
for F in "$PROC/cmdline" "$SYS/class/dmi/id/product_serial"; do
CLOUD=$(line_kval tinycloud "$F" : | line_kval cloud)
[ -z "$CLOUD" ] && CLOUD=$(line_kval ds "$F" ';' | cut -d' ' -f1 | lower)
[ -n "$CLOUD" ] && break
done
if [ -n "$CLOUD" ]; then
# convert cloud-init cloud names
case "$CLOUD" in
ec2) CLOUD=aws;;
gce) CLOUD=gcp;;
nocloud-net) CLOUD=nocloud;;
oracle) CLOUD=oci;;
esac
else
# try all the autodetects, sorted by confidence...
CLOUD=$(
for i in "$LIBDIR"/tiny-cloud/cloud/*/autodetect; do
[ -x "$i" ] && "$i"
done | sort -n | cut -d' ' -f2 | head -n 1
)
fi
if [ -z "$CLOUD" ] || [ ! -d "$LIBDIR/tiny-cloud/cloud/$CLOUD" ]; then
CLOUD=unknown
else
printf "%s\n" "$CLOUD" > "$TINY_CLOUD_VAR"/.autodetect
fi
}
fi
log() { log() {
local facility="local7" local facility="local7"

View File

@ -32,31 +32,12 @@ DEFAULT_ACTIONS_FINAL=""
: "${INIT_ACTIONS_MAIN=$DEFAULT_ACTIONS_MAIN}" : "${INIT_ACTIONS_MAIN=$DEFAULT_ACTIONS_MAIN}"
: "${INIT_ACTIONS_FINAL=$DEFAULT_ACTIONS_FINAL}" : "${INIT_ACTIONS_FINAL=$DEFAULT_ACTIONS_FINAL}"
# try to ensure existence of output directories, but otherwise don't panic
[ ! -d "$TINY_CLOUD_LOGS" ] && mkdir -p "$TINY_CLOUD_LOGS" || true
[ ! -d "$TINY_CLOUD_VAR" ] && mkdir -p "$TINY_CLOUD_VAR" || true
# autodetect cloud
if [ "$CLOUD" = "auto" ]; then
CLOUD=$(cat "$TINY_CLOUD_VAR"/.autodetect 2>/dev/null) || {
CLOUD=$(
for i in "$LIBDIR"/tiny-cloud/cloud/*/autodetect; do
if [ -f "$i" ]; then
"$i"
fi
done | sort -n | cut -d' ' -f2 | head -n 1
)
: ${CLOUD:=unknown}
printf "%s\n" "$CLOUD" > "$TINY_CLOUD_VAR"/.autodetect
}
fi
### standard boot phase functions... ### standard boot phase functions...
init__expand_root() { init__expand_root() {
local dev=$(awk '$2 == "/" {print $1}' "$ROOT"/proc/mounts 2>/dev/null) local dev=$(awk '$2 == "/" {print $1}' "$PROC"/mounts 2>/dev/null)
local filesystem=$(awk '$2 == "/" {print $3}' "$ROOT"/proc/mounts 2>/dev/null) local filesystem=$(awk '$2 == "/" {print $3}' "$PROC"/mounts 2>/dev/null)
local partition=$(cat "$ROOT/sys/class/block/${dev#/dev/}/partition" 2>/dev/null) local partition=$(cat "$SYS/class/block/${dev#/dev/}/partition" 2>/dev/null)
# only support ext2/ext3/ext4 for now # only support ext2/ext3/ext4 for now
case "$filesystem" in case "$filesystem" in
@ -66,7 +47,7 @@ init__expand_root() {
if [ -n "$partition" ]; then if [ -n "$partition" ]; then
# it's a partition, resize it # it's a partition, resize it
local volume=$(readlink -f "$ROOT/sys/class/block/${dev#/dev/}/..") local volume=$(readlink -f "$SYS/class/block/${dev#/dev/}/..")
volume="/dev/${volume##*/}" volume="/dev/${volume##*/}"
echo ", +" | $MOCK sfdisk -q --no-reread -N "$partition" "$volume" echo ", +" | $MOCK sfdisk -q --no-reread -N "$partition" "$volume"
$MOCK partx -u "$volume" $MOCK partx -u "$volume"
@ -79,7 +60,7 @@ init__expand_root() {
# collect ethernet interfaces, sorted by index # collect ethernet interfaces, sorted by index
ethernets() { ethernets() {
for i in "$ROOT/sys/class/net/"*; do for i in "$SYS/class/net/"*; do
local iface="${i##*/}" local iface="${i##*/}"
case "$iface" in case "$iface" in
eth*) echo "$(cat "$i/ifindex") $iface";; eth*) echo "$(cat "$i/ifindex") $iface";;
@ -93,7 +74,7 @@ find_first_interface_up() {
[ $# -eq 0 ] && return [ $# -eq 0 ] && return
while [ $n -le ${TINY_CLOUD_LINK_WAIT_MAX:-10} ]; do while [ $n -le ${TINY_CLOUD_LINK_WAIT_MAX:-10} ]; do
for i in "$@"; do for i in "$@"; do
if [ "$(cat "$ROOT/sys/class/net/$i/operstate")" = "up" ]; then if [ "$(cat "$SYS/class/net/$i/operstate")" = "up" ]; then
echo "$i" echo "$i"
return return
fi fi
@ -148,16 +129,16 @@ init__set_ephemeral_network() {
} }
init__set_default_interfaces() { init__set_default_interfaces() {
if [ -f "$ROOT"/etc/network/interfaces ]; then if [ -f "$ETC"/network/interfaces ]; then
log -i -t "$phase" info "$ACTION: already set up" log -i -t "$phase" info "$ACTION: already set up"
return return
fi fi
mkdir -p "$ROOT/etc/network" mkdir -p "$ETC/network"
printf "%s\n%s\n\n" \ printf "%s\n%s\n\n" \
"auto lo" \ "auto lo" \
"iface lo inet loopback" \ "iface lo inet loopback" \
> "$ROOT/etc/network/interfaces" > "$ETC/network/interfaces"
local iface="$(auto_detect_ethernet_interface)" local iface="$(auto_detect_ethernet_interface)"
if [ -z "$iface" ]; then if [ -z "$iface" ]; then
@ -167,7 +148,7 @@ init__set_default_interfaces() {
printf "%s\n%s\n\t%s\n\n" \ printf "%s\n%s\n\t%s\n\n" \
"auto $iface" \ "auto $iface" \
"iface $iface" \ "iface $iface" \
"use dhcp" >> "$ROOT/etc/network/interfaces" "use dhcp" >> "$ETC/network/interfaces"
} }
init__create_default_user() { init__create_default_user() {
@ -188,12 +169,12 @@ init__create_default_user() {
echo "$user:*" | $MOCK chpasswd -e echo "$user:*" | $MOCK chpasswd -e
# setup sudo and/or doas # setup sudo and/or doas
if [ -d "$ROOT/etc/sudoers.d" ]; then if [ -d "$ETC/sudoers.d" ]; then
echo '%wheel ALL=(ALL) NOPASSWD: ALL' > "$ROOT/etc/sudoers.d/wheel" echo '%wheel ALL=(ALL) NOPASSWD: ALL' > "$ETC/sudoers.d/wheel"
fi fi
if [ -d "$ROOT/etc/doas.d" ]; then if [ -d "$ETC/doas.d" ]; then
echo 'permit nopass :wheel' > "$TARGET/etc/doas.d/wheel.conf" echo 'permit nopass :wheel' > "$TARGET/etc/doas.d/wheel.conf"
elif [ -f "$ROOT/etc/doas.conf" ]; then elif [ -f "$ETC/doas.conf" ]; then
add_once "$TARGET/etc/doas.conf" "permit nopass :wheel" add_once "$TARGET/etc/doas.conf" "permit nopass :wheel"
fi fi
} }
@ -247,10 +228,10 @@ init__set_hostname() {
return 1 return 1
fi fi
mkdir -p "$ROOT"/etc mkdir -p "$ETC"
echo "$host" > "$ROOT"/etc/hostname echo "$host" > "$ETC"/hostname
$MOCK hostname -F "$ROOT"/etc/hostname $MOCK hostname -F "$ETC"/hostname
echo -e "127.0.1.1\t$fqdn $host" >> "$ROOT"/etc/hosts echo -e "127.0.1.1\t$fqdn $host" >> "$ETC"/hosts
} }
init__set_ssh_keys() { init__set_ssh_keys() {

View File

@ -21,24 +21,24 @@ init__userdata_apk_cache() {
case "$cache" in case "$cache" in
/*) cache="../..$cache";; /*) cache="../..$cache";;
esac esac
mkdir -p "$ROOT"/etc/apk mkdir -p "$ETC"/apk
ln -sf "$cache" "$ROOT"/etc/apk/cache ln -sf "$cache" "$ETC"/apk/cache
} }
init__userdata_apk_repositories() { init__userdata_apk_repositories() {
local apk="$(get_userdata apk)" local apk="$(get_userdata apk)"
if [ -z "$apk" ] && ! [ -e "$ROOT"/etc/apk/repositories ]; then if [ -z "$apk" ] && ! [ -e "$ETC"/apk/repositories ]; then
$MOCK setup-apkrepos -1 -c $MOCK setup-apkrepos -1 -c
return return
fi fi
local repositories="$(get_userdata apk/repositories)" local repositories="$(get_userdata apk/repositories)"
mkdir -p "$ROOT"/etc/apk mkdir -p "$ETC"/apk
for r in $repositories; do for r in $repositories; do
local baseurl="$(get_userdata apk/repositories/$r/base_url)" local baseurl="$(get_userdata apk/repositories/$r/base_url)"
local repos="$(get_userdata apk/repositories/$r/repos)" local repos="$(get_userdata apk/repositories/$r/repos)"
local version="$(get_userdata apk/repositories/$r/version)" local version="$(get_userdata apk/repositories/$r/version)"
if [ -z "$version" ]; then if [ -z "$version" ]; then
local version_id=$( . "$ROOT"/etc/os-release 2>/dev/null && echo "$VERSION_ID") local version_id=$( . "$ETC"/os-release 2>/dev/null && echo "$VERSION_ID")
case "$version_id" in case "$version_id" in
edge*|*_alpha*) version="edge";; edge*|*_alpha*) version="edge";;
[0-9]*.[0-9]*.[0-9]*) version="v${version_id%.*}";; [0-9]*.[0-9]*.[0-9]*) version="v${version_id%.*}";;
@ -49,14 +49,14 @@ init__userdata_apk_repositories() {
fi fi
for repo in $repos; do for repo in $repos; do
local uri="${baseurl%/}/$(get_userdata apk/repositories/$r/repos/$repo)" local uri="${baseurl%/}/$(get_userdata apk/repositories/$r/repos/$repo)"
add_once "$ROOT"/etc/apk/repositories "$uri" add_once "$ETC"/apk/repositories "$uri"
done done
done done
} }
find_biggest_empty_disk() { find_biggest_empty_disk() {
local d p local d p
for d in "$ROOT"/sys/class/block/*/device; do for d in "$SYS"/class/block/*/device; do
p=${d%/device} p=${d%/device}
if [ -e "$p"/size ] && [ -z "$(blkid /dev/${p##*/})" ]; then if [ -e "$p"/size ] && [ -z "$(blkid /dev/${p##*/})" ]; then
echo "$(cat $p/size) ${p##*/}" echo "$(cat $p/size) ${p##*/}"
@ -69,7 +69,7 @@ init__userdata_autoinstall() {
if [ "$autoinstall" = "true" ]; then if [ "$autoinstall" = "true" ]; then
local disk="$(find_biggest_empty_disk)" local disk="$(find_biggest_empty_disk)"
if [ -n "$disk" ]; then if [ -n "$disk" ]; then
rm -f "$ROOT"/etc/runlevels/*/tiny-cloud* rm -f "$ETC"/runlevels/*/tiny-cloud*
$MOCK lbu include /root/.ssh /home $MOCK lbu include /root/.ssh /home
$MOCK ERASE_DISKS=/dev/$disk setup-disk -m sys /dev/$disk $MOCK ERASE_DISKS=/dev/$disk setup-disk -m sys /dev/$disk
# TODO: make reboot configurable # TODO: make reboot configurable

View File

@ -291,17 +291,17 @@ init__userdata_users() {
done done
fi fi
if in_list doas $keys; then if in_list doas $keys; then
if [ -d "$ROOT/etc/doas.d" ]; then if [ -d "$ETC/doas.d" ]; then
touch "$ROOT/etc/doas.d/$name.conf" touch "$ETC/doas.d/$name.conf"
chmod 660 "$ROOT/etc/doas.d/$name.conf" chmod 660 "$ETC/doas.d/$name.conf"
fi fi
local j local j
for j in $(get_userdata users/$i/doas); do for j in $(get_userdata users/$i/doas); do
local line="$(get_userdata users/$i/doas/$j)" local line="$(get_userdata users/$i/doas/$j)"
if [ -d "$ROOT/etc/doas.d" ]; then if [ -d "$ETC/doas.d" ]; then
echo "$line" >> "$ROOT/etc/doas.d/$name.conf" echo "$line" >> "$ETC/doas.d/$name.conf"
elif [ -f "$ROOT/etc/doas.conf" ]; then elif [ -f "$ETC/doas.conf" ]; then
add_once "$ROOT/etc/doas.conf" "$line" add_once "$ETC/doas.conf" "$line"
fi fi
done done
fi fi

View File

@ -49,15 +49,15 @@ while true; do
-[ED]|--enable|--disable) # just openrc for now -[ED]|--enable|--disable) # just openrc for now
: "${ROOT:=}" # for mounted volumes : "${ROOT:=}" # for mounted volumes
# always start with a clean slate # always start with a clean slate
rm -f "$ROOT"/etc/runlevels/*/tiny-cloud* rm -f "$ETC"/runlevels/*/tiny-cloud*
log -i info "- tiny-cloud* services removed from all runlevels" log -i info "- tiny-cloud* services removed from all runlevels"
if [ "$1" = '-D' ] || [ "$1" = '--disable' ]; then if [ "$1" = '-D' ] || [ "$1" = '--disable' ]; then
exit 0 exit 0
fi fi
ln -s /etc/init.d/tiny-cloud-boot "$ROOT"/etc/runlevels/boot ln -s /etc/init.d/tiny-cloud-boot "$ETC"/runlevels/boot
log -i info "+ tiny-cloud-boot service added to boot runlevel" log -i info "+ tiny-cloud-boot service added to boot runlevel"
for p in early main final; do for p in early main final; do
ln -s "/etc/init.d/tiny-cloud-$p" "$ROOT"/etc/runlevels/default ln -s "/etc/init.d/tiny-cloud-$p" "$ETC"/runlevels/default
log -i info "+ tiny-cloud-$p service added to default runlevel" log -i info "+ tiny-cloud-$p service added to default runlevel"
done done
exit 0;; exit 0;;
@ -75,7 +75,7 @@ case "$phase" in
*) usage >&2; exit 1;; *) usage >&2; exit 1;;
esac esac
if [ -e "$ROOT"/etc/tiny-cloud.disabled ]; then if [ -e "$ETC"/tiny-cloud.disabled ]; then
log -i -t "$phase" info "tiny-cloud disabled" log -i -t "$phase" info "tiny-cloud disabled"
exit 0 exit 0
fi fi