Skip to content

Commit

Permalink
1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
reelsense committed May 18, 2018
1 parent efcf3f7 commit f5e368d
Show file tree
Hide file tree
Showing 13 changed files with 1,030 additions and 0 deletions.
116 changes: 116 additions & 0 deletions bin/ec2-resize-ebs
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
#!/bin/bash
# Stop the EC2 instance, Resize the EBS volume and reattch it, Start the EC2 instance and reassociate the original Elastic IP.

source $(dirname $0)/../inc/ec2-include

if [ ! $2 ]; then
echo "Usage: $(basename $0) INSTANCE_ID SIZE"
echo
echo " INSTANCE_ID - The EC2 instance whose EBS volume you wish to resize."
echo " SIZE - The new size for the EBS volume (In gigabytes)."
exit
fi

instanceid=$1
size=$2

# Get the root EBS volume id for the remote EC2 instance
oldvolumeid=$(ec2-describe-instances $instanceid | egrep "^BLOCKDEVICE./dev/sda1" | cut -f3)
# Get the availability zone for the remote EC2 instance
zone=$(ec2-describe-instances $instanceid | egrep ^INSTANCE | cut -f12)
# Check if the instance has an elastic IP so we can reassociate it with the instance after we stop and start it
ELASTIC_IP=$(ec2-describe-addresses | grep $instanceid | cut -f2)

# If the server didn't have an elastic IP we need to get its regular IP
if [ $ELASTIC_IP ]; then
INSTANCE_IP=$ELASTIC_IP
else
INSTANCE_IP=$(ec2-describe-instances $instanceid | egrep "^INSTANCE.$instanceid" | cut -f4)
fi

echo "Logging into remote server ($INSTANCE_IP) to check the remote filesystem is ext..."
FILESYSTEM=$(ssh -o StrictHostKeyChecking=no ubuntu@$INSTANCE_IP "df -T / | grep -v Filesystem" | awk '{ print $2 }')

# Check the filesystem is ext3 ext4 etc.. we remove the last character 3 or 4 so the check works for multiple versions and future versions of the ext filesystem
if [ ${FILESYSTEM%?} == "ext" ]; then
echo "The remote servers filesystem is $FILESYSTEM."
echo
else
echo "Error: The remote servers filesystem is '$FILESYSTEM' but this script only supports resizing ext filesystems."
exit 1
fi

# Stop the instance
echo "Stopping the remote EC2 instance ($instanceid)..."
ec2-stop-instances $instanceid
echo

# Detach the original volume from the instance
echo "Detaching the EBS volume ($oldvolumeid) from the EC2 instance..."
while ! ec2-detach-volume $oldvolumeid; do sleep 1; done
echo

# Create a snapshot of the original volume
echo "Create a snapshot of the EBS volume ($oldvolumeid)..."
snapshotid=$(ec2-create-snapshot $oldvolumeid --description "Backup before resizing the EBS volume to $size GB" | cut -f2)
while ec2-describe-snapshots $snapshotid | grep -q pending; do sleep 1; done
echo

# Set the tags on the EBS snapshot
echo "Set tags on the EBS snapshot ($snapshotid)..."
instancename=$(ec2-describe-tags --filter "resource-id=$instanceid" --filter "key=Name" | cut -f5)
ec2-create-tags $snapshotid --tag "Name=$instancename" --tag "Type=root"
echo

# Create a new volume from the snapshot, specifying a larger size
echo "Create a new volume from the EBS snapshot ($snapshotid) with the new size of $size GB..."
newvolumeid=$(ec2-create-volume --availability-zone $zone --size $size --snapshot $snapshotid | cut -f2)
echo

# Set the tags on the EBS volume
echo "Set tags on the EBS volume ($newvolumeid)..."
ec2-create-tags $newvolumeid --tag "Name=$instancename" --tag "Type=root"
echo

# Attach the new volume to the instance
echo "Attaching the new EBS volume ($newvolumeid) to the EC2 instance ($instanceid)..."
ec2-attach-volume --instance $instanceid --device /dev/sda1 $newvolumeid
while ! ec2-describe-volumes $newvolumeid | grep -q attached; do sleep 1; done
echo

