1414__author__ = 'dougalb'
1515
1616from datetime import datetime
17- import boto .ec2
18- import dateutil .parser
1917import urllib2
20- import ConfigParser
21- import boto .ec2 .autoscale
2218import os
2319import time
2420import sys
2521import tempfile
2622import logging
23+ import boto3
24+ import ConfigParser
25+ from botocore .config import Config
2726
2827log = logging .getLogger (__name__ )
2928
@@ -37,12 +36,20 @@ def getConfig(instance_id):
3736 logging .getLogger ().setLevel (lvl )
3837 _region = config .get ('nodewatcher' , 'region' )
3938 _scheduler = config .get ('nodewatcher' , 'scheduler' )
39+ _proxy = config .get ('nodewatcher' , 'proxy' )
40+ proxy_config = Config ()
41+
42+ if not _proxy == "NONE" :
43+ proxy_config = Config (proxies = {'https' : _proxy })
44+
4045 try :
4146 _asg = config .get ('nodewatcher' , 'asg' )
4247 except ConfigParser .NoOptionError :
43- conn = boto .ec2 .connect_to_region (_region ,proxy = boto .config .get ('Boto' , 'proxy' ),
44- proxy_port = boto .config .get ('Boto' , 'proxy_port' ))
45- _asg = conn .get_all_instances (instance_ids = instance_id )[0 ].instances [0 ].tags ['aws:autoscaling:groupName' ]
48+ ec2 = boto3 .resource ('ec2' , region_name = _region , config = proxy_config )
49+
50+ instances = ec2 .instances .filter (InstanceIds = [instance_id ])
51+ instance = next (iter (instances or []), None )
52+ _asg = filter (lambda tag : tag .get ('Key' ) == 'aws:autoscaling:groupName' , instance .tags )[0 ].get ('Value' )
4653 log .debug ("discovered asg: %s" % _asg )
4754 config .set ('nodewatcher' , 'asg' , _asg )
4855
@@ -53,13 +60,13 @@ def getConfig(instance_id):
5360
5461 os .rename (tup [1 ], 'nodewatcher.cfg' )
5562
56- log .debug ("region=%s asg=%s scheduler=%s" % (_region , _asg , _scheduler ))
57- return _region , _asg , _scheduler
63+ log .debug ("region=%s asg=%s scheduler=%s prox_config=%s " % (_region , _asg , _scheduler , proxy_config ))
64+ return _region , _asg , _scheduler , proxy_config
5865
59- def getHourPercentile (instance_id , conn ):
60- _reservations = conn . get_all_instances ( instance_ids = [instance_id ])
61- _instance = _reservations [ 0 ]. instances [ 0 ]
62- _launch_time = dateutil . parser . parse ( _instance . launch_time ) .replace (tzinfo = None )
66+ def getHourPercentile (instance_id , ec2 ):
67+ instances = ec2 . instances . filter ( InstanceIds = [instance_id ])
68+ instance = next ( iter ( instances or []), None )
69+ _launch_time = instance . launch_time .replace (tzinfo = None )
6370 _current_time = datetime .utcnow ()
6471 _delta = _current_time - _launch_time
6572 _delta_in_hours = _delta .seconds / 3600.0
@@ -121,20 +128,17 @@ def lockHost(s,hostname,unlock=False):
121128
122129 return _r
123130
124- def selfTerminate (region , asg , instance_id ):
125- _as_conn = boto .ec2 .autoscale .connect_to_region (region ,proxy = boto .config .get ('Boto' , 'proxy' ),
126- proxy_port = boto .config .get ('Boto' , 'proxy_port' ))
127- if not maintainSize (region , asg ):
131+ def selfTerminate (asg_name , asg_conn , instance_id ):
132+ if not maintainSize (asg_name , asg_conn ):
128133 log .info ("terminating %s" % instance_id )
129- _as_conn .terminate_instance (instance_id , decrement_capacity = True )
130-
131- def maintainSize (region , asg ):
132- _as_conn = boto .ec2 .autoscale .connect_to_region (region ,proxy = boto .config .get ('Boto' , 'proxy' ),
133- proxy_port = boto .config .get ('Boto' , 'proxy_port' ))
134- _asg = _as_conn .get_all_groups (names = [asg ])[0 ]
135- _capacity = _asg .desired_capacity
136- _min_size = _asg .min_size
137- log .debug ("capacity=%d min_size=%d" % (_capacity , _min_size ))
134+ asg_conn .terminate_instance_in_auto_scaling_group (InstanceId = instance_id , ShouldDecrementDesiredCapacity = True )
135+
136+ def maintainSize (asg_name , asg_conn ):
137+ asg = asg_conn .describe_auto_scaling_groups (AutoScalingGroupNames = [asg_name ]) \
138+ .get ('AutoScalingGroups' )[0 ]
139+ _capacity = asg .get ('DesiredCapacity' )
140+ _min_size = asg .get ('MinSize' )
141+ log .info ("capacity=%d min_size=%d" % (_capacity , _min_size ))
138142 if _capacity > _min_size :
139143 log .debug ('capacity greater then min size.' )
140144 return False
@@ -150,24 +154,25 @@ def main():
150154 log .info ("nodewatcher startup" )
151155 instance_id = getInstanceId ()
152156 hostname = getHostname ()
153- region , asg , scheduler = getConfig (instance_id )
157+ region , asg_name , scheduler , proxy_config = getConfig (instance_id )
154158
155159 s = loadSchedulerModule (scheduler )
156160
157161 while True :
158162 time .sleep (60 )
159- conn = boto .ec2 .connect_to_region (region )
160- hour_percentile = getHourPercentile (instance_id ,conn )
163+ ec2_conn = boto3 .resource ('ec2' , region_name = region , config = proxy_config )
164+ asg_conn = boto3 .client ('autoscaling' , region_name = region , config = proxy_config )
165+ hour_percentile = getHourPercentile (instance_id , ec2_conn )
161166 log .info ('Percent of hour used: %d' % hour_percentile )
162167
163168 if hour_percentile < 95 :
164169 continue
165-
170+
166171 jobs = getJobs (s , hostname )
167172 if jobs == True :
168173 log .info ('Instance has active jobs.' )
169174 else :
170- if maintainSize (region , asg ):
175+ if maintainSize (asg_name , asg_conn ):
171176 continue
172177 # avoid race condition by locking and verifying
173178 lockHost (s , hostname )
@@ -177,7 +182,7 @@ def main():
177182 lockHost (s , hostname , unlock = True )
178183 continue
179184 else :
180- selfTerminate (region , asg , instance_id )
185+ selfTerminate (asg_name , asg_conn , instance_id )
181186
182187if __name__ == "__main__" :
183188 main ()
0 commit comments