/** * Prunes Snapshots for the Given Volume * * @param string $volumeId * @param boolean $dryRun (Optional) Indicates if we should perform a dry run * @throws InvalidArgumentException if the volume id is not valid or $weeks is not numeric * @return App_Service_Amazon_Ec2_EbsSnapshotPruneResult */ public function prune($volumeId, $dryRun = false) { if (!$this->_volumeExists($volumeId)) { throw new InvalidArgumentException('The provided "' . $volumeId . '" volume does not exist'); } // Storage mechanism for to-be saved snapshots $save = array('month-first-day' => array(), 'sundays' => array(), 'past-week' => array(), 'only' => array()); $delete = array(); $savedAtLeastOne = false; foreach ($this->_ebs->describeSnapshot() as $s) { if (strcasecmp($s['volumeId'], $volumeId) !== 0) { continue; } $obj = new App_Service_Amazon_Ec2_EbsSnapshot($s); if ($obj->monthsElapsed() >= 1 && $obj->isFirstDayOfTheMonth() && !isset($save['month-first-day'][$obj->monthsElapsed()])) { $save['month-first-day'][$obj->monthsElapsed()] = $obj; $savedAtLeastOne = true; } else { if ($obj->weeksElapsed() > 0 && $obj->weeksElapsed() < 4 && $obj->isSunday() && !isset($save['sundays'][$obj->weeksElapsed()])) { $save['sundays'][$obj->weeksElapsed()] = $obj; $savedAtLeastOne = true; } else { if ($obj->weeksElapsed() == 0) { $save['past-week'][] = $obj; $savedAtLeastOne = true; } else { $delete[] = $obj; } } } } // Make sure we leave at least one backup // @todo: make this a config option if (!$savedAtLeastOne && !empty($delete)) { $newest['time'] = 0; $newest['obj'] = null; $newest['index'] = null; foreach ($delete as $k => $d) { /* @var $d App_Service_Amazon_Ec2_EbsSnapshot */ $data = $d->getData(); if (strtotime($data['startTime']) > $newest['time']) { $newest['obj'] = $d; $newest['index'] = $k; $newest['time'] = strtotime($data['startTime']); } } if (empty($newest['obj'])) { throw new RuntimeException('Sanity check failed. There should be at ' . 'least one backup to be saved'); } unset($delete[$newest['index']]); // rekey delete $delete = array_values($delete); } $result = new App_Service_Amazon_Ec2_EbsSnapshotPruneResult(); $result->setDeleted($delete); $result->setKept($save); if ($dryRun) { $result->setDryRun(true); return $result; } foreach ($delete as $d) { /* @var $d App_Service_Amazon_Ec2_EbsSnapshot */ $data = $d->getData(); if (!array_key_exists('snapshotId', $data)) { continue; } try { $this->_ebs->deleteSnapshot($data['snapshotId']); } catch (Zend_Service_Amazon_Ec2_Exception $e) { if (!strstr($e->getMessage(), 'is currently in use by ami')) { throw $e; } $result->addWarning($e->getMessage()); } } return $result; }
/** * Make sure we get the data as we sent it * @return void */ public function testGetData() { $this->assertEquals($this->_data, $this->_snapshot->getData()); }