#!/usr/bin/php -q <?php # ------------------------------------------------------------------ # We offer no warantee or guarantee - use this code at your own risk! # All code is Copyright (C) 2011, Applied Trust Engineering, Inc. # ------------------------------------------------------------------ putenv('TZ=America/Denver'); $debug = 0; $options = getopt("S:K:v:a:p:d"); if (!isset($options["S"])) { usage(); } if (!isset($options["K"])) { usage(); } if (!isset($options["v"])) { usage(); } if (!isset($options["a"])) { usage(); } if (!isset($options["p"])) { usage(); } if (isset($options["d"])) { $debug = 1; } define('AWS_KEY', $options["K"]); define('AWS_SECRET_KEY', $options["S"]); error_reporting(-1); require_once '/usr/local/aws-php-sdk/sdk.class.php'; $regions = array ( 'E1' => 'http://monitoring.amazonaws.com/doc/2010-08-01/CloudWatch.wsdl', 'W1' => 'http://monitoring.us-west-1.amazonaws.com/doc/2010-08-01/CloudWatch.wsdl', 'EU' => 'http://monitoring.eu-west-1.amazonaws.com/doc/2010-08-01/CloudWatch.wsdl', 'AP' => 'http://monitoring.ap-southeast-1.amazonaws.com/doc/2010-08-01/CloudWatch.wsdl', ); $quarters = array ( '01' => '1', '02' => '1', '03' => '1', '04' => '2', '05' => '2', '06' => '2', '07' => '3', '08' => '3', '09' => '3', '10' => '4', '11' => '4', '12' => '4', ); # Allow for a comma-separated list of volumes $volumes = preg_split('/,/', $options["v"]); $archive = $options["a"]; $period = $options["p"]; if (($period != "q") && ($period != "m")) { echo "Period option must be either q (quarterly) or m (monthly)."; usage(); } $ec2 = new AmazonEC2(); // Get the response from a call to the DescribeImages operation. $response = $ec2->describe_snapshots(); $errors = 0; $successes=0; $now = time(); $oneday = 86400; $olderthan = $now-($archive*$oneday); log_message("finished fetching list of snapshots, beginning to parse."); log_message("archive duration is $archive days, or older than " . date("m-d-Y H:i", $olderthan)); if ($period == "q") { log_message("period retention is quarterly"); } else { log_message("period retention is monthly"); } $all_snapshots = array(); foreach ( $response->body->snapshotSet->item as $snapshot) { $temparray = array( 'snapshotId' => $snapshot->snapshotId, 'volumeId' => $snapshot->volumeId, 'startTime' => $snapshot->startTime, ); array_push($all_snapshots, $temparray); } #foreach ($all_snapshots as $mysnap) { # echo "snapshotId: " . $mysnap['snapshotId'] . "\n"; # echo "volumeId: " . $mysnap['volumeId'] . "\n"; # echo "startTime: " . $mysnap['startTime'] . "\n\n"; #} #exit; foreach ($volumes as $volid) { log_message("Examining volume $volid..."); $snaplist=array(); foreach ($all_snapshots as $snapshot) { if ($snapshot['volumeId'] == $volid) { $snaplist[strtotime($snapshot['startTime'])] = $snapshot['snapshotId']; } } ksort ($snaplist); $keepers = array(); foreach ($snaplist as $ts => $id) { log_message("examining $id - " . date("m-d-Y H:i", $ts)); # this is crazy black magic to deal with retaining one snapshot per period $month = date("m", $ts); $quarter = $quarters[$month];; log_message("\ttaken in quarter: $quarter"); log_message("\ttaken in month: $month"); # first check if this is the first snapshot in the rentention period (quarter or month) if (($period == "q") && (!isset($keepers[$quarter]))) { log_message("\tkeeping because it's the first in quarter $quarter"); $keepers[$quarter] = $id; continue; } if (($period == "m") && (!isset($keepers[$month]))) { log_message("\tkeeping because it's the first in month $month"); $keepers[$month] = $id; continue; } # finally, keep if > $archive days old if ($ts > $olderthan) { log_message("\tkeeping because it's more recent than the archive duration"); continue; } # if we've gotten this far, we can delete the snapshot if ($debug) { log_message("\tIF THIS WERE NOT DEBUG MODE THIS SNAPSHOT WOULD BE DELETED!"); continue; } $response = $ec2->delete_snapshot($id); if ($response->isOK()) { $successes++; } else if (strcmp($response->body->Errors->Error->Code, 'InvalidSnapshot.InUse')==0) { log_message("\tskipped because it's in use (perhaps for an AMI)"); continue; } else { $errors++; } } } if ($errors) { echo "prune_ebs_snapshots CRITICAL - Error pruning snapshots\n"; exit(2); } else { echo "prune_ebs_snapshots OK - $successes snapshots pruned\n"; exit(0); } ############################################################ function log_message($message) { global $debug; if ($debug) { echo "$message\n"; } } function usage() { echo "usage: prune_ebs_snapshot -K <access_key_id> -S <secret_access_key> -v <volume_id(s)> -a <archive duration> -p <period>\n"; exit(1); }