Пример #1
0
    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)
Пример #2
0
 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
Пример #3
0
    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)
Пример #4
0
    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))