]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu: improve detection of UNIX path generated by libvirt
authorPavel Hrdina <phrdina@redhat.com>
Thu, 11 May 2017 12:09:35 +0000 (14:09 +0200)
committerPavel Hrdina <phrdina@redhat.com>
Tue, 16 May 2017 09:33:49 +0000 (11:33 +0200)
Currently we consider all UNIX paths with specific prefix as generated
by libvirt, but that's a wrong assumption.  Let's make the detection
better by actually checking whether the whole path matches one of the
paths that we generate or generated in the past.

The UNIX path isn't stored in config XML since libvirt-1.3.1.

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1446980

Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
src/qemu/qemu_domain.c
tests/qemuxml2argvdata/qemuxml2argv-channel-unix-source-path.xml [new file with mode: 0644]
tests/qemuxml2xmloutdata/qemuxml2xmlout-channel-unix-source-path.xml [new file with mode: 0644]
tests/qemuxml2xmltest.c

index 7805b76808bd561785b154446c32fd94d67fc5d1..2264ccb56ff6426ff64d7514a000f764280d17ce 100644 (file)
@@ -3173,24 +3173,58 @@ qemuDomainDefaultNetModel(const virDomainDef *def,
 
 
 /*
- * Clear auto generated unix socket path, i.e., the one which starts with our
- * channel directory.
+ * Clear auto generated unix socket paths:
+ *
+ * libvirt 1.2.18 and older:
+ *     {cfg->channelTargetDir}/{dom-name}.{target-name}
+ *
+ * libvirt 1.2.19 - 1.3.2:
+ *     {cfg->channelTargetDir}/domain-{dom-name}/{target-name}
+ *
+ * libvirt 1.3.3 and newer:
+ *     {cfg->channelTargetDir}/domain-{dom-id}-{short-dom-name}/{target-name}
+ *
+ * The unix socket path was stored in config XML until libvirt 1.3.0.
+ * If someone specifies the same path as we generate, they shouldn't do it.
+ *
+ * This function clears the path for migration as well, so we need to clear
+ * the path even if we are not storing it in the XML.
  */
-static void
+static int
 qemuDomainChrDefDropDefaultPath(virDomainChrDefPtr chr,
                                 virQEMUDriverPtr driver)
 {
-    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
+    virQEMUDriverConfigPtr cfg;
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+    char *regexp = NULL;
+    int ret = -1;
 
-    if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL &&
-        chr->targetType == VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO &&
-        chr->source->type == VIR_DOMAIN_CHR_TYPE_UNIX &&
-        chr->source->data.nix.path &&
-        STRPREFIX(chr->source->data.nix.path, cfg->channelTargetDir)) {
-        VIR_FREE(chr->source->data.nix.path);
+    if (chr->deviceType != VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL ||
+        chr->targetType != VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO ||
+        chr->source->type != VIR_DOMAIN_CHR_TYPE_UNIX ||
+        !chr->source->data.nix.path) {
+        return 0;
     }
 
+    cfg = virQEMUDriverGetConfig(driver);
+
+    virBufferEscapeRegex(&buf, "^%s", cfg->channelTargetDir);
+    virBufferAddLit(&buf, "/([^/]+\\.)|(domain-[^/]+/)");
+    virBufferEscapeRegex(&buf, "%s$", chr->target.name);
+
+    if (virBufferCheckError(&buf) < 0)
+        goto cleanup;
+
+    regexp = virBufferContentAndReset(&buf);
+
+    if (virStringMatch(chr->source->data.nix.path, regexp))
+        VIR_FREE(chr->source->data.nix.path);
+
+    ret = 0;
+ cleanup:
+    VIR_FREE(regexp);
     virObjectUnref(cfg);
+    return ret;
 }
 
 
@@ -3458,8 +3492,10 @@ qemuDomainDeviceDefPostParse(virDomainDeviceDefPtr dev,
 
     /* clear auto generated unix socket path for inactive definitions */
     if ((parseFlags & VIR_DOMAIN_DEF_PARSE_INACTIVE) &&
-        dev->type == VIR_DOMAIN_DEVICE_CHR)
-        qemuDomainChrDefDropDefaultPath(dev->data.chr, driver);
+        dev->type == VIR_DOMAIN_DEVICE_CHR) {
+        if (qemuDomainChrDefDropDefaultPath(dev->data.chr, driver) < 0)
+            goto cleanup;
+    }
 
     /* forbid capabilities mode hostdev in this kind of hypervisor */
     if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV &&
@@ -4245,8 +4281,10 @@ qemuDomainDefFormatBuf(virQEMUDriverPtr driver,
             }
         }
 
