1
0
mirror of https://gitlab.alpinelinux.org/alpine/cloud/tiny-cloud.git synced 2025-12-14 19:02:45 +03:00

Add .editorconfig and replace spaces with tabs

This commit is contained in:
Natanael Copa 2023-05-19 04:13:16 +00:00 committed by Jake Buchholz Göktürk
parent 7d9a280a67
commit 000f41a48b
36 changed files with 968 additions and 942 deletions

18
.editorconfig Normal file
View File

@ -0,0 +1,18 @@
# https://editorconfig.org
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = tab
insert_final_newline = true
trim_trailing_whitespace = true
[Makefile]
indent_size = 8
indent_style = tab
[*.{md,yml,yaml}]
indent_style = space
indent_size = 2

192
bin/imds
View File

@ -1,5 +1,5 @@
#!/bin/sh
# vim:set ts=4 et ft=sh:
# vim:set ft=sh:
# Tiny Cloud - Instance MetaData Service client
@ -9,43 +9,43 @@
. "$LIBDIR/tiny-cloud/common"
if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
cat <<EOT
Usage: imds [-h] { -e | +e | +n | +s | +t | @<alias> | <imds-path> } ...
-h : help
-e / +e : ignore / catch errors
+n / +s / +t : insert newline / space / tab
<alias> :-
hostname : instance hostname
local-hostname : instance local hostname
ssh-keys : instance SSH keys
userdata : instance user data
nics : instance NICs
nic:<iface>[,<nic-key> ...] : specific NIC interface
<iface> : network interface (i.e. eth1)
<nic-key> :- { -e | +e | +n | +s | +t | @<nic-alias> | <nic-path> }
<nic-alias> :-
mac : mac address
ipv4 : ipv4 address(es)
ipv6 : ipv6 address(es)
ipv4-net : subnet ipv4 network(s)
ipv6-net : subnet ipv6 network(s)
ipv4-prefix : delegated ipv4 CIDR(s)
ipv6-prefix : delegated ipv6 CIDR(s)
EOT
exit 0
cat <<-EOT
Usage: imds [-h] { -e | +e | +n | +s | +t | @<alias> | <imds-path> } ...
-h : help
-e / +e : ignore / catch errors
+n / +s / +t : insert newline / space / tab
<alias> :-
hostname : instance hostname
local-hostname : instance local hostname
ssh-keys : instance SSH keys
userdata : instance user data
nics : instance NICs
nic:<iface>[,<nic-key> ...] : specific NIC interface
<iface> : network interface (i.e. eth1)
<nic-key> :- { -e | +e | +n | +s | +t | @<nic-alias> | <nic-path> }
<nic-alias> :-
mac : mac address
ipv4 : ipv4 address(es)
ipv6 : ipv6 address(es)
ipv4-net : subnet ipv4 network(s)
ipv6-net : subnet ipv6 network(s)
ipv4-prefix : delegated ipv4 CIDR(s)
ipv6-prefix : delegated ipv6 CIDR(s)
EOT
exit 0
fi
### cloud-specific variables/functions
unset \
IMDS_HEADER \
IMDS_URI \
IMDS_QUERY
IMDS_HEADER \
IMDS_URI \
IMDS_QUERY
unset -f \
_imds_token \
_imds_header \
_imds_nic_index \
2>/dev/null || true
_imds_token \
_imds_header \
_imds_nic_index \
2>/dev/null || true
### default variables/functions
@ -67,19 +67,19 @@ IMDS_IPV4_PREFIX="ipv4-prefix"
IMDS_IPV6_PREFIX="ipv6-prefix"
_imds() {
wget --quiet --timeout 1 --output-document - \
--header "$(_imds_header)" \
"http://$IMDS_ENDPOINT/$IMDS_URI/$1$IMDS_QUERY"
wget --quiet --timeout 1 --output-document - \
--header "$(_imds_header)" \
"http://$IMDS_ENDPOINT/$IMDS_URI/$1$IMDS_QUERY"
}
_imds_userdata() { _imds "$IMDS_USERDATA"; }
_imds_ssh_keys() {
local key
for key in $(_imds "$IMDS_SSH_KEYS"); do
_imds "$IMDS_SSH_KEYS/${key%=*}/openssh-key"
echo
done | sort -u
local key
for key in $(_imds "$IMDS_SSH_KEYS"); do
_imds "$IMDS_SSH_KEYS/${key%=*}/openssh-key"
echo
done | sort -u
}
_imds_nic_index() { cat "/sys/class/net/$1/address"; }
@ -87,71 +87,71 @@ _imds_nic_index() { cat "/sys/class/net/$1/address"; }
### load cloud-specific variables and functions
if [ ! -d "$LIBDIR/tiny-cloud/cloud/$CLOUD" ]; then
echo "ERROR: Unknown Cloud '$CLOUD'" >&2
echo "ERROR: Unknown Cloud '$CLOUD'" >&2
fi
. "$LIBDIR/tiny-cloud/cloud/$CLOUD/imds"
### non-overrideable functions
imds() {
local cmd args key rv err=1
while [ -n "$1" ]; do
cmd=_imds
args=
key="$1"; shift
case $key in
# error handling
-e) err=0; continue ;; # ignore
+e) err=1; continue ;; # return
# TODO: retry/deadline
# output control
+n) printf "\n"; continue ;; # insert newline
+s) printf " "; continue ;; # insert space
+t) printf "\t"; continue ;; # insert tab
# key aliasing
@hostname) args="$IMDS_HOSTNAME" ;;
@local-hostname) args="$IMDS_LOCAL_HOSTNAME" ;;
@ssh-keys) cmd=_imds_ssh_keys ;;
@userdata) cmd=_imds_userdata ;;
@nics) args="$IMDS_NICS" ;;
@nic:*)
cmd=imds
args=$(_imds_nic_args $(echo "${key#@nic:}" | tr , ' '))
;;
# use key verbatim
*) args="$key" ;;
esac
# TODO: retry/deadline
"$cmd" $args
rv=$?
[ $err -eq 0 ] && continue
[ $rv = "0" ] || return $rv
done
local cmd args key rv err=1
while [ -n "$1" ]; do
cmd=_imds
args=
key="$1"; shift
case $key in
# error handling
-e) err=0; continue ;; # ignore
+e) err=1; continue ;; # return
# TODO: retry/deadline
# output control
+n) printf "\n"; continue ;; # insert newline
+s) printf " "; continue ;; # insert space
+t) printf "\t"; continue ;; # insert tab
# key aliasing
@hostname) args="$IMDS_HOSTNAME" ;;
@local-hostname) args="$IMDS_LOCAL_HOSTNAME" ;;
@ssh-keys) cmd=_imds_ssh_keys ;;
@userdata) cmd=_imds_userdata ;;
@nics) args="$IMDS_NICS" ;;
@nic:*)
cmd=imds
args=$(_imds_nic_args $(echo "${key#@nic:}" | tr , ' '))
;;
# use key verbatim
*) args="$key" ;;
esac
# TODO: retry/deadline
"$cmd" $args
rv=$?
[ $err -eq 0 ] && continue
[ $rv = "0" ] || return $rv
done
}
_imds_nic_args() {
local key nic
nic=$(_imds_nic_index "$1") || return 1
if [ -z "$2" ]; then
echo "$IMDS_NICS/$nic"
return
fi
while [ -n "$2" ]; do
key="$2"
shift
case "$key" in
@mac) key="$IMDS_MAC" ;;
@ipv4) key="$IMDS_IPV4" ;;
@ipv6) key="$IMDS_IPV6" ;;
@ipv4-net) key="$IMDS_IPV4_NET" ;;
@ipv6-net) key="$IMDS_IPV6_NET" ;;
@ipv4-prefix) key="$IMDS_IPV4_PREFIX" ;;
@ipv6-prefix) key="$IMDS_IPV6_PREFIX" ;;
# error/output control passthrough
-e|+[enst]) printf "$key\n"; continue ;;
esac
printf "$IMDS_NICS/$nic/$key\n"
done
local key nic
nic=$(_imds_nic_index "$1") || return 1
if [ -z "$2" ]; then
echo "$IMDS_NICS/$nic"
return
fi
while [ -n "$2" ]; do
key="$2"
shift
case "$key" in
@mac) key="$IMDS_MAC" ;;
@ipv4) key="$IMDS_IPV4" ;;
@ipv6) key="$IMDS_IPV6" ;;
@ipv4-net) key="$IMDS_IPV4_NET" ;;
@ipv6-net) key="$IMDS_IPV6_NET" ;;
@ipv4-prefix) key="$IMDS_IPV4_PREFIX" ;;
@ipv6-prefix) key="$IMDS_IPV6_PREFIX" ;;
# error/output control passthrough
-e|+[enst]) printf "$key\n"; continue ;;
esac
printf "$IMDS_NICS/$nic/$key\n"
done
}
imds "$@"

View File

@ -1,5 +1,5 @@
#!/sbin/openrc-run
# vim:set ts=8 noet ft=sh:
# vim:set ft=sh:
# shellcheck shell=sh
description="Tiny Cloud Bootstrap - main phase"

View File

@ -1,5 +1,5 @@
#!/sbin/openrc-run
# vim:set ts=8 noet ft=sh:
# vim:set ft=sh:
# shellcheck shell=sh
description="Tiny Cloud Bootstrap - early phase"

View File

@ -1,5 +1,5 @@
#!/sbin/openrc-run
# vim:set ts=8 noet ft=sh:
# vim:set ft=sh:
# shellcheck shell=sh
description="Tiny Cloud Bootstrap - final phase"

View File

@ -1,5 +1,5 @@
#!/sbin/openrc-run
# vim:set ts=8 noet ft=sh:
# vim:set ft=sh:
# shellcheck shell=sh
description="Tiny Cloud Bootstrap - net phase"

View File

