PageRenderTime 37ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/ec2-manage-snapshots.php

https://github.com/edasque/ec2-manage-snapshots
PHP | 238 lines | 160 code | 42 blank | 36 comment | 28 complexity | c2fccdc96d3b771be67dfdeef6ba86c8 MD5 | raw file
  1. <?php
  2. /**
  3. * Modified from code by:
  4. * Oren Solomianik’s
  5. * http://orensol.com/2009/02/12/how-to-delete-those-old-ec2-ebs-snapshots/
  6. * New region, snapshots managed as incremental backups and no-op code from:
  7. * @author Erik Dasque
  8. * @version 0.8
  9. * @copyright Erik Dasque, 8 March, 2010
  10. * @package default
  11. * WARNING : USE AT YOU OWN RISK!!! This application will delete snapshots unless you use the --noop option
  12. **/
  13. // Your EC2 credentials
  14. $AWS_ACCESS_KEY_ID = '';
  15. $AWS_SECRET_ACCESS_KEY='';
  16. define ('SYNTAX','Usage: php ec2-manage-snapshots.php -v vol-id [-v vol-id ...] [--noop]\n\n');
  17. // uncomment the next line and comment the one after so the application is always in NO-OP mode (no delete)
  18. //define("NOOP", "1");
  19. define("NOOP", "0");
  20. date_default_timezone_set('UTC');
  21. if ((empty($AWS_ACCESS_KEY_ID) ) && (!(strlen(getenv('AWS_ACCESS_KEY_ID'))==0)))
  22. { $AWS_ACCESS_KEY_ID=getenv('AWS_ACCESS_KEY_ID'); }
  23. if ((empty($AWS_SECRET_ACCESS_KEY) ) && (!(strlen(getenv('AWS_SECRET_ACCESS_KEY'))==0)))
  24. { $AWS_SECRET_ACCESS_KEY=getenv('AWS_SECRET_ACCESS_KEY'); }
  25. // parse options (vol-ids, older-than)
  26. $opts = getopt("v:",array("region:","noop"));
  27. if (($opts['v']) && !is_array($opts['v']))
  28. $volumes = array($opts['v']);
  29. else
  30. $volumes = $opts['v'];
  31. // to Debug getopt
  32. // var_dump($opts);
  33. if (isset($opts['noop'])) $noop=true; else $noop=false;
  34. if ($opts['region'])
  35. {
  36. if (is_array($opts['region']))
  37. die("\n\nRegion cannot have more than one value\n".SYNTAX);
  38. else
  39. $region = $opts['region'];
  40. }
  41. else { echo "No region specified, defaulting to us-east-1\n"; $region = "us-east-1"; }
  42. $ServiceURL = "https://".$region.".ec2.amazonaws.com";
  43. if ((!$volumes))
  44. die("\n\nDid not provide vol-id.\n".SYNTAX);
  45. echo "\n";
  46. foreach ($volumes as $volume)
  47. {
  48. echo "Will try to bulk delete for " . $volume ." in region ".$region."\n";
  49. }
  50. echo "\n";
  51. // include required EC2 library elements
  52. require_once("Amazon/EC2/Client.php");
  53. require_once("Amazon/EC2/Model/DescribeSnapshotsRequest.php");
  54. require_once("Amazon/EC2/Model/DescribeVolumesRequest.php");
  55. require_once("Amazon/EC2/Model/DeleteSnapshotRequest.php");
  56. //$ec2Config = array ('ServiceURL' => 'https://us-east-1.ec2.amazonaws.com');
  57. $ec2Config = array ('ServiceURL' => $ServiceURL);
  58. // instantiate EC2 client
  59. // was:
  60. //$service = new Amazon_EC2_Client(AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY);
  61. // with support for a different zone than US we do the following:
  62. $service = new Amazon_EC2_Client($AWS_ACCESS_KEY_ID, $AWS_SECRET_ACCESS_KEY, $ec2Config);
  63. // Modify for Europe
  64. // $ec2Config = array ('ServiceURL' => 'https://eu-west-1.ec2.amazonaws.com');
  65. // $ec2 = new Amazon_EC2_Client($accessKeyId, $secretAccessKey, $ec2Config);
  66. // for US-East:
  67. // $ec2Config = array ('ServiceURL' => 'https://us-east-1.ec2.amazonaws.com');
  68. // get all volumes
  69. $request_v = new Amazon_EC2_Model_DescribeVolumesRequest();
  70. try { $response_v = $service->describeVolumes($request_v);
  71. } catch (Amazon_EC2_Exception $e) {
  72. echo 'Error: ' .$e->getMessage()."\n";
  73. die ("\nExiting application\n\n");
  74. }
  75. $result_v = $response_v->getDescribeVolumesResult();
  76. $volumes_found = $result_v->getVolume();
  77. if (!is_array($volumes_found) || empty($volumes_found)) die ("No volumes found in region ".$region."\n\n");
  78. $a_match=false;
  79. foreach ($volumes_found as $volume_in_region)
  80. {
  81. foreach ($volumes as $volume_in_request)
  82. {
  83. $a_match = ($volume_in_request==$volume_in_region->getVolumeId());
  84. // echo $volume_in_request." may match (".$a_match.") ".$volume_in_region->getVolumeId()."\n";
  85. }
  86. if ($a_match) break;
  87. }
  88. if (!$a_match) die ("None of these volumes were found in region ".$region."\n\n");
  89. // get all snapshots
  90. $request = new Amazon_EC2_Model_DescribeSnapshotsRequest();
  91. $response = $service->describeSnapshots($request);
  92. $result = $response->getDescribeSnapshotsResult();
  93. $snaps = $result->getSnapshot();
  94. $now = time();
  95. $older_than = $now - 7 * 24 * 60 * 60;
  96. if (is_array($snaps))
  97. {
  98. // first check we have at least 1 newer snapshot for every vol-id we got
  99. // we don't want to delete all snapshots of a vol and be left with no snapshots,
  100. // this guarantees it. so we build a "go_ahead_volumes" array.
  101. foreach ($volumes as $volume)
  102. {
  103. foreach ($snaps as $snap)
  104. {
  105. $snapTimestamp = strtotime($snap->getStartTime());
  106. $snapStatus = $snap->getStatus();
  107. if (($snapTimestamp >= $older_than) && ($snapStatus=="completed"))
  108. {
  109. if ($snap->getVolumeId() == $volume)
  110. {
  111. $go_ahead_volumes[] = $volume;
  112. echo "Ready for deletion of snapshots older than ".date("Y/m/d H:i:s e", $older_than). " for volume[".$volume."] in region ".$region;
  113. echo ",\nfound newer snapshot [" . $snap->getSnapshotId() . "] taken on " . date('m/d/y \a\t H:i:s e',strtotime($snap->getStartTime())) . "\n";
  114. break;
  115. }
  116. }
  117. }
  118. }
  119. if (empty($go_ahead_volumes)) die ("No snapshots found for these volumes in region ".$region."\n\n");
  120. echo "\n";
  121. // now go over all snaps, if encounter a snap for a go_ahead_volume which
  122. // is older than, well, older_than, delete it.
  123. $dodelete = true;
  124. if (NOOP) { $dodelete = false; echo "WARNING: the global NOOP is set in the source code for debbugging purpose so we won't be actually performing deletions\n\n"; }
  125. else if ($noop) { $dodelete = false; echo "WARNING: not actually deleting, you specified --noop\n\n"; }
  126. foreach ($snaps as $snap)
  127. {
  128. $snapTimestamp = strtotime($snap->getStartTime());
  129. if ( (in_array($snap->getVolumeId(), $go_ahead_volumes)) )
  130. {
  131. if (!keepSnapShot($snap->getStartTime())) {
  132. echo "Deleting volume " . $snap->getVolumeId() . " snapshot " . $snap->getSnapshotId() . " created on: " . date('m/d/y \a\t H:i:s e',strtotime($snap->getStartTime())) ."\n";
  133. // and now really delete using EC2 library
  134. $request = new Amazon_EC2_Model_DeleteSnapshotRequest();
  135. $request->setSnapshotId($snap->getSnapshotId());
  136. if ($dodelete) $response = $service->deleteSnapshot($request);
  137. }
  138. }
  139. }
  140. echo "\n\n";
  141. }
  142. else
  143. {
  144. die ("\n\nNo snapshots found, quitting.\n\n");
  145. }
  146. /**
  147. * Define DocBlock
  148. **/
  149. function keepSnapShot($creation_date)
  150. {
  151. $now = time();
  152. $older_than = $now - 7 * 24 * 60 * 60;
  153. $older_than_month = $now - 30 * 24 * 60 * 60;
  154. // echo strtotime($creation_date);
  155. $ts = strtotime($creation_date);
  156. // echo 'Day of month: '.date("d",$ts)."\n";
  157. // echo 'Day of week: '.date("w",$ts)."\n";
  158. echo date('M d, Y',$ts)."\t";
  159. if ($ts>=$older_than) {
  160. echo "Recent backup\tKEEP\n" ;
  161. return(TRUE);
  162. }
  163. if (date("d",$ts)==1) {
  164. echo "1st of month\tKEEP\n" ;
  165. return(TRUE);
  166. }
  167. if ((date("w",$ts)==0) && $ts>$older_than_month) {
  168. echo "Recent Sunday\tKEEP\n" ;
  169. return(TRUE);
  170. }
  171. if ((date("w",$ts)==0) && $ts<=$older_than_month) {
  172. echo "Old Sunday\tDELETE\n" ;
  173. return(FALSE);
  174. }
  175. if ($ts<$older_than) {
  176. echo "Old backup\tDELETE\n" ;
  177. return(FALSE);
  178. }
  179. echo "Unknown condition on ".date('F d, Y',$ts)."\n"; exit(0);
  180. return(FALSE);
  181. }
  182. ?>