# Start the instance
echo "Start the EC2 instance ($instanceid)..."
ec2-start-instances $instanceid
while ! ec2-describe-instances $instanceid | grep -q running; do sleep 1; done
echo

# Get the IP of the EC2 instance
INSTANCE_IP=$(ec2-describe-instances $instanceid | egrep "^INSTANCE.$instanceid" | cut -f4)

# Even though the server says its running it sometimes takes a few seconds to get a route to host so we delay 5 seconds
sleep 5

# Resize the root file system to fill the new EBS volume
echo "Logging into the remote server ($INSTANCE_IP) to resize the root file system (/dev/xvda1) to fill the new EBS volume..."
ssh -o StrictHostKeyChecking=no ubuntu@$INSTANCE_IP "sudo resize2fs /dev/xvda1 | df -h /"
echo

# If the instance originally had an Elastic IP attached
if [ $ELASTIC_IP ]; then
# Associate the original Elastic IP
echo "Associating elastic IP ($ELASTIC_IP)..."
ec2-associate-address $ELASTIC_IP -i $instanceid
# Wait for the Elastic IP to associate
while ! ec2-describe-addresses | grep -q $instanceid; do sleep 1; done
echo
INSTANCE_IP=$ELASTIC_IP
fi

# Delete the old EBS volume
echo "Deleting the old EBS volume..."
ec2-delete-volume $oldvolumeid
echo

# Turn on delete-on-termination
echo "Turning on delete-on-termination so that the new EBS volume will be deleted when the EC2 instance is terminated as is common with EC2 instances..."
ec2-modify-instance-attribute --block-device-mapping /dev/sda1=$newvolumeid::true $instanceid
46 changes: 46 additions & 0 deletions bin/i-associate-address
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/bin/bash
# Associate an Elastic IP Address to an instance

source $(dirname $0)/../inc/ec2-include

if [ ! $1 ]; then
echo "Usage: $(basename $0) IP"
echo
echo " IP - The elastic IP to attach to this instance. "
echo " Specifying \"new\" will create a new IP and attach it to this instance. "
exit
fi

IP=$1

ATTACHED_IP=( $(i-describe-address) )

# If an Elastic IP is already attached to this EC2 instance.
if [ ! -z "${ATTACHED_IP[1]}" ]; then
echo "This EC2 instance already has an elastic IP (${ATTACHED_IP[1]}) associated."
echo "First disassociate it with 'i-disassociate-address'"
exit
else
# If the user specified they want a new Elastic IP created
if [ $IP == "new" ]; then
echo "Creating IP Address..."
OUTPUT=( $(ec2-allocate-address) )
echo ${OUTPUT[*]}
IP=${OUTPUT[1]}
echo
else
# If the Elastic IP is associated to another EC2 instance
IPS_INSTANCE_ID=( $(ec2-describe-addresses | grep "ADDRESS" | grep $IP) )

if [[ ${IPS_INSTANCE_ID[2]} == *i-* ]]; then
echo "That Elastic IP is already associated to another EC2 instance (${IPS_INSTANCE_ID[2]})."
exit
fi
fi
fi

echo "Attaching IP Address..."
ec2-associate-address -i $INSTANCE_ID $IP

# Make the script wait until the network connection is back up before we continue.
perl -MIO::Socket::INET -e 'until(new IO::Socket::INET("169.254.169.254:80")){print"Waiting for network connection after associating an Elastic IP...\n";sleep 1}'
74 changes: 74 additions & 0 deletions bin/i-create-ami
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#!/bin/bash
# Clean Instance, Bundle Instance, Upload Bundle to S3, Register AMI

source $(dirname $0)/../inc/ec2-include

if [ ! $3 ]; then
echo "Usage: $(basename $0) BUCKET PREFIX CLEAN"
echo
echo " BUCKET - The S3 bucket where the bundled AMI should be stored."
echo " PREFIX - The filename prefix for bundled AMI files."
echo " CLEAN - Should we clean potentially private data from this instance (true/false)?"
exit
fi

