1
0
mirror of https://gitlab.alpinelinux.org/alpine/cloud/tiny-cloud.git synced 2026-06-21 00:07:16 +03:00

Tiny cloud autodetect

This commit is contained in:
Natanael Copa 2026-06-07 16:01:36 +00:00 committed by Jake Buchholz Göktürk
parent 4cf9c51317
commit f6046351ca
5 changed files with 100 additions and 25 deletions

View File

@ -6,7 +6,7 @@ tiny-cloud - perform first-boot initialization for cloud instances
# SYNOPSIS
*tiny-cloud* [*-h*|*--help*] { *boot* | *early* | *main* | *final* | *-b*|*--bootstrap* { *complete* | *incomplete* | *status* } | *-E*|*--enable* | *-D*|*--disable* }
*tiny-cloud* [*-h*|*--help*] { *boot* | *early* | *main* | *final* | *autodetect* | *-b*|*--bootstrap* { *complete* | *incomplete* | *status* } | *-E*|*--enable* | *-D*|*--disable* }
# DESCRIPTION
@ -61,6 +61,11 @@ been marked complete, later phase invocations exit without doing further work.
Run finalization actions. By default this marks bootstrap complete after any
additional configured final actions have succeeded.
*autodetect*
Run provider autodetection probes and print the detected provider name.
This does not use the configured provider, kernel command line hints, or the
cached autodetection result.
# OPERATION
When invoked with a phase argument, *tiny-cloud* first checks whether

View File

@ -47,31 +47,42 @@ line_kval() {
cat "${2:--}" 2>/dev/null | xargs -n1 | grep "^$1=" | cut -d= -f2- | paste -sd' ' | tr "$3" ' '
}
if [ "$CLOUD" = "auto" ]; then
cloud_alias() {
case "$1" in
ec2) echo aws;;
gce) echo gcp;;
nocloud-net) echo nocloud;;
oracle) echo oci;;
*) echo "$1";;
esac
}
cloud_hint() {
local F cloud
# 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" ] && {
cloud_alias "$cloud"
return
}
done
}
cloud_autodetect() {
for i in "$LIBDIR"/tiny-cloud/cloud/*/autodetect; do
if [ -x "$i" ]; then
"$i" || :
fi
done | sort -n | cut -d' ' -f2 | head -n 1
}
if [ "$CLOUD" = "auto" ] && [ -z "$TINY_CLOUD_NO_RESOLVE" ]; 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
CLOUD=$(cloud_hint)
[ -z "$CLOUD" ] && CLOUD=$(cloud_autodetect)
if [ -z "$CLOUD" ] || [ ! -d "$LIBDIR/tiny-cloud/cloud/$CLOUD" ]; then
log -t autodetect err "unable to determine cloud"
CLOUD=unknown

View File

@ -7,11 +7,12 @@ set -e
: "${PREFIX:=/usr}"
: "${LIBDIR:=$PREFIX/lib}"
[ "$1" = "autodetect" ] && TINY_CLOUD_NO_RESOLVE=1
. "$LIBDIR/tiny-cloud/common"
usage() {
cat <<-EOF
Usage: ${0##*/} [-h | --help] { boot | early | main | final | --bootstrap {complete|incomplete|status} | --enable | --disable }
Usage: ${0##*/} [-h | --help] { boot | early | main | final | autodetect | --bootstrap {complete|incomplete|status} | --enable | --disable }
EOF
}
@ -72,6 +73,14 @@ shift
case "$phase" in
boot|early|main|final) ;;
autodetect)
CLOUD=$(cloud_autodetect)
if [ -z "$CLOUD" ] || [ ! -d "$LIBDIR/tiny-cloud/cloud/$CLOUD" ]; then
echo unknown
exit 1
fi
echo "$CLOUD"
exit 0;;
*) usage >&2; exit 1;;
esac

View File

@ -26,6 +26,8 @@ init_tests \
set_ssh_keys_gcp \
userdata_type \
run_userdata \
autodetect_config_overrides_cmdline \
autodetect_cache_overrides_cmdline \
autodetect_aws_cmdline \
autodetect_aws_nitro \
autodetect_aws_xen \
@ -38,6 +40,7 @@ init_tests \
autodetect_nocloud_dmi \
autodetect_nocloud_volume \
autodetect_oci \
autodetect_scaleway_cmdline \
autodetect_scaleway \
autodetect_unknown
@ -351,6 +354,23 @@ autodetect_unknown_body() {
sh -c ". \"$lib\"; echo \$CLOUD"
}
autodetect_config_overrides_cmdline_body() {
mkdir -p proc
echo "quiet ds=scaleway console=ttyS0" > proc/cmdline
CLOUD=aws atf_check \
-o match:"aws" \
sh -c ". \"$lib\"; echo \$CLOUD"
}
autodetect_cache_overrides_cmdline_body() {
mkdir -p proc var/lib/cloud
echo aws > var/lib/cloud/.autodetect
echo "quiet ds=scaleway console=ttyS0" > proc/cmdline
atf_check \
-o match:"aws" \
sh -c ". \"$lib\"; echo \$CLOUD"
}
autodetect_aws_cmdline_body() {
mkdir -p proc
echo "quiet tinycloud=cloud=aws console=ttyS0" > proc/cmdline
@ -466,6 +486,14 @@ autodetect_oci_body() {
sh -c ". \"$lib\"; echo \$CLOUD"
}
autodetect_scaleway_cmdline_body() {
mkdir -p proc
echo "quiet ds=scaleway console=ttyS0" > proc/cmdline
atf_check \
-o match:"scaleway" \
sh -c ". \"$lib\"; echo \$CLOUD"
}
autodetect_scaleway_body() {
mkdir -p sys/class/dmi/id
cat > sys/class/dmi/id/modalias <<-EOT

View File

@ -10,6 +10,8 @@ PROVIDERS="alpine aws azure digitalocean gcp incus hetzner nocloud oci scaleway"
init_tests \
tiny_cloud_help \
tiny_cloud_autodetect \
tiny_cloud_autodetect_unknown \
tiny_cloud_disabled \
no_metadata_boot \
no_userdata_early \
@ -28,6 +30,26 @@ tiny_cloud_help_body() {
done
}
tiny_cloud_autodetect_body() {
mkdir -p sys/class/dmi/id
cat > sys/class/dmi/id/modalias <<-EOT
dmi:bvnScaleway:bvrScaleway:bd10/22/2024:br1.0:svnScaleway:pnScaleway:pvr:rvnKVM:rnScaleway:rvr:cvnScaleway:ct1:cvr:sku:
EOT
atf_check -s exit:0 \
-o match:"^scaleway$" \
tiny-cloud autodetect
}
tiny_cloud_autodetect_unknown_body() {
mkdir -p etc proc var/lib/cloud
echo "CLOUD=auto" > etc/tiny-cloud.conf
echo scaleway > var/lib/cloud/.autodetect
echo "quiet ds=scaleway console=ttyS0" > proc/cmdline
atf_check -s exit:1 \
-o match:"^unknown$" \
tiny-cloud autodetect
}
tiny_cloud_disabled_body() {
mkdir -p etc
touch etc/tiny-cloud.disabled