@ -1,8 +1,8 @@
#!/bin/sh
# vim:set ts=2 et:
# vim:set ft=sh:
# NOTE: The mdev-conf APK handles this now, but only for xvd or sd links (not
# both)
# both)
: "${LIBDIR:=$PREFIX/lib}"
. "$LIBDIR/tiny-cloud/common"
@ -11,39 +11,39 @@
[ -x /usr/sbin/nvme ] || log crit "nvme cli not installed"
raw_ebs_alias() {
/usr/sbin/nvme id-ctrl "/dev/$BASE" -b 2>/dev/null |
dd bs=32 skip=96 count=1 2>/dev/null
/usr/sbin/nvme id-ctrl "/dev/$BASE" -b 2>/dev/null |
dd bs=32 skip=96 count=1 2>/dev/null
}
case $ACTION in
add|"")
BASE=$(echo "$MDEV" | sed -re 's/^(nvme[0-9]+n[0-9]+).*/\1/')
PART=$(echo "$MDEV" | sed -re 's/nvme[0-9]+n[0-9]+p?//g')
# TODO: deadline instead of max tries
MAXTRY=30
TRY=0
until [ -n "$EBS" ]; do
EBS=$(raw_ebs_alias | sed -nre '/^(\/dev\/)?(s|xv)d[a-z]{1,2} /p' | tr -d ' ')
[ -n "$EBS" ] && break
TRY=$((TRY + 1))
if [ $TRY -eq $MAXTRY ]; then
log err "Failed to get EBS volume alias for $MDEV after $MAXTRY attempts ($(raw_ebs_alias))"
exit 1
fi
sleep 0.1
done
# remove any leading '/dev/', 'sd', or 'xvd', and append partition
EBS=${EBS#/dev/}
EBS=${EBS#sd}
EBS=${EBS#xvd}$PART
ln -sf "$MDEV" "sd$EBS" && log notice "Added sd$EBS symlink for $MDEV"
ln -sf "$MDEV" "xvd$EBS" && log notice "Added xvd$EBS symlink for $MDEV"
;;
remove)
for TARGET in sd* xvd*
do
[ "$(readlink "$TARGET" 2>/dev/null)" = "$MDEV" ] && rm -f "$TARGET" && \
log notice "Removed $TARGET symlink for $MDEV"
done
;;
add|"")
BASE=$(echo "$MDEV" | sed -re 's/^(nvme[0-9]+n[0-9]+).*/\1/')
PART=$(echo "$MDEV" | sed -re 's/nvme[0-9]+n[0-9]+p?//g')
# TODO: deadline instead of max tries
MAXTRY=30
TRY=0
until [ -n "$EBS" ]; do
EBS=$(raw_ebs_alias | sed -nre '/^(\/dev\/)?(s|xv)d[a-z]{1,2} /p' | tr -d ' ')
[ -n "$EBS" ] && break
TRY=$((TRY + 1))
if [ $TRY -eq $MAXTRY ]; then
log err "Failed to get EBS volume alias for $MDEV after $MAXTRY attempts ($(raw_ebs_alias))"
exit 1
fi
sleep 0.1
done
# remove any leading '/dev/', 'sd', or 'xvd', and append partition
EBS=${EBS#/dev/}
EBS=${EBS#sd}
EBS=${EBS#xvd}$PART
ln -sf "$MDEV" "sd$EBS" && log notice "Added sd$EBS symlink for $MDEV"
ln -sf "$MDEV" "xvd$EBS" && log notice "Added xvd$EBS symlink for $MDEV"
;;
remove)
for TARGET in sd* xvd*
do
[ "$(readlink "$TARGET" 2>/dev/null)" = "$MDEV" ] && rm -f "$TARGET" && \
log notice "Removed $TARGET symlink for $MDEV"
done
;;
esac

View File

@ -1,5 +1,5 @@
#!/bin/sh
# vim:set ts=4 et:
# vim:set ft=sh:
set -e
@ -7,52 +7,52 @@ set -e
. "$LIBDIR/tiny-cloud/common"
if [ -z "$MDEV" ] || [ -z "$ACTION" ]; then
log crit "MDEV or ACTION undefined, aborting"
log crit "MDEV or ACTION undefined, aborting"
fi
IFACE_CFG=/etc/network/interfaces
ip() {
local v=-4 lev=info
if [ "$1" = '-4' ] || [ "$1" = '-6' ]; then
v="$1"
shift
fi
local op="$2"
local v=-4 lev=info
if [ "$1" = '-4' ] || [ "$1" = '-6' ]; then
v="$1"
shift
fi
local op="$2"
[ "$op" = show ] && lev=debug
if /sbin/ip "$v" "$@" || [ -n "$FAIL_OK" ]; then
log "$lev" "OK: ip $v $*"
else
log err "FAIL: ip $v $*"
fi
[ "$op" = show ] && lev=debug
if /sbin/ip "$v" "$@" || [ -n "$FAIL_OK" ]; then
log "$lev" "OK: ip $v $*"
else
log err "FAIL: ip $v $*"
fi
}
interface_up() {
log info "Bringing up $MDEV"
# umask so udhcpc PID file isn't non-owner writeable
(umask 0022 && ifup "$MDEV")
log info "Bringing up $MDEV"
# umask so udhcpc PID file isn't non-owner writeable
(umask 0022 && ifup "$MDEV")
}
cleanup_interface() {
local v pref rtable="${MDEV#eth}"
let rtable+=10000
local v pref rtable="${MDEV#eth}"
let rtable+=10000
log info "Cleaning up $MDEV"
log info "Cleaning up $MDEV"
# kill related udhcpc, don't panic if it's not there
kill "$(cat "/run/udhcpc.$MDEV.pid")" || true
# kill related udhcpc, don't panic if it's not there
kill "$(cat "/run/udhcpc.$MDEV.pid")" || true
# tidy up /run/ifstate, if it exists
[ -f /run/ifstate ] && sed -i -e "/^$MDEV=/d" /run/ifstate
rm -f /run/ifstate."$MDEV".lock
# tidy up /run/ifstate, if it exists
[ -f /run/ifstate ] && sed -i -e "/^$MDEV=/d" /run/ifstate
rm -f /run/ifstate."$MDEV".lock
# remove related rules
for v in 4 6; do
for pref in $(ip -"$v" rule show table "$rtable" | cut -d: -f1); do
ip -"$v" rule del pref "$pref"
done
done
# remove related rules
for v in 4 6; do
for pref in $(ip -"$v" rule show table "$rtable" | cut -d: -f1); do
ip -"$v" rule del pref "$pref"
done
done
}
is_networking_started() { service networking status -q 2>/dev/null; }
@ -60,28 +60,28 @@ is_networking_started() { service networking status -q 2>/dev/null; }
log info "STARTING: $ACTION $MDEV"
if exec 200>>"$IFACE_CFG"; then
if flock 200; then
case $ACTION in
add|"")
assemble-interfaces
is_networking_started && interface_up
;;
remove)
assemble-interfaces
is_networking_started && cleanup_interface
;;
*)
log err "Unknown action '$ACTION'"
exit 1
;;
esac
else
log err "Unable to flock $IFACE_CFG"
exit 1
fi
if flock 200; then
case $ACTION in
add|"")
assemble-interfaces
is_networking_started && interface_up
;;
remove)
assemble-interfaces
is_networking_started && cleanup_interface
;;
*)
log err "Unknown action '$ACTION'"
exit 1
;;
esac
else
log err "Unable to flock $IFACE_CFG"
exit 1
fi
else
log err "Unable to assign fd 200 to flock $IFACE_CFG"
exit 1
log err "Unable to assign fd 200 to flock $IFACE_CFG"
exit 1
fi
log info "FINISHED: $ACTION $MDEV"

View File

@ -1,27 +1,27 @@
# Tiny Cloud - Init Functions
# vim:set ts=4 et ft=sh:
# vim:set ft=sh:
# shellcheck shell=sh
INIT_ACTIONS_EARLY="$(replace_word set_default_interfaces set_network_interfaces $INIT_ACTIONS_EARLY)"
set_resolv_conf() {
# 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"
done
# 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"
done
}
init__set_network_interfaces() {
local interfaces="$(imds meta-data/network-interfaces)"
mkdir -p "$ROOT"/etc/network
if [ -n "$interfaces" ]; then
printf "%s\n" "$interfaces" > "$ROOT"/etc/network/interfaces
elif ! [ -f "$ROOT"/etc/network/interfaces ]; then
init__set_default_interfaces
fi
if ! grep -q dhcp "$ROOT"/etc/network/interfaces; then
set_resolv_conf
fi
local interfaces="$(imds meta-data/network-interfaces)"
mkdir -p "$ROOT"/etc/network
if [ -n "$interfaces" ]; then
printf "%s\n" "$interfaces" > "$ROOT"/etc/network/interfaces
elif ! [ -f "$ROOT"/etc/network/interfaces ]; then
init__set_default_interfaces
fi
if ! grep -q dhcp "$ROOT"/etc/network/interfaces; then
set_resolv_conf
fi
}

View File

@ -1,5 +1,5 @@
# AWS Instance MetaData Service variables and functions
# vim:set ts=4 et ft=sh:
# vim:set ft=sh:
# shellcheck shell=sh
IMDS_HEADER="X-aws-ec2-metadata-token"
@ -8,11 +8,11 @@ IMDS_TOKEN_TTL_HEADER="X-aws-ec2-metadata-token-ttl-seconds"
IMDS_URI="latest"
_imds_token() {
printf "PUT /latest/api/token HTTP/1.0\r\n%s: %s\r\n\r\n" \
"$IMDS_TOKEN_TTL_HEADER" "$IMDS_TOKEN_TTL" \
| nc -w 1 "$IMDS_ENDPOINT" 80 | tail -n 1
printf "PUT /latest/api/token HTTP/1.0\r\n%s: %s\r\n\r\n" \
"$IMDS_TOKEN_TTL_HEADER" "$IMDS_TOKEN_TTL" \
| nc -w 1 "$IMDS_ENDPOINT" 80 | tail -n 1
}
_imds_header() {
echo "$IMDS_HEADER: $(_imds_token)"
echo "$IMDS_HEADER: $(_imds_token)"
}

View File

@ -1,12 +1,12 @@
# AWS mdev Hotplug Modules
# vim:set ts=4 et ft=sh:
# vim:set ft=sh:
# shellcheck shell=sh
# makes symlinks for NVMe devices that correlate to AWS EBS sd/xvd devices
mod__nvme_ebs_links() {
# nvme-cli not installed?
[ -x /usr/sbin/nvme ] || return 1
# nvme-cli not installed?
[ -x /usr/sbin/nvme ] || return 1
install_before '^nvme\.\*' \
'nvme[0-9]+n.* root:disk 0660 */lib/mdev/nvme-ebs-links'
install_before '^nvme\.\*' \
'nvme[0-9]+n.* root:disk 0660 */lib/mdev/nvme-ebs-links'
}

