mirror of
https://gitlab.alpinelinux.org/alpine/cloud/tiny-cloud.git
synced 2025-12-14 19:02:45 +03:00
cloud via cmdline / move autodetect
This commit is contained in:
parent
0548b418ec
commit
3ea8b15de0
2
bin/imds
2
bin/imds
@ -84,7 +84,7 @@ _imds_ssh_keys() {
|
||||
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
|
||||
|
||||
|
||||
@ -4,8 +4,7 @@
|
||||
# vim:set filetype=sh:
|
||||
# shellcheck shell=sh
|
||||
|
||||
grep -w 'ds=nocloud' "$ROOT"/proc/cmdline 2>/dev/null \
|
||||
|| grep -w "^ds=nocloud" "$ROOT"/sys/class/dmi/id/product_serial 2>/dev/null \
|
||||
|| findfs LABEL=cidata >/dev/null 2>&1 \
|
||||
# kernel cmdline & DMI product serial are checked in common
|
||||
findfs LABEL=cidata >/dev/null 2>&1 \
|
||||
|| findfs LABEL=CIDATA >/dev/null 2>&1 \
|
||||
&& echo "10 nocloud"
|
||||
|
||||
@ -8,8 +8,8 @@ is_nocloud_loaded() { [ -f "$TINY_CLOUD_VAR/.nocloud_loaded" ]; }
|
||||
|
||||
_load_nocloud_cmdline() {
|
||||
local kopt kv k v data
|
||||
for kopt in $(cat "$ROOT/proc/cmdline" 2>/dev/null) \
|
||||
$(grep '^ds=nocloud' "$ROOT"/sys/class/dmi/id/product_serial 2>/dev/null) ; do
|
||||
for kopt in $(cat "$PROC/cmdline" 2>/dev/null) \
|
||||
$(grep '^ds=nocloud' "$SYS"/class/dmi/id/product_serial 2>/dev/null) ; do
|
||||
echo "$kopt" | grep -qE '(^|=)ds=nocloud(-net)?;' || continue
|
||||
for kv in $(echo "${kopt#*;}" | tr \; ' '); do
|
||||
k=$(echo "$kv" | cut -d= -f1)
|
||||
@ -88,7 +88,6 @@ load_nocloud() {
|
||||
}
|
||||
|
||||
_imds() {
|
||||
mkdir -p "$TINY_CLOUD_VAR"
|
||||
local file="$TINY_CLOUD_VAR/$(echo "$1" | cut -d/ -f1)"
|
||||
local keypath="$(echo "$1" | cut -d/ -f2- | tr / ' ')"
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@ set_resolv_conf() {
|
||||
local nameservers="$(imds meta-data/resolv_conf/nameservers)"
|
||||
for i in $nameservers; do
|
||||
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
|
||||
}
|
||||
|
||||
@ -22,8 +22,8 @@ want_ephemeral_network() {
|
||||
if has_ipv4_address; then
|
||||
return 1
|
||||
fi
|
||||
for i in $(cat "$ROOT"/proc/cmdline 2>/dev/null) \
|
||||
$(cat "$ROOT"/sys/class/dmi/id/product_serial 2>/dev/null); do
|
||||
for i in $(cat "$PROC"/cmdline 2>/dev/null) \
|
||||
$(cat "$SYS"/class/dmi/id/product_serial 2>/dev/null); do
|
||||
case "$i" in
|
||||
"ds=nocloud;"*)
|
||||
for kv in $(echo "${i#*;}" | tr \; ' '); do
|
||||
@ -45,13 +45,13 @@ want_ephemeral_network() {
|
||||
|
||||
init__set_network_interfaces() {
|
||||
local interfaces="$(imds meta-data/network-interfaces)"
|
||||
mkdir -p "$ROOT"/etc/network
|
||||
mkdir -p "$ETC"/network
|
||||
if [ -n "$interfaces" ]; then
|
||||
printf "%s\n" "$interfaces" > "$ROOT"/etc/network/interfaces
|
||||
elif ! [ -f "$ROOT"/etc/network/interfaces ]; then
|
||||
printf "%s\n" "$interfaces" > "$ETC"/network/interfaces
|
||||
elif ! [ -f "$ETC"/network/interfaces ]; then
|
||||
init__set_default_interfaces
|
||||
fi
|
||||
if ! grep -q dhcp "$ROOT"/etc/network/interfaces; then
|
||||
if ! grep -q dhcp "$ETC"/network/interfaces; then
|
||||
set_resolv_conf
|
||||
fi
|
||||
}
|
||||
|
||||
@ -29,7 +29,7 @@ _imds_ssh_keys() { _imds "$IMDS_SSH_KEYS"; }
|
||||
|
||||
_imds_nic_index() {
|
||||
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
|
||||
[ "$m" = "$mac" ] && echo $n; return 0
|
||||
done
|
||||
|
||||
@ -3,11 +3,58 @@
|
||||
# shellcheck shell=sh
|
||||
|
||||
# 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_USER:=alpine}"
|
||||
: "${TINY_CLOUD_LOGS:=$ROOT/var/log}"
|
||||
: "${TINY_CLOUD_VAR:=$ROOT/var/lib/cloud}"
|
||||
mkdir -p "${TINY_CLOUD_LOGS:=$ROOT/var/log}"
|
||||
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() {
|
||||
local facility="local7"
|
||||
|
||||
@ -32,31 +32,12 @@ DEFAULT_ACTIONS_FINAL=""
|
||||
: "${INIT_ACTIONS_MAIN=$DEFAULT_ACTIONS_MAIN}"
|
||||
: "${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...
|
||||
|
||||
init__expand_root() {
|
||||
local dev=$(awk '$2 == "/" {print $1}' "$ROOT"/proc/mounts 2>/dev/null)
|
||||
local filesystem=$(awk '$2 == "/" {print $3}' "$ROOT"/proc/mounts 2>/dev/null)
|
||||
local partition=$(cat "$ROOT/sys/class/block/${dev#/dev/}/partition" 2>/dev/null)
|
||||
local dev=$(awk '$2 == "/" {print $1}' "$PROC"/mounts 2>/dev/null)
|
||||
local filesystem=$(awk '$2 == "/" {print $3}' "$PROC"/mounts 2>/dev/null)
|
||||
local partition=$(cat "$SYS/class/block/${dev#/dev/}/partition" 2>/dev/null)
|
||||
|
||||
# only support ext2/ext3/ext4 for now
|
||||
case "$filesystem" in
|
||||
@ -66,7 +47,7 @@ init__expand_root() {
|
||||
|
||||
if [ -n "$partition" ]; then
|
||||
# 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##*/}"
|
||||
echo ", +" | $MOCK sfdisk -q --no-reread -N "$partition" "$volume"
|
||||
$MOCK partx -u "$volume"
|
||||
@ -79,7 +60,7 @@ init__expand_root() {
|
||||
|
||||
# collect ethernet interfaces, sorted by index
|
||||
ethernets() {
|
||||
for i in "$ROOT/sys/class/net/"*; do
|
||||
for i in "$SYS/class/net/"*; do
|
||||
local iface="${i##*/}"
|
||||
case "$iface" in
|
||||
eth*) echo "$(cat "$i/ifindex") $iface";;
|
||||
@ -93,7 +74,7 @@ find_first_interface_up() {
|
||||
[ $# -eq 0 ] && return
|
||||
while [ $n -le ${TINY_CLOUD_LINK_WAIT_MAX:-10} ]; 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"
|
||||
return
|
||||
fi
|
||||
@ -148,16 +129,16 @@ init__set_ephemeral_network() {
|
||||
}
|
||||
|
||||
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"
|
||||
return
|
||||
fi
|
||||
|
||||
mkdir -p "$ROOT/etc/network"
|
||||
mkdir -p "$ETC/network"
|
||||
printf "%s\n%s\n\n" \
|
||||
"auto lo" \
|
||||
"iface lo inet loopback" \
|
||||
> "$ROOT/etc/network/interfaces"
|
||||
> "$ETC/network/interfaces"
|
||||
|
||||
local iface="$(auto_detect_ethernet_interface)"
|
||||
if [ -z "$iface" ]; then
|
||||
@ -167,7 +148,7 @@ init__set_default_interfaces() {
|
||||
printf "%s\n%s\n\t%s\n\n" \
|
||||
"auto $iface" \
|
||||
"iface $iface" \
|
||||
"use dhcp" >> "$ROOT/etc/network/interfaces"
|
||||
"use dhcp" >> "$ETC/network/interfaces"
|
||||
}
|
||||
|
||||
init__create_default_user() {
|
||||
@ -188,12 +169,12 @@ init__create_default_user() {
|
||||
echo "$user:*" | $MOCK chpasswd -e
|
||||
|
||||
# setup sudo and/or doas
|
||||
if [ -d "$ROOT/etc/sudoers.d" ]; then
|
||||
echo '%wheel ALL=(ALL) NOPASSWD: ALL' > "$ROOT/etc/sudoers.d/wheel"
|
||||
if [ -d "$ETC/sudoers.d" ]; then
|
||||
echo '%wheel ALL=(ALL) NOPASSWD: ALL' > "$ETC/sudoers.d/wheel"
|
||||
fi
|
||||
if [ -d "$ROOT/etc/doas.d" ]; then
|
||||
if [ -d "$ETC/doas.d" ]; then
|
||||
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"
|
||||
fi
|
||||
}
|
||||
@ -247,10 +228,10 @@ init__set_hostname() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
mkdir -p "$ROOT"/etc
|
||||
echo "$host" > "$ROOT"/etc/hostname
|
||||
$MOCK hostname -F "$ROOT"/etc/hostname
|
||||
echo -e "127.0.1.1\t$fqdn $host" >> "$ROOT"/etc/hosts
|
||||
mkdir -p "$ETC"
|
||||
echo "$host" > "$ETC"/hostname
|
||||
$MOCK hostname -F "$ETC"/hostname
|
||||
echo -e "127.0.1.1\t$fqdn $host" >> "$ETC"/hosts
|
||||
}
|
||||
|
||||
init__set_ssh_keys() {
|
||||
|
||||
@ -21,24 +21,24 @@ init__userdata_apk_cache() {
|
||||
case "$cache" in
|
||||
/*) cache="../..$cache";;
|
||||
esac
|
||||
mkdir -p "$ROOT"/etc/apk
|
||||
ln -sf "$cache" "$ROOT"/etc/apk/cache
|
||||
mkdir -p "$ETC"/apk
|
||||
ln -sf "$cache" "$ETC"/apk/cache
|
||||
}
|
||||
|
||||
init__userdata_apk_repositories() {
|
||||
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
|
||||
return
|
||||
fi
|
||||
local repositories="$(get_userdata apk/repositories)"
|
||||
mkdir -p "$ROOT"/etc/apk
|
||||
mkdir -p "$ETC"/apk
|
||||
for r in $repositories; do
|
||||
local baseurl="$(get_userdata apk/repositories/$r/base_url)"
|
||||
local repos="$(get_userdata apk/repositories/$r/repos)"
|
||||
local version="$(get_userdata apk/repositories/$r/version)"
|
||||
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
|
||||
edge*|*_alpha*) version="edge";;
|
||||
[0-9]*.[0-9]*.[0-9]*) version="v${version_id%.*}";;
|
||||
@ -49,14 +49,14 @@ init__userdata_apk_repositories() {
|
||||
fi
|
||||
for repo in $repos; do
|
||||
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
|
||||
}
|
||||
|
||||
find_biggest_empty_disk() {
|
||||
local d p
|
||||
for d in "$ROOT"/sys/class/block/*/device; do
|
||||
for d in "$SYS"/class/block/*/device; do
|
||||
p=${d%/device}
|
||||
if [ -e "$p"/size ] && [ -z "$(blkid /dev/${p##*/})" ]; then
|
||||
echo "$(cat $p/size) ${p##*/}"
|
||||
@ -69,7 +69,7 @@ init__userdata_autoinstall() {
|
||||
if [ "$autoinstall" = "true" ]; then
|
||||
local disk="$(find_biggest_empty_disk)"
|
||||
if [ -n "$disk" ]; then
|
||||
rm -f "$ROOT"/etc/runlevels/*/tiny-cloud*
|
||||
rm -f "$ETC"/runlevels/*/tiny-cloud*
|
||||
$MOCK lbu include /root/.ssh /home
|
||||
$MOCK ERASE_DISKS=/dev/$disk setup-disk -m sys /dev/$disk
|
||||
# TODO: make reboot configurable
|
||||
|
||||
@ -291,17 +291,17 @@ init__userdata_users() {
|
||||
done
|
||||
fi
|
||||
if in_list doas $keys; then
|
||||
if [ -d "$ROOT/etc/doas.d" ]; then
|
||||
touch "$ROOT/etc/doas.d/$name.conf"
|
||||
chmod 660 "$ROOT/etc/doas.d/$name.conf"
|
||||
if [ -d "$ETC/doas.d" ]; then
|
||||
touch "$ETC/doas.d/$name.conf"
|
||||
chmod 660 "$ETC/doas.d/$name.conf"
|
||||
fi
|
||||
local j
|
||||
for j in $(get_userdata users/$i/doas); do
|
||||
local line="$(get_userdata users/$i/doas/$j)"
|
||||
if [ -d "$ROOT/etc/doas.d" ]; then
|
||||
echo "$line" >> "$ROOT/etc/doas.d/$name.conf"
|
||||
elif [ -f "$ROOT/etc/doas.conf" ]; then
|
||||
add_once "$ROOT/etc/doas.conf" "$line"
|
||||
if [ -d "$ETC/doas.d" ]; then
|
||||
echo "$line" >> "$ETC/doas.d/$name.conf"
|
||||
elif [ -f "$ETC/doas.conf" ]; then
|
||||
add_once "$ETC/doas.conf" "$line"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
@ -49,15 +49,15 @@ while true; do
|
||||
-[ED]|--enable|--disable) # just openrc for now
|
||||
: "${ROOT:=}" # for mounted volumes
|
||||
# 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"
|
||||
if [ "$1" = '-D' ] || [ "$1" = '--disable' ]; then
|
||||
exit 0
|
||||
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"
|
||||
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"
|
||||
done
|
||||
exit 0;;
|
||||
@ -75,7 +75,7 @@ case "$phase" in
|
||||
*) usage >&2; exit 1;;
|
||||
esac
|
||||
|
||||
if [ -e "$ROOT"/etc/tiny-cloud.disabled ]; then
|
||||
if [ -e "$ETC"/tiny-cloud.disabled ]; then
|
||||
log -i -t "$phase" info "tiny-cloud disabled"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user