'Move an existing ``unattached`` file into a per-node directory and
create a loopback device backed by that file.
Note: Although `mkfs` can format files directly and `mount` can mount
files directly (with the `-o loop` option), we want to simulate a real
block device which will be allocated a real block device file on the
node to which it is attached. This allows the consumer of this API to
perform formatting and mount operations exactly the same as for a real
block device.
See ``IBlockDeviceAPI.attach_volume`` for parameter and return type
documentation.'

def attach_volume(self, blockdevice_id, attach_to):

    volume = get_blockdevice_volume(self, blockdevice_id)
    filename = _backing_file_name(volume)
    if (volume.attached_to is None):
        old_path = self._unattached_directory.child(filename)
        host_directory = self._attached_directory.child(attach_to.encode('ascii'))
        try:
            host_directory.makedirs()
        except OSError:
            pass
        new_path = host_directory.child(filename)
        old_path.moveTo(new_path)
        self._allocate_device(new_path)
        attached_volume = volume.set(attached_to=attach_to)
        return attached_volume
    raise AlreadyAttachedVolume(blockdevice_id)
