pythonでEC2のリソースチェックする(AWS APIを利用) on CentOS

前提
やること 1. boto3のインストール

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)

参考:

コメント

このブログの人気の投稿

ソリューション構成ごとにconfigファイルを作成する

C++の古いプロジェクトのビルドでerror MIDL2311 : statements outside library block are illegal in mktyplib compatability mode

web.config debug/releaseの内容を変換構文を使って切り替える