-
-
Save Ashex/5630adf45f4e56916ed5ebe1855d88ea to your computer and use it in GitHub Desktop.
This file contains hidden or 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 json | |
from botocore.exceptions import ClientError | |
import boto3 | |
import sys | |
import logging | |
logger = logging.getLogger() | |
logger.setLevel(logging.INFO) | |
from zabbix.api import ZabbixAPI | |
## to install virtualenv | |
## pip install py-zabbix boto3 -t . | |
## to update this lambda use | |
## rm proj.zip ; zip -r proj.zip * && aws lambda update-function-code --function-name aws-deregister --zip-file fileb://proj.zip --region us-east-1 ; rm proj.zip | |
### Use for debug | |
# | |
#tes={u'event': [{u'Records': [{u'Sns': {u'Message': {u'EC2InstanceId': u'i-af391367', u'Service': u'AWS Auto Scaling', u'AutoScalingGroupName': u'exampleAutoScalingGroup', u'LifecycleActionToken': u'eaac0cdf-df85-4c8f-a9ed-f0a685066099', u'LifecycleHookName': u'do-some-work', u'RequestId': u'6648ba02-138b-4f56-a0c7-bc74f22c3b51', u'Time': u'2015-01-07T18:37:17.553Z', u'LifecycleTransition': u'autoscaling:EC2_INSTANCE_TERMINATING', u'AccountId': u'356438515751'}}}]}]} | |
#tes={u'Records': [{u'EventVersion': u'1.0', u'EventSubscriptionArn': u'arn:aws:sns:sa-east-1:444914307613:zabbix-terminate-sa-east-1:c29c67d2-d070-4353-9093-266e49338720', u'EventSource': u'aws:sns', u'Sns': {u'SignatureVersion': u'1', u'Timestamp': u'2016-04-04T03:32:25.787Z', u'Signature': u'TeAaHghsAkPUuxyE6gIAad7PzV2CH2n2YT4q7UEtypqjVF0TEmGPAwX0q80Dm2XLT5fHlHjnngR9zm+kaTu5T137eNwxt+6xJuU4/yOao8VrV3AJ/4o/oLhK5G8h+mLqOYuGpqWTGYuslKmNEmc5i9RNDau0tP03hXNRAm5b+33wTtLuQ8gOQ/mrf6fwsmhGJO05LUEBnLFI6+TVs6u+X4l3qr4nxuy1kS5DuXfrb9FYkKAXT9RELMOCYLbPhFinJfaGkwfa7evGuxUNAStCR2gbiBKEQ3Q12hrOsh5x3QfMufiJNIBuFQi6Za3hrWW5tYBrh0tObxm9Qa6nfgcWpA==', u'SigningCertUrl': u'https://sns.sa-east-1.amazonaws.com/SimpleNotificationService-bb750dd426d95ee9390147a5624348ee.pem', u'MessageId': u'e6edf556-18ff-58e6-b457-ba2dfa7615fc', u'Message': u'{"StatusCode":"InProgress","Service":"AWS Auto Scaling","AutoScalingGroupName":"ASG-nginx-images-prod-20160316","Description":"Terminating EC2 instance: i-cfb63f1e","ActivityId":"67a0a507-0e45-4c9d-9fc5-dba95087fb70","Event":"autoscaling:EC2_INSTANCE_TERMINATE","Details":{"InvokingAlarms":[{"Region":"SA-East-1","AWSAccountId":"444914307613","OldStateValue":"OK","AlarmName":"awsec2-ASG-nginx-images-prod-20160316-High-CPU-Utilization","AlarmDescription":null,"NewStateReason":"Threshold Crossed: 1 datapoint (49.994) was less than or equal to the threshold (50.0).","StateChangeTime":1459740644889,"NewStateValue":"ALARM","Trigger":{"Period":300,"Statistic":"AVERAGE","MetricName":"CPUUtilization","Threshold":50,"EvaluationPeriods":1,"Dimensions":[{"name":"AutoScalingGroupName","value":"ASG-nginx-images-prod-20160316"}],"Namespace":"AWS/EC2","ComparisonOperator":"LessThanOrEqualToThreshold","Unit":null}}],"Availability Zone":"sa-east-1c","Subnet ID":"subnet-efcd90a9"},"AutoScalingGroupARN":"arn:aws:autoscaling:sa-east-1:444914307613:autoScalingGroup:3d4a78e3-518f-4116-a408-c7f0f55ab9a9:autoScalingGroupName/ASG-nginx-images-prod-20160316","Progress":50,"Time":"2016-04-04T03:32:25.735Z","AccountId":"444914307613","RequestId":"67a0a507-0e45-4c9d-9fc5-dba95087fb70","StatusMessage":"","EndTime":"2016-04-04T03:32:25.735Z","EC2InstanceId":"i-cfb63f1e","StartTime":"2016-04-04T03:31:02.157Z","Cause":"At 2016-04-04T03:30:44Z a monitor alarm awsec2-ASG-nginx-images-prod-20160316-High-CPU-Utilization in state ALARM triggered policy Decrease Group Size changing the desired capacity from 5 to 4. At 2016-04-04T03:31:02Z an instance was taken out of service in response to a difference between desired and actual capacity, shrinking the capacity from 5 to 4. At 2016-04-04T03:31:02Z instance i-cfb63f1e was selected for termination."}', u'MessageAttributes': {}, u'Type': u'Notification', u'UnsubscribeUrl': u'https://sns.sa-east-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:sa-east-1:444914307613:zabbix-terminate-sa-east-1:c29c67d2-d070-4353-9093-266e49338720', u'TopicArn': u'arn:aws:sns:sa-east-1:444914307613:zabbix-terminate-sa-east-1', u'Subject': u'Auto Scaling: termination for group "ASG-nginx-images-prod-20160316"'}}]} | |
#lambda_handler(test, None) | |
## | |
class AwsEc2DeregisterZabbix(): | |
INSTANCE_TERMINATING = 'autoscaling:EC2_INSTANCE_TERMINATING' | |
INSTANCE_TERMINATE = 'autoscaling:EC2_INSTANCE_TERMINATE' | |
def __init__(self, ec2_instance_id): | |
self.ec2_instance_id = ec2_instance_id | |
self.host = None | |
self.aws_hostname = None | |
self.regions = ['us-east-1', 'sa-east-1'] | |
def zabbix_disable_host(self): | |
self.zabbix = ZabbixAPI(url='https://myzabbix.com', | |
user='myuser', password='mypassword') | |
ec2_internal_ip = self.ec2_get_ip() | |
# disable host from ec2 ip | |
if ec2_internal_ip: | |
hosts = self.zabbix.hostinterface.get(filter={'ip': ec2_internal_ip}) | |
# or disable host from zabbix hostname | |
else: | |
hosts = self.zabbix.host.get(search={"name": ["*{}".format(self.ec2_instance_id.replace('i-',''))]}, | |
searchWildcardsEnabled=True) | |
for host in hosts: | |
update_host = {'hostid': host['hostid'], 'status': 1} | |
self.zabbix.host.update(update_host) | |
logger.info('Disabling host {} ({}) Zabbix'.format(self.ec2_instance_id, ec2_internal_ip)) | |
return True | |
else: | |
logger.info('Host {} ({}) not found in Zabbix'.format(self.ec2_instance_id, ec2_internal_ip)) | |
return False | |
def ec2_get_ip(self): | |
for region in self.regions: | |
ec2 = boto3.client('ec2', region_name=region) | |
instance = ec2.describe_instances(Filters=[{'Name': 'instance-id', 'Values': [self.ec2_instance_id]}]) | |
logger.info('Found instance {}) '.format(instance)) | |
if instance['Reservations']: | |
response = instance['Reservations'][0]['Instances'][0] | |
# ip not found on aws | |
if 'PrivateIpAddress' in response: | |
return response['PrivateIpAddress'] | |
return None | |
def autoscaling_abandon(self, asg_name, asg_lifecycle_action_token, asg_hook_name): | |
for region in self.regions: | |
try: | |
boto3.client('autoscaling', region_name=region).complete_lifecycle_action( | |
AutoScalingGroupName=asg_name, | |
LifecycleActionToken=asg_lifecycle_action_token, | |
LifecycleActionResult='ABANDON', | |
LifecycleHookName=asg_hook_name, | |
) | |
except ClientError as e: | |
if e.message.__contains__("No active Lifecycle Action"): | |
pass | |
else: | |
raise e | |
def lambda_handler(event, context): | |
logger.info("Proccessing message {message}.".format(message=event)) | |
msg = json.loads(event['Records'][0]['Sns']['Message']) | |
if ('LifecycleTransition' in msg and \ | |
msg['LifecycleTransition'] \ | |
== AwsEc2DeregisterZabbix.INSTANCE_TERMINATING) \ | |
or ('Event' in msg and | |
msg['Event'] == AwsEc2DeregisterZabbix.INSTANCE_TERMINATE | |
): | |
aws_zabbix = AwsEc2DeregisterZabbix(ec2_instance_id=msg['EC2InstanceId']) | |
try: | |
aws_zabbix.zabbix_disable_host() | |
except Exception as e: | |
logger.exception(e) | |
finally: | |
asg_name = msg['AutoScalingGroupName'] | |
if 'LifecycleActionToken' in msg: | |
asg_lifecycle_action_token = msg['LifecycleActionToken'] | |
asg_hook_name = msg['LifecycleHookName'] | |
aws_zabbix.autoscaling_abandon(asg_name, asg_lifecycle_action_token, asg_hook_name) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment