Improve virsh start --console behavior

When starting a guest via libvirt (`virsh start --console`), early
console output was missed because the guest was started first and then
the console was attached. This patch changes this to the following
sequence:

1. create a paused guest
2. attach the console
3. resume the guest

Reviewed-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
Marc Hartmayer 2023-09-28 17:37:09 +02:00 committed by Michal Privoznik
parent 49e3e7f9e8
commit a99ed65db2

View File

@ -4059,12 +4059,29 @@ static const vshCmdOptDef opts_start[] = {
{.name = NULL} {.name = NULL}
}; };
static int
virshDomainCreateHelper(virDomainPtr dom,
unsigned int nfds,
int *fds,
unsigned int flags)
{
/* Prefer older API unless we have to pass a flag. */
if (nfds > 0) {
return virDomainCreateWithFiles(dom, nfds, fds, flags);
} else if (flags != 0) {
return virDomainCreateWithFlags(dom, flags);
}
return virDomainCreate(dom);
}
static bool static bool
cmdStart(vshControl *ctl, const vshCmd *cmd) cmdStart(vshControl *ctl, const vshCmd *cmd)
{ {
g_autoptr(virshDomain) dom = NULL; g_autoptr(virshDomain) dom = NULL;
#ifndef WIN32 #ifndef WIN32
bool console = vshCommandOptBool(cmd, "console"); bool console = vshCommandOptBool(cmd, "console");
bool resume_domain = false;
#endif #endif
unsigned int flags = VIR_DOMAIN_NONE; unsigned int flags = VIR_DOMAIN_NONE;
int rc; int rc;
@ -4083,8 +4100,14 @@ cmdStart(vshControl *ctl, const vshCmd *cmd)
if (virshFetchPassFdsList(ctl, cmd, &nfds, &fds) < 0) if (virshFetchPassFdsList(ctl, cmd, &nfds, &fds) < 0)
return false; return false;
if (vshCommandOptBool(cmd, "paused")) if (vshCommandOptBool(cmd, "paused")) {
flags |= VIR_DOMAIN_START_PAUSED; flags |= VIR_DOMAIN_START_PAUSED;
#ifndef WIN32
} else if (console) {
flags |= VIR_DOMAIN_START_PAUSED;
resume_domain = true;
#endif
}
if (vshCommandOptBool(cmd, "autodestroy")) if (vshCommandOptBool(cmd, "autodestroy"))
flags |= VIR_DOMAIN_START_AUTODESTROY; flags |= VIR_DOMAIN_START_AUTODESTROY;
if (vshCommandOptBool(cmd, "bypass-cache")) if (vshCommandOptBool(cmd, "bypass-cache"))
@ -4096,12 +4119,7 @@ cmdStart(vshControl *ctl, const vshCmd *cmd)
/* We can emulate force boot, even for older servers that reject it. */ /* We can emulate force boot, even for older servers that reject it. */
if (flags & VIR_DOMAIN_START_FORCE_BOOT) { if (flags & VIR_DOMAIN_START_FORCE_BOOT) {
if (nfds > 0) { rc = virshDomainCreateHelper(dom, nfds, fds, flags);
rc = virDomainCreateWithFiles(dom, nfds, fds, flags);
} else {
rc = virDomainCreateWithFlags(dom, flags);
}
if (rc == 0) if (rc == 0)
goto started; goto started;
@ -4124,14 +4142,20 @@ cmdStart(vshControl *ctl, const vshCmd *cmd)
flags &= ~VIR_DOMAIN_START_FORCE_BOOT; flags &= ~VIR_DOMAIN_START_FORCE_BOOT;
} }
/* Prefer older API unless we have to pass a flag. */ rc = virshDomainCreateHelper(dom, nfds, fds, flags);
if (nfds > 0) { #ifndef WIN32
rc = virDomainCreateWithFiles(dom, nfds, fds, flags); /* If the driver does not support the paused flag, let's fallback to the old
} else if (flags != 0) { * behavior without the flag. */
rc = virDomainCreateWithFlags(dom, flags); if (rc < 0 && resume_domain &&
} else { last_error && last_error->code == VIR_ERR_INVALID_ARG) {
rc = virDomainCreate(dom);
vshResetLibvirtError();
flags &= ~VIR_DOMAIN_START_PAUSED;
resume_domain = false;
rc = virshDomainCreateHelper(dom, nfds, fds, flags);
} }
#endif
if (rc < 0) { if (rc < 0) {
vshError(ctl, _("Failed to start domain '%1$s'"), virDomainGetName(dom)); vshError(ctl, _("Failed to start domain '%1$s'"), virDomainGetName(dom));
@ -4142,7 +4166,7 @@ cmdStart(vshControl *ctl, const vshCmd *cmd)
vshPrintExtra(ctl, _("Domain '%1$s' started\n"), vshPrintExtra(ctl, _("Domain '%1$s' started\n"),
virDomainGetName(dom)); virDomainGetName(dom));
#ifndef WIN32 #ifndef WIN32
if (console && !cmdRunConsole(ctl, dom, NULL, false, 0)) if (console && !cmdRunConsole(ctl, dom, NULL, resume_domain, 0))
return false; return false;
#endif #endif