RHEL Engineering is moving the tracking of its product development work on RHEL 6 through RHEL 9 to Red Hat Jira (issues.redhat.com). If you're a Red Hat customer, please continue to file support cases via the Red Hat customer portal. If you're not, please head to the "RHEL project" in Red Hat Jira and file new tickets here. Individual Bugzilla bugs in the statuses "NEW", "ASSIGNED", and "POST" are being migrated throughout September 2023. Bugs of Red Hat partners with an assigned Engineering Partner Manager (EPM) are migrated in late September as per pre-agreed dates. Bugs against components "kernel", "kernel-rt", and "kpatch" are only migrated if still in "NEW" or "ASSIGNED". If you cannot log in to RH Jira, please consult article #7032570. That failing, please send an e-mail to the RH Jira admins at rh-issues@redhat.com to troubleshoot your issue as a user management inquiry. The email creates a ServiceNow ticket with Red Hat. Individual Bugzilla bugs that are migrated will be moved to status "CLOSED", resolution "MIGRATED", and set with "MigratedToJIRA" in "Keywords". The link to the successor Jira issue will be found under "Links", have a little "two-footprint" icon next to it, and direct you to the "RHEL project" in Red Hat Jira (issue links are of type "https://issues.redhat.com/browse/RHEL-XXXX", where "X" is a digit). This same link will be available in a blue banner at the top of the page informing you that that bug has been migrated.
Bug 1540290 - libvirt needs to tolerate JSON backing store strings containing fields described as 'int' being a string in various cases
Summary: libvirt needs to tolerate JSON backing store strings containing fields descri...
Keywords:
Status: CLOSED ERRATA
Alias: None
Product: Red Hat Enterprise Linux 7
Classification: Red Hat
Component: libvirt
Version: 7.5
Hardware: x86_64
OS: Linux
high
high
Target Milestone: rc
: ---
Assignee: Peter Krempa
QA Contact: Meina Li
URL:
Whiteboard:
Depends On: 1534396
Blocks:
TreeView+ depends on / blocked
 
Reported: 2018-01-30 17:28 UTC by Peter Krempa
Modified: 2018-04-10 11:05 UTC (History)
23 users (show)

Fixed In Version: libvirt-3.9.0-10.el7
Doc Type: If docs needed, set a value
Doc Text:
Clone Of: 1534396
Environment:
Last Closed: 2018-04-10 11:04:21 UTC
Target Upstream Version:
Embargoed:


Attachments (Terms of Use)


Links
System ID Private Priority Status Summary Last Updated
Red Hat Product Errata RHEA-2018:0704 0 None None None 2018-04-10 11:05:38 UTC

Description Peter Krempa 2018-01-30 17:28:27 UTC
+++ This bug was initially created as a clone of Bug #1534396 +++

Description of problem:
The iscsi lun number in source name will be changed after guest restart with external snapshot.

Version-Release number of selected component (if applicable):
libvirt-3.9.0-7.el7.x86_64
qemu-kvm-rhev-2.10.0-15.el7.x86_64

How reproducible:
100%

Steps to Reproduce:
1. Prepare a guest with iscsi network disk.
# virsh dumpxml rhel7 | grep disk -a6
... <disk type='network' device='disk'>
     <driver name='qemu' type='qcow2'/>
     <source protocol='iscsi' name='iqn.2003-01.org.linux-iscsi.localhost.x8664:sn.9cba196611e6/2'>
       <host name='**IP**' port='3260'/>
       <auth username='redhat'>
         <secret type='iscsi' usage='libvirtiscsi'/>
       </auth>
     </source>
     <target dev='vda' bus='virtio'/>
     <alias name='virtio-disk0'/>
     <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
   </disk>...

