[libvirt] [PATCH 2/2] Add domain autostart for LXC driver

Daniel P. Berrange berrange at redhat.com
Wed Jul 22 16:02:56 UTC 2009


* src/lxc_driver.c: Implement support for domain autostart

Signed-off-by: Daniel P. Berrange <berrange at redhat.com>
---
 src/lxc_driver.c |  184 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 182 insertions(+), 2 deletions(-)

diff --git a/src/lxc_driver.c b/src/lxc_driver.c
index 1b5c86c..ef31be9 100644
--- a/src/lxc_driver.c
+++ b/src/lxc_driver.c
@@ -48,6 +48,7 @@
 #include "event.h"
 #include "cgroup.h"
 #include "nodeinfo.h"
+#include "uuid.h"
 
 
 #define VIR_FROM_THIS VIR_FROM_LXC
@@ -1301,6 +1302,48 @@ static int lxcCheckNetNsSupport(void)
     return 1;
 }
 
+
+static void
+lxcAutostartConfigs(lxc_driver_t *driver) {
+    unsigned int i;
+    /* XXX: Figure out a better way todo this. The domain
+     * startup code needs a connection handle in order
+     * to lookup the bridge associated with a virtual
+     * network
+     */
+    virConnectPtr conn = virConnectOpen("lxc:///");
+    /* Ignoring NULL conn which is mostly harmless here */
+
+    lxcDriverLock(driver);
+    for (i = 0 ; i < driver->domains.count ; i++) {
+        virDomainObjPtr vm = driver->domains.objs[i];
+        virDomainObjLock(vm);
+        if (vm->autostart &&
+            !virDomainIsActive(vm)) {
+            int ret = lxcVmStart(conn, driver, vm);
+            if (ret < 0) {
+                virErrorPtr err = virGetLastError();
+                VIR_ERROR(_("Failed to autostart VM '%s': %s\n"),
+                          vm->def->name,
+                          err ? err->message : "");
+            } else {
+                virDomainEventPtr event =
+                    virDomainEventNewFromObj(vm,
+                                             VIR_DOMAIN_EVENT_STARTED,
+                                             VIR_DOMAIN_EVENT_STARTED_BOOTED);
+                if (event)
+                    lxcDomainEventQueue(driver, event);
+            }
+        }
+        virDomainObjUnlock(vm);
+    }
+    lxcDriverUnlock(driver);
+
+    if (conn)
+        virConnectClose(conn);
+}
+
+
 static int lxcStartup(int privileged)
 {
     unsigned int i;
@@ -1413,6 +1456,45 @@ cleanup:
     return -1;
 }
 
+static void lxcNotifyLoadDomain(virDomainObjPtr vm, int newVM, void *opaque)
+{
+    lxc_driver_t *driver = opaque;
+
+    if (newVM) {
+        virDomainEventPtr event =
+            virDomainEventNewFromObj(vm,
+                                     VIR_DOMAIN_EVENT_DEFINED,
+                                     VIR_DOMAIN_EVENT_DEFINED_ADDED);
+        if (event)
+            lxcDomainEventQueue(driver, event);
+    }
+}
+
+/**
+ * lxcReload:
+ *
+ * Function to restart the LXC driver, it will recheck the configuration
+ * files and perform autostart
+ */
+static int
+lxcReload(void) {
+    if (!lxc_driver)
+        return 0;
+
+    lxcDriverLock(lxc_driver);
+    virDomainLoadAllConfigs(NULL,
+                            lxc_driver->caps,
+                            &lxc_driver->domains,
+                            lxc_driver->configDir,
+                            lxc_driver->autostartDir,
+                            0, lxcNotifyLoadDomain, lxc_driver);
+    lxcDriverUnlock(lxc_driver);
+
+    lxcAutostartConfigs(lxc_driver);
+
+    return 0;
+}
+
 static int lxcShutdown(void)
 {
     if (lxc_driver == NULL)
@@ -1589,6 +1671,103 @@ cleanup:
     return ret;
 }
 
