# # EC2 specific functions # ################################################################ # # Copyright (c) 1995-2014 SUSE Linux Products GmbH # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 or 3 as # published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program (see the file COPYING); if not, write to the # Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA # ################################################################ EC2_BUILD_TYPE="t1.micro" EC2_INSTANCE_ID= EC2_VOLUME_ROOT= EC2_VOLUME_SWAP= cloud_volume_attach_ec2() { local VM_SERVER="$1" local VM_VOL_NAME="$2" temp_file=`mktemp` if ! ec2-attach-volume "$VM_VOL_NAME" -d /dev/sdz -i `ec2-instance-id` --region "$BUILD_EC2_REGION" > "$temp_file"; then rm -f "$temp_file" cleanup_and_exit 1 fi # wait that it becomes available while true; do state=`ec2_volume_state "$VM_VOL_NAME"` test "$state" = attached && break sleep 1 done # print device node grep ^ATTACHMENT "$temp_file" | awk '{ print $4 }' rm -f "$temp_file" } cloud_volume_detach_ec2() { local VM_SERVER="$1" local VM_VOL_NAME="$2" state=`ec2_volume_state "$VM_VOL_NAME"` if test "$state" != available ; then ec2-detach-volume "$VM_VOL_NAME" --region "$BUILD_EC2_REGION" || return 3 fi return 0 } vm_wipe_ec2() { # not yet implemented : } vm_verify_options_ec2() { EC2_VOLUME_ROOT="$VM_ROOT" EC2_VOLUME_SWAP="$VM_SWAP" VM_ROOT_TYPE=unattached VM_SWAP_TYPE=unattached if test -n "$KILL" -o -n "$DO_WIPE" ; then return fi # verify settings if test -z "$AWS_ACCESS_KEY" -o -z "$AWS_ACCESS_KEY" ; then cleanup_and_exit 3 "ERROR: No amazon EC2 environment set. Set AWS_ACCESS_KEY and AWS_SECRET_KEY." fi . /etc/profile.d/ec2.sh EC2_INSTANCE_ID=`ec2-instance-id` BUILD_EC2_AKI= BUILD_EC2_ZONE=`ec2-meta-data placement/availability-zone` BUILD_EC2_REGION=${BUILD_EC2_ZONE%?} case "$BUILD_EC2_ZONE" in us-east-1) BUILD_EC2_AKI=aki-88aa75e1 ;; us-west-1) BUILD_EC2_AKI=aki-f77e26b2 ;; us-west-2) BUILD_EC2_AKI=aki-fc37bacc ;; eu-west-1) BUILD_EC2_AKI=aki-71665e05 ;; ap-southeast-1) BUILD_EC2_AKI=aki-fe1354ac ;; ap-southeast-2) BUILD_EC2_AKI=aki-3f990e05 ;; ap-northeast-1) BUILD_EC2_AKI=aki-44992845 ;; sa-east-1) BUILD_EC2_AKI=aki-c48f51d9 ;; us-gov-west-1) BUILD_EC2_AKI=aki-79a4c05a ;; esac if test -z "$BUILD_EC2_AKI" ; then cleanup_and_exit 1 "Unknown Amazon EC2 Zone: $BUILD_EC2_ZONE" fi if test -z "$BUILD_EC2_AKI" ; then cleanup_and_exit 3 "ERROR: No image refering to kernel and ramdisk is defined in BUILD_EC2_AKI env." fi if test -z "$VM_ROOT" ; then cleanup_and_exit 3 "ERROR: No worker root VM volume name specified." fi if test -z "$VM_SWAP" ; then cleanup_and_exit 3 "ERROR: No worker swap VM volume name specified." fi VM_SWAPDEV=/dev/sdb1 # in the vm } vm_attach_root_ec2() { VM_ROOT=`cloud_volume_attach_ec2 "$VM_SERVER" "$EC2_VOLUME_ROOT" test "${VM_ROOT:0:5}" = /dev/ || cleanup_and_exit 3 VM_ROOT_TYPE=device } vm_attach_swap_ec2() { VM_SWAP=`cloud_volume_attach_ec2 "$VM_SERVER" "$EC2_VOLUME_SWAP" test "${VM_SWAP:0:5}" = /dev/ || cleanup_and_exit 3 VM_SWAP_TYPE=device } vm_detach_root_ec2() { test "$VM_ROOT_TYPE" = device && cloud_volume_detach_ec2 "$VM_SERVER" "$EC2_VOLUME_ROOT" VM_ROOT_TYPE=unattached } vm_detach_swap_ec2() { test "$VM_SWAP_TYPE" = device && cloud_volume_detach_ec2 "$VM_SERVER" "$EC2_VOLUME_SWAP" VM_SWAP_TYPE=unattached } vm_fixup_ec2() { # No way to handle this via init= parameter here.... echo "#!/bin/sh" > "$BUILD_ROOT/sbin/init" echo 'exec /.build/build "$@"' >> "$BUILD_ROOT/sbin/init" chmod 0755 "$BUILD_ROOT/sbin/init" # use the instance kernel, if no kernel got installed via preinstall if ! test -e "$BUILD_ROOT/boot/vmlinuz"; then cp /boot/vmlinuz-ec2 "$BUILD_ROOT/boot/vmlinuz" cp /boot/initrd-ec2 "$BUILD_ROOT/boot/initrd" fi # install menu.lst for pv grub if ! test -e "$BUILD_ROOT/boot/grub/menu.lst"; then mkdir -p "$BUILD_ROOT/boot/grub" echo "serial --unit=0 --speed=9600" > "$BUILD_ROOT/boot/grub/menu.lst" echo "terminal --dumb serial" >> "$BUILD_ROOT/boot/grub/menu.lst" echo "default 0" >> "$BUILD_ROOT/boot/grub/menu.lst" echo "timeout 0" >> "$BUILD_ROOT/boot/grub/menu.lst" echo "hiddenmenu" >> "$BUILD_ROOT/boot/grub/menu.lst" echo "" >> "$BUILD_ROOT/boot/grub/menu.lst" echo "title default" >> "$BUILD_ROOT/boot/grub/menu.lst" echo " root (hd0)" >> "$BUILD_ROOT/boot/grub/menu.lst" echo " kernel /boot/vmlinuz root=/dev/sda1 xencons=xvc0 console=xvc0 splash=silent $vm_linux_kernel_parameter" >> "$BUILD_ROOT/boot/grub/menu.lst" echo " initrd /boot/initrd" >> "$BUILD_ROOT/boot/grub/menu.lst" fi } vm_cleanup_ec2() { cloud_volume_detach_ec2 "$VM_SERVER" "$EC2_VOLUME_ROOT" cloud_volume_detach_ec2 "$VM_SERVER" "$EC2_VOLUME_SWAP" test -n "$EC2_SNAP_root" && ec2-delete-snapshot --region "$BUILD_EC2_REGION" "$EC2_SNAP_root" test -n "$EC2_SNAP_swap" && ec2-delete-snapshot --region "$BUILD_EC2_REGION" "$EC2_SNAP_swap" test -n "$EC2_EXTRACT_VOLUME_root" && ec2-delete-volume --region "$BUILD_EC2_REGION" "$EC2_EXTRACT_VOLUME_root" test -n "$EC2_EXTRACT_VOLUME_swap" && ec2-delete-volume --region "$BUILD_EC2_REGION" "$EC2_EXTRACT_VOLUME_swap" } vm_sysrq_ec2() { : } vm_kill_ec2() { if ec2-describe-instance-status "$VM_BUILD_INSTANCE" --region "$BUILD_EC2_REGION" >/dev/null 2>&1 ; then if ec2-terminate-instances "$VM_BUILD_INSTANCE" >/dev/null 2>&1 ; then cleanup_and_exit 1 "could not kill EC2 instance $VM_BUILD_INSTANCE" fi fi } vm_startup_ec2() { EC2_SNAP_root=`ec2-create-snapshot --region "$BUILD_EC2_REGION" "$EC2_VOLUME_ROOT" | awk '{ print $2 }'` if test "$EC2_SNAP_root" = "${EC2_SNAP_root#snap-}" ; then cleanup_and_exit 3 "ERROR: Failed to create snapshot for root disk $EC2_VOLUME_ROOT" fi EC2_SNAP_swap=`ec2-create-snapshot --region "$BUILD_EC2_REGION" "$EC2_VOLUME_SWAP" | awk '{ print $2 }'` if test "$EC2_SNAP_swap" = "${EC2_SNAP_swap#snap-}" ; then echo "ERROR: Failed to create snapshot for swap disk $EC2_VOLUME_SWAP" ec2-delete-snapshot --region "$BUILD_EC2_REGION" "$EC2_SNAP_root" cleanup_and_exit 3 fi # wait for snapshots being processed while true; do c=`ec2-describe-snapshots --region "$BUILD_EC2_REGION" "$EC2_SNAP_root" "$EC2_SNAP_swap" | grep completed | wc -l` test "$c" = 2 && break done EC2_AMI=`ec2-register --region "$BUILD_EC2_REGION" -n build-$EC2_VOLUME_ROOT -a x86_64 -b "/dev/sda1=$EC2_SNAP_root::false" -b "/dev/sdb1=$EC2_SNAP_swap::false" --kernel "$BUILD_EC2_AKI" | awk '{ print $2 }'` if test "$EC2_AMI" == "${EC2_AMI#ami-}" ; then echo "ERROR: Failed to register the AMI" ec2-delete-snapshot --region "$BUILD_EC2_REGION" "$EC2_SNAP_root" ec2-delete-snapshot --region "$BUILD_EC2_REGION" "$EC2_SNAP_swap" cleanup_and_exit 3 fi INSTANCE=`ec2-run-instances --region "$BUILD_EC2_REGION" -z "$BUILD_EC2_ZONE" -t $EC2_BUILD_TYPE --kernel "$BUILD_EC2_AKI" --instance-initiated-shutdown-behavior terminate "$EC2_AMI" | grep ^INSTANCE | awk '{ print $2 }'` if test "$INSTANCE" == "${INSTANCE#i-}" ; then echo "ERROR: Failed to run the instance for AMI $EC2_AMI" ec2-deregister --region "$BUILD_EC2_REGION" "$EC2_AMI" ec2-delete-snapshot --region "$BUILD_EC2_REGION" "$EC2_SNAP_root" ec2-delete-snapshot --region "$BUILD_EC2_REGION" "$EC2_SNAP_swap" cleanup_and_exit 3 fi echo "Waiting for finishing the build. No log file until then on EC2 ...." I=0 L=0 EC2_EXTRACT_VOLUME_root= EC2_EXTRACT_VOLUME_swap= temp_file=`mktemp` while true; do ec2-describe-instances --region "$BUILD_EC2_REGION" "$INSTANCE" > $temp_file state=`grep ^INSTANCE "$temp_file"` if test -z "$EC2_EXTRACT_VOLUME_root" ; then EC2_EXTRACT_VOLUME_root=`grep ^BLOCKDEVICE $temp_file | grep /dev/sda1 | awk '{ print $3 }'` EC2_EXTRACT_VOLUME_swap=`grep ^BLOCKDEVICE $temp_file | grep /dev/sdb1 | awk '{ print $3 }'` fi # the column of the state is at a differen position depending on the state :/ # test "$state" = "${state/stopped/}" || break test "$state" = "${state/terminated/}" || break I=$(( $I + 1 )) if test $I -gt 10 ; then echo -n . I=0 L=$(( $L + 1 )) fi if test $L -gt 10 ; then # dump entire console log as raw here ec2-get-console-output --region "$BUILD_EC2_REGION" -r "$INSTANCE" L=0 fi sleep 1 done rm -f "$temp_file" echo ec2-deregister --region "$BUILD_EC2_REGION" "$EC2_AMI" # switch to extract volumnes EC2_VOLUME_ROOT=$EC2_EXTRACT_VOLUME_root EC2_VOLUME_SWAP=$EC2_EXTRACT_VOLUME_swap # snapshots get deleted after extract }