def attach_volume(self, blockdevice_id, attach_to):
        """ Attach ``blockdevice_id`` to ``host``.

        :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 ``host`` attribute set to
            ``host``.
        """

        vol = self._get_solidfire_volume(blockdevice_id)
        if not vol:
            raise UnknownVolume(blockdevice_id)

        tgt_iqn = vol['iqn']
        if utils.path_exists('/dev/disk/by-path/ip-%s-iscsi-%s-lun-0' %
                             (self.svip, tgt_iqn), 1):
            raise AlreadyAttachedVolume(blockdevice_id)

        # It's not attached here, make sure it's not attached somewhere else
        # In the future we can add multi-attach support maybe, but for now
        # avoid the trouble of file-systems etc
        current_sessions = self._current_iscsi_sessions(blockdevice_id)
        if current_sessions:
            raise AlreadyAttachedVolume(blockdevice_id)

        targets = utils.iscsi_discovery(self.svip)
        if len(targets) < 1 and tgt_iqn not in targets:
            raise Exception("No targes found during discovery.")
        if utils.iscsi_login(self.svip, tgt_iqn):
            return BlockDeviceVolume(
                blockdevice_id=unicode(blockdevice_id),
                size=vol['totalSize'],
                attached_to=attach_to,
                dataset_id=uuid.UUID(str(vol['name'])))
        raise Exception("Failed iSCSI login to device: %s" % blockdevice_id)
    def detach_volume(self, blockdevice_id):
        """ Detach ``blockdevice_id`` from whatever host it is attached to.

        :param unicode blockdevice_id: The unique identifier for the block
            device being detached.

        :raises UnknownVolume: If the supplied ``blockdevice_id`` does not
            exist.
        :raises UnattachedVolume: If the supplied ``blockdevice_id`` is
            not attached to anything.
        :returns: ``None``
        """
        vol = self._get_solidfire_volume(blockdevice_id)
        if not vol:
            raise UnknownVolume(blockdevice_id)

        tgt_iqn = vol['iqn']
        if not utils.path_exists('/dev/disk/by-path/ip-%s-iscsi-%s-lun-0' %
                                 (self.svip, tgt_iqn), 1):
            raise UnattachedVolume(blockdevice_id)
        utils.iscsi_logout(self.svip, tgt_iqn)
    def list_volumes(self):
        """ List all the block devices available via the back end API.

        :returns: A ``list`` of ``BlockDeviceVolume``s.
        """
        volumes = []
        sfvols = self.client.issue_request('ListVolumesForAccount',
                                           {'accountID': self.account_id},
                                           version='7.0')['volumes']
        for v in sfvols:
            attached_to = None
            tgt_iqn = v['iqn']
            if utils.path_exists('/dev/disk/by-path/ip-%s-iscsi-%s-lun-0' %
                                 (self.svip, tgt_iqn), 1):
                attached_to = self.compute_instance_id()
            name = v['name']
            if 'flock-' in v['name']:
                name = name.replace('flock-', '')
            volumes.append(BlockDeviceVolume(
                           blockdevice_id=unicode(v['volumeID']),
                           size=v['totalSize'],
                           attached_to=attached_to,
                           dataset_id=uuid.UUID(str(name))))
        return volumes