Lambda-Funktion zur Erstellung eines AMI-Backups (Python)

In Zukunft sind verschiedene Verbesserungen geplant.

Bitte beachten Sie die folgenden Einstellungen usw. http://pict3.hatenablog.com/entry/2015/12/09/104015

#!/usr/bin/python
# -*- coding: utf-8 -*-

import json

import boto3
from boto3.session import Session

import time
from datetime import datetime as dt

import pprint

TAG_KEY_BACKUP_GENERATION = 'Backup-Generation'
TAG_KEY_AUTO_BACKUP       = 'Backup-Type'
TAG_VAL_AUTO_BACKUP       = 'auto'

print('Loading function')

pp = pprint.PrettyPrinter(indent=4)

#Funktionsname: Lambda_handler
def lambda_handler(event, context):
    print("Received event: " + json.dumps(event, indent=2))

    ec2_client   = boto3.client('ec2')
    ec2_resource = boto3.resource('ec2')

    ret = execute_ami_backup_task(ec2_client, ec2_resource)
    print 'AMI buckup task is completed(%s).' % (ret)

    return 0
    raise Exception('Something went wrong')


#Funktionsname: ausführen_ami_backup_task
#Rückgabewert: Ausführungsergebnis
#Argument: ec2_client
#       : ec2_resource
#Funktion: Führen Sie eine AMI-Sicherung durch
def execute_ami_backup_task(ec2_client, ec2_resource):
    response = ec2_client.describe_instances()

    exec_time = dt.now().strftime('%Y%m%d%H%M%S')

    result = True
    for ec2_group in response['Reservations']:
        for instance_info in ec2_group['Instances']:
            ret = is_target(instance_info)
            if (ret == False):
                continue
        
            ret = create_buckup_image(ec2_client, ec2_resource, instance_info, exec_time)
            if not ret:
                print 'create_buckup_image(%s) was failed.' % (instance_info['InstanceId'])
                result = False

                continue

            ret = delete_old_image(ec2_client, ec2_resource, instance_info)
            if not ret:
                print 'delete_old_image(%s) was failed.' % (instance_info['InstanceId'])
                result = False

                continue
    
    return result


#Funktionsname: ist_target
#Rückgabewert: Gibt an, ob eine Sicherung erforderlich ist
#Argument: Instanz_info <dict>
#Funktion: Beurteilen Sie die Notwendigkeit einer Sicherung
def is_target(instance_info):
    val = get_tag_value(
        instance_info, 
        TAG_KEY_BACKUP_GENERATION
    )

    if val is None:
        return False

    return True


#Funktionsname: get_tag_value
#Rückgabewert: Tag-Wert (Keine, wenn der Schlüssel nicht übereinstimmt)
#Argument: Instanz_info <dict>
#       : key <str>
#Funktion: Ruft den Tag-Wert des angegebenen Schlüssels aus den Instanzinformationen ab
def get_tag_value(instance_info, key):
    tags = instance_info['Tags']
    for tag in tags:
        if not (key == tag['Key']):
            continue
        
        return tag['Value']

    return None


#Funktionsname: erstellen_buckup_image
#Rückgabewert: Ausführungsergebnis
#Argument: ec2_client
#       : ec2_resource
#       : instance_info <dict>
#       : exec_time <str>
#Funktion: Erstellen Sie ein Backup-Image
def create_buckup_image(ec2_client, ec2_resource, instance_info, exec_time):
    inst_id = instance_info['InstanceId']
    name    = get_tag_value(instance_info, 'Name')
    if name is None:
        print('Get name error!!')
        
        return False

    image_name = name + '-' + exec_time

    response = ec2_client.create_image(
        InstanceId  = inst_id,
        Name        = image_name,
        Description = image_name,
        NoReboot    = True
    )

    image_id = response['ImageId']
    print '%s was created.' % (image_id)

    #Warten Sie für alle Fälle, bis das zu markierende Bild und der zu markierende Schnappschuss fertig sind
    time.sleep(10)

    tags  = construct_backup_tags(instance_info)
    image = ec2_resource.Image(image_id)

    set_tags_to_image(image, tags)

    set_tags_to_snapshot(ec2_resource, image, tags, image_name)

    return True


