Bug 1147471

Summary: Ejecting locked cdrom tray using update-device fails but next try succeeds
Product: Red Hat Enterprise Linux 7 Reporter: hongming <honzhang>
Component: libvirtAssignee: Pavel Hrdina <phrdina>
Status: CLOSED ERRATA QA Contact: Virtualization Bugs <virt-bugs>
Severity: high Docs Contact:
Priority: unspecified    
Version: 7.1CC: dyuan, eblake, jdenemar, mzhan, rbalakri, weizhan, xuzhang, yanyang
Target Milestone: rc   
Target Release: ---   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: libvirt-1.2.17-2.el7 Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of:
: 1289069 (view as bug list) Environment:
Last Closed: 2015-11-19 05:53:33 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:    
Bug Blocks: 1289069    

Description hongming 2014-09-29 10:07:39 UTC
Description of problem:
Failed to update media device with RHEL7 guests using python-binding.It can be successfully updated using virsh. 

Version-Release number of selected component (if applicable):
qemu-kvm-rhev-2.1.2-1.el7.x86_64
libvirt-1.2.8-4.el7.x86_64
libvirt-python-1.2.8-3.el7.x86_64 

How reproducible:
100% 

Steps to Reproduce:
[root@libvirt-jenkins-test-01 libvirt-test-API]# python
Python 2.7.5 (default, Feb 11 2014, 07:46:25)
[GCC 4.8.2 20140120 (Red Hat 4.8.2-13)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import libvirt
>>> con = libvirt.open('')
>>> dom = con.lookupByName('virtlab_test')
>>> import os
>>> f = open('/tmp/cdrom.xml', 'r')
>>> devxml = f.read()
>>> f.close()
>>> print devxml
<disk type='file' device='cdrom'>
  <driver name='qemu' type='raw' cache='none'/>
  <source file='/tmp/cdrom.iso'/>
  <target dev='hdc' bus='ide' tray='open'/>
</disk>
>>> dom.updateDeviceFlags(devxml, 1)
libvirt: QEMU Driver error : internal error: unable to execute QEMU command 'eject': Device 'drive-ide0-1-0' is locked
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python2.7/site-packages/libvirt.py", line 2582, in updateDeviceFlags
    if ret == -1: raise libvirtError ('virDomainUpdateDeviceFlags() failed', dom=self)
libvirt.libvirtError: internal error: unable to execute QEMU command 'eject': Device 'drive-ide0-1-0' is locked

>>> quit()



[root@libvirt-jenkins-test-01 libvirt-test-API]# virsh list
 Id    Name                           State
----------------------------------------------------
 68    virtlab_test                   running

[root@libvirt-jenkins-test-01 libvirt-test-API]# cat /tmp/cdrom.xml
<disk type='file' device='cdrom'>
  <driver name='qemu' type='raw' cache='none'/>
  <source file='/tmp/cdrom.iso'/>
  <target dev='hdc' bus='ide' tray='open'/>
</disk>

[root@libvirt-jenkins-test-01 libvirt-test-API]# virsh update-device virtlab_test /tmp/cdrom.xml
Device updated successfully

Actual results:
Failed to update media device with RHEL7 guests using python-binding.

Expected results:
Successfully update devices 

Additional info:

Comment 2 Jiri Denemark 2014-11-06 14:14:59 UTC
In python, you called dom.updateDeviceFlags(devxml, 1), while the virsh command was virsh update-device virtlab_test /tmp/cdrom.xml. Strictly speaking these two are not equivalent. You either need to pass 0 flags (instead of 1) or add --live to the virsh command to make both approaches equivalent. However, --current will be transformed into --live when the domain is running, so this is not a big deal in fact.

Anyway, this has nothing to do with python bindings as I was able to reproduce this issue just using virsh. The strange thing is it's inconsistent. Running virsh update-device sometimes succeeds and sometimes fails. It seems like it fails for the first time complaining about a locked device but within a second or two QEMU sends DEVICE_TRAY_MOVED event saying the tray is opened. After this happens, update-device command succeeds but closes the tray so the next update-device fails again.

Comment 3 Eric Blake 2014-11-06 14:22:36 UTC
See also this thread where the qemu folks admitted their QMP commands suck, and where libvirt needs to be taught to try harder at ejecting CD-ROM disks:

https://www.redhat.com/archives/libvir-list/2014-October/msg00817.html

with a proposed solution to wait until the DEVICE_TRAY_MOVED event occurs to determine what happened on the first QMP attempt, and to have up to two QMP attempts per single libvirt API try.

Comment 4 Pavel Hrdina 2015-06-23 11:13:38 UTC
Upstream patch proposed:

https://www.redhat.com/archives/libvir-list/2015-June/msg01135.html

Comment 7 Yang Yang 2015-09-22 03:16:13 UTC
I can reproduce it, verify it with libvirt-1.2.17-9.el7.x86_64

Steps
1. prepare a running guest with boot.iso
<disk type='file' device='disk'>
      <driver name='qemu' type='qcow2'/>
      <source file='/var/lib/libvirt/images/rhel7.2.qcow2'/>
      <backingStore/>
      <target dev='vda' bus='virtio'/>
      <alias name='virtio-disk0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'/>
    </disk>
    <disk type='file' device='cdrom'>
      <driver name='qemu' type='raw' cache='none'/>
      <source file='/var/lib/libvirt/images/boot.iso'/>
      <backingStore/>
      <target dev='hdc' bus='ide'/>
      <readonly/>
      <alias name='ide0-1-0'/>
      <address type='drive' controller='0' bus='1' target='0' unit='0'/>
    </disk>

# cat /yy/cdrom1.xml 
<disk type='file' device='cdrom'>
<driver name='qemu' type='raw'/>
<source file='/var/lib/libvirt/images/bbb.iso'/>
<target dev='hdc' bus='ide'/>
</disk>

2. update-device with bbb.iso
# virsh update-device vm1 /yy/cdrom1.xml 
Device updated successfully

# virsh dumpxml vm1 | grep disk -a6
<disk type='file' device='disk'>
      <driver name='qemu' type='qcow2'/>
      <source file='/var/lib/libvirt/images/rhel7.2.qcow2'/>
      <backingStore/>
      <target dev='vda' bus='virtio'/>
      <alias name='virtio-disk0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'/>
    </disk>
    <disk type='file' device='cdrom'>
      <driver name='qemu' type='raw' cache='none'/>
      <source file='/var/lib/libvirt/images/bbb.iso'/>
      <backingStore/>
      <target dev='hdc' bus='ide'/>
      <readonly/>
      <alias name='ide0-1-0'/>
      <address type='drive' controller='0' bus='1' target='0' unit='0'/>
    </disk>

3. change-media with boot.iso
# virsh change-media vm1 hdc --update /var/lib/libvirt/images/boot.iso 
Successfully updated media.

# virsh dumpxml vm1 | grep disk -a6
<disk type='file' device='disk'>
      <driver name='qemu' type='qcow2'/>
      <source file='/var/lib/libvirt/images/rhel7.2.qcow2'/>
      <backingStore/>
      <target dev='vda' bus='virtio'/>
      <alias name='virtio-disk0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'/>
    </disk>
    <disk type='file' device='cdrom'>
      <driver name='qemu' type='raw' cache='none'/>
      <source file='/var/lib/libvirt/images/boot.iso'/>
      <backingStore/>
      <target dev='hdc' bus='ide'/>
      <readonly/>
      <alias name='ide0-1-0'/>
      <address type='drive' controller='0' bus='1' target='0' unit='0'/>
    </disk>

4. eject cdrom
# virsh change-media vm1 hdc --update
Successfully ejected media.

# virsh dumpxml vm1 | grep disk -a6
<disk type='file' device='disk'>
      <driver name='qemu' type='qcow2'/>
      <source file='/var/lib/libvirt/images/rhel7.2.qcow2'/>
      <backingStore/>
      <target dev='vda' bus='virtio'/>
      <alias name='virtio-disk0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'/>
    </disk>
    <disk type='file' device='cdrom'>
      <driver name='qemu' type='raw' cache='none'/>
      <backingStore/>
      <target dev='hdc' bus='ide' tray='open'/>
      <readonly/>
      <alias name='ide0-1-0'/>
      <address type='drive' controller='0' bus='1' target='0' unit='0'/>
    </disk>

5. insert cdrom
# virsh change-media vm1 hdc --insert /var/lib/libvirt/images/bbb.iso 
Successfully inserted media.

# virsh dumpxml vm1 | grep disk -a6
<disk type='file' device='disk'>
      <driver name='qemu' type='qcow2'/>
      <source file='/var/lib/libvirt/images/rhel7.2.qcow2'/>
      <backingStore/>
      <target dev='vda' bus='virtio'/>
      <alias name='virtio-disk0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'/>
    </disk>
    <disk type='file' device='cdrom'>
      <driver name='qemu' type='raw' cache='none'/>
      <source file='/var/lib/libvirt/images/bbb.iso'/>
      <backingStore/>
      <target dev='hdc' bus='ide'/>
      <readonly/>
      <alias name='ide0-1-0'/>
      <address type='drive' controller='0' bus='1' target='0' unit='0'/>
    </disk>

6. prepare a running guest with a cdrom without source
#  virsh dumpxml vm1 | grep disk -a6
<disk type='file' device='disk'>
      <driver name='qemu' type='qcow2'/>
      <source file='/var/lib/libvirt/images/rhel7.2.qcow2'/>
      <backingStore/>
      <target dev='vda' bus='virtio'/>
      <alias name='virtio-disk0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'/>
    </disk>
    <disk type='file' device='cdrom'>
      <driver name='qemu' type='raw' cache='none'/>
      <backingStore/>
      <target dev='sdc' bus='scsi'/>
      <readonly/>
      <alias name='scsi0-0-0-2'/>
      <address type='drive' controller='0' bus='0' target='0' unit='2'/>
    </disk>

7. insert cdrom
# virsh change-media vm1 sdc --insert /var/lib/libvirt/images/boot.iso 
Successfully inserted media.

#  virsh dumpxml vm1 | grep disk -a6
<disk type='file' device='disk'>
      <driver name='qemu' type='qcow2'/>
      <source file='/var/lib/libvirt/images/rhel7.2.qcow2'/>
      <backingStore/>
      <target dev='vda' bus='virtio'/>
      <alias name='virtio-disk0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'/>
    </disk>
    <disk type='file' device='cdrom'>
      <driver name='qemu' type='raw' cache='none'/>
      <source file='/var/lib/libvirt/images/boot.iso'/>
      <backingStore/>
      <target dev='sdc' bus='scsi'/>
      <readonly/>
      <alias name='scsi0-0-0-2'/>
      <address type='drive' controller='0' bus='0' target='0' unit='2'/>
    </disk>

update-device and change-media can be done once

Comment 9 errata-xmlrpc 2015-11-19 05:53:33 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/RHBA-2015-2202.html