View File

@ -1,5 +1,5 @@
# Azure Instance MetaData Service variables and functions
# vim:set ts=4 et ft=sh:
# vim:set ft=sh:
# shellcheck shell=sh
IMDS_HEADER="Metadata"
@ -14,28 +14,28 @@ IMDS_NICS="network/interface"
# TODO: flesh out networking
unset \
IMDS_MAC \
IMDS_IPV4 \
IMDS_IPV6 \
IMDS_IPV4_NET \
IMDS_IPV6_NET \
IMDS_IPV4_PREFIX \
IMDS_IPV6_PREFIX
IMDS_MAC \
IMDS_IPV4 \
IMDS_IPV6 \
IMDS_IPV4_NET \
IMDS_IPV6_NET \
IMDS_IPV4_PREFIX \
IMDS_IPV6_PREFIX
_imds_header() {
echo "$IMDS_HEADER: true"
echo "$IMDS_HEADER: true"
}
# dig deeper than default
_imds_ssh_keys() {
local key
local key
for key in $(imds "$IMDS_SSH_KEYS"); do
imds "$IMDS_SSH_KEYS/${key}/keyData"
done | sort -u
for key in $(imds "$IMDS_SSH_KEYS"); do
imds "$IMDS_SSH_KEYS/${key}/keyData"
done | sort -u
}
# decode userdata value
_imds_userdata() {
imds "$IMDS_USERDATA" | base64 -d
imds "$IMDS_USERDATA" | base64 -d
}

View File

@ -1,5 +1,5 @@
# Google Cloud Instance MetaData Service variables and functions
# vim:set ts=4 et ft=sh:
# vim:set ft=sh:
# shellcheck shell=sh
IMDS_HEADER="Metadata-Flavor"
@ -8,21 +8,21 @@ IMDS_URI="computeMetadata/v1"
IMDS_HOSTNAME="instance/hostname"
IMDS_LOCAL_HOSTNAME="$IMDS_HOSTNAME"
IMDS_SSH_KEYS="
project/attributes/ssh-keys
instance/attributes/ssh-keys
project/attributes/ssh-keys
instance/attributes/ssh-keys
"
IMDS_USERDATA="instance/attributes/user-data"
_imds_header() {
echo "$IMDS_HEADER: Google"
echo "$IMDS_HEADER: Google"
}
# merge project and instance keys
_imds_ssh_keys() {
local ssh_keys
local ssh_keys
for ssh_keys in $IMDS_SSH_KEYS; do
# ignore errors and strip leading '<login>:'
imds -e "$ssh_keys" | cut -d: -f2-
done | sort -u
for ssh_keys in $IMDS_SSH_KEYS; do
# ignore errors and strip leading '<login>:'
imds -e "$ssh_keys" | cut -d: -f2-
done | sort -u
}

View File