2. Create external disk and check xml.
# for i in 1 2 3 4;do virsh snapshot-create-as rhel7 s$i --disk-only --diskspec vda,file=/tmp/rhel7.s$i;done
# virsh dumpxml rhel7 | grep disk -a12 
... <disk type='file' device='disk'>
     <driver name='qemu' type='qcow2'/>
     <source file='/tmp/rhel7.s4'/>
     <backingStore type='file' index='1'>
       <format type='qcow2'/>
       <source file='/tmp/rhel7.s3'/>
       <backingStore type='file' index='2'>
         <format type='qcow2'/>
         <source file='/tmp/rhel7.s2'/>
         <backingStore type='file' index='3'>
          <format type='qcow2'/>
           <source file='/tmp/rhel7.s1'/>
           <backingStore type='network' index='4'>
            <format type='qcow2'/>
             <source protocol='iscsi' name='iqn.2003-01.org.linux-iscsi.localhost.x8664:sn.9cba196611e6/2'>
               <host name='**IP**' port='3260'/>
             </source>
           </backingStore>...

3. Restart guest and check guest xml.
# virsh destroy rhel7
# virsh start rhel7
# virsh dumpxml rhel7 | grep disk -a12
... <disk type='file' device='disk'>
     <driver name='qemu' type='qcow2'/>
     <source file='/tmp/rhel7.s4'/>
         <backingStore type='file' index='2'>
          <format type='qcow2'/>
           <source file='/tmp/rhel7.s1'/>
           <backingStore type='network' index='3'>
            <format type='qcow2'/>
             <source protocol='iscsi' name='iqn.2003-01.org.linux-iscsi.localhost.x8664:sn.9cba196611e6/0'>     
               <host name='**IP**' port='3260'/>
             </source>                                                    --
           </backingStore>...

Actual results:
As above step 3.

Expected results:
# virsh dumpxml rhel7 | grep disk -a12
… <backingStore type='network' index='2'>
            <format type='qcow2'/>
             <source protocol='iscsi' name='iqn.2003-01.org.linux-iscsi.localhost.x8664:sn.9cba196611e6/2'>
               <host name='**IP**' port='3260'/>
             </source>
           </backingStore>...

Additional info:
After blockcommit/blockpull/blockcopy, it also will be changed.

--- Additional comment from Peter Krempa on 2018-01-25 13:49:02 CET ---

Could you please post output of 'qemu-img info /tmp/rhel7.s1' when that reproduces? it looks like we parse something wrong from the file on the disk

--- Additional comment from Meina Li on 2018-01-26 03:26:37 CET ---

After restart guest, check the info:
# qemu-img info /tmp/lmn.s1 -U  --backing-chain
image: /tmp/lmn.s1
file format: qcow2
virtual size: 5.0G (5368709120 bytes)
disk size: 196K
cluster_size: 65536
backing file: json:{"driver": "qcow2", "file": {"lun": "2", "portal": "**IP**:3260", "driver": "iscsi", "transport": "tcp", "target": "iqn.2003-01.org.linux-iscsi.localhost.x8664:sn.9cba196611e6"}}
backing file format: qcow2
Format specific information:
    compat: 1.1
    lazy refcounts: false
    refcount bits: 16
    corrupt: false

image: json:{"driver": "qcow2", "file": {"lun": "2", "portal": "**IP**:3260", "driver": "iscsi", "transport": "tcp", "target": "iqn.2003-01.org.linux-iscsi.localhost.x8664:sn.9cba196611e6"}}
file format: qcow2
virtual size: 5.0G (5368709120 bytes)
disk size: unavailable
cluster_size: 65536
Format specific information:
    compat: 1.1
    lazy refcounts: false
    refcount bits: 16
    corrupt: false

--- Additional comment from Peter Krempa on 2018-01-29 15:39:38 CET ---

Thanks for the information.

In the backing json string the 'lun' field is clearly a string:

json:{"driver": "qcow2", "file": {"lun": "2", "portal": "**IP**:3260", "driver": "iscsi", "transport": "tcp", "target": "iqn.2003-01.org.linux-iscsi.localhost.x8664:sn.9cba196611e6"}}

while the documentation in qemu (qapi/block-core.json) clearly states that 'lun' is an int:

{ 'struct': 'BlockdevOptionsIscsi',
  'data': { 'transport': 'IscsiTransport',
            'portal': 'str',
            'target': 'str',
            '*lun': 'int',
            '*user': 'str',
            '*password-secret': 'str',
            '*initiator-name': 'str',
            '*header-digest': 'IscsiHeaderDigest',
            '*timeout': 'int' } }


Libvirt is parsing it as an int and thus fails to find it and uses the default (0).


