Created
May 15, 2017 23:43
-
-
Save z-shah/aa74a46231c1135f7378b70c4768eb99 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import boto3 | |
import json | |
import time | |
config = { | |
'tag': 'schedule', | |
'exclude': ['i-071a35b4439f1a581'], | |
'exclude-tag': '', | |
'default': '{"mon": {"start": 7, "stop": 19},"tue": {"start": 7, "stop": 19},"wed": {"start": 7, "stop": 19},"thu": {"start": 7, "stop": 19},"fri": {"start": 7, "stop": 19},"sat": {"start": 7, "stop": 19},"sun": {"start": 15, "stop": 16}}' | |
} | |
sps = ['Launch', 'Terminate', 'HealthCheck', 'ReplaceUnhealthy', 'AZRebalance'] | |
# | |
# Loop EC2 instances and check if a 'schedule' tag has been set. If not, create it using default schedule. Next, evaluate value and start/stop instance if needed. | |
# | |
def lambda_handler(event, context): | |
print "=== Start parsing AWS schedule." | |
ec2 = boto3.client('ec2') | |
asc = boto3.client('autoscaling') | |
response = ec2.describe_instances() | |
# Get current day + hour (using GMT) | |
hh = int(time.strftime("%H", time.localtime())) | |
day = time.strftime("%a", time.localtime()).lower() | |
# Print full date and time to log for records | |
from time import gmtime, strftime | |
fulldatetime = strftime("%a, %d %b %Y %H:%M:%S", gmtime()) | |
print "=== This schedule run is beginning at %s UTC time" % fulldatetime | |
started = [] | |
stopped = [] | |
exclude_list = config['exclude'] | |
# Loop reservations/instances. | |
for r in response['Reservations']: | |
for ins in r['Instances']: | |
if (ins['InstanceId'] not in exclude_list) and (not any('ignore' in t['Key'] for t in ins['Tags'])): | |
try: | |
data = None | |
for tag in ins['Tags']: | |
if tag['Key'] == 'schedule': | |
data = tag['Value'] | |
if tag['Key'] == 'aws:autoscaling:groupName': | |
asg = tag['Value'] | |
if data is None: | |
create_schedule_tag(ins, ec2) | |
data = config['default'] | |
schedule = json.loads(data) | |
try: | |
if hh == schedule[day]['start'] and not ins['State']['Name'] == 'running': | |
print "Starting instance %s" % ins['InstanceId'] | |
started.append(ins['InstanceId']) | |
ec2.start_instances(InstanceIds=[ins['InstanceId']]) | |
except: | |
pass # catch exception if 'start' is not in schedule. | |
try: | |
if hh == schedule[day]['stop'] and ins['State']['Name'] == 'running': | |
if asg is not None: | |
print "Suspending autoscaling process for ASG %s before shutting down the instance." % asg | |
asc.suspend_processes(AutoScalingGroupName=asg, ScalingProcesses=sps) | |
print "Stopping instance %s" % ins['InstanceId'] | |
stopped.append(ins['InstanceId']) | |
ec2.stop_instances(InstanceIds=[ins['InstanceId']]) | |
except: | |
pass # catch exception if 'stop' is not in schedule. | |
asg = None | |
except KeyError as e: | |
create_schedule_tag(ins, ec2) | |
except ValueError as e: | |
# invalid json | |
print 'Invalid value for tag "schedule" on instance "%s", please check!' % (ins['InstanceId']) | |
else: | |
print "Instance %s is successfully ignored." % ins['InstanceId'] | |
# Fix ELB configuration - not working currently | |
''' | |
# TODO: Deregister and register from ELB only if instances are not InService. | |
if len(started) > 0: | |
print "Instances have been started... Checking instances in Elastic Load Balancer." | |
elb = boto3.client('elb') | |
lbd = elb.describe_load_balancers() | |
for e in lbd['LoadBalancerDescriptions']: | |
for inss in e['Instances']: | |
if inss['InstanceId'] in started: | |
print "Deregistering instance %s from ELB %s" % (inss['InstanceId'], e['LoadBalancerName']) | |
elb.deregister_instances_from_load_balancer(LoadBalancerName=e['LoadBalancerName'], | |
Instances=[{'InstanceId': inss['InstanceId']}]) | |
time.sleep(3) | |
print "Registering instance %s with ELB %s" % (inss['InstanceId'], e['LoadBalancerName']) | |
elb.register_instances_with_load_balancer(LoadBalancerName=e['LoadBalancerName'], | |
Instances=[{'InstanceId': inss['InstanceId']}]) | |
''' | |
print "=== Finished parsing AWS schedule." | |
def create_schedule_tag(instance, ec2): | |
if instance['InstanceId'] not in config['exclude']: | |
try: | |
tag_name = config['tag'] | |
tag_value = config['default'] | |
print "About to create tag on instance %s with value: %s" % (instance['InstanceId'], tag_value) | |
ec2.create_tags(Resources=[instance['InstanceId']], Tags=[{'Key': tag_name, 'Value': tag_value}]) | |
except Exception as e: | |
print e | |
else: | |
print "Instance %s is successfully ignored." % instance.id | |
if __name__ == '__main__': | |
lambda_handler('event', 'handler') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment