def attach_volume(self, blockdevice_id, attach_to):
        """
        Attach ``blockdevice_id`` to the node indicated by ``attach_to``.

        :param unicode blockdevice_id: The unique identifier for the block
                                       device being attached.
        :param unicode attach_to: An identifier like the one returned by the
                                  ``compute_instance_id`` method indicating the
                                  node to which to attach the volume.

        :raises UnknownVolume: If the supplied ``blockdevice_id`` does not
                               exist
        :raises AlreadyAttachedVolume: If the supplied ``blockdevice_id`` is
                                       already attached

        :returns: A ``BlockDeviceVolume`` with a ``attached_to`` attribute set
                  to ``attach_to``
        """
        blockdevice_id_str = self._vol_f2n(blockdevice_id)
        logger.debug('Attaching volume %s to %s', blockdevice_id, attach_to)
        if not self._volume_exists(blockdevice_id=blockdevice_id):
            raise UnknownVolume(blockdevice_id)

        if self._volume_attached(blockdevice_id=blockdevice_id):
            raise AlreadyAttachedVolume(blockdevice_id)

        self.driver.attach_volume(pool_name=self.pool_name,
                                  volume_name=blockdevice_id_str,
                                  igroup_name=attach_to)

        # The volume is attached. Now extract the other properties of the
        # volume to create a BlockDeviceVolume.
        volumes = self.list_volumes()
        for volume in volumes:
            if volume.blockdevice_id == blockdevice_id:
                return _blockdevicevolume_from_blockdevice_id(
                    blockdevice_id=volume.blockdevice_id,
                    size=int(volume.size),
                    attached_to=attach_to)
        raise UnknownVolume(blockdevice_id)
    def _get_vol_details(self, blockdevice_id):
        """
        :param blockdevice_id - volume id
        :return:volume details
        :exception: Unknown volume
        """
        try:
            vol = self.mgmt.request('volumes', 'GET', name=blockdevice_id)
            vol_content = vol['content']

            if int(vol_content['num-of-lun-mappings']) == 0:
                is_attached_to = None
            else:
                is_attached_to = unicode(vol_content['lun-mapping-list'][0][0][1])

            volume = _blockdevicevolume_from_blockdevice_id(
                blockdevice_id=blockdevice_id,
                size=self._convert_size(int(vol_content['vol-size'])),
                attached_to=is_attached_to
            )
            return volume
        except DeviceExceptionObjNotFound as exc:
            raise UnknownVolume(blockdevice_id)
    def _get_vol_details(self, blockdevice_id):
        """
        :param blockdevice_id - volume id
        :return:volume details
        :exception: Unknown volume
        """
        try:
            vol = self.mgmt.request('volumes', 'GET', name=blockdevice_id)
            vol_content = vol['content']

            if int(vol_content['num-of-lun-mappings']) == 0:
                is_attached_to = None
            else:
                is_attached_to = unicode(
                    vol_content['lun-mapping-list'][0][0][1])

            volume = _blockdevicevolume_from_blockdevice_id(
                blockdevice_id=blockdevice_id,
                size=self._convert_size(int(vol_content['vol-size'])),
                attached_to=is_attached_to)
            return volume
        except DeviceExceptionObjNotFound as exc:
            raise UnknownVolume(blockdevice_id)
    def list_volumes(self):
        """
        List all the block devices available via the back end API.

        :return: The :py:class:`~flocker.node.agents.blockdevice.BlockDeviceVolume`
                 volumes
        :rtype: list
        """
        logger.debug('Getting a list of block device volumes')
        netapp_volumes = self.driver.volumes(self.vserver,
                                             pool_name=self.pool_name)

        block_device_volumes = []
        for netapp_volume in netapp_volumes:
            logger.debug('Creating a BlockDeviceVolume object for %s',
                         netapp_volume)
            try:
                # Create a BlockDeviceVolume, and append it to list.
                attached_to = None
                # TODO: Clean this up a bit
                if unicode(netapp_volume['attached_to']) != 'None':
                    attached_to = unicode(netapp_volume['attached_to'])

                volume = _blockdevicevolume_from_blockdevice_id(
                    blockdevice_id=unicode(self._vol_n2f(
                        netapp_volume['blockdevice_id'])),
                    size=int(netapp_volume['size']),
                    attached_to=attached_to)
                block_device_volumes.append(volume)
            except Exception:  # TODO: Too broad, make more specific
                logger.exception('Unexpected error while creating a '
                                 'BlockDeviceVolume for %s', netapp_volume)

        logger.debug('Found the following block device volumes: %s',
                     block_device_volumes)
        return block_device_volumes