]> xenbits.xensource.com Git - libvirt.git/commitdiff
qemu: Add the ability to hotplug the TLS X.509 environment
authorJohn Ferlan <jferlan@redhat.com>
Mon, 13 Jun 2016 16:30:34 +0000 (12:30 -0400)
committerJohn Ferlan <jferlan@redhat.com>
Fri, 9 Sep 2016 12:09:47 +0000 (08:09 -0400)
If the incoming XML defined a path to a TLS X.509 certificate environment,
add the necessary 'tls-creds-x509' object to the VIR_DOMAIN_CHR_TYPE_TCP
character device.

Likewise, if the environment exists the hot unplug needs adjustment as
well.  Note that all the return ret were changed to goto cleanup since
the cfg needs to be unref'd

Signed-off-by: John Ferlan <jferlan@redhat.com>
src/conf/domain_conf.h
src/qemu/qemu_command.c
src/qemu/qemu_command.h
src/qemu/qemu_hotplug.c
src/qemu/qemu_monitor_json.c

index 79dda1c321fc5d094e093d8b541fb0dfe5490ee5..3a559274872f0d3f7cb64edb456576e5b57f2b75 100644 (file)
@@ -1091,6 +1091,7 @@ struct _virDomainChrSourceDef {
             char *service;
             bool listen;
             int protocol;
+            bool tlscreds;
         } tcp;
         struct {
             char *bindHost;
index eb97d8d17c6e869e2ce3c6799e91cb9ba649d71e..8565d795e78b7c74ffc996d238af23b8e7035f0b 100644 (file)
@@ -690,7 +690,7 @@ qemuBuildRBDSecinfoURI(virBufferPtr buf,
  *
  * Returns 0 on success, -1 on failure with error set.
  */
-static int
+int
 qemuBuildTLSx509BackendProps(const char *tlspath,
                              bool listen,
                              bool verifypeer,
index 9b9ccb6e00831185146b8045368bfd7c8aea76fd..b7c59bb9e61e62f987ebbc4b329a5ce960b78e17 100644 (file)
@@ -60,10 +60,18 @@ virCommandPtr qemuBuildCommandLine(virQEMUDriverPtr driver,
                                    const char *domainLibDir)
     ATTRIBUTE_NONNULL(15);
 
+
 /* Generate the object properties for a secret */
 int qemuBuildSecretInfoProps(qemuDomainSecretInfoPtr secinfo,
                              virJSONValuePtr *propsret);
 
+/* Generate the object properties for a tls-creds-x509 */
+int qemuBuildTLSx509BackendProps(const char *tlspath,
+                                 bool listen,
+                                 bool verifypeer,
+                                 virQEMUCapsPtr qemuCaps,
+                                 virJSONValuePtr *propsret);
+
 /* Generate '-device' string for chardev device */
 int
 qemuBuildChrDeviceStr(char **deviceStr,
index d13474afcbfc81ea327984a179ab2bc2bdc89450..df374b1596c632850de9be9f7a61b01d47f839e0 100644 (file)
@@ -1644,12 +1644,17 @@ int qemuDomainAttachChrDevice(virQEMUDriverPtr driver,
                               virDomainChrDefPtr chr)
 {
     int ret = -1, rc;
+    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
     qemuDomainObjPrivatePtr priv = vm->privateData;
     virErrorPtr orig_err;
     virDomainDefPtr vmdef = vm->def;
     char *devstr = NULL;
+    virDomainChrSourceDefPtr dev = &chr->source;
     char *charAlias = NULL;
     bool chardevAttached = false;
+    bool tlsobjAdded = false;
+    virJSONValuePtr tlsProps = NULL;
+    char *tlsAlias = NULL;
     bool need_release = false;
 
     if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL &&
@@ -1673,7 +1678,29 @@ int qemuDomainAttachChrDevice(virQEMUDriverPtr driver,
     if (qemuDomainChrPreInsert(vmdef, chr) < 0)
         goto cleanup;
 
+    if (cfg->chardevTLS) {
+        if (qemuBuildTLSx509BackendProps(cfg->chardevTLSx509certdir,
+                                         dev->data.tcp.listen,
+                                         cfg->chardevTLSx509verify,
+                                         priv->qemuCaps,
+                                         &tlsProps) < 0)
+            goto cleanup;
+
+        if (!(tlsAlias = qemuAliasTLSObjFromChardevAlias(chr->info.alias)))
+            goto cleanup;
+        dev->data.tcp.tlscreds = true;
+    }
+
     qemuDomainObjEnterMonitor(driver, vm);
+    if (tlsAlias) {
+        rc = qemuMonitorAddObject(priv->mon, "tls-creds-x509",
+                                  tlsAlias, tlsProps);
+        tlsProps = NULL; /* qemuMonitorAddObject consumes */
+        if (rc < 0)
+            goto exit_monitor;
+        tlsobjAdded = true;
+    }
+
     if (qemuMonitorAttachCharDev(priv->mon, charAlias, &chr->source) < 0)
         goto exit_monitor;
     chardevAttached = true;
@@ -1693,12 +1720,17 @@ int qemuDomainAttachChrDevice(virQEMUDriverPtr driver,
         qemuDomainChrInsertPreAllocCleanup(vmdef, chr);
     if (ret < 0 && need_release)
         qemuDomainReleaseDeviceAddress(vm, &chr->info, NULL);
+    VIR_FREE(tlsAlias);
+    virJSONValueFree(tlsProps);
     VIR_FREE(charAlias);
     VIR_FREE(devstr);
+    virObjectUnref(cfg);
     return ret;
 
  exit_monitor:
     orig_err = virSaveLastError();
+    if (tlsobjAdded)
+        ignore_value(qemuMonitorDelObject(priv->mon, tlsAlias));
     /* detach associated chardev on error */
     if (chardevAttached)
         qemuMonitorDetachCharDev(priv->mon, charAlias);
@@ -4281,32 +4313,40 @@ int qemuDomainDetachChrDevice(virQEMUDriverPtr driver,
                               virDomainChrDefPtr chr)
 {
     int ret = -1;
+    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
     qemuDomainObjPrivatePtr priv = vm->privateData;
     virDomainDefPtr vmdef = vm->def;
     virDomainChrDefPtr tmpChr;
+    char *objAlias = NULL;
     char *devstr = NULL;
 
     if (!(tmpChr = virDomainChrFind(vmdef, chr))) {
         virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                        _("device not present in domain configuration"));
-        return ret;
+        goto cleanup;
     }
 
     if (!tmpChr->info.alias && qemuAssignDeviceChrAlias(vmdef, tmpChr, -1) < 0)
-        return ret;
+        goto cleanup;
 
     sa_assert(tmpChr->info.alias);
 
+    if (cfg->chardevTLS &&
+        !(objAlias = qemuAliasTLSObjFromChardevAlias(tmpChr->info.alias)))
+        goto cleanup;
+
     if (qemuBuildChrDeviceStr(&devstr, vmdef, chr, priv->qemuCaps) < 0)
-        return ret;
+        goto cleanup;
 
     qemuDomainMarkDeviceForRemoval(vm, &tmpChr->info);
 
     qemuDomainObjEnterMonitor(driver, vm);
-    if (devstr && qemuMonitorDelDevice(priv->mon, tmpChr->info.alias) < 0) {
-        ignore_value(qemuDomainObjExitMonitor(driver, vm));
-        goto cleanup;
-    }
+    if (devstr && qemuMonitorDelDevice(priv->mon, tmpChr->info.alias) < 0)
+        goto exit_monitor;
+
+    if (objAlias && qemuMonitorDelObject(priv->mon, objAlias) < 0)
+        goto exit_monitor;
+
     if (qemuDomainObjExitMonitor(driver, vm) < 0)
         goto cleanup;
 
@@ -4318,7 +4358,12 @@ int qemuDomainDetachChrDevice(virQEMUDriverPtr driver,
  cleanup:
     qemuDomainResetDeviceRemoval(vm);
     VIR_FREE(devstr);
+    virObjectUnref(cfg);
     return ret;
+
+ exit_monitor:
+    ignore_value(qemuDomainObjExitMonitor(driver, vm));
+    goto cleanup;
 }
 
 
index 8384314771f86ac2096522d53d670e757db686fb..de746f172ebfd6420f8de010c25e80d905ebbf6e 100644 (file)
@@ -6155,6 +6155,7 @@ qemuMonitorJSONAttachCharDevCommand(const char *chrID,
     virJSONValuePtr data = NULL;
     virJSONValuePtr addr = NULL;
     const char *backend_type = NULL;
+    char *tlsalias = NULL;
     bool telnet;
 
     if (!(backend = virJSONValueNewObject()) ||
@@ -6200,6 +6201,13 @@ qemuMonitorJSONAttachCharDevCommand(const char *chrID,
             virJSONValueObjectAppendBoolean(data, "telnet", telnet) < 0 ||
             virJSONValueObjectAppendBoolean(data, "server", chr->data.tcp.listen) < 0)
             goto error;
+        if (chr->data.tcp.tlscreds) {
+            if (!(tlsalias = qemuAliasTLSObjFromChardevAlias(chrID)))
+                goto error;
+
+            if (virJSONValueObjectAppendString(data, "tls-creds", tlsalias) < 0)
+                goto error;
+        }
         break;
 
     case VIR_DOMAIN_CHR_TYPE_UDP:
@@ -6265,6 +6273,7 @@ qemuMonitorJSONAttachCharDevCommand(const char *chrID,
     return ret;
 
  error:
+    VIR_FREE(tlsalias);
     virJSONValueFree(addr);
     virJSONValueFree(data);
     virJSONValueFree(backend);