'Create volume backups using configured backup service.'

def create_backup(self, context, backup):

    volume_id = backup.volume_id
    snapshot_id = backup.snapshot_id
    volume = objects.Volume.get_by_id(context, volume_id)
    snapshot = (objects.Snapshot.get_by_id(context, snapshot_id) if snapshot_id else None)
    previous_status = volume.get('previous_status', None)
    updates = {}
    if snapshot_id:
        log_message = ('Create    backup    started,    backup:    %(backup_id)s    volume:    %(volume_id)s    snapshot:    %(snapshot_id)s.' % {'backup_id': backup.id, 'volume_id': volume_id, 'snapshot_id': snapshot_id})
    else:
        log_message = ('Create    backup    started,    backup:    %(backup_id)s    volume:    %(volume_id)s.' % {'backup_id': backup.id, 'volume_id': volume_id})
    LOG.info(log_message)
    self._notify_about_backup_usage(context, backup, 'create.start')
    backup.host = self.host
    backup.service = self.driver_name
    backup.availability_zone = self.az
    backup.save()
    expected_status = 'backing-up'
    if snapshot_id:
        actual_status = snapshot['status']
        if (actual_status != expected_status):
            err = (_('Create    backup    aborted,    expected    snapshot    status    %(expected_status)s    but    got    %(actual_status)s.') % {'expected_status': expected_status, 'actual_status': actual_status})
            self._update_backup_error(backup, err)
            raise exception.InvalidSnapshot(reason=err)
    else:
        actual_status = volume['status']
        if (actual_status != expected_status):
            err = (_('Create    backup    aborted,    expected    volume    status    %(expected_status)s    but    got    %(actual_status)s.') % {'expected_status': expected_status, 'actual_status': actual_status})
            self._update_backup_error(backup, err)
            raise exception.InvalidVolume(reason=err)
    expected_status = fields.BackupStatus.CREATING
    actual_status = backup.status
    if (actual_status != expected_status):
        err = (_('Create    backup    aborted,    expected    backup    status    %(expected_status)s    but    got    %(actual_status)s.') % {'expected_status': expected_status, 'actual_status': actual_status})
        self._update_backup_error(backup, err)
        backup.save()
        raise exception.InvalidBackup(reason=err)
    try:
        if (not self.is_working()):
            err = _('Create    backup    aborted    due    to    backup    service    is    down')
            self._update_backup_error(backup, err)
            raise exception.InvalidBackup(reason=err)
        updates = self._run_backup(context, backup, volume)
    except Exception as err:
        with excutils.save_and_reraise_exception():
            if snapshot_id:
                snapshot.status = fields.SnapshotStatus.AVAILABLE
                snapshot.save()
            else:
                self.db.volume_update(context, volume_id, {'status': previous_status, 'previous_status': 'error_backing-up'})
            self._update_backup_error(backup, six.text_type(err))
    if snapshot_id:
        self.db.snapshot_update(context, snapshot_id, {'status': fields.BackupStatus.AVAILABLE})
    else:
        self.db.volume_update(context, volume_id, {'status': previous_status, 'previous_status': 'backing-up'})
    backup.status = fields.BackupStatus.AVAILABLE
    backup.size = volume['size']
    if updates:
        backup.update(updates)
    backup.save()
    if backup.parent_id:
        parent_backup = objects.Backup.get_by_id(context, backup.parent_id)
        parent_backup.num_dependent_backups += 1
        parent_backup.save()
    LOG.info('Create    backup    finished.    backup:    %s.', backup.id)
    self._notify_about_backup_usage(context, backup, 'create.end')
