mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-07-30 21:47:18 +00:00
Support reboots with the QEMU driver
For controlled shutdown we issue a 'system_powerdown' command to the QEMU monitor. This triggers an ACPI event which (most) guest OS wire up to a controlled shutdown. There is no equiv ACPI event to trigger a controlled reboot. This patch attempts to fake a reboot. - In qemuDomainObjPrivatePtr we have a bool fakeReboot flag. - The virDomainReboot method sets this flag and then triggers a normal 'system_powerdown'. - The QEMU process is started with '-no-shutdown' so that the guest CPUs pause when it powers off the guest - When we receive the 'POWEROFF' event from QEMU JSON monitor if fakeReboot is not set we invoke the qemuProcessKill command and shutdown continues normally - If fakeReboot was set, we spawn a background thread which issues 'system_reset' to perform a warm reboot of the guest hardware. Then it issues 'cont' to start the CPUs again * src/qemu/qemu_command.c: Add -no-shutdown flag if we have JSON support * src/qemu/qemu_domain.h: Add 'fakeReboot' flag to qemuDomainObjPrivate struct * src/qemu/qemu_driver.c: Fake reboot using the system_powerdown command if JSON support is available * src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h, src/qemu/qemu_monitor_json.c, src/qemu/qemu_monitor_json.h, src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h: Add binding for system_reset command * src/qemu/qemu_process.c: Reset the guest & start CPUs if fakeReboot is set
This commit is contained in:
parent
b17b4afafd
commit
42f43592be
@ -3222,6 +3222,13 @@ qemuBuildCommandLine(virConnectPtr conn,
|
|||||||
def->onReboot != VIR_DOMAIN_LIFECYCLE_RESTART)
|
def->onReboot != VIR_DOMAIN_LIFECYCLE_RESTART)
|
||||||
virCommandAddArg(cmd, "-no-reboot");
|
virCommandAddArg(cmd, "-no-reboot");
|
||||||
|
|
||||||
|
/* If JSON monitor is enabled, we can receive an event
|
||||||
|
* when QEMU stops. If we use no-shutdown, then we can
|
||||||
|
* watch for this event and do a soft/warm reboot.
|
||||||
|
*/
|
||||||
|
if (monitor_json)
|
||||||
|
virCommandAddArg(cmd, "-no-shutdown");
|
||||||
|
|
||||||
if (!(def->features & (1 << VIR_DOMAIN_FEATURE_ACPI)))
|
if (!(def->features & (1 << VIR_DOMAIN_FEATURE_ACPI)))
|
||||||
virCommandAddArg(cmd, "-no-acpi");
|
virCommandAddArg(cmd, "-no-acpi");
|
||||||
|
|
||||||
|
@ -91,6 +91,8 @@ struct _qemuDomainObjPrivate {
|
|||||||
|
|
||||||
virBitmapPtr qemuCaps;
|
virBitmapPtr qemuCaps;
|
||||||
char *lockState;
|
char *lockState;
|
||||||
|
|
||||||
|
bool fakeReboot;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct qemuDomainWatchdogEvent
|
struct qemuDomainWatchdogEvent
|
||||||
|
@ -1428,7 +1428,7 @@ cleanup:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int qemudDomainShutdown(virDomainPtr dom) {
|
static int qemuDomainShutdown(virDomainPtr dom) {
|
||||||
struct qemud_driver *driver = dom->conn->privateData;
|
struct qemud_driver *driver = dom->conn->privateData;
|
||||||
virDomainObjPtr vm;
|
virDomainObjPtr vm;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
@ -1460,6 +1460,8 @@ static int qemudDomainShutdown(virDomainPtr dom) {
|
|||||||
ret = qemuMonitorSystemPowerdown(priv->mon);
|
ret = qemuMonitorSystemPowerdown(priv->mon);
|
||||||
qemuDomainObjExitMonitor(vm);
|
qemuDomainObjExitMonitor(vm);
|
||||||
|
|
||||||
|
priv->fakeReboot = false;
|
||||||
|
|
||||||
endjob:
|
endjob:
|
||||||
if (qemuDomainObjEndJob(vm) == 0)
|
if (qemuDomainObjEndJob(vm) == 0)
|
||||||
vm = NULL;
|
vm = NULL;
|
||||||
@ -1471,11 +1473,68 @@ cleanup:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int qemuDomainReboot(virDomainPtr dom, unsigned int flags) {
|
||||||
|
struct qemud_driver *driver = dom->conn->privateData;
|
||||||
|
virDomainObjPtr vm;
|
||||||
|
int ret = -1;
|
||||||
|
qemuDomainObjPrivatePtr priv;
|
||||||
|
|
||||||
|
virCheckFlags(0, -1);
|
||||||
|
|
||||||
|
qemuDriverLock(driver);
|
||||||
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
||||||
|
qemuDriverUnlock(driver);
|
||||||
|
|
||||||
|
if (!vm) {
|
||||||
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
||||||
|
virUUIDFormat(dom->uuid, uuidstr);
|
||||||
|
qemuReportError(VIR_ERR_NO_DOMAIN,
|
||||||
|
_("no domain with matching uuid '%s'"), uuidstr);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
priv = vm->privateData;
|
||||||
|
|
||||||
|
#if HAVE_YAJL
|
||||||
|
if (qemuCapsGet(priv->qemuCaps, QEMU_CAPS_MONITOR_JSON)) {
|
||||||
|
if (qemuDomainObjBeginJob(vm) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (!virDomainObjIsActive(vm)) {
|
||||||
|
qemuReportError(VIR_ERR_OPERATION_INVALID,
|
||||||
|
"%s", _("domain is not running"));
|
||||||
|
goto endjob;
|
||||||
|
}
|
||||||
|
|
||||||
|
qemuDomainObjEnterMonitor(vm);
|
||||||
|
ret = qemuMonitorSystemPowerdown(priv->mon);
|
||||||
|
qemuDomainObjExitMonitor(vm);
|
||||||
|
|
||||||
|
priv->fakeReboot = true;
|
||||||
|
|
||||||
|
endjob:
|
||||||
|
if (qemuDomainObjEndJob(vm) == 0)
|
||||||
|
vm = NULL;
|
||||||
|
} else {
|
||||||
|
#endif
|
||||||
|
qemuReportError(VIR_ERR_NO_SUPPORT, "%s",
|
||||||
|
_("Reboot is not supported without the JSON monitor"));
|
||||||
|
#if HAVE_YAJL
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
if (vm)
|
||||||
|
virDomainObjUnlock(vm);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int qemudDomainDestroy(virDomainPtr dom) {
|
static int qemudDomainDestroy(virDomainPtr dom) {
|
||||||
struct qemud_driver *driver = dom->conn->privateData;
|
struct qemud_driver *driver = dom->conn->privateData;
|
||||||
virDomainObjPtr vm;
|
virDomainObjPtr vm;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
virDomainEventPtr event = NULL;
|
virDomainEventPtr event = NULL;
|
||||||
|
qemuDomainObjPrivatePtr priv;
|
||||||
|
|
||||||
qemuDriverLock(driver);
|
qemuDriverLock(driver);
|
||||||
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
||||||
@ -1487,6 +1546,9 @@ static int qemudDomainDestroy(virDomainPtr dom) {
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
priv = vm->privateData;
|
||||||
|
priv->fakeReboot = false;
|
||||||
|
|
||||||
/* Although qemuProcessStop does this already, there may
|
/* Although qemuProcessStop does this already, there may
|
||||||
* be an outstanding job active. We want to make sure we
|
* be an outstanding job active. We want to make sure we
|
||||||
* can kill the process even if a job is active. Killing
|
* can kill the process even if a job is active. Killing
|
||||||
@ -8336,7 +8398,8 @@ static virDriver qemuDriver = {
|
|||||||
.domainLookupByName = qemudDomainLookupByName, /* 0.2.0 */
|
.domainLookupByName = qemudDomainLookupByName, /* 0.2.0 */
|
||||||
.domainSuspend = qemudDomainSuspend, /* 0.2.0 */
|
.domainSuspend = qemudDomainSuspend, /* 0.2.0 */
|
||||||
.domainResume = qemudDomainResume, /* 0.2.0 */
|
.domainResume = qemudDomainResume, /* 0.2.0 */
|
||||||
.domainShutdown = qemudDomainShutdown, /* 0.2.0 */
|
.domainShutdown = qemuDomainShutdown, /* 0.2.0 */
|
||||||
|
.domainReboot = qemuDomainReboot, /* 0.9.3 */
|
||||||
.domainDestroy = qemudDomainDestroy, /* 0.2.0 */
|
.domainDestroy = qemudDomainDestroy, /* 0.2.0 */
|
||||||
.domainGetOSType = qemudDomainGetOSType, /* 0.2.2 */
|
.domainGetOSType = qemudDomainGetOSType, /* 0.2.2 */
|
||||||
.domainGetMaxMemory = qemudDomainGetMaxMemory, /* 0.4.2 */
|
.domainGetMaxMemory = qemudDomainGetMaxMemory, /* 0.4.2 */
|
||||||
|
@ -1095,6 +1095,25 @@ int qemuMonitorSystemPowerdown(qemuMonitorPtr mon)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int qemuMonitorSystemReset(qemuMonitorPtr mon)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
VIR_DEBUG("mon=%p", mon);
|
||||||
|
|
||||||
|
if (!mon) {
|
||||||
|
qemuReportError(VIR_ERR_INVALID_ARG, "%s",
|
||||||
|
_("monitor must not be NULL"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mon->json)
|
||||||
|
ret = qemuMonitorJSONSystemReset(mon);
|
||||||
|
else
|
||||||
|
ret = qemuMonitorTextSystemReset(mon);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int qemuMonitorGetCPUInfo(qemuMonitorPtr mon,
|
int qemuMonitorGetCPUInfo(qemuMonitorPtr mon,
|
||||||
int **pids)
|
int **pids)
|
||||||
{
|
{
|
||||||
|
@ -194,6 +194,7 @@ int qemuMonitorStartCPUs(qemuMonitorPtr mon,
|
|||||||
int qemuMonitorStopCPUs(qemuMonitorPtr mon);
|
int qemuMonitorStopCPUs(qemuMonitorPtr mon);
|
||||||
int qemuMonitorGetStatus(qemuMonitorPtr mon, bool *running);
|
int qemuMonitorGetStatus(qemuMonitorPtr mon, bool *running);
|
||||||
|
|
||||||
|
int qemuMonitorSystemReset(qemuMonitorPtr mon);
|
||||||
int qemuMonitorSystemPowerdown(qemuMonitorPtr mon);
|
int qemuMonitorSystemPowerdown(qemuMonitorPtr mon);
|
||||||
|
|
||||||
int qemuMonitorGetCPUInfo(qemuMonitorPtr mon,
|
int qemuMonitorGetCPUInfo(qemuMonitorPtr mon,
|
||||||
|
@ -947,6 +947,25 @@ int qemuMonitorJSONSystemPowerdown(qemuMonitorPtr mon)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int qemuMonitorJSONSystemReset(qemuMonitorPtr mon)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("system_reset", NULL);
|
||||||
|
virJSONValuePtr reply = NULL;
|
||||||
|
if (!cmd)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ret = qemuMonitorJSONCommand(mon, cmd, &reply);
|
||||||
|
|
||||||
|
if (ret == 0)
|
||||||
|
ret = qemuMonitorJSONCheckError(cmd, reply);
|
||||||
|
|
||||||
|
virJSONValueFree(cmd);
|
||||||
|
virJSONValueFree(reply);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* [ { "CPU": 0, "current": true, "halted": false, "pc": 3227107138 },
|
* [ { "CPU": 0, "current": true, "halted": false, "pc": 3227107138 },
|
||||||
* { "CPU": 1, "current": false, "halted": true, "pc": 7108165 } ]
|
* { "CPU": 1, "current": false, "halted": true, "pc": 7108165 } ]
|
||||||
|
@ -49,6 +49,7 @@ int qemuMonitorJSONStopCPUs(qemuMonitorPtr mon);
|
|||||||
int qemuMonitorJSONGetStatus(qemuMonitorPtr mon, bool *running);
|
int qemuMonitorJSONGetStatus(qemuMonitorPtr mon, bool *running);
|
||||||
|
|
||||||
int qemuMonitorJSONSystemPowerdown(qemuMonitorPtr mon);
|
int qemuMonitorJSONSystemPowerdown(qemuMonitorPtr mon);
|
||||||
|
int qemuMonitorJSONSystemReset(qemuMonitorPtr mon);
|
||||||
|
|
||||||
int qemuMonitorJSONGetCPUInfo(qemuMonitorPtr mon,
|
int qemuMonitorJSONGetCPUInfo(qemuMonitorPtr mon,
|
||||||
int **pids);
|
int **pids);
|
||||||
|
@ -417,6 +417,19 @@ int qemuMonitorTextSystemPowerdown(qemuMonitorPtr mon) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int qemuMonitorTextSystemReset(qemuMonitorPtr mon) {
|
||||||
|
char *info;
|
||||||
|
|
||||||
|
if (qemuMonitorHMPCommand(mon, "system_reset", &info) < 0) {
|
||||||
|
qemuReportError(VIR_ERR_OPERATION_FAILED,
|
||||||
|
"%s", _("system reset operation failed"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
VIR_FREE(info);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int qemuMonitorTextGetCPUInfo(qemuMonitorPtr mon,
|
int qemuMonitorTextGetCPUInfo(qemuMonitorPtr mon,
|
||||||
int **pids)
|
int **pids)
|
||||||
{
|
{
|
||||||
|
@ -46,6 +46,7 @@ int qemuMonitorTextStopCPUs(qemuMonitorPtr mon);
|
|||||||
int qemuMonitorTextGetStatus(qemuMonitorPtr mon, bool *running);
|
int qemuMonitorTextGetStatus(qemuMonitorPtr mon, bool *running);
|
||||||
|
|
||||||
int qemuMonitorTextSystemPowerdown(qemuMonitorPtr mon);
|
int qemuMonitorTextSystemPowerdown(qemuMonitorPtr mon);
|
||||||
|
int qemuMonitorTextSystemReset(qemuMonitorPtr mon);
|
||||||
|
|
||||||
int qemuMonitorTextGetCPUInfo(qemuMonitorPtr mon,
|
int qemuMonitorTextGetCPUInfo(qemuMonitorPtr mon,
|
||||||
int **pids);
|
int **pids);
|
||||||
|
@ -353,13 +353,103 @@ qemuProcessHandleReset(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Since we have the '-no-shutdown' flag set, the
|
||||||
|
* QEMU process will currently have guest OS shutdown
|
||||||
|
* and the CPUS stopped. To fake the reboot, we thus
|
||||||
|
* want todo a reset of the virtual hardware, followed
|
||||||
|
* by restart of the CPUs. This should result in the
|
||||||
|
* guest OS booting up again
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
qemuProcessFakeReboot(void *opaque)
|
||||||
|
{
|
||||||
|
struct qemud_driver *driver = qemu_driver;
|
||||||
|
virDomainObjPtr vm = opaque;
|
||||||
|
qemuDomainObjPrivatePtr priv = vm->privateData;
|
||||||
|
virDomainEventPtr event = NULL;
|
||||||
|
int ret = -1;
|
||||||
|
VIR_DEBUG("vm=%p", vm);
|
||||||
|
qemuDriverLock(driver);
|
||||||
|
virDomainObjLock(vm);
|
||||||
|
if (qemuDomainObjBeginJob(vm) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (!virDomainObjIsActive(vm)) {
|
||||||
|
qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
|
_("guest unexpectedly quit"));
|
||||||
|
goto endjob;
|
||||||
|
}
|
||||||
|
|
||||||
|
qemuDomainObjEnterMonitorWithDriver(driver, vm);
|
||||||
|
if (qemuMonitorSystemReset(priv->mon) < 0) {
|
||||||
|
qemuDomainObjExitMonitorWithDriver(driver, vm);
|
||||||
|
goto endjob;
|
||||||
|
}
|
||||||
|
qemuDomainObjExitMonitorWithDriver(driver, vm);
|
||||||
|
|
||||||
|
if (!virDomainObjIsActive(vm)) {
|
||||||
|
qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
|
_("guest unexpectedly quit"));
|
||||||
|
goto endjob;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qemuProcessStartCPUs(driver, vm, NULL,
|
||||||
|
VIR_DOMAIN_RUNNING_BOOTED) < 0) {
|
||||||
|
if (virGetLastError() == NULL)
|
||||||
|
qemuReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"%s", _("resume operation failed"));
|
||||||
|
goto endjob;
|
||||||
|
}
|
||||||
|
event = virDomainEventNewFromObj(vm,
|
||||||
|
VIR_DOMAIN_EVENT_RESUMED,
|
||||||
|
VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
endjob:
|
||||||
|
if (qemuDomainObjEndJob(vm) == 0)
|
||||||
|
vm = NULL;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
if (vm) {
|
||||||
|
if (ret == -1)
|
||||||
|
qemuProcessKill(vm);
|
||||||
|
if (virDomainObjUnref(vm) > 0)
|
||||||
|
virDomainObjUnlock(vm);
|
||||||
|
}
|
||||||
|
if (event)
|
||||||
|
qemuDomainEventQueue(driver, event);
|
||||||
|
qemuDriverUnlock(driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
qemuProcessHandleShutdown(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
|
qemuProcessHandleShutdown(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
|
||||||
virDomainObjPtr vm)
|
virDomainObjPtr vm)
|
||||||
{
|
{
|
||||||
|
qemuDomainObjPrivatePtr priv = vm->privateData;
|
||||||
|
VIR_DEBUG("vm=%p", vm);
|
||||||
|
|
||||||
virDomainObjLock(vm);
|
virDomainObjLock(vm);
|
||||||
((qemuDomainObjPrivatePtr) vm->privateData)->gotShutdown = true;
|
priv->gotShutdown = true;
|
||||||
virDomainObjUnlock(vm);
|
if (priv->fakeReboot) {
|
||||||
|
virDomainObjRef(vm);
|
||||||
|
virThread th;
|
||||||
|
if (virThreadCreate(&th,
|
||||||
|
false,
|
||||||
|
qemuProcessFakeReboot,
|
||||||
|
vm) < 0) {
|
||||||
|
VIR_ERROR("Failed to create reboot thread, killing domain");
|
||||||
|
qemuProcessKill(vm);
|
||||||
|
if (virDomainObjUnref(vm) == 0)
|
||||||
|
vm = NULL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
qemuProcessKill(vm);
|
||||||
|
}
|
||||||
|
if (vm)
|
||||||
|
virDomainObjUnlock(vm);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -2087,6 +2177,11 @@ qemuProcessPrepareMonitorChr(struct qemud_driver *driver,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Precondition: Both driver and vm must be locked,
|
||||||
|
* and a job must be active. This method will call
|
||||||
|
* {Enter,Exit}MonitorWithDriver
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
qemuProcessStartCPUs(struct qemud_driver *driver, virDomainObjPtr vm,
|
qemuProcessStartCPUs(struct qemud_driver *driver, virDomainObjPtr vm,
|
||||||
virConnectPtr conn, virDomainRunningReason reason)
|
virConnectPtr conn, virDomainRunningReason reason)
|
||||||
@ -2349,6 +2444,7 @@ int qemuProcessStart(virConnectPtr conn,
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
vm->def->id = driver->nextvmid++;
|
vm->def->id = driver->nextvmid++;
|
||||||
|
priv->fakeReboot = false;
|
||||||
|
|
||||||
/* Run an early hook to set-up missing devices */
|
/* Run an early hook to set-up missing devices */
|
||||||
if (virHookPresent(VIR_HOOK_DRIVER_QEMU)) {
|
if (virHookPresent(VIR_HOOK_DRIVER_QEMU)) {
|
||||||
|
5
tests/qemuxml2argvdata/qemuxml2argv-monitor-json.args
Normal file
5
tests/qemuxml2argvdata/qemuxml2argv-monitor-json.args
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M \
|
||||||
|
pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -chardev socket,\
|
||||||
|
id=charmonitor,path=/tmp/test-monitor,server,nowait -mon chardev=charmonitor,\
|
||||||
|
id=monitor,mode=control -no-shutdown -no-acpi -boot c -hda /dev/hda1 -usb -device \
|
||||||
|
virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3
|
24
tests/qemuxml2argvdata/qemuxml2argv-monitor-json.xml
Normal file
24
tests/qemuxml2argvdata/qemuxml2argv-monitor-json.xml
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<domain type='qemu'>
|
||||||
|
<name>encryptdisk</name>
|
||||||
|
<uuid>496898a6-e6ff-f7c8-5dc2-3cf410945ee9</uuid>
|
||||||
|
<memory>219100</memory>
|
||||||
|
<currentMemory>219100</currentMemory>
|
||||||
|
<vcpu>1</vcpu>
|
||||||
|
<os>
|
||||||
|
<type arch='i686' machine='pc'>hvm</type>
|
||||||
|
<boot dev='hd'/>
|
||||||
|
</os>
|
||||||
|
<clock offset='utc'/>
|
||||||
|
<on_poweroff>destroy</on_poweroff>
|
||||||
|
<on_reboot>restart</on_reboot>
|
||||||
|
<on_crash>destroy</on_crash>
|
||||||
|
<devices>
|
||||||
|
<emulator>/usr/bin/qemu</emulator>
|
||||||
|
<disk type='file' device='disk'>
|
||||||
|
<driver name='qemu' type='qcow2'/>
|
||||||
|
<source file='/dev/hda1'/>
|
||||||
|
<target dev='hda'/>
|
||||||
|
</disk>
|
||||||
|
<memballoon model='virtio'/>
|
||||||
|
</devices>
|
||||||
|
</domain>
|
@ -27,6 +27,7 @@ static int testCompareXMLToArgvFiles(const char *xml,
|
|||||||
virBitmapPtr extraFlags,
|
virBitmapPtr extraFlags,
|
||||||
const char *migrateFrom,
|
const char *migrateFrom,
|
||||||
int migrateFd,
|
int migrateFd,
|
||||||
|
bool json,
|
||||||
bool expectError)
|
bool expectError)
|
||||||
{
|
{
|
||||||
char *expectargv = NULL;
|
char *expectargv = NULL;
|
||||||
@ -116,7 +117,7 @@ static int testCompareXMLToArgvFiles(const char *xml,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!(cmd = qemuBuildCommandLine(conn, &driver,
|
if (!(cmd = qemuBuildCommandLine(conn, &driver,
|
||||||
vmdef, &monitor_chr, false, extraFlags,
|
vmdef, &monitor_chr, json, extraFlags,
|
||||||
migrateFrom, migrateFd, NULL,
|
migrateFrom, migrateFd, NULL,
|
||||||
VIR_VM_OP_NO_OP)))
|
VIR_VM_OP_NO_OP)))
|
||||||
goto fail;
|
goto fail;
|
||||||
@ -168,6 +169,7 @@ struct testInfo {
|
|||||||
virBitmapPtr extraFlags;
|
virBitmapPtr extraFlags;
|
||||||
const char *migrateFrom;
|
const char *migrateFrom;
|
||||||
int migrateFd;
|
int migrateFd;
|
||||||
|
bool json;
|
||||||
bool expectError;
|
bool expectError;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -186,8 +188,8 @@ testCompareXMLToArgvHelper(const void *data)
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
result = testCompareXMLToArgvFiles(xml, args, info->extraFlags,
|
result = testCompareXMLToArgvFiles(xml, args, info->extraFlags,
|
||||||
info->migrateFrom, info->migrateFd,
|
info->migrateFrom, info->migrateFd,
|
||||||
info->expectError);
|
info->json, info->expectError);
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
free(xml);
|
free(xml);
|
||||||
@ -202,6 +204,7 @@ mymain(void)
|
|||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
char *map = NULL;
|
char *map = NULL;
|
||||||
|
bool json = false;
|
||||||
|
|
||||||
abs_top_srcdir = getenv("abs_top_srcdir");
|
abs_top_srcdir = getenv("abs_top_srcdir");
|
||||||
if (!abs_top_srcdir)
|
if (!abs_top_srcdir)
|
||||||
@ -229,7 +232,7 @@ mymain(void)
|
|||||||
# define DO_TEST_FULL(name, migrateFrom, migrateFd, expectError, ...) \
|
# define DO_TEST_FULL(name, migrateFrom, migrateFd, expectError, ...) \
|
||||||
do { \
|
do { \
|
||||||
struct testInfo info = { \
|
struct testInfo info = { \
|
||||||
name, NULL, migrateFrom, migrateFd, expectError \
|
name, NULL, migrateFrom, migrateFd, json, expectError \
|
||||||
}; \
|
}; \
|
||||||
if (!(info.extraFlags = qemuCapsNew())) \
|
if (!(info.extraFlags = qemuCapsNew())) \
|
||||||
return EXIT_FAILURE; \
|
return EXIT_FAILURE; \
|
||||||
@ -529,6 +532,11 @@ mymain(void)
|
|||||||
QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG,
|
QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG,
|
||||||
QEMU_CAPS_PCI_MULTIFUNCTION);
|
QEMU_CAPS_PCI_MULTIFUNCTION);
|
||||||
|
|
||||||
|
json = true;
|
||||||
|
DO_TEST("monitor-json", false, QEMU_CAPS_DEVICE,
|
||||||
|
QEMU_CAPS_CHARDEV, QEMU_CAPS_MONITOR_JSON, QEMU_CAPS_NODEFCONFIG);
|
||||||
|
json = false;
|
||||||
|
|
||||||
free(driver.stateDir);
|
free(driver.stateDir);
|
||||||
virCapabilitiesFree(driver.caps);
|
virCapabilitiesFree(driver.caps);
|
||||||
free(map);
|
free(map);
|
||||||
|
Loading…
Reference in New Issue
Block a user