@ -1,5 +1,5 @@
# NoCloud Instance Metadata
# vim: ts=4 et ft=sh:
# vim:set ft=sh:
# shellcheck shell=sh
NOCLOUD_FILES="meta-data user-data vendor-data network-config"
@ -7,100 +7,100 @@ NOCLOUD_FILES="meta-data user-data vendor-data network-config"
is_nocloud_loaded() { [ -f "$TINY_CLOUD_VAR/.nocloud_loaded" ]; }
_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); do
echo "$kopt" | grep -qE '(^|=)ds=nocloud(-net)?;' || continue
for kv in $(echo "${kopt#*;}" | tr \; ' '); do
k=$(echo "$kv" | cut -d= -f1)
v=$(echo "$kv" | cut -d= -f2-)
case "$k" in
h|local-hostname)
printf "\nlocal-hostname: %s" "$v" >> "$TINY_CLOUD_VAR/meta-data"
;;
i|instance-id)
printf "\ninstance-id: %s" "$v" >> "$TINY_CLOUD_VAR/meta-data"
;;
s|seedfrom)
for data in $NOCLOUD_FILES; do
case "${v#file:/}" in
/*)
cat "$v/$data" >> "$TINY_CLOUD_VAR/$data" || continue
echo >> "$TINY_CLOUD_VAR/$data"
;;
http://*|https://*)
wget -qO - "$v/$data" >> "$TINY_CLOUD_VAR/$data" || continue
echo >> "$TINY_CLOUD_VAR/$data"
;;
*) log -s warning "Unknown NoCloud seedfrom value '$v'"
;;
esac
done
;;
*) log -s warning "Unknown NoCloud kernel cmdline key '$k'"
;;
esac
done
return
done
return 1
for kopt in $(cat "$ROOT/proc/cmdline" 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)
v=$(echo "$kv" | cut -d= -f2-)
case "$k" in
h|local-hostname)
printf "\nlocal-hostname: %s" "$v" >> "$TINY_CLOUD_VAR/meta-data"
;;
i|instance-id)
printf "\ninstance-id: %s" "$v" >> "$TINY_CLOUD_VAR/meta-data"
;;
s|seedfrom)
for data in $NOCLOUD_FILES; do
case "${v#file:/}" in
/*)
cat "$v/$data" >> "$TINY_CLOUD_VAR/$data" || continue
echo >> "$TINY_CLOUD_VAR/$data"
;;
http://*|https://*)
wget -qO - "$v/$data" >> "$TINY_CLOUD_VAR/$data" || continue
echo >> "$TINY_CLOUD_VAR/$data"
;;
*) log -s warning "Unknown NoCloud seedfrom value '$v'"
;;
esac
done
;;
*) log -s warning "Unknown NoCloud kernel cmdline key '$k'"
;;
esac
done
return
done
return 1
}
_load_nocloud_volume() {
mkdir -p "$ROOT"/run/tiny-cloud
local mntdir=$(mktemp -d "$ROOT/run/tiny-cloud/cidata-XXXXXX")
local data mounted
mkdir -p "$ROOT"/run/tiny-cloud
local mntdir=$(mktemp -d "$ROOT/run/tiny-cloud/cidata-XXXXXX")
local data mounted
mkdir -p "$mntdir"
for fstype in vfat iso9660; do
[ "$mounted" ] && break
for label in cidata CIDATA; do
[ -n "$mounted" ] && break
mount -o ro -t "$fstype" LABEL="$label" "$mntdir" && mounted=1
done
done
if [ -n "$mounted" ]; then
for data in $NOCLOUD_FILES; do
# lack of source results in empty target
cat "$mntdir/$data" > "$TINY_CLOUD_VAR/$data" 2>/dev/null
done
umount "$mntdir"
else
return 1
fi
rmdir "$mntdir"
mkdir -p "$mntdir"
for fstype in vfat iso9660; do
[ "$mounted" ] && break
for label in cidata CIDATA; do
[ -n "$mounted" ] && break
mount -o ro -t "$fstype" LABEL="$label" "$mntdir" && mounted=1
done
done
if [ -n "$mounted" ]; then
for data in $NOCLOUD_FILES; do
# lack of source results in empty target
cat "$mntdir/$data" > "$TINY_CLOUD_VAR/$data" 2>/dev/null
done
umount "$mntdir"
else
return 1
fi
rmdir "$mntdir"
}
load_nocloud() {
# start with a clean slate
(cd "$TINY_CLOUD_VAR" && rm -f $NOCLOUD_FILES)
# start with a clean slate
(cd "$TINY_CLOUD_VAR" && rm -f $NOCLOUD_FILES)
if _load_nocloud_cmdline || _load_nocloud_volume; then
touch "$TINY_CLOUD_VAR/.nocloud_loaded"
else
log -s err "Unable to load NoCloud datasource"
return 1
fi
if _load_nocloud_cmdline || _load_nocloud_volume; then
touch "$TINY_CLOUD_VAR/.nocloud_loaded"
else
log -s err "Unable to load NoCloud datasource"
return 1
fi
# minimally, we expect some content in meta-data
[ -s "$TINY_CLOUD_VAR/meta-data" ] ||
log -s warning "NoCloud 'meta-data' is empty"
# minimally, we expect some content in meta-data
[ -s "$TINY_CLOUD_VAR/meta-data" ] ||
log -s warning "NoCloud 'meta-data' is empty"
}
_imds() {
mkdir -p "$TINY_CLOUD_VAR"
local file="$TINY_CLOUD_VAR/$(echo "$1" | cut -d/ -f1)"
local keypath="$(echo "$1" | cut -d/ -f2- | tr / ' ')"
mkdir -p "$TINY_CLOUD_VAR"
local file="$TINY_CLOUD_VAR/$(echo "$1" | cut -d/ -f1)"
local keypath="$(echo "$1" | cut -d/ -f2- | tr / ' ')"
is_nocloud_loaded || load_nocloud
is_nocloud_loaded || load_nocloud
# does file exist?
[ -f "$file" ] || return 1
# does file exist?
[ -f "$file" ] || return 1
# use 'file/' to get top-level keys
if [ $(basename "$file") = "$keypath" ]; then
cat "$file"
else
yx -f "$file" $keypath
fi
# use 'file/' to get top-level keys
if [ $(basename "$file") = "$keypath" ]; then
cat "$file"
else
yx -f "$file" $keypath
fi
}

View File

@ -1,5 +1,5 @@
# OCI Instance MetaData Service variables and functions
# vim:set ts=4 et ft=sh:
# vim:set ft=sh:
# shellcheck shell=sh
IMDS_HEADER="Authorization"
@ -13,25 +13,25 @@ IMDS_NICS="nics"
# TODO: flesh out networking
unset \
IMDS_MAC \
IMDS_IPV4 \
IMDS_IPV6 \
IMDS_IPV4_NET \
IMDS_IPV6_NET \
IMDS_IPV4_PREFIX \
IMDS_IPV6_PREFIX
IMDS_MAC \
IMDS_IPV4 \
IMDS_IPV6 \
IMDS_IPV4_NET \
IMDS_IPV6_NET \
IMDS_IPV4_PREFIX \
IMDS_IPV6_PREFIX
_imds_header() {
echo "$IMDS_HEADER: Bearer Oracle"
echo "$IMDS_HEADER: Bearer Oracle"
}
_imds_ssh_keys() { _imds "$IMDS_SSH_KEYS"; }
_imds_nic_index() {
local m n=0
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
return 1
local m n=0
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
return 1
}

View File

@ -1,5 +1,5 @@
# Tiny Cloud - common script functions
# vim: ts=4 et ft=sh:
# vim:set ft=sh:
# shellcheck shell=sh
# set defaults
@ -10,62 +10,62 @@
: "${TINY_CLOUD_VAR:=$ROOT/var/lib/cloud}"
log() {
local facility="local7"
local stderr init
local tag=$(basename "$0")
while [ "${1#-}" != "$1" ]; do
case "$1" in
-i) init=1 ;; # TODO: value = indent?
-f) facility="$2"; shift ;;
-s) stderr=-s ;;
-t) tag="$tag/$2"; shift ;;
esac
shift
done
local level="$1"
[ -z "$DEBUG" ] && [ "$level" = debug ] && return
shift
local facility="local7"
local stderr init
local tag=$(basename "$0")
while [ "${1#-}" != "$1" ]; do
case "$1" in
-i) init=1 ;; # TODO: value = indent?
-f) facility="$2"; shift ;;
-s) stderr=-s ;;
-t) tag="$tag/$2"; shift ;;
esac
shift
done
local level="$1"
[ -z "$DEBUG" ] && [ "$level" = debug ] && return
shift
[ -n "$init" ] && echo "$@" >&2
logger $stderr -p "$facility.$level" -t "${tag}[$$]" "$@"
case "$level" in
crit|alert|emerg) exit 1 ;;
esac
[ -n "$init" ] && echo "$@" >&2
logger $stderr -p "$facility.$level" -t "${tag}[$$]" "$@"
case "$level" in
crit|alert|emerg) exit 1 ;;
esac
}
# usage: replace_word <search> <replace> <list>...
replace_word() {
local search="$1" replace="$2"
shift 2
for word in "$@"; do
if [ "$word" = "$search" ]; then
echo "$replace"
else
echo "$word"
fi
done
local search="$1" replace="$2"
shift 2
for word in "$@"; do
if [ "$word" = "$search" ]; then
echo "$replace"
else
echo "$word"
fi
done
}
# usage: insert_after <where> <what> <list>...
insert_after() {
local search="$1" addition="$2"
shift 2
for i in "$@"; do
echo "$i"
if [ "$i" = "$search" ]; then
echo "$addition"
fi
done
local search="$1" addition="$2"
shift 2
for i in "$@"; do
echo "$i"
if [ "$i" = "$search" ]; then
echo "$addition"
fi
done
}
# usage: add_once <file> <line-to-add>...
add_once() {
local file="$1"
shift
for line; do
if ! grep -x -F "$line" "$file" 2>/dev/null; then
mkdir -p "${file%/*}"
printf "%s\n" "$line" >> "$file"
fi
done
local file="$1"
shift
for line; do
if ! grep -x -F "$line" "$file" 2>/dev/null; then
mkdir -p "${file%/*}"
printf "%s\n" "$line" >> "$file"
fi
done
}

View File

@ -1,5 +1,5 @@
# Tiny Cloud - Init Functions
# vim:set ts=4 et ft=sh:
# vim:set ft=sh:
# shellcheck shell=sh
# set defaults
@ -12,18 +12,18 @@
### default phase actions (without leading 'init__')
DEFAULT_ACTIONS_EARLY="
expand_root
install_hotplugs
set_default_interfaces
create_default_user
enable_sshd
expand_root
install_hotplugs
set_default_interfaces
create_default_user
enable_sshd
"
DEFAULT_ACTIONS_NET="
save_userdata
save_userdata
"
DEFAULT_ACTIONS_MAIN="
set_hostname
set_ssh_keys
set_hostname
set_ssh_keys
"
DEFAULT_ACTIONS_FINAL=""
@ -40,236 +40,236 @@ DEFAULT_ACTIONS_FINAL=""
### standard init-early 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}' "$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)
# only support ext2/ext3/ext4 for now
case "$filesystem" in
ext*) ;;
*) return;;
esac
# only support ext2/ext3/ext4 for now
case "$filesystem" in
ext*) ;;
*) return;;
esac
if [ -n "$partition" ]; then
# it's a partition, resize it
local volume=$(readlink -f "$ROOT/sys/class/block/${dev#/dev/}/..")
volume="/dev/${volume##*/}"
echo ", +" | $MOCK sfdisk -q --no-reread -N "$partition" "$volume"
$MOCK partx -u "$volume"
fi
# resize filesystem
$MOCK resize2fs "$dev"
if [ -n "$partition" ]; then
# it's a partition, resize it
local volume=$(readlink -f "$ROOT/sys/class/block/${dev#/dev/}/..")
volume="/dev/${volume##*/}"
echo ", +" | $MOCK sfdisk -q --no-reread -N "$partition" "$volume"
$MOCK partx -u "$volume"
fi
# resize filesystem
$MOCK resize2fs "$dev"
}
init__install_hotplugs() {
local level result rc=0
local level result rc=0
[ ! -n "$HOTPLUG_MODULES" ] && return
if [ -f "$LIBDIR/tiny-cloud/$HOTPLUG_TYPE" ]; then
. "$LIBDIR/tiny-cloud/$HOTPLUG_TYPE"
fi
[ ! -n "$HOTPLUG_MODULES" ] && return
if [ -f "$LIBDIR/tiny-cloud/$HOTPLUG_TYPE" ]; then
. "$LIBDIR/tiny-cloud/$HOTPLUG_TYPE"
fi
for module in $HOTPLUG_MODULES; do
result='unknown'
level='err'
printf " >> " >&2
log -i -t "$phase/$ACTION" info "$module: installing"
if type "mod__$module" | grep -q -w "function"; then
if "mod__$module"; then
result='installed'
level='info'
else
result='failed'
rc=1
fi
fi
printf " >> " >&2
log -i -t "$phase/$ACTION" info "$module: $result"
done
return $rc
for module in $HOTPLUG_MODULES; do
result='unknown'
level='err'
printf " >> " >&2
log -i -t "$phase/$ACTION" info "$module: installing"
if type "mod__$module" | grep -q -w "function"; then
if "mod__$module"; then
result='installed'
level='info'
else
result='failed'
rc=1
fi
fi
printf " >> " >&2
log -i -t "$phase/$ACTION" info "$module: $result"
done
return $rc
}
# collect ethernet interfaces, sorted by index
ethernets() {
for i in "$ROOT/sys/class/net/"*; do
local iface="${i##*/}"
case "$iface" in
eth*) echo "$(cat "$i/ifindex") $iface";;
esac
done | sort -n | awk '{print $2}'
for i in "$ROOT/sys/class/net/"*; do
local iface="${i##*/}"
case "$iface" in
eth*) echo "$(cat "$i/ifindex") $iface";;
esac
done | sort -n | awk '{print $2}'
}
# find the interface that is has operstate up
find_first_interface_up() {
local n=0
[ $# -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
echo "$i"
return
fi
done
sleep 0.1
n=$((n+1))
done
local n=0
[ $# -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
echo "$i"
return
fi
done
sleep 0.1
n=$((n+1))
done
}
# auto detect which network interface to auto configure
# check which is connected or fallback to first
# This will set link to down to all eth* except the found
auto_detect_ethernet_interface() {
local ifaces="$(ethernets)"
[ -z "$ifaces" ] && return
local ifaces="$(ethernets)"
[ -z "$ifaces" ] && return
# find first connected interface
for i in $ifaces; do
$MOCK ip link set dev $i up >/dev/null
done
local iface="$(find_first_interface_up $ifaces)"
# find first connected interface
for i in $ifaces; do
$MOCK ip link set dev $i up >/dev/null
done
local iface="$(find_first_interface_up $ifaces)"
# use first if all are disconnected
if [ -z "$iface" ]; then
set -- $ifaces
iface="$1"
fi
# use first if all are disconnected
if [ -z "$iface" ]; then
set -- $ifaces
iface="$1"
fi
# we will use the found interface later so lets keep it up
for i in $ifaces; do
if [ "$i" != "$iface" ]; then
$MOCK ip link set dev $i down >/dev/null
fi
done
echo "$iface"
# we will use the found interface later so lets keep it up
for i in $ifaces; do
if [ "$i" != "$iface" ]; then
$MOCK ip link set dev $i down >/dev/null
fi
done
echo "$iface"
}
init__set_default_interfaces() {
if [ -f "$ROOT"/etc/network/interfaces ]; then
log -i -t "$phase" info "$ACTION: already set up"
return
fi
if [ -f "$ROOT"/etc/network/interfaces ]; then
log -i -t "$phase" info "$ACTION: already set up"
return
fi
mkdir -p "$ROOT/etc/network"
printf "%s\n%s\n\n" \
"auto lo" \
"iface lo inet loopback" \
> "$ROOT/etc/network/interfaces"
mkdir -p "$ROOT/etc/network"
printf "%s\n%s\n\n" \
"auto lo" \
"iface lo inet loopback" \
> "$ROOT/etc/network/interfaces"
local iface="$(auto_detect_ethernet_interface)"
if [ -z "$iface" ]; then
# TODO: message/log?
return
fi
printf "%s\n%s\n\t%s\n\n" \
"auto $iface" \
"iface $iface" \
"use dhcp" >> "$ROOT/etc/network/interfaces"
local iface="$(auto_detect_ethernet_interface)"
if [ -z "$iface" ]; then
# TODO: message/log?
return
fi
printf "%s\n%s\n\t%s\n\n" \
"auto $iface" \
"iface $iface" \
"use dhcp" >> "$ROOT/etc/network/interfaces"
}
init__create_default_user() {
local user="$CLOUD_USER"
# don't do anything if it already exists
if getent passwd "$user" >/dev/null; then
log -i -t "$phase" info "$ACTION: already exists"
return
fi
local user="$CLOUD_USER"
# don't do anything if it already exists
if getent passwd "$user" >/dev/null; then
log -i -t "$phase" info "$ACTION: already exists"
return
fi
$MOCK addgroup "$user"
$MOCK adduser -h "/home/$user" -s /bin/sh -G "$user" -D "$user"
$MOCK addgroup "$user" wheel
echo "$user:*" | $MOCK chpasswd -e
$MOCK addgroup "$user"
$MOCK adduser -h "/home/$user" -s /bin/sh -G "$user" -D "$user"
$MOCK addgroup "$user" wheel
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"
fi
if [ -d "$ROOT/etc/doas.d" ]; then
echo 'permit nopass :wheel' > "$TARGET/etc/doas.d/wheel.conf"
fi
# setup sudo and/or doas
if [ -d "$ROOT/etc/sudoers.d" ]; then
echo '%wheel ALL=(ALL) NOPASSWD: ALL' > "$ROOT/etc/sudoers.d/wheel"
fi
if [ -d "$ROOT/etc/doas.d" ]; then
echo 'permit nopass :wheel' > "$TARGET/etc/doas.d/wheel.conf"
fi
}
init__enable_sshd() {
$MOCK rc-update add sshd default
# in case something else has enabled/disabled dservices
$MOCK rc-update --update
$MOCK rc-update add sshd default
# in case something else has enabled/disabled dservices
$MOCK rc-update --update
}
### standard init-main functions
init__set_hostname() {
local fqdn=$(imds @hostname)
if [ -z "$fqdn" ]; then
log -i -t "$phase" info "$ACTION: no hostname set"
return
fi
local fqdn=$(imds @hostname)
if [ -z "$fqdn" ]; then
log -i -t "$phase" info "$ACTION: no hostname set"
return
fi
local host="${fqdn%%\.*}"
if [ -z "$host" ]; then
log -i -t "$phase" warn "$ACTION: invalid hostname '$fqdn'"
return 1
fi
local host="${fqdn%%\.*}"
if [ -z "$host" ]; then
log -i -t "$phase" warn "$ACTION: invalid hostname '$fqdn'"
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 "$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
}
init__set_ssh_keys() {
local sshkeys="$(imds @ssh-keys)"
if [ -z "$sshkeys" ]; then
log -i -t "$phase" info "$ACTION: no ssh key found"
return
fi
local user="$CLOUD_USER"
local pwent="$(getent passwd "$user")"
if [ -z "$pwent" ]; then
log -i -t "$phase" err "$ACTION: failed to find user $user"
return 1
fi
local group=$(echo "$pwent" | cut -d: -f4)
local ssh_dir="${ROOT}$(echo "$pwent" | cut -d: -f6)/.ssh"
local keys_file="$ssh_dir/authorized_keys"
local sshkeys="$(imds @ssh-keys)"
if [ -z "$sshkeys" ]; then
log -i -t "$phase" info "$ACTION: no ssh key found"
return
fi
local user="$CLOUD_USER"
local pwent="$(getent passwd "$user")"
if [ -z "$pwent" ]; then
log -i -t "$phase" err "$ACTION: failed to find user $user"
return 1
fi
local group=$(echo "$pwent" | cut -d: -f4)
local ssh_dir="${ROOT}$(echo "$pwent" | cut -d: -f6)/.ssh"
local keys_file="$ssh_dir/authorized_keys"
if [ ! -d "$ssh_dir" ]; then
mkdir -p "$ssh_dir"
chmod 700 "$ssh_dir"
fi
if [ ! -d "$ssh_dir" ]; then
mkdir -p "$ssh_dir"
chmod 700 "$ssh_dir"
fi
touch "$keys_file"
chmod 600 "$keys_file"
$MOCK chown -R "$user:$group" "$ssh_dir"
echo "$sshkeys" > "$keys_file"
touch "$keys_file"
chmod 600 "$keys_file"
$MOCK chown -R "$user:$group" "$ssh_dir"
echo "$sshkeys" > "$keys_file"
}
init__save_userdata() {
local userdata="$TINY_CLOUD_VAR/user-data"
if [ -f "$userdata" ]; then
log -i -t "$phase" info "$ACTION: user-data already saved"
return
fi
local tmpfile=$(mktemp "$userdata.XXXXXX")
local userdata="$TINY_CLOUD_VAR/user-data"
if [ -f "$userdata" ]; then
log -i -t "$phase" info "$ACTION: user-data already saved"
return
fi
local tmpfile=$(mktemp "$userdata.XXXXXX")
imds -e @userdata > "$tmpfile"
if printf '\037\213\010' | cmp -s -n 3 "$tmpfile"; then
gzip -dc "$tmpfile" > "$userdata"
elif printf 'BZh' | cmp -s -n 3 "$tmpfile"; then
bzip2 -dc "$tmpfile" > "$userdata"
elif printf '\375\067\172\130\132\000' | cmp -s -n 6 "$tmpfile"; then
unxz -c "$tmpfile" > "$userdata"
elif printf '\135\000\000' | cmp -s -n 3 "$tmpfile"; then
lzma -dc "$tmpfile" > "$userdata"
elif printf '\211\114\132' | cmp -s -n 3 "$tmpfile"; then
lzop -dc "$tmpfile" > "$userdata"
elif printf '\004\042\115\030' | cmp -s -n 4 "$tmpfile"; then
lz4 -dc "$tmpfile" > "$userdata"
elif printf '(\265/\375' | cmp -s -n 4 "$tmpfile"; then
zstd -dc "$tmpfile" > "$userdata"
else
cp "$tmpfile" "$userdata"
fi
rm "$tmpfile"
imds -e @userdata > "$tmpfile"
if printf '\037\213\010' | cmp -s -n 3 "$tmpfile"; then
gzip -dc "$tmpfile" > "$userdata"
elif printf 'BZh' | cmp -s -n 3 "$tmpfile"; then
bzip2 -dc "$tmpfile" > "$userdata"
elif printf '\375\067\172\130\132\000' | cmp -s -n 6 "$tmpfile"; then
unxz -c "$tmpfile" > "$userdata"
elif printf '\135\000\000' | cmp -s -n 3 "$tmpfile"; then
lzma -dc "$tmpfile" > "$userdata"
elif printf '\211\114\132' | cmp -s -n 3 "$tmpfile"; then
lzop -dc "$tmpfile" > "$userdata"
elif printf '\004\042\115\030' | cmp -s -n 4 "$tmpfile"; then
lz4 -dc "$tmpfile" > "$userdata"
elif printf '(\265/\375' | cmp -s -n 4 "$tmpfile"; then
zstd -dc "$tmpfile" > "$userdata"
else
cp "$tmpfile" "$userdata"
fi
rm "$tmpfile"
}
@ -279,26 +279,26 @@ init__save_userdata() {
### load cloud-specific init functions / vars (potentially overriding)
if [ -f "$LIBDIR/tiny-cloud/cloud/$CLOUD/init" ]; then
. "$LIBDIR/tiny-cloud/cloud/$CLOUD/init"
. "$LIBDIR/tiny-cloud/cloud/$CLOUD/init"
fi
### load user-data type-specific init functions / vars (potentially overriding)
userdata_type() {
if [ ! -f "$TINY_CLOUD_VAR/user-data" ]; then
echo missing
return
fi
header=$(head -n1 "$TINY_CLOUD_VAR/user-data" | sed -e 's/[[:space:]].*//g')
case "$header" in
'#!'*) echo script;;
'#'*) echo ${header#\#};;
*) echo unknown;;
esac
if [ ! -f "$TINY_CLOUD_VAR/user-data" ]; then
echo missing
return
fi
header=$(head -n1 "$TINY_CLOUD_VAR/user-data" | sed -e 's/[[:space:]].*//g')
case "$header" in
'#!'*) echo script;;
'#'*) echo ${header#\#};;
*) echo unknown;;
esac
}
USERDATA_TYPE="$(userdata_type)"
if [ -f "$LIBDIR/tiny-cloud/user-data/$USERDATA_TYPE" ]; then
. "$LIBDIR/tiny-cloud/user-data/$USERDATA_TYPE"
. "$LIBDIR/tiny-cloud/user-data/$USERDATA_TYPE"
fi

