[libvirt] [PATCH v3 2/4] qemu: configurable remote display port boundaries

Martin Kletzander mkletzan at redhat.com
Mon Aug 13 13:21:23 UTC 2012


The defines QEMU_REMOTE_PORT_MIN and QEMU_REMOTE_PORT_MAX were used to
find free port when starting domains. As this was hard-coded to the
same ports as default VNC servers, there were races with these other
programs. This patch includes the possibility to change the default
starting port as well as the maximum port (mostly for completeness) in
qemu config file.

Support for two new config options in qemu.conf is added:
 - remote_port_min (defaults to QEMU_REMOTE_PORT_MIN and
   must be >= than this value)
 - remote_port_max (defaults to QEMU_REMOTE_PORT_MAX and
   must be <= than this value)
---
 src/qemu/libvirtd_qemu.aug         |    4 +++
 src/qemu/qemu.conf                 |   14 ++++++++++
 src/qemu/qemu_command.h            |    7 +++++
 src/qemu/qemu_conf.c               |   48 +++++++++++++++++++++++++++++++++++-
 src/qemu/qemu_conf.h               |    2 +
 src/qemu/qemu_driver.c             |   12 +++++---
 src/qemu/qemu_process.c            |   14 +++++-----
 src/qemu/test_libvirtd_qemu.aug.in |    2 +
 8 files changed, 90 insertions(+), 13 deletions(-)

diff --git a/src/qemu/libvirtd_qemu.aug b/src/qemu/libvirtd_qemu.aug
index 683aadb..b95d751 100644
--- a/src/qemu/libvirtd_qemu.aug
+++ b/src/qemu/libvirtd_qemu.aug
@@ -39,6 +39,9 @@ module Libvirtd_qemu =
                  | str_entry  "spice_tls_x509_cert_dir"
                  | str_entry "spice_password"

+   let remote_display_entry = int_entry "remote_display_port_min"
+                 | int_entry "remote_display_port_max"
+
    let security_entry = str_entry "security_driver"
                  | bool_entry "security_default_confined"
                  | bool_entry "security_require_confined"
@@ -72,6 +75,7 @@ module Libvirtd_qemu =
    (* Each enty in the config is one of the following three ... *)
    let entry = vnc_entry
              | spice_entry
+             | remote_display_entry
              | security_entry
              | save_entry
              | process_entry
diff --git a/src/qemu/qemu.conf b/src/qemu/qemu.conf
index ed4683c..bfdf351 100644
--- a/src/qemu/qemu.conf
+++ b/src/qemu/qemu.conf
@@ -140,6 +140,20 @@
 #spice_password = "XYZ12345"


+# Override the port for creating both VNC and SPICE sessions (min).
+# This defaults to 5900 and increases for consecutive sessions
+# or when ports are occupied, until it hits the maximum.
+#
+# Minimum must be greater than or equal to 5900 as lower number would
+# result into negative vnc display number.
+#
+# Maximum must be less than 65536, because higher numbers do not make
+# sense as a port number.
+#
+#remote_display_port_min = 5900
+#remote_display_port_max = 65535
+
+
 # The default security driver is SELinux. If SELinux is disabled
 # on the host, then the security driver will automatically disable
 # itself. If you wish to disable QEMU SELinux security driver while
diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
index 14afd9b..7c5e8dd 100644
--- a/src/qemu/qemu_command.h
+++ b/src/qemu/qemu_command.h
@@ -37,6 +37,13 @@
 # define QEMU_VIRTIO_SERIAL_PREFIX "virtio-serial"
 # define QEMU_FSDEV_HOST_PREFIX "fsdev-"

+/* These are only defaults, they can be changed now in qemu.conf and
+ * explicitely specified port is checked against these two (makes
+ * sense to limit the values).
+ *
+ * This limitation is mentioned in qemu.conf, so bear in mind that the
+ * configuration file should reflect any changes made to these values.
+ */
 # define QEMU_REMOTE_PORT_MIN  5900
 # define QEMU_REMOTE_PORT_MAX  65535

diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index b7db277..e1528af 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -1,7 +1,7 @@
 /*
  * qemu_conf.c: QEMU configuration management
  *
- * Copyright (C) 2006-2011 Red Hat, Inc.
+ * Copyright (C) 2006-2012 Red Hat, Inc.
  * Copyright (C) 2006 Daniel P. Berrange
  *
  * This library is free software; you can redistribute it and/or
@@ -38,6 +38,7 @@

 #include "virterror_internal.h"
 #include "qemu_conf.h"
+#include "qemu_command.h"
 #include "qemu_capabilities.h"
 #include "qemu_bridge_filter.h"
 #include "uuid.h"
@@ -89,6 +90,10 @@ int qemudLoadDriverConfig(struct qemud_driver *driver,
         virReportOOMError();
         return -1;
     }
+
+    driver->remotePortMin = QEMU_REMOTE_PORT_MIN;
+    driver->remotePortMax = QEMU_REMOTE_PORT_MAX;
+
     if (!(driver->vncTLSx509certdir = strdup(SYSCONFDIR "/pki/libvirt-vnc"))) {
         virReportOOMError();
         return -1;
@@ -263,6 +268,47 @@ int qemudLoadDriverConfig(struct qemud_driver *driver,
         }
     }

+    p = virConfGetValue (conf, "remote_display_port_min");
+    CHECK_TYPE ("remote_display_port_min", VIR_CONF_LONG);
+    if (p) {
+        if (p->l < QEMU_REMOTE_PORT_MIN) {
+            /* if the port is too low, we can't get the display name
+             * to tell to vnc (usually subtract 5900, e.g. localhost:1
+             * for port 5901) */
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("%s: remote_display_port_min: port must be greater than or equal to %d"),
+                            filename, QEMU_REMOTE_PORT_MIN);
+            virConfFree(conf);
+            return -1;
+        }
+        driver->remotePortMin = p->l;
+    }
+
+    p = virConfGetValue (conf, "remote_display_port_max");
+    CHECK_TYPE ("remote_display_port_max", VIR_CONF_LONG);
+    if (p) {
+        if (p->l > QEMU_REMOTE_PORT_MAX ||
+            p->l < driver->remotePortMin) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                            _("%s: remote_display_port_max: port must be between the minimal port and %d"),
+                            filename, QEMU_REMOTE_PORT_MAX);
+            virConfFree(conf);
+            return -1;
+        }
+        /* increasing the value by 1 makes all the loops going through
+        the bitmap (i = remotePortMin; i < remotePortMax; i++), work as
+        expected. */
+        driver->remotePortMax = p->l + 1;
+    }
+
+    if (driver->remotePortMin > driver->remotePortMax) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                        _("%s: remote_display_port_min: min port must not be greater than max port"),
+                        filename);
+        virConfFree(conf);
+        return -1;
+    }
+
     p = virConfGetValue (conf, "user");
     CHECK_TYPE ("user", VIR_CONF_STRING);
     if (!(user = strdup(p && p->str ? p->str : QEMU_USER))) {
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index 3895889..ea81b35 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -95,6 +95,8 @@ struct qemud_driver {
     char *spiceTLSx509certdir;
     char *spiceListen;
     char *spicePassword;
+    int remotePortMin;
+    int remotePortMax;
     char *hugetlbfs_mount;
     char *hugepage_path;

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 0d886c1..5a82e76 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -520,11 +520,6 @@ qemudStartup(int privileged) {
     if (!qemu_driver->domainEventState)
         goto error;

-    /* Allocate bitmap for vnc port reservation */
-    if ((qemu_driver->reservedRemotePorts =
-         virBitmapAlloc(QEMU_REMOTE_PORT_MAX - QEMU_REMOTE_PORT_MIN)) == NULL)
-        goto out_of_memory;
-
     /* read the host sysinfo */
     if (privileged)
         qemu_driver->hostsysinfo = virSysinfoRead();
@@ -650,6 +645,13 @@ qemudStartup(int privileged) {
     }
     VIR_FREE(driverConf);

+    /* Allocate bitmap for remote display port reservations. We cannot
+     * do this before the config is loaded properly, since the port
+     * numbers are configurable now */
+    if ((qemu_driver->reservedRemotePorts =
+         virBitmapAlloc(qemu_driver->remotePortMax - qemu_driver->remotePortMin)) == NULL)
+        goto out_of_memory;
+
     /* We should always at least have the 'nop' manager, so
      * NULLs here are a fatal error
      */
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 4c40b49..05b2f18 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -2454,15 +2454,15 @@ static int qemuProcessNextFreePort(struct qemud_driver *driver,
 {
     int i;

-    for (i = startPort ; i < QEMU_REMOTE_PORT_MAX; i++) {
+    for (i = startPort ; i < driver->remotePortMax; i++) {
         int fd;
         int reuse = 1;
         struct sockaddr_in addr;
         bool used = false;

         if (virBitmapGetBit(driver->reservedRemotePorts,
-                            i - QEMU_REMOTE_PORT_MIN, &used) < 0)
-            VIR_DEBUG("virBitmapGetBit failed on bit %d", i - QEMU_REMOTE_PORT_MIN);
+                            i - driver->remotePortMin, &used) < 0)
+            VIR_DEBUG("virBitmapGetBit failed on bit %d", i - driver->remotePortMin);

         if (used)
             continue;
@@ -2484,9 +2484,9 @@ static int qemuProcessNextFreePort(struct qemud_driver *driver,
             VIR_FORCE_CLOSE(fd);
             /* Add port to bitmap of reserved ports */
             if (virBitmapSetBit(driver->reservedRemotePorts,
-                                i - QEMU_REMOTE_PORT_MIN) < 0) {
+                                i - driver->remotePortMin) < 0) {
                 VIR_DEBUG("virBitmapSetBit failed on bit %d",
-                          i - QEMU_REMOTE_PORT_MIN);
+                          i - driver->remotePortMin);
             }
             return i;
         }
@@ -2507,11 +2507,11 @@ static void
 qemuProcessReturnPort(struct qemud_driver *driver,
                       int port)
 {
-    if (port < QEMU_REMOTE_PORT_MIN)
+    if (port < driver->remotePortMin)
         return;

     if (virBitmapClearBit(driver->reservedRemotePorts,
-                          port - QEMU_REMOTE_PORT_MIN) < 0)
+                          port - driver->remotePortMin) < 0)
         VIR_DEBUG("Could not mark port %d as unused", port);
 }

diff --git a/src/qemu/test_libvirtd_qemu.aug.in b/src/qemu/test_libvirtd_qemu.aug.in
index 959f250..eac5882 100644
--- a/src/qemu/test_libvirtd_qemu.aug.in
+++ b/src/qemu/test_libvirtd_qemu.aug.in
@@ -15,6 +15,8 @@ module Test_libvirtd_qemu =
 { "spice_tls" = "1" }
 { "spice_tls_x509_cert_dir" = "/etc/pki/libvirt-spice" }
 { "spice_password" = "XYZ12345" }
+{ "remote_display_port_min" = "5900" }
+{ "remote_display_port_max" = "65535" }
 { "security_driver" = "selinux" }
 { "security_default_confined" = "1" }
 { "security_require_confined" = "1" }
-- 
1.7.8.6




More information about the libvir-list mailing list