Fix numerous bugs in QEMU domain startup

This commit is contained in:
Daniel P. Berrange 2009-01-30 17:07:29 +00:00
parent 05436ab7ff
commit 896761e5c7
3 changed files with 70 additions and 23 deletions

View File

@ -1,3 +1,12 @@
Fri Jan 30 16:58:22 GMT 2009 Daniel P. Berrange <berrange@redhat.com>
Misc QEMU driver startup fixes
* src/domain_conf.c: Add initialization of monitor_watch
* src/qemud_driver.c: Fix infinite loop when QEMU quits on
startup. Fix watch removal if watch isn't added. Fix use
of VNC password from global driver config. Avoid zombies
from daemonizing QEMU. Fix memory leak in monitorpath
Fri Jan 30 16:51:22 GMT 2009 Daniel P. Berrange <berrange@redhat.com> Fri Jan 30 16:51:22 GMT 2009 Daniel P. Berrange <berrange@redhat.com>
* src/lxc_driver.c: Avoid probing for LXC until we know we're * src/lxc_driver.c: Avoid probing for LXC until we know we're

View File

@ -497,6 +497,7 @@ virDomainObjPtr virDomainAssignDef(virConnectPtr conn,
virDomainObjLock(domain); virDomainObjLock(domain);
domain->state = VIR_DOMAIN_SHUTOFF; domain->state = VIR_DOMAIN_SHUTOFF;
domain->def = def; domain->def = def;
domain->monitor_watch = -1;
if (VIR_REALLOC_N(doms->objs, doms->count + 1) < 0) { if (VIR_REALLOC_N(doms->objs, doms->count + 1) < 0) {
virReportOOMError(conn); virReportOOMError(conn);

View File

@ -355,10 +355,9 @@ qemudReconnectVMs(struct qemud_driver *driver)
qemudLog(QEMUD_ERR, _("Failed to reconnect monitor for %s: %d\n"), qemudLog(QEMUD_ERR, _("Failed to reconnect monitor for %s: %d\n"),
vm->def->name, rc); vm->def->name, rc);
goto next_error; goto next_error;
} else }
vm->monitorpath = status->monitorpath;
if((vm->logfile = qemudLogFD(NULL, driver->logDir, vm->def->name)) < 0) if ((vm->logfile = qemudLogFD(NULL, driver->logDir, vm->def->name)) < 0)
return -1; return -1;
if (vm->def->id >= driver->nextvmid) if (vm->def->id >= driver->nextvmid)
@ -376,6 +375,8 @@ next_error:
vm->newDef = NULL; vm->newDef = NULL;
next: next:
virDomainObjUnlock(vm); virDomainObjUnlock(vm);
if (status)
VIR_FREE(status->monitorpath);
VIR_FREE(status); VIR_FREE(status);
VIR_FREE(config); VIR_FREE(config);
} }
@ -617,6 +618,9 @@ typedef int qemudHandlerMonitorOutput(virConnectPtr conn,
const char *output, const char *output,
int fd); int fd);
/*
* Returns -1 for error, 0 on end-of-file, 1 for success
*/
static int static int
qemudReadMonitorOutput(virConnectPtr conn, qemudReadMonitorOutput(virConnectPtr conn,
virDomainObjPtr vm, virDomainObjPtr vm,
@ -630,7 +634,7 @@ qemudReadMonitorOutput(virConnectPtr conn,
int got = 0; int got = 0;
buf[0] = '\0'; buf[0] = '\0';
/* Consume & discard the initial greeting */ /* Consume & discard the initial greeting */
while (got < (buflen-1)) { while (got < (buflen-1)) {
int ret; int ret;
@ -670,11 +674,17 @@ qemudReadMonitorOutput(virConnectPtr conn,
_("Failure while reading %s startup output"), what); _("Failure while reading %s startup output"), what);
return -1; return -1;
} }
} else if (ret == 0) {
return 0;
} else { } else {
got += ret; got += ret;
buf[got] = '\0'; buf[got] = '\0';
if ((ret = func(conn, vm, buf, fd)) != 1) ret = func(conn, vm, buf, fd);
return ret; if (ret == -1)
return -1;
if (ret == 1)
continue;
return 1;
} }
} }
@ -724,11 +734,14 @@ static int qemudOpenMonitor(virConnectPtr conn,
} }
if (!reconnect) { if (!reconnect) {
ret = qemudReadMonitorOutput(conn, if (qemudReadMonitorOutput(conn,
vm, monfd, vm, monfd,
buf, sizeof(buf), buf, sizeof(buf),
qemudCheckMonitorPrompt, qemudCheckMonitorPrompt,
"monitor", 10000); "monitor", 10000) <= 0)
ret = -1;
else
ret = 0;
} else { } else {
vm->monitor = monfd; vm->monitor = monfd;
ret = 0; ret = 0;
@ -858,7 +871,7 @@ static int qemudWaitForMonitor(virConnectPtr conn,
if ((logfd = qemudLogReadFD(conn, driver->logDir, vm->def->name, pos)) if ((logfd = qemudLogReadFD(conn, driver->logDir, vm->def->name, pos))
< 0) < 0)
return logfd; return -1;
ret = qemudReadMonitorOutput(conn, vm, logfd, buf, sizeof(buf), ret = qemudReadMonitorOutput(conn, vm, logfd, buf, sizeof(buf),
qemudFindCharDevicePTYs, qemudFindCharDevicePTYs,
@ -866,7 +879,17 @@ static int qemudWaitForMonitor(virConnectPtr conn,
if (close(logfd) < 0) if (close(logfd) < 0)
qemudLog(QEMUD_WARN, _("Unable to close logfile: %s\n"), qemudLog(QEMUD_WARN, _("Unable to close logfile: %s\n"),
strerror(errno)); strerror(errno));
return ret;
if (ret == 1) /* Success */
return 0;
if (ret == -1)
return -1;
/* Unexpected end of file - inform user of QEMU log data */
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("unable to start guest: %s"), buf);
return -1;
} }
static int static int
@ -1033,7 +1056,7 @@ qemudInitPasswords(virConnectPtr conn,
if (vm->def->graphics && if (vm->def->graphics &&
vm->def->graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC && vm->def->graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
vm->def->graphics->data.vnc.passwd) { (vm->def->graphics->data.vnc.passwd || driver->vncPassword)) {
if (qemudMonitorCommandExtra(vm, "change vnc password", if (qemudMonitorCommandExtra(vm, "change vnc password",
vm->def->graphics->data.vnc.passwd ? vm->def->graphics->data.vnc.passwd ?
@ -1212,14 +1235,25 @@ static int qemudStartVMDaemon(virConnectPtr conn,
/* wait for qemu process to to show up */ /* wait for qemu process to to show up */
if (ret == 0) { if (ret == 0) {
int retries = 100; int retries = 100;
while (retries) { int childstat;
if ((ret = virFileReadPid(driver->stateDir, vm->def->name, &vm->pid)) == 0)
break; while (waitpid(child, &childstat, 0) == -1 &&
usleep(100*1000); errno == EINTR);
retries--;
if (childstat == 0) {
while (retries) {
if ((ret = virFileReadPid(driver->stateDir, vm->def->name, &vm->pid)) == 0)
break;
usleep(100*1000);
retries--;
}
if (ret)
qemudLog(QEMUD_WARN, _("Domain %s didn't show up\n"), vm->def->name);
} else {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("Unable to daemonize QEMU process"));
ret = -1;
} }
if (ret)
qemudLog(QEMUD_WARN, _("Domain %s didn't show up\n"), vm->def->name);
} }
if (ret == 0) { if (ret == 0) {
@ -1262,14 +1296,17 @@ static void qemudShutdownVMDaemon(virConnectPtr conn ATTRIBUTE_UNUSED,
if (!virDomainIsActive(vm)) if (!virDomainIsActive(vm))
return; return;
qemudLog(QEMUD_INFO, _("Shutting down VM '%s'\n"), vm->def->name); qemudLog(QEMUD_DEBUG, _("Shutting down VM '%s'\n"), vm->def->name);
if (virKillProcess(vm->pid, 0) == 0 && if (virKillProcess(vm->pid, 0) == 0 &&
virKillProcess(vm->pid, SIGTERM) < 0) virKillProcess(vm->pid, SIGTERM) < 0)
qemudLog(QEMUD_ERROR, _("Failed to send SIGTERM to %s (%d): %s\n"), qemudLog(QEMUD_ERROR, _("Failed to send SIGTERM to %s (%d): %s\n"),
vm->def->name, vm->pid, strerror(errno)); vm->def->name, vm->pid, strerror(errno));
virEventRemoveHandle(vm->monitor_watch); if (vm->monitor_watch != -1) {
virEventRemoveHandle(vm->monitor_watch);
vm->monitor_watch = -1;
}
if (close(vm->logfile) < 0) if (close(vm->logfile) < 0)
qemudLog(QEMUD_WARN, _("Unable to close logfile %d: %s\n"), qemudLog(QEMUD_WARN, _("Unable to close logfile %d: %s\n"),