[Libvir] PATCH: Allow libvirtd configuration for QEMU VNC server

Daniel P. Berrange berrange at redhat.com
Thu Oct 11 21:52:13 UTC 2007


The QEMU VNC server spawned by the QEMU driver in libvirt is hardcoded to
start off on 127.0.0.1, unless the person creating a guest overides this in
the XML passed to libvirt. If wanting to setup off-host VNC access, it is
much much more convenient to be able to set the system wide default to be
0.0.0.0 than to specify 0.0.0.0 for each VM created. 

In addition, it is desirable to be able to configure use of TLS and x509
certificates for the VNC servers system wide.

In Xen world this is already possible through the /etc/xen/xend-config.sxp
configuration file.

In QEMU world, libvirtd takes the place of XenD. The /etc/libvirt/libvirtd.conf
file though is for the daemon as a whole. There is no config file for the 
QEMU driver in libvirt itself. So this patch extends the QEMU driver to be
able to load /etc/libvirt/qemu.conf and configure a handful of options.

  - vnc_listen = "0.0.0.0"   - the address for VNC to listen on. Defaults
                               to 127.0.0.1 for security sake
  - vnc_tls = 1              - turn on use of TLS extension
  - vnc_tls_x509_verify      - request client certificates for auth
  - vnc_tls_cert_dir         - the location of the VNC server certs.
                               Defaults to /etc/pki/libvirt-vnc

The code for building command line args for the -vnc flag to QEMU takes
care to look at these options & add approprivate syntax.

Dan.
-- 
|=- Red Hat, Engineering, Emerging Technologies, Boston.  +1 978 392 2496 -=|
|=-           Perl modules: http://search.cpan.org/~danberr/              -=|
|=-               Projects: http://freshmeat.net/~danielpb/               -=|
|=-  GnuPG: 7D3B9505   F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505  -=| 
-------------- next part --------------
Index: src/qemu_conf.c
===================================================================
RCS file: /data/cvs/libvirt/src/qemu_conf.c,v
retrieving revision 1.15
diff -u -p -r1.15 qemu_conf.c
--- src/qemu_conf.c	28 Sep 2007 20:47:58 -0000	1.15
+++ src/qemu_conf.c	11 Oct 2007 21:33:11 -0000
@@ -45,6 +45,7 @@
 #include "qemu_conf.h"
 #include "uuid.h"
 #include "buf.h"
+#include "conf.h"
 
 #define qemudLog(level, msg...) fprintf(stderr, msg)
 
@@ -66,6 +67,68 @@ void qemudReportError(virConnectPtr conn
                     NULL, NULL, NULL, -1, -1, errorMessage);
 }
 
+int qemudLoadDriverConfig(struct qemud_driver *driver,
+                          const char *filename) {
+    virConfPtr conf;
+    virConfValuePtr p;
+
+    /* Setup 2 critical defaults */
+    strcpy(driver->vncListen, "127.0.0.1");
+    if (!(driver->vncTLSx509certdir = strdup(SYSCONF_DIR "/pki/libvirt-vnc"))) {
+        qemudReportError(NULL, NULL, NULL, VIR_ERR_NO_MEMORY,
+                         "vncTLSx509certdir");
+        return -1;
+    }
+
+    /* Just check the file is readable before opening it, otherwise
+     * libvirt emits an error.
+     */
+    if (access (filename, R_OK) == -1) return 0;
+
+    conf = virConfReadFile (filename);
+    if (!conf) return 0;
+
+
+#define CHECK_TYPE(name,typ) if (p && p->type != (typ)) {               \
+        qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR,      \
+                         "remoteReadConfigFile: %s: %s: expected type " #typ "\n", \
+                         filename, (name));                             \
+        virConfFree(conf);                                              \
+        return -1;                                                      \
+    }
+
+    p = virConfGetValue (conf, "vnc_tls");
+    CHECK_TYPE ("vnc_tls", VIR_CONF_LONG);
+    if (p) driver->vncTLS = p->l;
+
+    p = virConfGetValue (conf, "vnc_tls_x509_verify");
+    CHECK_TYPE ("vnc_tls_x509_verify", VIR_CONF_LONG);
+    if (p) driver->vncTLSx509verify = p->l;
+
+    p = virConfGetValue (conf, "vnc_tls_x509_cert_dir");
+    CHECK_TYPE ("vnc_tls_x509_cert_dir", VIR_CONF_STRING);
+    if (p && p->str) {
+        free(driver->vncTLSx509certdir);
+        if (!(driver->vncTLSx509certdir = strdup(p->str))) {
+            qemudReportError(NULL, NULL, NULL, VIR_ERR_NO_MEMORY,
+                             "vncTLSx509certdir");
+            virConfFree(conf);
+            return -1;
+        }
+    }
+
+    p = virConfGetValue (conf, "vnc_listen");
+    CHECK_TYPE ("vnc_listen", VIR_CONF_STRING);
+    if (p && p->str) {
+        strncpy(driver->vncListen, p->str, sizeof(driver->vncListen));
+        driver->vncListen[sizeof(driver->vncListen)-1] = '\0';
+    }
+
+    virConfFree (conf);
+    return 0;
+}
+
+
 struct qemud_vm *qemudFindVMByID(const struct qemud_driver *driver, int id) {
     struct qemud_vm *vm = driver->vms;
 
@@ -1234,7 +1297,7 @@ static struct qemud_vm_def *qemudParseXM
             if (vnclisten && *vnclisten)
                 strncpy(def->vncListen, (char *)vnclisten, BR_INET_ADDR_MAXLEN-1);
             else
-                strcpy(def->vncListen, "127.0.0.1");
+                strcpy(def->vncListen, driver->vncListen);
             def->vncListen[BR_INET_ADDR_MAXLEN-1] = '\0';
             xmlFree(vncport);
             xmlFree(vnclisten);
@@ -1750,15 +1813,30 @@ int qemudBuildCommandLine(virConnectPtr 
     }
 
     if (vm->def->graphicsType == QEMUD_GRAPHICS_VNC) {
-        char vncdisplay[BR_INET_ADDR_MAXLEN+20];
+        char vncdisplay[PATH_MAX];
         int ret;
-        if (vm->qemuCmdFlags & QEMUD_CMD_FLAG_VNC_COLON)
-            ret = snprintf(vncdisplay, sizeof(vncdisplay), "%s:%d",
+
+        if (vm->qemuCmdFlags & QEMUD_CMD_FLAG_VNC_COLON) {
+            char options[PATH_MAX] = "";
+            if (driver->vncTLS) {
+                strcat(options, ",tls");
+                if (driver->vncTLSx509verify) {
+                    strcat(options, ",x509verify=");
+                } else {
+                    strcat(options, ",x509=");
+                }
+                strncat(options, driver->vncTLSx509certdir,
+                        sizeof(options) - (strlen(driver->vncTLSx509certdir)-1));
+                options[sizeof(options)-1] = '\0';
+            }
+            ret = snprintf(vncdisplay, sizeof(vncdisplay), "%s:%d%s",
                            vm->def->vncListen,
-                           vm->def->vncActivePort - 5900);
-        else
+                           vm->def->vncActivePort - 5900,
+                           options);
+        } else {
             ret = snprintf(vncdisplay, sizeof(vncdisplay), "%d",
                            vm->def->vncActivePort - 5900);
+        }
         if (ret < 0 || ret >= (int)sizeof(vncdisplay))
             goto error;
 
Index: src/qemu_conf.h
===================================================================
RCS file: /data/cvs/libvirt/src/qemu_conf.h,v
retrieving revision 1.9
diff -u -p -r1.9 qemu_conf.h
--- src/qemu_conf.h	21 Sep 2007 21:20:32 -0000	1.9
+++ src/qemu_conf.h	11 Oct 2007 21:33:11 -0000
@@ -289,6 +289,10 @@ struct qemud_driver {
     char *networkConfigDir;
     char *networkAutostartDir;
     char logDir[PATH_MAX];
+    int vncTLS : 1;
+    int vncTLSx509verify : 1;
+    char *vncTLSx509certdir;
+    char vncListen[BR_INET_ADDR_MAXLEN];
 };
 
 
@@ -311,6 +315,8 @@ void qemudReportError(virConnectPtr conn
     ATTRIBUTE_FORMAT(printf,5,6);
 
 
+int qemudLoadDriverConfig(struct qemud_driver *driver,
+                          const char *filename);
 
 struct qemud_vm *qemudFindVMByID(const struct qemud_driver *driver,
                                  int id);
Index: src/qemu_driver.c
===================================================================
RCS file: /data/cvs/libvirt/src/qemu_driver.c,v
retrieving revision 1.29
diff -u -p -r1.29 qemu_driver.c
--- src/qemu_driver.c	10 Oct 2007 19:46:17 -0000	1.29
+++ src/qemu_driver.c	11 Oct 2007 21:33:13 -0000
@@ -155,6 +155,7 @@ qemudStartup(void) {
     uid_t uid = geteuid();
     struct passwd *pw;
     char *base = NULL;
+    char driverConf[PATH_MAX];
 
     if (!(qemu_driver = calloc(1, sizeof(struct qemud_driver)))) {
         return -1;
@@ -167,7 +168,7 @@ qemudStartup(void) {
         if (snprintf(qemu_driver->logDir, PATH_MAX, "%s/log/libvirt/qemu", LOCAL_STATE_DIR) >= PATH_MAX)
             goto snprintf_error;
 
-        if ((base = strdup (SYSCONF_DIR "/libvirt/qemu")) == NULL)
+        if ((base = strdup (SYSCONF_DIR "/libvirt")) == NULL)
             goto out_of_memory;
     } else {
         if (!(pw = getpwuid(uid))) {
@@ -179,7 +180,7 @@ qemudStartup(void) {
         if (snprintf(qemu_driver->logDir, PATH_MAX, "%s/.libvirt/qemu/log", pw->pw_dir) >= PATH_MAX)
             goto snprintf_error;
 
-        if (asprintf (&base, "%s/.libvirt/qemu", pw->pw_dir) == -1) {
+        if (asprintf (&base, "%s/.libvirt", pw->pw_dir) == -1) {
             qemudLog (QEMUD_ERR, "out of memory in asprintf");
             goto out_of_memory;
         }
@@ -188,24 +189,36 @@ qemudStartup(void) {
     /* Configuration paths are either ~/.libvirt/qemu/... (session) or
      * /etc/libvirt/qemu/... (system).
      */
-    if (asprintf (&qemu_driver->configDir, "%s", base) == -1)
+    if (snprintf (driverConf, sizeof(driverConf), "%s/qemu.conf", base) == -1)
         goto out_of_memory;
+    driverConf[sizeof(driverConf)-1] = '\0';
 
-    if (asprintf (&qemu_driver->autostartDir, "%s/autostart", base) == -1)
+    if (asprintf (&qemu_driver->configDir, "%s/qemu", base) == -1)
         goto out_of_memory;
 
-    if (asprintf (&qemu_driver->networkConfigDir, "%s/networks", base) == -1)
+    if (asprintf (&qemu_driver->autostartDir, "%s/qemu/autostart", base) == -1)
         goto out_of_memory;
 
-    if (asprintf (&qemu_driver->networkAutostartDir, "%s/networks/autostart",
+    if (asprintf (&qemu_driver->networkConfigDir, "%s/qemu/networks", base) == -1)
+        goto out_of_memory;
+
+    if (asprintf (&qemu_driver->networkAutostartDir, "%s/qemu/networks/autostart",
                   base) == -1)
         goto out_of_memory;
 
-    if (qemudScanConfigs(qemu_driver) < 0)
+    free(base);
+
+    if (qemudLoadDriverConfig(qemu_driver, driverConf) < 0) {
         qemudShutdown();
+        return -1;
+    }
+
+    if (qemudScanConfigs(qemu_driver) < 0) {
+        qemudShutdown();
+        return -1;
+    }
     qemudAutostartConfigs(qemu_driver);
 
-    free(base);
     return 0;
 
  snprintf_error:


More information about the libvir-list mailing list