2022-11-22 05:59:53 +00:00
|
|
|
#!/usr/bin/env bash
|
|
|
|
|
|
|
|
VERSION="$1"
|
2022-11-22 13:58:01 +00:00
|
|
|
EPOCH=${EPOCH:-0}
|
2022-11-22 05:59:53 +00:00
|
|
|
|
|
|
|
RLVER=$VERSION
|
|
|
|
|
|
|
|
# Source common variables
|
|
|
|
# shellcheck disable=SC2046,1091,1090
|
|
|
|
source "$(dirname "${BASH_SOURCE[0]}")/common"
|
|
|
|
|
|
|
|
usage() {
|
2023-05-12 18:00:52 +00:00
|
|
|
echo "usage: $0 VERSION ($0 8.7)"
|
2022-11-22 05:59:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
aws() {
|
2023-05-12 18:00:52 +00:00
|
|
|
command aws --region us-east-1 --profile resf-ami --output text $@
|
2022-11-22 05:59:53 +00:00
|
|
|
}
|
|
|
|
|
2023-05-12 18:00:52 +00:00
|
|
|
DATE=${DATE:-$(date +%Y%m%d)}
|
2022-11-22 05:59:53 +00:00
|
|
|
|
|
|
|
if [[ -z $VERSION ]]; then
|
2023-05-12 18:00:52 +00:00
|
|
|
usage
|
|
|
|
exit 1
|
2022-11-22 05:59:53 +00:00
|
|
|
fi
|
|
|
|
|
|
|
|
download() {
|
2023-05-12 18:00:52 +00:00
|
|
|
curl -o "$qcow" "https://dl.rockylinux.org/stg/rocky/$VERSION/images/$arch/$qcow"
|
|
|
|
return $?
|
2022-11-22 05:59:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
exists() {
|
2023-05-12 18:00:52 +00:00
|
|
|
aws s3 ls $2/$1 &>/dev/null
|
|
|
|
return $?
|
2022-11-22 05:59:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
upload() {
|
2023-05-12 18:00:52 +00:00
|
|
|
if exists $raw $BUCKET/$DATE; then
|
|
|
|
echo "Found existing upload in $BUCKET"
|
|
|
|
return 0
|
|
|
|
fi
|
|
|
|
aws s3 cp $raw $BUCKET/$DATE/
|
2022-11-22 05:59:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
convert() {
|
2023-05-12 18:00:52 +00:00
|
|
|
qemu-img convert -f qcow2 -O raw "$qcow" $raw
|
|
|
|
return $?
|
2022-11-22 05:59:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
BUCKET="s3://resf-prod-import-use1"
|
|
|
|
|
|
|
|
write-container-file() {
|
2023-05-12 18:00:52 +00:00
|
|
|
printf '{"Description": "%s", "Format": "raw", "Url": "%s/%s"}\n' $name "$BUCKET/$DATE" $raw >$json
|
2022-11-22 05:59:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
download-convert-upload() {
|
2023-05-12 18:00:52 +00:00
|
|
|
if ! [[ -f $qcow ]]; then
|
|
|
|
echo "Downloading $qcow from cdn"
|
|
|
|
download || exit
|
|
|
|
fi
|
|
|
|
|
|
|
|
if ! [[ -f ${raw} ]]; then
|
|
|
|
echo "Converting qcow2 $qcow to RAW $raw"
|
|
|
|
convert || exit
|
|
|
|
fi
|
|
|
|
|
|
|
|
echo "Uploading raw image back to s3"
|
|
|
|
if ! upload; then
|
|
|
|
echo "Failed to upload"
|
|
|
|
exit
|
|
|
|
fi
|
2022-11-22 05:59:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
begin-job() {
|
2023-05-12 18:00:52 +00:00
|
|
|
import_task_id="$(aws ec2 import-snapshot --disk-container "file://$PWD/$json" --query 'ImportTaskId')"
|
|
|
|
if [[ -z $import_task_id ]]; then
|
|
|
|
echo "Failed to import $json"
|
|
|
|
return 1
|
|
|
|
fi
|
|
|
|
echo $import_task_id
|
|
|
|
return 0
|
2022-11-22 05:59:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
is-snapshot-imported() {
|
2023-05-12 18:00:52 +00:00
|
|
|
snapshot_id=$(aws ec2 describe-import-snapshot-tasks --query 'ImportSnapshotTasks[].SnapshotTaskDetail.SnapshotId[]' --import-task-ids $1)
|
|
|
|
if [[ -z "$snapshot_id" ]]; then
|
|
|
|
return 1
|
|
|
|
fi
|
|
|
|
return 0
|
2022-11-22 05:59:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
register-image() {
|
2023-05-12 18:00:52 +00:00
|
|
|
# Given a snapshot id, register the image
|
|
|
|
name=$1
|
|
|
|
snapshot_id=$2
|
|
|
|
|
|
|
|
case $(awk -F'.' '{print $NF}' <<<"$name") in
|
|
|
|
x86_64)
|
|
|
|
arch=x86_64
|
|
|
|
;;
|
|
|
|
aarch64)
|
|
|
|
arch=arm64
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
|
|
|
|
ami_id=$(aws --query "ImageId" ec2 register-image --name "$name" --description "$name" --block-device-mappings DeviceName="/dev/sda1",Ebs={SnapshotId="$snapshot_id"} --root-device-name "/dev/sda1" --virtualization-type hvm --architecture $arch --ena-support)
|
|
|
|
|
|
|
|
if [[ -z "$ami_id" ]]; then
|
|
|
|
return 1
|
|
|
|
fi
|
|
|
|
return 0
|
2022-11-22 05:59:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
tag-resources() {
|
2023-05-12 18:00:52 +00:00
|
|
|
local resources="$1"
|
|
|
|
local tags="$2"
|
|
|
|
if [[ -z $resources || -z $tags ]]; then
|
|
|
|
echo "Need to provide tags and resources to tag"
|
|
|
|
return 1
|
|
|
|
fi
|
|
|
|
aws ec2 create-tags --resources $resources --tags $tags
|
2022-11-22 05:59:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
image-exists() {
|
2023-05-12 18:00:52 +00:00
|
|
|
local RESF_AMI_ACCOUNT_ID=792107900819
|
|
|
|
local query="$(printf 'Images[?Name==`%s`].[ImageId,Name][]' "${1}")"
|
|
|
|
mapfile -t res < <(aws ec2 describe-images --owners $RESF_AMI_ACCOUNT_ID --query "${query}" 2>/dev/null)
|
|
|
|
res=($res)
|
|
|
|
if [[ ${#res[@]} -eq 0 ]]; then
|
|
|
|
# Skip empty results
|
|
|
|
return 1 #not found
|
|
|
|
fi
|
|
|
|
id=${res[0]//\"/}
|
|
|
|
name=${res[@]/$id/}
|
|
|
|
found_image_id=$id
|
|
|
|
return 0 # found
|
2022-11-22 05:59:53 +00:00
|
|
|
}
|
|
|
|
snapshot-exists() {
|
2023-05-12 18:00:52 +00:00
|
|
|
local RESF_AMI_ACCOUNT_ID=792107900819
|
|
|
|
local filter="$(printf 'Name=tag:Name,Values=%s' "${1}")"
|
|
|
|
local query='Snapshots[].[SnapshotId][]'
|
|
|
|
mapfile -t res < <(aws ec2 describe-snapshots --owner-ids $RESF_AMI_ACCOUNT_ID --filter "${filter}" --query "${query}" 2>/dev/null)
|
|
|
|
res=($res)
|
|
|
|
if [[ ${#res[@]} -eq 0 ]]; then
|
|
|
|
# Skip empty results
|
|
|
|
return 1 #not found
|
|
|
|
fi
|
|
|
|
id=${res[0]//\"/}
|
|
|
|
found_snapshot_id=$id
|
|
|
|
return 0 # found
|
2022-11-22 05:59:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
declare -A import_jobs
|
|
|
|
declare -A snapshot_ids
|
|
|
|
declare -A ami_ids
|
|
|
|
|
2022-11-22 13:58:01 +00:00
|
|
|
TARGET_ARCHES=(x86_64 aarch64)
|
|
|
|
TARGET_VARIANTS=(Base LVM)
|
2022-11-22 05:59:53 +00:00
|
|
|
|
2022-11-22 13:58:01 +00:00
|
|
|
for variant in "${TARGET_VARIANTS[@]}"; do
|
2023-05-12 18:00:52 +00:00
|
|
|
for arch in "${TARGET_ARCHES[@]}"; do
|
|
|
|
latest=$(printf "Rocky-%s-EC2-%s.latest.%s" "$VERSION" $variant $arch)
|
|
|
|
name=$(printf "Rocky-%s-EC2-%s-%s-%s.%s.%s" "$VERSION" $variant $REVISION $DATE $EPOCH $arch)
|
|
|
|
qcow=${name}.qcow2
|
|
|
|
raw=${name}.raw
|
|
|
|
json=${name}.json
|
|
|
|
|
|
|
|
if image-exists $name; then
|
|
|
|
echo "Found existing AMI in us-east-1. Skipping. ($found_image_id,$name)"
|
|
|
|
continue
|
|
|
|
fi
|
|
|
|
|
|
|
|
if snapshot-exists $name; then
|
|
|
|
# If the snapshot exists, we can skip the import task and just do the image registration
|
|
|
|
echo "Found existing snapshot: ($found_snapshot_id,$name)"
|
|
|
|
snapshot_ids[$name]="${found_snapshot_id}"
|
|
|
|
continue
|
|
|
|
fi
|
|
|
|
|
|
|
|
# Download latest artifacts from CDN, convert from qcow2 to raw, and upload to the proper bucket
|
|
|
|
echo "Downloading/converting artifacts for $name"
|
|
|
|
download-convert-upload
|
|
|
|
|
|
|
|
echo "Writing disk container json file"
|
|
|
|
write-container-file
|
|
|
|
|
|
|
|
jobid=$(begin-job)
|
|
|
|
echo "Beginning snapshot import task with id $jobid"
|
|
|
|
import_jobs[$name]=$jobid
|
|
|
|
done
|
2022-11-22 05:59:53 +00:00
|
|
|
done
|
|
|
|
|
|
|
|
# wait for all import jobs to complete, then tag the resultant images
|
|
|
|
finished=false
|
|
|
|
while ! $finished; do
|
2023-05-12 18:00:52 +00:00
|
|
|
for name in "${!import_jobs[@]}"; do
|
|
|
|
import_task_id="${import_jobs[${name}]}"
|
|
|
|
if ! is-snapshot-imported $import_task_id; then
|
|
|
|
echo "Snapshot for $import_task_id ($name) is not yet finished"
|
|
|
|
continue
|
|
|
|
fi
|
|
|
|
|
|
|
|
# await finalization
|
|
|
|
sleep 2
|
|
|
|
|
|
|
|
if [[ -z $snapshot_id ]]; then
|
|
|
|
echo "Snapshot ID is null.. exiting"
|
|
|
|
exit 2
|
|
|
|
fi
|
|
|
|
|
|
|
|
echo "Tagging snapshot with name"
|
|
|
|
tag-resources $snapshot_id "Key=Name,Value=$name"
|
|
|
|
|
|
|
|
unset import_jobs[${name}]
|
|
|
|
snapshot_ids[${name}]=$snapshot_id
|
|
|
|
done
|
|
|
|
# Check if we're done, if so, great!
|
|
|
|
if [[ ${#import_jobs[@]} -gt 0 ]]; then
|
|
|
|
echo "Sleeping for 1m"
|
|
|
|
sleep 1m
|
|
|
|
continue
|
|
|
|
else
|
|
|
|
finished=true
|
|
|
|
break
|
|
|
|
fi
|
2022-11-22 05:59:53 +00:00
|
|
|
done
|
|
|
|
|
|
|
|
finished=false
|
|
|
|
while ! $finished; do
|
2023-05-12 18:00:52 +00:00
|
|
|
for name in "${!snapshot_ids[@]}"; do
|
|
|
|
# If the snapshot is imported, turn it into an AMI
|
|
|
|
snapshot_id="${snapshot_ids[${name}]}"
|
|
|
|
|
|
|
|
echo "Creating AMI from snapshot $snapshot_id ($name)"
|
|
|
|
if ! register-image $name $snapshot_id; then
|
|
|
|
echo "ERROR: Failed to create image for $name with snapshot id $snapshot_id"
|
|
|
|
continue
|
|
|
|
fi
|
|
|
|
|
|
|
|
echo "Tagging AMI - Name=$name"
|
|
|
|
tag-resources $ami_id "Key=Name,Value=$name"
|
|
|
|
|
|
|
|
if [[ -z $ami_id ]]; then
|
|
|
|
echo "AMI ID is null. continuing..."
|
|
|
|
continue
|
|
|
|
fi
|
|
|
|
|
|
|
|
unset snapshot_ids[${name}]
|
|
|
|
ami_ids[$name]=$ami_id
|
|
|
|
done
|
|
|
|
if [[ ${#snapshot_ids[@]} -gt 0 ]]; then
|
|
|
|
sleep 1m
|
|
|
|
continue
|
|
|
|
else
|
|
|
|
finished=true
|
|
|
|
break
|
|
|
|
fi
|
2022-11-22 05:59:53 +00:00
|
|
|
done
|
|
|
|
|
|
|
|
res=""
|
|
|
|
for name in "${!ami_ids[@]}"; do
|
2023-05-12 18:00:52 +00:00
|
|
|
ami_id="${ami_ids[${name}]}"
|
|
|
|
res="${res}\n$(printf '%s\t%s\n' $name $ami_id)"
|
2022-11-22 05:59:53 +00:00
|
|
|
done
|
|
|
|
|
|
|
|
printf "$res\n"
|