Bug 1301021

Summary: [RFE] add support for LUKS disk encryption format driver w/ RBD, iSCSI, and qcow2
Product: Red Hat Enterprise Linux 7 Reporter: Daniel Berrangé <berrange>
Component: libvirtAssignee: John Ferlan <jferlan>
Status: CLOSED ERRATA QA Contact: Virtualization Bugs <virt-bugs>
Severity: unspecified Docs Contact:
Priority: unspecified    
Version: 7.3CC: dyuan, jbelka, jdenemar, jferlan, jomurphy, kchamart, lyarwood, pkrempa, rbalakri, sherold, virt-bugs, virt-maint, yanyang, yisun
Target Milestone: rcKeywords: FutureFeature
Target Release: ---   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: libvirt-2.0.0-4.el7 Doc Type: Enhancement
Doc Text:
Story Points: ---
Clone Of: 1301019 Environment:
Last Closed: 2016-11-03 18:36:22 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Bug Depends On: 1301019    
Bug Blocks: 1821539, 1230405, 1262121, 1301026, 1305606, 1353247, 1411525, 1419710    
Attachments:
Description Flags
script to frequently create/destroy luks vol with different param combinations
none
log of script execution none

Description Daniel Berrangé 2016-01-22 10:59:01 UTC
Clone of QEMU bug to track libvirt enablement tasks for LUKS disk encryption

+++ This bug was initially created as a clone of Bug #1301019 +++

Description of problem:
QCow2 currently has a built-in AES encryption feature, however, it is broken by design and does not offer acceptable security. It is possible to have QEMU access a dm-crypt device setup by the cryptosetup tools in the host, however, that requires that the backend storage be exposed via a kernel block device driver. In OpenStack there is a move towards using the in-QEMU network clients for everything, as they have proved more reliable to manage than kernel + usersapce tools. The LUKS format used by dm-crypt, is very well designed and desirable to use. As such OpenStack requires that QEMU gain support to use LUKS directly as a layer above its native RBD and iSCSI drivers, as well as to integrate it in QCow2 as a  replacement for the current broken AES support.

Most recent posting of this work upstream

https://lists.gnu.org/archive/html/qemu-devel/2016-01/msg03871.html

Comment 2 John Ferlan 2016-06-18 10:33:58 UTC
After a few rounds of attempts to address various parts of this with patches that would help reduce the quantity of patches, I settled on the following series as a v1 for support:

http://www.redhat.com/archives/libvir-list/2016-June/msg00804.html

Comment 3 John Ferlan 2016-06-23 17:36:44 UTC
Some patches pushed, some patches adjusted, reposted :

http://www.redhat.com/archives/libvir-list/2016-June/msg01691.html

Comment 4 John Ferlan 2016-07-19 14:10:29 UTC

A v4 was posted:

  http://www.redhat.com/archives/libvir-list/2016-July/msg00360.html

Reviews resulted in another series dealing with hotplug error paths being posted and pushed:

  http://www.redhat.com/archives/libvir-list/2016-July/msg00528.html

and some adjustments to the original series to handle those changes, resulting in the final push:

commit da86c6c22674ccc147224afa2740e33d8cbdbf22
Author: John Ferlan <jferlan>
Date:   Thu Jun 2 16:28:28 2016 -0400

    qemu: Add luks support for domain disk

Comment 14 yisun 2016-08-22 12:59:34 UTC
Created attachment 1192930 [details]
script to frequently create/destroy luks vol with different param combinations

Comment 15 yisun 2016-08-22 13:07:30 UTC
Created attachment 1192931 [details]
log of script execution

Comment 16 yisun 2016-08-22 13:09:25 UTC
execute a test with vol-create/vol-delete luks vol frequently with following parameters combination:
cipher_names = ["aes","des","cast5","serpent","twofish","invalid"]
cipher_sizes = ["256","192","128","6"] # 6 is invalid value for negative test
cipher_modes = ["cbc","xts","ecb","invalid"]
cipher_hashes = ["md5","sha1","sha256","invalid"]
ivgen_names = ["plain","plain64","essiv","invalid"]
ivgen_hashes = ["md5","sha1","sha256","invalid"]

steps:
1. prepare a secret with uuid=f981dd17-143f-45bc-88e6-ed1fe20ce9da
# virsh secret-dumpxml f981dd17-143f-45bc-88e6-ed1fe20ce9da
<secret ephemeral='no' private='yes'>
  <uuid>f981dd17-143f-45bc-88e6-ed1fe20ce9da</uuid>
  <description>LUKS Sample Secret</description>
  <usage type='volume'>
    <volume>/var/libvirt/images/luks/luks_1.vol</volume>
  </usage>
</secret>

2. prepare a dir pool for luks vol
# virsh pool-dumpxml luks
<pool type='dir'>
  <name>luks</name>
  <uuid>0e20f159-2a41-435b-af31-b33993633ec6</uuid>
  <capacity unit='bytes'>53660876800</capacity>
  <allocation unit='bytes'>37977546752</allocation>
  <available unit='bytes'>15683330048</available>
  <source>
  </source>
  <target>
    <path>/var/lib/libvirt/images/luks</path>
    <permissions>
      <mode>0711</mode>
      <owner>0</owner>
      <group>0</group>
      <label>system_u:object_r:virt_image_t:s0</label>
    </permissions>
  </target>
</pool>

3. run attached python script in attachment: attachment 1192930 [details]
#python luks_vol_create_delete.py

4. will get a log file as attachment: attachment 1192931 [details]

5. there are some issues but seems qemu-kvm-rhev issues, so needinfo in qemu's bug https://bugzilla.redhat.com/show_bug.cgi?id=1301019#c7

Comment 17 yisun 2016-08-24 09:20:33 UTC
Hi John, 
I have a question about why libvirt doesn't have a new format type='luks' in volume/virtual_disk's xml. But it uses 'raw' as follow:
##################### volume #####################
      <volume>
        <name>twofish.luks</name>
        <capacity unit='G'>5</capacity>
        <target>
          <path>/var/lib/libvirt/images/demo.luks</path>
          <format type='raw'/>   <========================== here
          <encryption format='luks'>
             <secret type='passphrase' uuid='f52a81b2-424e-490c-823d-6bd4235bc572'/>
             <cipher name='twofish' size='256' mode='cbc' hash='sha256'/>
             <ivgen name='plain64' hash='sha256'/>
          </encryption>
        </target>
      </volume>
###############################################################
##################### vm's virtual disk #####################
    <disk type='file' device='disk'>
      <driver name='qemu' type='raw'/>   <================= here
      <source file='/var/lib/libvirt/images/luks/luks_1.img'/>
      <backingStore/>
      <target dev='vdb' bus='virtio'/>
      <encryption format='luks'>
        <secret type='passphrase' uuid='f981dd17-143f-45bc-88e6-ed1fe20ce9da'/>
      </encryption>
      <alias name='virtio-disk1'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x0b' function='0x0'/>
    </disk>