View File

@ -1,36 +1,36 @@
# Tiny Cloud - mdev hotplug functions
# vim:set ts=4 et ft=sh:
# vim:set ft=sh:
# shellcheck shell=sh
# generic helper function to install mdev rules
install_before() {
local before="$1"
shift
local line="$*"
local before="$1"
shift
local line="$*"
# already installed
fgrep -q "$line" /etc/mdev.conf && return 0
# already installed
fgrep -q "$line" /etc/mdev.conf && return 0
if grep -q "$before" /etc/mdev.conf; then
# install before existing rule
line="-$line"
else
# no rule exists, put it before the catch-all fallback
before="^# fallback"
line="$line\n"
fi
sed -i -Ee "s|($before.*)|$line\n\1|" /etc/mdev.conf
if grep -q "$before" /etc/mdev.conf; then
# install before existing rule
line="-$line"
else
# no rule exists, put it before the catch-all fallback
before="^# fallback"
line="$line\n"
fi
sed -i -Ee "s|($before.*)|$line\n\1|" /etc/mdev.conf
}
# hotpluggable VNICs (multi-cloud)
mod__vnic_eth_hotplug() {
[ -f /lib/mdev/vnic-eth-hotplug ] || return 1
[ -f /lib/mdev/vnic-eth-hotplug ] || return 1
install_before "^eth" \
"eth[0-9] root:root 0644 */lib/mdev/vnic-eth-hotplug"
install_before "^eth" \
"eth[0-9] root:root 0644 */lib/mdev/vnic-eth-hotplug"
# NICs attached at launch don't get added with mdev -s
assemble-interfaces
# NICs attached at launch don't get added with mdev -s
assemble-interfaces
}
# load cloud-specific functions

View File