#Funktionsname: Konstrukt_backup_tags
#Rückgabewert: Tags-Gruppe
#Argument: Instanz_info <dict>
#Funktion: Konfigurieren Sie eine Gruppe von Tags für die Sicherungseinstellungen
def construct_backup_tags(instance_info):
    ret_tags = []
    tags = instance_info['Tags']
    for tag in tags:
        if (TAG_KEY_BACKUP_GENERATION == tag['Key']):
            continue

        ret_tags.append(tag)

    t = {u'Value': TAG_VAL_AUTO_BACKUP, u'Key': TAG_KEY_AUTO_BACKUP}
    ret_tags.append(t)

    return ret_tags


#Funktionsname: gesetzt_tags_to_image
#Rückgabewert: non
#Argument: Bild
#       : tags <list>
#Funktion: Legen Sie die Tag-Informationen im AMI-Image fest
def set_tags_to_image(image, tags):
    image.create_tags(Tags = tags)

    return


#Funktionsname: gesetzt_tags_to_snapshot
#Rückgabewert: non
#Argument: ec2_resource
#       : image
#       : tags <list>
#       : image_name <str>
#Funktion: Legen Sie die Tag-Informationen im Snapshot fest
def set_tags_to_snapshot(ec2_resource, image, tags, image_name):
    for dev in image.block_device_mappings:
        #Gilt nicht für EBS
        if not dev.has_key('Ebs'):
            continue

        #Einmal gelöscht, um das Namensschild zu ersetzen
        name_idx = get_name_tag_index(tags)
        tags.pop(name_idx)

        #Namensschildeinstellung
        dev_name = dev['DeviceName'][5:]
        name = image_name + '-' + dev_name
        t = {u'Value': name, u'Key': 'Name'}
        tags.append(t)
       
        snapshot_id = dev['Ebs']['SnapshotId']
        snapshot = ec2_resource.Snapshot(snapshot_id)

        snapshot.create_tags(Tags = tags)

    return


#Funktionsname: get_name_tag_index
#Rückgabewert: Indexposition des Namensschilds (Keine, wenn der Schlüssel nicht übereinstimmt)
#Argumente: Tags<list>
#Funktion: Ermittelt die Indexposition des Name-Tags in der Tag-Liste
def get_name_tag_index(tags):
    idx = 0
    for tag in tags:
        if tag['Key'] == 'Name':
            return idx

        idx += 1

    return None


#Funktionsname: löschen_old_image
#Rückgabewert: Ausführungsergebnis
#Argument: ec2_client
#       : ec2_resource
#       : instance_info <dict>
#Funktion: Löscht Bilder, die älter als die Aufbewahrungsgenerierung sind
def delete_old_image(ec2_client, ec2_resource, instance_info):
    sorted_images = get_sorted_images(ec2_client, instance_info)

    generation = int(get_tag_value(instance_info, TAG_KEY_BACKUP_GENERATION))
    cnt = 0
    for img in sorted_images:
        cnt += 1
        if generation >= cnt:
            continue

        image_id  = img['ImageId']
        snapshots = get_snapshots(ec2_resource, image_id)

        #Geben Sie das AMI-Image frei
        ec2_client.deregister_image(
            ImageId = image_id
        )
        print '%s was deregistered.' % (image_id)

        #Warten Sie, bis die Freigabe abgeschlossen ist
        time.sleep(10)

        #Löschen Sie den entsprechenden Schnappschuss
        for snapshot in snapshots:
            snapshot.delete()
            print '%s was deleted.' % (snapshot)

    return True


#Funktionsname: get_sorted_images
#Rückgabewert: Sortiertes Bild<list>
#Argument: ec2_client
#       : instance_info <dict>
#Funktion: Ordnen Sie die AMI-Bildliste in der Reihenfolge ihrer Erstellung
def get_sorted_images(ec2_client, instance_info):
    sorted_images = []
    name     = get_tag_value(instance_info, 'Name')
    response = ec2_client.describe_images(
        Owners  = ['self'],
        Filters = [{'Name': 'tag:Name',                   'Values': [name]},
                   {'Name': 'tag:' + TAG_KEY_AUTO_BACKUP, 'Values': [TAG_VAL_AUTO_BACKUP]}]
    )

    images = response['Images']
    sorted_images = sorted(
        images, 
        key = lambda x: x['CreationDate'], 
        reverse = True
    )

    return sorted_images


