'Tune the volume to change the userCPG and/or provisioningType.
The volume will be modified/tuned/converted to the new userCPG and
provisioningType, as needed.
TaskWaiter is used to make this function wait until the 3PAR task
is no longer active.  When the task is no longer active, then it must
either be done or it is in a state that we need to treat as an error.'

def tune_vv(self, old_tpvv, new_tpvv, old_tdvv, new_tdvv, old_cpg, new_cpg, volume_name, new_compression):

    compression = False
    if (new_compression is not None):
        compression = new_compression
    if ((old_tpvv == new_tpvv) and (old_tdvv == new_tdvv)):
        if (new_cpg != old_cpg):
            LOG.info('Modifying    %(volume_name)s    userCPG    from    %(old_cpg)s    to    %(new_cpg)s', {'volume_name': volume_name, 'old_cpg': old_cpg, 'new_cpg': new_cpg})
            (_response, body) = self.client.modifyVolume(volume_name, {'action': 6, 'tuneOperation': 1, 'userCPG': new_cpg})
            task_id = body['taskid']
            status = self.TaskWaiter(self.client, task_id).wait_for_task()
            if (status['status'] is not self.client.TASK_DONE):
                msg = (_('Tune    volume    task    stopped    before    it    was    done:    volume_name=%(volume_name)s,    task-status=%(status)s.') % {'status': status, 'volume_name': volume_name})
                raise exception.VolumeBackendAPIException(msg)
    else:
        if new_tpvv:
            cop = self.CONVERT_TO_THIN
            LOG.info('Converting    %(volume_name)s    to    thin    provisioning    with    userCPG=%(new_cpg)s', {'volume_name': volume_name, 'new_cpg': new_cpg})
        elif new_tdvv:
            cop = self.CONVERT_TO_DEDUP
            LOG.info('Converting    %(volume_name)s    to    thin    dedup    provisioning    with    userCPG=%(new_cpg)s', {'volume_name': volume_name, 'new_cpg': new_cpg})
        else:
            cop = self.CONVERT_TO_FULL
            LOG.info('Converting    %(volume_name)s    to    full    provisioning    with    userCPG=%(new_cpg)s', {'volume_name': volume_name, 'new_cpg': new_cpg})
        try:
            if (self.API_VERSION < COMPRESSION_API_VERSION):
                (response, body) = self.client.modifyVolume(volume_name, {'action': 6, 'tuneOperation': 1, 'userCPG': new_cpg, 'conversionOperation': cop})
            else:
                (response, body) = self.client.modifyVolume(volume_name, {'action': 6, 'tuneOperation': 1, 'userCPG': new_cpg, 'compression': compression, 'conversionOperation': cop})
        except hpeexceptions.HTTPBadRequest as ex:
            if ((ex.get_code() == 40) and ('keepVV' in six.text_type(ex))):
                LOG.info("tunevv    failed    because    the    volume    '%s'    has    snapshots.", volume_name)
                raise
        task_id = body['taskid']
        status = self.TaskWaiter(self.client, task_id).wait_for_task()
        if (status['status'] is not self.client.TASK_DONE):
            msg = (_('Tune    volume    task    stopped    before    it    was    done:    volume_name=%(volume_name)s,    task-status=%(status)s.') % {'status': status, 'volume_name': volume_name})
            raise exception.VolumeBackendAPIException(msg)