@ -1,117 +1,117 @@
# Script UserData Functions
# vim:set ts=4 et ft=sh:
# vim:set ft=sh:
# shellcheck shell=sh
INIT_ACTIONS_MAIN="$(insert_after set_hostname \
"userdata_bootcmd userdata_write_files userdata_ntp userdata_apk_cache userdata_apk_repositories userdata_packages" \
$INIT_ACTIONS_MAIN)"
"userdata_bootcmd userdata_write_files userdata_ntp userdata_apk_cache userdata_apk_repositories userdata_packages" \
$INIT_ACTIONS_MAIN)"
INIT_ACTIONS_FINAL="$INIT_ACTIONS_FINAL userdata_runcmd"
get_userdata() {
IFS="/"
yx -f "$TINY_CLOUD_VAR/user-data" $1 2>/dev/null
unset IFS
IFS="/"
yx -f "$TINY_CLOUD_VAR/user-data" $1 2>/dev/null
unset IFS
}
init__userdata_bootcmd() {
# run bootcmd
local bootcmds="$(get_userdata bootcmd)"
for i in $bootcmds; do
local cmd="$(get_userdata bootcmd/"$i")"
sh -c "$cmd"
done
# run bootcmd
local bootcmds="$(get_userdata bootcmd)"
for i in $bootcmds; do
local cmd="$(get_userdata bootcmd/"$i")"
sh -c "$cmd"
done
}
init__userdata_ntp() {
local ntp_enabled="$(get_userdata ntp/enabled)"
if [ "$ntp_enabled" != "yes" ] && [ "$ntp_enabled" != "true" ]; then
return
fi
local ntp_client="$(get_userdata ntp/ntp_client)"
local svc= pkg=
case "$ntp_client" in
busybox)
svc=ntpd
;;
chrony|"")
pkg=chrony
svc=chronyd
;;
openntpd)
pkg=openntpd
svc=openntpd
;;
esac
if [ -n "$pkg" ]; then
$MOCK apk add "$pkg"
fi
if [ -n "$svc" ]; then
$MOCK rc-update add "$svc" default
$MOCK rc-service "$svc" start
fi
local ntp_enabled="$(get_userdata ntp/enabled)"
if [ "$ntp_enabled" != "yes" ] && [ "$ntp_enabled" != "true" ]; then
return
fi
local ntp_client="$(get_userdata ntp/ntp_client)"
local svc= pkg=
case "$ntp_client" in
busybox)
svc=ntpd
;;
chrony|"")
pkg=chrony
svc=chronyd
;;
openntpd)
pkg=openntpd
svc=openntpd
;;
esac
if [ -n "$pkg" ]; then
$MOCK apk add "$pkg"
fi
if [ -n "$svc" ]; then
$MOCK rc-update add "$svc" default
$MOCK rc-service "$svc" start
fi
}
init__userdata_apk_cache() {
local cache="$(get_userdata apk/cache)"
if [ -z "$cache" ]; then
return
fi
mkdir -p "$ROOT/$cache"
# make link relative
case "$cache" in
/*) cache="../..$cache";;
esac
mkdir -p "$ROOT"/etc/apk
ln -sf "$cache" "$ROOT"/etc/apk/cache
local cache="$(get_userdata apk/cache)"
if [ -z "$cache" ]; then
return
fi
mkdir -p "$ROOT/$cache"
# make link relative
case "$cache" in
/*) cache="../..$cache";;
esac
mkdir -p "$ROOT"/etc/apk
ln -sf "$cache" "$ROOT"/etc/apk/cache
}
init__userdata_apk_cache() {
local cache="$(get_userdata apk/cache)"
if [ -z "$cache" ]; then
return
fi
mkdir -p "$ROOT/$cache"
# make link relative
case "$cache" in
/*) cache="../..$cache";;
esac
mkdir -p "$ROOT"/etc/apk
ln -sf "$cache" "$ROOT"/etc/apk/cache
local cache="$(get_userdata apk/cache)"
if [ -z "$cache" ]; then
return
fi
mkdir -p "$ROOT/$cache"
# make link relative
case "$cache" in
/*) cache="../..$cache";;
esac
mkdir -p "$ROOT"/etc/apk
ln -sf "$cache" "$ROOT"/etc/apk/cache
}
init__userdata_apk_repositories() {
local repositories="$(get_userdata apk/repositories)"
mkdir -p "$ROOT"/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")
case "$version_id" in
edge*|*_alpha*) version="edge";;
[0-9]*.[0-9]*.[0-9]*) version="v${version_id%.*}";;
esac
fi
if [ -n "$version" ] && [ "$version" != "." ] && [ "$version" != "/" ]; then
baseurl="${baseurl%/}/$version"
fi
for repo in $repos; do
local uri="${baseurl%/}/$(get_userdata apk/repositories/$r/repos/$repo)"
add_once "$ROOT"/etc/apk/repositories "$uri"
done
done
local repositories="$(get_userdata apk/repositories)"
mkdir -p "$ROOT"/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")
case "$version_id" in
edge*|*_alpha*) version="edge";;
[0-9]*.[0-9]*.[0-9]*) version="v${version_id%.*}";;
esac
fi
if [ -n "$version" ] && [ "$version" != "." ] && [ "$version" != "/" ]; then
baseurl="${baseurl%/}/$version"
fi
for repo in $repos; do
local uri="${baseurl%/}/$(get_userdata apk/repositories/$r/repos/$repo)"
add_once "$ROOT"/etc/apk/repositories "$uri"
done
done
}
init__userdata_packages() {
local packages="$(get_userdata packages)"
local pkgs=
for i in $packages; do
pkgs="$pkgs $(get_userdata packages/$i)"
done
if [ -n "$pkgs" ]; then
$MOCK apk add $pkgs
fi
local packages="$(get_userdata packages)"
local pkgs=
for i in $packages; do
pkgs="$pkgs $(get_userdata packages/$i)"
done
if [ -n "$pkgs" ]; then
$MOCK apk add $pkgs
fi
}
init__userdata_runcmd() {
@ -124,60 +124,60 @@ init__userdata_runcmd() {
# write_file <path> <mode> <owner> <encoding> <append>
write_file() {
# Defaults used are the same as for full cloud-init "spec":
# https://cloudinit.readthedocs.io/en/latest/reference/modules.html#write-files
local path="$1"
local mode="${2:-0644}"
local owner="${3:-root:root}"
local encoding="${4:-text/plain}"
local append="${5:-false}"
# Defaults used are the same as for full cloud-init "spec":
# https://cloudinit.readthedocs.io/en/latest/reference/modules.html#write-files
local path="$1"
local mode="${2:-0644}"
local owner="${3:-root:root}"
local encoding="${4:-text/plain}"
local append="${5:-false}"
if [ "$append" != "true" ] && [ "$append" != "false" ]; then
log err "append must be true or false"
return
fi
if [ "$append" != "true" ] && [ "$append" != "false" ]; then
log err "append must be true or false"
return
fi
local tmpfile="$(mktemp $TINY_CLOUD_VAR/user-data.write_files.XXXXXX)"
local tmpfile="$(mktemp $TINY_CLOUD_VAR/user-data.write_files.XXXXXX)"
case "$encoding" in
gzip|gz|gz+base64|gzip+base64|gz+b64|gzip+b64)
base64 -d | gzip -d > "$tmpfile"
;;
base64|b64)
base64 -d > "$tmpfile"
;;
text/plain)
cat > "$tmpfile"
;;
esac
case "$encoding" in
gzip|gz|gz+base64|gzip+base64|gz+b64|gzip+b64)
base64 -d | gzip -d > "$tmpfile"
;;
base64|b64)
base64 -d > "$tmpfile"
;;
text/plain)
cat > "$tmpfile"
;;
esac
if [ "$append" = "true" ]; then
cat "$tmpfile" >> "$path"
else
cat "$tmpfile" > "$path"
fi
rm -f "$tmpfile"
if [ "$append" = "true" ]; then
cat "$tmpfile" >> "$path"
else
cat "$tmpfile" > "$path"
fi
rm -f "$tmpfile"
chmod "$mode" "$path"
# mocked as we do not know which users we could use in testing
# this way we can check the proper invocation at least
$MOCK chown "$owner" "$path"
chmod "$mode" "$path"
# mocked as we do not know which users we could use in testing
# this way we can check the proper invocation at least
$MOCK chown "$owner" "$path"
}
init__userdata_write_files() {
local files="$(get_userdata write_files)"
local files="$(get_userdata write_files)"
for i in $files; do
local path="$(get_userdata write_files/$i/path)"
if [ -z "$path" ]; then
continue
fi
for i in $files; do
local path="$(get_userdata write_files/$i/path)"
if [ -z "$path" ]; then
continue
fi
mkdir -p "$(dirname "$ROOT/$path")"
get_userdata write_files/$i/content | write_file "$ROOT/$path" \
"$(get_userdata write_files/$i/permissions)" \
"$(get_userdata write_files/$i/owner)" \
"$(get_userdata write_files/$i/encoding)" \
"$(get_userdata write_files/$i/append)"
done
mkdir -p "$(dirname "$ROOT/$path")"
get_userdata write_files/$i/content | write_file "$ROOT/$path" \
"$(get_userdata write_files/$i/permissions)" \
"$(get_userdata write_files/$i/owner)" \
"$(get_userdata write_files/$i/encoding)" \
"$(get_userdata write_files/$i/append)"
done
}

View File

@ -1,5 +1,5 @@
# CloudConfig UserData Functions
# vim:set ts=4 et ft=sh:
# vim:set ft=sh:
# shellcheck shell=sh
# TODO

View File

@ -1,9 +1,9 @@
# Missing UserData Functions
# vim:set ts=4 et ft=sh:
# vim:set ft=sh:
# shellcheck shell=sh
init__missing_userdata() {
log -i -t "$phase" notice "$ACTION: no user-data found"
log -i -t "$phase" notice "$ACTION: no user-data found"
}
INIT_ACTIONS_MAIN="missing_userdata ${INIT_ACTIONS_MAIN}"

View File

@ -1,16 +1,16 @@
# Script UserData Functions
# vim:set ts=4 et ft=sh:
# vim:set ft=sh:
# shellcheck shell=sh
init__run_userdata() {
local log="$TINY_CLOUD_LOGS/user-data.log"
local exit="$TINY_CLOUD_LOGS/user-data.exit"
local userdata="$TINY_CLOUD_VAR/user-data"
local log="$TINY_CLOUD_LOGS/user-data.log"
local exit="$TINY_CLOUD_LOGS/user-data.exit"
local userdata="$TINY_CLOUD_VAR/user-data"
chmod u+x "$userdata"
{ "$userdata" 2>& 1; echo $? > "$exit"; } | tee "$log"
chmod u+x "$userdata"
{ "$userdata" 2>& 1; echo $? > "$exit"; } | tee "$log"
return $(cat "$exit")
return $(cat "$exit")
}
# add init actions

View File

@ -1,10 +1,10 @@
# Unknown UserData Functions
# vim:set ts=4 et ft=sh:
# vim:set ft=sh:
# shellcheck shell=sh
init__unknown_userdata() {
local type="$(userdata_type)"
log -i -t "$phase" warn "$ACTION: unable to process '$type' user-data"
local type="$(userdata_type)"
log -i -t "$phase" warn "$ACTION: unable to process '$type' user-data"
}
INIT_ACTIONS_MAIN="unknown_userdata ${INIT_ACTIONS_MAIN}"

View File

@ -1,5 +1,5 @@
#!/bin/sh
# vim:set ts=4 et:
# vim:set ft=sh:
set -e
@ -10,33 +10,33 @@ cd "$IFACE_DIR"
cat > "$IFACE_CFG.new" <<EOT
# NOTE: $0 rewrites this file. Edit files in
# /etc/network/interfaces.d/ to persist any customizations.
# /etc/network/interfaces.d/ to persist any customizations.
EOT
# existing loopback and eths
for i in $ROOT/sys/class/net/*; do
IFACE="$(basename "$i")"
case $IFACE in
lo|eth*)
[ ! -f "$IFACE" ] && sed -e "s/%%/$IFACE/g" DEFAULT > "$IFACE"
printf "%s\n\n" "$(cat "$IFACE")" >> "$IFACE_CFG.new"
;;
*) continue ;;
esac
IFACE="$(basename "$i")"
case $IFACE in
lo|eth*)
[ ! -f "$IFACE" ] && sed -e "s/%%/$IFACE/g" DEFAULT > "$IFACE"
printf "%s\n\n" "$(cat "$IFACE")" >> "$IFACE_CFG.new"
;;
*) continue ;;
esac
done
# all the rest
for i in "$IFACE_DIR"/*; do
IFACE="$(basename "$i")"
case $IFACE in
DEFAULT|lo|eth*)
continue
;;
*)
printf "%s\n\n" "$(cat "$IFACE")" >> "$IFACE_CFG.new"
;;
esac
IFACE="$(basename "$i")"
case $IFACE in
DEFAULT|lo|eth*)
continue
;;
*)
printf "%s\n\n" "$(cat "$IFACE")" >> "$IFACE_CFG.new"
;;
esac
done
# install new interfaces config

View File

@ -1,5 +1,5 @@
#!/bin/sh
# vim: ts=4 et ft=sh:
# vim:set ft=sh:
# Sync interface's network configuration with IMDS
@ -21,129 +21,129 @@ let RTABLE+=10000
# ip [+F] [-4|-6] <object> <command> [<parameters>]
ip() {
local fail_ok v=-4 cmd level
[ "$1" = '+F' ] && fail_ok=1 && shift
if [ "$1" = '-4' ] || [ "$1" = '-6' ]; then
v="$1"
shift
fi
cmd="$2"
[ "$cmd" = show ] && level=debug || level=info
if /sbin/ip "$v" "$@" || [ -n "$fail_ok" ]; then
log -s "$level" "OK: ip $v $*"
else
log -s err "FAIL: ip $v $*"
fi
local fail_ok v=-4 cmd level
[ "$1" = '+F' ] && fail_ok=1 && shift
if [ "$1" = '-4' ] || [ "$1" = '-6' ]; then
v="$1"
shift
fi
cmd="$2"
[ "$cmd" = show ] && level=debug || level=info
if /sbin/ip "$v" "$@" || [ -n "$fail_ok" ]; then
log -s "$level" "OK: ip $v $*"
else
log -s err "FAIL: ip $v $*"
fi
}
# get secondary IPv4s currently on the interface
iface_ip4s() {
ip -4 addr show "$IFACE" secondary |
sed -E -e '/inet /!d' -e 's/.*inet ([0-9.]+).*/\1/'
ip -4 addr show "$IFACE" secondary |
sed -E -e '/inet /!d' -e 's/.*inet ([0-9.]+).*/\1/'
}
# get IPv6s currently on the interface
iface_ip6s() {
ip -6 addr show "$IFACE" scope global |
sed -E -e '/inet6/!d' -e 's/.*inet6 ([0-9a-f:]+).*/\1/'
ip -6 addr show "$IFACE" scope global |
sed -E -e '/inet6/!d' -e 's/.*inet6 ([0-9a-f:]+).*/\1/'
}
imds_ip4s() {
local ip4=$(imds "@nic:$IFACE,@ipv4")
local ip4s=$(echo "$ip4" | tail +2) # secondary IPv4s
local ip4p ip4_cidr ip4_gw
local ip4=$(imds "@nic:$IFACE,@ipv4")
local ip4s=$(echo "$ip4" | tail +2) # secondary IPv4s
local ip4p ip4_cidr ip4_gw
# non-eth0 interfaces need custom route tables
#
if [ "$IFACE" != eth0 ] && [ -n "$ip4s" ] &&
[ -z $(ip +F -4 route show table "$RTABLE" 2>/dev/null) ]; then
ip4p=$(echo "$ip4" | head -1) # primary IPv4
ip4_cidr=$(imds "@nic:$IFACE,@ipv4-net") # TODO: get from iface instead?
# TODO: this may not hold true for non-AWS clouds
ip4_gw=$(echo "$ip4_cidr" | cut -d/ -f1 |
awk -F. '{ print $1"."$2"."$3"."$4+1 }')
ip -4 route add default via "$ip4_gw" dev "$IFACE" table "$RTABLE"
ip -4 route add "$ip4_cidr" dev "$IFACE" proto kernel scope link \
src "$ip4p" table "$RTABLE"
fi
echo "$ip4s"
# non-eth0 interfaces need custom route tables
#
if [ "$IFACE" != eth0 ] && [ -n "$ip4s" ] &&
[ -z $(ip +F -4 route show table "$RTABLE" 2>/dev/null) ]; then
ip4p=$(echo "$ip4" | head -1) # primary IPv4
ip4_cidr=$(imds "@nic:$IFACE,@ipv4-net") # TODO: get from iface instead?
# TODO: this may not hold true for non-AWS clouds
ip4_gw=$(echo "$ip4_cidr" | cut -d/ -f1 |
awk -F. '{ print $1"."$2"."$3"."$4+1 }')
ip -4 route add default via "$ip4_gw" dev "$IFACE" table "$RTABLE"
ip -4 route add "$ip4_cidr" dev "$IFACE" proto kernel scope link \
src "$ip4p" table "$RTABLE"
fi
echo "$ip4s"
}
# TODO: 3.18+ when we use dhcpcd for ipv4 & ipv6, we only need to do secondary IPv6s
# circle back and see how amazon-ec2-net-utils is handling everything these days
imds_ip6s() {
local ip6s gw tries=20
ip6s=$(imds "@nic:$IFACE,@ipv6")
local ip6s gw tries=20
ip6s=$(imds "@nic:$IFACE,@ipv6")
# non-eth0 interfaces need custom route tables
#
# NOTE: busybox iproute2 doesn't do 'route show table' properly for IPv6,
# so iproute2-minimal package is required!
#
if [ "$IFACE" != eth0 ] && [ -n "$ip6s" ] &&
[ -z $(ip +F -6 route show table "$RTABLE" 2>/dev/null) ]; then
while true; do
gw=$(ip -6 route show dev "$IFACE" default | awk '{ print $3 }')
[ -n "$gw" ] && break
let tries--
if [ "$tries" -eq 0 ]; then
log -s warn "Unable to get IPv6 gateway RA after 10s"
break
fi
sleep 0.5
done
ip -6 route add default via "$gw" dev "$IFACE" table "$RTABLE"
# TODO? match imds_ip4s() with ip -6 route add "ip6_cidr" dev "$IFACE" ...
fi
echo "$ip6s"
# non-eth0 interfaces need custom route tables
#
# NOTE: busybox iproute2 doesn't do 'route show table' properly for IPv6,
# so iproute2-minimal package is required!
#
if [ "$IFACE" != eth0 ] && [ -n "$ip6s" ] &&
[ -z $(ip +F -6 route show table "$RTABLE" 2>/dev/null) ]; then
while true; do
gw=$(ip -6 route show dev "$IFACE" default | awk '{ print $3 }')
[ -n "$gw" ] && break
let tries--
if [ "$tries" -eq 0 ]; then
log -s warn "Unable to get IPv6 gateway RA after 10s"
break
fi
sleep 0.5
done
ip -6 route add default via "$gw" dev "$IFACE" table "$RTABLE"
# TODO? match imds_ip4s() with ip -6 route add "ip6_cidr" dev "$IFACE" ...
fi
echo "$ip6s"
}
in_list() {
echo "$2" | grep -q "^$1$"
echo "$2" | grep -q "^$1$"
}
# ip_addr {4|6} {add|del} <ip>
ip_addr() {
local mask=32 # IPv4 always /32
[ "$1" -eq 6 ] && mask=128 # IPv6 always /128
ip -"$1" addr "$2" "$3/$mask" dev "$IFACE"
local mask=32 # IPv4 always /32
[ "$1" -eq 6 ] && mask=128 # IPv6 always /128
ip -"$1" addr "$2" "$3/$mask" dev "$IFACE"
# TODO? delegated ipv[46] prefixes?
# TODO? delegated ipv[46] prefixes?
# non-eth0 interfaces get rules associating IPs with route tables
[ "$IFACE" = eth0 ] && return
ip -"$1" rule "$2" from "$3" lookup "$RTABLE"
ip -"$1" rule "$2" to "$3" lookup "$RTABLE"
# non-eth0 interfaces get rules associating IPs with route tables
[ "$IFACE" = eth0 ] && return
ip -"$1" rule "$2" from "$3" lookup "$RTABLE"
ip -"$1" rule "$2" to "$3" lookup "$RTABLE"
}
# sync_ips {4|6} "<imds-ips>" "<iface-ips>"
sync_ips() {
local i
# remove extra IPs
for i in $3; do
in_list "$i" "$2" || ip_addr "$1" del "$i"
done
# add missing IPs
# NOTE: this adds an extra <IPv4>/32 for the primary IP
for i in $2; do
in_list "$i" "$3" || ip_addr "$1" add "$i"
done
local i
# remove extra IPs
for i in $3; do
in_list "$i" "$2" || ip_addr "$1" del "$i"
done
# add missing IPs
# NOTE: this adds an extra <IPv4>/32 for the primary IP
for i in $2; do
in_list "$i" "$3" || ip_addr "$1" add "$i"
done
}
imds_iface_sync() {
log -s info "SYNCING: $IFACE"
sync_ips 4 "$(imds_ip4s)" "$(iface_ip4s)"
sync_ips 6 "$(imds_ip6s)" "$(iface_ip6s)"
log -s info "FINISHED: $IFACE"
log -s info "SYNCING: $IFACE"
sync_ips 4 "$(imds_ip4s)" "$(iface_ip4s)"
sync_ips 6 "$(imds_ip6s)" "$(iface_ip6s)"
log -s info "FINISHED: $IFACE"
}
case "$PHASE" in
post-up)
# TODO: daemonize this
imds_iface_sync
;;
pre-down)
# TODO: kill daemon, maybe some cleanup
;;
*)
post-up)
# TODO: daemonize this
imds_iface_sync
;;
pre-down)
# TODO: kill daemon, maybe some cleanup
;;
*)
esac

