mirror of
https://gitlab.alpinelinux.org/alpine/cloud/tiny-cloud.git
synced 2025-12-15 11:22:43 +03:00
* imds is now an executable script
* numerous imds script enhancements, including -h/--help * check imds for secondary ipv4 & ipvs via ifupdown-ng executor * simplify shell source to things /etc/conf.d/ and /lib/tiny-cloud/ * move log function to /lib/tiny-cloud/common
This commit is contained in:
parent
3eb1358940
commit
1d2618dfd0
3
Makefile
3
Makefile
@ -2,5 +2,4 @@ PREFIX?=/
|
||||
|
||||
.PHONY: install
|
||||
install:
|
||||
cp -r etc $(PREFIX)
|
||||
cp -r lib $(PREFIX)
|
||||
cp -r bin etc lib sbin usr $(PREFIX)
|
||||
|
||||
147
bin/imds
Executable file
147
bin/imds
Executable file
@ -0,0 +1,147 @@
|
||||
#!/bin/sh
|
||||
# vim:set ts=4 et ft=sh:
|
||||
|
||||
# Tiny Cloud - Instance MetaData Service client
|
||||
|
||||
### configuration
|
||||
|
||||
source /etc/conf.d/tiny-cloud
|
||||
|
||||
### cloud-specific variables/functions
|
||||
|
||||
unset \
|
||||
IMDS_HEADER \
|
||||
IMDS_URI \
|
||||
IMDS_QUERY \
|
||||
IMDS_HOSTNAME \
|
||||
IMDS_SSH_KEYS \
|
||||
IMDS_USERDATA \
|
||||
IMDS_NICS \
|
||||
IMDS_MAC \
|
||||
IMDS_IPV4 \
|
||||
IMDS_IPV6 \
|
||||
IMDS_IPV4_NET \
|
||||
IMDS_IPV6_NET \
|
||||
IMDS_IPV4_PREFIX \
|
||||
IMDS_IPV6_PREFIX
|
||||
unset -f \
|
||||
_imds_token \
|
||||
_imds_header \
|
||||
_imds_nic_index \
|
||||
2>/dev/null || true
|
||||
|
||||
### default variables/functions
|
||||
|
||||
CLOUD="${CLOUD:-unknown}"
|
||||
IMDS_ENDPOINT="169.254.169.254"
|
||||
|
||||
_imds_ssh_keys() { _imds "$IMDS_SSH_KEYS"; }
|
||||
_imds_userdata() { _imds "$IMDS_USERDATA"; }
|
||||
|
||||
### load cloud-specific variables and functions
|
||||
|
||||
if [ ! -d /lib/tiny-cloud/"$CLOUD" ]; then
|
||||
echo "ERROR: Unknown Cloud '$CLOUD'" >&2
|
||||
exit 1
|
||||
fi
|
||||
source /lib/tiny-cloud/"$CLOUD"/imds
|
||||
|
||||
### non-overrideable functions
|
||||
|
||||
_imds() {
|
||||
wget --quiet --timeout 1 --output-document - \
|
||||
--header "$(_imds_header)" \
|
||||
"http://$IMDS_ENDPOINT/$IMDS_URI/$1$IMDS_QUERY"
|
||||
}
|
||||
|
||||
imds() {
|
||||
local cmd args key rv err=1
|
||||
if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
|
||||
_imds_help
|
||||
return
|
||||
fi
|
||||
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) echo; continue ;; # insert newline
|
||||
+s) echo -n " "; continue ;; # insert space
|
||||
+t) echo -en "\t"; continue ;; # insert tab
|
||||
# key aliasing
|
||||
@hostname) args="$IMDS_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 2>/dev/null
|
||||
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
|
||||
}
|
||||
|
||||
_imds_help() {
|
||||
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
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
imds "$@"
|
||||
@ -13,9 +13,6 @@
|
||||
# IMDS token validity, in seconds (AWS only)
|
||||
#IMDS_TOKEN_TTL=5
|
||||
|
||||
# Location of libraries
|
||||
#TINY_CLOUD_LIBS=/lib/tiny-cloud
|
||||
|
||||
# Location of var directory
|
||||
#TINY_CLOUD_VAR=/var/lib/cloud
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#!/sbin/openrc-run
|
||||
# vim:set ft=sh noet ts=4:
|
||||
# vim:set ts=8 noet ft=sh:
|
||||
|
||||
description="Tiny Cloud Bootstrap - main phase"
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#!/sbin/openrc-run
|
||||
# vim:set ft=sh noet ts=4:
|
||||
# vim:set ts=8 noet ft=sh:
|
||||
|
||||
description="Tiny Cloud Bootstrap - early phase"
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#!/sbin/openrc-run
|
||||
# vim:set ft=sh noet ts=4:
|
||||
# vim:set ts=8 noet ft=sh:
|
||||
|
||||
description="Tiny Cloud Bootstrap - final phase"
|
||||
|
||||
|
||||
@ -1,2 +1,5 @@
|
||||
auto %%
|
||||
iface %% inet dhcp
|
||||
iface %%
|
||||
use dhcp
|
||||
use imds
|
||||
imds-resync 300
|
||||
|
||||
@ -1,2 +1,4 @@
|
||||
auto lo
|
||||
iface lo inet loopback
|
||||
iface lo
|
||||
use link
|
||||
use loopback
|
||||
@ -1,25 +1,21 @@
|
||||
#!/bin/sh
|
||||
# vim:set ts=2 et:
|
||||
|
||||
source /lib/tiny-cloud/common
|
||||
|
||||
# nvme tool not installed?
|
||||
[ -x /usr/sbin/nvme ] || exit
|
||||
|
||||
PROC="$(basename "$0")[$$]"
|
||||
|
||||
log() {
|
||||
FACILITY="kern.$1"
|
||||
shift
|
||||
logger -p "$FACILITY" -t "$PROC" "$@"
|
||||
}
|
||||
[ -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
|
||||
@ -42,7 +38,8 @@ case $ACTION in
|
||||
remove)
|
||||
for TARGET in sd* xvd*
|
||||
do
|
||||
[ "$(readlink "$TARGET" 2>/dev/null)" = "$MDEV" ] && rm -f "$TARGET" && log notice "Removed $TARGET symlink for $MDEV"
|
||||
[ $(readlink "$TARGET" 2>/dev/null) = "$MDEV" ] && rm -f "$TARGET" && \
|
||||
log notice "Removed $TARGET symlink for $MDEV"
|
||||
done
|
||||
;;
|
||||
esac
|
||||
|
||||
@ -1,29 +1,12 @@
|
||||
#!/bin/sh
|
||||
# vim: set ts=4 et:
|
||||
# vim:set ts=4 et:
|
||||
|
||||
set -e
|
||||
|
||||
PROC="$(basename "$0")[$$]"
|
||||
source /lib/tiny-cloud/common
|
||||
|
||||
DEBUG=
|
||||
|
||||
log() {
|
||||
[ -z "$DEBUG" ] && [ "$1" = "debug" ] && return
|
||||
local facility="kern.$1"
|
||||
shift
|
||||
logger -p "$facility" -t "$PROC" "$@"
|
||||
}
|
||||
|
||||
if [ -z "$MDEV" ]; then
|
||||
log err "MDEV env not defined"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# where's the tiny-cloud lib directory?
|
||||
if [ -z "$TINY_CLOUD_LIBS" ]; then
|
||||
TINY_CLOUD_CONF=${TINY_CLOUD_CONF:-/etc/conf.d/tiny-cloud}
|
||||
[ -f "$TINY_CLOUD_CONF" ] && source "$TINY_CLOUD_CONF"
|
||||
TINY_CLOUD_LIBS=${TINY_CLOUD_LIBS:-/lib/tiny-cloud}
|
||||
if [ -z "$MDEV" ] || [ -z "$ACTION" ]; then
|
||||
log crit "MDEV or ACTION undefined, aborting"
|
||||
fi
|
||||
|
||||
IFACE_CFG=/etc/network/interfaces
|
||||
@ -46,19 +29,18 @@ ip() {
|
||||
|
||||
assemble_interfaces() {
|
||||
log info "Rebuilding $IFACE_CFG"
|
||||
# TODO: might be elsewhere, source /etc/conf.d/tiny-cloud
|
||||
"$TINY_CLOUD_LIBS"/network-interfaces
|
||||
/lib/tiny-cloud/network-interfaces
|
||||
}
|
||||
|
||||
interface_up() {
|
||||
log info "Bringing up $MDEV"
|
||||
# so /run/udhcpcd.$MDEV.pid isn't non-owner writeable
|
||||
# umask so udhcpc PID file isn't non-owner writeable
|
||||
(umask 0022 && ifup "$MDEV")
|
||||
}
|
||||
|
||||
cleanup_interface() {
|
||||
local v p rtable="${MDEV#eth}"
|
||||
let rtable+=1000
|
||||
local v pref rtable="${MDEV#eth}"
|
||||
let rtable+=10000
|
||||
|
||||
log info "Cleaning up $MDEV"
|
||||
|
||||
@ -71,8 +53,8 @@ cleanup_interface() {
|
||||
|
||||
# remove related rules
|
||||
for v in 4 6; do
|
||||
for p in $(ip -"$v" rule show table "$rtable" | cut -d: -f1); do
|
||||
ip -"$v" rule del pref "$p"
|
||||
for pref in $(ip -"$v" rule show table "$rtable" | cut -d: -f1); do
|
||||
ip -"$v" rule del pref "$pref"
|
||||
done
|
||||
done
|
||||
}
|
||||
|
||||
@ -1,35 +1,40 @@
|
||||
# AWS Instance MetaData Service variables and functions
|
||||
# vim:set ft=sh noet ts=4:
|
||||
# vim:set ts=4 et ft=sh:
|
||||
|
||||
IMDS_HEADER="X-aws-ec2-metadata-token"
|
||||
IMDS_TOKEN_TTL_HEADER="X-aws-ec2-metadata-token-ttl-seconds"
|
||||
IMDS_TOKEN_TTL=${IMDS_TOKEN_TTL:-5}
|
||||
IMDS_URL="http://169.254.169.254/latest"
|
||||
IMDS_URI="latest"
|
||||
|
||||
IMDS_HOSTNAME="meta-data/hostname"
|
||||
IMDS_SSH_KEYS="meta-data/public-keys"
|
||||
IMDS_USERDATA="user-data"
|
||||
|
||||
IMDS_NICS="meta-data/network/interfaces/macs"
|
||||
IMDS_MAC="mac"
|
||||
IMDS_IPV4="local-ipv4s"
|
||||
IMDS_IPV6="ipv6s"
|
||||
IMDS_IPV4_NET="subnet-ipv4-cidr-block"
|
||||
IMDS_IPV6_NET="subnet-ipv6-cidr-blocks"
|
||||
IMDS_IPV4_PREFIX="ipv4-prefix"
|
||||
IMDS_IPV6_PREFIX="ipv6-prefix"
|
||||
|
||||
_imds_token() {
|
||||
echo -ne "PUT /latest/api/token" \
|
||||
"HTTP/1.0\r\n$IMDS_TOKEN_TTL_HEADER: $IMDS_TOKEN_TTL\r\n\r\n" |
|
||||
nc 169.254.169.254 80 | tail -n 1
|
||||
echo -ne "PUT /latest/api/token" \
|
||||
"HTTP/1.0\r\n$IMDS_TOKEN_TTL_HEADER: $IMDS_TOKEN_TTL\r\n\r\n" |
|
||||
nc -w 1 "$IMDS_ENDPOINT" 80 | tail -n 1
|
||||
}
|
||||
|
||||
_imds_header() {
|
||||
echo "$IMDS_HEADER: $(_imds_token)"
|
||||
echo "$IMDS_HEADER: $(_imds_token)"
|
||||
}
|
||||
|
||||
# digs deeper than the default
|
||||
imds_ssh_keys() {
|
||||
local key
|
||||
|
||||
for key in $(imds "$IMDS_SSH_KEYS"); do
|
||||
imds "$IMDS_SSH_KEYS/${key%=*}/openssh-key"
|
||||
done | sort -u
|
||||
_imds_ssh_keys() {
|
||||
local key
|
||||
for key in $(imds "$IMDS_SSH_KEYS"); do
|
||||
imds "$IMDS_SSH_KEYS/${key%=*}/openssh-key"
|
||||
done | sort -u
|
||||
}
|
||||
|
||||
# ignore 404s from IMDS, if no user-data is set
|
||||
imds_userdata() {
|
||||
_imds "$IMDS_USERDATA" || true
|
||||
}
|
||||
_imds_nic_index() { cat "/sys/class/net/$1/address"; }
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
# AWS mdev Hotplug Modules
|
||||
# vim:set ft=sh ts=4 noet:
|
||||
# vim:set ts=4 et ft=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'
|
||||
}
|
||||
@ -1,28 +1,30 @@
|
||||
# Azure Instance MetaData Service variables and functions
|
||||
# vim:set ft=sh noet ts=4:
|
||||
# vim:set ts=4 et ft=sh:
|
||||
|
||||
IMDS_HEADER="Metadata"
|
||||
IMDS_QUERY="?format=text&api-version=2021-05-01"
|
||||
IMDS_URL="http://169.254.169.254/metadata/instance"
|
||||
IMDS_URI="metadata/instance"
|
||||
|
||||
IMDS_HOSTNAME="compute/name"
|
||||
IMDS_SSH_KEYS="compute/publicKeys"
|
||||
IMDS_USERDATA="compute/userData"
|
||||
|
||||
IMDS_NICS=""
|
||||
|
||||
_imds_header() {
|
||||
echo "$IMDS_HEADER: true"
|
||||
echo "$IMDS_HEADER: true"
|
||||
}
|
||||
|
||||
# dig deeper than default
|
||||
imds_ssh_keys() {
|
||||
local key
|
||||
_imds_ssh_keys() {
|
||||
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_userdata() {
|
||||
imds "$IMDS_USERDATA" | base64 -d
|
||||
}
|
||||
24
lib/tiny-cloud/common
Normal file
24
lib/tiny-cloud/common
Normal file
@ -0,0 +1,24 @@
|
||||
# Tiny Cloud - common script functions
|
||||
# vim: ts=4 et ft=sh:
|
||||
|
||||
log() {
|
||||
local facility=kern
|
||||
local stderr
|
||||
local tag=$(basename "$0")
|
||||
while [ "${1:0:1}" = '-' ]; do
|
||||
case "$1" in
|
||||
-f) facility="$2"; shift ;;
|
||||
-s) stderr=-s ;;
|
||||
-t) tag="$tag/$2"; shift ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
local level="$1"
|
||||
[ -z "$DEBUG" ] && [ "$level" = debug ] && return
|
||||
shift
|
||||
|
||||
logger $stderr -p "$facility.$level" -t "$tag" "$@"
|
||||
case "$level" in
|
||||
crit|alert|emerg) exit 1 ;;
|
||||
esac
|
||||
}
|
||||
@ -1,26 +1,26 @@
|
||||
# Google Cloud Instance MetaData Service variables and functions
|
||||
# vim:set ft=sh noet ts=4:
|
||||
# vim:set ts=4 et ft=sh:
|
||||
|
||||
IMDS_HEADER="Metadata-Flavor"
|
||||
IMDS_URL="http://169.254.169.254/computeMetadata/v1"
|
||||
IMDS_URI="computeMetadata/v1"
|
||||
|
||||
IMDS_HOSTNAME="instance/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
|
||||
_imds_ssh_keys() {
|
||||
local ssh_keys
|
||||
|
||||
for ssh_keys in $IMDS_SSH_KEYS; do
|
||||
# ignore errors and strip leading '<login>:'
|
||||
_imds "$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
|
||||
}
|
||||
@ -1,62 +0,0 @@
|
||||
# Tiny Cloud - Instance MetaData Service functions and variables
|
||||
# vim:set ft=sh ts=4 noet:
|
||||
|
||||
### configuration
|
||||
|
||||
if [ -z "$TINY_CLOUD_LIBS" ]; then
|
||||
TINY_CLOUD_CONF=${TINY_CLOUD_CONF:-/etc/conf.d/tiny-cloud}
|
||||
[ -f "$TINY_CLOUD_CONF" ] && source "$TINY_CLOUD_CONF"
|
||||
TINY_CLOUD_LIBS=${TINY_CLOUD_LIBS:-/lib/tiny-cloud}
|
||||
fi
|
||||
|
||||
# defaults
|
||||
CLOUD="${CLOUD:-unknown}"
|
||||
|
||||
# these are always cloud-specific
|
||||
|
||||
unset \
|
||||
IMDS_HEADER \
|
||||
IMDS_QUERY \
|
||||
IMDS_URL \
|
||||
IMDS_HOSTNAME \
|
||||
IMDS_SSH_KEYS \
|
||||
IMDS_USERDATA
|
||||
|
||||
unset -f \
|
||||
_imds_token \
|
||||
_imds_header \
|
||||
2>/dev/null || true
|
||||
|
||||
# without error reporting
|
||||
_imds() {
|
||||
wget --quiet --header "$(_imds_header)" --output-document - \
|
||||
"$IMDS_URL/$1$IMDS_QUERY"
|
||||
}
|
||||
|
||||
imds() {
|
||||
_imds "$1"
|
||||
RV=$?
|
||||
[ $RV != 0 ] && echo "ERROR: $RV" >&2
|
||||
return $RV
|
||||
}
|
||||
|
||||
imds_hostname() {
|
||||
imds "$IMDS_HOSTNAME"
|
||||
}
|
||||
|
||||
imds_ssh_keys() {
|
||||
imds "$IMDS_SSH_KEYS"
|
||||
}
|
||||
|
||||
imds_userdata() {
|
||||
imds "$IMDS_USERDATA"
|
||||
}
|
||||
|
||||
### load cloud-specific things
|
||||
|
||||
if [ ! -d "$TINY_CLOUD_LIBS/$CLOUD" ]; then
|
||||
echo "ERROR: Unknown Cloud '$CLOUD'" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
source "$TINY_CLOUD_LIBS/$CLOUD/imds"
|
||||
@ -1,5 +1,5 @@
|
||||
# Tiny Cloud - Common Initialization
|
||||
# vim:set ft=sh ts=4 noet:
|
||||
# vim:set ts=4 et ft=sh:
|
||||
|
||||
# set defaults
|
||||
CLOUD_USER=${CLOUD_USER:-alpine}
|
||||
|
||||
@ -1,49 +1,44 @@
|
||||
# Tiny Cloud - Early Phase Functions
|
||||
# vim:set ft=sh ts=4 noet:
|
||||
# vim:set ts=4 et ft=sh:
|
||||
|
||||
if [ -z "$TINY_CLOUD_LIBS" ]; then
|
||||
TINY_CLOUD_CONF=${TINY_CLOUD_CONF:-/etc/conf.d/tiny-cloud}
|
||||
[ -f "$TINY_CLOUD_CONF" ] && source "$TINY_CLOUD_CONF"
|
||||
TINY_CLOUD_LIBS=${TINY_CLOUD_LIBS:-/lib/tiny-cloud}
|
||||
fi
|
||||
|
||||
source "$TINY_CLOUD_LIBS"/init-common
|
||||
source /etc/conf.d/tiny-cloud
|
||||
source /lib/tiny-cloud/init-common
|
||||
|
||||
expand_root() {
|
||||
# explicitly use busybox, in case util-linux is also installed
|
||||
local mountpoint=$(busybox mountpoint -n / | cut -d' ' -f1)
|
||||
local volume=$(echo "$mountpoint" |
|
||||
sed -Ee "s/(nvme\d+n\d|(xv|s)d[a-z])p?\d?$/\1/"
|
||||
)
|
||||
local partition
|
||||
# explicitly use busybox, in case util-linux is also installed
|
||||
local mountpoint=$(busybox mountpoint -n / | cut -d' ' -f1)
|
||||
local volume=$(echo "$mountpoint" |
|
||||
sed -Ee "s/(nvme\d+n\d|(xv|s)d[a-z])p?\d?$/\1/"
|
||||
)
|
||||
local partition
|
||||
|
||||
if [ "$mountpoint" != "$volume" ]; then
|
||||
# it's a partition, resize it
|
||||
partition=$(echo "$mountpoint" | sed -Ee "s/.*(\d+)$/\1/")
|
||||
echo ", +" | sfdisk -q --no-reread -N "$partition" "$volume"
|
||||
partx -u "$volume"
|
||||
fi
|
||||
# resize filesystem
|
||||
mount -orw,remount /
|
||||
resize2fs "$mountpoint"
|
||||
if [ "$mountpoint" != "$volume" ]; then
|
||||
# it's a partition, resize it
|
||||
partition=$(echo "$mountpoint" | sed -Ee "s/.*(\d+)$/\1/")
|
||||
echo ", +" | sfdisk -q --no-reread -N "$partition" "$volume"
|
||||
partx -u "$volume"
|
||||
fi
|
||||
# resize filesystem
|
||||
mount -orw,remount /
|
||||
resize2fs "$mountpoint"
|
||||
}
|
||||
|
||||
assemble_interfaces() { "$TINY_CLOUD_LIBS"/network-interfaces; }
|
||||
assemble_interfaces() { /lib/tiny-cloud/network-interfaces; }
|
||||
|
||||
has_cloud_hotplugs() { [ -n "$HOTPLUG_MODULES" ]; }
|
||||
|
||||
install_hotplugs() {
|
||||
local result
|
||||
local result
|
||||
|
||||
for module in $HOTPLUG_MODULES; do
|
||||
result='-'
|
||||
echo -n " $module"
|
||||
if type "mod__$module" | grep -q "is a function"; then
|
||||
"mod__$module" && result='+' || result='!'
|
||||
fi
|
||||
echo -n "($result)"
|
||||
done
|
||||
for module in $HOTPLUG_MODULES; do
|
||||
result='-'
|
||||
echo -n " $module"
|
||||
if type "mod__$module" | grep -q "is a function"; then
|
||||
"mod__$module" && result='+' || result='!'
|
||||
fi
|
||||
echo -n "($result)"
|
||||
done
|
||||
}
|
||||
|
||||
HOTPLUG_TYPE=${HOTPLUG_TYPE:-mdev}
|
||||
source "$TINY_CLOUD_LIBS/$HOTPLUG_TYPE"
|
||||
source /lib/tiny-cloud/"$HOTPLUG_TYPE"
|
||||
@ -1,30 +1,24 @@
|
||||
# Tiny Cloud - Final Phase Functions
|
||||
# vim:set ft=sh ts=4 noet:
|
||||
# vim:set ts=4 et ft=sh:
|
||||
|
||||
if [ -z "$TINY_CLOUD_LIBS" ]; then
|
||||
TINY_CLOUD_CONF=${TINY_CLOUD_CONF:-/etc/conf.d/tiny-cloud}
|
||||
[ -f "$TINY_CLOUD_CONF" ] && source "$TINY_CLOUD_CONF"
|
||||
TINY_CLOUD_LIBS=${TINY_CLOUD_LIBS:-/lib/tiny-cloud}
|
||||
fi
|
||||
|
||||
source "$TINY_CLOUD_LIBS"/init-common
|
||||
source "$TINY_CLOUD_LIBS"/imds
|
||||
source /etc/conf.d/tiny-cloud
|
||||
source /lib/tiny-cloud/init-common
|
||||
|
||||
save_userdata() {
|
||||
imds_userdata > "$TINY_CLOUD_VAR/$CLOUD_USERDATA"
|
||||
imds -e @userdata > "$TINY_CLOUD_VAR/$CLOUD_USERDATA"
|
||||
}
|
||||
|
||||
is_userdata_script() {
|
||||
head -n1 "$TINY_CLOUD_VAR/$CLOUD_USERDATA" | grep -q '#!/'
|
||||
head -n1 "$TINY_CLOUD_VAR/$CLOUD_USERDATA" | grep -q '#!/'
|
||||
}
|
||||
|
||||
run_userdata() {
|
||||
local log="$TINY_CLOUD_LOGS/$CLOUD_USERDATA.log"
|
||||
local exit="$TINY_CLOUD_LOGS/$CLOUD_USERDATA.exit"
|
||||
local userdata="$TINY_CLOUD_VAR/$CLOUD_USERDATA"
|
||||
local log="$TINY_CLOUD_LOGS/$CLOUD_USERDATA.log"
|
||||
local exit="$TINY_CLOUD_LOGS/$CLOUD_USERDATA.exit"
|
||||
local userdata="$TINY_CLOUD_VAR/$CLOUD_USERDATA"
|
||||
|
||||
chmod +x "$userdata"
|
||||
{ "$userdata" 2>& 1; echo $? > "$exit"; } | tee "$log"
|
||||
chmod +x "$userdata"
|
||||
{ "$userdata" 2>& 1; echo $? > "$exit"; } | tee "$log"
|
||||
|
||||
return $(cat "$exit")
|
||||
return $(cat "$exit")
|
||||
}
|
||||
@ -1,41 +1,35 @@
|
||||
# Tiny Cloud - Main Phase Functions
|
||||
# vim:set ft=sh ts=4 noet:
|
||||
# vim:set ts=4 et ft=sh:
|
||||
|
||||
if [ -z "$TINY_CLOUD_LIBS" ]; then
|
||||
TINY_CLOUD_CONF=${TINY_CLOUD_CONF:-/etc/conf.d/tiny-cloud}
|
||||
[ -f "$TINY_CLOUD_CONF" ] && source "$TINY_CLOUD_CONF"
|
||||
TINY_CLOUD_LIBS=${TINY_CLOUD_LIBS:-/lib/tiny-cloud}
|
||||
fi
|
||||
|
||||
source "$TINY_CLOUD_LIBS"/init-common
|
||||
source "$TINY_CLOUD_LIBS"/imds
|
||||
source /etc/conf.d/tiny-cloud
|
||||
source /lib/tiny-cloud/init-common
|
||||
|
||||
# ensure existence of output directories
|
||||
[ ! -d "$TINY_CLOUD_LOGS" ] && mkdir -p "$TINY_CLOUD_LOGS"
|
||||
[ ! -d "$TINY_CLOUD_VAR" ] && mkdir -p "$TINY_CLOUD_VAR"
|
||||
|
||||
set_hostname() {
|
||||
local fqdn=$(imds_hostname)
|
||||
local host="${fqdn%%\.*}"
|
||||
echo "$host" > /etc/hostname
|
||||
hostname -F /etc/hostname
|
||||
echo -e "127.0.1.1\t$fqdn $host" >> /etc/hosts
|
||||
local fqdn=$(imds @hostname)
|
||||
local host="${fqdn%%\.*}"
|
||||
echo "$host" > /etc/hostname
|
||||
hostname -F /etc/hostname
|
||||
echo -e "127.0.1.1\t$fqdn $host" >> /etc/hosts
|
||||
}
|
||||
|
||||
set_ssh_keys() {
|
||||
local user="$CLOUD_USER"
|
||||
local pwent=$(getent passwd "$user")
|
||||
local group=$(echo "$pwent" | cut -d: -f4)
|
||||
local ssh_dir="$(echo "$pwent" | cut -d: -f6)/.ssh"
|
||||
local keys_file="$ssh_dir/authorized_keys"
|
||||
local user="$CLOUD_USER"
|
||||
local pwent=$(getent passwd "$user")
|
||||
local group=$(echo "$pwent" | cut -d: -f4)
|
||||
local ssh_dir="$(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"
|
||||
chown -R "$user:$group" "$ssh_dir"
|
||||
imds_ssh_keys > "$keys_file"
|
||||
touch "$keys_file"
|
||||
chmod 600 "$keys_file"
|
||||
chown -R "$user:$group" "$ssh_dir"
|
||||
imds @ssh-keys > "$keys_file"
|
||||
}
|
||||
@ -1,35 +1,35 @@
|
||||
# Tiny Cloud - mdev hotplug functions
|
||||
# vim:set ft=sh ts=4 noet:
|
||||
# vim:set ts=4 et ft=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() {
|
||||
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
|
||||
|
||||
[ -f "$TINY_CLOUD_LIBS/$CLOUD/mdev" ] && source "$TINY_CLOUD_LIBS/$CLOUD/mdev"
|
||||
[ -f /lib/tiny-cloud/"$CLOUD"/mdev ] && source /lib/tiny-cloud/"$CLOUD"/mdev
|
||||
@ -1,5 +1,5 @@
|
||||
#!/bin/sh
|
||||
# vim: set ts=4 et:
|
||||
# vim:set ts=4 et:
|
||||
|
||||
set -e
|
||||
|
||||
@ -15,10 +15,15 @@ cat > "$IFACE_CFG.new" <<EOT
|
||||
EOT
|
||||
|
||||
# existing loopback and eths
|
||||
for i in /sys/class/net/{lo,eth*}; do
|
||||
for i in /sys/class/net/*; do
|
||||
IFACE="$(basename "$i")"
|
||||
[ ! -f "$IFACE" ] && sed -e "s/%%/$IFACE/g" DEFAULT > "$IFACE"
|
||||
printf "%s\n\n" "$(cat "$IFACE")" >> "$IFACE_CFG.new"
|
||||
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
|
||||
|
||||
@ -1,13 +1,22 @@
|
||||
# OCI Instance MetaData Service variables and functions
|
||||
# vim:set ft=sh noet ts=4:
|
||||
# vim:set ts=4 et ft=sh:
|
||||
|
||||
IMDS_HEADER="Authorization"
|
||||
IMDS_URL="http://169.254.169.254/opc/v2"
|
||||
IMDS_URI="opc/v2"
|
||||
|
||||
IMDS_HOSTNAME="instance/hostname"
|
||||
IMDS_SSH_KEYS="instance/metadata/ssh_authorized_keys"
|
||||
IMDS_USERDATA="instance/metadata/userdata"
|
||||
|
||||
_imds_header() {
|
||||
echo "$IMDS_HEADER: Bearer Oracle"
|
||||
echo "$IMDS_HEADER: Bearer Oracle"
|
||||
}
|
||||
|
||||
_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
|
||||
}
|
||||
|
||||
144
sbin/imds-net-sync
Executable file
144
sbin/imds-net-sync
Executable file
@ -0,0 +1,144 @@
|
||||
#!/bin/sh
|
||||
# vim: ts=4 et ft=sh:
|
||||
|
||||
# Sync interface's network configuration with IMDS
|
||||
|
||||
[ -z "$VERBOSE" ] || set -x
|
||||
|
||||
source /lib/tiny-cloud/common
|
||||
|
||||
IFACE=${IFACE:-unknown}
|
||||
[ "$IFACE" = unknown ] && log -s crit "IFACE not set, aborting"
|
||||
|
||||
# kill interface's imds-net-sync daemon
|
||||
[ "$1" = '-k' ] && PHASE=pre=down && shift
|
||||
|
||||
PHASE=${PHASE:-post-up}
|
||||
|
||||
# route table number
|
||||
RTABLE=${IFACE#eth}
|
||||
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
|
||||
}
|
||||
|
||||
# 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/'
|
||||
}
|
||||
|
||||
# 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/'
|
||||
}
|
||||
|
||||
imds_ip4s() {
|
||||
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"
|
||||
}
|
||||
|
||||
imds_ip6s() {
|
||||
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"
|
||||
fi
|
||||
echo "$ip6s"
|
||||
}
|
||||
|
||||
in_list() {
|
||||
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"
|
||||
|
||||
# TODO: only non eth0? delegated ipv[46] prefixes?
|
||||
[ "$IFACE" = eth0 ] && return
|
||||
|
||||
# non-eth0 interfaces get rules associating IPs with route tables
|
||||
ip -"$1" rule "$2" from "$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
|
||||
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"
|
||||
}
|
||||
|
||||
case "$PHASE" in
|
||||
post-up)
|
||||
# TODO: daemonize this
|
||||
imds_iface_sync
|
||||
;;
|
||||
pre-down)
|
||||
# TODO: kill daemon, maybe some cleanup
|
||||
;;
|
||||
*)
|
||||
esac
|
||||
14
usr/libexec/ifupdown-ng/imds
Executable file
14
usr/libexec/ifupdown-ng/imds
Executable file
@ -0,0 +1,14 @@
|
||||
#!/bin/sh
|
||||
# vim: set ts=8 noet:
|
||||
|
||||
# Tiny Cloud IMDS ifupdown-ng executor
|
||||
|
||||
case "$PHASE" in
|
||||
post-up)
|
||||
/sbin/imds-net-sync
|
||||
;;
|
||||
pre-down)
|
||||
/sbin/imds-net-sync -k
|
||||
;;
|
||||
*) ;;
|
||||
esac
|
||||
Loading…
x
Reference in New Issue
Block a user