#Funktionsname: get_snapshots
#Rückgabewert: Snapshot-Gruppe<list>
#Argument: ec2_resource
#       : image_id <str>
#Funktion: Erfasst im AMI-Image enthaltene Schnappschüsse
def get_snapshots(ec2_resource, image_id):
    snapshots = []
    image     = ec2_resource.Image(image_id)

    for dev in image.block_device_mappings:
        if not dev.has_key('Ebs'):
            continue

        snapshot_id = dev['Ebs']['SnapshotId']
        snapshot    = ec2_resource.Snapshot(snapshot_id)
            
        snapshots.append(snapshot)

    return snapshots

Recommended Posts

Lambda-Funktion zur Erstellung eines AMI-Backups (Python)
Wie benutzt man Python Lambda?
[Einführung in die Udemy Python3 + -Anwendung] 58. Lambda
[Lambda] [Python] Von Lambda auf Twitter posten!
Schreiben Sie die AWS Lambda-Funktion in Python
Verwendung der Zip-Funktion von Python
Python-Funktion ①
[Python 3.8 ~] Wie man rekursive Funktionen mit Lambda-Ausdrücken intelligent definiert
[Python] -Funktion
Python-Funktion ②
[Einführung in die Udemy Python3 + -Anwendung] 48. Funktionsdefinition
[Python] Verwendung von __command__, Funktionserklärung
[Einführung in die Udemy Python3 + -Anwendung] 45. Aufzählungsfunktion
[Einführung in die Udemy Python3 + -Anwendung] 41. Eingabefunktion
Funktion zum Speichern von Bildern nach Datum [python3]
[Einführung in die Udemy Python3 + -Anwendung] 44. Bereichsfunktion
Zugriff auf RDS von Lambda (Python)
[Einführung in die Udemy Python3 + -Anwendung] 46. Zip-Funktion
Stellen Sie mit AWS Lambda Python eine Verbindung zu s3 her
[Road to Intermediate Python] Verwenden Sie Lambda-Ausdrücke
UNHEALTHY Workspaces starten Lambda neu, das in Python umgeschrieben wurde
Auf Python 2.7.9 aktualisiert
python3x: Lambda-Funktion
Registrieren Sie Funktionsargumente automatisch in argparse in Python
Python-Aufzählungsfunktion
Python: Ich konnte in Lambda rekursieren
Python> Funktion> Schließen
[Python] Generatorfunktion
Sie können Python mithilfe der Bibliothek in eine AWS Lambda-Funktion verwandeln
Beispiel für eine Slack-Benachrichtigung mit Python Lambda
Exportieren Sie den RDS-Snapshot mit Lambda (Python) nach S3.
[Python] Verwendung von Hash-Funktion und Taple.
[AWS / Lambda] Laden einer externen Python-Bibliothek
Laden Sie Dateien mit Lambda (Python) auf Google Drive hoch.
Python> Funktion> Innere Funktion
Zusammenfassung des Studiums von Python zur Verwendung von AWS Lambda
Python-Funktionsdekorateur
"Backport" zu Python 2
[Einführung in Python] Grundlegende Verwendung von Lambda-Ausdrücken
[Einführung in Python] Wie iteriere ich mit der Bereichsfunktion?
Einführung in Pipe Operator und Funktionszusammensetzung in Python (vorläufig)
Erstellen Sie eine Python-Version der Lambda-Funktion (+ Lambda-Schicht) mit Serverless Framework
[Road to Intermediate Python] Definieren Sie die Funktion __getattr__ in der Klasse
Ich habe versucht, mit AWS Lambda einen AMI zu erhalten
Stellen Sie die Python 3-Funktion mit Serverless Framework unter AWS Lambda bereit
Schreiben Sie mit Lambda (Python, JavaScript) mehrere Datensätze in DynamoDB.
Ich möchte Lambda mit Python auf Mac AWS!
Python Gibt die Funktion an, die ausgeführt werden soll, wenn das Programm endet
Betrachten Sie die Konvertierung von Python rekursiv in nicht rekursiv
Führen Sie die Python-Funktion von Powershell aus (wie Sie Argumente übergeben).
Python: Kann in Lambda wiederholt werden
Betreff: Python Lambda ist nutzlos ^ H ^ H ^ H ^ H ^ H Schwer zu bedienen
Erklärender Text, der mit Python> Funktion> Docstrings> help () / .__ doc__ angezeigt werden soll
[Python] So rufen Sie eine Funktion von c aus Python auf (ctypes edition)
Über Funktionsargumente (Python)
[Python] Machen Sie einen Screenshot
So installieren Sie Python
Funktionsausführungszeit (Python)
Änderungen von Python 3.0 zu Python 3.5
Änderungen von Python 2 zu Python 3.0