View File

@ -1,5 +1,5 @@
#!/bin/sh
# vim:set ts=4 et ft=sh:
# vim:set ft=sh:
# Tiny Cloud
@ -9,69 +9,69 @@ set -e
. "$LIBDIR/tiny-cloud/common"
usage() {
cat <<EOF
Usage: ${0##*/} [-h | --help] { early | net | main | final | --bootstrap [complete|incomplete|status] | --setup }
EOF
cat <<-EOF
Usage: ${0##*/} [-h | --help] { early | net | main | final | --bootstrap [complete|incomplete|status] | --setup }
EOF
}
bootstrap_complete() {
touch "$TINY_CLOUD_VAR/.bootstrap-complete"
touch "$TINY_CLOUD_VAR/.bootstrap-complete"
}
bootstrap_incomplete() {
rm -f "$TINY_CLOUD_VAR/.bootstrap-complete"
rm -f "$TINY_CLOUD_VAR/.bootstrap-complete"
}
is_bootstrap_complete() {
[ -f "$TINY_CLOUD_VAR/.bootstrap-complete" ]
[ -f "$TINY_CLOUD_VAR/.bootstrap-complete" ]
}
args=$(getopt -o hsb: --long help,setup,bootstrap: -n ${0##*/} -- "$@") || { usage >&2; exit 1; }
if [ $# -eq 0 ]; then
usage >&2
exit 1
usage >&2
exit 1
fi
eval set -- "$args"
while true; do
case "$1" in
-h|--help) usage; exit 0;;
-b|--bootstrap) shift
case "$1" in
complete) # indicate bootstrap is done
bootstrap_complete
log -i notice 'bootstrap marked complete';;
incomplete) # indicate bootstrap isn't done
bootstrap_incomplete
log -i warn 'bootstrap marked incomplete';;
status) is_bootstrap_complete && echo 'complete' || echo 'incomplete' ;;
*) usage >&2; exit 1;;
esac
exit 0;;
-s|--setup) # just openrc for now
for phase in -early -net '' -final; do
rc-update -a del "tiny-cloud$phase" || true
done
rc-update add tiny-cloud-early boot
rc-update add tiny-cloud-net default
rc-update add tiny-cloud default
rc-update add tiny-cloud-final default
exit 0;;
--) shift; break;;
*) usage >&2; exit 1;;
esac
shift
case "$1" in
-h|--help) usage; exit 0;;
-b|--bootstrap) shift
case "$1" in
complete) # indicate bootstrap is done
bootstrap_complete
log -i notice 'bootstrap marked complete';;
incomplete) # indicate bootstrap isn't done
bootstrap_incomplete
log -i warn 'bootstrap marked incomplete';;
status) is_bootstrap_complete && echo 'complete' || echo 'incomplete' ;;
*) usage >&2; exit 1;;
esac
exit 0;;
-s|--setup) # just openrc for now
for phase in -early -net '' -final; do
rc-update -a del "tiny-cloud$phase" || true
done
rc-update add tiny-cloud-early boot
rc-update add tiny-cloud-net default
rc-update add tiny-cloud default
rc-update add tiny-cloud-final default
exit 0;;
--) shift; break;;
*) usage >&2; exit 1;;
esac
shift
done
phase="$1"
shift
case "$phase" in
early|net|main|final) ;;
*) usage >&2; exit 1;;
early|net|main|final) ;;
*) usage >&2; exit 1;;
esac
# is initial bootstrap already done?
if is_bootstrap_complete; then
log -i -t "$phase" info "already bootstrapped"
exit 0;
log -i -t "$phase" info "already bootstrapped"
exit 0;
fi
# load init functions
@ -81,48 +81,48 @@ fi
# should we skip this action?
skip_action() {
local action="$1"
for i in $SKIP_INIT_ACTIONS; do
[ "$i" = "$action" ] && return 0
done
return 1
local action="$1"
for i in $SKIP_INIT_ACTIONS; do
[ "$i" = "$action" ] && return 0
done
return 1
}
# mandatory final action...
init__bootstrap_complete() {
bootstrap_complete
bootstrap_complete
}
INIT_ACTIONS_FINAL="${INIT_ACTIONS_FINAL} bootstrap_complete"
### let's do stuff!
case "$phase" in
early) INIT_ACTIONS="$INIT_ACTIONS_EARLY";;
net) INIT_ACTIONS="$INIT_ACTIONS_NET";;
main) INIT_ACTIONS="$INIT_ACTIONS_MAIN";;
final) INIT_ACTIONS="$INIT_ACTIONS_FINAL";;
*) usage >&2; exit 1
early) INIT_ACTIONS="$INIT_ACTIONS_EARLY";;
net) INIT_ACTIONS="$INIT_ACTIONS_NET";;
main) INIT_ACTIONS="$INIT_ACTIONS_MAIN";;
final) INIT_ACTIONS="$INIT_ACTIONS_FINAL";;
*) usage >&2; exit 1
esac
printf '\n' >&2
for ACTION in $INIT_ACTIONS; do
if skip_action "$ACTION"; then
printf ' -- ' >&2
log -i -t "$phase" notice "$ACTION: skipped"
continue
fi
printf ' ++ ' >&2
log -i -t "$phase" info "$ACTION: starting"
RESULT="unknown"
LEVEL="err"
if type "init__$ACTION" | grep -q -w "function"; then
if "init__$ACTION" "$@"; then
RESULT="done"
LEVEL="info"
else
RESULT="failed"
fi
fi
printf ' ++ ' >&2
log -i -t "$phase" "$LEVEL" "$ACTION: $RESULT"
if skip_action "$ACTION"; then
printf ' -- ' >&2
log -i -t "$phase" notice "$ACTION: skipped"
continue
fi
printf ' ++ ' >&2
log -i -t "$phase" info "$ACTION: starting"
RESULT="unknown"
LEVEL="err"
if type "init__$ACTION" | grep -q -w "function"; then
if "init__$ACTION" "$@"; then
RESULT="done"
LEVEL="info"
else
RESULT="failed"
fi
fi
printf ' ++ ' >&2
log -i -t "$phase" "$LEVEL" "$ACTION: $RESULT"
done

