From fcd2b354b22efb3099b021c4c25ad81f819da847 Mon Sep 17 00:00:00 2001 From: Hagai Kariti Date: Tue, 30 Sep 2014 14:14:43 +0300 Subject: [PATCH] Add to the ec2_snapshot module the ability to create a snapshot only if one hasn't recently been created - Added snapshot_max_age parameter - Updated docs - Made the default value of wait to be false, as it used to be --- .../modules/cloud/amazon/ec2_snapshot.py | 56 +++++++++++++++++-- 1 file changed, 50 insertions(+), 6 deletions(-) diff --git a/lib/ansible/modules/cloud/amazon/ec2_snapshot.py b/lib/ansible/modules/cloud/amazon/ec2_snapshot.py index 41dc4bdb21a..d2847aa937f 100644 --- a/lib/ansible/modules/cloud/amazon/ec2_snapshot.py +++ b/lib/ansible/modules/cloud/amazon/ec2_snapshot.py @@ -74,6 +74,12 @@ options: - snapshot id to remove required: false version_added: "1.9" + snapshot_max_age: + description: + - If the volume's most recent snapshot has started less than `snapshot_max_age' minutes ago, a new snapshot will not be created. + required: false + default: 0 + version_added: "1.9" author: "Will Thames (@willthames)" extends_documentation_fragment: aws @@ -104,6 +110,12 @@ EXAMPLES = ''' module: ec2_snapshot snapshot_id: snap-abcd1234 state: absent + +# Create a snapshot only if the most recent one is older than 1 hour +- local_action: + module: ec2_snapshot + volume_id: vol-abcdef12 + snapshot_max_age: 60 ''' import time @@ -124,8 +136,9 @@ def main(): instance_id = dict(), snapshot_id = dict(), device_name = dict(), - wait = dict(type='bool', default='true'), - wait_timeout = dict(default=0), + wait = dict(type='bool', default='false'), + wait_timeout = dict(type='int', default=0), + snapshot_max_age = dict(type='int', default=0), snapshot_tags = dict(type='dict', default=dict()), state = dict(choices=['absent','present'], default='present'), ) @@ -142,9 +155,13 @@ def main(): device_name = module.params.get('device_name') wait = module.params.get('wait') wait_timeout = module.params.get('wait_timeout') + snapshot_max_age = module.params.get('snapshot_max_age') snapshot_tags = module.params.get('snapshot_tags') state = module.params.get('state') + snapshot = None + changed = False + if not volume_id and not instance_id and not snapshot_id or volume_id and instance_id and snapshot_id: module.fail_json(msg='One and only one of volume_id or instance_id or snapshot_id must be specified') if instance_id and not device_name or device_name and not instance_id: @@ -175,10 +192,37 @@ def main(): else: module.fail_json(msg = "%s: %s" % (e.error_code, e.error_message)) + if snapshot_max_age > 0: + try: + snapshot_max_age = snapshot_max_age * 60 # Convert to seconds + current_snapshots = ec2.get_all_snapshots(filters={'volume_id': volume_id}) + # Find the most recent snapshot + recent = dict(start_time=0, snapshot=None) + for s in current_snapshots: + start_time = time.mktime(time.strptime(s.start_time, '%Y-%m-%dT%H:%M:%S.000Z')) + if start_time > recent['start_time']: + recent['start_time'] = start_time + recent['snapshot'] = s + + # Adjust snapshot start time to local timezone + tz_adjustment = time.daylight and time.altzone or time.timezone + recent['start_time'] -= tz_adjustment + + # See if the snapshot is younger that the given max age + current_time = time.mktime(time.localtime()) + snapshot_age = current_time - recent['start_time'] + if snapshot_age < snapshot_max_age: + snapshot = recent['snapshot'] + except boto.exception.BotoServerError, e: + module.fail_json(msg="%s: %s" % (e.error_code, e.error_message)) + try: - snapshot = ec2.create_snapshot(volume_id, description=description) - time_waited = 0 + # Create a new snapshot if we didn't find an existing one to use + if snapshot is None: + snapshot = ec2.create_snapshot(volume_id, description=description) + changed = True if wait: + time_waited = 0 snapshot.update() while snapshot.status != 'completed': time.sleep(3) @@ -189,9 +233,9 @@ def main(): for k, v in snapshot_tags.items(): snapshot.add_tag(k, v) except boto.exception.BotoServerError, e: - module.fail_json(msg = "%s: %s" % (e.error_code, e.error_message)) + module.fail_json(msg="%s: %s" % (e.error_code, e.error_message)) - module.exit_json(changed=True, snapshot_id=snapshot.id, volume_id=snapshot.volume_id, + module.exit_json(changed=changed, snapshot_id=snapshot.id, volume_id=snapshot.volume_id, volume_size=snapshot.volume_size, tags=snapshot.tags.copy()) # import module snippets