###############################################################

The concern is, when start a vm with above virtual disk xml, if there is a <encryption> segment, libvirt will call qemu-kvm as follow:
#####
/usr/libexec/qemu-kvm -name guest=test,debug-threads=on ... -drive file=/var/lib/libvirt/images/luks/luks_1.img,key-secret=virtio-disk1-luks-secret0,format=luks,if=none,id=drive-virtio-disk1 ...#<<<<<<<<<<<<<<<here the format =luks
#####
But if we start a vm, whose virtual disk xml without <encryption> by mistake, as follow:
#####
    <disk type='file' device='disk'>
      <driver name='qemu' type='raw'/>
      <source file='/var/lib/libvirt/images/luks/luks_1.img'/>
      <target dev='vdb' bus='virtio'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x0b' function='0x0'/>
    </disk>
#####
qemu-kvm cmd will be like:
#####
/usr/libexec/qemu-kvm -name guest=test,debug-threads=on... -drive file=/var/lib/libvirt/images/luks/luks_1.img,format=raw,if=none,id=drive-virtio-disk1 -device virtio-blk-pci,scsi=off,bus=pci.0,addr=0xb,drive=drive-virtio-disk1,id=virtio-disk1 #<<<<<<<<<<<<<<< here format=raw
#####

so the current logic is something like:
if format == 'raw':
    if isExist('<encryption>'):
        qemu-kvm ... format='luks'
    else:
        qemu-kvm ... format='raw'


why don't we have a:
if format == 'luks':
     qemu-kvm ... format='luks'

That seems more clear and won't cause risk if user forget to add the encryption part ( in this case, luks disk will be used as raw and can be formatted in vm)

Comment 18 Daniel Berrangé 2016-08-24 12:53:57 UTC
QEMU uses the "format" option to refer to multiple different concepts. Libvirt separates those concepts out into distinct attributes, which all map to format, hence use of type=luks is not appropriate from libvirt POV. See further explanation in

https://www.redhat.com/archives/libvir-list/2016-July/msg01063.html

