Ejemplo n.º 1
0
    def _get_import_backup(self, context, backup_url):
        """Prepare database backup record for import.

        This method decodes provided backup_url and expects to find the id of
        the backup in there.

        Then checks the DB for the presence of this backup record and if it
        finds it and is not deleted it will raise an exception because the
        record cannot be created or used.

        If the record is in deleted status then we must be trying to recover
        this record, so we'll reuse it.

        If the record doesn't already exist we create it with provided id.

        :param context: running context
        :param backup_url: backup description to be used by the backup driver
        :return: BackupImport object
        :raises InvalidBackup:
        :raises InvalidInput:
        """
        reservations = None
        backup = None
        # Deserialize string backup record into a dictionary
        backup_record = objects.Backup.decode_record(backup_url)

        # ID is a required field since it's what links incremental backups
        if 'id' not in backup_record:
            msg = _('Provided backup record is missing an id')
            raise exception.InvalidInput(reason=msg)

        # Since we use size to reserve&commit quota, size is another required
        # field.
        if 'size' not in backup_record:
            msg = _('Provided backup record is missing size attribute')
            raise exception.InvalidInput(reason=msg)

        try:
            reserve_opts = {
                'backups': 1,
                'backup_gigabytes': backup_record['size']
            }
            reservations = QUOTAS.reserve(context, **reserve_opts)
        except exception.OverQuota as e:
            quota_utils.process_reserve_over_quota(context,
                                                   e,
                                                   resource='backups',
                                                   size=backup_record['size'])

        kwargs = {
            'user_id': context.user_id,
            'project_id': context.project_id,
            'volume_id': IMPORT_VOLUME_ID,
            'status': fields.BackupStatus.CREATING,
            'deleted_at': None,
            'deleted': False,
            'metadata': {}
        }

        try:
            try:
                # Try to get the backup with that ID in all projects even among
                # deleted entries.
                backup = objects.BackupImport.get_by_id(
                    context.elevated(read_deleted='yes'),
                    backup_record['id'],
                    project_only=False)

                # If record exists and it's not deleted we cannot proceed
                # with the import
                if backup.status != fields.BackupStatus.DELETED:
                    msg = _('Backup already exists in database.')
                    raise exception.InvalidBackup(reason=msg)

                # Otherwise we'll "revive" delete backup record
                backup.update(kwargs)
                backup.save()
                QUOTAS.commit(context, reservations)
            except exception.BackupNotFound:
                # If record doesn't exist create it with the specific ID
                backup = objects.BackupImport(context=context,
                                              id=backup_record['id'],
                                              **kwargs)
                backup.create()
                QUOTAS.commit(context, reservations)
        except Exception:
            with excutils.save_and_reraise_exception():
                try:
                    if backup and 'id' in backup:
                        backup.destroy()
                finally:
                    QUOTAS.rollback(context, reservations)
        return backup
Ejemplo n.º 2
0
    def _get_import_backup(self, context, backup_url):
        """Prepare database backup record for import.

        This method decodes provided backup_url and expects to find the id of
        the backup in there.

        Then checks the DB for the presence of this backup record and if it
        finds it and is not deleted it will raise an exception because the
        record cannot be created or used.

        If the record is in deleted status then we must be trying to recover
        this record, so we'll reuse it.

        If the record doesn't already exist we create it with provided id.

        :param context: running context
        :param backup_url: backup description to be used by the backup driver
        :return: BackupImport object
        :raises InvalidBackup:
        :raises InvalidInput:
        """
        # Deserialize string backup record into a dictionary
        backup_record = objects.Backup.decode_record(backup_url)

        # ID is a required field since it's what links incremental backups
        if 'id' not in backup_record:
            msg = _('Provided backup record is missing an id')
            raise exception.InvalidInput(reason=msg)

        kwargs = {
            'user_id': context.user_id,
            'project_id': context.project_id,
            'volume_id': IMPORT_VOLUME_ID,
            'status': fields.BackupStatus.CREATING,
            'deleted_at': None,
            'deleted': False,
            'metadata': {}
        }

        try:
            # Try to get the backup with that ID in all projects even among
            # deleted entries.
            backup = objects.BackupImport.get_by_id(
                context.elevated(read_deleted='yes'),
                backup_record['id'],
                project_only=False)

            # If record exists and it's not deleted we cannot proceed with the
            # import
            if backup.status != fields.BackupStatus.DELETED:
                msg = _('Backup already exists in database.')
                raise exception.InvalidBackup(reason=msg)

            # Otherwise we'll "revive" delete backup record
            backup.update(kwargs)
            backup.save()

        except exception.BackupNotFound:
            # If record doesn't exist create it with the specific ID
            backup = objects.BackupImport(context=context,
                                          id=backup_record['id'],
                                          **kwargs)
            backup.create()

        return backup