-        for (i = 0; i < def->nchannels; i++)
-            qemuDomainChrDefDropDefaultPath(def->channels[i], driver);
+        for (i = 0; i < def->nchannels; i++) {
+            if (qemuDomainChrDefDropDefaultPath(def->channels[i], driver) < 0)
+                goto cleanup;
+        }
     }
 
  format:
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-channel-unix-source-path.xml b/tests/qemuxml2argvdata/qemuxml2argv-channel-unix-source-path.xml
new file mode 100644 (file)
index 0000000..42cb3c3
--- /dev/null
@@ -0,0 +1,29 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>219100</memory>
+  <vcpu placement='static'>1</vcpu>
+  <os>
+    <type arch='x86_64' machine='pc'>hvm</type>
+  </os>
+  <devices>
+    <emulator>/usr/bin/qemu-system-x86_64</emulator>
+    <channel type='unix'>
+      <source mode='bind' path='/tmp/channel/QEMUGuest1.org.qemu.guest_agent.0'/>
+      <target type='virtio' name='org.qemu.guest_agent.0'/>
+    </channel>
+    <channel type='unix'>
+      <source mode='bind' path='/tmp/channel/domain-QEMUGuest1/org.qemu.guest_agent.1'/>
+      <target type='virtio' name='org.qemu.guest_agent.1'/>
+    </channel>
+    <channel type='unix'>
+      <source mode='bind' path='/tmp/channel/domain-1-QEMUGuest1/org.qemu.guest_agent.2'/>
+      <target type='virtio' name='org.qemu.guest_agent.2'/>
+    </channel>
+    <channel type='unix'>
+      <source mode='bind' path='/tmp/channel/QEMUGuest1/org.qemu.guest_agent.3'/>
+      <target type='virtio' name='org.qemu.guest_agent.3'/>
+    </channel>
+    <memballoon model='none'/>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-channel-unix-source-path.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-channel-unix-source-path.xml
new file mode 100644 (file)
index 0000000..2d8fa1e
--- /dev/null
@@ -0,0 +1,45 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>219100</memory>
+  <currentMemory unit='KiB'>219100</currentMemory>
+  <vcpu placement='static'>1</vcpu>
+  <os>
+    <type arch='x86_64' 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-system-x86_64</emulator>
+    <controller type='usb' index='0'>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
+    </controller>
+    <controller type='pci' index='0' model='pci-root'/>
+    <controller type='virtio-serial' index='0'>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
+    </controller>
+    <channel type='unix'>
+      <target type='virtio' name='org.qemu.guest_agent.0'/>
+      <address type='virtio-serial' controller='0' bus='0' port='1'/>
+    </channel>
+    <channel type='unix'>
+      <target type='virtio' name='org.qemu.guest_agent.1'/>
+      <address type='virtio-serial' controller='0' bus='0' port='2'/>
+    </channel>
+    <channel type='unix'>
+      <target type='virtio' name='org.qemu.guest_agent.2'/>
+      <address type='virtio-serial' controller='0' bus='0' port='3'/>
+    </channel>
+    <channel type='unix'>
+      <source mode='bind' path='/tmp/channel/QEMUGuest1/org.qemu.guest_agent.3'/>
+      <target type='virtio' name='org.qemu.guest_agent.3'/>
+      <address type='virtio-serial' controller='0' bus='0' port='4'/>
+    </channel>
+    <input type='mouse' bus='ps2'/>
+    <input type='keyboard' bus='ps2'/>
+    <memballoon model='none'/>
+  </devices>
+</domain>
index 81d810537be8e5835818a530b602e1186ad0c957..f8a607ffc481acb908e9604e8ee1522372f00f11 100644 (file)
@@ -551,6 +551,8 @@ mymain(void)
     DO_TEST("channel-virtio", NONE);
     DO_TEST("channel-virtio-state", NONE);
 
+    DO_TEST_FULL("channel-unix-source-path", WHEN_INACTIVE, GIC_NONE, NONE);
+
     DO_TEST("hostdev-usb-address", NONE);
     DO_TEST("hostdev-pci-address", NONE);
     DO_TEST("hostdev-vfio", NONE);