From 177c74b1fa7bc065fe3caefc369c8a9839a8e3d2 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Wed, 20 Aug 2008 20:55:32 +0000 Subject: [PATCH] Create lxc_controller standalone binary --- ChangeLog | 9 ++ src/Makefile.am | 26 +++- src/domain_conf.c | 6 +- src/lxc_conf.c | 8 +- src/lxc_conf.h | 4 + src/lxc_controller.c | 314 +++++++++++++++++++++++++++---------------- src/lxc_driver.c | 191 +++++++++++++++++--------- 7 files changed, 372 insertions(+), 186 deletions(-) diff --git a/ChangeLog b/ChangeLog index 76a5cae7ee..e85f0507b6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +Wed Aug 20 21:50:09 BST 2008 Daniel P. Berrange + + * src/domain_conf.c: Include PTY name if available + * src/Makefile.am: Add lxc_controller binary + * src/lxc_conf.c, src/lxc_conf.h, src/lxc_controller.c, + src/lxc_controller.h, src/lxc_driver.c: Move LXC controller + into a properly exec'd binary, instead of fork'd child of + libvirtd daemon + Wed Aug 20 21:05:09 BST 2008 Daniel P. Berrange * configure.in, qemud/Makefile.am, src/Makefile.am: Use automake diff --git a/src/Makefile.am b/src/Makefile.am index 879741284a..a659214e30 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -88,10 +88,15 @@ XEN_DRIVER_SOURCES = \ LXC_DRIVER_SOURCES = \ lxc_conf.c lxc_conf.h \ lxc_container.c lxc_container.h \ - lxc_controller.c lxc_controller.h \ lxc_driver.c lxc_driver.h \ veth.c veth.h +LXC_CONTROLLER_SOURCES = \ + lxc_conf.c lxc_conf.h \ + lxc_container.c lxc_container.h \ + lxc_controller.c \ + veth.c veth.h + OPENVZ_DRIVER_SOURCES = \ openvz_conf.c openvz_conf.h \ openvz_driver.c openvz_driver.h @@ -272,9 +277,11 @@ virsh-pool-edit.c: virsh.c Makefile.am rm -f $@ mv $@-tmp $@ +libexec_PROGRAMS = + if WITH_STORAGE_DISK if WITH_LIBVIRTD -libexec_PROGRAMS = libvirt_parthelper +libexec_PROGRAMS += libvirt_parthelper libvirt_parthelper_SOURCES = $(STORAGE_HELPER_DISK_SOURCES) libvirt_parthelper_LDFLAGS = $(WARN_CFLAGS) $(COVERAGE_LDCFLAGS) @@ -285,6 +292,21 @@ endif EXTRA_DIST += $(STORAGE_HELPER_DISK_SOURCES) +if WITH_LXC +if WITH_LIBVIRTD +libexec_PROGRAMS += libvirt_lxc + +libvirt_lxc_SOURCES = \ + $(LXC_CONTROLLER_SOURCES) \ + $(GENERIC_LIB_SOURCES) \ + $(DOMAIN_CONF_SOURCES) +libvirt_lxc_LDFLAGS = $(WARN_CFLAGS) $(COVERAGE_LDCFLAGS) +libvirt_lxc_LDADD = $(LIBXML_LIBS) ../gnulib/lib/libgnu.la +libvirt_lxc_CFLAGS = $(LIBPARTED_CFLAGS) +endif +endif +EXTRA_DIST += $(LXC_CONTROLLER_SOURCES) + # Create the /var/cache/libvirt directory when installing. install-exec-local: $(MKDIR_P) $(DESTDIR)$(localstatedir)/cache/libvirt diff --git a/src/domain_conf.c b/src/domain_conf.c index fc2bcf3132..d482e689aa 100644 --- a/src/domain_conf.c +++ b/src/domain_conf.c @@ -1109,13 +1109,11 @@ virDomainChrDefParseXML(virConnectPtr conn, 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 --git a/src/lxc_conf.c b/src/lxc_conf.c index a4d5f0a82a..4228b866d4 100644 --- a/src/lxc_conf.c +++ b/src/lxc_conf.c @@ -71,7 +71,7 @@ virCapsPtr lxcCapsInit(void) "exe", utsname.machine, sizeof(int) == 4 ? 32 : 8, - NULL, + BINDIR "/libvirt_lxc", NULL, 0, NULL)) == NULL) @@ -94,11 +94,11 @@ no_memory: int lxcLoadDriverConfig(lxc_driver_t *driver) { /* Set the container configuration directory */ - if ((driver->configDir = strdup(SYSCONF_DIR "/libvirt/lxc")) == NULL) + if ((driver->configDir = strdup(LXC_CONFIG_DIR)) == NULL) goto no_memory; - if ((driver->stateDir = strdup(LOCAL_STATE_DIR "/run/libvirt/lxc")) == NULL) + if ((driver->stateDir = strdup(LXC_STATE_DIR)) == NULL) goto no_memory; - if ((driver->logDir = strdup(LOCAL_STATE_DIR "/log/libvirt/lxc")) == NULL) + if ((driver->logDir = strdup(LXC_LOG_DIR)) == NULL) goto no_memory; return 0; diff --git a/src/lxc_conf.h b/src/lxc_conf.h index 8f4887f022..00442b4fec 100644 --- a/src/lxc_conf.h +++ b/src/lxc_conf.h @@ -30,6 +30,10 @@ #include "domain_conf.h" #include "capabilities.h" +#define LXC_CONFIG_DIR SYSCONF_DIR "/libvirt/lxc" +#define LXC_STATE_DIR LOCAL_STATE_DIR "/run/libvirt/lxc" +#define LXC_LOG_DIR LOCAL_STATE_DIR "/log/libvirt/lxc" + typedef struct __lxc_driver lxc_driver_t; struct __lxc_driver { virCapsPtr caps; diff --git a/src/lxc_controller.c b/src/lxc_controller.c index 9f67ce574d..79270515c7 100644 --- a/src/lxc_controller.c +++ b/src/lxc_controller.c @@ -23,22 +23,22 @@ #include -#ifdef WITH_LXC - #include #include #include +#include +#include #include #include #include #include +#include #include "internal.h" #include "util.h" #include "lxc_conf.h" #include "lxc_container.h" -#include "lxc_controller.h" #include "veth.h" #include "memory.h" #include "util.h" @@ -47,6 +47,56 @@ #define DEBUG(fmt,...) VIR_DEBUG(__FILE__, fmt, __VA_ARGS__) #define DEBUG0(msg) VIR_DEBUG(__FILE__, "%s", msg) +int debugFlag = 0; + +static char*lxcMonitorPath(virDomainDefPtr def) +{ + char *sockpath; + if (asprintf(&sockpath, "%s/%s.sock", + LXC_STATE_DIR, def->name) < 0) { + lxcError(NULL, NULL, VIR_ERR_NO_MEMORY, NULL); + return NULL; + } + return sockpath; +} + +static int lxcMonitorServer(const char *sockpath) +{ + int fd; + struct sockaddr_un addr; + + if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { + lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, + _("failed to create server socket %s: %s"), + sockpath, strerror(errno)); + goto error; + } + + unlink(sockpath); + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, sockpath, sizeof(addr.sun_path)); + + if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { + lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, + _("failed to bind server socket %s: %s"), + sockpath, strerror(errno)); + goto error; + } + if (listen(fd, 30 /* backlog */ ) < 0) { + lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, + _("failed to listen server socket %s: %s"), + sockpath, strerror(errno)); + goto error; + } + + return fd; + +error: + if (fd != -1) + close(fd); + return -1; +} /** * lxcFdForward: @@ -305,8 +355,7 @@ static int lxcControllerCleanupInterfaces(unsigned int nveths, static int -lxcControllerRun(const char *stateDir, - virDomainDefPtr def, +lxcControllerRun(virDomainDefPtr def, unsigned int nveths, char **veths, int monitor, @@ -359,148 +408,187 @@ cleanup: if (containerPty != -1) close(containerPty); - kill(container, SIGTERM); - waitpid(container, NULL, 0); - lxcControllerCleanupInterfaces(nveths, veths); - virFileDeletePid(stateDir, def->name); + if (container > 1) { + kill(container, SIGTERM); + waitpid(container, NULL, 0); + } return rc; } -int lxcControllerStart(const char *stateDir, - virDomainDefPtr def, - unsigned int nveths, - char **veths, - int monitor, - int appPty, - int logfd) +int main(int argc, char *argv[]) { pid_t pid; - int rc; - int status, null; - int open_max, i; + int rc = 1; int client; - struct sigaction sig_action; + char *name = NULL; + int nveths = 0; + char **veths = NULL; + int monitor = -1; + int appPty = -1; + int bg = 0; + virCapsPtr caps = NULL; + virDomainDefPtr def = NULL; + int nnets = 0; + virDomainNetDefPtr nets = NULL; + char *configFile = NULL; + char *sockpath = NULL; + const struct option const options[] = { + { "background", 0, NULL, 'b' }, + { "name", 1, NULL, 'n' }, + { "veth", 1, NULL, 'v' }, + { "console", 1, NULL, 'c' }, + { "help", 0, NULL, 'h' }, + { 0, 0, 0, 0 }, + }; - if ((pid = fork()) < 0) - return -1; + while (1) { + int c; - if (pid > 0) { - /* Original caller waits for first child to exit */ - while (1) { - rc = waitpid(pid, &status, 0); - if (rc < 0) { - if (errno == EINTR) - continue; - return -1; + c = getopt_long(argc, argv, "dn:v:m:c:h", + options, NULL); + + if (c == -1) + break; + + switch (c) { + case 'b': + bg = 1; + break; + + case 'n': + if ((name = strdup(optarg)) == NULL) { + fprintf(stderr, "%s", strerror(errno)); + goto cleanup; } - if (rc != pid) { - fprintf(stderr, - _("Unexpected pid %d != %d from waitpid\n"), - rc, pid); - return -1; + break; + + case 'v': + if (VIR_REALLOC_N(veths, nveths+1) < 0) { + fprintf(stderr, "cannot allocate veths %s", strerror(errno)); + goto cleanup; } - if (WIFEXITED(status) && - WEXITSTATUS(status) == 0) - return 0; - else { - fprintf(stderr, - _("Unexpected status %d from pid %d\n"), - status, pid); - return -1; + if ((veths[nveths++] = strdup(optarg)) == NULL) { + fprintf(stderr, "cannot allocate veth name %s", strerror(errno)); + goto cleanup; } + break; + + case 'c': + if (virStrToLong_i(optarg, NULL, 10, &appPty) < 0) { + fprintf(stderr, "malformed --console argument '%s'", optarg); + goto cleanup; + } + break; + + case 'h': + case '?': + fprintf(stderr, "\n"); + fprintf(stderr, "syntax: %s [OPTIONS]\n", argv[0]); + fprintf(stderr, "\n"); + fprintf(stderr, "Options\n"); + fprintf(stderr, "\n"); + fprintf(stderr, " -b, --background\n"); + fprintf(stderr, " -n NAME, --name NAME\n"); + fprintf(stderr, " -c FD, --console FD\n"); + fprintf(stderr, " -v VETH, --veth VETH\n"); + fprintf(stderr, " -h, --help\n"); + fprintf(stderr, "\n"); + goto cleanup; } } - /* First child is running here */ - /* Clobber all libvirtd's signal handlers so they - * don't affect us - */ - sig_action.sa_handler = SIG_DFL; - sig_action.sa_flags = 0; - sigemptyset(&sig_action.sa_mask); - - sigaction(SIGHUP, &sig_action, NULL); - sigaction(SIGINT, &sig_action, NULL); - sigaction(SIGQUIT, &sig_action, NULL); - sigaction(SIGTERM, &sig_action, NULL); - sigaction(SIGCHLD, &sig_action, NULL); - - sig_action.sa_handler = SIG_IGN; - sigaction(SIGPIPE, &sig_action, NULL); - - - /* Don't hold onto any cwd we inherit from libvirtd either */ - if (chdir("/") < 0) { - fprintf(stderr, _("Unable to change to root dir: %s\n"), - strerror(errno)); - _exit(-1); + if (name == NULL) { + fprintf(stderr, "%s: missing --name argument for configuration\n", argv[0]); + goto cleanup; } - if (setsid() < 0) { - fprintf(stderr, _("Unable to become session leader: %s\n"), - strerror(errno)); - _exit(-1); + if (appPty < 0) { + fprintf(stderr, "%s: missing --console argument for container PTY\n", argv[0]); + goto cleanup; } - if ((null = open(_PATH_DEVNULL, O_RDONLY)) < 0) { - fprintf(stderr, _("Unable to open %s: %s\n"), - _PATH_DEVNULL, strerror(errno)); - _exit(-1); + if (getuid() && 0) { + fprintf(stderr, "%s: must be run as the 'root' user\n", argv[0]); + goto cleanup; } - open_max = sysconf (_SC_OPEN_MAX); - for (i = 0; i < open_max; i++) - if (i != appPty && - i != monitor && - i != logfd && - i != null) - close(i); + if ((caps = lxcCapsInit()) == NULL) + goto cleanup; - if (dup2(null, STDIN_FILENO) < 0 || - dup2(logfd, STDOUT_FILENO) < 0 || - dup2(logfd, STDERR_FILENO) < 0) { - fprintf(stderr, _("Unable to redirect stdio: %s\n"), - strerror(errno)); - _exit(-1); + if ((configFile = virDomainConfigFile(NULL, + LXC_STATE_DIR, + name)) == NULL) + goto cleanup; + + if ((def = virDomainDefParseFile(NULL, caps, configFile)) == NULL) + goto cleanup; + + nets = def->nets; + while (nets) { + nnets++; + nets = nets->next; + } + if (nnets != nveths) { + fprintf(stderr, "%s: expecting %d veths, but got %d\n", + argv[0], nnets, nveths); + goto cleanup; } - close(null); - close(logfd); + if ((sockpath = lxcMonitorPath(def)) == NULL) + goto cleanup; - /* Now fork the real controller process */ - if ((pid = fork()) < 0) { - fprintf(stderr, _("Unable to fork controller: %s\n"), - strerror(errno)); - _exit(-1); - } + if ((monitor = lxcMonitorServer(sockpath)) < 0) + goto cleanup; - if (pid > 0) { - if ((rc = virFileWritePid(stateDir, def->name, pid)) != 0) { - fprintf(stderr, _("Unable to write pid file: %s\n"), - strerror(rc)); - _exit(-1); + if (bg) { + if ((pid = fork()) < 0) + goto cleanup; + + if (pid > 0) { + if ((rc = virFileWritePid(LXC_STATE_DIR, name, pid)) != 0) { + fprintf(stderr, _("Unable to write pid file: %s\n"), + strerror(rc)); + _exit(1); + } + + /* First child now exits, allowing original caller + * (ie libvirtd's LXC driver to complete their + * waitpid & continue */ + _exit(0); } - /* First child now exits, allowing originall caller to - * complete their waitpid & continue */ - _exit(0); - } - /* This is real controller running finally... */ + /* Don't hold onto any cwd we inherit from libvirtd either */ + if (chdir("/") < 0) { + fprintf(stderr, _("Unable to change to root dir: %s\n"), + strerror(errno)); + goto cleanup; + } + + if (setsid() < 0) { + fprintf(stderr, _("Unable to become session leader: %s\n"), + strerror(errno)); + goto cleanup; + } + } /* Accept initial client which is the libvirtd daemon */ - if ((client = accept(monitor, NULL, 0))) { + if ((client = accept(monitor, NULL, 0)) < 0) { fprintf(stderr, _("Failed connection from LXC driver: %s\n"), strerror(errno)); - _exit(-1); + goto cleanup; } - /* Controlling libvirtd LXC driver now knows - what our PID is, and is able to cleanup after - us from now on */ - _exit(lxcControllerRun(stateDir, def, nveths, veths, monitor, client, appPty)); + rc = lxcControllerRun(def, nveths, veths, monitor, client, appPty); + + +cleanup: + virFileDeletePid(LXC_STATE_DIR, def->name); + lxcControllerCleanupInterfaces(nveths, veths); + unlink(sockpath); + VIR_FREE(sockpath); + + return rc; } - -#endif diff --git a/src/lxc_driver.c b/src/lxc_driver.c index f0f3c258c8..3f67c8a372 100644 --- a/src/lxc_driver.c +++ b/src/lxc_driver.c @@ -38,7 +38,6 @@ #include "lxc_conf.h" #include "lxc_container.h" #include "lxc_driver.h" -#include "lxc_controller.h" #include "memory.h" #include "util.h" #include "bridge.h" @@ -398,6 +397,7 @@ static int lxcVMCleanup(virConnectPtr conn, close(vm->monitor); virFileDeletePid(driver->stateDir, vm->def->name); + virDomainDeleteConfig(conn, driver->stateDir, NULL, vm); vm->state = VIR_DOMAIN_SHUTOFF; vm->pid = -1; @@ -507,55 +507,6 @@ error_exit: return rc; } -static int lxcMonitorServer(virConnectPtr conn, - lxc_driver_t * driver, - virDomainObjPtr vm) -{ - char *sockpath = NULL; - int fd; - struct sockaddr_un addr; - - if (asprintf(&sockpath, "%s/%s.sock", - driver->stateDir, vm->def->name) < 0) { - lxcError(conn, NULL, VIR_ERR_NO_MEMORY, NULL); - return -1; - } - - if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { - lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR, - _("failed to create server socket: %s"), - strerror(errno)); - goto error; - } - - unlink(sockpath); - memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - strncpy(addr.sun_path, sockpath, sizeof(addr.sun_path)); - - if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR, - _("failed to bind server socket: %s"), - strerror(errno)); - goto error; - } - if (listen(fd, 30 /* backlog */ ) < 0) { - lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR, - _("failed to listen server socket: %s"), - strerror(errno)); - goto error; - return (-1); - } - - VIR_FREE(sockpath); - return fd; - -error: - VIR_FREE(sockpath); - if (fd != -1) - close(fd); - return -1; -} static int lxcMonitorClient(virConnectPtr conn, lxc_driver_t * driver, @@ -608,6 +559,12 @@ static int lxcVmTerminate(virConnectPtr conn, if (signum == 0) signum = SIGINT; + if (vm->pid <= 0) { + lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR, + _("invalid PID %d for container"), vm->pid); + return -1; + } + if (kill(vm->pid, signum) < 0) { if (errno != ESRCH) { lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR, @@ -644,6 +601,102 @@ static void lxcMonitorEvent(int fd, } +static int lxcControllerStart(virConnectPtr conn, + virDomainObjPtr vm, + int nveths, + char **veths, + int appPty, + int logfd) +{ + int i; + int rc; + int ret = -1; + int largc = 0, larga = 0; + const char **largv = NULL; + pid_t child; + int status; + +#define ADD_ARG_SPACE \ + do { \ + if (largc == larga) { \ + larga += 10; \ + if (VIR_REALLOC_N(largv, larga) < 0) \ + goto no_memory; \ + } \ + } while (0) + +#define ADD_ARG(thisarg) \ + do { \ + ADD_ARG_SPACE; \ + largv[largc++] = thisarg; \ + } while (0) + +#define ADD_ARG_LIT(thisarg) \ + do { \ + ADD_ARG_SPACE; \ + if ((largv[largc++] = strdup(thisarg)) == NULL) \ + goto no_memory; \ + } while (0) + + ADD_ARG_LIT(vm->def->emulator); + ADD_ARG_LIT("--name"); + ADD_ARG_LIT(vm->def->name); + ADD_ARG_LIT("--console"); + ADD_ARG_LIT("0"); /* Passing console master PTY as FD 0 */ + ADD_ARG_LIT("--background"); + + for (i = 0 ; i < nveths ; i++) { + ADD_ARG_LIT("--veth"); + ADD_ARG_LIT(veths[i]); + } + + ADD_ARG(NULL); + + vm->stdin_fd = appPty; /* Passing console master PTY as FD 0 */ + vm->stdout_fd = vm->stderr_fd = logfd; + + if (virExec(conn, largv, NULL, &child, + vm->stdin_fd, &vm->stdout_fd, &vm->stderr_fd, + VIR_EXEC_NONE) < 0) + goto cleanup; + + /* We now wait for the process to exit - the controller + * will fork() itself into the background - waiting for + * it to exit thus guarentees it has written its pidfile + */ + while ((rc = waitpid(child, &status, 0) == -1) && errno == EINTR); + if (rc == -1) { + lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR, + _("cannot wait for '%s': %s"), + largv[0], strerror(errno)); + goto cleanup; + } + + if (!(WIFEXITED(status) && WEXITSTATUS(status) == 0)) { + lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR, + _("container '%s' unexpectedly shutdown during startup"), + largv[0]); + goto cleanup; + } + +#undef ADD_ARG +#undef ADD_ARG_LIT +#undef ADD_ARG_SPACE + + ret = 0; + +cleanup: + for (i = 0 ; i < largc ; i++) + VIR_FREE(largv[i]); + + return ret; + +no_memory: + lxcError(conn, NULL, VIR_ERR_NO_MEMORY, NULL); + goto cleanup; +} + + /** * lxcVmStart: * @conn: pointer to connection @@ -660,7 +713,6 @@ static int lxcVmStart(virConnectPtr conn, { int rc = -1; unsigned int i; - int monitor; int parentTty; char *parentTtyPath = NULL; char *logfile = NULL; @@ -681,9 +733,6 @@ static int lxcVmStart(virConnectPtr conn, return -1; } - if ((monitor = lxcMonitorServer(conn, driver, vm)) < 0) - goto cleanup; - /* open parent tty */ if (virFileOpenTty(&parentTty, &parentTtyPath, 1) < 0) { lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR, @@ -702,6 +751,12 @@ static int lxcVmStart(virConnectPtr conn, if (lxcSetupInterfaces(conn, vm->def, &nveths, &veths) != 0) goto cleanup; + /* Persist the live configuration now we have veth & tty info */ + if (virDomainSaveConfig(conn, driver->stateDir, vm->def) < 0) { + rc = -1; + goto cleanup; + } + if ((logfd = open(logfile, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR|S_IWUSR)) < 0) { lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR, @@ -710,14 +765,11 @@ static int lxcVmStart(virConnectPtr conn, goto cleanup; } - if (lxcControllerStart(driver->stateDir, - vm->def, nveths, veths, - monitor, parentTty, logfd) < 0) + if (lxcControllerStart(conn, + vm, + nveths, veths, + parentTty, logfd) < 0) goto cleanup; - /* Close the server side of the monitor, now owned - * by the controller process */ - close(monitor); - monitor = -1; /* Connect to the controller as a client *first* because * this will block until the child has written their @@ -753,8 +805,6 @@ cleanup: vethDelete(veths[i]); VIR_FREE(veths[i]); } - if (monitor != -1) - close(monitor); if (rc != 0 && vm->monitor != -1) { close(vm->monitor); vm->monitor = -1; @@ -951,6 +1001,8 @@ static int lxcStartup(void) vm = lxc_driver->domains; while (vm) { + char *config = NULL; + virDomainDefPtr tmp; int rc; if ((vm->monitor = lxcMonitorClient(NULL, lxc_driver, vm)) < 0) { vm = vm->next; @@ -965,6 +1017,19 @@ static int lxcStartup(void) continue; } + if ((config = virDomainConfigFile(NULL, + lxc_driver->stateDir, + vm->def->name)) == NULL) + continue; + + /* Try and load the live config */ + tmp = virDomainDefParseFile(NULL, lxc_driver->caps, config); + VIR_FREE(config); + if (tmp) { + vm->newDef = vm->def; + vm->def = tmp; + } + if (vm->pid != 0) { vm->def->id = vm->pid; vm->state = VIR_DOMAIN_RUNNING;