Change-Id: Ia1a025585cf2ce3cf008d75a3e52881d29ef774a
Reviewed-on: http://photon-jenkins.eng.vmware.com:8082/2672
Tested-by: gerrit-photon <photon-checkins@vmware.com>
Reviewed-by: Anish Swaminathan <anishs@vmware.com>
Reviewed-by: Sharath George
(cherry picked from commit 21eb5b23a4fff599a6cf0d1c324f41bb1e1f3869)
Reviewed-on: http://photon-jenkins.eng.vmware.com:8082/3394
| 1 | 1 |
new file mode 100755 |
| ... | ... |
@@ -0,0 +1,340 @@ |
| 0 |
+#!/bin/bash |
|
| 1 |
+ |
|
| 2 |
+set -o errexit # exit if any command returns non true return value |
|
| 3 |
+set -o nounset # exit if you try to use uninitialised variable |
|
| 4 |
+set -x |
|
| 5 |
+PRGNAME=${0##*/} # script name minus the path
|
|
| 6 |
+LOGFILE="${PRGNAME}-$(date +%Y-%m-%d).log"
|
|
| 7 |
+ |
|
| 8 |
+#expected number of command line argument |
|
| 9 |
+NARGS=16 |
|
| 10 |
+ARGS_PASSED=$# |
|
| 11 |
+VOLUME_SIZE=10 |
|
| 12 |
+COPY_VOLUME_SIZE=20 |
|
| 13 |
+DEVICE="/dev/xvdd" |
|
| 14 |
+COPY_DEVICE="/dev/xvdc" |
|
| 15 |
+EBS_IMAGE_ROOT_DEVICE_NAME="/dev/xvda" |
|
| 16 |
+LOOP_WAIT=2 |
|
| 17 |
+SSH_WAIT=30 |
|
| 18 |
+SNAPSHOT_WAIT=60 |
|
| 19 |
+LOOP_TRIAL=100 |
|
| 20 |
+ |
|
| 21 |
+#AMI_IDS of different US Regions |
|
| 22 |
+AMI_ID_US_EAST_1="ami-83614695" |
|
| 23 |
+AMI_ID_US_EAST_2="ami-45311120" |
|
| 24 |
+AMI_ID_US_WEST_1="ami-e04b6380" |
|
| 25 |
+AMI_ID_US_WEST_2="ami-c0df50a0" |
|
| 26 |
+ |
|
| 27 |
+while [[ $# > 0 ]] |
|
| 28 |
+do |
|
| 29 |
+ key="$1" |
|
| 30 |
+ shift |
|
| 31 |
+ |
|
| 32 |
+ case $key in |
|
| 33 |
+ -g|--GN) |
|
| 34 |
+ GROUP_NAME="$1" |
|
| 35 |
+ shift |
|
| 36 |
+ ;; |
|
| 37 |
+ -ai|--AMI_ID) |
|
| 38 |
+ AMI_ID="$1" |
|
| 39 |
+ shift |
|
| 40 |
+ ;; |
|
| 41 |
+ -tf|--TAR_FILE) |
|
| 42 |
+ TAR_FILE="$1" |
|
| 43 |
+ shift |
|
| 44 |
+ ;; |
|
| 45 |
+ -kn|--KEY_NAME) |
|
| 46 |
+ KEY_NAME="$1" |
|
| 47 |
+ shift |
|
| 48 |
+ ;; |
|
| 49 |
+ -n|--IMG_NAME) |
|
| 50 |
+ IMAGE_NAME="$1" |
|
| 51 |
+ shift |
|
| 52 |
+ ;; |
|
| 53 |
+ -aki|--ACCESS_KEY_ID) |
|
| 54 |
+ ACCESS_KEY_ID="$1" |
|
| 55 |
+ shift |
|
| 56 |
+ ;; |
|
| 57 |
+ -sak|--SECRET_ACCESS_KEY) |
|
| 58 |
+ SECRET_ACCESS_KEY="$1" |
|
| 59 |
+ shift |
|
| 60 |
+ ;; |
|
| 61 |
+ -dr|--DEFAULT_REGION) |
|
| 62 |
+ DEFAULT_REGION="$1" |
|
| 63 |
+ shift |
|
| 64 |
+ ;; |
|
| 65 |
+ -h|--help) |
|
| 66 |
+ echo 'Usage:' |
|
| 67 |
+ echo '-g|--GN :security group name for the instance' |
|
| 68 |
+ echo '-ai|--AMI_ID :ami id for launching an instance. This is optional' |
|
| 69 |
+ echo '-tf|--TAR_FILE :tar filename without extension' |
|
| 70 |
+ echo '-kn|--KEY_NAME :pem filename without pem extension to download' |
|
| 71 |
+ echo '-n|--IMG_NAME :sets name of the ebs image' |
|
| 72 |
+ echo '-aki|--ACCESS_KEY_ID :aws access key id' |
|
| 73 |
+ echo '-sak|--SECRET_ACCESS_KEY :aws secret access key' |
|
| 74 |
+ echo '-dr|--DEFAULT_REEGION :aws default region' |
|
| 75 |
+ exit 0 |
|
| 76 |
+ ;; |
|
| 77 |
+ *) |
|
| 78 |
+ # unknown option |
|
| 79 |
+ ;; |
|
| 80 |
+ esac |
|
| 81 |
+done |
|
| 82 |
+ |
|
| 83 |
+if [ $ARGS_PASSED -eq $[$NARGS-2] ]; then |
|
| 84 |
+ if [ ! -z "${AMI_ID:-}" ]; then
|
|
| 85 |
+ echo "Error in the arguments passed. Try ./create-ebs-image.sh -h for help" |
|
| 86 |
+ exit 1 |
|
| 87 |
+ fi |
|
| 88 |
+ key=$DEFAULT_REGION |
|
| 89 |
+ case $key in |
|
| 90 |
+ us-east-1) |
|
| 91 |
+ AMI_ID=$AMI_ID_US_EAST_1 |
|
| 92 |
+ ;; |
|
| 93 |
+ us-east-2) |
|
| 94 |
+ AMI_ID=$AMI_ID_US_EAST_2 |
|
| 95 |
+ ;; |
|
| 96 |
+ us-west-1) |
|
| 97 |
+ AMI_ID=$AMI_ID_US_WEST_1 |
|
| 98 |
+ ;; |
|
| 99 |
+ us-west-2) |
|
| 100 |
+ AMI_ID=$AMI_ID_US_WEST_2 |
|
| 101 |
+ ;; |
|
| 102 |
+ *) |
|
| 103 |
+ #unkown region |
|
| 104 |
+ exit 1 |
|
| 105 |
+ esac |
|
| 106 |
+ ARGS_PASSED=$[$ARGS_PASSED+2] |
|
| 107 |
+fi |
|
| 108 |
+ |
|
| 109 |
+if [ $ARGS_PASSED -ne $NARGS ]; then |
|
| 110 |
+ echo "Error in the arguments passed. Try ./create-ebs-image.sh -h for help" |
|
| 111 |
+ exit 1 |
|
| 112 |
+fi |
|
| 113 |
+ |
|
| 114 |
+#set the credential necessary to run the aws cli |
|
| 115 |
+export AWS_ACCESS_KEY_ID=$ACCESS_KEY_ID |
|
| 116 |
+export AWS_SECRET_ACCESS_KEY=$SECRET_ACCESS_KEY |
|
| 117 |
+export AWS_DEFAULT_REGION=$DEFAULT_REGION |
|
| 118 |
+KEY_FILE=$KEY_NAME.pem |
|
| 119 |
+ |
|
| 120 |
+function cleanup {
|
|
| 121 |
+ if [ ! -z "${INSTANCE_ID:-}" ]; then
|
|
| 122 |
+ aws ec2 terminate-instances --instance-ids $INSTANCE_ID |
|
| 123 |
+ while : ; do |
|
| 124 |
+ INSTANCE_STATE=`aws ec2 describe-instances --instance-ids $INSTANCE_ID --output=text --query 'Reservations[0].Instances[0].State.Name'` |
|
| 125 |
+ if [ "$INSTANCE_STATE" == "terminated" ]; then |
|
| 126 |
+ break |
|
| 127 |
+ fi |
|
| 128 |
+ sleep $LOOP_WAIT |
|
| 129 |
+ done |
|
| 130 |
+ fi |
|
| 131 |
+ if [ ! -z "${VOLUMEID_COPY:-}" ]; then
|
|
| 132 |
+ aws ec2 delete-volume --volume-id $VOLUMEID_COPY |
|
| 133 |
+ fi |
|
| 134 |
+ if [ ! -z "${GROUP_NAME:-}" ]; then
|
|
| 135 |
+ aws ec2 delete-security-group --group-name $GROUP_NAME |
|
| 136 |
+ fi |
|
| 137 |
+ if [ ! -z "${KEY_NAME:-}" ]; then
|
|
| 138 |
+ aws ec2 delete-key-pair --key-name $KEY_NAME |
|
| 139 |
+ fi |
|
| 140 |
+ rm $KEY_FILE |
|
| 141 |
+} |
|
| 142 |
+trap 'cleanup' EXIT |
|
| 143 |
+ |
|
| 144 |
+function check_counter {
|
|
| 145 |
+ if [ $# -ne 3 ]; then |
|
| 146 |
+ echo "Pass the counter,max value and the error message" |
|
| 147 |
+ exit 1 |
|
| 148 |
+ fi |
|
| 149 |
+ if [ $1 -ge $2 ]; then |
|
| 150 |
+ echo "$3" >> $LOGFILE |
|
| 151 |
+ exit |
|
| 152 |
+ fi |
|
| 153 |
+} |
|
| 154 |
+ |
|
| 155 |
+#Start an AMI Instance |
|
| 156 |
+aws ec2 create-security-group --group-name $GROUP_NAME --description "AMI Creation Sec Group" |
|
| 157 |
+aws ec2 authorize-security-group-ingress --group-name $GROUP_NAME --protocol tcp --port 22 --cidr 0.0.0.0/0 |
|
| 158 |
+aws ec2 create-key-pair --key-name $KEY_NAME --query 'KeyMaterial' --output text > $KEY_FILE |
|
| 159 |
+chmod 400 $KEY_FILE |
|
| 160 |
+SECURITY_GROUP_ID=`aws ec2 describe-security-groups --group-name $GROUP_NAME --output=text --query 'SecurityGroups[0].GroupId'` |
|
| 161 |
+INSTANCE_ID=`aws ec2 run-instances --image-id $AMI_ID --security-group-ids $SECURITY_GROUP_ID --count 1 --instance-type m3.medium --key-name $KEY_NAME --output=text --query 'Instances[0].InstanceId'` |
|
| 162 |
+AVAILABILITY_ZONE=`aws ec2 describe-instances --instance-ids $INSTANCE_ID --output=text --query 'Reservations[0].Instances[0].Placement.AvailabilityZone'` |
|
| 163 |
+ |
|
| 164 |
+count=0 |
|
| 165 |
+while : ; do |
|
| 166 |
+ INSTANCE_STATE=`aws ec2 describe-instances --instance-ids $INSTANCE_ID --output=text --query 'Reservations[0].Instances[0].State.Name'` |
|
| 167 |
+ if [ "$INSTANCE_STATE" == "running" ]; then |
|
| 168 |
+ break |
|
| 169 |
+ else |
|
| 170 |
+ count=$[$count+1] |
|
| 171 |
+ fi |
|
| 172 |
+ check_counter $count $LOOP_TRIAL "Instance $INSTANCE_ID not in running state" |
|
| 173 |
+ sleep $LOOP_WAIT |
|
| 174 |
+done |
|
| 175 |
+ |
|
| 176 |
+count=0 |
|
| 177 |
+while : ; do |
|
| 178 |
+ IP=`aws ec2 describe-instances --instance-ids $INSTANCE_ID --output=text --query 'Reservations[0].Instances[0].PublicIpAddress'` |
|
| 179 |
+ if [ "$IP" == "None" ]; then |
|
| 180 |
+ count=$[$count+1] |
|
| 181 |
+ else |
|
| 182 |
+ break |
|
| 183 |
+ fi |
|
| 184 |
+ check_counter $count $LOOP_TRIAL "Instance $INSTANCE_ID does not have an IP yet" |
|
| 185 |
+ sleep $LOOP_WAIT |
|
| 186 |
+done |
|
| 187 |
+ |
|
| 188 |
+sleep $SSH_WAIT |
|
| 189 |
+ |
|
| 190 |
+while : ; do |
|
| 191 |
+ output=$(eval ssh -o StrictHostKeyChecking=no -i $KEY_FILE root@$IP 'tdnf install -y kpartx wget') |
|
| 192 |
+ ret=$? |
|
| 193 |
+ if [ "$ret" -eq 0 ]; then |
|
| 194 |
+ break |
|
| 195 |
+ else |
|
| 196 |
+ count=$[$count+1] |
|
| 197 |
+ fi |
|
| 198 |
+ check_counter $count $LOOP_TRIAL "Unable to ssh the Instance $INSTANCE_ID with IP $IP" |
|
| 199 |
+ sleep $LOOP_WAIT |
|
| 200 |
+done |
|
| 201 |
+ |
|
| 202 |
+#create two volumes one to copy the tar file and another for ebs image creation |
|
| 203 |
+VOLUMEID=`aws ec2 create-volume --size $VOLUME_SIZE --region $AWS_DEFAULT_REGION --availability-zone $AVAILABILITY_ZONE --output=text --query 'VolumeId'` |
|
| 204 |
+VOLUMEID_COPY=`aws ec2 create-volume --size $COPY_VOLUME_SIZE --region $AWS_DEFAULT_REGION --availability-zone $AVAILABILITY_ZONE --output=text --query 'VolumeId'` |
|
| 205 |
+ |
|
| 206 |
+#attach both the volumes |
|
| 207 |
+count=0 |
|
| 208 |
+while : ; do |
|
| 209 |
+ STATE_1=`aws ec2 describe-volumes --volume-id $VOLUMEID_COPY --output=text --query 'Volumes[0].State'` |
|
| 210 |
+ if [ "$STATE_1" == "available" ]; then |
|
| 211 |
+ break |
|
| 212 |
+ else |
|
| 213 |
+ count=$[$count+1] |
|
| 214 |
+ fi |
|
| 215 |
+ check_counter $count $LOOP_TRIAL "Volume with ID $VOLUMEID_COPY is not available" |
|
| 216 |
+ sleep $LOOP_WAIT |
|
| 217 |
+done |
|
| 218 |
+ |
|
| 219 |
+aws ec2 attach-volume --volume-id $VOLUMEID_COPY --instance-id $INSTANCE_ID --device $COPY_DEVICE --region $AWS_DEFAULT_REGION >> $LOGFILE |
|
| 220 |
+ |
|
| 221 |
+count=0 |
|
| 222 |
+while : ; do |
|
| 223 |
+ STATE_2=`aws ec2 describe-volumes --volume-id $VOLUMEID_COPY --output=text --query 'Volumes[0].Attachments[0].State'` |
|
| 224 |
+ if [ "$STATE_2" == "attached" ]; then |
|
| 225 |
+ break |
|
| 226 |
+ else |
|
| 227 |
+ count=$[$count+1] |
|
| 228 |
+ fi |
|
| 229 |
+ check_counter $count $LOOP_TRIAL "Volume with ID $VOLUMEID_COPY is not in attached state" |
|
| 230 |
+ sleep $LOOP_WAIT |
|
| 231 |
+done |
|
| 232 |
+ |
|
| 233 |
+count=0 |
|
| 234 |
+while : ; do |
|
| 235 |
+ STATE_3=`aws ec2 describe-volumes --volume-id $VOLUMEID --output=text --query 'Volumes[0].State'` |
|
| 236 |
+ if [ "$STATE_3" == "available" ]; then |
|
| 237 |
+ break |
|
| 238 |
+ else |
|
| 239 |
+ count=$[$count+1] |
|
| 240 |
+ fi |
|
| 241 |
+ check_counter $count $LOOP_TRIAL "Volume with ID $VOLUMEID is not available" |
|
| 242 |
+ sleep $LOOP_WAIT |
|
| 243 |
+done |
|
| 244 |
+ |
|
| 245 |
+aws ec2 attach-volume --volume-id $VOLUMEID --instance-id $INSTANCE_ID --device $DEVICE --region $AWS_DEFAULT_REGION >> $LOGFILE |
|
| 246 |
+ |
|
| 247 |
+count=0 |
|
| 248 |
+while : ; do |
|
| 249 |
+ STATE_4=`aws ec2 describe-volumes --volume-id $VOLUMEID --output text --query 'Volumes[0].Attachments[0].State'` |
|
| 250 |
+ if [ "$STATE_4" == "attached" ]; then |
|
| 251 |
+ break |
|
| 252 |
+ else |
|
| 253 |
+ count=$[$count+1] |
|
| 254 |
+ fi |
|
| 255 |
+ check_counter $count $LOOP_TRIAL "Volume with ID $VOLUMEID is not in attached state" |
|
| 256 |
+ sleep $LOOP_WAIT |
|
| 257 |
+done |
|
| 258 |
+ |
|
| 259 |
+#Copy the image file |
|
| 260 |
+ssh -i $KEY_FILE root@$IP 'rm -rf /mnt/copy; rm -rf /mnt/ebs; mkdir /mnt/copy; mkdir /mnt/ebs' >> $LOGFILE |
|
| 261 |
+ssh -i $KEY_FILE root@$IP "mkfs.ext4 $COPY_DEVICE" >> $LOGFILE |
|
| 262 |
+ssh -i $KEY_FILE root@$IP "mount $COPY_DEVICE /mnt/copy" >> $LOGFILE |
|
| 263 |
+scp -i $KEY_FILE $TAR_FILE.tar.gz root@$IP:/mnt/copy >> $LOGFILE |
|
| 264 |
+ssh -i $KEY_FILE root@$IP "cd /mnt/copy; tar -xf $TAR_FILE.tar.gz; dd if=$TAR_FILE.raw of=$DEVICE bs=1M" >> $LOGFILE |
|
| 265 |
+ssh -i $KEY_FILE root@$IP 'umount /mnt/copy' |
|
| 266 |
+ssh -i $KEY_FILE root@$IP 'rm -rf /mnt/copy /mnt/ebs' |
|
| 267 |
+ |
|
| 268 |
+#detach the volume |
|
| 269 |
+aws ec2 detach-volume --volume-id $VOLUMEID --region $AWS_DEFAULT_REGION >> $LOGFILE |
|
| 270 |
+aws ec2 detach-volume --volume-id $VOLUMEID_COPY --region $AWS_DEFAULT_REGION >> $LOGFILE |
|
| 271 |
+ |
|
| 272 |
+#wait for the volume to detach |
|
| 273 |
+count=0 |
|
| 274 |
+while : ; do |
|
| 275 |
+ STATE_5=`aws ec2 describe-volumes --volume-id $VOLUMEID --output text --query 'Volumes[0].Attachments[0].State'` |
|
| 276 |
+ if [ "$STATE_5" == "detached" ] || [ "$STATE_5" == "None" ]; then |
|
| 277 |
+ break |
|
| 278 |
+ else |
|
| 279 |
+ count=$[$count+1] |
|
| 280 |
+ fi |
|
| 281 |
+ check_counter $count $LOOP_TRIAL "Volume with ID $VOLUMEID is not in detached state" |
|
| 282 |
+ sleep $LOOP_WAIT |
|
| 283 |
+done |
|
| 284 |
+ |
|
| 285 |
+#create the snapshot |
|
| 286 |
+SNAPSHOT_ID=`aws ec2 create-snapshot --region $AWS_DEFAULT_REGION --description $TAR_FILE --volume-id $VOLUMEID --output=text --query 'SnapshotId'` |
|
| 287 |
+ |
|
| 288 |
+#wait for the snapshot creation to succeed. This takes some time |
|
| 289 |
+count=0 |
|
| 290 |
+while : ; do |
|
| 291 |
+ PROGRESS=`aws ec2 describe-snapshots --region $AWS_DEFAULT_REGION --snapshot-id $SNAPSHOT_ID --output=text --query 'Snapshots[0].Progress'` |
|
| 292 |
+ echo $PROGRESS |
|
| 293 |
+ if [ "$PROGRESS" == "100%" ]; then |
|
| 294 |
+ break |
|
| 295 |
+ else |
|
| 296 |
+ count=$[$count+1] |
|
| 297 |
+ fi |
|
| 298 |
+ check_counter $count $LOOP_TRIAL "Snapshot creation for snapshot with ID $SNAPSHOT_ID failed" |
|
| 299 |
+ sleep $SNAPSHOT_WAIT |
|
| 300 |
+done |
|
| 301 |
+ |
|
| 302 |
+#register the image name |
|
| 303 |
+AMI_IMAGE_ID=`aws ec2 register-image --region $AWS_DEFAULT_REGION --name $TAR_FILE --root-device-name $EBS_IMAGE_ROOT_DEVICE_NAME --ena-support --block-device-mappings DeviceName=$EBS_IMAGE_ROOT_DEVICE_NAME,Ebs={SnapshotId=$SNAPSHOT_ID} --virtualization-type hvm --architecture x86_64 --output=text --query 'ImageId'`
|
|
| 304 |
+ |
|
| 305 |
+#check the status of the AMI |
|
| 306 |
+count=0 |
|
| 307 |
+while : ; do |
|
| 308 |
+ AMI_STATE=`aws ec2 describe-images --image-ids $AMI_IMAGE_ID --output=text --query 'Images[0].State'` |
|
| 309 |
+ echo $AMI_STATE |
|
| 310 |
+ if [ "$AMI_STATE" == "available" ]; then |
|
| 311 |
+ break |
|
| 312 |
+ else |
|
| 313 |
+ count=$[$count+1] |
|
| 314 |
+ fi |
|
| 315 |
+ check_counter $count $LOOP_TRIAL "Registering AMI with AMI ID $AMI_IMAGE_ID and $SNAPSHOT_ID failed" |
|
| 316 |
+ sleep $SNAPSHOT_WAIT |
|
| 317 |
+done |
|
| 318 |
+ |
|
| 319 |
+#Make AMI Public |
|
| 320 |
+aws ec2 modify-image-attribute --image-id $AMI_IMAGE_ID --launch-permission "{\"Add\":[{\"Group\":\"all\"}]}"
|
|
| 321 |
+ |
|
| 322 |
+#Loop till AMI is public |
|
| 323 |
+count=0 |
|
| 324 |
+while : ; do |
|
| 325 |
+ PUBLIC=`aws ec2 describe-images --image-ids $AMI_IMAGE_ID --output=text --query 'Images[0].Public'` |
|
| 326 |
+ echo $PUBLIC |
|
| 327 |
+ if [ "$PUBLIC" == "True" ]; then |
|
| 328 |
+ break |
|
| 329 |
+ else |
|
| 330 |
+ count=$[$count+1] |
|
| 331 |
+ fi |
|
| 332 |
+ check_counter $count $LOOP_TRIAL "Making the AMI with AMI ID $AMI_IMAGE_ID Public failed" |
|
| 333 |
+ sleep $LOOP_WAIT |
|
| 334 |
+done |
|
| 335 |
+ |
|
| 336 |
+aws ec2 create-tags --resources $SNAPSHOT_ID --tags Key=Name,Value=$IMAGE_NAME |
|
| 337 |
+aws ec2 create-tags --resources $AMI_IMAGE_ID --tags Key=Name,Value=$IMAGE_NAME |
|
| 338 |
+ |
|
| 339 |
+echo "SUCCESS: AMI with ID $AMI_IMAGE_ID was registered and made Public" |