[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCH] qemu: Support setting the 'removable' flag for USB disks



This adds an attribute named 'removable' to the 'target' element of
disks, which controls the removable flag. For instance, on a Linux
guest it controls the value of /sys/block/$dev/removable. This option
is only valid for USB disks (i.e. bus='usb'), and its default value is
'off', which is the same behaviour as before.

To achieve this, 'removable=on' is appended to the '-device
usb-storage' parameter sent to qemu when adding a USB disk via
'-disk'. For versions of qemu only supporting '-usbdevice disk:' for
adding USB disks this feature always remains 'off' since there's no
support for passing such an option.

Bug: https://bugzilla.redhat.com/show_bug.cgi?id=922495
---
 docs/formatdomain.html.in                          |    8 +++--
 docs/schemas/domaincommon.rng                      |    8 +++++
 src/conf/domain_conf.c                             |   35 ++++++++++++++++++--
 src/conf/domain_conf.h                             |    9 +++++
 src/libvirt_private.syms                           |    1 +
 src/qemu/qemu_command.c                            |    6 ++++
 .../qemuxml2argv-disk-usb-device-removable.args    |    8 +++++
 .../qemuxml2argv-disk-usb-device-removable.xml     |   27 +++++++++++++++
 tests/qemuxml2argvtest.c                           |    2 ++
 9 files changed, 99 insertions(+), 5 deletions(-)
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-usb-device-removable.args
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-usb-device-removable.xml

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 8a3c3b7..384da4f 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -1498,9 +1498,13 @@
         removable disks (i.e. CDROM or Floppy disk), the value can be either
         "open" or "closed", defaults to "closed". NB, the value of
         <code>tray</code> could be updated while the domain is running.
-        <span class="since">Since 0.0.3; <code>bus</code> attribute since 0.4.3;
+        The optional attribute <code>removable</code> sets the
+        removable flag for USB disks, and its value can be either "on"
+        or "off", defaulting to "off". <span class="since">Since
+        0.0.3; <code>bus</code> attribute since 0.4.3;
         <code>tray</code> attribute since 0.9.11; "usb" attribute value since
-        after 0.4.4; "sata" attribute value since 0.9.7</span>
+        after 0.4.4; "sata" attribute value since 0.9.7; "removable" attribute
+        value since X.Y.Z</span>
       </dd>
       <dt><code>iotune</code></dt>
       <dd>The optional <code>iotune</code> element provides the
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 9792065..eab6aa3 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -1164,6 +1164,14 @@
           </choice>
         </attribute>
       </optional>
+      <optional>
+        <attribute name="removable">
+          <choice>
+            <value>on</value>
+            <value>off</value>
+          </choice>
+        </attribute>
+      </optional>
     </element>
   </define>
   <define name="geometry">
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 3278e9c..551bac3 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -709,6 +709,10 @@ VIR_ENUM_IMPL(virDomainDiskTray, VIR_DOMAIN_DISK_TRAY_LAST,
               "closed",
               "open");
 
