]> xenbits.xensource.com Git - people/liuw/libxenctrl-split/libvirt.git/commitdiff
qemu: Implement chardev hotplug on config level
authorMichal Privoznik <mprivozn@redhat.com>
Tue, 12 Mar 2013 14:59:25 +0000 (15:59 +0100)
committerMichal Privoznik <mprivozn@redhat.com>
Tue, 16 Jul 2013 09:47:39 +0000 (11:47 +0200)
There are two levels on which a device may be hotplugged: config
and live. The config level requires just an insert or remove from
internal domain definition structure, which is exactly what this
patch does. There is currently no implementation for a chardev
update action, as there's not much to be updated. But more
importantly, the only thing that can be updated is path or socket
address by which chardevs are distinguished. So the update action
is currently not supported.

src/conf/domain_conf.c
src/conf/domain_conf.h
src/libvirt_private.syms
src/qemu/qemu_driver.c
src/qemu/qemu_hotplug.c
src/qemu/qemu_hotplug.h

index 6ba1eea99bbf335742671cb667bb23f85ee054e6..5f7ef1952dc7db7045d423567213d3347afd32cc 100644 (file)
@@ -10099,7 +10099,7 @@ virDomainLeaseRemove(virDomainDefPtr def,
     return virDomainLeaseRemoveAt(def, idx);
 }
 
