'retype the volume.
:param ctxt: Context
:param volume: A dictionary describing the volume to migrate
:param new_type: A dictionary describing the volume type to convert to
:param diff: A dictionary with the difference between the two types
:param host: A dictionary describing the host to migrate to, where
host[\'host\'] is its name, and host[\'capabilities\'] is a
dictionary of its reported capabilities.'

@proxy._trace_time
def retype(self, ctxt, volume, new_type, diff, host):

    def _check_extra_specs(key, value=None):
        extra_specs = diff.get('extra_specs')
        specific_type = (extra_specs.get(key) if extra_specs else None)
        old_type = None
        new_type = None
        if specific_type:
            (old_type, new_type) = specific_type
            if value:
                old_type = (True if (old_type and (old_type.upper() == value)) else False)
                new_type = (True if (new_type and (new_type.upper() == value)) else False)
        return (old_type, new_type)
    lun = Lun(volume)
    (old_specified_pool, new_specified_pool) = _check_extra_specs('drivers:storage_pool_ids')
    (old_specified_lss, new_specified_lss) = _check_extra_specs('drivers:storage_lss_ids')
    (old_type_thick, new_type_thick) = _check_extra_specs('drivers:thin_provision', 'FALSE')
    (old_type_replication, new_type_replication) = _check_extra_specs('replication_enabled', strings.METADATA_IS_TRUE)
    new_props = {}
    if (old_type_thick != new_type_thick):
        new_props['type_thin'] = (not new_type_thick)
    if ((old_specified_pool == new_specified_pool) and (old_specified_lss == new_specified_lss)):
        LOG.info('Same    pool    and    lss.')
    elif ((old_specified_pool or old_specified_lss) and (new_specified_pool or new_specified_lss)):
        raise exception.VolumeDriverException(message=_('Retype    does    not    support    to    move    volume    from    specified    pool    or    lss    to    another    specified    pool    or    lss.'))
    elif (((old_specified_pool is None) and new_specified_pool) or ((old_specified_lss is None) and new_specified_lss)):
        storage_pools = self._helper.get_pools(new_specified_pool)
        self._helper.verify_pools(storage_pools)
        storage_lss = self._helper.verify_lss_ids(new_specified_lss)
        vol_pool = self._helper.get_lun_pool(lun.ds_id)['id']
        vol_lss = lun.ds_id[:2].upper()
        if ((storage_lss and (vol_lss not in storage_lss)) or new_props.get('type_thin')):
            new_props['specified_pool'] = new_specified_pool
            new_props['specified_lss'] = new_specified_lss
        elif (vol_pool not in storage_pools.keys()):
            vol_node = (int(vol_lss, 16) % 2)
            new_pool_id = None
            for (pool_id, pool) in storage_pools.items():
                if (vol_node == pool['node']):
                    new_pool_id = pool_id
                    break
            if new_pool_id:
                self._helper.change_lun(lun.ds_id, {'pool': new_pool_id})
            else:
                raise exception.VolumeDriverException(message=_('Can    not    change    the    pool    volume    allocated.'))
    new_lun = None
    if new_props:
        new_lun = lun.shallow_copy()
        for (key, value) in new_props.items():
            setattr(new_lun, key, value)
        self._clone_lun(lun, new_lun)
    volume_update = None
    if new_lun:
        if new_type_replication:
            new_lun.type_replication = True
            new_lun = self._replication.establish_replication(new_lun, True)
        elif old_type_replication:
            new_lun.type_replication = False
            try:
                self._replication.delete_replica(lun)
            except Exception:
                pass
        try:
            self._helper.delete_lun(lun)
        except Exception:
            pass
        volume_update = new_lun.update_volume(lun)
    else:
        if ((not old_type_replication) and new_type_replication):
            lun.type_replication = True
            lun = self._replication.establish_replication(lun)
        elif (old_type_replication and (not new_type_replication)):
            lun = self._replication.delete_replica(lun)
            lun.type_replication = False
        volume_update = lun.get_volume_update()
    return (True, volume_update)