--- Additional comment from Kevin Wolf on 2018-01-30 16:45:57 CET ---

Well, nobody told libvirt to parse this string or that it matches the BlockdevOptionsIscsi structure... qemu accepts both strings and integers in json: strings because internally everything is converted into strings anyway (we're in the -drive legacy code path here, so no QAPI schema involved at all). Consequently, the generated json: strings treat all values as strings, too.

Maybe this can be improved by going through a real QAPI object using the keyval visitor, if we can assume that the content always actually contains everything that the schema requires. In that case you'd actually get JSON numbers for integers in the schema.

If that doesn't work and we actually need to use QAPI objects internally (which is something that we want, but it's really hard), don't hold your breath. It might be a few years then.

Either way, if libvirt parses the strings, it should probably accept both integers and strings as we won't be able to retroactively change all qemu versions from 2.1 where the feature was introduced.

--- Additional comment from Peter Krempa on 2018-01-30 18:25:53 CET ---

(In reply to Kevin Wolf from comment #7)
> Well, nobody told libvirt to parse this string or that it matches the
> BlockdevOptionsIscsi structure... qemu accepts both strings and integers in
> json: strings because internally everything is converted into strings anyway
> (we're in the -drive legacy code path here, so no QAPI schema involved at
> all). Consequently, the generated json: strings treat all values as strings,
> too.

Well the fact that we parse it is a result of qemu starting to put those strings into the backing store field in the qcow images. Libvirt uses those to reconstruct the backing chain and since there's no other documentation than the QAPI schema it makes sense that people will use it.

Okay I'll clone this BZ to fix the JSON parsers to accept both strings and numbers for the 'int' fields.

Comment 2 Peter Krempa 2018-01-31 11:47:24 UTC
Fixed upstream:

commit f46d6e22f2dc352cd43480c1d148222f4e62b8e6 
Author: Peter Krempa <pkrempa>
Date:   Wed Jan 31 12:00:42 2018 +0100

    util: storage: Parse 'lun' for iSCSI protocol from JSON as string or number
    
    While the QEMU QAPI schema describes 'lun' as a number, the code dealing
    with JSON strings does not strictly adhere to this schema and thus
    formats the number back as a string. Use the new helper to retrieve both
    possibilities.
    
    Note that the formatting code is okay and qemu will accept it as an int.
    
    Tweak also one of the test strings to verify that both formats work
    with libvirt.
    
    Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1540290

commit d3da8013cc11d6a10d4a4146bcbb0a7e34523fa5
Author: Peter Krempa <pkrempa>
Date:   Wed Jan 31 11:54:31 2018 +0100

    util: json: Add helper to return string or number properties as string
    
    The helper is useful in cases when the JSON we have to parse may contain
    one of the two due to historical reasons and the number value itself
    would be stored as a string.

Comment 5 Meina Li 2018-02-02 05:30:09 UTC
Verified on libvirt-3.9.0-10.el7.x86_64.
The result is expected and move it to verified.

Scenario 1: restart guest 
1. Prepare a guest with iscsi network disk.
# virsh dumpxml rhel7 | grep “<disk” -a8
    <disk type='network' device='disk'>
      <driver name='qemu' type='qcow2'/>
      <source protocol='iscsi' name='iqn.2003-01.org.linux-iscsi.intel-e5530-8-1.x8664:sn.135b6ed5e6b2/2'>
        <host name='**IP**' port='3260'/>
      </source>
      <target dev='vda' bus='virtio'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/>
    </disk>

2. Create external disk, check xml and qemu-img info.
# for i in 1 2 3 4;do virsh snapshot-create-as rhel7 s$i --disk-only --diskspec vda,file=/tmp/rhel7.s$i;done
# virsh dumpxml rhel7 | grep “<disk” -a20
    <disk type='file' device='disk'>
      <driver name='qemu' type='qcow2'/>
      <source file='/tmp/rhel7.s4'/>
      <backingStore type='file' index='1'>
        <format type='qcow2'/>
        <source file='/tmp/rhel7.s3'/>
        <backingStore type='file' index='2'>
          <format type='qcow2'/>
          <source file='/tmp/rhel7.s2'/>
          <backingStore type='file' index='3'>
            <format type='qcow2'/>
            <source file='/tmp/rhel7.s1'/>
            <backingStore type='network' index='4'>
              <format type='qcow2'/>
              <source protocol='iscsi' name='iqn.2003-01.org.linux-iscsi.intel-e5530-8-1.x8664:sn.135b6ed5e6b2/2'>
                <host name='**IP**' port='3260'/>
              </source>
            </backingStore>
          </backingStore>
        </backingStore>
      </backingStore>
# qemu-img info /tmp/rhel7.s4 -U --backing-chain | grep "backing file:"
backing file: /tmp/rhel7.s3
backing file: /tmp/rhel7.s2
backing file: /tmp/rhel7.s1
backing file: json:{"driver": "qcow2", "file": {"lun": "2", "portal": "**IP**", "driver": "iscsi", "transport": "tcp", "target": "iqn.2003-01.org.linux-iscsi.intel-e5530-8-1.x8664:sn.135b6ed5e6b2"}}

3. Restart guest and check guest xml.
# virsh destroy rhel7
# virsh start rhel7
# virsh dumpxml rhel7 | grep “<disk” -a20
# qemu-img info /tmp/rhel7.s4 -U --backing-chain | grep "backing file:"
--------the actual result is same with step 2, as expected result-------------

4. Restart libvirtd, check guest xml and qemu-img info.
# systemctl restart libvirtd
# virsh dumpxml rhel7 | grep “<disk” -a20
# qemu-img info /tmp/rhel7.s4 -U --backing-chain | grep "backing file:"
--------the actual result is same with step 2, as expected result-------------

Scenario 2: Do blockcommit.
1. Repeat step 1~step 2 in Scenario 1.
2. Do blockcommit from top to middle.
# virsh blockcommit rhel7 vda --base vda[2] --active --verbose --wait --pivot
Block commit: [100 %]
Successfully pivoted
# virsh dumpxml rhel7 | grep "iscsi" -a2
      <backingStore type='network' index='2'>
        <format type='qcow2'/>
        <source protocol='iscsi' name='iqn.2003-01.org.linux-iscsi.intel-e5530-8-1.x8664:sn.135b6ed5e6b2/2'>
          <host name='**IP**' port='3260'/>
        </source>

3. Do blockcommit from top to base.
# virsh blockcommit rhel7 vda --active --verbose --wait --pivot
Block commit: [100 %]
Successfully pivoted
# virsh dumpxml rhel7 | grep "iscsi" -a2
    <disk type='network' device='disk'>
      <driver name='qemu' type='qcow2'/>
      <source protocol='iscsi' name='iqn.2003-01.org.linux-iscsi.intel-e5530-8-1.x8664:sn.135b6ed5e6b2/2'>
        <host name='**IP**' port='3260'/>
      </source>


Scenario 3: Do blockpull and blockcopy with --shallow.
1. Repeat step 1~step 2 in Scenario 1.

2. Do blockpull from middle to top.
# virsh blockpull rhel7 vda --base vda[2] --wait --verbose
Block Pull: [100 %]
Pull complete
# virsh dumpxml rhel7 | grep "iscsi" -a2
      <backingStore type='network' index='3'>
        <format type='qcow2'/>
        <source protocol='iscsi' name='iqn.2003-01.org.linux-iscsi.intel-e5530-8-1.x8664:sn.135b6ed5e6b2/2'>
          <host name='**IP**' port='3260'/>
        </source>

3. Do blockcopy with --shallow.
# virsh blockcopy rhel7 vda /tmp/rhel7.copy --wait --verbose --transient-job --shallow
Block Copy: [100 %]
Now in mirroring phase
# virsh dumpxml rhel7 | grep "iscsi" -a2
          <backingStore type='network' index='3'>
            <format type='qcow2'/>
            <source protocol='iscsi' name='iqn.2003-01.org.linux-iscsi.intel-e5530-8-1.x8664:sn.135b6ed5e6b2/2'>
              <host name='**IP**' port='3260'/>
            </source>

Comment 9 errata-xmlrpc 2018-04-10 11:04:21 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://access.redhat.com/errata/RHEA-2018:0704


Note You need to log in before you can comment on or make changes to this bug.