BUCKET=$1
PREFIX=$2
CLEAN=$3
ACCOUNT_NUMBER=$(cat /root/.ec2/account-number)
ACCESS_KEY_ID=$(cat /root/.ec2/access-key-id)
SECRET_ACCESS_KEY=$(cat /root/.ec2/secret-access-key)

if [ $(uname -m) = 'x86_64' ]; then
ARCH=x86_64
else
ARCH=i386
fi

# For security reasons we remove any files from the instance that may contain sensitive information
if [ ! $CLEAN = "false" ]; then
echo "Cleaning the instance ready for bundling..."
rm -f /root/.*hist* $HOME/.*hist*
rm -f /root/.my.cnf
rm -rf /root/.ec2
rm -f /root/.ssh/*
rm -f /var/log/*.gz
rm -f /var/ec2/*
find /var/log -name mysql -prune -o -type f -print | while read i; do sudo cp /dev/null $i; done
fi

# Remove any existing AMI bundles, and create a location for new AMI bundles
echo
if [ -d /mnt/ami ]; then
if [ "$(ls -A /mnt/ami)" ]; then # Make sure there's files in the directory
echo "Removing existing AMI Bundle from /mnt/ami to avoid conflicts..."
rm /mnt/ami/*;
fi
else
echo "Creating a location at /mnt/ami for the bundled instance..."
mkdir /mnt/ami
fi

# Bundle the instance
echo
echo "Bundling the instance..."
sudo -E ec2-bundle-vol \
-r $ARCH \
-d /mnt/ami \
-p $PREFIX \
-u $ACCOUNT_NUMBER \
-k /root/.ec2/pk.pem \
-c /root/.ec2/cert.pem \
-s 10240 \
--ec2cert /etc/ec2/amitools/cert-ec2.pem \
-e /tmp,/mnt,/root/.ssh,/root/.ec2

# Upload bundle to an S3 Bucket
echo
echo "Uploading instance bundle to S3..."
ec2-upload-bundle -b $BUCKET -m /mnt/ami/$PREFIX.manifest.xml -a $ACCESS_KEY_ID -s $SECRET_ACCESS_KEY

# Register the AMI
echo
echo "Registering the AMI..."
ec2-register $BUCKET/$PREFIX.manifest.xml
18 changes: 18 additions & 0 deletions bin/i-delete-volume
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/bin/bash
# Unmount, Detach and Delete an EBS Volume

source $(dirname $0)/../inc/ec2-include

if [ ! $1 ]; then
echo "Usage: $(basename $0) MOUNT_POINT"
echo
echo " MOUNT_POINT - The mount location of the volume that you wish to delete. (E.g. /ebs)"
exit
fi

echo "Detaching EBS Volume..."
source i-detach-volume $1
echo

echo "Deleting EBS Volume..."
ec2-delete-volume $VOLUME_ID
6 changes: 6 additions & 0 deletions bin/i-describe-address
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/bin/bash
# Describe the Elastic IP attached to this instance

source $(dirname $0)/../inc/ec2-include

ec2-describe-addresses | grep "ADDRESS" | grep $INSTANCE_ID
6 changes: 6 additions & 0 deletions bin/i-describe-volumes
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/bin/bash
# Describe the EBS Volumes attached to this instance

source $(dirname $0)/../inc/ec2-include

ec2-describe-volumes | grep -B1 $INSTANCE_ID
108 changes: 108 additions & 0 deletions bin/i-detach-volume
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
#!/bin/bash
# Unmount, and Detach an EBS Volume

source $(dirname $0)/../inc/ec2-include

if [ ! $1 ]; then
echo "Usage: $(basename $0) MOUNT_POINT"
echo
echo " MOUNT_POINT - The mount location of the volume that you wish to detach. (E.g. /ebs)"
exit
fi

# Check if the specified mount point exists
if [ -d "$1" ]; then
# Unify mount point to ensure it will match the 'df' output
# For example ../mountpoint/ will become /mountpoint
MOUNT_POINT=$(cd "$1"; pwd)

# Find the device belonging to this mount point
DEVICE=( $(df $MOUNT_POINT | grep " $MOUNT_POINT") )
DEVICE=${DEVICE[0]}
else
MOUNT_POINT=$1
fi

if [ $DEVICE ]; then
echo "Device location for '$MOUNT_POINT' is '$DEVICE'"
echo

else
echo "Warning: '$MOUNT_POINT' isn't currently mounted."
echo " Type 'df' to list currently mounted devices."
echo
UNMOUNTED="true"

# Check /etc/fstab incase there's an entry for the device
echo "Checking /etc/fstab for an associated device..."
DEVICE=( $(cat /etc/fstab | grep " $MOUNT_POINT ") )
DEVICE=${DEVICE[0]}

if [ $DEVICE ]; then
echo "Device location for '$MOUNT_POINT' is '$DEVICE'"
echo
else
echo "Error: Couldn't locate an associated device for '$MOUNT_POINT'"
echo
exit 1
fi
fi

# Find the Volume ID of the device
echo "Locating EBS Volume ID..."
VOLUME_ID=( $(i-describe-volumes | grep "ATTACHMENT" | grep /dev/sdk${DEVICE: -1} | grep "attached") )
VOLUME_ID=${VOLUME_ID[1]}

if [ ! $VOLUME_ID ]; then
echo "Error: We couldn't associate '/dev/sdk${DEVICE: -1}' with an EBS Volume. Please ensure the device exists. "
echo " Type 'ec2-describe-volumes' to list attached EBS Volumes and their device locations."
else
echo "Volume ID is '$VOLUME_ID'"
fi

if [ ! $UNMOUNTED ]; then
# Unmount the EBS Volume
echo
echo "Unmounting device..."
umount $DEVICE
echo
fi

# Remove the EBS Volume from /etc/fstab
FSTAB_CONTENT=$(grep " $MOUNT_POINT " /etc/fstab);

if [ "$FSTAB_CONTENT" ]; then
echo "Removing the following entries from fstab:"
echo "$FSTAB_CONTENT"
cp /etc/fstab /tmp/fstab.bak
grep -v " $MOUNT_POINT " /tmp/fstab.bak > /etc/fstab
else
echo "No mount entries found in /etc/fstab"
fi

echo

# Remove the crontab entry that performs EBS Snapshots for this Volume
CRONTAB_CONTENT=$(grep "i-snapshot-volume $MOUNT_POINT " /etc/cron.d/snapshot-ebs);

if [ "$CRONTAB_CONTENT" ]; then
echo "Removing the following entries from the '/etc/cron.d/snapshot-ebs' crontab:"
echo "$CRONTAB_CONTENT"
cp /etc/cron.d/snapshot-ebs /tmp/ebs-snapshots.bak
grep -v "i-snapshot-volume $MOUNT_POINT " /tmp/ebs-snapshots.bak > /etc/cron.d/snapshot-ebs
else
echo "Cron entry wasn't found in /etc/cron.d/snapshot-ebs"
fi

echo

# Detach the EBS Volume
if [ "$VOLUME_ID" ]; then
echo "Detaching EBS Volume..."
# Wait for EBS volume to detach before doing anything else
ec2-detach-volume $VOLUME_ID --instance $INSTANCE_ID
while [ ! -z "$(i-describe-volumes | grep "ATTACHMENT" | grep /dev/sdf${DEVICE: -1})" ]; do sleep 1; done
echo
fi

echo -e "\E[31mPlease note the directory '$MOUNT_POINT' still exists but can be manually removed if unneeded.\033[0m"
7 changes: 7 additions & 0 deletions bin/i-disassociate-address
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/bash
# Disassociate the IP address from the instance.

source $(dirname $0)/../inc/ec2-include

echo "Disassociating IP ($IP) from instance..."
ec2-disassociate-address $IP
Loading

0 comments on commit f5e368d

Please sign in to comment.