+VIR_ENUM_IMPL(virDomainDiskRemovable, VIR_DOMAIN_DISK_REMOVABLE_LAST,
+              "on",
+              "off");
+
 VIR_ENUM_IMPL(virDomainNumatuneMemPlacementMode,
               VIR_DOMAIN_NUMATUNE_MEM_PLACEMENT_MODE_LAST,
               "default",
@@ -3996,6 +4000,7 @@ virDomainDiskDefParseXML(virCapsPtr caps,
     char *authUUID = NULL;
     char *usageType = NULL;
     char *tray = NULL;
+    char *removable = NULL;
     char *logical_block_size = NULL;
     char *physical_block_size = NULL;
     char *wwn = NULL;
@@ -4149,6 +4154,7 @@ virDomainDiskDefParseXML(virCapsPtr caps,
                 target = virXMLPropString(cur, "dev");
                 bus = virXMLPropString(cur, "bus");
                 tray = virXMLPropString(cur, "tray");
+                removable = virXMLPropString(cur, "removable");
 
                 /* HACK: Work around for compat with Xen
                  * driver in previous libvirt releases */
@@ -4556,6 +4562,24 @@ virDomainDiskDefParseXML(virCapsPtr caps,
             def->tray_status = VIR_DOMAIN_DISK_TRAY_CLOSED;
     }
 
+    if (removable) {
+        if ((def->removable = virDomainDiskRemovableTypeFromString(removable)) < 0) {
+            virReportError(VIR_ERR_XML_ERROR,
+                           _("unknown disk removable status '%s'"), removable);
+            goto error;
+        }
+
+        if (def->bus != VIR_DOMAIN_DISK_BUS_USB) {
+            virReportError(VIR_ERR_XML_ERROR, "%s",
+                           _("removable is only valid for usb disks"));
+            goto error;
+        }
+    } else {
+        if (def->bus == VIR_DOMAIN_DISK_BUS_USB) {
+            def->removable = VIR_DOMAIN_DISK_REMOVABLE_OFF;
+        }
+    }
+
     if (def->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY &&
         def->bus != VIR_DOMAIN_DISK_BUS_FDC) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
@@ -4754,6 +4778,7 @@ cleanup:
     VIR_FREE(target);
     VIR_FREE(source);
     VIR_FREE(tray);
+    VIR_FREE(removable);
     VIR_FREE(trans);
     while (nhosts > 0) {
         virDomainDiskHostDefFree(&hosts[nhosts - 1]);
@@ -12915,10 +12940,14 @@ virDomainDiskDefFormat(virBufferPtr buf,
     if ((def->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY ||
          def->device == VIR_DOMAIN_DISK_DEVICE_CDROM) &&
         def->tray_status != VIR_DOMAIN_DISK_TRAY_CLOSED)
-        virBufferAsprintf(buf, " tray='%s'/>\n",
+        virBufferAsprintf(buf, " tray='%s'",
                           virDomainDiskTrayTypeToString(def->tray_status));
-    else
-        virBufferAddLit(buf, "/>\n");
+    if (def->bus == VIR_DOMAIN_DISK_BUS_USB &&
+        def->removable != VIR_DOMAIN_DISK_REMOVABLE_OFF) {
+        virBufferAsprintf(buf, " removable='%s'",
+                          virDomainDiskRemovableTypeToString(def->removable));
+    }
+    virBufferAddLit(buf, "/>\n");
 
     /*disk I/O throttling*/
     if (def->blkdeviotune.total_bytes_sec ||
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 96f11ba..0f4f0d7 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -518,6 +518,13 @@ enum virDomainDiskTray {
     VIR_DOMAIN_DISK_TRAY_LAST
 };
 
+enum virDomainDiskRemovable {
+    VIR_DOMAIN_DISK_REMOVABLE_ON,
+    VIR_DOMAIN_DISK_REMOVABLE_OFF,
+
+    VIR_DOMAIN_DISK_REMOVABLE_LAST
+};
+
 enum  virDomainDiskGeometryTrans {
     VIR_DOMAIN_DISK_TRANS_DEFAULT = 0,
     VIR_DOMAIN_DISK_TRANS_NONE,
@@ -612,6 +619,7 @@ struct _virDomainDiskDef {
     char *src;
     char *dst;
     int tray_status;
+    int removable;
     int protocol;
     size_t nhosts;
     virDomainDiskHostDefPtr hosts;
@@ -2346,6 +2354,7 @@ VIR_ENUM_DECL(virDomainDiskIo)
 VIR_ENUM_DECL(virDomainDiskSecretType)
 VIR_ENUM_DECL(virDomainDiskSGIO)
 VIR_ENUM_DECL(virDomainDiskTray)
+VIR_ENUM_DECL(virDomainDiskRemovable)
 VIR_ENUM_DECL(virDomainIoEventFd)
 VIR_ENUM_DECL(virDomainVirtioEventIdx)
 VIR_ENUM_DECL(virDomainDiskCopyOnRead)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 5cad990..0d1a9d6 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -156,6 +156,7 @@ virDomainDiskIoTypeToString;
 virDomainDiskPathByName;
 virDomainDiskProtocolTransportTypeFromString;
 virDomainDiskProtocolTransportTypeToString;
+virDomainDiskRemovableTypeToString;
 virDomainDiskRemove;
 virDomainDiskRemoveByName;
 virDomainDiskTypeFromString;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 4891b65..c04cecf 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -3219,6 +3219,11 @@ qemuBuildDriveDevStr(virDomainDefPtr def,
     if (disk->product)
         virBufferAsprintf(&opt, ",product=%s", disk->product);
 
+    if (disk->bus == VIR_DOMAIN_DISK_BUS_USB &&
+        disk->removable != VIR_DOMAIN_DISK_REMOVABLE_OFF) {
+        virBufferAsprintf(&opt, ",removable=%s",
+                          virDomainDiskRemovableTypeToString(disk->removable));
+    }
     if (virBufferError(&opt)) {
         virReportOOMError();
         goto error;
@@ -9391,6 +9396,7 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr qemuCaps,
                     disk->type = VIR_DOMAIN_DISK_TYPE_FILE;
                 disk->device = VIR_DOMAIN_DISK_DEVICE_DISK;
                 disk->bus = VIR_DOMAIN_DISK_BUS_USB;
+                disk->removable = VIR_DOMAIN_DISK_REMOVABLE_OFF;
                 if (!(disk->dst = strdup("sda")) ||
                     VIR_REALLOC_N(def->disks, def->ndisks+1) < 0)
                     goto no_memory;
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-usb-device-removable.args b/tests/qemuxml2argvdata/qemuxml2argv-disk-usb-device-removable.args
new file mode 100644
index 0000000..36be080
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-usb-device-removable.args
@@ -0,0 +1,8 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M \
+pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -monitor \
+unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -usb -drive \
+file=/dev/HostVG/QEMUGuest1,if=none,id=drive-ide0-0-0 -device ide-drive,\
+bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0 -drive file=/tmp/usbdisk.img,\
+if=none,id=drive-usb-disk0 -device usb-storage,drive=drive-usb-disk0,\
+id=usb-disk0,removable=on -device virtio-balloon-pci,id=balloon0,bus=pci.0,\
+addr=0x3
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-usb-device-removable.xml b/tests/qemuxml2argvdata/qemuxml2argv-disk-usb-device-removable.xml
new file mode 100644
index 0000000..6ee3e9b
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-usb-device-removable.xml
@@ -0,0 +1,27 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>219136</memory>
+  <currentMemory unit='KiB'>219136</currentMemory>
+  <vcpu placement='static'>1</vcpu>
+  <os>
+    <type arch='i686' machine='pc'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu</emulator>
+    <disk type='block' device='disk'>
+      <source dev='/dev/HostVG/QEMUGuest1'/>
+      <target dev='hda' bus='ide'/>
+    </disk>
+    <disk type='file' device='disk'>
+      <source file='/tmp/usbdisk.img'/>
+      <target dev='sda' bus='usb' removable='on'/>
+    </disk>
+    <memballoon model='virtio'/>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index e76d844..2eca7ac 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -516,6 +516,8 @@ mymain(void)
     DO_TEST("disk-usb",  NONE);
     DO_TEST("disk-usb-device",
             QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG);
+    DO_TEST("disk-usb-device-removable",
+            QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG);
     DO_TEST("disk-scsi-device",
             QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG,
             QEMU_CAPS_SCSI_LSI);
-- 
1.7.10.4



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]