#!/bin/sh # We built on top of tiny-cloud . /etc/conf.d/tiny-cloud # extract user-data args and cloud meta-data into /var/lib/cloud/meta-data get_meta_data() { if [ ! -f /var/lib/cloud/meta-data ]; then [ -f /var/lib/cloud/user-data ] && bash /var/lib/cloud/user-data get_meta_data || echo "Error trying to extract cloud meta-data" >&2 fi . /var/lib/cloud/meta-data } # archive orig /var, mount new var on top and restore orig var copy_and_mount() { local dev=$1 tar cf /tmp/var.tar /var 2>/dev/null mount -t xfs -o noatime "$dev" /var tar xf /tmp/var.tar -C / && rm -f /tmp/var.tar } setup_var() { for d in $(find /dev/sd?); do # resolve to a valid block device dev="$(realpath "$d")" [ -b "$dev" ] || continue # already mounted mount | grep -q "$dev" && continue case "$CLOUD" in aws) # on AWS look for sdx if [ "$d" = "/dev/sdx" ]; then # check volume for existing filesystem type=$(file -Lbs $d) if [[ "$type" =~ "XFS filesystem" ]]; then xfs_repair $d >/dev/null 2>&1 else mkfs.xfs -qf $d >/dev/null fi copy_and_mount "$dev" grep -q "$dev" /etc/fstab || echo "$dev /var xfs defaults,noatime,nofail 0 2" >> /etc/fstab fi ;; *) echo "Unsupported Cloud '$CLOUD'" >&2 exit 1 ;; esac done } attach_ebs() { local volId="$1" local device="$2" local tries=30 while true; do _json="$(aws ec2 describe-volumes --volume-ids $volId --region $REGION --output json)" rc=$?; [ $rc -ne 0 ] && return $rc vol_status=$(echo "$_json" | jq -r .Volumes[].State) attachId=$(echo "$_json" | jq -r .Volumes[].Attachments[].InstanceId) [ "$attachId" = "$INSTANCE_ID" ] && break if [ "$vol_status" = "available" ]; then aws ec2 attach-volume --volume-id "$volId" --instance-id "$INSTANCE_ID" --region "$REGION" --device "$device" > /dev/null rc=$?; [ $rc -ne 0 ] && return $rc break fi # if attached but not to us -> detach if [ "$vol_status" = "in-use" ]; then aws ec2 detach-volume --volume-id "$volId" --region "$REGION" --force rc=$?; [ $rc -ne 0 ] && return $rc fi ((tries=tries-1)) [ $tries -eq 0 ] && return 1 sleep 5 done } _parse_volume() { # Todo: proper checks once all is yaml # For now just replace ':' echo $1 | sed -e 's/:/ /g' } # mount optional remote volumes mount_volumes() { local volumes="$1" for vol in $volumes; do # Todo: check volume type and call matching func read volType volId volDevice volPath < <(_parse_volume $vol) [ "$volType" != "ebs" ] && { echo "Unknown volume type $volType"; break; } attach_ebs $volId $volDevice rc=$? [ $rc -ne 0 ] && { ewarn "error trying to attach $volId"; break; } # wait for the block device to become available while true; do mdev -s test -b $volDevice && break sleep 1 done # check volume for existing filesystem type=$(file -Lbs $volDevice) if [[ "$type" =~ "XFS filesystem" ]]; then xfs_repair $volDevice >/dev/null 2>&1 else mkfs.xfs -qf $volDevice >/dev/null fi # mount mkdir -p $volPath mount -t xfs -o noatime $volDevice $volPath done } unmount_volumes() { local volumes="$1" for vol in $volumes; do read volType volId volDevice volPath < <(_parse_volume $vol) umount $volPath && aws ec2 detach-volume --volume-id "$volId" --instance-id $INSTANCE_ID --region $REGION > /dev/null done }