View File

@ -1,4 +1,5 @@
#!/usr/bin/env atf-sh
# vim:set ft=sh
# shellcheck shell=sh
. $(atf_get_srcdir)/test_env.sh

View File

@ -2,27 +2,27 @@
prog=${0##*/}
usage() {
cat <<EOF
usage: wget [-cqS] [--spider] [-O FILE] [-o LOGFILE] [--header STR]
[--post-data STR | --post-file FILE] [-Y on/off]
[-P DIR] [-U AGENT] [-T SEC] URL...
cat <<-EOF
usage: wget [-cqS] [--spider] [-O FILE] [-o LOGFILE] [--header STR]
[--post-data STR | --post-file FILE] [-Y on/off]
[-P DIR] [-U AGENT] [-T SEC] URL...
Retrieve files via HTTP or FTP
Retrieve files via HTTP or FTP
--spider Only check URL existence: \$? is 0 if exists
--header STR Add STR (of form 'header: value') to headers
--post-data STR Send STR using POST method
--post-file FILE Send FILE using POST method
-c Continue retrieval of aborted transfer
-q Quiet
-P DIR Save to DIR (default .)
-S Show server response
-T SEC Network read timeout is SEC seconds
-O FILE Save to FILE ('-' for stdout)
-o LOGFILE Log messages to FILE
-U STR Use STR for User-Agent header
-Y on/off Use proxy
EOF
--spider Only check URL existence: \$? is 0 if exists
--header STR Add STR (of form 'header: value') to headers
--post-data STR Send STR using POST method
--post-file FILE Send FILE using POST method
-c Continue retrieval of aborted transfer
-q Quiet
-P DIR Save to DIR (default .)
-S Show server response
-T SEC Network read timeout is SEC seconds
-O FILE Save to FILE ('-' for stdout)
-o LOGFILE Log messages to FILE
-U STR Use STR for User-Agent header
-Y on/off Use proxy
EOF
exit $1
}

View File

@ -1,4 +1,5 @@
#!/usr/bin/env atf-sh
# vim:set ft=sh
# shellcheck shell=sh
. $(atf_get_srcdir)/test_env.sh

View File

@ -1,4 +1,5 @@
#!/usr/bin/env atf-sh
# vim:set ft=sh
# shellcheck shell=sh
. $(atf_get_srcdir)/test_env.sh

View File

@ -1,4 +1,5 @@
#!/usr/bin/env atf-sh
# vim:set ft=sh
# shellcheck shell=sh
. $(atf_get_srcdir)/test_env.sh

View File

@ -1,4 +1,5 @@
#!/usr/bin/env atf-sh
# vim:set ft=sh
# shellcheck shell=sh
. $(atf_get_srcdir)/test_env.sh

View File

@ -1,4 +1,5 @@
#!/usr/bin/env atf-sh
# vim:set ft=sh
# shellcheck shell=sh
. $(atf_get_srcdir)/test_env.sh

View File

@ -1,4 +1,5 @@
#!/usr/bin/env atf-sh
# vim:set ft=sh
# shellcheck shell=sh
. $(atf_get_srcdir)/test_env.sh

View File

@ -1,4 +1,5 @@
#!/usr/bin/env atf-sh
# vim:set ft=sh
# shellcheck shell=sh
. $(atf_get_srcdir)/test_env.sh

View File

@ -1,5 +1,5 @@
#!/bin/sh
# vim: set ts=8 noet:
# vim:set ft=sh:
# Tiny Cloud IMDS ifupdown-ng executor