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" |