Comment 19 yisun 2016-09-05 12:17:12 UTC
(In reply to Daniel Berrange from comment #18)
> QEMU uses the "format" option to refer to multiple different concepts.
> Libvirt separates those concepts out into distinct attributes, which all map
> to format, hence use of type=luks is not appropriate from libvirt POV. See
> further explanation in
> 
> https://www.redhat.com/archives/libvir-list/2016-July/msg01063.html

That's clear, thx

Comment 20 yisun 2016-09-05 12:22:17 UTC
Snapshot for luks encrypted img doesn't work, the backingStore file's xml doesn't have encryption part(do we need to support encryption for backing store?). As follow:


# virsh dumpxml virtlab_test_copy
...
    <disk type='file' device='disk'>
      <driver name='qemu' type='raw'/>
      <source file='/var/lib/libvirt/images/luks/hei.img'/>
      <target dev='vdd' bus='virtio'/>
      <encryption format='luks'>
        <secret type='passphrase' uuid='4ff78f8c-6ee6-4a8d-b638-2b59d5d49279'/>
      </encryption>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/>
    </disk>
...



# virsh start virtlab_test_copy
Domain virtlab_test_copy started


# virsh domblklist virtlab_test_copy
Target     Source
------------------------------------------------
...
vdd        /var/lib/libvirt/images/luks/hei.img


# virsh snapshot-create-as virtlab_test_copy snap1 --disk-only --diskspec vdd,file=/tmp/hei.img.snap1
Domain snapshot snap1 created


# virsh dumpxml virtlab_test_copy
...
    <disk type='file' device='disk'>
      <driver name='qemu' type='qcow2'/>
      <source file='/tmp/hei.img.snap1'/>
      <backingStore type='file' index='1'>
        <format type='raw'/>
        <source file='/var/lib/libvirt/images/luks/hei.img'/> 
        <backingStore/>
      </backingStore>
      <target dev='vdd' bus='virtio'/>
      <alias name='virtio-disk3'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/>
    </disk>
...




# virsh destroy virtlab_test_copy
Domain virtlab_test_copy destroyed



# virsh start virtlab_test_copy
error: Failed to start domain virtlab_test_copy
error: internal error: process exited while connecting to monitor: 2016-09-05T11:31:39.269057Z qemu-kvm: -drive file=/tmp/hei.img.snap1,format=qcow2,if=none,id=drive-virtio-disk3: Could not open backing file: No secret with id 'virtio-disk3-luks-secret0'


//now the vm is still in shutdown status
# virsh dumpxml virtlab_test_copy   
...
    <disk type='file' device='disk'>
      <driver name='qemu' type='qcow2'/>
      <source file='/tmp/hei.img.snap1'/>
      <target dev='vdd' bus='virtio'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/>
    </disk>
...

Comment 21 yisun 2016-09-06 12:42:52 UTC
And another issue pls help to confirm - when vol-create a qcow2 vol with "default" encryption. libvirt'll automatically generate a secret, and put it in vol's xml. before libvirt-2.0.0-4, the <encryption> part will exist in vol-dumpxml. But after libvirt-2.0.0-4, the <encryption> part will be gone after pool-refresh. Is this a intentional change? I think it may be not a issue, but out auto test report regression error. So pls help to confirm. 

Steps:
# /bin/virsh pool-create-as --name temp_pool --type dir --target /tmp/dir
Pool temp_pool created

# cat vol.xml 
<volume>
<name>temp_vol_0</name>
<capacity>104857600</capacity>
<allocation>52428800</allocation>
<target><format type="qcow2" />
<encryption format="default" />
</target>
</volume>

# /bin/virsh vol-create --pool temp_pool --file vol.xml 
Vol temp_vol_0 created from vol.xml

# virsh vol-dumpxml /tmp/dir/temp_vol_0 
<volume type='file'>
  <name>temp_vol_0</name>
  <key>/tmp/dir/temp_vol_0</key>
  <source>
  </source>
  <capacity unit='bytes'>104857600</capacity>
  <allocation unit='bytes'>200704</allocation>
  <target>
    <path>/tmp/dir/temp_vol_0</path>
    <format type='qcow2'/>
    <permissions>
      <mode>0600</mode>
      <owner>0</owner>
      <group>0</group>
      <label>system_u:object_r:user_tmp_t:s0</label>
    </permissions>
    <timestamps>
      <atime>1473165357.642969550</atime>
      <mtime>1473165357.615969146</mtime>
      <ctime>1473165357.642969550</ctime>
    </timestamps>
    <encryption format='qcow'>   <==== currently, the encryption part exists
      <secret type='passphrase' uuid='3dc1ea14-0eb4-4d8c-938d-5174f33d9b80'/>
    </encryption>
  </target>
</volume>


# virsh pool-refresh temp_pool
Pool temp_pool refreshed

<=== now the <encryption> part gone, as follow:
# virsh vol-dumpxml /tmp/dir/temp_vol_0 
<volume type='file'>
  <name>temp_vol_0</name>
  <key>/tmp/dir/temp_vol_0</key>
  <source>
  </source>
  <capacity unit='bytes'>104857600</capacity>
  <allocation unit='bytes'>200704</allocation>
  <target>
    <path>/tmp/dir/temp_vol_0</path>
    <format type='qcow2'/>
    <permissions>
      <mode>0600</mode>
      <owner>0</owner>
      <group>0</group>
      <label>system_u:object_r:user_tmp_t:s0</label>
    </permissions>
    <timestamps>
      <atime>1473165374.469221007</atime>
      <mtime>1473165357.615969146</mtime>
      <ctime>1473165357.642969550</ctime>
    </timestamps>
  </target>
</volume>

Comment 22 Daniel Berrangé 2016-09-06 12:48:24 UTC
There should not have been any change to existing qcow2 encryption functionality, so that sounds like a bug

Comment 23 John Ferlan 2016-09-06 14:28:00 UTC
When implementing the luks code I neglected to consider snapshots. Whether the <backingStore> or the <disk> should have the <encryption> I'm not quite sure, but I assume it'd the the <disk>. I'm not quite sure how 'virtio-disk3-luks-secret0' gets stored away so that the subsequent start needs to find it. In any case for whatever reason that <encryption>...</encryption> block is lost once the snapshot is taken. Trying to read/follow the code, but the answer just doesn't jump out at me... 

Placed a needsinfo on pkrempa to perhaps help get me the answer.

Comment 24 Peter Krempa 2016-09-06 14:58:03 UTC
(In reply to John Ferlan from comment #23)
> When implementing the luks code I neglected to consider snapshots. Whether
> the <backingStore> or the <disk> should have the <encryption> I'm not quite

The encryption element really should be on <backingStore> elements as well. The problem is that currently libvirt doesn't allow to specify the full backing chain including custom data.

I'm still planing to do it since it also has implications for disks needing authentication which stop to work once a snapshot is created.

> sure, but I assume it'd the the <disk>. I'm not quite sure how

The encryption key info from the <disk> needs to become encryption info of the backing store. This may work right now for live VMs but certainly breaks if you turn it of and back on.

> 'virtio-disk3-luks-secret0' gets stored away so that the subsequent start
> needs to find it. In any case for whatever reason that
> <encryption>...</encryption> block is lost once the snapshot is taken.
> Trying to read/follow the code, but the answer just doesn't jump out at
> me... 
> 
> Placed a needsinfo on pkrempa to perhaps help get me the answer.

I've expected it to happen, but with external snapshots this bug still exists for the authentication case and even for the long broken qcow2 internal encryption which would break as well with external snapshots.

The only way to do this is to fully implement backing chain construction from a full backing chain expressed in the XML. Our long standing excuse was that blockdev-add is not finished in qemu and thus the backing chain can't really be built.

Comment 25 John Ferlan 2016-09-06 19:28:24 UTC
Some more digging w/r/t Comment 21 seems to be a bug caused by commit id 'a48c714115'.

The issue is that it doesn't seems that the removed code to determine whether the volume had qcow encryption:

   crypt_format = virReadBufInt32BE(buf +
                                    fileTypeInfo[meta->format].qcowCryptOffset);
   if (crypt_format && !meta->encryption &&
       VIR_ALLOC(meta->encryption) < 0)
       goto cleanup;

would be equivalent to the new code which is detecting encryption based upon the :

    } else if (info->modeOffset != -1) {
        if (info->modeOffset >= len)
            return false;

        if (buf[info->modeOffset] != info->modeValue)
            return false;

        return true;

In particular, debugging shows "buf[info->modeOffset]" is 0, but if I replace the buf[] compare code with?

        crypt_format = virReadBufInt32BE(buf + info->modeOffset);
        if (crypt_format != info->modeValue)
...

then the <encryption> is once again displayed for the qcow2 volume. 

BTW: There's a similar phenomena with a LUKS volume for pool-refresh...  Although for LUKS, just the <secret type='passphrase' uuid='$UUID'/> is not formatted.

Comment 26 yisun 2016-09-09 08:37:35 UTC
(In reply to John Ferlan from comment #25)
> Some more digging w/r/t Comment 21 seems to be a bug caused by commit id
> 'a48c714115'.
> 
> The issue is that it doesn't seems that the removed code to determine
> whether the volume had qcow encryption:
> 
>    crypt_format = virReadBufInt32BE(buf +
>                                    
> fileTypeInfo[meta->format].qcowCryptOffset);
>    if (crypt_format && !meta->encryption &&
>        VIR_ALLOC(meta->encryption) < 0)
>        goto cleanup;
> 
> would be equivalent to the new code which is detecting encryption based upon
> the :
> 
>     } else if (info->modeOffset != -1) {
>         if (info->modeOffset >= len)
>             return false;
> 
>         if (buf[info->modeOffset] != info->modeValue)
>             return false;
> 
>         return true;
> 
> In particular, debugging shows "buf[info->modeOffset]" is 0, but if I
> replace the buf[] compare code with?
> 
>         crypt_format = virReadBufInt32BE(buf + info->modeOffset);
>         if (crypt_format != info->modeValue)
> ...
> 
> then the <encryption> is once again displayed for the qcow2 volume. 
> 
> BTW: There's a similar phenomena with a LUKS volume for pool-refresh... 
> Although for LUKS, just the <secret type='passphrase' uuid='$UUID'/> is not
> formatted.

Hi John, 
Since our test process will be done by end of September, and we're making a schedule. Do you think we can fix snapshot related issue in rhel7.3? Or do I need to open a new bug to track it in 7.4? as well as comment 25 issue. thx

Comment 27 John Ferlan 2016-09-09 10:39:49 UTC
There's a patch upstream for the comment 25 issue, see:

http://www.redhat.com/archives/libvir-list/2016-September/msg00180.html

It's the 2/2 of the series, where the 1/2 modifies the code for a similar refresh issue for the LUKS volume:

http://www.redhat.com/archives/libvir-list/2016-September/msg00179.html

Both have the same caveat that the either the secret uses the 'uuid' for lookup or if the 'usage' is supplied, then it must be the path to the volume (as documented). While these patches are relatively simple, I'd be hard pressed to call them release blockers as they're "annoyances" in the volume display. Perhaps more likely for them to make a z-stream release...

As for the snapshot issue, seems like it has no chance of resolution by the end of September. It's not just a luks issue...

In order to make progress here though - I'd say just generate new bzs.

Comment 28 yisun 2016-09-14 06:28:31 UTC
Verified with libvirt-2.0.0-8.el7.x86_64


SCENARIO 1: Check local luks volume can be created and used in vm
1.   prepare secret xml file
 # cat luks-secret.xml
      <secret ephemeral='no' private='yes'>
         <description>LUKS Sample Secret</description>
         <uuid>f981dd17-143f-45bc-88e6-ed1fe20ce9da</uuid>
         <usage type='volume'>
            <volume>/var/lib/libvirt/images/luks/luks_1.img</volume>
         </usage>
      </secret>

2.   define luks secret
# virsh secret-define luks-secret.xml
      Secret f52a81b2-424e-490c-823d-6bd4235bc57 created

3.  set value of the luks scret.
      # MYSECRET=`printf %s "redhat" | base64`
      # virsh secret-set-value f981dd17-143f-45bc-88e6-ed1fe20ce9da $MYSECRET
      Secret value set
4. prepare a dir pool
# virsh pool-dumpxml luks
<pool type='dir'>
  <name>luks</name>
  <uuid>0e20f159-2a41-435b-af31-b33993633ec6</uuid>
  <capacity unit='bytes'>53660876800</capacity>
  <allocation unit='bytes'>42532622336</allocation>
  <available unit='bytes'>11128254464</available>
  <source>
  </source>
  <target>
    <path>/var/lib/libvirt/images/luks</path>
    <permissions>
      <mode>0711</mode>
      <owner>0</owner>
      <group>0</group>
      <label>system_u:object_r:virt_image_t:s0</label>
    </permissions>
  </target>
</pool>

5. prepare a luks vol xlm
# cat luks_1.vol
<volume>
        <name>luks_1.img</name>
        <capacity unit='M'>1</capacity>
        <target>
          <path>/var/lib/libvirt/images/luks/luks_1.img</path>
          <format type='raw'/>
          <encryption format='luks'>
             <secret type='passphrase' uuid='4ff78f8c-6ee6-4a8d-b638-2b59d5d49279'/>
             <cipher name='twofish' size='128' mode='cbc' hash='sha256'/>
             <ivgen name='plain64' hash='sha1'/>        
          </encryption>        
         </target>
</volume>

# virsh vol-create luks luks_1.vol
Vol luks_1.img created from luks_1.vol

6. add the vol in a vm
#virsh edit test
...
    <disk type='file' device='disk'>
      <driver name='qemu' type='raw'/>
      <source file='/var/lib/libvirt/images/luks/luks_1.img'/>
      <target dev='vdb' bus='virtio'/>
      <encryption format='luks'>
        <secret type='passphrase' uuid='f981dd17-143f-45bc-88e6-ed1fe20ce9da'/>
      </encryption>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x0c' function='0x0'/>
    </disk>
...

7. start the vm, should have no error
8. login the vm, mkfs.ext4 the disk, mount it and create a file in it
vm# mkfs.ext4 /dev/vdb
vm#mount /dev/vdb /mnt
vm#echo "hello" > /mnt/test.txt
vm#umount /mnt

9. on host, use cryptsetup to decrypt the image
#cryptsetup luksOpen /var/lib/libvirt/images/luks/luks_1.img hehe

10. add the /dev/mapper/hehe device to another vm, and check it
#virsh edit vm1
...

    <disk type='block' device='disk'>
      <driver name='qemu' type='raw'/>
      <source dev='/dev/mapper/hehe'/>
      <target dev='vda' bus='virtio'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x0b' function='0x0'/>
    </disk>
...
#virsh start vm1
login vm:
vm# mount /dev/vda /mnt
vm# cat /mnt/test.txt
hello

SCENARIO 2: Install vm in luks disk and boot from it
1. prepare a luks vol xlm
# cat luks_1.vol
<volume>
        <name>luks_1.img</name>
        <capacity unit='G'>6</capacity>
        <target>
          <path>/var/lib/libvirt/images/luks/luks_1.img</path>
          <format type='raw'/>
          <encryption format='luks'>
             <secret type='passphrase' uuid='4ff78f8c-6ee6-4a8d-b638-2b59d5d49279'/>
             <cipher name='twofish' size='128' mode='cbc' hash='sha256'/>
             <ivgen name='plain64' hash='sha1'/>        
          </encryption>        
         </target>
</volume>

2. create a luks vol
# virsh vol-create luks luks_1.vol
Vol luks_1.img created from luks_1.vol

3. prepare a vm with following xml
...
  <os>
    <type arch='x86_64' machine='pc-i440fx-rhel7.3.0'>hvm</type>
    <kernel>/var/lib/libvirt/boot/vmlinuz</kernel>
    <initrd>/var/lib/libvirt/boot/initrd.img</initrd>
    <cmdline>inst.repo=http://download.eng.pek2.redhat.com//pub/rhel/nightly/RHEL-7.3-20160825.n.0/compose/Server/x86_64/os/</cmdline>
    <boot dev='hd'/>
  </os>
...
<device>
...
    <disk type='file' device='disk'>
      <driver name='qemu' type='raw'/>
      <source file='/var/lib/libvirt/images/luks/luks_2.img'/>
      <backingStore/>
      <target dev='vda' bus='virtio'/>
      <encryption format='luks'>
        <secret type='passphrase' uuid='4ff78f8c-6ee6-4a8d-b638-2b59d5d49279'/>
      </encryption>
      <alias name='virtio-disk0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/>
    </disk>
...
</device>

4. start the vm and install a os in luks vol
5. login vm and do some disk operation such as: #echo "hello world" > /tmp/1.txt

6. reboot the vm and login to check /tmp/1.txt still exist

7. edit vm's xml and remove
      <encryption format='luks'>
        <secret type='passphrase' uuid='4ff78f8c-6ee6-4a8d-b638-2b59d5d49279'/>
      </encryption>

8. reboot vm, see a "no bootable device" error.

SCENARIO 3: ISCSI luks
Prepare a iscsi server:

~# mkdir /luks

~# qemu-img create -f luks --object secret,id=sec0,data=`printf %s "redhat" | base64`,format=base64 -o key-secret=sec0 /luks/1.img 1G
Formatting '/luks/1.img', fmt=luks size=1073741824 key-secret=sec0

~# targetcli /backstores/fileio/ create device.luks /luks/1.img
Created fileio device.luks with size 1075810304

~# targetcli /iscsi/ create iqn.2016-08.com.virttest:luks.target

~# targetcli /iscsi/iqn.2016-08.com.virttest:luks.target/tpg1/luns/ create /backstores/fileio/device.luks

~# setenforce enforcing

~# targetcli /iscsi/iqn.2016-08.com.virttest:luks.target/tpg1/ set attribute authentication=0 demo_mode_write_protect=0 generate_node_acls=1 cache_dynamic_acls=1
~# targetcli / saveconfig

~# systemctl restart iscsid.service
On vm host:
1. # virsh edit rhel7.3
...
    <disk type='network' device='disk'>
      <driver name='qemu' type='raw'/>
      <source protocol='iscsi' name='iqn.2016-08.com.virttest:luks.target/0'>
        <host name='10.73.72.85' port='3260'/>
      </source>
      <target dev='vdb' bus='virtio'/>
      <encryption format='luks'>
        <secret type='passphrase' uuid='4ff78f8c-6ee6-4a8d-b638-2b59d5d49279'/>
      </encryption>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x09' function='0x0'/>
    </disk>
...

2. start the vm and check the qemu-kvm process
#virsh start rhel7.3
#ps -ef | grep qemu-kvm
...-drive file=iscsi://10.73.72.85:3260/iqn.2016-08.com.virttest%3Aluks.target/0,key-secret=virtio-disk1-luks-secret0,format=luks,if=none,id=drive-virtio-disk1...

3. login the vm
3.1 # mkfs.ext4 /dev/vdb
3.2 #mount /dev/vdb /mnt
3.3.#echo "hello world" > /mnt/1.txt
3.4.#halt

4. in vm host, check the newly added block device
# lsscsi
...
[36:0:0:0]   disk    LIO-ORG  device.luks      4.0   /dev/sdb
...

# qemu-img info /dev/sdb
image: /dev/sdb
file format: luks
virtual size: 1.0G (1073741824 bytes)
disk size: 0
encrypted: yes

5. start the vm and login:
5.1 #mount /dev/vdb /mnt
5.2 #cat /mnt/1.txt
hello world

6. migrate the vm to another host (need to prepare a secret on target host)
# virsh migrate rhel7.3 qemu+ssh://10.73.72.85/system --verbose --copy-storage-all --unsafe
Migration: [100 %]

7. in target host, check the vm is running and with correct disk info
#virsh dumpxml rhel7.3
   <disk type='network' device='disk'>
      <driver name='qemu' type='raw'/>
      <source protocol='iscsi' name='iqn.2016-08.com.virttest:luks.target/0'>
        <host name='10.73.72.85' port='3260'/>
      </source>
      <backingStore/>
      <target dev='vdb' bus='virtio'/>
      <encryption format='luks'>
        <secret type='passphrase' uuid='4ff78f8c-6ee6-4a8d-b638-2b59d5d49279'/>
      </encryption>
      <alias name='virtio-disk1'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x09' function='0x0'/>
    </disk>

8. login vm on target host and mount the disk, check the file still exist
#mount /dev/vdb /mnt
#cat /mnt/1.txt
hello world

SCENARIO 4: ceph luks
have a ceph cluster:
mon:10.73.75.52,osd1:10.73.75.41,osd2:10.73.75.54
1. prepare a luks encrypted image
# /usr/bin/qemu-img create -f luks --object secret,id=luks1.img_luks0,data=`printf %s "redhat" | base64`,format=base64 -o key-secret=luks1.img_luks0,cipher-alg=aes-128,cipher-mode=xts,hash-alg=md5,ivgen-alg=essiv,ivgen-hash-alg=md5 rbd:yisun-pool/ys2.img:mon_host=10.73.75.52 1G

# qemu-img info rbd:yisun-pool/ys2.img:mon_host=10.73.75.52
image: rbd:yisun-pool/ys2.img:mon_host=10.73.75.52
file format: luks
virtual size: 1.0G (1073741824 bytes)
disk size: unavailable
encrypted: yes


2. prepare a rbd pool
# virsh pool-dumpxml rbd
<pool type='rbd'>
  <name>rbd</name>
  <uuid>ab987a2a-e5c1-4b67-ad2f-ea2801541766</uuid>
  <capacity unit='bytes'>101880209408</capacity>
  <allocation unit='bytes'>132220</allocation>
  <available unit='bytes'>37518467072</available>
  <source>
    <host name='10.73.75.52' port='6789'/>
    <host name='10.73.75.41' port='6789'/>
    <host name='10.73.75.54' port='6789'/>
    <name>yisun-pool</name>
  </source>
</pool>

3. # virsh vol-list rbd
 Name                 Path                                    
------------------------------------------------------------------------------
 ys2.img              yisun-pool/ys2.img                    

4. add the volume in a vm as network virtual disk
#virsh edit virtlab_test_copy
...
    <disk type='network' device='disk'>
      <driver name='qemu' type='raw' cache='none'/>
      <source protocol='rbd' name='yisun-pool/ys2.img'>
        <host name='10.73.75.52' port='6789'/>
        <host name='10.73.75.41' port='6789'/>
        <host name='10.73.75.54' port='6789'/>
      </source>
      <backingStore/>
      <target dev='vdb' bus='virtio'/>
      <encryption format='luks'>
        <secret type='passphrase' uuid='4ff78f8c-6ee6-4a8d-b638-2b59d5d49279'/>
      </encryption>
      <alias name='virtio-disk1'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x09' function='0x0'/>
    </disk>
...

5. start the vm and login:
vm# mkfs.xfs /dev/vdb
vm# mount /dev/vdb /mnt
vm# echo "hello world" > /mnt/1.txt

6. reboot the vm and re-mount the disk, check the 1.txt still exists with content
vm# mount /dev/vdb /mnt
vm#cat /mnt/1.txt
hello world

make sure the image still luks encrypted
# qemu-img info rbd:yisun-pool/ys2.img:mon_host=10.73.75.52
image: rbd:yisun-pool/ys2.img:mon_host=10.73.75.52
file format: luks
virtual size: 1.0G (1073741824 bytes)
disk size: unavailable
encrypted: yes

7. migrate the vm to another host (need to prepare a secret on target host)
# virsh migrate virtlab_test_copy qemu+ssh://10.73.72.85/system --verbose --copy-storage-all --unsafe
Migration: [100 %]

8. in target host, check the vm is running and with correct disk info
#virsh dumpxml virtlab_test_copy
       <disk type='network' device='disk'>
      <driver name='qemu' type='raw'/>
      <source protocol='iscsi' name='iqn.2016-08.com.virttest:luks.target/0'>
        <host name='10.73.72.85' port='3260'/>
      </source>
      <backingStore/>
      <target dev='vdb' bus='virtio'/>
      <encryption format='luks'>
        <secret type='passphrase' uuid='4ff78f8c-6ee6-4a8d-b638-2b59d5d49279'/>
      </encryption>
      <alias name='virtio-disk1'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x0b' function='0x0'/>
    </disk>


9. login vm on target host and mount the disk, check the file still exist
#mount /dev/vdb /mnt
#cat /mnt/1.txt
hello world

10. use the volume as vol type virtual disk  (which is not supported yet)
#virsh edit virtlab_test_copy
...
    <disk type='volume' device='disk'>
      <driver name='qemu' type='raw'/>
      <source pool='rbd' volume='ys2.img'/>
      <target dev='hdk' bus='ide'/>
      <encryption format='luks'>
        <secret type='passphrase' uuid='4ff78f8c-6ee6-4a8d-b638-2b59d5d49279'/>
      </encryption>
      <address type='drive' controller='0' bus='1' target='0' unit='0'/>
    </disk>
...

# virsh start virtlab_test_copy
error: Failed to start domain virtlab_test_copy
error: unsupported configuration: using 'rbd' pools for backing 'volume' disks isn't yet supported

SCENARIO 5: virtual disk hotplug-unplug
In all below attached disks, I already create a 1.txt with content "hellow world"
1. rbd disk
1.1 # cat rbd.disk
      <disk type='network' device='disk'>
      <driver name='qemu' type='raw'/>
      <source protocol='iscsi' name='iqn.2016-08.com.virttest:luks.target/0'>
        <host name='10.73.72.85' port='3260'/>
      </source>
      <backingStore/>
      <target dev='vdb' bus='virtio'/>
      <encryption format='luks'>
        <secret type='passphrase' uuid='4ff78f8c-6ee6-4a8d-b638-2b59d5d49279'/>
      </encryption>
      <alias name='virtio-disk1'/>
    </disk>

1.2 # virsh attach-device virtlab_test_copy rbd.disk
Device attached successfully

1.3 login vm and check the disk:
vm# mount /dev/vdb /mnt
vm#cat /mnt/1.txt
hello world

1.4 hot unplug the disk
# virsh detach-device virtlab_test_copy rbd.disk
Device detached successfully

1.5 in guest, the disk disappear and xml of the disk not existing in vm xml any more
vm# lsblk
... attached disk gone
#virsh dumpxml virtlab_test_copy
... disk xml not there ...

2. iscsi disk
2.1 # cat iscsi.disk
    <disk type='network' device='disk'>
      <driver name='qemu' type='raw'/>
      <source protocol='iscsi' name='iqn.2016-08.com.virttest:luks.target/0'>
        <host name='10.73.72.85' port='3260'/>
      </source>
      <target dev='vdb' bus='virtio'/>
      <encryption format='luks'>
        <secret type='passphrase' uuid='4ff78f8c-6ee6-4a8d-b638-2b59d5d49279'/>
      </encryption>
    </disk>

2.2 # virsh attach-device virtlab_test_copy iscsi.disk
Device attached successfully

2.3 login vm and check the disk:
vm# mount /dev/vdb /mnt
vm#cat /mnt/1.txt
hello world

2.4 hot unplug the disk
# virsh detach-device virtlab_test_copy iscsi.disk
Device detached successfully

2.5 in guest, the disk disappear and xml of the disk not existing in vm xml any more
vm# lsblk
... attached disk gone
#virsh dumpxml virtlab_test_copy
... disk xml not there ...

3. local image
3.1 prepare a luks vol
# virsh vol-list luks
 Name                 Path                                    
------------------------------------------------------------------------------
 ...
luks_4.img           /var/lib/libvirt/images/luks/luks_4.img
...

# qemu-img info /var/lib/libvirt/images/luks/luks_4.img
image: /var/lib/libvirt/images/luks/luks_4.img
file format: luks
virtual size: 1.0G (1073741824 bytes)
disk size: 10M
encrypted: yes


3.2 # cat iscsi.disk
    <disk type='network' device='disk'>
      <driver name='qemu' type='raw'/>
      <source protocol='iscsi' name='iqn.2016-08.com.virttest:luks.target/0'>
        <host name='10.73.72.85' port='3260'/>
      </source>
      <target dev='vdb' bus='virtio'/>
      <encryption format='luks'>
        <secret type='passphrase' uuid='4ff78f8c-6ee6-4a8d-b638-2b59d5d49279'/>
      </encryption>
    </disk>

3.3 # virsh attach-device virtlab_test_copy local.disk
Device attached successfully


3.4 login vm and check the disk:
vm# mount /dev/vdb /mnt
vm#cat /mnt/1.txt
hello world

3.5 hot unplug the disk
# virsh detach-device virtlab_test_copy local.disk
Device detached successfully

3.6 in guest, the disk disappear and xml of the disk not existing in vm xml any more
vm# lsblk
... attached disk gone
#virsh dumpxml virtlab_test_copy
... disk xml not there ...

SCENARIO 6: vol operations
1. vol-resize:
# virsh vol-list luks --details
 Name        Path                                     Type  Capacity   Allocation
----------------------------------------------------------------------------------
...
 luks_4.img  /var/lib/libvirt/images/luks/luks_4.img  file  1.00 GiB  1023.13 MiB

# qemu-img info /var/lib/libvirt/images/luks/luks_4.img
image: /var/lib/libvirt/images/luks/luks_4.img
file format: luks
virtual size: 1.0G (1072689152 bytes)
disk size: 1.0G
encrypted: yes

# virsh vol-resize /var/lib/libvirt/images/luks/luks_4.img 2G
Size of volume 'luks_4.img' successfully changed to 2G

# qemu-img info /var/lib/libvirt/images/luks/luks_4.img
image: /var/lib/libvirt/images/luks/luks_4.img
file format: luks
virtual size: 2.0G (2146430976 bytes)
disk size: 1.0G
encrypted: yes

# virsh vol-resize /var/lib/libvirt/images/luks/luks_4.img 1G --shrink
Size of volume 'luks_4.img' successfully changed to 1G

# qemu-img info /var/lib/libvirt/images/luks/luks_4.img
image: /var/lib/libvirt/images/luks/luks_4.img
file format: luks
virtual size: 1.0G (1072689152 bytes)
disk size: 1.0G
encrypted: yes

use this block in vm, and do disk io
vm# mkfs.xfs /dev/vdb -f
vm# mount /dev/vdb /mnt
vm# dd if=/dev/urandom of=/mnt/bigfie bs=1M count=1024

2. vol-clone
# virsh vol-clone /var/lib/libvirt/images/luks/luks_4.img luks_5.img
error: Failed to clone vol from luks_4.img
error: unsupported configuration: storage pool does not support building encrypted volumes from other volumes

3. vol-download
# virsh vol-list luks --details
 Name          Path                                       Type  Capacity  Allocation
-------------------------------------------------------------------------------------
...
 luks_4.img    /var/lib/libvirt/images/luks/luks_4.img    file  1.00 GiB   10.30 MiB


# virsh vol-download /var/lib/libvirt/images/luks/luks_4.img newluks.img

#virsh edit virtlab_test_copy
...
    <disk type='volume' device='disk'>
      <driver name='qemu' type='raw'/>
      <source pool='luks' volume='newluks.img'/>
      <target dev='vdb' bus='virtio'/>
      <encryption format='luks'>
        <secret type='passphrase' uuid='4ff78f8c-6ee6-4a8d-b638-2b59d5d49279'/>
      </encryption>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x09' function='0x0'/>
    </disk>...

#virsh start virtlab_test_copy

vm# mount /dev/vdb /mnt
vm# cat /mnt/1.txt
hello world

4. vol-wipe
# cat luks_5.vol
<volume>
        <name>luks_5.img</name>
        <capacity unit='M'>1</capacity>
        <target>
          <path>/var/lib/libvirt/images/luks/luks_5.img</path>
          <format type='raw'/>
          <encryption format='luks'>
             <secret type='passphrase' uuid='4ff78f8c-6ee6-4a8d-b638-2b59d5d49279'/>
             <cipher name='aes' size='256' mode='cbc' hash='sha256'/>
             <ivgen name='plain64' hash='sha256'/>
          </encryption>        
</target>
</volume>

# virsh vol-create luks luks_5.vol
Vol luks_5.img created from luks_5.vol
#xxd /var/lib/libvirt/images/luks/luks_5.img | more
0000000: 4c55 4b53 babe 0001 6165 7300 0000 0000  LUKS....aes.....
0000010: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000020: 0000 0000 0000 0000 6362 632d 706c 6169  ........cbc-plai
0000030: 6e36 343a 7368 6132 3536 0000 0000 0000  n64:sha256......
0000040: 0000 0000 0000 0000 7368 6132 3536 0000  ........sha256..
...

# virsh vol-wipe /var/lib/libvirt/images/luks/luks_5.img
Vol /var/lib/libvirt/images/luks/luks_5.img wiped

# xxd /var/lib/libvirt/images/luks/luks_5.img | more
0000000: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000010: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000020: 0000 0000 0000 0000 0000 0000 0000 0000  ................
...

5. vol-info
# cat luks_5.vol
<volume>
        <name>luks_5.img</name>
        <capacity unit='M'>1</capacity>
        <target>
          <path>/var/lib/libvirt/images/luks/luks_5.img</path>
          <format type='raw'/>
          <encryption format='luks'>
             <secret type='passphrase' uuid='4ff78f8c-6ee6-4a8d-b638-2b59d5d49279'/>
             <cipher name='aes' size='256' mode='cbc' hash='sha256'/>
             <ivgen name='plain64' hash='sha256'/>
          </encryption>        
</target>
</volume>

# virsh vol-create luks luks_5.vol
Vol luks_5.img created from luks_5.vol

# virsh vol-info /var/lib/libvirt/images/luks/luks_5.img  --bytes
Name:           luks_5.img
Type:           file
Capacity:       2101248 bytes
Allocation:     135168 bytes

# qemu-img info /var/lib/libvirt/images/luks/luks_5.img
image: /var/lib/libvirt/images/luks/luks_5.img
file format: luks
virtual size: 1.0M (1048576 bytes)
disk size: 132K
encrypted: yes

<==== vol-info has wrong capacity, open a bz 1371892

SCENARIO 7: gluster luks
1. prepare a luks encrypted img
#qemu-img create -f luks --object secret,id=sec0,data=`printf %s "redhat" | base64`,format=base64 -o key-secret=sec0,cipher-alg=twofishes-192,cipher-mode=ecb,hash-alg=sha1,ivgen-alg=plain,ivgen-hash-alg=md5 1.img 1G

# qemu-img info gluster://10.66.5.88/gluster-vol1/luks_1.img
image: gluster://10.66.5.88/gluster-vol1/luks_1.img
file format: luks
virtual size: 1.0G (1073741824 bytes)
disk size: 136K
encrypted: yes

2. start a vm with network type virtual disk
#virsh edit virtlab_test_copy
...
    <disk type='network' device='disk'>
      <driver name='qemu' type='raw'/>
      <source protocol='gluster' name='gluster-vol1/luks_1.img'>
        <host name='10.66.5.88' port='24007'/>
      </source>
      <target dev='vdd' bus='virtio'/>
      <encryption format='luks'>
        <secret type='passphrase' uuid='4ff78f8c-6ee6-4a8d-b638-2b59d5d49279'/>
      </encryption>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x0a' function='0x0'/>
    </disk>
...

#virsh start virtlab_test_copy
 
3. login vm and check the disk:
vm#mkfs.xfs /dev/vdc
vm#mount /dev/vdc /mnt
vm#echo "hello world" > /mnt/1.txt

4. remove the disk's xml, destroy and restart the vm
#virsh edit virtlab_test_copy
<!-- remove the xml in step 2 -->

#virsh destroy virtlab_test_copy; virsh start virtlab_test_copy

5. hotplug and unplug the disk
#cat gluster.vol
# cat gluster.vol
    <disk type='network' device='disk'>
      <driver name='qemu' type='raw'/>
      <source protocol='gluster' name='gluster-vol1/luks_1.img'>
        <host name='10.66.5.88' port='24007'/>
      </source>
      <target dev='vdd' bus='virtio'/>
      <encryption format='luks'>
        <secret type='passphrase' uuid='4ff78f8c-6ee6-4a8d-b638-2b59d5d49279'/>
      </encryption>
    </disk>

# virsh attach-device virtlab_test_copy gluster.vol
Device attached successfully

login vm and check the disk has file 1.txt and its content is "hello world"

# virsh detach-device virtlab_test_copy gluster.vol
Device detached successfully

login vm and check the disk is gone

SCENARIO 8: nfs luks
1. prepare a nfs pool:
# virsh pool-dumpxml nfs
<pool type='netfs'>
  <name>nfs</name>
  <uuid>e97bb13f-3d20-4670-8087-127dc9a911e9</uuid>
  <capacity unit='bytes'>0</capacity>
  <allocation unit='bytes'>0</allocation>
  <available unit='bytes'>0</available>
  <source>
    <host name='10.73.194.27'/>
    <dir path='/vol/S3/libvirtmanual/yisun'/>
    <format type='auto'/>
  </source>
  <target>
    <path>/nfs</path>
  </target>
</pool>

2. prepare a vol xml
#cat luks_1.vol
<volume>
        <name>luks_1.img</name>
        <capacity unit='G'>1</capacity>
        <target>
          <path>/var/lib/libvirt/images/luks/luks_1.img</path>
          <format type='raw'/>
          <encryption format='luks'>
             <secret type='passphrase' uuid='4ff78f8c-6ee6-4a8d-b638-2b59d5d49279'/>
             <cipher name='aes' size='256' mode='cbc' hash='sha256'/>
             <ivgen name='plain64' hash='sha256'/>
          </encryption>
         </target>
</volume>

# virsh vol-create nfs luks_1.vol
Vol luks_1.img created from luks_1.vol

# qemu-img info /nfs/luks_1.img
image: /nfs/luks_1.img
file format: luks
virtual size: 1.0G (1073741824 bytes)
disk size: 140K
encrypted: yes

3. start a vm with this disk
#virsh dumpxml virtlab_test_copy
...
    <disk type='file' device='disk'>
      <driver name='qemu' type='raw'/>
      <source file='/nfs/luks_1.img'>
        <seclabel model='selinux' labelskip='yes'/>
      </source>
      <backingStore/>
      <target dev='vdd' bus='virtio'/>
      <encryption format='luks'>
        <secret type='passphrase' uuid='4ff78f8c-6ee6-4a8d-b638-2b59d5d49279'/>
      </encryption>
      <alias name='virtio-disk3'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x09' function='0x0'/>
    </disk>
...

4. login vm:
vm# mkfs.xfs /dev/vdb
vm# mount /dev/vdb /mnt
vm# echo "hello world" > /mnt/1.txt

5. #virsh destroy virtlab_test_copy
#virsh start virtlab_test_copy
login vm and check the file still exists
vm# mount /dev/vdb /mnt
vm# cat /mnt/1.txt
hello world

Scenario 9: block luks
1. create a luks encrypted block device
# qemu-img create -f luks --object secret,id=sec0,data=`printf %s "redhat" | base64`,format=base64 -o key-secret=sec0,cipher-alg=aes-256,cipher-mode=ecb,hash-alg=sha1,ivgen-alg=plain,ivgen-hash-alg=md5 /dev/sdb 5G
Formatting '/dev/sdb', fmt=luks size=5368709120 key-secret=sec0 cipher-alg=aes-256 cipher-mode=ecb ivgen-alg=plain ivgen-hash-alg=md5 hash-alg=sha1

# qemu-img info /dev/sdb
image: /dev/sdb
file format: luks
virtual size: 7.5G (8003252224 bytes)
disk size: 0
encrypted: yes

2. use this block in vm as a scsi disk
#virsh edit virtlab_test_copy
...
  <disk type='block' device='disk'>
      <driver name='qemu' type='raw'/>
      <source dev='/dev/sdb'/>
      <target dev='sdb' bus='scsi'/>
      <encryption format='luks'>
        <secret type='passphrase' uuid='4ff78f8c-6ee6-4a8d-b638-2b59d5d49279'/>
      </encryption>
      <address type='drive' controller='0' bus='0' target='0' unit='1'/>
    </disk>
...
 #virsh start virtlab_test_copy
 
3. login vm and check disk can be used
vm#v mount /dev/sdb /mnt
vm# echo "hello world" > /mnt/1.txt

4. remove the disk xml, destroy and start the vm again, test hot plug/unplug
#virsh destroy virtlab_test_copy; virsh start virtlab_test_copy

# cat block.vol
    <disk type='block' device='disk'>
      <driver name='qemu' type='raw'/>
      <source dev='/dev/sdb'/>
      <target dev='sdb' bus='scsi'/>
      <encryption format='luks'>
        <secret type='passphrase' uuid='4ff78f8c-6ee6-4a8d-b638-2b59d5d49279'/>
      </encryption>
    </disk>

# virsh attach-device virtlab_test_copy block.vol
Device attached successfully

login vm and check the disk can be used, and file 1.txt exists
vm# mount /dev/sdb /mnt
vm# cat /mnt/1.txt
hello world

# virsh detach-device virtlab_test_copy block.vol
Device detached successfully

login vm and the disk is gone.

Scenario 10: luks with snapshot

Comment 29 yisun 2016-09-14 08:38:07 UTC
main function of this RFE has been implemented, and some cross function issues will be tracked in new bugs:
Bug 1371892 - vol-info get incorrect size info for luks encrypted volume
Bug 1375855 - luks encryption not supported for snapshots' backing files
Bug 1371022 - Failed to migrate vm with copy-storage-all flag when using luks encrypted disk
Bug 1375870 - rbd pool should support vol-create a encrypted volume
Bug 1375887 - volume xml's encryption info lost after pool refreshed

So close this RFE as verified.

Comment 31 errata-xmlrpc 2016-11-03 18:36:22 UTC
Since the problem described in this bug report should be
resolved in a recent advisory, it has been closed with a
resolution of ERRATA.

For information on the advisory, and where to find the updated
files, follow the link below.

If the solution does not work for you, open a new bug report.

https://rhn.redhat.com/errata/RHSA-2016-2577.html

Comment 32 Jiri Belka 2017-02-27 09:34:00 UTC
(In reply to yisun from comment #28)
> Verified with libvirt-2.0.0-8.el7.x86_64
> ...
> Scenario 9: block luks
> 1. create a luks encrypted block device
> # qemu-img create -f luks --object secret,id=sec0,data=`printf %s "redhat" |
> base64`,format=base64 -o
> key-secret=sec0,cipher-alg=aes-256,cipher-mode=ecb,hash-alg=sha1,ivgen-
> alg=plain,ivgen-hash-alg=md5 /dev/sdb 5G
> Formatting '/dev/sdb', fmt=luks size=5368709120 key-secret=sec0
> cipher-alg=aes-256 cipher-mode=ecb ivgen-alg=plain ivgen-hash-alg=md5
> hash-alg=sha1

We could not use a logical storage pool? It seems not. Have you tried with a logical storage pool and then creating the volume via vol-create?

> # qemu-img info /dev/sdb
> image: /dev/sdb
> file format: luks
> virtual size: 7.5G (8003252224 bytes)
> disk size: 0
> encrypted: yes

Why is the size (ie. virtual size) different with size you gave it as argument for qemu-img? (IMO qemu-img should "detect" size of a block device, get space for LUKS payload and use the remaining for the volume data).
 
> 2. use this block in vm as a scsi disk
> #virsh edit virtlab_test_copy
> ...
>   <disk type='block' device='disk'>
>       <driver name='qemu' type='raw'/>
>       <source dev='/dev/sdb'/>
>       <target dev='sdb' bus='scsi'/>
>       <encryption format='luks'>
>         <secret type='passphrase'
> uuid='4ff78f8c-6ee6-4a8d-b638-2b59d5d49279'/>
>       </encryption>
>       <address type='drive' controller='0' bus='0' target='0' unit='1'/>
>     </disk>

It would be nice if libvirt could use LUKS on block device directly.