[libvirt] PATCH: 5/5: Preserve live XML config across restarts

Daniel P. Berrange berrange at redhat.com
Tue Jul 15 14:15:40 UTC 2008


Although the LXC driver can cope with libvirtd restarts, there is one
small problem relating to the XML format. The XML format as stored in
/etc/libvirtd/lxc/NAME.xml is the canonical 'inactive' configuration
data. There are a few pieces of data which are filled in at runtime,
such as the current /dev/pty/XXX path, and vethXXX inteface name.
Previously, the LXC drive would re-write /etc/libvirtd/lxc/NAME.xml
to add in this data, but this is not good practice. Even though we
tell sysadmins not to change this files directly, many people do, and
this obliterates data important to libvirt.

The 'controller' process however knows what the live config data is
since it has a copy of the virDomainDefPtr object from when it was
started up. The controller process stays around even across restarts
of the libvirtd daemon. So this patch updates the handshake between
the libvirtd LXC driver  & controller, so that as well as sending
back the PID, it also sends back the live XML configuration. So when
starting up, libvirtd can get back a guarenteed accurate XML doc for
the current live container config.

I'm not entirely happy with this approach though - I'd ideally like
to avoid having communications between the libvirtd & the controller
process if practical, because it forms an ABI we have to preserve
across daemon upgrades. So I'm sort of inclined to change this so
that the 'live' XML config and PID are simply kept on disk in the
paths /var/run/libvirt/lxc/NAME.{xml,pid} alongside the UNIX socket,
and then just keep the UNIX socket connection as a way for getting
notification of container shutdown (via POLLHUP).

 domain_conf.c    |    6 +----
 lxc_controller.c |   66 ++++++++++++++++++++++++++++++++++++++++++++++++++-----
 lxc_controller.h |    1 
 lxc_driver.c     |   20 ++++++++++++++++
 4 files changed, 83 insertions(+), 10 deletions(-)

Daniel

diff -r 33a641a0a0d9 src/domain_conf.c
--- a/src/domain_conf.c	Mon Jul 14 21:34:07 2008 +0100
+++ b/src/domain_conf.c	Tue Jul 15 11:35:10 2008 +0100
@@ -1078,13 +1078,11 @@
         break;
 
     case VIR_DOMAIN_CHR_TYPE_PTY:
-        /* @path attribute is an output only property - pty is auto-allocted */
-        break;
-
     case VIR_DOMAIN_CHR_TYPE_DEV:
     case VIR_DOMAIN_CHR_TYPE_FILE:
     case VIR_DOMAIN_CHR_TYPE_PIPE:
-        if (path == NULL) {
+        if (path == NULL &&
+            def->type != VIR_DOMAIN_CHR_TYPE_PTY) {
             virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
                                  "%s", _("Missing source path attribute for char device"));
             goto error;
diff -r 33a641a0a0d9 src/lxc_controller.c
--- a/src/lxc_controller.c	Mon Jul 14 21:34:07 2008 +0100
+++ b/src/lxc_controller.c	Tue Jul 15 11:35:10 2008 +0100
@@ -54,6 +54,55 @@
         return -1;
 
     return pid;
+}
+
+char *lxcControllerLiveConfig(int monitor)
+{
+    unsigned int len;
+    char *data;
+
+    if (saferead(monitor, &len, sizeof(len)) != sizeof(len))
+        return NULL;
+
+    /* Refuse stupid size allocations */
+    if (len > (1024 * 1024))
+        return NULL;
+
+    if (VIR_ALLOC_N(data, len+1) < 0)
+        return NULL;
+
+    if (saferead(monitor, data, len) != len) {
+        VIR_FREE(data);
+        return NULL;
+    }
+    data[len] = '\0';
+    printf("[%s]\n", data);
+    return data;
+}
+
+
+static int lxcControllerSendGreeting(int client,
+                                     virDomainDefPtr def)
+{
+    pid_t pid = getpid();
+    char *xml;
+    int ret = -1;
+    unsigned int len;
+
+    /* Sync up with libvirtd LXC driver to tell it our PID */
+    if (safewrite(client, &pid, sizeof(pid)) != sizeof(pid))
+        return -1;
+
+    if (!(xml = virDomainDefFormat(NULL, def, VIR_DOMAIN_XML_SECURE)))
+        return -1;
+
+    len = strlen(xml);
+    if (safewrite(client, &len, sizeof(len)) == sizeof(len) &&
+        safewrite(client, xml, len) == len)
+        ret = 0;
+    VIR_FREE(xml);
+
+    return ret;
 }
 
 /**
@@ -110,7 +159,8 @@
  *
  * Returns 0 on success or -1 in case of error
  */
