mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-23 06:05:27 +00:00
qemu: Introduce qemuProcessLaunch
Once qemuProcessInit was called, qemuProcessLaunch will launch a new QEMU process with stopped virtual CPUs. Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
This commit is contained in:
parent
b5ffd224f1
commit
f618d662ca
@ -4560,16 +4560,28 @@ qemuProcessInit(virQEMUDriverPtr driver,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int qemuProcessStart(virConnectPtr conn,
|
/**
|
||||||
virQEMUDriverPtr driver,
|
* qemuProcessLaunch:
|
||||||
virDomainObjPtr vm,
|
*
|
||||||
qemuDomainAsyncJob asyncJob,
|
* Launch a new QEMU process with stopped virtual CPUs.
|
||||||
const char *migrateFrom,
|
*
|
||||||
int migrateFd,
|
* The caller is supposed to call qemuProcessStop with appropriate
|
||||||
const char *migratePath,
|
* flags in case of failure.
|
||||||
virDomainSnapshotObjPtr snapshot,
|
*
|
||||||
virNetDevVPortProfileOp vmop,
|
* Returns 0 on success,
|
||||||
unsigned int flags)
|
* -1 on error which happened before devices were labeled and thus
|
||||||
|
* there is no need to restore them,
|
||||||
|
* -2 on error requesting security labels to be restored.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
qemuProcessLaunch(virConnectPtr conn,
|
||||||
|
virQEMUDriverPtr driver,
|
||||||
|
virDomainObjPtr vm,
|
||||||
|
qemuDomainAsyncJob asyncJob,
|
||||||
|
qemuProcessIncomingDefPtr incoming,
|
||||||
|
virDomainSnapshotObjPtr snapshot,
|
||||||
|
virNetDevVPortProfileOp vmop,
|
||||||
|
unsigned int flags)
|
||||||
{
|
{
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
int rv;
|
int rv;
|
||||||
@ -4581,18 +4593,22 @@ int qemuProcessStart(virConnectPtr conn,
|
|||||||
struct qemuProcessHookData hookData;
|
struct qemuProcessHookData hookData;
|
||||||
size_t i;
|
size_t i;
|
||||||
char *nodeset = NULL;
|
char *nodeset = NULL;
|
||||||
unsigned int stop_flags;
|
virQEMUDriverConfigPtr cfg;
|
||||||
virQEMUDriverConfigPtr cfg = NULL;
|
|
||||||
virCapsPtr caps = NULL;
|
virCapsPtr caps = NULL;
|
||||||
unsigned int hostdev_flags = 0;
|
unsigned int hostdev_flags = 0;
|
||||||
size_t nnicindexes = 0;
|
size_t nnicindexes = 0;
|
||||||
int *nicindexes = NULL;
|
int *nicindexes = NULL;
|
||||||
qemuProcessIncomingDefPtr incoming = NULL;
|
|
||||||
|
|
||||||
VIR_DEBUG("vm=%p name=%s id=%d asyncJob=%d migrateFrom=%s migrateFd=%d "
|
VIR_DEBUG("vm=%p name=%s id=%d asyncJob=%d "
|
||||||
"migratePath=%s snapshot=%p vmop=%d flags=0x%x",
|
"incoming.launchURI=%s incoming.deferredURI=%s "
|
||||||
vm, vm->def->name, vm->def->id, asyncJob, NULLSTR(migrateFrom),
|
"incoming.fd=%d incoming.path=%s "
|
||||||
migrateFd, NULLSTR(migratePath), snapshot, vmop, flags);
|
"snapshot=%p vmop=%d flags=0x%x",
|
||||||
|
vm, vm->def->name, vm->def->id, asyncJob,
|
||||||
|
NULLSTR(incoming ? incoming->launchURI : NULL),
|
||||||
|
NULLSTR(incoming ? incoming->deferredURI : NULL),
|
||||||
|
incoming ? incoming->fd : -1,
|
||||||
|
NULLSTR(incoming ? incoming->path : NULL),
|
||||||
|
snapshot, vmop, flags);
|
||||||
|
|
||||||
/* Okay, these are just internal flags,
|
/* Okay, these are just internal flags,
|
||||||
* but doesn't hurt to check */
|
* but doesn't hurt to check */
|
||||||
@ -4600,21 +4616,8 @@ int qemuProcessStart(virConnectPtr conn,
|
|||||||
VIR_QEMU_PROCESS_START_PAUSED |
|
VIR_QEMU_PROCESS_START_PAUSED |
|
||||||
VIR_QEMU_PROCESS_START_AUTODESTROY, -1);
|
VIR_QEMU_PROCESS_START_AUTODESTROY, -1);
|
||||||
|
|
||||||
if (qemuProcessInit(driver, vm, !!migrateFrom))
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
cfg = virQEMUDriverGetConfig(driver);
|
cfg = virQEMUDriverGetConfig(driver);
|
||||||
|
|
||||||
/* From now on until domain security labeling is done:
|
|
||||||
* if any operation fails and we goto cleanup, we must not
|
|
||||||
* restore any security label as we would overwrite labels
|
|
||||||
* we did not set. */
|
|
||||||
stop_flags = VIR_QEMU_PROCESS_STOP_NO_RELABEL;
|
|
||||||
/* If we fail while doing incoming migration, then we must not
|
|
||||||
* relabel, as the source is still using the files. */
|
|
||||||
if (migrateFrom)
|
|
||||||
stop_flags |= VIR_QEMU_PROCESS_STOP_MIGRATED;
|
|
||||||
|
|
||||||
hookData.conn = conn;
|
hookData.conn = conn;
|
||||||
hookData.vm = vm;
|
hookData.vm = vm;
|
||||||
hookData.driver = driver;
|
hookData.driver = driver;
|
||||||
@ -4622,7 +4625,7 @@ int qemuProcessStart(virConnectPtr conn,
|
|||||||
hookData.cfg = cfg;
|
hookData.cfg = cfg;
|
||||||
|
|
||||||
if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
|
if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
|
||||||
goto error;
|
goto cleanup;
|
||||||
|
|
||||||
/* network devices must be "prepared" before hostdevs, because
|
/* network devices must be "prepared" before hostdevs, because
|
||||||
* setting up a network device might create a new hostdev that
|
* setting up a network device might create a new hostdev that
|
||||||
@ -4630,35 +4633,35 @@ int qemuProcessStart(virConnectPtr conn,
|
|||||||
*/
|
*/
|
||||||
VIR_DEBUG("Preparing network devices");
|
VIR_DEBUG("Preparing network devices");
|
||||||
if (qemuNetworkPrepareDevices(vm->def) < 0)
|
if (qemuNetworkPrepareDevices(vm->def) < 0)
|
||||||
goto error;
|
goto cleanup;
|
||||||
|
|
||||||
/* Must be run before security labelling */
|
/* Must be run before security labelling */
|
||||||
VIR_DEBUG("Preparing host devices");
|
VIR_DEBUG("Preparing host devices");
|
||||||
if (!cfg->relaxedACS)
|
if (!cfg->relaxedACS)
|
||||||
hostdev_flags |= VIR_HOSTDEV_STRICT_ACS_CHECK;
|
hostdev_flags |= VIR_HOSTDEV_STRICT_ACS_CHECK;
|
||||||
if (!migrateFrom)
|
if (!incoming)
|
||||||
hostdev_flags |= VIR_HOSTDEV_COLD_BOOT;
|
hostdev_flags |= VIR_HOSTDEV_COLD_BOOT;
|
||||||
if (qemuHostdevPrepareDomainDevices(driver, vm->def, priv->qemuCaps,
|
if (qemuHostdevPrepareDomainDevices(driver, vm->def, priv->qemuCaps,
|
||||||
hostdev_flags) < 0)
|
hostdev_flags) < 0)
|
||||||
goto error;
|
goto cleanup;
|
||||||
|
|
||||||
VIR_DEBUG("Preparing chr devices");
|
VIR_DEBUG("Preparing chr devices");
|
||||||
if (virDomainChrDefForeach(vm->def,
|
if (virDomainChrDefForeach(vm->def,
|
||||||
true,
|
true,
|
||||||
qemuProcessPrepareChardevDevice,
|
qemuProcessPrepareChardevDevice,
|
||||||
NULL) < 0)
|
NULL) < 0)
|
||||||
goto error;
|
goto cleanup;
|
||||||
|
|
||||||
VIR_DEBUG("Checking domain and device security labels");
|
VIR_DEBUG("Checking domain and device security labels");
|
||||||
if (virSecurityManagerCheckAllLabel(driver->securityManager, vm->def) < 0)
|
if (virSecurityManagerCheckAllLabel(driver->securityManager, vm->def) < 0)
|
||||||
goto error;
|
goto cleanup;
|
||||||
|
|
||||||
/* If you are using a SecurityDriver with dynamic labelling,
|
/* If you are using a SecurityDriver with dynamic labelling,
|
||||||
then generate a security label for isolation */
|
then generate a security label for isolation */
|
||||||
VIR_DEBUG("Generating domain security label (if required)");
|
VIR_DEBUG("Generating domain security label (if required)");
|
||||||
if (virSecurityManagerGenLabel(driver->securityManager, vm->def) < 0) {
|
if (virSecurityManagerGenLabel(driver->securityManager, vm->def) < 0) {
|
||||||
virDomainAuditSecurityLabel(vm, false);
|
virDomainAuditSecurityLabel(vm, false);
|
||||||
goto error;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
virDomainAuditSecurityLabel(vm, true);
|
virDomainAuditSecurityLabel(vm, true);
|
||||||
|
|
||||||
@ -4667,14 +4670,14 @@ int qemuProcessStart(virConnectPtr conn,
|
|||||||
char *hugepagePath = qemuGetHugepagePath(&cfg->hugetlbfs[i]);
|
char *hugepagePath = qemuGetHugepagePath(&cfg->hugetlbfs[i]);
|
||||||
|
|
||||||
if (!hugepagePath)
|
if (!hugepagePath)
|
||||||
goto error;
|
goto cleanup;
|
||||||
|
|
||||||
if (virSecurityManagerSetHugepages(driver->securityManager,
|
if (virSecurityManagerSetHugepages(driver->securityManager,
|
||||||
vm->def, hugepagePath) < 0) {
|
vm->def, hugepagePath) < 0) {
|
||||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
"%s", _("Unable to set huge path in security driver"));
|
"%s", _("Unable to set huge path in security driver"));
|
||||||
VIR_FREE(hugepagePath);
|
VIR_FREE(hugepagePath);
|
||||||
goto error;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
VIR_FREE(hugepagePath);
|
VIR_FREE(hugepagePath);
|
||||||
}
|
}
|
||||||
@ -4687,18 +4690,18 @@ int qemuProcessStart(virConnectPtr conn,
|
|||||||
|
|
||||||
VIR_DEBUG("Setting up ports for graphics");
|
VIR_DEBUG("Setting up ports for graphics");
|
||||||
if (qemuProcessSetupGraphics(driver, vm) < 0)
|
if (qemuProcessSetupGraphics(driver, vm) < 0)
|
||||||
goto error;
|
goto cleanup;
|
||||||
|
|
||||||
if (virFileMakePath(cfg->logDir) < 0) {
|
if (virFileMakePath(cfg->logDir) < 0) {
|
||||||
virReportSystemError(errno,
|
virReportSystemError(errno,
|
||||||
_("cannot create log directory %s"),
|
_("cannot create log directory %s"),
|
||||||
cfg->logDir);
|
cfg->logDir);
|
||||||
goto error;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
VIR_DEBUG("Creating domain log file");
|
VIR_DEBUG("Creating domain log file");
|
||||||
if ((logfile = qemuDomainCreateLog(driver, vm, false)) < 0)
|
if ((logfile = qemuDomainCreateLog(driver, vm, false)) < 0)
|
||||||
goto error;
|
goto cleanup;
|
||||||
|
|
||||||
if (vm->def->virtType == VIR_DOMAIN_VIRT_KVM) {
|
if (vm->def->virtType == VIR_DOMAIN_VIRT_KVM) {
|
||||||
VIR_DEBUG("Checking for KVM availability");
|
VIR_DEBUG("Checking for KVM availability");
|
||||||
@ -4707,15 +4710,15 @@ int qemuProcessStart(virConnectPtr conn,
|
|||||||
_("Domain requires KVM, but it is not available. "
|
_("Domain requires KVM, but it is not available. "
|
||||||
"Check that virtualization is enabled in the host BIOS, "
|
"Check that virtualization is enabled in the host BIOS, "
|
||||||
"and host configuration is setup to load the kvm modules."));
|
"and host configuration is setup to load the kvm modules."));
|
||||||
goto error;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!qemuValidateCpuMax(vm->def, priv->qemuCaps))
|
if (!qemuValidateCpuMax(vm->def, priv->qemuCaps))
|
||||||
goto error;
|
goto cleanup;
|
||||||
|
|
||||||
if (qemuAssignDeviceAliases(vm->def, priv->qemuCaps) < 0)
|
if (qemuAssignDeviceAliases(vm->def, priv->qemuCaps) < 0)
|
||||||
goto error;
|
goto cleanup;
|
||||||
|
|
||||||
/* Get the advisory nodeset from numad if 'placement' of
|
/* Get the advisory nodeset from numad if 'placement' of
|
||||||
* either <vcpu> or <numatune> is 'auto'.
|
* either <vcpu> or <numatune> is 'auto'.
|
||||||
@ -4724,48 +4727,48 @@ int qemuProcessStart(virConnectPtr conn,
|
|||||||
nodeset = virNumaGetAutoPlacementAdvice(vm->def->vcpus,
|
nodeset = virNumaGetAutoPlacementAdvice(vm->def->vcpus,
|
||||||
virDomainDefGetMemoryActual(vm->def));
|
virDomainDefGetMemoryActual(vm->def));
|
||||||
if (!nodeset)
|
if (!nodeset)
|
||||||
goto error;
|
goto cleanup;
|
||||||
|
|
||||||
VIR_DEBUG("Nodeset returned from numad: %s", nodeset);
|
VIR_DEBUG("Nodeset returned from numad: %s", nodeset);
|
||||||
|
|
||||||
if (virBitmapParse(nodeset, 0, &priv->autoNodeset,
|
if (virBitmapParse(nodeset, 0, &priv->autoNodeset,
|
||||||
VIR_DOMAIN_CPUMASK_LEN) < 0)
|
VIR_DOMAIN_CPUMASK_LEN) < 0)
|
||||||
goto error;
|
goto cleanup;
|
||||||
|
|
||||||
if (!(priv->autoCpuset = virCapabilitiesGetCpusForNodemask(caps,
|
if (!(priv->autoCpuset = virCapabilitiesGetCpusForNodemask(caps,
|
||||||
priv->autoNodeset)))
|
priv->autoNodeset)))
|
||||||
goto error;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!migrateFrom && !snapshot &&
|
if (!incoming && !snapshot &&
|
||||||
virDomainDefCheckDuplicateDiskInfo(vm->def) < 0)
|
virDomainDefCheckDuplicateDiskInfo(vm->def) < 0)
|
||||||
goto error;
|
goto cleanup;
|
||||||
|
|
||||||
/* "volume" type disk's source must be translated before
|
/* "volume" type disk's source must be translated before
|
||||||
* cgroup and security setting.
|
* cgroup and security setting.
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < vm->def->ndisks; i++) {
|
for (i = 0; i < vm->def->ndisks; i++) {
|
||||||
if (virStorageTranslateDiskSourcePool(conn, vm->def->disks[i]) < 0)
|
if (virStorageTranslateDiskSourcePool(conn, vm->def->disks[i]) < 0)
|
||||||
goto error;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qemuDomainCheckDiskPresence(driver, vm,
|
if (qemuDomainCheckDiskPresence(driver, vm,
|
||||||
flags & VIR_QEMU_PROCESS_START_COLD) < 0)
|
flags & VIR_QEMU_PROCESS_START_COLD) < 0)
|
||||||
goto error;
|
goto cleanup;
|
||||||
|
|
||||||
if (vm->def->mem.min_guarantee) {
|
if (vm->def->mem.min_guarantee) {
|
||||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||||
_("Parameter 'min_guarantee' "
|
_("Parameter 'min_guarantee' "
|
||||||
"not supported by QEMU."));
|
"not supported by QEMU."));
|
||||||
goto error;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (VIR_ALLOC(priv->monConfig) < 0)
|
if (VIR_ALLOC(priv->monConfig) < 0)
|
||||||
goto error;
|
goto cleanup;
|
||||||
|
|
||||||
VIR_DEBUG("Preparing monitor state");
|
VIR_DEBUG("Preparing monitor state");
|
||||||
if (qemuProcessPrepareMonitorChr(cfg, priv->monConfig, vm->def->name) < 0)
|
if (qemuProcessPrepareMonitorChr(cfg, priv->monConfig, vm->def->name) < 0)
|
||||||
goto error;
|
goto cleanup;
|
||||||
|
|
||||||
priv->monJSON = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_MONITOR_JSON);
|
priv->monJSON = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_MONITOR_JSON);
|
||||||
priv->monError = false;
|
priv->monError = false;
|
||||||
@ -4776,7 +4779,7 @@ int qemuProcessStart(virConnectPtr conn,
|
|||||||
if (!(priv->pidfile = virPidFileBuildPath(cfg->stateDir, vm->def->name))) {
|
if (!(priv->pidfile = virPidFileBuildPath(cfg->stateDir, vm->def->name))) {
|
||||||
virReportSystemError(errno,
|
virReportSystemError(errno,
|
||||||
"%s", _("Failed to build pidfile path."));
|
"%s", _("Failed to build pidfile path."));
|
||||||
goto error;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unlink(priv->pidfile) < 0 &&
|
if (unlink(priv->pidfile) < 0 &&
|
||||||
@ -4784,7 +4787,7 @@ int qemuProcessStart(virConnectPtr conn,
|
|||||||
virReportSystemError(errno,
|
virReportSystemError(errno,
|
||||||
_("Cannot remove stale PID file %s"),
|
_("Cannot remove stale PID file %s"),
|
||||||
priv->pidfile);
|
priv->pidfile);
|
||||||
goto error;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -4797,14 +4800,7 @@ int qemuProcessStart(virConnectPtr conn,
|
|||||||
if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
|
if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
|
||||||
VIR_DEBUG("Assigning domain PCI addresses");
|
VIR_DEBUG("Assigning domain PCI addresses");
|
||||||
if ((qemuDomainAssignAddresses(vm->def, priv->qemuCaps, vm)) < 0)
|
if ((qemuDomainAssignAddresses(vm->def, priv->qemuCaps, vm)) < 0)
|
||||||
goto error;
|
goto cleanup;
|
||||||
}
|
|
||||||
|
|
||||||
if (migrateFrom) {
|
|
||||||
incoming = qemuProcessIncomingDefNew(priv->qemuCaps, migrateFrom,
|
|
||||||
migrateFd, migratePath);
|
|
||||||
if (!incoming)
|
|
||||||
goto error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VIR_DEBUG("Building emulator command line");
|
VIR_DEBUG("Building emulator command line");
|
||||||
@ -4816,7 +4812,7 @@ int qemuProcessStart(virConnectPtr conn,
|
|||||||
qemuCheckFips(),
|
qemuCheckFips(),
|
||||||
priv->autoNodeset,
|
priv->autoNodeset,
|
||||||
&nnicindexes, &nicindexes)))
|
&nnicindexes, &nicindexes)))
|
||||||
goto error;
|
goto cleanup;
|
||||||
|
|
||||||
if (incoming && incoming->fd != -1)
|
if (incoming && incoming->fd != -1)
|
||||||
virCommandPassFD(cmd, incoming->fd, 0);
|
virCommandPassFD(cmd, incoming->fd, 0);
|
||||||
@ -4827,13 +4823,13 @@ int qemuProcessStart(virConnectPtr conn,
|
|||||||
*/
|
*/
|
||||||
if (qemuProcessMakeDir(driver, vm, cfg->libDir) < 0 ||
|
if (qemuProcessMakeDir(driver, vm, cfg->libDir) < 0 ||
|
||||||
qemuProcessMakeDir(driver, vm, cfg->channelTargetDir) < 0)
|
qemuProcessMakeDir(driver, vm, cfg->channelTargetDir) < 0)
|
||||||
goto error;
|
goto cleanup;
|
||||||
|
|
||||||
/* now that we know it is about to start call the hook if present */
|
/* now that we know it is about to start call the hook if present */
|
||||||
if (qemuProcessStartHook(driver, vm,
|
if (qemuProcessStartHook(driver, vm,
|
||||||
VIR_HOOK_QEMU_OP_START,
|
VIR_HOOK_QEMU_OP_START,
|
||||||
VIR_HOOK_SUBOP_BEGIN) < 0)
|
VIR_HOOK_SUBOP_BEGIN) < 0)
|
||||||
goto error;
|
goto cleanup;
|
||||||
|
|
||||||
qemuLogOperation(vm, "starting up", logfile, cmd);
|
qemuLogOperation(vm, "starting up", logfile, cmd);
|
||||||
|
|
||||||
@ -4850,7 +4846,7 @@ int qemuProcessStart(virConnectPtr conn,
|
|||||||
|
|
||||||
VIR_DEBUG("Setting up raw IO");
|
VIR_DEBUG("Setting up raw IO");
|
||||||
if (qemuProcessSetupRawIO(driver, vm, cmd) < 0)
|
if (qemuProcessSetupRawIO(driver, vm, cmd) < 0)
|
||||||
goto error;
|
goto cleanup;
|
||||||
|
|
||||||
virCommandSetPreExecHook(cmd, qemuProcessHook, &hookData);
|
virCommandSetPreExecHook(cmd, qemuProcessHook, &hookData);
|
||||||
virCommandSetMaxProcesses(cmd, cfg->maxProcesses);
|
virCommandSetMaxProcesses(cmd, cfg->maxProcesses);
|
||||||
@ -4860,7 +4856,7 @@ int qemuProcessStart(virConnectPtr conn,
|
|||||||
VIR_DEBUG("Setting up security labelling");
|
VIR_DEBUG("Setting up security labelling");
|
||||||
if (virSecurityManagerSetChildProcessLabel(driver->securityManager,
|
if (virSecurityManagerSetChildProcessLabel(driver->securityManager,
|
||||||
vm->def, cmd) < 0)
|
vm->def, cmd) < 0)
|
||||||
goto error;
|
goto cleanup;
|
||||||
|
|
||||||
virCommandSetOutputFD(cmd, &logfile);
|
virCommandSetOutputFD(cmd, &logfile);
|
||||||
virCommandSetErrorFD(cmd, &logfile);
|
virCommandSetErrorFD(cmd, &logfile);
|
||||||
@ -4870,7 +4866,7 @@ int qemuProcessStart(virConnectPtr conn,
|
|||||||
virCommandRequireHandshake(cmd);
|
virCommandRequireHandshake(cmd);
|
||||||
|
|
||||||
if (virSecurityManagerPreFork(driver->securityManager) < 0)
|
if (virSecurityManagerPreFork(driver->securityManager) < 0)
|
||||||
goto error;
|
goto cleanup;
|
||||||
rv = virCommandRun(cmd, NULL);
|
rv = virCommandRun(cmd, NULL);
|
||||||
virSecurityManagerPostFork(driver->securityManager);
|
virSecurityManagerPostFork(driver->securityManager);
|
||||||
|
|
||||||
@ -4890,37 +4886,38 @@ int qemuProcessStart(virConnectPtr conn,
|
|||||||
|
|
||||||
VIR_DEBUG("Writing early domain status to disk");
|
VIR_DEBUG("Writing early domain status to disk");
|
||||||
if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
|
if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
|
||||||
goto error;
|
goto cleanup;
|
||||||
|
|
||||||
VIR_DEBUG("Waiting for handshake from child");
|
VIR_DEBUG("Waiting for handshake from child");
|
||||||
if (virCommandHandshakeWait(cmd) < 0) {
|
if (virCommandHandshakeWait(cmd) < 0) {
|
||||||
/* Read errors from child that occurred between fork and exec. */
|
/* Read errors from child that occurred between fork and exec. */
|
||||||
qemuProcessReadChildErrors(driver, vm, pos);
|
qemuProcessReadChildErrors(driver, vm, pos);
|
||||||
goto error;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
VIR_DEBUG("Setting up domain cgroup (if required)");
|
VIR_DEBUG("Setting up domain cgroup (if required)");
|
||||||
if (qemuSetupCgroup(driver, vm, nnicindexes, nicindexes) < 0)
|
if (qemuSetupCgroup(driver, vm, nnicindexes, nicindexes) < 0)
|
||||||
goto error;
|
goto cleanup;
|
||||||
|
|
||||||
/* This must be done after cgroup placement to avoid resetting CPU
|
/* This must be done after cgroup placement to avoid resetting CPU
|
||||||
* affinity */
|
* affinity */
|
||||||
if (!vm->def->cputune.emulatorpin &&
|
if (!vm->def->cputune.emulatorpin &&
|
||||||
qemuProcessInitCpuAffinity(vm) < 0)
|
qemuProcessInitCpuAffinity(vm) < 0)
|
||||||
goto error;
|
goto cleanup;
|
||||||
|
|
||||||
VIR_DEBUG("Setting domain security labels");
|
VIR_DEBUG("Setting domain security labels");
|
||||||
if (virSecurityManagerSetAllLabel(driver->securityManager,
|
if (virSecurityManagerSetAllLabel(driver->securityManager,
|
||||||
vm->def, migratePath) < 0)
|
vm->def,
|
||||||
goto error;
|
incoming ? incoming->path : NULL) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
/* Security manager labeled all devices, therefore
|
/* Security manager labeled all devices, therefore
|
||||||
* if any operation from now on fails and we goto cleanup,
|
* if any operation from now on fails, we need to ask the caller to
|
||||||
* where virSecurityManagerRestoreAllLabel() is called
|
* restore labels.
|
||||||
* (hidden under qemuProcessStop) we need to restore labels. */
|
*/
|
||||||
stop_flags &= ~VIR_QEMU_PROCESS_STOP_NO_RELABEL;
|
ret = -2;
|
||||||
|
|
||||||
if (migrateFd != -1) {
|
if (incoming && incoming->fd != -1) {
|
||||||
/* if there's an fd to migrate from, and it's a pipe, put the
|
/* if there's an fd to migrate from, and it's a pipe, put the
|
||||||
* proper security label on it
|
* proper security label on it
|
||||||
*/
|
*/
|
||||||
@ -4928,43 +4925,44 @@ int qemuProcessStart(virConnectPtr conn,
|
|||||||
|
|
||||||
VIR_DEBUG("setting security label on pipe used for migration");
|
VIR_DEBUG("setting security label on pipe used for migration");
|
||||||
|
|
||||||
if (fstat(migrateFd, &stdin_sb) < 0) {
|
if (fstat(incoming->fd, &stdin_sb) < 0) {
|
||||||
virReportSystemError(errno,
|
virReportSystemError(errno,
|
||||||
_("cannot stat fd %d"), migrateFd);
|
_("cannot stat fd %d"), incoming->fd);
|
||||||
goto error;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
if (S_ISFIFO(stdin_sb.st_mode) &&
|
if (S_ISFIFO(stdin_sb.st_mode) &&
|
||||||
virSecurityManagerSetImageFDLabel(driver->securityManager, vm->def, migrateFd) < 0)
|
virSecurityManagerSetImageFDLabel(driver->securityManager,
|
||||||
goto error;
|
vm->def, incoming->fd) < 0)
|
||||||
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
VIR_DEBUG("Labelling done, completing handshake to child");
|
VIR_DEBUG("Labelling done, completing handshake to child");
|
||||||
if (virCommandHandshakeNotify(cmd) < 0)
|
if (virCommandHandshakeNotify(cmd) < 0)
|
||||||
goto error;
|
goto cleanup;
|
||||||
VIR_DEBUG("Handshake complete, child running");
|
VIR_DEBUG("Handshake complete, child running");
|
||||||
|
|
||||||
if (rv == -1) /* The VM failed to start; tear filters before taps */
|
if (rv == -1) /* The VM failed to start; tear filters before taps */
|
||||||
virDomainConfVMNWFilterTeardown(vm);
|
virDomainConfVMNWFilterTeardown(vm);
|
||||||
|
|
||||||
if (rv == -1) /* The VM failed to start */
|
if (rv == -1) /* The VM failed to start */
|
||||||
goto error;
|
goto cleanup;
|
||||||
|
|
||||||
VIR_DEBUG("Setting cgroup for emulator (if required)");
|
VIR_DEBUG("Setting cgroup for emulator (if required)");
|
||||||
if (qemuSetupCgroupForEmulator(vm) < 0)
|
if (qemuSetupCgroupForEmulator(vm) < 0)
|
||||||
goto error;
|
goto cleanup;
|
||||||
|
|
||||||
VIR_DEBUG("Setting affinity of emulator threads");
|
VIR_DEBUG("Setting affinity of emulator threads");
|
||||||
if (qemuProcessSetEmulatorAffinity(vm) < 0)
|
if (qemuProcessSetEmulatorAffinity(vm) < 0)
|
||||||
goto error;
|
goto cleanup;
|
||||||
|
|
||||||
VIR_DEBUG("Waiting for monitor to show up");
|
VIR_DEBUG("Waiting for monitor to show up");
|
||||||
if (qemuProcessWaitForMonitor(driver, vm, asyncJob, priv->qemuCaps, pos) < 0)
|
if (qemuProcessWaitForMonitor(driver, vm, asyncJob, priv->qemuCaps, pos) < 0)
|
||||||
goto error;
|
goto cleanup;
|
||||||
|
|
||||||
/* Failure to connect to agent shouldn't be fatal */
|
/* Failure to connect to agent shouldn't be fatal */
|
||||||
if ((rv = qemuConnectAgent(driver, vm)) < 0) {
|
if ((rv = qemuConnectAgent(driver, vm)) < 0) {
|
||||||
if (rv == -2)
|
if (rv == -2)
|
||||||
goto error;
|
goto cleanup;
|
||||||
|
|
||||||
VIR_WARN("Cannot connect to QEMU guest agent for %s",
|
VIR_WARN("Cannot connect to QEMU guest agent for %s",
|
||||||
vm->def->name);
|
vm->def->name);
|
||||||
@ -4974,50 +4972,50 @@ int qemuProcessStart(virConnectPtr conn,
|
|||||||
|
|
||||||
VIR_DEBUG("Detecting if required emulator features are present");
|
VIR_DEBUG("Detecting if required emulator features are present");
|
||||||
if (!qemuProcessVerifyGuestCPU(driver, vm, asyncJob))
|
if (!qemuProcessVerifyGuestCPU(driver, vm, asyncJob))
|
||||||
goto error;
|
goto cleanup;
|
||||||
|
|
||||||
VIR_DEBUG("Setting up post-init cgroup restrictions");
|
VIR_DEBUG("Setting up post-init cgroup restrictions");
|
||||||
if (qemuSetupCpusetMems(vm) < 0)
|
if (qemuSetupCpusetMems(vm) < 0)
|
||||||
goto error;
|
goto cleanup;
|
||||||
|
|
||||||
VIR_DEBUG("Detecting VCPU PIDs");
|
VIR_DEBUG("Detecting VCPU PIDs");
|
||||||
if (qemuProcessDetectVcpuPIDs(driver, vm, asyncJob) < 0)
|
if (qemuProcessDetectVcpuPIDs(driver, vm, asyncJob) < 0)
|
||||||
goto error;
|
goto cleanup;
|
||||||
|
|
||||||
VIR_DEBUG("Detecting IOThread PIDs");
|
VIR_DEBUG("Detecting IOThread PIDs");
|
||||||
if (qemuProcessDetectIOThreadPIDs(driver, vm, asyncJob) < 0)
|
if (qemuProcessDetectIOThreadPIDs(driver, vm, asyncJob) < 0)
|
||||||
goto error;
|
goto cleanup;
|
||||||
|
|
||||||
VIR_DEBUG("Setting cgroup for each VCPU (if required)");
|
VIR_DEBUG("Setting cgroup for each VCPU (if required)");
|
||||||
if (qemuSetupCgroupForVcpu(vm) < 0)
|
if (qemuSetupCgroupForVcpu(vm) < 0)
|
||||||
goto error;
|
goto cleanup;
|
||||||
|
|
||||||
VIR_DEBUG("Setting cgroup for each IOThread (if required)");
|
VIR_DEBUG("Setting cgroup for each IOThread (if required)");
|
||||||
if (qemuSetupCgroupForIOThreads(vm) < 0)
|
if (qemuSetupCgroupForIOThreads(vm) < 0)
|
||||||
goto error;
|
goto cleanup;
|
||||||
|
|
||||||
VIR_DEBUG("Setting VCPU affinities");
|
VIR_DEBUG("Setting VCPU affinities");
|
||||||
if (qemuProcessSetVcpuAffinities(vm) < 0)
|
if (qemuProcessSetVcpuAffinities(vm) < 0)
|
||||||
goto error;
|
goto cleanup;
|
||||||
|
|
||||||
VIR_DEBUG("Setting affinity of IOThread threads");
|
VIR_DEBUG("Setting affinity of IOThread threads");
|
||||||
if (qemuProcessSetIOThreadsAffinity(vm) < 0)
|
if (qemuProcessSetIOThreadsAffinity(vm) < 0)
|
||||||
goto error;
|
goto cleanup;
|
||||||
|
|
||||||
VIR_DEBUG("Setting scheduler parameters");
|
VIR_DEBUG("Setting scheduler parameters");
|
||||||
if (qemuProcessSetSchedulers(vm) < 0)
|
if (qemuProcessSetSchedulers(vm) < 0)
|
||||||
goto error;
|
goto cleanup;
|
||||||
|
|
||||||
VIR_DEBUG("Setting any required VM passwords");
|
VIR_DEBUG("Setting any required VM passwords");
|
||||||
if (qemuProcessInitPasswords(conn, driver, vm, asyncJob) < 0)
|
if (qemuProcessInitPasswords(conn, driver, vm, asyncJob) < 0)
|
||||||
goto error;
|
goto cleanup;
|
||||||
|
|
||||||
/* If we have -device, then addresses are assigned explicitly.
|
/* If we have -device, then addresses are assigned explicitly.
|
||||||
* If not, then we have to detect dynamic ones here */
|
* If not, then we have to detect dynamic ones here */
|
||||||
if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
|
if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
|
||||||
VIR_DEBUG("Determining domain device PCI addresses");
|
VIR_DEBUG("Determining domain device PCI addresses");
|
||||||
if (qemuProcessInitPCIAddresses(driver, vm, asyncJob) < 0)
|
if (qemuProcessInitPCIAddresses(driver, vm, asyncJob) < 0)
|
||||||
goto error;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set default link states */
|
/* set default link states */
|
||||||
@ -5025,72 +5023,34 @@ int qemuProcessStart(virConnectPtr conn,
|
|||||||
* enter the monitor */
|
* enter the monitor */
|
||||||
VIR_DEBUG("Setting network link states");
|
VIR_DEBUG("Setting network link states");
|
||||||
if (qemuProcessSetLinkStates(driver, vm, asyncJob) < 0)
|
if (qemuProcessSetLinkStates(driver, vm, asyncJob) < 0)
|
||||||
goto error;
|
goto cleanup;
|
||||||
|
|
||||||
VIR_DEBUG("Fetching list of active devices");
|
VIR_DEBUG("Fetching list of active devices");
|
||||||
if (qemuDomainUpdateDeviceList(driver, vm, asyncJob) < 0)
|
if (qemuDomainUpdateDeviceList(driver, vm, asyncJob) < 0)
|
||||||
goto error;
|
goto cleanup;
|
||||||
|
|
||||||
VIR_DEBUG("Updating info of memory devices");
|
VIR_DEBUG("Updating info of memory devices");
|
||||||
if (qemuDomainUpdateMemoryDeviceInfo(driver, vm, asyncJob) < 0)
|
if (qemuDomainUpdateMemoryDeviceInfo(driver, vm, asyncJob) < 0)
|
||||||
goto error;
|
goto cleanup;
|
||||||
|
|
||||||
VIR_DEBUG("Setting initial memory amount");
|
VIR_DEBUG("Setting initial memory amount");
|
||||||
if (qemuProcessSetupBalloon(driver, vm, asyncJob) < 0)
|
if (qemuProcessSetupBalloon(driver, vm, asyncJob) < 0)
|
||||||
goto error;
|
goto cleanup;
|
||||||
|
|
||||||
/* Since CPUs were not started yet, the balloon could not return the memory
|
/* Since CPUs were not started yet, the balloon could not return the memory
|
||||||
* to the host and thus cur_balloon needs to be updated so that GetXMLdesc
|
* to the host and thus cur_balloon needs to be updated so that GetXMLdesc
|
||||||
* and friends return the correct size in case they can't grab the job */
|
* and friends return the correct size in case they can't grab the job */
|
||||||
if (!incoming && !snapshot &&
|
if (!incoming && !snapshot &&
|
||||||
qemuProcessRefreshBalloonState(driver, vm, asyncJob) < 0)
|
qemuProcessRefreshBalloonState(driver, vm, asyncJob) < 0)
|
||||||
goto error;
|
goto cleanup;
|
||||||
|
|
||||||
VIR_DEBUG("Detecting actual memory size for video device");
|
VIR_DEBUG("Detecting actual memory size for video device");
|
||||||
if (qemuProcessUpdateVideoRamSize(driver, vm, asyncJob) < 0)
|
if (qemuProcessUpdateVideoRamSize(driver, vm, asyncJob) < 0)
|
||||||
goto error;
|
goto cleanup;
|
||||||
|
|
||||||
if (incoming &&
|
|
||||||
incoming->deferredURI &&
|
|
||||||
qemuMigrationRunIncoming(driver, vm, incoming->deferredURI, asyncJob) < 0)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
if (!(flags & VIR_QEMU_PROCESS_START_PAUSED)) {
|
|
||||||
VIR_DEBUG("Starting domain CPUs");
|
|
||||||
/* Allow the CPUS to start executing */
|
|
||||||
if (qemuProcessStartCPUs(driver, vm, conn,
|
|
||||||
VIR_DOMAIN_RUNNING_BOOTED,
|
|
||||||
asyncJob) < 0) {
|
|
||||||
if (virGetLastError() == NULL)
|
|
||||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
||||||
"%s", _("resume operation failed"));
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
virDomainObjSetState(vm, VIR_DOMAIN_PAUSED,
|
|
||||||
incoming ?
|
|
||||||
VIR_DOMAIN_PAUSED_MIGRATION :
|
|
||||||
VIR_DOMAIN_PAUSED_USER);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & VIR_QEMU_PROCESS_START_AUTODESTROY &&
|
if (flags & VIR_QEMU_PROCESS_START_AUTODESTROY &&
|
||||||
qemuProcessAutoDestroyAdd(driver, vm, conn) < 0)
|
qemuProcessAutoDestroyAdd(driver, vm, conn) < 0)
|
||||||
goto error;
|
goto cleanup;
|
||||||
|
|
||||||
VIR_DEBUG("Writing domain status to disk");
|
|
||||||
if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
/* finally we can call the 'started' hook script if any */
|
|
||||||
if (qemuProcessStartHook(driver, vm,
|
|
||||||
VIR_HOOK_QEMU_OP_STARTED,
|
|
||||||
VIR_HOOK_SUBOP_BEGIN) < 0)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
/* Keep watching qemu log for errors during incoming migration, otherwise
|
|
||||||
* unset reporting errors from qemu log. */
|
|
||||||
if (!incoming)
|
|
||||||
qemuMonitorSetDomainLog(priv->mon, -1);
|
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
@ -5101,14 +5061,111 @@ int qemuProcessStart(virConnectPtr conn,
|
|||||||
virObjectUnref(caps);
|
virObjectUnref(caps);
|
||||||
VIR_FREE(nicindexes);
|
VIR_FREE(nicindexes);
|
||||||
VIR_FREE(nodeset);
|
VIR_FREE(nodeset);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
qemuProcessStart(virConnectPtr conn,
|
||||||
|
virQEMUDriverPtr driver,
|
||||||
|
virDomainObjPtr vm,
|
||||||
|
qemuDomainAsyncJob asyncJob,
|
||||||
|
const char *migrateFrom,
|
||||||
|
int migrateFd,
|
||||||
|
const char *migratePath,
|
||||||
|
virDomainSnapshotObjPtr snapshot,
|
||||||
|
virNetDevVPortProfileOp vmop,
|
||||||
|
unsigned int flags)
|
||||||
|
{
|
||||||
|
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
|
||||||
|
qemuDomainObjPrivatePtr priv = vm->privateData;
|
||||||
|
qemuProcessIncomingDefPtr incoming = NULL;
|
||||||
|
unsigned int stopFlags;
|
||||||
|
bool relabel = false;
|
||||||
|
int ret = -1;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
VIR_DEBUG("conn=%p driver=%p vm=%p name=%s id=%d asyncJob=%s "
|
||||||
|
"migrateFrom=%s migrateFd=%d migratePath=%s "
|
||||||
|
"snapshot=%p vmop=%d flags=0x%x",
|
||||||
|
conn, driver, vm, vm->def->name, vm->def->id,
|
||||||
|
qemuDomainAsyncJobTypeToString(asyncJob),
|
||||||
|
NULLSTR(migrateFrom), migrateFd, NULLSTR(migratePath),
|
||||||
|
snapshot, vmop, flags);
|
||||||
|
|
||||||
|
virCheckFlagsGoto(VIR_QEMU_PROCESS_START_COLD |
|
||||||
|
VIR_QEMU_PROCESS_START_PAUSED |
|
||||||
|
VIR_QEMU_PROCESS_START_AUTODESTROY, cleanup);
|
||||||
|
|
||||||
|
if (qemuProcessInit(driver, vm, !!migrateFrom) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (migrateFrom) {
|
||||||
|
incoming = qemuProcessIncomingDefNew(priv->qemuCaps, migrateFrom,
|
||||||
|
migrateFd, migratePath);
|
||||||
|
if (!incoming)
|
||||||
|
goto stop;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((rv = qemuProcessLaunch(conn, driver, vm, asyncJob, incoming,
|
||||||
|
snapshot, vmop, flags)) < 0) {
|
||||||
|
if (rv == -1)
|
||||||
|
relabel = true;
|
||||||
|
goto stop;
|
||||||
|
}
|
||||||
|
relabel = true;
|
||||||
|
|
||||||
|
if (incoming &&
|
||||||
|
incoming->deferredURI &&
|
||||||
|
qemuMigrationRunIncoming(driver, vm, incoming->deferredURI, asyncJob) < 0)
|
||||||
|
goto stop;
|
||||||
|
|
||||||
|
if (!(flags & VIR_QEMU_PROCESS_START_PAUSED)) {
|
||||||
|
VIR_DEBUG("Starting domain CPUs");
|
||||||
|
/* Allow the CPUS to start executing */
|
||||||
|
if (qemuProcessStartCPUs(driver, vm, conn,
|
||||||
|
VIR_DOMAIN_RUNNING_BOOTED,
|
||||||
|
asyncJob) < 0) {
|
||||||
|
if (virGetLastError() == NULL)
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"%s", _("resume operation failed"));
|
||||||
|
goto stop;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
virDomainObjSetState(vm, VIR_DOMAIN_PAUSED,
|
||||||
|
incoming ?
|
||||||
|
VIR_DOMAIN_PAUSED_MIGRATION :
|
||||||
|
VIR_DOMAIN_PAUSED_USER);
|
||||||
|
}
|
||||||
|
|
||||||
|
VIR_DEBUG("Writing domain status to disk");
|
||||||
|
if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
|
||||||
|
goto stop;
|
||||||
|
|
||||||
|
if (qemuProcessStartHook(driver, vm,
|
||||||
|
VIR_HOOK_QEMU_OP_STARTED,
|
||||||
|
VIR_HOOK_SUBOP_BEGIN) < 0)
|
||||||
|
goto stop;
|
||||||
|
|
||||||
|
/* Keep watching qemu log for errors during incoming migration, otherwise
|
||||||
|
* unset reporting errors from qemu log. */
|
||||||
|
if (!incoming)
|
||||||
|
qemuMonitorSetDomainLog(priv->mon, -1);
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
virObjectUnref(cfg);
|
||||||
qemuProcessIncomingDefFree(incoming);
|
qemuProcessIncomingDefFree(incoming);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
error:
|
stop:
|
||||||
/* We jump here if we failed to start the VM for any reason, or
|
stopFlags = 0;
|
||||||
* if we failed to initialize the now running VM. kill it off and
|
if (!relabel)
|
||||||
* pretend we never started it */
|
stopFlags |= VIR_QEMU_PROCESS_STOP_NO_RELABEL;
|
||||||
qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED, stop_flags);
|
if (migrateFrom)
|
||||||
|
stopFlags |= VIR_QEMU_PROCESS_STOP_MIGRATED;
|
||||||
|
qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED, stopFlags);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,6 +85,15 @@ int qemuProcessInit(virQEMUDriverPtr driver,
|
|||||||
virDomainObjPtr vm,
|
virDomainObjPtr vm,
|
||||||
bool migration);
|
bool migration);
|
||||||
|
|
||||||
|
int qemuProcessLaunch(virConnectPtr conn,
|
||||||
|
virQEMUDriverPtr driver,
|
||||||
|
virDomainObjPtr vm,
|
||||||
|
qemuDomainAsyncJob asyncJob,
|
||||||
|
qemuProcessIncomingDefPtr incoming,
|
||||||
|
virDomainSnapshotObjPtr snapshot,
|
||||||
|
virNetDevVPortProfileOp vmop,
|
||||||
|
unsigned int flags);
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
VIR_QEMU_PROCESS_STOP_MIGRATED = 1 << 0,
|
VIR_QEMU_PROCESS_STOP_MIGRATED = 1 << 0,
|
||||||
VIR_QEMU_PROCESS_STOP_NO_RELABEL = 1 << 1,
|
VIR_QEMU_PROCESS_STOP_NO_RELABEL = 1 << 1,
|
||||||
|
Loading…
Reference in New Issue
Block a user