· 6 years ago · Jun 17, 2019, 05:42 AM
1## Usage: see README file
2##
3#####################################################################
4import sys
5import time
6import argparse
7from boto import ec2
8from boto.exception import EC2ResponseError
9
10AWS_ACCESS_KEY = ''
11AWS_SECRET_KEY = ''
12AWS_REGION = u'us-west-1'
13
14def confirm_action (msg):
15 """
16 Confirms action with user
17 """
18
19 valid = {'yes':True, 'y':True,
20 'no':False, 'n':False}
21
22 while True:
23 sys.stdout.write (msg+' ')
24 choice = raw_input().lower()
25 if choice in valid.keys ():
26 return valid[choice]
27 sys.stdout.write ('Please respond with \'yes\' or \'no\' (or \'y\' or \'n\').\n')
28
29def ec2_connect (access_key, secret_key, region):
30 """
31 Connects to EC2, returns a connection object
32 """
33
34 try:
35 conn = ec2.connect_to_region (region,
36 aws_access_key_id=access_key,
37 aws_secret_access_key=secret_key)
38 except Exception, e:
39 sys.stderr.write ('Could not connect to region: %s. Exception: %s\n' % (region, e))
40 conn = None
41
42 return conn
43
44
45def start_instance (conn, instance_id):
46 """
47 Gets a connection object and instance id
48 Starts the instance and waits until it's in 'running' state
49 """
50
51 sys.stdout.write ('Starting instance %s\n' % instance_id)
52 try:
53 instance = conn.start_instances (instance_ids=[instance_id])[0]
54 except EC2ResponseError, e:
55 sys.stderr.write ('Could not start instance %s. Error: %s\n' % (instance_id, e.error_message))
56 return False
57
58 status = instance.update ()
59 while status != u'running':
60 sys.stdout.write ('Waiting for instance %s to be in \'running\' state\n' % instance_id)
61 time.sleep (5)
62 status = instance.update ()
63
64 sys.stdout.write ('Successfully started instance %s\n' % instance_id)
65 return True
66
67def reboot_instance (conn, instance_id):
68 """
69 Gets a connection object and instance id
70 Reboots the instance and waits until it's in 'running' state
71 """
72
73 sys.stdout.write ('Rebooting instance %s\n' % instance_id)
74 try:
75 instance = conn.reboot_instances (instance_ids=[instance_id])[0]
76 except EC2ResponseError, e:
77 sys.stderr.write ('Could not re-reboot instance %s. Error: %s\n' % (instance_id, e.error_message))
78 return False
79
80 status = instance.update ()
81 while status != u'running':
82 sys.stdout.write ('Waiting for instance %s to be in \'running\' state\n' % instance_id)
83 time.sleep (5)
84 status = instance.update ()
85
86 sys.stdout.write ('Successfully rebooted instance %s\n' % instance_id)
87 return True
88
89def stop_instance (conn, instance_id):
90 """
91 Gets a connection object and instance id
92 Stops the instance and waits until it's in 'stopped' state
93 """
94
95 sys.stdout.write ('Stopping instance %s\n' % instance_id)
96 try:
97 instance = conn.stop_instances (instance_ids=[instance_id])[0]
98 except EC2ResponseError, e:
99 sys.stderr.write ('Could not stop instance %s. Error: %s\n' % (instance_id, e.error_message))
100 return False
101
102 status = instance.update ()
103 while status != u'stopped':
104 sys.stdout.write ('Waiting for instance %s to be in \'stopped\' state\n' % instance_id)
105 time.sleep (5)
106 status = instance.update ()
107
108 sys.stdout.write ('Successfully stopped instance %s\n' % instance_id)
109 return True
110
111def kill_instance (conn, instance_id):
112 """
113 Gets a connection object and instance id
114 Kills an instancemeaning terminating it and making sure all attached volumes
115 are deleted
116 """
117
118 sys.stdout.write ('Killing instance %s and all its attached volumes\n' % instance_id)
119 # gets instance
120 try:
121 instance = conn.get_all_instances (instance_ids=[instance_id])[0].instances[0]
122 except EC2ResponseError, e:
123 sys.stderr.write ('Could not kill instance %s. Error: %s\n' % (instance_id, e.error_message))
124 return False
125
126 # find block devices
127 vols_to_delete = []
128 for bd in instance.block_device_mapping.values():
129 if bd.delete_on_termination == False:
130 vols_to_delete.append (bd.volume_id)
131
132 # terminate instance
133 try:
134 conn.terminate_instances (instance_ids=[instance_id])
135 except EC2ResponseError, e:
136 sys.stderr.write ('Could not kill instance %s. Error: %s\n' % (instance_id, e.error_message))
137 return False
138
139 # waits for termination
140 status = instance.update ()
141 while status != u'terminated':
142 sys.stdout.write ('Waiting for instance %s to be in \'terminated\' state\n' % instance_id)
143 time.sleep (5)
144 status = instance.update ()
145
146 # deletes extra volumes
147 first_vol_delete = True
148 for vol in vols_to_delete:
149 for try_num in 1,2:
150 sys.stdout.write ('Deleting attached volume %s, try number %d\n' % (vol, try_num))
151 try:
152 conn.delete_volume (vol)
153 break
154 except EC2ResponseError, e:
155 sys.stderr.write ('Could not delete attached volume %s. Error: %s\n' % (vol, e.error_message))
156 if try_num == 1:
157 time.sleep (15)
158
159
160 sys.stdout.write ('Successfully killed instance %s with all attached volumes\n' % instance_id)
161 return True
162
163
164if __name__ == '__main__':
165
166 # Define command line argument parser
167 parser = argparse.ArgumentParser(description='Performs actions on an EC2 instance.')
168 parser.add_argument('action', choices=['start', 'reboot', 'stop', 'kill'])
169 parser.add_argument('--instance', required=True, help='EC2 instance ID to perform the action on')
170 parser.add_argument('--region', default = AWS_REGION, help='AWS region the instance is in. If missing default is used')
171 parser.add_argument('--access_key', default = AWS_ACCESS_KEY, help='AWS API access key. If missing default is used')
172 parser.add_argument('--secret_key', default = AWS_SECRET_KEY, help='AWS API secret key. If missing default is used')
173 parser.add_argument('--force', action='store_true', help='If set, this flag will prevent confirmation for the action')
174
175 args = parser.parse_args ()
176
177 if args.force:
178 perform = True
179 else:
180 perform = confirm_action ('Confirm %s of instance %s in region %s [yes/no]' % \
181 (args.action, args.instance, args.region))
182
183 if perform:
184 conn = ec2_connect (args.access_key, args.secret_key, args.region)
185 if conn == None:
186 sys.exit (1)
187 retval = locals()[args.action+'_instance'](conn, args.instance)
188 else:
189 retval = True
190
191 if retval:
192 sys.exit (0)
193 else:
194 sys.exit (1)