-static int lxcControllerMain(int monitor,
+static int lxcControllerMain(virDomainDefPtr def,
+                             int monitor,
                              int client,
                              int appPty,
                              int contPty)
@@ -178,13 +228,11 @@
             fprintf(stderr, "%d %d\n", epollEvent.data.fd, epollEvent.events);
             if (epollEvent.data.fd == monitor) {
                 int fd = accept(monitor, NULL, 0);
-                pid_t pid = getpid();
                 if (client != -1) {
                     close(fd);
                     continue;
                 }
-                /* Sync up with libvirtd LXC driver to tell it our PID */
-                if (safewrite(fd, &pid, sizeof(pid)) != sizeof(pid)) {
+                if (lxcControllerSendGreeting(fd, def) < 0) {
                     close(fd);
                     continue;
                 }
@@ -362,7 +410,11 @@
     if (lxcContainerSendContinue(control[0]) < 0)
         goto cleanup;
 
-    rc = lxcControllerMain(monitor, client, appPty, containerPty);
+    rc = lxcControllerMain(def,
+                           monitor,
+                           client,
+                           appPty,
+                           containerPty);
 
 cleanup:
     if (control[0] != -1)
@@ -463,8 +515,10 @@
         _exit(-1);
 
     /* Sync up with libvirtd LXC driver to tell it our PID */
-    if (safewrite(client, &pid, sizeof(pid)) != sizeof(pid))
+    if (lxcControllerSendGreeting(client, def) < 0) {
+        close(client);
         _exit(-1);
+    }
 
     /* Controlling libvirtd LXC driver now knows
        what our PID is, and is able to cleanup after
diff -r 33a641a0a0d9 src/lxc_controller.h
--- a/src/lxc_controller.h	Mon Jul 14 21:34:07 2008 +0100
+++ b/src/lxc_controller.h	Tue Jul 15 11:35:10 2008 +0100
@@ -29,6 +29,7 @@
 #include "lxc_conf.h"
 
 pid_t lxcControllerPID(int monitor);
+char *lxcControllerLiveConfig(int monitor);
 
 int lxcControllerStart(virDomainDefPtr def,
                        int nveths,
diff -r 33a641a0a0d9 src/lxc_driver.c
--- a/src/lxc_driver.c	Mon Jul 14 21:34:07 2008 +0100
+++ b/src/lxc_driver.c	Tue Jul 15 11:35:10 2008 +0100
@@ -874,6 +874,8 @@
     vm = lxc_driver->domains;
     while (vm) {
         pid_t pid;
+        char *xml;
+        virDomainDefPtr def;
         if ((vm->monitor = lxcMonitorClient(NULL, lxc_driver, vm)) < 0) {
             vm = vm->next;
             continue;
@@ -881,10 +883,28 @@
 
         /* Read pid from controller */
         if ((pid = lxcControllerPID(vm->monitor)) < 0) {
+            printf("Failed to get PID\n");
             close(vm->monitor);
             vm->monitor = -1;
             vm = vm->next;
             continue;
+        }
+
+        /* Fetch and load the live container config */
+        if ((xml = lxcControllerLiveConfig(vm->monitor)) == NULL) {
+            printf("Failed to get config\n");
+            /* XXX should we kill off the container if this
+               happens ? */
+            vm = vm->next;
+            continue;
+        }
+        def = virDomainDefParseString(NULL, lxc_driver->caps, xml);
+        VIR_FREE(xml);
+        if (def) {
+            vm->newDef = vm->def;
+            vm->def = def;
+        } else {
+            printf("Failed to pase config\n");
         }
 
         vm->pid = vm->def->id = pid;

-- 
|: Red Hat, Engineering, London   -o-   http://people.redhat.com/berrange/ :|
|: http://libvirt.org  -o-  http://virt-manager.org  -o-  http://ovirt.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505  -o-  F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|




More information about the libvir-list mailing list