def get_volumeid(self, volume_name):
        """
        Return ScaleIO volume ID given a unique string volume name
        :param volume_name: Unique 32 character string name of the volume
        :return: ScaleIO ID of volume
        """

        volume_id = None

        if not volume_name:
            raise ValueError(
                'Invalid volume_name parameter, volume_name=%s' % volume_name)

        r_uri = '/api/types/Volume/instances/getByName::' + \
            utilities.encode_string(volume_name, double=True)
        req = self._get(r_uri)
        if req.status_code == 200:
            volume_id = req.json()
            LOG.debug('Retrieved volume id %s successfully', volume_id)
            return volume_id
        elif req.json().get('errorCode') == RESOURCE_NOT_FOUND_ERROR:
            raise exceptions.VolumeNotFound("Volume name '%s' is not found"
                                            % volume_name)
        else:
            raise exceptions.Error(
                "Error resolving volume name '%s' to id: %s"
                % (volume_name, req.json().get('message')))
    def get_volume_properties(self, volume_id_or_name):
        """
        Returns properties of a ScaleIO volume
        :param volume_id_or_name: ScaleIO volume ID or volume name
        :return: Dict containing volume properties
        """

        volume_id = self._validate_volume_id(volume_id_or_name)

        r_uri = '/api/instances/Volume::' + volume_id
        req = self._get(r_uri)
        if req.status_code == 200:  # success
            LOG.debug('Retrieved volume object %s successfully', volume_id)
        elif req.json().get('errorCode') == VOLUME_NOT_FOUND_ERROR:
            raise exceptions.VolumeNotFound('Volume %s is not found'
                                            % volume_id)
        else:
            raise exceptions.Error("Error retrieving volume '%s': %s"
                                   % (volume_id, req.json().get('message')))

        return req.json()
    def _volume(self, volume_id_or_name):
        """
        Return a ScaleIOVolume object
        :param volume_id_or_name: ScaleIO volume ID or volume name
        :return: ScaleIOVolume object or None if no valid volume found
        """

        volume_id = self._validate_volume_id(volume_id_or_name)

        volume_obj = None

        r_uri = '/api/instances/Volume::' + volume_id
        req = self._get(r_uri)
        if req.status_code == 200:  # success
            LOG.debug('Retrieved volume object %s successfully', volume_id)
            volume_obj = _ScaleIOVolume(req.json())
        elif req.json().get('errorCode') == VOLUME_NOT_FOUND_ERROR:
            raise exceptions.VolumeNotFound('Volume %s is not found'
                                            % volume_id)
        else:
            raise exceptions.Error("Error retrieving volume '%s': %s"
                                   % (volume_id, req.json().get('message')))

        return volume_obj
    def delete_volume(self, volume_id_or_name, include_descendents=False,
                      only_descendents=False, vtree=False,
                      unmap_on_delete=False, force_delete=True):
        """
        Delete a volume. This command removes a ScaleIO volume. Before
        removing a volume, you must ensure that it is not mapped to any SDCs.

        When removing a volume, you can remove the VTree as well
        (all related snapshots), the volume and its snapshots, or
        just the snapshots. Before removing a VTree, you must unmap
        all volumes in the VTree before removing them.

        Note: Removal of a volume erases all the data on the corresponding
        volume.

        :param volume_id_or_name: ScaleIO volume ID or volume name
        :param include_descendents: Remove volume along with any descendents
        :param only_descendents: Remove only the descendents of the volume
        :param vtree: Remove the entire VTREE
        :param unmap_on_delete: Unmap volume from all SDCs before deleting
        :param force_delete: Ignore if volume is already deleted
        :return: Nothing
        """

        volume_id = self._validate_volume_id(volume_id_or_name)

        # the removeMode options are mutually exclusive
        if [include_descendents, only_descendents, vtree].count(True) > 1:
            raise ValueError(
                'Only one removeMode flag can be specified '
                '(include_descendants, only_descendants, vtree)')

        # default removeMode is ONLY_ME
        remove_mode = 'ONLY_ME'
        if (include_descendents):
            remove_mode = 'INCLUDING_DESCENDANTS'
        if (only_descendents):
            remove_mode = 'DESCENDANTS_ONLY'
        if (vtree):
            remove_mode = 'WHOLE_VTREE'

        params = {'removeMode': remove_mode}

        if unmap_on_delete:
            LOG.debug('Unmap before delete flag True, attempting '
                      'to unmap volume %s from all sdcs before deletion',
                      volume_id)
            try:
                self._unmap_volume(volume_id, unmap_all=True)
            except exceptions.VolumeNotMapped:
                pass

        r_uri = '/api/instances/Volume::' + volume_id + '/action/removeVolume'
        req = self._post(r_uri, params=params)
        if req.status_code == 200:
            LOG.debug('Removed volume %s successfully', volume_id)
        elif req.json().get('errorCode') == VOLUME_NOT_FOUND_ERROR:
            if not force_delete:
                LOG.warn('Error removing volume %s: %s', volume_id,
                         (req.json().get('message')))
                raise exceptions.VolumeNotFound("Volume '%s' is not found"
                                                % volume_id)
        else:
            raise exceptions.Error("Error removing volume '%s': %s"
                                   % (volume_id, req.json().get('message')))