lxc: only write XML once for lxc controller

Currently when launching the LXC controller we first write out
the plain, inactive XML configuration, then launch the controller,
then replace the file with the live status XML configuration.
By good fortune this hasn't caused any problems other than some
misleading error messages during failure scenarios.

This simplifies the code so it only writes out the XML once and
always writes the live status XML. To do this we need to handshake
with the child process, to make execution pause just before exec()
so we can write the XML status with the child PID present.
This commit is contained in:
Daniel P. Berrange 2015-01-16 16:39:57 +00:00
parent e1de552150
commit 0a8addc103
4 changed files with 33 additions and 19 deletions

View File

@ -14634,7 +14634,7 @@ virDomainObjParseNode(xmlDocPtr xml,
}
static virDomainObjPtr
virDomainObjPtr
virDomainObjParseFile(const char *filename,
virCapsPtr caps,
virDomainXMLOptionPtr xmlopt,

View File

@ -2489,6 +2489,11 @@ virDomainDefPtr virDomainDefParseNode(xmlDocPtr doc,
virDomainXMLOptionPtr xmlopt,
unsigned int expectedVirtTypes,
unsigned int flags);
virDomainObjPtr virDomainObjParseFile(const char *filename,
virCapsPtr caps,
virDomainXMLOptionPtr xmlopt,
unsigned int expectedVirtTypes,
unsigned int flags);
bool virDomainDefCheckABIStability(virDomainDefPtr src,
virDomainDefPtr dst);

View File

@ -100,6 +100,7 @@ typedef struct _virLXCController virLXCController;
typedef virLXCController *virLXCControllerPtr;
struct _virLXCController {
char *name;
virDomainObjPtr vm;
virDomainDefPtr def;
int handshakeFd;
@ -175,11 +176,12 @@ static virLXCControllerPtr virLXCControllerNew(const char *name)
ctrl->name)) == NULL)
goto error;
if ((ctrl->def = virDomainDefParseFile(configFile,
if ((ctrl->vm = virDomainObjParseFile(configFile,
caps, xmlopt,
1 << VIR_DOMAIN_VIRT_LXC,
0)) == NULL)
goto error;
ctrl->def = ctrl->vm->def;
if ((ctrl->timerShutdown = virEventAddTimeout(-1,
virLXCControllerQuitTimer, ctrl,
@ -269,7 +271,7 @@ static void virLXCControllerFree(virLXCControllerPtr ctrl)
VIR_FREE(ctrl->devptmx);
virDomainDefFree(ctrl->def);
virObjectUnref(ctrl->vm);
VIR_FREE(ctrl->name);
if (ctrl->timerShutdown != -1)

View File

@ -821,6 +821,9 @@ virLXCProcessBuildControllerCmd(virLXCDriverPtr driver,
virCommandSetPidFile(cmd, pidfile);
virCommandSetOutputFD(cmd, &logfd);
virCommandSetErrorFD(cmd, &logfd);
/* So we can pause before exec'ing the controller to
* write the live domain status XML with the PID */
virCommandRequireHandshake(cmd);
return cmd;
cleanup:
@ -1169,10 +1172,6 @@ int virLXCProcessStart(virConnectPtr conn,
if (virLXCProcessSetupInterfaces(conn, vm->def, &nveths, &veths) < 0)
goto cleanup;
/* Save the configuration for the controller */
if (virDomainSaveConfig(cfg->stateDir, vm->def) < 0)
goto cleanup;
if ((logfd = open(logfile, O_WRONLY | O_APPEND | O_CREAT,
S_IRUSR|S_IWUSR)) < 0) {
virReportSystemError(errno,
@ -1271,6 +1270,23 @@ int virLXCProcessStart(virConnectPtr conn,
goto error;
}
if (VIR_CLOSE(handshakefds[1]) < 0) {
virReportSystemError(errno, "%s", _("could not close handshake fd"));
goto error;
}
if (virCommandHandshakeWait(cmd) < 0)
goto error;
/* Write domain status to disk for the controller to
* read when it starts */
if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
goto error;
/* Allow the child to exec the controller */
if (virCommandHandshakeNotify(cmd) < 0)
goto error;
if (virAtomicIntInc(&driver->nactive) == 1 && driver->inhibitCallback)
driver->inhibitCallback(true, driver->inhibitOpaque);
@ -1328,15 +1344,6 @@ int virLXCProcessStart(virConnectPtr conn,
/* We don't need the temporary NIC names anymore, clear them */
virLXCProcessCleanInterfaces(vm->def);
/* Write domain status to disk.
*
* XXX: Earlier we wrote the plain "live" domain XML to this
* location for the benefit of libvirt_lxc. We're now overwriting
* it with the live status XML instead. This is a (currently
* harmless) inconsistency we should fix one day */
if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
goto error;
/* finally we can call the 'started' hook script if any */
if (virHookPresent(VIR_HOOK_DRIVER_LXC)) {
char *xml = virDomainDefFormat(vm->def, 0);