def test_suspects(self): backup = BackupSuspects(self.conf, self.sess) # Insert a backup suspect expected1 = Backup(self.volume, id='1', status='SAVING', size=1, last_modified=datetime(2000, 01, 01, 1, 1, 1)) self.sess.add(expected1) # Not expected, because the status is AVAIL notexpected_avail = Backup( self.volume, id='2', status='AVAILABLE', size=1, last_modified=datetime(2000, 01, 01, 1, 1, 1)) self.sess.add(notexpected_avail) # Not expected, because the time is within our 10 second window notexpected_new = Backup( self.volume, id='3', status='NEW', size=1, last_modified=datetime(2000, 01, 01, 1, 1, 25)) self.sess.add(notexpected_new) # Query the backup suspects for backups older than 10 seconds ago results = backup.suspects( timedelta(seconds=10), datetime(2000, 01, 01, 1, 1, 30)).all() # Assert the correct backups are in the results self.assertIn(expected1, results) self.assertNotIn(notexpected_avail, results) self.assertNotIn(notexpected_new, results)
def create(self, status, last_modified): volume = Volume(0, 'vtype', status=status, id=str(uuid.uuid4()), node=self.node, account=self.account) backup = Backup(volume, status='AVAILABLE', volume_id=str(uuid.uuid4())) self.db.add_all([volume, backup]) self.db.commit() # Assign the backup as the restore of the volume volume.restore_of = backup.id volume.last_modified = last_modified self.db.commit() return volume
def test_used(self): backup = Backup(self.volume, id='1', status='SAVING', size=1, last_modified=datetime(2000, 01, 01, 1, 1, 1)) def urlopen(request, **kwargs): return MockResponse(dumps({ 'in-use': True, 'uri': 'DELETE /volumes/ed209cdd-1317-41e8-8474-b0c0f6c3369c/' 'backups/a30a6e5b-2a96-489c-bde1-56f9c615ea1f', }), 200) prune = PruneSuspects(self.conf, self.sess) with patch(suspects, 'urlopen', urlopen): with patch(suspects, 'log', MockLog()): prune.locked(backup) self.assertEquals(suspects.log.count, 1)
def create(self, request): """ PUT /v1.0/{account_id}/backups/{id}?volume={volume_id} Create backup """ # extract volume reference try: volume_id = request.params['volume'] except KeyError: raise HTTPPreconditionFailed("Must specify a 'volume' parameter") try: volume = self.account_query(Volume).\ filter_by(id=volume_id).one() except NoResultFound: raise HTTPPreconditionFailed("Cannot create backup for " "non-existent volume '%s'" % volume_id) if volume.status not in ('ACTIVE', 'IMAGING_SCRUB'): raise HTTPPreconditionFailed( "Status of volume '%s' is '%s', not ACTIVE" % (volume.id, volume.status)) backup_count = volume.active_backup_count() if backup_count >= self.app.backups_per_volume: raise HTTPPreconditionFailed( "Volume '%s' already has %s out of %s allowed backups" % (volume_id, backup_count, self.app.backups_per_volume)) params = { 'id': self.id, 'account_id': self.account_id, 'volume': volume, 'status': 'NEW', } backup = Backup(**params) self.db.add(backup) try: self.db.commit() except IntegrityError: self.db.rollback() # optomistic lock count = self.db.query(Backup).filter( and_(Backup.id == self.id, Backup.account_id == self.account_id, Backup.status.in_(['ERROR', 'DELETED' ]))).update(params, synchronize_session=False) if not count: raise HTTPConflict("Backup '%s' already exists" % self.id) # still in uncommited update transaction backup = self.db.query(Backup).get(self.id) try: path = '/volumes/%s/backups/%s' % (backup.volume.name, backup.id) params = { 'account': self.account_id, 'timestamp': int(mktime(backup.created_at.timetuple())), } info = self.node_request(backup.volume.node, 'PUT', path, **params) except NodeError: # Remove the backup record if the node failed to create the backup self.db.delete(backup) self.db.commit() # force commit before wsgi rollback raise backup.status = 'SAVING' return Response(dict(backup))
def create(self, request): """ PUT /v1.0/{account_id}/backups/{id}?volume={volume_id} Create backup """ # extract volume reference try: volume_id = request.params['volume'] except KeyError: raise HTTPPreconditionFailed("Must specify a 'volume' parameter") try: volume = self.account_query(Volume).\ filter_by(id=volume_id).one() except NoResultFound: raise HTTPPreconditionFailed("Cannot create backup for " "non-existent volume '%s'" % volume_id) if volume.status not in ('ACTIVE', 'IMAGING_SCRUB'): raise HTTPPreconditionFailed( "Status of volume '%s' is '%s', not ACTIVE" % ( volume.id, volume.status)) backup_count = volume.active_backup_count() if backup_count >= self.app.backups_per_volume: raise HTTPPreconditionFailed( "Volume '%s' already has %s out of %s allowed backups" % ( volume_id, backup_count, self.app.backups_per_volume)) params = { 'id': self.id, 'account_id': self.account_id, 'volume': volume, 'status': 'NEW', } backup = Backup(**params) self.db.add(backup) try: self.db.commit() except IntegrityError: self.db.rollback() # optomistic lock count = self.db.query(Backup).filter( and_(Backup.id == self.id, Backup.account_id == self.account_id, Backup.status.in_(['ERROR', 'DELETED'])) ).update(params, synchronize_session=False) if not count: raise HTTPConflict("Backup '%s' already exists" % self.id) # still in uncommited update transaction backup = self.db.query(Backup).get(self.id) try: path = '/volumes/%s/backups/%s' % (backup.volume.name, backup.id) params = { 'account': self.account_id, 'timestamp': int(mktime(backup.created_at.timetuple())), } info = self.node_request(backup.volume.node, 'PUT', path, **params) except NodeError: # Remove the backup record if the node failed to create the backup self.db.delete(backup) self.db.commit() # force commit before wsgi rollback raise backup.status = 'SAVING' return Response(dict(backup))