+static int lxcDomainGetAutostart(virDomainPtr dom,
+                                   int *autostart) {
+    lxc_driver_t *driver = dom->conn->privateData;
+    virDomainObjPtr vm;
+    int ret = -1;
+
+    lxcDriverLock(driver);
+    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    lxcDriverUnlock(driver);
+
+    if (!vm) {
+        char uuidstr[VIR_UUID_STRING_BUFLEN];
+        virUUIDFormat(dom->uuid, uuidstr);
+        lxcError(dom->conn, dom, VIR_ERR_NO_DOMAIN,
+                 _("no domain with matching uuid '%s'"), uuidstr);
+        goto cleanup;
+    }
+
+    *autostart = vm->autostart;
+    ret = 0;
+
+cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
+    return ret;
+}
+
+static int lxcDomainSetAutostart(virDomainPtr dom,
+                                   int autostart) {
+    lxc_driver_t *driver = dom->conn->privateData;
+    virDomainObjPtr vm;
+    char *configFile = NULL, *autostartLink = NULL;
+    int ret = -1;
+
+    lxcDriverLock(driver);
+    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+
+    if (!vm) {
+        char uuidstr[VIR_UUID_STRING_BUFLEN];
+        virUUIDFormat(dom->uuid, uuidstr);
+        lxcError(dom->conn, dom, VIR_ERR_NO_DOMAIN,
+                 _("no domain with matching uuid '%s'"), uuidstr);
+        goto cleanup;
+    }
+
+    if (!vm->persistent) {
+        lxcError(dom->conn, dom, VIR_ERR_INTERNAL_ERROR,
+                 "%s", _("cannot set autostart for transient domain"));
+        goto cleanup;
+    }
+
+    autostart = (autostart != 0);
+
+    if (vm->autostart != autostart) {
+        if ((configFile = virDomainConfigFile(dom->conn, driver->configDir, vm->def->name)) == NULL)
+            goto cleanup;
+        if ((autostartLink = virDomainConfigFile(dom->conn, driver->autostartDir, vm->def->name)) == NULL)
+            goto cleanup;
+
+        if (autostart) {
+            int err;
+
+            if ((err = virFileMakePath(driver->autostartDir))) {
+                virReportSystemError(dom->conn, err,
+                                     _("cannot create autostart directory %s"),
+                                     driver->autostartDir);
+                goto cleanup;
+            }
+
+            if (symlink(configFile, autostartLink) < 0) {
+                virReportSystemError(dom->conn, errno,
+                                     _("Failed to create symlink '%s to '%s'"),
+                                     autostartLink, configFile);
+                goto cleanup;
+            }
+        } else {
+            if (unlink(autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR) {
+                virReportSystemError(dom->conn, errno,
+                                     _("Failed to delete symlink '%s'"),
+                                     autostartLink);
+                goto cleanup;
+            }
+        }
+
+        vm->autostart = autostart;
+    }
+    ret = 0;
+
+cleanup:
+    VIR_FREE(configFile);
+    VIR_FREE(autostartLink);
+    if (vm)
+        virDomainObjUnlock(vm);
+    lxcDriverUnlock(driver);
+    return ret;
+}
+
 static char *lxcGetHostname (virConnectPtr conn)
 {
     char *result;
@@ -1651,8 +1830,8 @@ static virDriver lxcDriver = {
     lxcDomainUndefine, /* domainUndefine */
     NULL, /* domainAttachDevice */
     NULL, /* domainDetachDevice */
-    NULL, /* domainGetAutostart */
-    NULL, /* domainSetAutostart */
+    lxcDomainGetAutostart, /* domainGetAutostart */
+    lxcDomainSetAutostart, /* domainSetAutostart */
     lxcGetSchedulerType, /* domainGetSchedulerType */
     lxcGetSchedulerParameters, /* domainGetSchedulerParameters */
     lxcSetSchedulerParameters, /* domainSetSchedulerParameters */
@@ -1678,6 +1857,7 @@ static virStateDriver lxcStateDriver = {
     .initialize = lxcStartup,
     .cleanup = lxcShutdown,
     .active = lxcActive,
+    .reload = lxcReload,
 };
 
 int lxcRegister(void)
-- 
1.6.2.5




More information about the libvir-list mailing list