pythonでEC2のリソースチェックする(AWS APIを利用) on CentOS
前提
- aws cliをインストール(Installing the AWS CLI)して、aws configureは設定しておく。
- aws configureしておく。(What Is the AWS Command Line Interface?)
- vagrantを使ってのインストールは前回の(ココ)を参照
やること
1. boto3のインストール
# インストール $ pip install boto3 # バージョン確認 $ pip freeze | grep boto3 boto3==1.14.12
すべてのインスタンスの起動、停止
ec2_status.py
#!/usr/bin/env python3
import sys
import logging
import boto3
import botocore
from ec2.check import EC2_Instance_Check
# ログレベル設定
logging.basicConfig(level=logging.INFO)
'''
# ログ群
logging.critical('critical')
logging.error('error')
logging.warning('warning')
logging.info('info')
logging.debug('debug')
'''
class RDS_Instance_Check:
rds = None
def __init__(self):
self.rds = boto3.client('rds')
def get_tags_for_db(self, db):
try:
logging.debug("get_tags_for_db start")
instance_arn = db['DBInstanceArn']
instance_tags = self.rds.list_tags_for_resource(ResourceName=instance_arn)
return instance_tags['TagList']
except:
raise
def start_db_instances(self, target_tag):
try:
dbs = self.rds.describe_db_instances()
except Exception as e:
print(e)
return { 'status': 2 }
for db in dbs['DBInstances']:
db_tags = get_tags_for_db(db)
tag = next(iter(filter(lambda tag: tag['Key'] == target_tag and tag['Value'] == 'True', db_tags)), None)
if tag and db['DBInstanceStatus'] == 'stopped':
response = rds.start_db_instance(DBInstanceIdentifier=db["DBInstanceIdentifier"])
print(db['DBInstanceIdentifier'])
raise
def lambda_start_handler(self, event, context):
target_tag = "AutoStart"
start_db_instances(target_tag)
return { 'status': 0 }
def stop_db_instances(self, target_tag):
"""
stop instances
"""
try:
dbs = rds.describe_db_instances()
except Exception as e:
print(e)
return { 'status': 2 }
for db in dbs['DBInstances']:
db_tags = get_tags_for_db(db)
tag = next(iter(filter(lambda tag: tag['Key'] == target_tag and tag['Value'] == 'True', db_tags)), None)
if tag and db['DBInstanceStatus'] == 'available':
response = rds.stop_db_instance(DBInstanceIdentifier=db["DBInstanceIdentifier"])
print(db['DBInstanceIdentifier'])
def lambda_stop_handler(self, event, context):
target_tag = "AutoStop"
stop_db_instances(target_tag)
return { 'status': 0 }
if __name__ == '__main__':
args = sys.argv
# print (boto3.Session().get_credentials().access_key)
# print boto3.Session().get_credentials().secret_key
inscheck = EC2_Instance_Check()
# 停止しているInstanceをすべて起動する
# inscheck.start_first_instances(inscheck.ListInstances)
# inscheck.start_all_instances()
# 指定するIDのインスタンスをすべて停止する
# inscheck.stop_instances(inscheck.ListInstances, inscheck.CODE_STOPPING)
# 起動しているInstanceをすべてTerminateする
inscheck.stop_all_instances(inscheck.CODE_TERMINATED)
check.py
#!/usr/bin/env python3
import sys
import logging
import boto3
import botocore
import time
# ログレベル設定
logging.basicConfig(level=logging.DEBUG)
'''
# ログ群
logging.critical('critical')
logging.error('error')
logging.warning('warning')
logging.info('info')
logging.debug('debug')
'''
class EC2_Instance_Check:
CODE_PENDING = 0
CODE_RUNNING = 16
CODE_SHUTTING_DOWN = 32
CODE_TERMINATED = 48
CODE_STOPPING = 64
CODE_STOPED = 80
FIRST_FTP_SRV_ID = 'i-0c4b0ba37630791a0'
FIRST_STORAGE_SRV_ID = FIRST_FTP_SRV_ID
FIRST_BASTION_SRV_ID = FIRST_FTP_SRV_ID
ListInstances=[
FIRST_FTP_SRV_ID
,FIRST_STORAGE_SRV_ID
,FIRST_BASTION_SRV_ID
]
RETRY_VALUE = 3
WAIT_TIME = 2
def start_first_instances(self, instanceList):
try:
logging.debug("start_first_instances start")
ec2 = boto3.client('ec2')
for instance_id in instanceList:
# Instance起動
response = ec2.start_instances(InstanceIds=[instance_id])
logging.info(" ==> instance start:%s", response)
# リスト順に1インスタンスずつ完全起動を繰り返す。
# 10回はリトライする
for i in range(self.RETRY_VALUE):
time.sleep(self.WAIT_TIME)
instance_statuses = ec2.describe_instance_status(InstanceIds=[instance_id])
if instance_statuses['InstanceStatuses'][0]['InstanceState']['Code'] == self.CODE_RUNNING:
logging.info(" ==> instance launched")
break;
except botocore.exceptions.ClientError as e:
code = e.response['Error']['Code']
status_code = e.response['ResponseMetadata']['HTTPStatusCode']
message = e.response['Error']['Message']
if e.response['ResponseMetadata']['HTTPStatusCode'] == 400:
logging.error("%s, %s", code, message)
else:
# まだ未発見のエラー
logging.error("%s, %s, %s",status_code, code, message)
raise Exception(e)
except Exception as e:
# まだ未発見のエラー
logging.error("!! Undiscovered Error !!")
raise Exception(e)
def start_all_instances(self):
try:
logging.debug("=== start_all_instances start")
# ec2 = boto3.client('ec2').describe_instances()
ec2 = boto3.client('ec2')
res = ec2.describe_instances(Filters=[{'Name': 'instance-state-name', 'Values':['stopping','stopped']}]);
if 0 == len(res['Reservations']):
logging.info("Nothing instance")
return False
instances = res['Reservations'][0]['Instances']
for instance in instances:
state = instance.get('State')
keyname = instance.get('KeyName')
logging.debug(" ==> KeyName:%s, Status: %s", keyname, state)
code = state.get('Code')
if code == self.CODE_STOPED:
instance_id = instance.get('InstanceId')
# Instance起動
ec2.start_instances(InstanceIds=[instance_id])
logging.info(" ==> instance start:%s", instance_id)
logging.info("=== start_all_instances Success")
return True
except botocore.exceptions.ClientError as e:
code = e.response['Error']['Code']
status_code = e.response['ResponseMetadata']['HTTPStatusCode']
message = e.response['Error']['Message']
if e.response['ResponseMetadata']['HTTPStatusCode'] == 400:
logging.error("%s, %s", code, message)
else:
# まだ未発見のエラー
logging.error("%s, %s, %s",status_code, code, message)
raise Exception(e)
except Exception as e:
# まだ未発見のエラー
logging.error("!! Undiscovered Error !!")
raise Exception(e)
def stop_instances(self, instanceList, destStatus):
try:
logging.info("start_stop_instances start")
ec2 = boto3.client('ec2')
for instanceId in instanceList:
# Instance停止
try:
# boto3 new method 使えない。。。response = ec2.instances.filter(InstanceIds=instanceId).stop()
response = ec2.stop_instances(InstanceIds=[instanceId])
logging.info(" ==> response:%s", response)
# リスト順に1インスタンスずつ完全停止を繰り返す。
# 10回はリトライする
for i in range(self.RETRY_VALUE):
time.sleep(self.WAIT_TIME)
# boto3 new method 使えない。。status = ec2.meta.client.describe_instance_status(InstanceIds=[instanceId])
status = ec2.describe_instance_status(InstanceIds=[instanceId])
if len(status['InstanceStatuses']) != 0:
code = status['InstanceStatuses'][0]['InstanceState']['Code']
name = status['InstanceStatuses'][0]['InstanceState']['Name']
if code == self.CODE_STOPPING or code == self.CODE_STOPED :
logging.info(" ==> instance stopped: %s", code)
break
else:
code = status['ResponseMetadata']['HTTPStatusCode']
if code == 200:
logging.info(" ==> instance stopping: %s", code)
break
logging.info("not enough %s, %s, %s, %s", i, instanceId, name)
except Exception as e:
logging.info('instance:%s is no existed', instanceId)
continue
except botocore.exceptions.ClientError as e:
code = e.response['Error']['Code']
status_code = e.response['ResponseMetadata']['HTTPStatusCode']
message = e.response['Error']['Message']
if e.response['ResponseMetadata']['HTTPStatusCode'] == 400:
logging.error("%s, %s", code, message)
else:
# まだ未発見のエラー
logging.error("%s, %s, %s",status_code, code, message)
raise Exception(e)
except Exception as e:
# まだ未発見のエラーがあるかも
raise Exception(e)
def stop_all_instances(self, destStatus):
try:
logging.debug("=== stop_all_instances start")
# ec2 = boto3.client('ec2').describe_instances()
ec2 = boto3.client('ec2')
res = ec2.describe_instances(Filters=[{'Name': 'instance-state-name', 'Values':['pending','running','stopping','stopped']}]);
if 0 == len(res['Reservations']):
logging.info("Nothing instance")
return False
instances = res['Reservations'][0]['Instances']
for instance in instances:
state = instance.get('State')
keyname = instance.get('KeyName')
logging.debug(" ==> KeyName:%s, Status: %s", keyname, state)
code = state.get('Code')
instance_id = instance.get('InstanceId')
if destStatus == self.CODE_TERMINATED:
ec2.terminate_instances(InstanceIds=[instance_id])
logging.info("=== terminate_all_instances Success")
else:
ec2.stop_instances(InstanceIds=[instance_id])
logging.info("=== stop_all_instances Success")
return True
except botocore.exceptions.ClientError as e:
code = e.response['Error']['Code']
status_code = e.response['ResponseMetadata']['HTTPStatusCode']
message = e.response['Error']['Message']
if e.response['ResponseMetadata']['HTTPStatusCode'] == 400:
logging.error("%s, %s", code, message)
else:
# まだ未発見のエラー
logging.error("%s, %s, %s",status_code, code, message)
raise Exception(e)
except Exception as e:
# まだ未発見のエラー
logging.error("!! Undiscovered Error !!")
raise Exception(e)
RDSの起動、停止
#!/usr/bin/env python3
import sys
import logging
import boto3
import botocore
import ec2.EC2_Instance_Check as EC2_Instance_Check
# ログレベル設定
logging.basicConfig(level=logging.DEBUG)
'''
# ログ群
logging.critical('critical')
logging.error('error')
logging.warning('warning')
logging.info('info')
logging.debug('debug')
'''
class RDS_Instance_Check:
rds = None
def __init__(self):
self.rds = boto3.client('rds')
def get_tags_for_db(self, db):
try:
logging.debug("get_tags_for_db start")
instance_arn = db['DBInstanceArn']
instance_tags = self.rds.list_tags_for_resource(ResourceName=instance_arn)
return instance_tags['TagList']
except:
raise
def start_db_instances(self, target_tag):
try:
dbs = self.rds.describe_db_instances()
except Exception as e:
print(e)
return { 'status': 2 }
for db in dbs['DBInstances']:
db_tags = get_tags_for_db(db)
tag = next(iter(filter(lambda tag: tag['Key'] == target_tag and tag['Value'] == 'True', db_tags)), None)
if tag and db['DBInstanceStatus'] == 'stopped':
response = rds.start_db_instance(DBInstanceIdentifier=db["DBInstanceIdentifier"])
print(db['DBInstanceIdentifier'])
raise
def lambda_start_handler(self, event, context):
target_tag = "AutoStart"
start_db_instances(target_tag)
return { 'status': 0 }
def stop_db_instances(self, target_tag):
"""
stop instances
"""
try:
dbs = rds.describe_db_instances()
except Exception as e:
print(e)
return { 'status': 2 }
for db in dbs['DBInstances']:
db_tags = get_tags_for_db(db)
tag = next(iter(filter(lambda tag: tag['Key'] == target_tag and tag['Value'] == 'True', db_tags)), None)
if tag and db['DBInstanceStatus'] == 'available':
response = rds.stop_db_instance(DBInstanceIdentifier=db["DBInstanceIdentifier"])
print(db['DBInstanceIdentifier'])
def lambda_stop_handler(self, event, context):
target_tag = "AutoStop"
stop_db_instances(target_tag)
return { 'status': 0 }
if __name__ == '__main__':
args = sys.argv
# print (boto3.Session().get_credentials().access_key)
# print boto3.Session().get_credentials().secret_key
inscheck = EC2_Instance_Check()
# 停止しているInstanceをすべて起動させる
inscheck.start_first_instances()
inscheck.start_all_instances()
# 起動しているInstanceをすべて停止させる
inscheck.stop_all_instances(inscheck.CODE_TERMINATED)
参考:
コメント
コメントを投稿