def retype(self, ctxt, volume_id, new_type_id, host, migration_policy='never', reservations=None, volume=None, old_reservations=None):

    def _retype_error(context, volume, old_reservations, new_reservations, status_update):
        try:
            volume.update(status_update)
            volume.save()
        finally:
            QUOTAS.rollback(context, old_reservations)
            QUOTAS.rollback(context, new_reservations)
    context = ctxt.elevated()
    if (volume is None):
        volume = objects.Volume.get_by_id(context, volume_id)
    status_update = {'status': volume.previous_status}
    if (context.project_id != volume.project_id):
        project_id = volume.project_id
    else:
        project_id = context.project_id
    try:
        utils.require_driver_initialized(self.driver)
    except exception.DriverNotInitialized:
        with excutils.save_and_reraise_exception():
            volume.update(status_update)
            volume.save()
    if (not old_reservations):
        try:
            reserve_opts = {'volumes': (- 1), 'gigabytes': (- volume.size)}
            QUOTAS.add_volume_type_opts(context, reserve_opts, volume.volume_type_id)
            reserve_opts.pop('volumes')
            reserve_opts.pop('gigabytes')
            old_reservations = QUOTAS.reserve(context, project_id=project_id, **reserve_opts)
        except Exception:
            volume.update(status_update)
            volume.save()
            msg = _('Failed to update quota usage while retyping volume.')
            LOG.exception(msg, resource=volume)
            raise exception.CinderException(msg)
    new_reservations = reservations
    retyped = False
    (diff, all_equal) = volume_types.volume_types_diff(context, volume.volume_type_id, new_type_id)
    if all_equal:
        retyped = True
    retype_model_update = None
    if ((not retyped) and vol_utils.hosts_are_equivalent(self.driver.host, host['host'])):
        try:
            new_type = volume_types.get_volume_type(context, new_type_id)
            ret = self.driver.retype(context, volume, new_type, diff, host)
            if (type(ret) == tuple):
                (retyped, retype_model_update) = ret
            else:
                retyped = ret
            if retyped:
                LOG.info(_LI('Volume %s: retyped successfully'), volume.id)
        except Exception:
            retyped = False
            LOG.exception(_LE('Volume %s: driver error when trying to retype, falling back to generic mechanism.'), volume.id)
    if (not retyped):
        if (migration_policy == 'never'):
            _retype_error(context, volume, old_reservations, new_reservations, status_update)
            msg = _('Retype requires migration but is not allowed.')
            raise exception.VolumeMigrationFailed(reason=msg)
        snaps = objects.SnapshotList.get_all_for_volume(context, volume.id)
        if snaps:
            _retype_error(context, volume, old_reservations, new_reservations, status_update)
            msg = _('Volume must not have snapshots.')
            LOG.error(msg)
            raise exception.InvalidVolume(reason=msg)
        rep_status = volume.replication_status
        if ((rep_status is not None) and (rep_status != 'disabled')):
            _retype_error(context, volume, old_reservations, new_reservations, status_update)
            msg = _('Volume must not be replicated.')
            LOG.error(msg)
            raise exception.InvalidVolume(reason=msg)
        volume.migration_status = 'starting'
        volume.save()
        try:
            self.migrate_volume(context, volume.id, host, new_type_id=new_type_id)
        except Exception:
            with excutils.save_and_reraise_exception():
                _retype_error(context, volume, old_reservations, new_reservations, status_update)
    else:
        model_update = {'volume_type_id': new_type_id, 'host': host['host'], 'status': status_update['status']}
        if retype_model_update:
            model_update.update(retype_model_update)
        volume.update(model_update)
        volume.save()
    if old_reservations:
        QUOTAS.commit(context, old_reservations, project_id=project_id)
    if new_reservations:
        QUOTAS.commit(context, new_reservations, project_id=project_id)
    self._notify_about_volume_usage(context, volume, 'retype', extra_usage_info={'volume_type': new_type_id})
    self.publish_service_capabilities(context)
    LOG.info(_LI('Retype volume completed successfully.'), resource=volume)