-static bool
+bool
 virDomainChrEquals(virDomainChrDefPtr src,
                    virDomainChrDefPtr tgt)
 {
@@ -18036,9 +18036,11 @@ virDomainDeviceDefCopy(virDomainDeviceDefPtr src,
     case VIR_DOMAIN_DEVICE_RNG:
         rc = virDomainRNGDefFormat(&buf, src->data.rng, flags);
         break;
+    case VIR_DOMAIN_DEVICE_CHR:
+        rc = virDomainChrDefFormat(&buf, src->data.chr, flags);
+        break;
     case VIR_DOMAIN_DEVICE_NONE:
     case VIR_DOMAIN_DEVICE_SMARTCARD:
-    case VIR_DOMAIN_DEVICE_CHR:
     case VIR_DOMAIN_DEVICE_MEMBALLOON:
     case VIR_DOMAIN_DEVICE_NVRAM:
     case VIR_DOMAIN_DEVICE_LAST:
index ef72d248303ac30eed33fee8be77c73b6e4ab7da..c26f4e2a44a5688f98d6ef5a1e12cd8c882b3673 100644 (file)
@@ -2399,6 +2399,9 @@ virDomainChrGetDomainPtrs(virDomainDefPtr vmdef,
 virDomainChrDefPtr
 virDomainChrFind(virDomainDefPtr def,
                  virDomainChrDefPtr target);
+bool
+virDomainChrEquals(virDomainChrDefPtr src,
+                   virDomainChrDefPtr tgt);
 int
 virDomainChrInsert(virDomainDefPtr vmdef,
                    virDomainChrDefPtr chr);
index 3c27041ed12987216b763f9d3e3fb7d748638677..fc4e750b536365a40d442da94cc0995660640db5 100644 (file)
@@ -115,6 +115,7 @@ virDomainChrConsoleTargetTypeToString;
 virDomainChrDefForeach;
 virDomainChrDefFree;
 virDomainChrDefNew;
+virDomainChrEquals;
 virDomainChrFind;
 virDomainChrGetDomainPtrs;
 virDomainChrInsert;
index 495867a50cf0fb1e3a600f35350667886dbc5d2a..852db8ba0e13f6a58bb8babe71f01cd6d3840d31 100644 (file)
@@ -6686,6 +6686,12 @@ qemuDomainAttachDeviceConfig(virQEMUCapsPtr qemuCaps,
             return -1;
         break;
 
+    case VIR_DOMAIN_DEVICE_CHR:
+        if (qemuDomainChrInsert(vmdef, dev->data.chr) < 0)
+            return -1;
+        dev->data.chr = NULL;
+        break;
+
     default:
          virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
                         _("persistent attach of device '%s' is not supported"),
@@ -6705,6 +6711,7 @@ qemuDomainDetachDeviceConfig(virDomainDefPtr vmdef,
     virDomainHostdevDefPtr hostdev, det_hostdev;
     virDomainLeaseDefPtr lease, det_lease;
     virDomainControllerDefPtr cont, det_cont;
+    virDomainChrDefPtr chr;
     int idx;
     char mac[VIR_MAC_STRING_BUFLEN];
 
@@ -6772,6 +6779,15 @@ qemuDomainDetachDeviceConfig(virDomainDefPtr vmdef,
 
         break;
 
+    case VIR_DOMAIN_DEVICE_CHR:
+        if (!(chr = qemuDomainChrRemove(vmdef, dev->data.chr)))
+            return -1;
+
+        virDomainChrDefFree(chr);
+        virDomainChrDefFree(dev->data.chr);
+        dev->data.chr = NULL;
+        break;
+
     default:
         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
                        _("persistent detach of device '%s' is not supported"),
index ac9350b0cf1a60e1141d36b7f36f586cb373691f..dc24ea4485e7b895c75592a403dbab038e79fbfb 100644 (file)
@@ -1172,6 +1172,78 @@ error:
 
 }
 
+int
+qemuDomainChrInsert(virDomainDefPtr vmdef,
+                    virDomainChrDefPtr chr)
+{
+    if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE &&
+        chr->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL) {
+        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
+                       _("attaching serial console is not supported"));
+        return -1;
+    }
+
+    if (virDomainChrFind(vmdef, chr)) {
+        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+                       _("chardev already exists"));
+        return -1;
+    }
+
+    if (virDomainChrInsert(vmdef, chr) < 0)
+        return -1;
+
+    /* Due to some crazy backcompat stuff, the first serial device is an alias
+     * to the first console too. If this is the case, the definition must be
+     * duplicated as first console device. */
+    if (vmdef->nserials == 1 && vmdef->nconsoles == 0) {
+        if ((!vmdef->consoles && VIR_ALLOC(vmdef->consoles) < 0) ||
+            VIR_ALLOC(vmdef->consoles[0]) < 0) {
+            virDomainChrRemove(vmdef, chr);
+            return -1;
+        }
+        vmdef->nconsoles = 1;
+
+        /* Create an console alias for the serial port */
+        vmdef->consoles[0]->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE;
+        vmdef->consoles[0]->targetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL;
+    }
+
+    return 0;
+}
+
+virDomainChrDefPtr
+qemuDomainChrRemove(virDomainDefPtr vmdef,
+                    virDomainChrDefPtr chr)
+{
+    virDomainChrDefPtr ret;
+    bool removeCompat;
+
+    if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE &&
+        chr->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL) {
+        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+                       _("detaching serial console is not supported"));
+        return NULL;
+    }
+
+    /* Due to some crazy backcompat stuff, the first serial device is an alias
+     * to the first console too. If this is the case, the definition must be
+     * duplicated as first console device. */
+    removeCompat = vmdef->nserials && vmdef->nconsoles &&
+        vmdef->consoles[0]->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE &&
+        vmdef->consoles[0]->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL &&
+        virDomainChrEquals(vmdef->serials[0], chr);
+
+    if (!(ret = virDomainChrRemove(vmdef, chr))) {
+        virReportError(VIR_ERR_INVALID_ARG, "%s",
+                       _("device not present in domain configuration"));
+            return NULL;
+    }
+
+    if (removeCompat)
+        VIR_DELETE_ELEMENT(vmdef->consoles, 0, vmdef->nconsoles);
+
+    return ret;
+}
 int qemuDomainAttachHostUsbDevice(virQEMUDriverPtr driver,
                                   virDomainObjPtr vm,
                                   virDomainHostdevDefPtr hostdev)
index da20eb1fe94840e1c54c686ad14e3e5ec00c2829..c947d56258197ac2088a4438addd786ef90a9829 100644 (file)
@@ -106,4 +106,11 @@ int qemuDomainDetachLease(virQEMUDriverPtr driver,
                           virDomainLeaseDefPtr lease);
 
 
+int
+qemuDomainChrInsert(virDomainDefPtr vmdef,
+                    virDomainChrDefPtr chr);
+virDomainChrDefPtr
+qemuDomainChrRemove(virDomainDefPtr vmdef,
+                    virDomainChrDefPtr chr);
+
 #endif /* __QEMU_HOTPLUG_H__ */