def retype(self, ctxt, volume_id, new_type_id, host, migration_policy='never', reservations=None, volume=None, old_reservations=None):

    def _retype_error(context, volume, old_reservations, new_reservations, status_update):
        try:
            volume.update(status_update)
            volume.save()
        finally:
            QUOTAS.rollback(context, old_reservations)
            QUOTAS.rollback(context, new_reservations)
    context = ctxt.elevated()
    if (volume is None):
        volume = objects.Volume.get_by_id(context, volume_id)
    status_update = {'status': volume.previous_status}
    if (context.project_id != volume.project_id):
        project_id = volume.project_id
    else:
        project_id = context.project_id
    try:
        utils.require_driver_initialized(self.driver)
    except exception.DriverNotInitialized:
        with excutils.save_and_reraise_exception():
            volume.update(status_update)
            volume.save()
    if (not old_reservations):
        try:
            reserve_opts = {'volumes': (- 1), 'gigabytes': (- volume.size)}
            QUOTAS.add_volume_type_opts(context, reserve_opts, volume.volume_type_id)
            reserve_opts.pop('volumes')
            reserve_opts.pop('gigabytes')
            old_reservations = QUOTAS.reserve(context, project_id=project_id, **reserve_opts)
        except Exception:
            volume.update(status_update)
            volume.save()
            msg = _('Failed to update quota usage while retyping volume.')
            LOG.exception(msg, resource=volume)
            raise exception.CinderException(msg)
    new_reservations = reservations
    retyped = False
    (diff, all_equal) = volume_types.volume_types_diff(context, volume.volume_type_id, new_type_id)
    if all_equal:
        retyped = True
    retype_model_update = None
    if ((not retyped) and vol_utils.hosts_are_equivalent(self.driver.host, host['host'])):
        try:
            new_type = volume_types.get_volume_type(context, new_type_id)
            ret = self.driver.retype(context, volume, new_type, diff, host)
            if (type(ret) == tuple):
                (retyped, retype_model_update) = ret
            else:
                retyped = ret
            if retyped:
                LOG.info(_LI('Volume %s: retyped successfully'), volume.id)
        except Exception:
            retyped = False
            LOG.exception(_LE('Volume %s: driver error when trying to retype, falling back to generic mechanism.'), volume.id)
    if (not retyped):
        if (migration_policy == 'never'):
            _retype_error(context, volume, old_reservations, new_reservations, status_update)
            msg = _('Retype requires migration but is not allowed.')
            raise exception.VolumeMigrationFailed(reason=msg)
        snaps = objects.SnapshotList.get_all_for_volume(context, volume.id)
        if snaps:
            _retype_error(context, volume, old_reservations, new_reservations, status_update)
            msg = _('Volume must not have snapshots.')
            LOG.error(msg)
            raise exception.InvalidVolume(reason=msg)
        rep_status = volume.replication_status
        if ((rep_status is not None) and (rep_status != 'disabled')):
            _retype_error(context, volume, old_reservations, new_reservations, status_update)
            msg = _('Volume must not be replicated.')
            LOG.error(msg)
            raise exception.InvalidVolume(reason=msg)
        volume.migration_status = 'starting'
        volume.save()
        try:
            self.migrate_volume(context, volume.id, host, new_type_id=new_type_id)
        except Exception:
            with excutils.save_and_reraise_exception():
                _retype_error(context, volume, old_reservations, new_reservations, status_update)
    else:
        model_update = {'volume_type_id': new_type_id, 'host': host['host'], 'status': status_update['status']}
        if retype_model_update:
            model_update.update(retype_model_update)
        volume.update(model_update)
        volume.save()
    if old_reservations:
        QUOTAS.commit(context, old_reservations, project_id=project_id)
    if new_reservations:
        QUOTAS.commit(context, new_reservations, project_id=project_id)
    self._notify_about_volume_usage(context, volume, 'retype', extra_usage_info={'volume_type': new_type_id})
    self.publish_service_capabilities(context)
    LOG.info(_LI('Retype volume completed successfully.'), resource=volume)