2012-08-20 12:31:29 +00:00
|
|
|
/*
|
2014-04-04 23:36:25 +00:00
|
|
|
* Copyright (C) 2011-2014 Red Hat, Inc.
|
2012-08-20 12:31:29 +00:00
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
2012-09-20 22:30:55 +00:00
|
|
|
* License along with this library. If not, see
|
2012-08-20 12:31:29 +00:00
|
|
|
* <http://www.gnu.org/licenses/>.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#include "testutils.h"
|
|
|
|
#include "testutilsqemu.h"
|
|
|
|
#include "qemumonitortestutils.h"
|
2016-05-20 05:21:04 +00:00
|
|
|
#include "qemu/qemu_domain.h"
|
2013-06-24 17:51:56 +00:00
|
|
|
#include "qemu/qemu_monitor_json.h"
|
2012-12-13 15:49:48 +00:00
|
|
|
#include "virthread.h"
|
2012-12-13 18:21:53 +00:00
|
|
|
#include "virerror.h"
|
2013-04-26 11:13:05 +00:00
|
|
|
#include "virstring.h"
|
2013-07-22 11:07:23 +00:00
|
|
|
#include "cpu/cpu.h"
|
2015-04-28 01:16:13 +00:00
|
|
|
#include "qemu/qemu_monitor.h"
|
2012-08-20 12:31:29 +00:00
|
|
|
|
|
|
|
#define VIR_FROM_THIS VIR_FROM_NONE
|
|
|
|
|
2013-09-18 15:28:31 +00:00
|
|
|
typedef struct _testQemuMonitorJSONSimpleFuncData testQemuMonitorJSONSimpleFuncData;
|
|
|
|
typedef testQemuMonitorJSONSimpleFuncData *testQemuMonitorJSONSimpleFuncDataPtr;
|
|
|
|
struct _testQemuMonitorJSONSimpleFuncData {
|
|
|
|
const char *cmd;
|
|
|
|
int (* func) (qemuMonitorPtr mon);
|
|
|
|
virDomainXMLOptionPtr xmlopt;
|
|
|
|
const char *reply;
|
|
|
|
};
|
|
|
|
|
2013-10-02 16:46:42 +00:00
|
|
|
const char *queryBlockReply =
|
|
|
|
"{"
|
|
|
|
" \"return\": ["
|
|
|
|
" {"
|
|
|
|
" \"io-status\": \"ok\","
|
|
|
|
" \"device\": \"drive-virtio-disk0\","
|
|
|
|
" \"locked\": false,"
|
|
|
|
" \"removable\": false,"
|
|
|
|
" \"inserted\": {"
|
|
|
|
" \"iops_rd\": 5,"
|
|
|
|
" \"iops_wr\": 6,"
|
|
|
|
" \"ro\": false,"
|
|
|
|
" \"backing_file_depth\": 0,"
|
|
|
|
" \"drv\": \"qcow2\","
|
|
|
|
" \"iops\": 4,"
|
|
|
|
" \"bps_wr\": 3,"
|
|
|
|
" \"encrypted\": false,"
|
|
|
|
" \"bps\": 1,"
|
|
|
|
" \"bps_rd\": 2,"
|
2014-12-03 13:42:27 +00:00
|
|
|
" \"bps_max\": 7,"
|
|
|
|
" \"iops_max\": 10,"
|
|
|
|
" \"bps_rd_max\": 8,"
|
|
|
|
" \"bps_wr_max\": 9,"
|
|
|
|
" \"iops_rd_max\": 11,"
|
|
|
|
" \"iops_wr_max\": 12,"
|
|
|
|
" \"iops_size\": 13,"
|
2016-10-31 21:22:59 +00:00
|
|
|
" \"group\": \"group14\","
|
|
|
|
" \"bps_max_length\": 15,"
|
|
|
|
" \"bps_rd_max_length\": 16,"
|
|
|
|
" \"bps_wr_max_length\": 17,"
|
|
|
|
" \"iops_max_length\": 18,"
|
|
|
|
" \"iops_rd_max_length\": 19,"
|
|
|
|
" \"iops_wr_max_length\": 20,"
|
2013-10-02 16:46:42 +00:00
|
|
|
" \"file\": \"/home/zippy/work/tmp/gentoo.qcow2\","
|
|
|
|
" \"encryption_key_missing\": false"
|
|
|
|
" },"
|
|
|
|
" \"type\": \"unknown\""
|
|
|
|
" },"
|
|
|
|
" {"
|
|
|
|
" \"io-status\": \"ok\","
|
|
|
|
" \"device\": \"drive-virtio-disk1\","
|
|
|
|
" \"locked\": false,"
|
|
|
|
" \"removable\": false,"
|
|
|
|
" \"inserted\": {"
|
|
|
|
" \"iops_rd\": 0,"
|
|
|
|
" \"iops_wr\": 0,"
|
|
|
|
" \"ro\": false,"
|
|
|
|
" \"backing_file_depth\": 0,"
|
|
|
|
" \"drv\": \"raw\","
|
|
|
|
" \"iops\": 0,"
|
|
|
|
" \"bps_wr\": 0,"
|
|
|
|
" \"encrypted\": false,"
|
|
|
|
" \"bps\": 0,"
|
|
|
|
" \"bps_rd\": 0,"
|
|
|
|
" \"file\": \"/home/zippy/test.bin\","
|
|
|
|
" \"encryption_key_missing\": false"
|
|
|
|
" },"
|
|
|
|
" \"type\": \"unknown\""
|
|
|
|
" },"
|
|
|
|
" {"
|
|
|
|
" \"io-status\": \"ok\","
|
|
|
|
" \"device\": \"drive-ide0-1-0\","
|
|
|
|
" \"locked\": true,"
|
|
|
|
" \"removable\": true,"
|
|
|
|
" \"inserted\": {"
|
|
|
|
" \"iops_rd\": 0,"
|
|
|
|
" \"iops_wr\": 0,"
|
|
|
|
" \"ro\": true,"
|
|
|
|
" \"backing_file_depth\": 0,"
|
|
|
|
" \"drv\": \"raw\","
|
|
|
|
" \"iops\": 0,"
|
|
|
|
" \"bps_wr\": 0,"
|
|
|
|
" \"encrypted\": false,"
|
|
|
|
" \"bps\": 0,"
|
|
|
|
" \"bps_rd\": 0,"
|
|
|
|
" \"file\": \"/home/zippy/tmp/install-amd64-minimal-20121210.iso\","
|
|
|
|
" \"encryption_key_missing\": false"
|
|
|
|
" },"
|
|
|
|
" \"tray_open\": false,"
|
|
|
|
" \"type\": \"unknown\""
|
2016-05-19 12:57:41 +00:00
|
|
|
" },"
|
|
|
|
" {"
|
|
|
|
" \"io-status\": \"ok\","
|
|
|
|
" \"device\": \"drive-ide0-1-1\","
|
|
|
|
" \"locked\": false,"
|
|
|
|
" \"removable\": true,"
|
|
|
|
" \"tray_open\": false,"
|
|
|
|
" \"type\": \"unknown\""
|
2013-10-02 16:46:42 +00:00
|
|
|
" }"
|
|
|
|
" ],"
|
|
|
|
" \"id\": \"libvirt-10\""
|
|
|
|
"}";
|
|
|
|
|
2012-08-20 12:31:29 +00:00
|
|
|
static int
|
|
|
|
testQemuMonitorJSONGetStatus(const void *data)
|
|
|
|
{
|
2013-03-31 18:03:42 +00:00
|
|
|
virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
|
2013-07-25 17:17:44 +00:00
|
|
|
qemuMonitorTestPtr test = qemuMonitorTestNewSimple(true, xmlopt);
|
2012-08-20 12:31:29 +00:00
|
|
|
int ret = -1;
|
|
|
|
bool running = false;
|
|
|
|
virDomainPausedReason reason = 0;
|
|
|
|
|
|
|
|
if (!test)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (qemuMonitorTestAddItem(test, "query-status",
|
|
|
|
"{ "
|
|
|
|
" \"return\": { "
|
|
|
|
" \"status\": \"running\", "
|
|
|
|
" \"singlestep\": false, "
|
|
|
|
" \"running\": true "
|
|
|
|
" } "
|
|
|
|
"}") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
if (qemuMonitorTestAddItem(test, "query-status",
|
|
|
|
"{ "
|
|
|
|
" \"return\": { "
|
|
|
|
" \"singlestep\": false, "
|
|
|
|
" \"running\": false "
|
|
|
|
" } "
|
|
|
|
"}") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
if (qemuMonitorTestAddItem(test, "query-status",
|
|
|
|
"{ "
|
|
|
|
" \"return\": { "
|
|
|
|
" \"status\": \"inmigrate\", "
|
|
|
|
" \"singlestep\": false, "
|
|
|
|
" \"running\": false "
|
|
|
|
" } "
|
|
|
|
"}") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (qemuMonitorGetStatus(qemuMonitorTestGetMonitor(test),
|
|
|
|
&running, &reason) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!running) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
"Running was not true");
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (reason != VIR_DOMAIN_PAUSED_UNKNOWN) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Reason was unexpectedly set to %d", reason);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (qemuMonitorGetStatus(qemuMonitorTestGetMonitor(test),
|
|
|
|
&running, &reason) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (running) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
"Running was not false");
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (reason != VIR_DOMAIN_PAUSED_UNKNOWN) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Reason was unexpectedly set to %d", reason);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (qemuMonitorGetStatus(qemuMonitorTestGetMonitor(test),
|
|
|
|
&running, &reason) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (running) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
"Running was not false");
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (reason != VIR_DOMAIN_PAUSED_MIGRATION) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Reason was unexpectedly set to %d", reason);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 06:53:44 +00:00
|
|
|
cleanup:
|
2012-08-20 12:31:29 +00:00
|
|
|
qemuMonitorTestFree(test);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2012-08-15 14:04:09 +00:00
|
|
|
static int
|
|
|
|
testQemuMonitorJSONGetVersion(const void *data)
|
|
|
|
{
|
2013-03-31 18:03:42 +00:00
|
|
|
virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
|
2013-07-25 17:17:44 +00:00
|
|
|
qemuMonitorTestPtr test = qemuMonitorTestNewSimple(true, xmlopt);
|
2012-08-15 14:04:09 +00:00
|
|
|
int ret = -1;
|
|
|
|
int major;
|
|
|
|
int minor;
|
|
|
|
int micro;
|
2013-02-04 16:17:52 +00:00
|
|
|
char *package = NULL;
|
2012-08-15 14:04:09 +00:00
|
|
|
|
|
|
|
if (!test)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (qemuMonitorTestAddItem(test, "query-version",
|
|
|
|
"{ "
|
|
|
|
" \"return\":{ "
|
|
|
|
" \"qemu\":{ "
|
|
|
|
" \"major\":1, "
|
|
|
|
" \"minor\":2, "
|
|
|
|
" \"micro\":3 "
|
|
|
|
" },"
|
|
|
|
" \"package\":\"\""
|
|
|
|
" }"
|
|
|
|
"}") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (qemuMonitorTestAddItem(test, "query-version",
|
|
|
|
"{ "
|
|
|
|
" \"return\":{ "
|
|
|
|
" \"qemu\":{ "
|
|
|
|
" \"major\":0, "
|
|
|
|
" \"minor\":11, "
|
|
|
|
" \"micro\":6 "
|
|
|
|
" },"
|
|
|
|
" \"package\":\"2.283.el6\""
|
|
|
|
" }"
|
|
|
|
"}") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (qemuMonitorGetVersion(qemuMonitorTestGetMonitor(test),
|
|
|
|
&major, &minor, µ,
|
|
|
|
&package) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (major != 1) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Major %d was not 1", major);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
if (minor != 2) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Minor %d was not 2", major);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
if (micro != 3) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Micro %d was not 3", major);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (STRNEQ(package, "")) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Package %s was not ''", package);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2013-02-04 16:17:52 +00:00
|
|
|
VIR_FREE(package);
|
2012-08-15 14:04:09 +00:00
|
|
|
|
|
|
|
if (qemuMonitorGetVersion(qemuMonitorTestGetMonitor(test),
|
|
|
|
&major, &minor, µ,
|
|
|
|
&package) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (major != 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Major %d was not 0", major);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
if (minor != 11) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Minor %d was not 11", major);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
if (micro != 6) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Micro %d was not 6", major);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (STRNEQ(package, "2.283.el6")) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Package %s was not '2.283.el6'", package);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 06:53:44 +00:00
|
|
|
cleanup:
|
2012-08-15 14:04:09 +00:00
|
|
|
qemuMonitorTestFree(test);
|
2013-02-04 16:17:52 +00:00
|
|
|
VIR_FREE(package);
|
2012-08-15 14:04:09 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2012-08-15 15:18:41 +00:00
|
|
|
static int
|
|
|
|
testQemuMonitorJSONGetMachines(const void *data)
|
|
|
|
{
|
2013-03-31 18:03:42 +00:00
|
|
|
virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
|
2013-07-25 17:17:44 +00:00
|
|
|
qemuMonitorTestPtr test = qemuMonitorTestNewSimple(true, xmlopt);
|
2012-08-15 15:18:41 +00:00
|
|
|
int ret = -1;
|
|
|
|
qemuMonitorMachineInfoPtr *info;
|
2013-02-04 16:17:52 +00:00
|
|
|
int ninfo = 0;
|
2012-08-15 15:18:41 +00:00
|
|
|
const char *null = NULL;
|
Convert 'int i' to 'size_t i' in tests/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
size_t i;
|
2012-08-15 15:18:41 +00:00
|
|
|
|
|
|
|
if (!test)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (qemuMonitorTestAddItem(test, "query-machines",
|
|
|
|
"{ "
|
|
|
|
" \"return\": [ "
|
|
|
|
" { "
|
|
|
|
" \"name\": \"pc-1.0\" "
|
|
|
|
" }, "
|
|
|
|
" { "
|
|
|
|
" \"name\": \"pc-1.1\" "
|
|
|
|
" }, "
|
|
|
|
" { "
|
|
|
|
" \"name\": \"pc-1.2\", "
|
|
|
|
" \"is-default\": true, "
|
|
|
|
" \"alias\": \"pc\" "
|
|
|
|
" } "
|
|
|
|
" ]"
|
|
|
|
"}") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if ((ninfo = qemuMonitorGetMachines(qemuMonitorTestGetMonitor(test),
|
|
|
|
&info)) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (ninfo != 3) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"ninfo %d is not 3", ninfo);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define CHECK(i, wantname, wantisDefault, wantalias) \
|
|
|
|
do { \
|
|
|
|
if (STRNEQ(info[i]->name, (wantname))) { \
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, \
|
|
|
|
"name %s is not %s", \
|
|
|
|
info[i]->name, (wantname)); \
|
|
|
|
goto cleanup; \
|
|
|
|
} \
|
|
|
|
if (info[i]->isDefault != (wantisDefault)) { \
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, \
|
|
|
|
"isDefault %d is not %d", \
|
|
|
|
info[i]->isDefault, (wantisDefault)); \
|
|
|
|
goto cleanup; \
|
|
|
|
} \
|
|
|
|
if (STRNEQ_NULLABLE(info[i]->alias, (wantalias))) { \
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, \
|
|
|
|
"alias %s is not %s", \
|
|
|
|
info[i]->alias, NULLSTR(wantalias)); \
|
|
|
|
goto cleanup; \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
CHECK(0, "pc-1.0", false, null);
|
|
|
|
CHECK(1, "pc-1.1", false, null);
|
|
|
|
CHECK(2, "pc-1.2", true, "pc");
|
|
|
|
|
|
|
|
#undef CHECK
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 06:53:44 +00:00
|
|
|
cleanup:
|
2012-08-15 15:18:41 +00:00
|
|
|
qemuMonitorTestFree(test);
|
2013-02-04 16:17:52 +00:00
|
|
|
for (i = 0; i < ninfo; i++)
|
|
|
|
qemuMonitorMachineInfoFree(info[i]);
|
|
|
|
VIR_FREE(info);
|
|
|
|
|
2012-08-15 15:18:41 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-08-20 14:58:20 +00:00
|
|
|
static int
|
|
|
|
testQemuMonitorJSONGetCPUDefinitions(const void *data)
|
|
|
|
{
|
2013-03-31 18:03:42 +00:00
|
|
|
virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
|
2013-07-25 17:17:44 +00:00
|
|
|
qemuMonitorTestPtr test = qemuMonitorTestNewSimple(true, xmlopt);
|
2012-08-20 14:58:20 +00:00
|
|
|
int ret = -1;
|
2016-04-21 10:51:01 +00:00
|
|
|
qemuMonitorCPUDefInfoPtr *cpus = NULL;
|
2013-02-04 16:17:52 +00:00
|
|
|
int ncpus = 0;
|
Convert 'int i' to 'size_t i' in tests/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
size_t i;
|
2012-08-20 14:58:20 +00:00
|
|
|
|
|
|
|
if (!test)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (qemuMonitorTestAddItem(test, "query-cpu-definitions",
|
|
|
|
"{ "
|
|
|
|
" \"return\": [ "
|
|
|
|
" { "
|
|
|
|
" \"name\": \"qemu64\" "
|
|
|
|
" }, "
|
|
|
|
" { "
|
2016-04-21 11:08:12 +00:00
|
|
|
" \"name\": \"Opteron_G4\", "
|
|
|
|
" \"unavailable-features\": [\"vme\"]"
|
2012-08-20 14:58:20 +00:00
|
|
|
" }, "
|
|
|
|
" { "
|
2016-04-21 11:08:12 +00:00
|
|
|
" \"name\": \"Westmere\", "
|
|
|
|
" \"unavailable-features\": []"
|
2012-08-20 14:58:20 +00:00
|
|
|
" } "
|
|
|
|
" ]"
|
|
|
|
"}") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if ((ncpus = qemuMonitorGetCPUDefinitions(qemuMonitorTestGetMonitor(test),
|
|
|
|
&cpus)) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (ncpus != 3) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"ncpus %d is not 3", ncpus);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2016-04-21 11:08:12 +00:00
|
|
|
#define CHECK_FULL(i, wantname, Usable) \
|
2012-08-20 14:58:20 +00:00
|
|
|
do { \
|
2016-04-21 10:51:01 +00:00
|
|
|
if (STRNEQ(cpus[i]->name, (wantname))) { \
|
2012-08-20 14:58:20 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, \
|
|
|
|
"name %s is not %s", \
|
2016-04-21 10:51:01 +00:00
|
|
|
cpus[i]->name, (wantname)); \
|
2012-08-20 14:58:20 +00:00
|
|
|
goto cleanup; \
|
|
|
|
} \
|
2016-04-21 11:08:12 +00:00
|
|
|
if (cpus[i]->usable != (Usable)) { \
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, \
|
|
|
|
"%s: expecting usable flag %d, got %d", \
|
|
|
|
cpus[i]->name, Usable, cpus[i]->usable); \
|
|
|
|
goto cleanup; \
|
|
|
|
} \
|
2012-08-20 14:58:20 +00:00
|
|
|
} while (0)
|
|
|
|
|
2016-04-21 11:08:12 +00:00
|
|
|
#define CHECK(i, wantname) \
|
|
|
|
CHECK_FULL(i, wantname, VIR_TRISTATE_BOOL_ABSENT)
|
|
|
|
|
|
|
|
#define CHECK_USABLE(i, wantname, usable) \
|
|
|
|
CHECK_FULL(i, wantname, \
|
|
|
|
usable ? VIR_TRISTATE_BOOL_YES : VIR_TRISTATE_BOOL_NO)
|
|
|
|
|
2012-08-20 14:58:20 +00:00
|
|
|
CHECK(0, "qemu64");
|
2016-04-21 11:08:12 +00:00
|
|
|
CHECK_USABLE(1, "Opteron_G4", false);
|
|
|
|
CHECK_USABLE(2, "Westmere", true);
|
2012-08-20 14:58:20 +00:00
|
|
|
|
|
|
|
#undef CHECK
|
2016-04-21 11:08:12 +00:00
|
|
|
#undef CHECK_USABLE
|
|
|
|
#undef CHECK_FULL
|
2012-08-20 14:58:20 +00:00
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 06:53:44 +00:00
|
|
|
cleanup:
|
2012-08-20 14:58:20 +00:00
|
|
|
qemuMonitorTestFree(test);
|
2013-02-04 16:17:52 +00:00
|
|
|
for (i = 0; i < ncpus; i++)
|
2016-04-21 10:51:01 +00:00
|
|
|
qemuMonitorCPUDefInfoFree(cpus[i]);
|
2013-02-04 16:17:52 +00:00
|
|
|
VIR_FREE(cpus);
|
2012-08-20 14:58:20 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-08-22 09:25:20 +00:00
|
|
|
static int
|
|
|
|
testQemuMonitorJSONGetCommands(const void *data)
|
|
|
|
{
|
2013-03-31 18:03:42 +00:00
|
|
|
virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
|
2013-07-25 17:17:44 +00:00
|
|
|
qemuMonitorTestPtr test = qemuMonitorTestNewSimple(true, xmlopt);
|
2012-08-22 09:25:20 +00:00
|
|
|
int ret = -1;
|
|
|
|
char **commands = NULL;
|
2013-02-04 16:17:52 +00:00
|
|
|
int ncommands = 0;
|
Convert 'int i' to 'size_t i' in tests/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
size_t i;
|
2012-08-22 09:25:20 +00:00
|
|
|
|
|
|
|
if (!test)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (qemuMonitorTestAddItem(test, "query-commands",
|
|
|
|
"{ "
|
|
|
|
" \"return\": [ "
|
|
|
|
" { "
|
|
|
|
" \"name\": \"system_wakeup\" "
|
|
|
|
" }, "
|
|
|
|
" { "
|
|
|
|
" \"name\": \"cont\" "
|
|
|
|
" }, "
|
|
|
|
" { "
|
|
|
|
" \"name\": \"quit\" "
|
|
|
|
" } "
|
|
|
|
" ]"
|
|
|
|
"}") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if ((ncommands = qemuMonitorGetCommands(qemuMonitorTestGetMonitor(test),
|
|
|
|
&commands)) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (ncommands != 3) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"ncommands %d is not 3", ncommands);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define CHECK(i, wantname) \
|
|
|
|
do { \
|
|
|
|
if (STRNEQ(commands[i], (wantname))) { \
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, \
|
|
|
|
"name %s is not %s", \
|
|
|
|
commands[i], (wantname)); \
|
|
|
|
goto cleanup; \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
CHECK(0, "system_wakeup");
|
|
|
|
CHECK(1, "cont");
|
|
|
|
CHECK(2, "quit");
|
|
|
|
|
|
|
|
#undef CHECK
|
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 06:53:44 +00:00
|
|
|
cleanup:
|
2012-08-22 09:25:20 +00:00
|
|
|
qemuMonitorTestFree(test);
|
2013-02-04 16:17:52 +00:00
|
|
|
for (i = 0; i < ncommands; i++)
|
|
|
|
VIR_FREE(commands[i]);
|
|
|
|
VIR_FREE(commands);
|
2012-08-22 09:25:20 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-04-26 11:13:05 +00:00
|
|
|
static int
|
|
|
|
testQemuMonitorJSONGetTPMModels(const void *data)
|
|
|
|
{
|
2013-10-05 01:40:19 +00:00
|
|
|
virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
|
2013-07-25 17:17:44 +00:00
|
|
|
qemuMonitorTestPtr test = qemuMonitorTestNewSimple(true, xmlopt);
|
2013-04-26 11:13:05 +00:00
|
|
|
int ret = -1;
|
|
|
|
char **tpmmodels = NULL;
|
|
|
|
int ntpmmodels = 0;
|
|
|
|
|
|
|
|
if (!test)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (qemuMonitorTestAddItem(test, "query-tpm-models",
|
|
|
|
"{ "
|
|
|
|
" \"return\": [ "
|
|
|
|
" \"passthrough\""
|
|
|
|
" ]"
|
|
|
|
"}") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if ((ntpmmodels = qemuMonitorGetTPMModels(qemuMonitorTestGetMonitor(test),
|
|
|
|
&tpmmodels)) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (ntpmmodels != 1) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"ntpmmodels %d is not 1", ntpmmodels);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define CHECK(i, wantname) \
|
|
|
|
do { \
|
|
|
|
if (STRNEQ(tpmmodels[i], (wantname))) { \
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, \
|
|
|
|
"name %s is not %s", \
|
|
|
|
tpmmodels[i], (wantname)); \
|
|
|
|
goto cleanup; \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
CHECK(0, "passthrough");
|
|
|
|
|
|
|
|
#undef CHECK
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 06:53:44 +00:00
|
|
|
cleanup:
|
2013-04-26 11:13:05 +00:00
|
|
|
qemuMonitorTestFree(test);
|
2016-11-25 08:18:35 +00:00
|
|
|
virStringListFree(tpmmodels);
|
2013-04-26 11:13:05 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-04-26 17:13:45 +00:00
|
|
|
static int
|
|
|
|
testQemuMonitorJSONGetCommandLineOptionParameters(const void *data)
|
|
|
|
{
|
2013-10-05 01:40:19 +00:00
|
|
|
virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
|
2013-07-25 17:17:44 +00:00
|
|
|
qemuMonitorTestPtr test = qemuMonitorTestNewSimple(true, xmlopt);
|
2013-04-26 17:13:45 +00:00
|
|
|
int ret = -1;
|
|
|
|
char **params = NULL;
|
|
|
|
int nparams = 0;
|
2014-06-17 11:41:16 +00:00
|
|
|
bool found = false;
|
2013-04-26 17:13:45 +00:00
|
|
|
|
|
|
|
if (!test)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (qemuMonitorTestAddItem(test, "query-command-line-options",
|
|
|
|
"{ "
|
|
|
|
" \"return\": [ "
|
|
|
|
" {\"parameters\": [], \"option\": \"acpi\" },"
|
|
|
|
" {\"parameters\": ["
|
|
|
|
" {\"name\": \"romfile\", "
|
|
|
|
" \"type\": \"string\"}, "
|
|
|
|
" {\"name\": \"bootindex\", "
|
|
|
|
" \"type\": \"number\"}], "
|
|
|
|
" \"option\": \"option-rom\"}"
|
|
|
|
" ]"
|
|
|
|
"}") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/* present with params */
|
|
|
|
if ((nparams = qemuMonitorGetCommandLineOptionParameters(qemuMonitorTestGetMonitor(test),
|
|
|
|
"option-rom",
|
2014-06-17 11:41:16 +00:00
|
|
|
¶ms,
|
|
|
|
NULL)) < 0)
|
2013-04-26 17:13:45 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (nparams != 2) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"nparams was %d, expected 2", nparams);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define CHECK(i, wantname) \
|
|
|
|
do { \
|
|
|
|
if (STRNEQ(params[i], (wantname))) { \
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, \
|
|
|
|
"name was %s, expected %s", \
|
|
|
|
params[i], (wantname)); \
|
|
|
|
goto cleanup; \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
CHECK(0, "romfile");
|
|
|
|
CHECK(1, "bootindex");
|
|
|
|
|
|
|
|
#undef CHECK
|
|
|
|
|
2016-11-25 08:18:35 +00:00
|
|
|
virStringListFree(params);
|
2013-04-26 17:13:45 +00:00
|
|
|
params = NULL;
|
|
|
|
|
|
|
|
/* present but empty */
|
|
|
|
if ((nparams = qemuMonitorGetCommandLineOptionParameters(qemuMonitorTestGetMonitor(test),
|
|
|
|
"acpi",
|
2014-06-17 11:41:16 +00:00
|
|
|
¶ms,
|
|
|
|
&found)) < 0)
|
2013-04-26 17:13:45 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (nparams != 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"nparams was %d, expected 0", nparams);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2014-06-17 11:41:16 +00:00
|
|
|
if (!found) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
"found was false, expected true");
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2013-04-26 17:13:45 +00:00
|
|
|
if (params && params[0]) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
"unexpected array contents");
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2016-11-25 08:18:35 +00:00
|
|
|
virStringListFree(params);
|
2013-04-26 17:13:45 +00:00
|
|
|
params = NULL;
|
|
|
|
|
|
|
|
/* no such option */
|
|
|
|
if ((nparams = qemuMonitorGetCommandLineOptionParameters(qemuMonitorTestGetMonitor(test),
|
|
|
|
"foobar",
|
2014-06-17 11:41:16 +00:00
|
|
|
¶ms,
|
|
|
|
&found)) < 0)
|
2013-04-26 17:13:45 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (nparams != 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"nparams was %d, expected 0", nparams);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2014-06-17 11:41:16 +00:00
|
|
|
if (found) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
"found was true, expected false");
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2013-04-26 17:13:45 +00:00
|
|
|
if (params && params[0]) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
"unexpected array contents");
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 06:53:44 +00:00
|
|
|
cleanup:
|
2013-04-26 17:13:45 +00:00
|
|
|
qemuMonitorTestFree(test);
|
2016-11-25 08:18:35 +00:00
|
|
|
virStringListFree(params);
|
2013-04-26 17:13:45 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2016-09-27 13:49:05 +00:00
|
|
|
|
|
|
|
struct qemuMonitorJSONTestAttachChardevData {
|
|
|
|
qemuMonitorTestPtr test;
|
|
|
|
virDomainChrSourceDefPtr chr;
|
|
|
|
const char *expectPty;
|
|
|
|
bool fail;
|
|
|
|
};
|
|
|
|
|
2013-03-12 18:48:04 +00:00
|
|
|
static int
|
2016-09-27 13:49:05 +00:00
|
|
|
testQemuMonitorJSONAttachChardev(const void *opaque)
|
2013-03-12 18:48:04 +00:00
|
|
|
{
|
2016-09-27 13:49:05 +00:00
|
|
|
const struct qemuMonitorJSONTestAttachChardevData *data = opaque;
|
|
|
|
int rc;
|
2013-03-12 18:48:04 +00:00
|
|
|
|
2016-09-27 13:49:05 +00:00
|
|
|
if ((rc = qemuMonitorAttachCharDev(qemuMonitorTestGetMonitor(data->test),
|
|
|
|
"alias", data->chr)) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (data->chr->type == VIR_DOMAIN_CHR_TYPE_PTY) {
|
|
|
|
if (STRNEQ_NULLABLE(data->expectPty, data->chr->data.file.path)) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"expected PTY path: %s got: %s",
|
|
|
|
NULLSTR(data->expectPty),
|
|
|
|
NULLSTR(data->chr->data.file.path));
|
|
|
|
rc = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
VIR_FREE(data->chr->data.file.path);
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if ((rc != 0) != data->fail)
|
2013-03-12 18:48:04 +00:00
|
|
|
return -1;
|
2016-09-27 13:49:05 +00:00
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
2013-03-12 18:48:04 +00:00
|
|
|
|
|
|
|
|
2016-09-27 13:49:05 +00:00
|
|
|
static int
|
|
|
|
qemuMonitorJSONTestAttachOneChardev(virDomainXMLOptionPtr xmlopt,
|
|
|
|
const char *label,
|
|
|
|
virDomainChrSourceDefPtr chr,
|
2016-09-27 07:52:50 +00:00
|
|
|
const char *expectargs,
|
2016-09-27 13:49:05 +00:00
|
|
|
const char *reply,
|
|
|
|
const char *expectPty,
|
|
|
|
bool fail)
|
2013-03-12 18:48:04 +00:00
|
|
|
|
2016-09-27 13:49:05 +00:00
|
|
|
{
|
2016-10-10 15:08:26 +00:00
|
|
|
struct qemuMonitorJSONTestAttachChardevData data = {0};
|
2016-09-27 13:49:05 +00:00
|
|
|
char *jsonreply = NULL;
|
|
|
|
char *fulllabel = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (!reply)
|
|
|
|
reply = "";
|
|
|
|
|
|
|
|
if (virAsprintf(&jsonreply, "{\"return\": {%s}}", reply) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virAsprintf(&fulllabel, "qemuMonitorJSONTestAttachChardev(%s)", label) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
data.chr = chr;
|
|
|
|
data.fail = fail;
|
|
|
|
data.expectPty = expectPty;
|
|
|
|
if (!(data.test = qemuMonitorTestNewSimple(true, xmlopt)))
|
|
|
|
goto cleanup;
|
|
|
|
|
2016-09-27 07:52:50 +00:00
|
|
|
if (qemuMonitorTestAddItemExpect(data.test, "chardev-add",
|
|
|
|
expectargs, true, jsonreply) < 0)
|
2016-09-27 13:49:05 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virTestRun(fulllabel, &testQemuMonitorJSONAttachChardev, &data) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
qemuMonitorTestFree(data.test);
|
|
|
|
VIR_FREE(jsonreply);
|
|
|
|
VIR_FREE(fulllabel);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
qemuMonitorJSONTestAttachChardev(virDomainXMLOptionPtr xmlopt)
|
|
|
|
{
|
|
|
|
virDomainChrSourceDef chr;
|
|
|
|
int ret = 0;
|
|
|
|
|
2016-09-27 07:52:50 +00:00
|
|
|
#define CHECK(label, fail, expectargs) \
|
|
|
|
if (qemuMonitorJSONTestAttachOneChardev(xmlopt, label, &chr, expectargs, \
|
|
|
|
NULL, NULL, fail) < 0) \
|
2016-09-27 13:49:05 +00:00
|
|
|
ret = -1
|
2013-03-12 18:48:04 +00:00
|
|
|
|
|
|
|
chr = (virDomainChrSourceDef) { .type = VIR_DOMAIN_CHR_TYPE_NULL };
|
2016-09-27 07:52:50 +00:00
|
|
|
CHECK("null", false,
|
|
|
|
"{'id':'alias','backend':{'type':'null','data':{}}}");
|
2013-03-12 18:48:04 +00:00
|
|
|
|
2014-01-20 11:27:29 +00:00
|
|
|
chr = (virDomainChrSourceDef) { .type = VIR_DOMAIN_CHR_TYPE_VC };
|
2016-09-27 07:52:50 +00:00
|
|
|
CHECK("vc", false,
|
|
|
|
"{'id':'alias','backend':{'type':'null','data':{}}}");
|
2013-03-12 18:48:04 +00:00
|
|
|
|
|
|
|
chr = (virDomainChrSourceDef) { .type = VIR_DOMAIN_CHR_TYPE_PTY };
|
2016-09-27 13:49:05 +00:00
|
|
|
if (qemuMonitorJSONTestAttachOneChardev(xmlopt, "pty", &chr,
|
2016-09-27 07:52:50 +00:00
|
|
|
"{'id':'alias',"
|
|
|
|
"'backend':{'type':'pty',"
|
|
|
|
"'data':{}}}",
|
2016-09-27 13:49:05 +00:00
|
|
|
"\"pty\" : \"/dev/pts/0\"",
|
|
|
|
"/dev/pts/0", false) < 0)
|
2013-03-12 18:48:04 +00:00
|
|
|
ret = -1;
|
|
|
|
|
|
|
|
chr = (virDomainChrSourceDef) { .type = VIR_DOMAIN_CHR_TYPE_PTY };
|
2016-09-27 07:52:50 +00:00
|
|
|
CHECK("pty missing path", true,
|
|
|
|
"{'id':'alias','backend':{'type':'pty','data':{}}}");
|
|
|
|
|
|
|
|
memset(&chr, 0, sizeof(chr));
|
|
|
|
chr.type = VIR_DOMAIN_CHR_TYPE_FILE;
|
|
|
|
chr.data.file.path = (char *) "/test/path";
|
|
|
|
CHECK("file", false,
|
|
|
|
"{'id':'alias','backend':{'type':'file','data':{'out':'/test/path'}}}");
|
|
|
|
|
|
|
|
memset(&chr, 0, sizeof(chr));
|
|
|
|
chr.type = VIR_DOMAIN_CHR_TYPE_DEV;
|
|
|
|
chr.data.file.path = (char *) "/test/path";
|
|
|
|
CHECK("device", false,
|
|
|
|
"{'id':'alias','backend':{'type':'serial','data':{'device':'/test/path'}}}");
|
|
|
|
|
|
|
|
memset(&chr, 0, sizeof(chr));
|
|
|
|
chr.type = VIR_DOMAIN_CHR_TYPE_TCP;
|
|
|
|
chr.data.tcp.host = (char *) "example.com";
|
|
|
|
chr.data.tcp.service = (char *) "1234";
|
|
|
|
CHECK("tcp", false,
|
|
|
|
"{'id':'alias',"
|
|
|
|
"'backend':{'type':'socket',"
|
|
|
|
"'data':{'addr':{'type':'inet',"
|
|
|
|
"'data':{'host':'example.com',"
|
|
|
|
"'port':'1234'}},"
|
|
|
|
"'wait':false,"
|
|
|
|
"'telnet':false,"
|
|
|
|
"'server':false}}}");
|
|
|
|
|
|
|
|
memset(&chr, 0, sizeof(chr));
|
|
|
|
chr.type = VIR_DOMAIN_CHR_TYPE_UDP;
|
|
|
|
chr.data.udp.connectHost = (char *) "example.com";
|
|
|
|
chr.data.udp.connectService = (char *) "1234";
|
|
|
|
CHECK("udp", false,
|
|
|
|
"{'id':'alias',"
|
2016-09-27 14:01:55 +00:00
|
|
|
"'backend':{'type':'udp',"
|
|
|
|
"'data':{'remote':{'type':'inet',"
|
|
|
|
"'data':{'host':'example.com',"
|
|
|
|
"'port':'1234'}}}}}");
|
|
|
|
|
|
|
|
chr.data.udp.bindHost = (char *) "localhost";
|
|
|
|
chr.data.udp.bindService = (char *) "4321";
|
|
|
|
CHECK("udp", false,
|
|
|
|
"{'id':'alias',"
|
|
|
|
"'backend':{'type':'udp',"
|
|
|
|
"'data':{'remote':{'type':'inet',"
|
|
|
|
"'data':{'host':'example.com',"
|
|
|
|
"'port':'1234'}},"
|
|
|
|
"'local':{'type':'inet',"
|
|
|
|
"'data':{'host':'localhost',"
|
|
|
|
"'port':'4321'}}}}}");
|
2016-09-27 07:52:50 +00:00
|
|
|
|
|
|
|
memset(&chr, 0, sizeof(chr));
|
|
|
|
chr.type = VIR_DOMAIN_CHR_TYPE_UNIX;
|
|
|
|
chr.data.nix.path = (char *) "/path/to/socket";
|
|
|
|
CHECK("unix", false,
|
|
|
|
"{'id':'alias',"
|
|
|
|
"'backend':{'type':'socket',"
|
|
|
|
"'data':{'addr':{'type':'unix',"
|
|
|
|
"'data':{'path':'/path/to/socket'}},"
|
|
|
|
"'wait':false,"
|
|
|
|
"'server':false}}}");
|
2013-03-12 18:48:04 +00:00
|
|
|
|
|
|
|
chr = (virDomainChrSourceDef) { .type = VIR_DOMAIN_CHR_TYPE_SPICEVMC };
|
2016-09-27 07:52:50 +00:00
|
|
|
CHECK("spicevmc", false,
|
|
|
|
"{'id':'alias','backend':{'type':'spicevmc','"
|
|
|
|
"data':{'type':'vdagent'}}}");
|
2013-03-12 18:48:04 +00:00
|
|
|
|
|
|
|
chr = (virDomainChrSourceDef) { .type = VIR_DOMAIN_CHR_TYPE_PIPE };
|
2016-09-27 07:52:50 +00:00
|
|
|
CHECK("pipe", true, "");
|
2013-03-12 18:48:04 +00:00
|
|
|
|
|
|
|
chr = (virDomainChrSourceDef) { .type = VIR_DOMAIN_CHR_TYPE_STDIO };
|
2016-09-27 07:52:50 +00:00
|
|
|
CHECK("stdio", true, "");
|
2013-03-12 18:48:04 +00:00
|
|
|
#undef CHECK
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
2013-04-26 17:13:45 +00:00
|
|
|
|
2016-09-27 13:49:05 +00:00
|
|
|
|
2013-03-12 18:57:48 +00:00
|
|
|
static int
|
|
|
|
testQemuMonitorJSONDetachChardev(const void *data)
|
|
|
|
{
|
2013-10-05 01:40:19 +00:00
|
|
|
virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
|
2013-07-25 17:17:44 +00:00
|
|
|
qemuMonitorTestPtr test = qemuMonitorTestNewSimple(true, xmlopt);
|
2013-03-12 18:57:48 +00:00
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (!test)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
if (qemuMonitorTestAddItem(test, "chardev-remove", "{\"return\": {}}") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (qemuMonitorDetachCharDev(qemuMonitorTestGetMonitor(test),
|
|
|
|
"dummy_chrID") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 06:53:44 +00:00
|
|
|
cleanup:
|
2013-03-12 18:57:48 +00:00
|
|
|
qemuMonitorTestFree(test);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-06-24 17:51:56 +00:00
|
|
|
/*
|
|
|
|
* This test will request to return a list of paths for "/". It should be
|
|
|
|
* a simple list of 1 real element that being the "machine". The following
|
|
|
|
* is the execution and expected return:
|
|
|
|
*
|
|
|
|
* {"execute":"qom-list", "arguments": { "path": "/"}}"
|
|
|
|
* {"return": [{"name": "machine", "type": "child<container>"}, \
|
|
|
|
* {"name": "type", "type": "string"}]}
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
testQemuMonitorJSONGetListPaths(const void *data)
|
|
|
|
{
|
2013-10-05 01:40:19 +00:00
|
|
|
virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
|
2013-07-25 17:17:44 +00:00
|
|
|
qemuMonitorTestPtr test = qemuMonitorTestNewSimple(true, xmlopt);
|
2013-06-24 17:51:56 +00:00
|
|
|
int ret = -1;
|
|
|
|
qemuMonitorJSONListPathPtr *paths;
|
|
|
|
int npaths = 0;
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
if (!test)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (qemuMonitorTestAddItem(test, "qom-list",
|
|
|
|
"{ "
|
|
|
|
" \"return\": [ "
|
|
|
|
" {\"name\": \"machine\", "
|
|
|
|
" \"type\": \"child<container>\"}, "
|
|
|
|
" {\"name\": \"type\", "
|
|
|
|
" \"type\": \"string\"} "
|
|
|
|
" ]"
|
|
|
|
"}") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/* present with path */
|
|
|
|
if ((npaths = qemuMonitorJSONGetObjectListPaths(
|
|
|
|
qemuMonitorTestGetMonitor(test),
|
|
|
|
"/",
|
|
|
|
&paths)) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (npaths != 2) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"npaths was %d, expected 1", npaths);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define CHECK(i, wantname, wanttype) \
|
|
|
|
do { \
|
|
|
|
if (STRNEQ(paths[i]->name, (wantname))) { \
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, \
|
|
|
|
"name was %s, expected %s", \
|
|
|
|
paths[i]->name, (wantname)); \
|
|
|
|
goto cleanup; \
|
|
|
|
} \
|
|
|
|
if (STRNEQ_NULLABLE(paths[i]->type, (wanttype))) { \
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, \
|
|
|
|
"type was %s, expected %s", \
|
|
|
|
NULLSTR(paths[i]->type), (wanttype)); \
|
|
|
|
goto cleanup; \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
CHECK(0, "machine", "child<container>");
|
|
|
|
|
|
|
|
#undef CHECK
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 06:53:44 +00:00
|
|
|
cleanup:
|
2013-06-24 17:51:56 +00:00
|
|
|
qemuMonitorTestFree(test);
|
|
|
|
for (i = 0; i < npaths; i++)
|
|
|
|
qemuMonitorJSONListPathFree(paths[i]);
|
|
|
|
VIR_FREE(paths);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-03 18:15:07 +00:00
|
|
|
/*
|
|
|
|
* This test will use a path to /machine/i440fx which should exist in order
|
|
|
|
* to ensure that the qom-get property fetch works properly. The following
|
|
|
|
* is the execution and expected return:
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* { "execute": "qom-get","arguments": \
|
|
|
|
* { "path": "/machine/i440fx","property": "realized"}}
|
|
|
|
* {"return": true}
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
testQemuMonitorJSONGetObjectProperty(const void *data)
|
|
|
|
{
|
2013-10-05 01:40:19 +00:00
|
|
|
virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
|
2013-07-25 17:17:44 +00:00
|
|
|
qemuMonitorTestPtr test = qemuMonitorTestNewSimple(true, xmlopt);
|
2013-07-03 18:15:07 +00:00
|
|
|
int ret = -1;
|
|
|
|
qemuMonitorJSONObjectProperty prop;
|
|
|
|
|
|
|
|
if (!test)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (qemuMonitorTestAddItem(test, "qom-get",
|
|
|
|
"{ \"return\": true }") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/* Present with path and property */
|
|
|
|
memset(&prop, 0, sizeof(qemuMonitorJSONObjectProperty));
|
|
|
|
prop.type = QEMU_MONITOR_OBJECT_PROPERTY_BOOLEAN;
|
|
|
|
if (qemuMonitorJSONGetObjectProperty(qemuMonitorTestGetMonitor(test),
|
|
|
|
"/machine/i440fx",
|
|
|
|
"realized",
|
|
|
|
&prop) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!prop.val.b) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
"expected true, but false returned");
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
2014-03-25 06:53:44 +00:00
|
|
|
cleanup:
|
2013-07-03 18:15:07 +00:00
|
|
|
qemuMonitorTestFree(test);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-03 18:42:40 +00:00
|
|
|
/*
|
|
|
|
* This test will use a path to /machine/i440fx which should exist in order
|
|
|
|
* to ensure that the qom-set property set works properly. The test will
|
|
|
|
* set a true property to true just as a proof of concept. Setting it to
|
|
|
|
* false is not a good idea...
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
testQemuMonitorJSONSetObjectProperty(const void *data)
|
|
|
|
{
|
2013-10-05 01:40:19 +00:00
|
|
|
virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
|
2013-07-25 17:17:44 +00:00
|
|
|
qemuMonitorTestPtr test = qemuMonitorTestNewSimple(true, xmlopt);
|
2013-07-03 18:42:40 +00:00
|
|
|
int ret = -1;
|
|
|
|
qemuMonitorJSONObjectProperty prop;
|
|
|
|
|
|
|
|
if (!test)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (qemuMonitorTestAddItem(test, "qom-set",
|
|
|
|
"{ \"return\": {} }") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
if (qemuMonitorTestAddItem(test, "qom-get",
|
|
|
|
"{ \"return\": true }") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/* Let's attempt the setting */
|
|
|
|
memset(&prop, 0, sizeof(qemuMonitorJSONObjectProperty));
|
|
|
|
prop.type = QEMU_MONITOR_OBJECT_PROPERTY_BOOLEAN;
|
|
|
|
prop.val.b = true;
|
|
|
|
if (qemuMonitorJSONSetObjectProperty(qemuMonitorTestGetMonitor(test),
|
|
|
|
"/machine/i440fx",
|
|
|
|
"realized",
|
|
|
|
&prop) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/* To make sure it worked, fetch the property - if this succeeds then
|
|
|
|
* we didn't hose things
|
|
|
|
*/
|
|
|
|
memset(&prop, 0, sizeof(qemuMonitorJSONObjectProperty));
|
|
|
|
prop.type = QEMU_MONITOR_OBJECT_PROPERTY_BOOLEAN;
|
|
|
|
if (qemuMonitorJSONGetObjectProperty(qemuMonitorTestGetMonitor(test),
|
|
|
|
"/machine/i440fx",
|
|
|
|
"realized",
|
|
|
|
&prop) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!prop.val.b) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
"expected true, but false returned");
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
2014-03-25 06:53:44 +00:00
|
|
|
cleanup:
|
2013-07-03 18:42:40 +00:00
|
|
|
qemuMonitorTestFree(test);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-19 13:01:38 +00:00
|
|
|
static int
|
|
|
|
testQemuMonitorJSONGetDeviceAliases(const void *data)
|
|
|
|
{
|
2013-10-05 01:40:19 +00:00
|
|
|
virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
|
2013-07-25 17:17:44 +00:00
|
|
|
qemuMonitorTestPtr test = qemuMonitorTestNewSimple(true, xmlopt);
|
2013-07-19 13:01:38 +00:00
|
|
|
int ret = -1;
|
|
|
|
char **aliases = NULL;
|
2016-08-16 10:20:56 +00:00
|
|
|
const char **alias;
|
2013-07-19 13:01:38 +00:00
|
|
|
const char *expected[] = {
|
|
|
|
"virtio-disk25", "video0", "serial0", "ide0-0-0", "usb", NULL };
|
|
|
|
|
|
|
|
if (!test)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (qemuMonitorTestAddItem(test,
|
|
|
|
"qom-list",
|
|
|
|
"{\"return\": ["
|
|
|
|
" {\"name\": \"virtio-disk25\","
|
|
|
|
" \"type\": \"child<virtio-blk-pci>\"},"
|
|
|
|
" {\"name\": \"video0\","
|
|
|
|
" \"type\": \"child<VGA>\"},"
|
|
|
|
" {\"name\": \"serial0\","
|
|
|
|
" \"type\": \"child<isa-serial>\"},"
|
|
|
|
" {\"name\": \"ide0-0-0\","
|
|
|
|
" \"type\": \"child<ide-cd>\"},"
|
|
|
|
" {\"name\": \"usb\","
|
|
|
|
" \"type\": \"child<piix3-usb-uhci>\"},"
|
|
|
|
" {\"name\": \"type\", \"type\": \"string\"}"
|
|
|
|
"]}") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (qemuMonitorJSONGetDeviceAliases(qemuMonitorTestGetMonitor(test),
|
|
|
|
&aliases) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!aliases) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", "no aliases returned");
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
2016-08-16 10:20:56 +00:00
|
|
|
for (alias = (const char **) aliases; *alias; alias++) {
|
2016-11-25 08:18:35 +00:00
|
|
|
if (!virStringListHasString(expected, *alias)) {
|
2013-07-19 13:01:38 +00:00
|
|
|
fprintf(stderr, "got unexpected device alias '%s'\n", *alias);
|
|
|
|
ret = -1;
|
|
|
|
}
|
|
|
|
}
|
2016-08-16 10:20:56 +00:00
|
|
|
for (alias = expected; *alias; alias++) {
|
2016-11-25 08:18:35 +00:00
|
|
|
if (!virStringListHasString((const char **) aliases, *alias)) {
|
2013-07-19 13:01:38 +00:00
|
|
|
fprintf(stderr, "missing expected alias '%s'\n", *alias);
|
|
|
|
ret = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-25 06:53:44 +00:00
|
|
|
cleanup:
|
2016-11-25 08:18:35 +00:00
|
|
|
virStringListFree(aliases);
|
2013-07-22 12:56:21 +00:00
|
|
|
qemuMonitorTestFree(test);
|
2013-07-19 13:01:38 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-09-18 13:11:06 +00:00
|
|
|
static int
|
|
|
|
testQemuMonitorJSONCPU(const void *data)
|
|
|
|
{
|
2013-10-05 01:40:19 +00:00
|
|
|
virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
|
2013-09-18 13:11:06 +00:00
|
|
|
qemuMonitorTestPtr test = qemuMonitorTestNewSimple(true, xmlopt);
|
|
|
|
int ret = -1;
|
|
|
|
bool running = false;
|
|
|
|
virDomainPausedReason reason = 0;
|
|
|
|
|
2013-09-20 11:02:43 +00:00
|
|
|
if (!test)
|
|
|
|
return -1;
|
|
|
|
|
2013-09-18 13:11:06 +00:00
|
|
|
if (qemuMonitorTestAddItem(test, "stop", "{\"return\": {}}") < 0 ||
|
|
|
|
qemuMonitorTestAddItem(test, "query-status",
|
|
|
|
"{\"return\": {"
|
|
|
|
" \"status\": \"paused\","
|
|
|
|
" \"singlestep\": false,"
|
|
|
|
" \"running\": false}}") < 0 ||
|
|
|
|
qemuMonitorTestAddItem(test, "cont", "{\"return\": {}}") < 0 ||
|
|
|
|
qemuMonitorTestAddItem(test, "query-status",
|
|
|
|
"{\"return\": {"
|
|
|
|
" \"status\": \"running\","
|
|
|
|
" \"singlestep\": false,"
|
|
|
|
" \"running\": true}}") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (qemuMonitorJSONStopCPUs(qemuMonitorTestGetMonitor(test)) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (qemuMonitorGetStatus(qemuMonitorTestGetMonitor(test),
|
|
|
|
&running, &reason) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (running) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
"Running was not false");
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (qemuMonitorJSONStartCPUs(qemuMonitorTestGetMonitor(test), NULL) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (qemuMonitorGetStatus(qemuMonitorTestGetMonitor(test),
|
|
|
|
&running, &reason) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!running) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
"Running was not true");
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 06:53:44 +00:00
|
|
|
cleanup:
|
2013-09-18 13:11:06 +00:00
|
|
|
qemuMonitorTestFree(test);
|
|
|
|
return ret;
|
|
|
|
}
|
2013-07-19 13:01:38 +00:00
|
|
|
|
2013-09-18 15:28:31 +00:00
|
|
|
static int
|
|
|
|
testQemuMonitorJSONSimpleFunc(const void *opaque)
|
|
|
|
{
|
2013-10-05 01:40:19 +00:00
|
|
|
testQemuMonitorJSONSimpleFuncDataPtr data =
|
|
|
|
(testQemuMonitorJSONSimpleFuncDataPtr) opaque;
|
2013-09-18 15:28:31 +00:00
|
|
|
virDomainXMLOptionPtr xmlopt = data->xmlopt;
|
|
|
|
qemuMonitorTestPtr test = qemuMonitorTestNewSimple(true, xmlopt);
|
|
|
|
const char *reply = data->reply;
|
|
|
|
int ret = -1;
|
|
|
|
|
2013-09-20 11:02:43 +00:00
|
|
|
if (!test)
|
|
|
|
return -1;
|
|
|
|
|
2013-09-18 15:28:31 +00:00
|
|
|
if (!reply)
|
|
|
|
reply = "{\"return\":{}}";
|
|
|
|
|
|
|
|
if (qemuMonitorTestAddItem(test, data->cmd, reply) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (data->func(qemuMonitorTestGetMonitor(test)) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = 0;
|
2014-03-25 06:53:44 +00:00
|
|
|
cleanup:
|
2013-09-18 15:28:31 +00:00
|
|
|
qemuMonitorTestFree(test);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-10-01 14:23:50 +00:00
|
|
|
#define GEN_TEST_FUNC(funcName, ...) \
|
|
|
|
static int \
|
|
|
|
testQemuMonitorJSON ## funcName(const void *opaque) \
|
|
|
|
{ \
|
2013-10-05 01:40:19 +00:00
|
|
|
const testQemuMonitorJSONSimpleFuncData *data = opaque; \
|
2013-10-01 14:23:50 +00:00
|
|
|
virDomainXMLOptionPtr xmlopt = data->xmlopt; \
|
|
|
|
qemuMonitorTestPtr test = qemuMonitorTestNewSimple(true, xmlopt); \
|
|
|
|
const char *reply = data->reply; \
|
|
|
|
int ret = -1; \
|
|
|
|
\
|
|
|
|
if (!test) \
|
|
|
|
return -1; \
|
|
|
|
\
|
|
|
|
if (!reply) \
|
|
|
|
reply = "{\"return\":{}}"; \
|
|
|
|
\
|
|
|
|
if (qemuMonitorTestAddItem(test, data->cmd, reply) < 0) \
|
|
|
|
goto cleanup; \
|
|
|
|
\
|
|
|
|
if (funcName(qemuMonitorTestGetMonitor(test), __VA_ARGS__) < 0) \
|
|
|
|
goto cleanup; \
|
|
|
|
\
|
|
|
|
ret = 0; \
|
|
|
|
cleanup: \
|
|
|
|
qemuMonitorTestFree(test); \
|
|
|
|
return ret; \
|
|
|
|
}
|
|
|
|
|
|
|
|
GEN_TEST_FUNC(qemuMonitorJSONSetLink, "vnet0", VIR_DOMAIN_NET_INTERFACE_LINK_STATE_DOWN)
|
|
|
|
GEN_TEST_FUNC(qemuMonitorJSONBlockResize, "vda", 123456)
|
|
|
|
GEN_TEST_FUNC(qemuMonitorJSONSetVNCPassword, "secret_password")
|
|
|
|
GEN_TEST_FUNC(qemuMonitorJSONSetPassword, "spice", "secret_password", "disconnect")
|
|
|
|
GEN_TEST_FUNC(qemuMonitorJSONExpirePassword, "spice", "123456")
|
|
|
|
GEN_TEST_FUNC(qemuMonitorJSONSetBalloon, 1024)
|
|
|
|
GEN_TEST_FUNC(qemuMonitorJSONSetCPU, 1, true)
|
|
|
|
GEN_TEST_FUNC(qemuMonitorJSONEjectMedia, "hdc", true)
|
|
|
|
GEN_TEST_FUNC(qemuMonitorJSONChangeMedia, "hdc", "/foo/bar", NULL)
|
|
|
|
GEN_TEST_FUNC(qemuMonitorJSONSaveVirtualMemory, 0, 1024, "/foo/bar")
|
|
|
|
GEN_TEST_FUNC(qemuMonitorJSONSavePhysicalMemory, 0, 1024, "/foo/bar")
|
|
|
|
GEN_TEST_FUNC(qemuMonitorJSONSetMigrationSpeed, 1024)
|
|
|
|
GEN_TEST_FUNC(qemuMonitorJSONSetMigrationDowntime, 1)
|
|
|
|
GEN_TEST_FUNC(qemuMonitorJSONMigrate, QEMU_MONITOR_MIGRATE_BACKGROUND |
|
|
|
|
QEMU_MONITOR_MIGRATE_NON_SHARED_DISK |
|
|
|
|
QEMU_MONITOR_MIGRATE_NON_SHARED_INC, "tcp:localhost:12345")
|
2014-03-23 03:51:14 +00:00
|
|
|
GEN_TEST_FUNC(qemuMonitorJSONDump, "dummy_protocol", "dummy_memory_dump_format")
|
2013-10-01 14:23:50 +00:00
|
|
|
GEN_TEST_FUNC(qemuMonitorJSONGraphicsRelocate, VIR_DOMAIN_GRAPHICS_TYPE_SPICE,
|
|
|
|
"localhost", 12345, 12346, NULL)
|
|
|
|
GEN_TEST_FUNC(qemuMonitorJSONAddNetdev, "some_dummy_netdevstr")
|
|
|
|
GEN_TEST_FUNC(qemuMonitorJSONRemoveNetdev, "net0")
|
|
|
|
GEN_TEST_FUNC(qemuMonitorJSONDelDevice, "ide0")
|
|
|
|
GEN_TEST_FUNC(qemuMonitorJSONAddDevice, "some_dummy_devicestr")
|
2016-08-01 12:11:44 +00:00
|
|
|
GEN_TEST_FUNC(qemuMonitorJSONSetDrivePassphrase, "drive-vda", "secret_passhprase")
|
blockcopy: add qemu implementation of new tunables
Upstream qemu 1.4 added some drive-mirror tunables not present
when it was first introduced in 1.3. Management apps may want
to set these in some cases (for example, without tuning
granularity down to sector size, a copy may end up occupying
more bytes than the original because an entire cluster is
copied even when only a sector within the cluster is dirty,
although tuning it down results in more CPU time to do the
copy). I haven't personally needed to use the parameters, but
since they exist, and since the new API supports virTypedParams,
we might as well expose them.
Since the tuning parameters aren't often used, and omitted from
the QMP command when unspecified, I think it is safe to rely on
qemu 1.3 to issue an error about them being unsupported, rather
than trying to create a new capability bit in libvirt.
Meanwhile, all versions of qemu from 1.4 to 2.1 have a bug where
a bad granularity (such as non-power-of-2) gives a poor message:
error: internal error: unable to execute QEMU command 'drive-mirror': Invalid parameter 'drive-virtio-disk0'
because of abuse of QERR_INVALID_PARAMETER (which is supposed to
name the parameter that was given a bad value, rather than the
value passed to some other parameter). I don't see that a
capability check will help, so we'll just live with it (and it
has since been improved in upstream qemu).
* src/qemu/qemu_monitor.h (qemuMonitorDriveMirror): Add
parameters.
* src/qemu/qemu_monitor.c (qemuMonitorDriveMirror): Likewise.
* src/qemu/qemu_monitor_json.h (qemuMonitorJSONDriveMirror):
Likewise.
* src/qemu/qemu_monitor_json.c (qemuMonitorJSONDriveMirror):
Likewise.
* src/qemu/qemu_driver.c (qemuDomainBlockCopyCommon): Likewise.
(qemuDomainBlockRebase, qemuDomainBlockCopy): Adjust callers.
* src/qemu/qemu_migration.c (qemuMigrationDriveMirror): Likewise.
* tests/qemumonitorjsontest.c (qemuMonitorJSONDriveMirror): Likewise.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-09-08 20:53:12 +00:00
|
|
|
GEN_TEST_FUNC(qemuMonitorJSONDriveMirror, "vdb", "/foo/bar", NULL, 1024, 0, 0,
|
2013-10-01 14:23:50 +00:00
|
|
|
VIR_DOMAIN_BLOCK_REBASE_SHALLOW | VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT)
|
2014-05-13 15:41:33 +00:00
|
|
|
GEN_TEST_FUNC(qemuMonitorJSONBlockCommit, "vdb", "/foo/bar1", "/foo/bar2", NULL, 1024)
|
2015-04-01 08:06:55 +00:00
|
|
|
GEN_TEST_FUNC(qemuMonitorJSONDrivePivot, "vdb")
|
2013-10-01 14:23:50 +00:00
|
|
|
GEN_TEST_FUNC(qemuMonitorJSONScreendump, "/foo/bar")
|
|
|
|
GEN_TEST_FUNC(qemuMonitorJSONOpenGraphics, "spice", "spicefd", false)
|
|
|
|
GEN_TEST_FUNC(qemuMonitorJSONNBDServerStart, "localhost", 12345)
|
|
|
|
GEN_TEST_FUNC(qemuMonitorJSONNBDServerAdd, "vda", true)
|
|
|
|
GEN_TEST_FUNC(qemuMonitorJSONDetachCharDev, "serial1")
|
|
|
|
|
2016-08-01 11:44:25 +00:00
|
|
|
static bool
|
|
|
|
testQemuMonitorJSONqemuMonitorJSONQueryCPUsEqual(struct qemuMonitorQueryCpusEntry *a,
|
|
|
|
struct qemuMonitorQueryCpusEntry *b)
|
|
|
|
{
|
2016-07-28 08:33:10 +00:00
|
|
|
if (a->tid != b->tid ||
|
|
|
|
STRNEQ_NULLABLE(a->qom_path, b->qom_path))
|
2016-08-01 11:44:25 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-10-02 09:40:33 +00:00
|
|
|
|
|
|
|
static int
|
2016-07-08 13:36:27 +00:00
|
|
|
testQemuMonitorJSONqemuMonitorJSONQueryCPUs(const void *data)
|
2013-10-02 09:40:33 +00:00
|
|
|
{
|
|
|
|
virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
|
|
|
|
qemuMonitorTestPtr test = qemuMonitorTestNewSimple(true, xmlopt);
|
|
|
|
int ret = -1;
|
2016-08-01 11:44:25 +00:00
|
|
|
struct qemuMonitorQueryCpusEntry *cpudata = NULL;
|
|
|
|
struct qemuMonitorQueryCpusEntry expect[] = {
|
2016-11-21 13:57:54 +00:00
|
|
|
{0, 17622, (char *) "/machine/unattached/device[0]", true},
|
|
|
|
{1, 17624, (char *) "/machine/unattached/device[1]", true},
|
|
|
|
{2, 17626, (char *) "/machine/unattached/device[2]", true},
|
|
|
|
{3, 17628, NULL, true},
|
2016-08-01 11:44:25 +00:00
|
|
|
};
|
|
|
|
size_t ncpudata = 0;
|
2013-10-02 09:40:33 +00:00
|
|
|
size_t i;
|
|
|
|
|
|
|
|
if (!test)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (qemuMonitorTestAddItem(test, "query-cpus",
|
|
|
|
"{"
|
|
|
|
" \"return\": ["
|
|
|
|
" {"
|
|
|
|
" \"current\": true,"
|
|
|
|
" \"CPU\": 0,"
|
2016-07-28 08:33:10 +00:00
|
|
|
" \"qom_path\": \"/machine/unattached/device[0]\","
|
2013-10-02 09:40:33 +00:00
|
|
|
" \"pc\": -2130530478,"
|
|
|
|
" \"halted\": true,"
|
|
|
|
" \"thread_id\": 17622"
|
|
|
|
" },"
|
|
|
|
" {"
|
|
|
|
" \"current\": false,"
|
|
|
|
" \"CPU\": 1,"
|
2016-07-28 08:33:10 +00:00
|
|
|
" \"qom_path\": \"/machine/unattached/device[1]\","
|
2013-10-02 09:40:33 +00:00
|
|
|
" \"pc\": -2130530478,"
|
|
|
|
" \"halted\": true,"
|
|
|
|
" \"thread_id\": 17624"
|
|
|
|
" },"
|
|
|
|
" {"
|
|
|
|
" \"current\": false,"
|
|
|
|
" \"CPU\": 2,"
|
2016-07-28 08:33:10 +00:00
|
|
|
" \"qom_path\": \"/machine/unattached/device[2]\","
|
2013-10-02 09:40:33 +00:00
|
|
|
" \"pc\": -2130530478,"
|
|
|
|
" \"halted\": true,"
|
|
|
|
" \"thread_id\": 17626"
|
|
|
|
" },"
|
|
|
|
" {"
|
|
|
|
" \"current\": false,"
|
|
|
|
" \"CPU\": 3,"
|
|
|
|
" \"pc\": -2130530478,"
|
|
|
|
" \"halted\": true,"
|
|
|
|
" \"thread_id\": 17628"
|
|
|
|
" }"
|
|
|
|
" ],"
|
|
|
|
" \"id\": \"libvirt-7\""
|
|
|
|
"}") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2016-08-01 11:44:25 +00:00
|
|
|
if (qemuMonitorJSONQueryCPUs(qemuMonitorTestGetMonitor(test),
|
2016-12-04 17:53:03 +00:00
|
|
|
&cpudata, &ncpudata, true) < 0)
|
2016-08-01 11:44:25 +00:00
|
|
|
goto cleanup;
|
2013-10-02 09:40:33 +00:00
|
|
|
|
2016-08-01 11:44:25 +00:00
|
|
|
if (ncpudata != 4) {
|
2013-10-02 09:40:33 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
2016-08-01 11:44:25 +00:00
|
|
|
"Expecting ncpupids = 4 but got %zu", ncpudata);
|
2013-10-02 09:40:33 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2016-08-01 11:44:25 +00:00
|
|
|
for (i = 0; i < ncpudata; i++) {
|
|
|
|
if (!testQemuMonitorJSONqemuMonitorJSONQueryCPUsEqual(cpudata + i,
|
|
|
|
expect + i)) {
|
2013-10-02 09:40:33 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
2016-08-01 11:44:25 +00:00
|
|
|
"vcpu entry %zu does not match expected data", i);
|
2013-10-02 09:40:33 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 06:53:44 +00:00
|
|
|
cleanup:
|
2016-08-01 11:44:25 +00:00
|
|
|
qemuMonitorQueryCpusFree(cpudata, ncpudata);
|
2013-10-02 09:40:33 +00:00
|
|
|
qemuMonitorTestFree(test);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-10-02 10:02:53 +00:00
|
|
|
static int
|
|
|
|
testQemuMonitorJSONqemuMonitorJSONGetBalloonInfo(const void *data)
|
|
|
|
{
|
|
|
|
virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
|
|
|
|
qemuMonitorTestPtr test = qemuMonitorTestNewSimple(true, xmlopt);
|
|
|
|
int ret = -1;
|
|
|
|
unsigned long long currmem;
|
|
|
|
|
|
|
|
if (!test)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (qemuMonitorTestAddItem(test, "query-balloon",
|
|
|
|
"{"
|
|
|
|
" \"return\": {"
|
|
|
|
" \"actual\": 4294967296"
|
|
|
|
" },"
|
|
|
|
" \"id\": \"libvirt-9\""
|
|
|
|
"}") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (qemuMonitorJSONGetBalloonInfo(qemuMonitorTestGetMonitor(test), &currmem) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2013-10-04 23:46:43 +00:00
|
|
|
if (currmem != (4294967296ULL/1024)) {
|
2013-10-02 10:02:53 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Unexpected currmem value: %llu", currmem);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 06:53:44 +00:00
|
|
|
cleanup:
|
2013-10-02 10:02:53 +00:00
|
|
|
qemuMonitorTestFree(test);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-10-02 09:56:43 +00:00
|
|
|
static int
|
|
|
|
testQemuMonitorJSONqemuMonitorJSONGetVirtType(const void *data)
|
|
|
|
{
|
|
|
|
virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
|
|
|
|
qemuMonitorTestPtr test = qemuMonitorTestNewSimple(true, xmlopt);
|
|
|
|
int ret = -1;
|
2015-09-17 08:46:56 +00:00
|
|
|
virDomainVirtType virtType;
|
2013-10-02 09:56:43 +00:00
|
|
|
|
|
|
|
if (!test)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (qemuMonitorTestAddItem(test, "query-kvm",
|
|
|
|
"{"
|
|
|
|
" \"return\": {"
|
|
|
|
" \"enabled\": true,"
|
|
|
|
" \"present\": true"
|
|
|
|
" },"
|
|
|
|
" \"id\": \"libvirt-8\""
|
|
|
|
"}") < 0 ||
|
|
|
|
qemuMonitorTestAddItem(test, "query-kvm",
|
|
|
|
"{"
|
|
|
|
" \"return\": {"
|
|
|
|
" \"enabled\": false,"
|
|
|
|
" \"present\": true"
|
|
|
|
" },"
|
|
|
|
" \"id\": \"libvirt-7\""
|
|
|
|
"}") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (qemuMonitorJSONGetVirtType(qemuMonitorTestGetMonitor(test), &virtType) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virtType != VIR_DOMAIN_VIRT_KVM) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Unexpected virt type: %d, expecting %d", virtType, VIR_DOMAIN_VIRT_KVM);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (qemuMonitorJSONGetVirtType(qemuMonitorTestGetMonitor(test), &virtType) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virtType != VIR_DOMAIN_VIRT_QEMU) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Unexpected virt type: %d, expecting %d", virtType, VIR_DOMAIN_VIRT_QEMU);
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
2014-03-25 06:53:44 +00:00
|
|
|
cleanup:
|
2013-10-02 09:56:43 +00:00
|
|
|
qemuMonitorTestFree(test);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-10-02 12:39:10 +00:00
|
|
|
static int
|
|
|
|
testHashEqualQemuDomainDiskInfo(const void *value1, const void *value2)
|
|
|
|
{
|
|
|
|
const struct qemuDomainDiskInfo *info1 = value1, *info2 = value2;
|
|
|
|
|
|
|
|
return memcmp(info1, info2, sizeof(*info1));
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
testQemuMonitorJSONqemuMonitorJSONGetBlockInfo(const void *data)
|
|
|
|
{
|
|
|
|
virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
|
|
|
|
qemuMonitorTestPtr test = qemuMonitorTestNewSimple(true, xmlopt);
|
|
|
|
int ret = -1;
|
|
|
|
virHashTablePtr blockDevices = NULL, expectedBlockDevices = NULL;
|
|
|
|
struct qemuDomainDiskInfo *info;
|
|
|
|
|
|
|
|
if (!test)
|
|
|
|
return -1;
|
|
|
|
|
2014-04-04 23:36:25 +00:00
|
|
|
if (!(blockDevices = virHashCreate(32, virHashValueFree)) ||
|
|
|
|
!(expectedBlockDevices = virHashCreate(32, virHashValueFree)))
|
2013-10-02 12:39:10 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (VIR_ALLOC(info) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virHashAddEntry(expectedBlockDevices, "virtio-disk0", info) < 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
"Unable to create expectedBlockDevices hash table");
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (VIR_ALLOC(info) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virHashAddEntry(expectedBlockDevices, "virtio-disk1", info) < 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
"Unable to create expectedBlockDevices hash table");
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (VIR_ALLOC(info) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
info->locked = true;
|
|
|
|
info->removable = true;
|
2016-05-19 12:57:41 +00:00
|
|
|
info->tray = true;
|
|
|
|
|
2013-10-02 12:39:10 +00:00
|
|
|
if (virHashAddEntry(expectedBlockDevices, "ide0-1-0", info) < 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
"Unable to create expectedBlockDevices hash table");
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2016-05-19 12:57:41 +00:00
|
|
|
if (VIR_ALLOC(info) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
info->removable = true;
|
|
|
|
info->tray = true;
|
|
|
|
info->empty = true;
|
|
|
|
|
|
|
|
if (virHashAddEntry(expectedBlockDevices, "ide0-1-1", info) < 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
"Unable to create expectedBlockDevices hash table");
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2013-10-02 16:46:42 +00:00
|
|
|
if (qemuMonitorTestAddItem(test, "query-block", queryBlockReply) < 0)
|
2013-10-02 12:39:10 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (qemuMonitorJSONGetBlockInfo(qemuMonitorTestGetMonitor(test), blockDevices) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!virHashEqual(blockDevices, expectedBlockDevices, testHashEqualQemuDomainDiskInfo)) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
"Hashtable is different to the expected one");
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
2014-03-25 06:53:44 +00:00
|
|
|
cleanup:
|
2013-10-02 12:39:10 +00:00
|
|
|
virHashFree(blockDevices);
|
|
|
|
virHashFree(expectedBlockDevices);
|
|
|
|
qemuMonitorTestFree(test);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-10-02 13:08:02 +00:00
|
|
|
static int
|
|
|
|
testQemuMonitorJSONqemuMonitorJSONGetBlockStatsInfo(const void *data)
|
|
|
|
{
|
|
|
|
virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
|
|
|
|
qemuMonitorTestPtr test = qemuMonitorTestNewSimple(true, xmlopt);
|
2015-03-10 16:11:22 +00:00
|
|
|
virHashTablePtr blockstats = NULL;
|
|
|
|
qemuBlockStatsPtr stats;
|
2013-10-02 13:08:02 +00:00
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
const char *reply =
|
|
|
|
"{"
|
|
|
|
" \"return\": ["
|
|
|
|
" {"
|
|
|
|
" \"device\": \"drive-virtio-disk0\","
|
|
|
|
" \"parent\": {"
|
|
|
|
" \"stats\": {"
|
|
|
|
" \"flush_total_time_ns\": 0,"
|
|
|
|
" \"wr_highest_offset\": 5256018944,"
|
|
|
|
" \"wr_total_time_ns\": 0,"
|
|
|
|
" \"wr_bytes\": 0,"
|
|
|
|
" \"rd_total_time_ns\": 0,"
|
|
|
|
" \"flush_operations\": 0,"
|
|
|
|
" \"wr_operations\": 0,"
|
|
|
|
" \"rd_bytes\": 0,"
|
|
|
|
" \"rd_operations\": 0"
|
|
|
|
" }"
|
|
|
|
" },"
|
|
|
|
" \"stats\": {"
|
|
|
|
" \"flush_total_time_ns\": 0,"
|
|
|
|
" \"wr_highest_offset\": 10406001664,"
|
|
|
|
" \"wr_total_time_ns\": 530699221,"
|
|
|
|
" \"wr_bytes\": 2845696,"
|
|
|
|
" \"rd_total_time_ns\": 640616474,"
|
|
|
|
" \"flush_operations\": 0,"
|
|
|
|
" \"wr_operations\": 174,"
|
|
|
|
" \"rd_bytes\": 28505088,"
|
|
|
|
" \"rd_operations\": 1279"
|
|
|
|
" }"
|
|
|
|
" },"
|
|
|
|
" {"
|
|
|
|
" \"device\": \"drive-virtio-disk1\","
|
|
|
|
" \"parent\": {"
|
|
|
|
" \"stats\": {"
|
|
|
|
" \"flush_total_time_ns\": 0,"
|
|
|
|
" \"wr_highest_offset\": 0,"
|
|
|
|
" \"wr_total_time_ns\": 0,"
|
|
|
|
" \"wr_bytes\": 0,"
|
|
|
|
" \"rd_total_time_ns\": 0,"
|
|
|
|
" \"flush_operations\": 0,"
|
|
|
|
" \"wr_operations\": 0,"
|
|
|
|
" \"rd_bytes\": 0,"
|
|
|
|
" \"rd_operations\": 0"
|
|
|
|
" }"
|
|
|
|
" },"
|
|
|
|
" \"stats\": {"
|
|
|
|
" \"flush_total_time_ns\": 0,"
|
|
|
|
" \"wr_highest_offset\": 0,"
|
|
|
|
" \"wr_total_time_ns\": 0,"
|
|
|
|
" \"wr_bytes\": 0,"
|
|
|
|
" \"rd_total_time_ns\": 8232156,"
|
|
|
|
" \"flush_operations\": 0,"
|
|
|
|
" \"wr_operations\": 0,"
|
|
|
|
" \"rd_bytes\": 348160,"
|
|
|
|
" \"rd_operations\": 85"
|
|
|
|
" }"
|
|
|
|
" },"
|
|
|
|
" {"
|
|
|
|
" \"device\": \"drive-ide0-1-0\","
|
|
|
|
" \"parent\": {"
|
|
|
|
" \"stats\": {"
|
|
|
|
" \"flush_total_time_ns\": 0,"
|
|
|
|
" \"wr_total_time_ns\": 0,"
|
|
|
|
" \"wr_bytes\": 0,"
|
|
|
|
" \"rd_total_time_ns\": 0,"
|
|
|
|
" \"flush_operations\": 0,"
|
|
|
|
" \"wr_operations\": 0,"
|
|
|
|
" \"rd_bytes\": 0,"
|
|
|
|
" \"rd_operations\": 0"
|
|
|
|
" }"
|
|
|
|
" },"
|
|
|
|
" \"stats\": {"
|
|
|
|
" \"flush_total_time_ns\": 0,"
|
|
|
|
" \"wr_highest_offset\": 0,"
|
|
|
|
" \"wr_total_time_ns\": 0,"
|
|
|
|
" \"wr_bytes\": 0,"
|
|
|
|
" \"rd_total_time_ns\": 1004952,"
|
|
|
|
" \"flush_operations\": 0,"
|
|
|
|
" \"wr_operations\": 0,"
|
|
|
|
" \"rd_bytes\": 49250,"
|
|
|
|
" \"rd_operations\": 16"
|
|
|
|
" }"
|
|
|
|
" }"
|
|
|
|
" ],"
|
|
|
|
" \"id\": \"libvirt-11\""
|
|
|
|
"}";
|
|
|
|
|
|
|
|
if (!test)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
/* fill in seven times - we are gonna ask seven times later on */
|
|
|
|
if (qemuMonitorTestAddItem(test, "query-blockstats", reply) < 0 ||
|
|
|
|
qemuMonitorTestAddItem(test, "query-blockstats", reply) < 0 ||
|
|
|
|
qemuMonitorTestAddItem(test, "query-blockstats", reply) < 0 ||
|
|
|
|
qemuMonitorTestAddItem(test, "query-blockstats", reply) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2015-06-23 14:58:07 +00:00
|
|
|
#define CHECK0FULL(var, value, varformat, valformat) \
|
2015-03-10 16:11:22 +00:00
|
|
|
if (stats->var != value) { \
|
2013-10-02 13:08:02 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, \
|
2015-06-23 14:58:07 +00:00
|
|
|
"Invalid " #var " value: " varformat \
|
|
|
|
", expected " valformat, \
|
2015-03-10 16:11:22 +00:00
|
|
|
stats->var, value); \
|
2013-10-02 13:08:02 +00:00
|
|
|
goto cleanup; \
|
|
|
|
}
|
|
|
|
|
2015-06-23 14:58:07 +00:00
|
|
|
#define CHECK0(var, value) CHECK0FULL(var, value, "%lld", "%d")
|
|
|
|
|
2015-03-10 16:11:22 +00:00
|
|
|
#define CHECK(NAME, RD_REQ, RD_BYTES, RD_TOTAL_TIMES, WR_REQ, WR_BYTES, \
|
2015-06-23 14:58:07 +00:00
|
|
|
WR_TOTAL_TIMES, FLUSH_REQ, FLUSH_TOTAL_TIMES, \
|
|
|
|
WR_HIGHEST_OFFSET, WR_HIGHEST_OFFSET_VALID) \
|
2015-03-10 16:11:22 +00:00
|
|
|
if (!(stats = virHashLookup(blockstats, NAME))) { \
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, \
|
|
|
|
"block stats for device '%s' is missing", NAME); \
|
|
|
|
goto cleanup; \
|
|
|
|
} \
|
2013-10-02 13:08:02 +00:00
|
|
|
CHECK0(rd_req, RD_REQ) \
|
|
|
|
CHECK0(rd_bytes, RD_BYTES) \
|
|
|
|
CHECK0(rd_total_times, RD_TOTAL_TIMES) \
|
|
|
|
CHECK0(wr_req, WR_REQ) \
|
|
|
|
CHECK0(wr_bytes, WR_BYTES) \
|
|
|
|
CHECK0(wr_total_times, WR_TOTAL_TIMES) \
|
|
|
|
CHECK0(flush_req, FLUSH_REQ) \
|
2015-06-23 14:58:07 +00:00
|
|
|
CHECK0(flush_total_times, FLUSH_TOTAL_TIMES) \
|
|
|
|
CHECK0FULL(wr_highest_offset, WR_HIGHEST_OFFSET, "%llu", "%llu") \
|
|
|
|
CHECK0FULL(wr_highest_offset_valid, WR_HIGHEST_OFFSET_VALID, "%d", "%d")
|
2013-10-02 13:08:02 +00:00
|
|
|
|
2015-03-10 16:11:22 +00:00
|
|
|
if (qemuMonitorGetAllBlockStatsInfo(qemuMonitorTestGetMonitor(test),
|
|
|
|
&blockstats, false) < 0)
|
2013-10-02 13:08:02 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2015-03-10 16:11:22 +00:00
|
|
|
if (!blockstats) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
"qemuMonitorJSONGetBlockStatsInfo didn't return stats");
|
2013-10-02 13:08:02 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2015-06-23 14:58:07 +00:00
|
|
|
CHECK("virtio-disk0", 1279, 28505088, 640616474, 174, 2845696, 530699221, 0, 0, 5256018944ULL, true)
|
|
|
|
CHECK("virtio-disk1", 85, 348160, 8232156, 0, 0, 0, 0, 0, 0ULL, true)
|
2015-06-26 14:40:29 +00:00
|
|
|
CHECK("ide0-1-0", 16, 49250, 1004952, 0, 0, 0, 0, 0, 0ULL, false)
|
2015-03-10 16:11:22 +00:00
|
|
|
|
2013-10-02 13:08:02 +00:00
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
#undef CHECK
|
|
|
|
#undef CHECK0
|
2015-06-23 14:58:07 +00:00
|
|
|
#undef CHECK0FULL
|
2013-10-02 13:08:02 +00:00
|
|
|
|
2014-03-25 06:53:44 +00:00
|
|
|
cleanup:
|
2013-10-02 13:08:02 +00:00
|
|
|
qemuMonitorTestFree(test);
|
2015-03-10 16:11:22 +00:00
|
|
|
virHashFree(blockstats);
|
2013-10-02 13:08:02 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2016-04-14 10:33:50 +00:00
|
|
|
static int
|
2016-06-20 13:47:46 +00:00
|
|
|
testQemuMonitorJSONqemuMonitorJSONGetMigrationParams(const void *data)
|
2016-04-14 10:33:50 +00:00
|
|
|
{
|
|
|
|
virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
|
|
|
|
qemuMonitorTestPtr test = qemuMonitorTestNewSimple(true, xmlopt);
|
2016-06-20 13:47:46 +00:00
|
|
|
qemuMonitorMigrationParams params;
|
2016-04-14 10:33:50 +00:00
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (!test)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (qemuMonitorTestAddItem(test, "query-migrate-parameters",
|
|
|
|
"{"
|
|
|
|
" \"return\": {"
|
|
|
|
" \"decompress-threads\": 2,"
|
2016-06-20 15:10:32 +00:00
|
|
|
" \"cpu-throttle-increment\": 10,"
|
2016-04-14 10:33:50 +00:00
|
|
|
" \"compress-threads\": 8,"
|
2016-06-20 15:10:32 +00:00
|
|
|
" \"compress-level\": 1,"
|
2017-02-16 23:33:22 +00:00
|
|
|
" \"cpu-throttle-initial\": 20,"
|
|
|
|
" \"tls-creds\": \"tls0\","
|
|
|
|
" \"tls-hostname\": \"\""
|
2016-04-14 10:33:50 +00:00
|
|
|
" }"
|
|
|
|
"}") < 0) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2016-06-20 13:47:46 +00:00
|
|
|
if (qemuMonitorJSONGetMigrationParams(qemuMonitorTestGetMonitor(test),
|
|
|
|
¶ms) < 0)
|
2016-04-14 10:33:50 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2016-06-20 15:07:55 +00:00
|
|
|
#define CHECK(VAR, FIELD, VALUE) \
|
|
|
|
do { \
|
|
|
|
if (!params.VAR ## _set) { \
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s is not set", FIELD); \
|
|
|
|
goto cleanup; \
|
|
|
|
} \
|
|
|
|
if (params.VAR != VALUE) { \
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, \
|
|
|
|
"Invalid %s: %d, expected %d", \
|
|
|
|
FIELD, params.VAR, VALUE); \
|
|
|
|
goto cleanup; \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
CHECK(compressLevel, "compress-level", 1);
|
|
|
|
CHECK(compressThreads, "compress-threads", 8);
|
|
|
|
CHECK(decompressThreads, "decompress-threads", 2);
|
2016-06-20 15:10:32 +00:00
|
|
|
CHECK(cpuThrottleInitial, "cpu-throttle-initial", 20);
|
|
|
|
CHECK(cpuThrottleIncrement, "cpu-throttle-increment", 10);
|
2016-06-20 15:07:55 +00:00
|
|
|
|
2017-02-16 23:33:22 +00:00
|
|
|
#undef CHECK
|
|
|
|
|
|
|
|
#define CHECK(VAR, FIELD, VALUE) \
|
|
|
|
do { \
|
|
|
|
if (!params.VAR) { \
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s is not set", FIELD); \
|
|
|
|
goto cleanup; \
|
|
|
|
} \
|
|
|
|
if (STRNEQ(params.VAR, VALUE)) { \
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, \
|
|
|
|
"Invalid %s:'%s', expected '%s'", \
|
|
|
|
FIELD, params.VAR, VALUE); \
|
|
|
|
goto cleanup; \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
CHECK(migrateTLSAlias, "tls-creds", "tls0");
|
|
|
|
CHECK(migrateTLSHostname, "tls-hostname", "");
|
|
|
|
|
2016-06-20 15:07:55 +00:00
|
|
|
#undef CHECK
|
2016-04-14 10:33:50 +00:00
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
2017-02-16 23:33:22 +00:00
|
|
|
VIR_FREE(params.migrateTLSAlias);
|
|
|
|
VIR_FREE(params.migrateTLSHostname);
|
2016-04-14 10:33:50 +00:00
|
|
|
qemuMonitorTestFree(test);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-10-02 14:01:46 +00:00
|
|
|
static int
|
|
|
|
testQemuMonitorJSONqemuMonitorJSONGetMigrationCacheSize(const void *data)
|
|
|
|
{
|
|
|
|
virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
|
|
|
|
qemuMonitorTestPtr test = qemuMonitorTestNewSimple(true, xmlopt);
|
|
|
|
int ret = -1;
|
|
|
|
unsigned long long cacheSize;
|
|
|
|
|
|
|
|
if (!test)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (qemuMonitorTestAddItem(test, "query-migrate-cache-size",
|
|
|
|
"{"
|
|
|
|
" \"return\": 67108864,"
|
|
|
|
" \"id\": \"libvirt-12\""
|
|
|
|
"}") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (qemuMonitorJSONGetMigrationCacheSize(qemuMonitorTestGetMonitor(test),
|
|
|
|
&cacheSize) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (cacheSize != 67108864) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Invalid cacheSize: %llu, expected 67108864",
|
|
|
|
cacheSize);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 06:53:44 +00:00
|
|
|
cleanup:
|
2013-10-02 14:01:46 +00:00
|
|
|
qemuMonitorTestFree(test);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-10-02 14:43:35 +00:00
|
|
|
static int
|
2015-11-26 12:23:08 +00:00
|
|
|
testQemuMonitorJSONqemuMonitorJSONGetMigrationStats(const void *data)
|
2013-10-02 14:43:35 +00:00
|
|
|
{
|
|
|
|
virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
|
|
|
|
qemuMonitorTestPtr test = qemuMonitorTestNewSimple(true, xmlopt);
|
|
|
|
int ret = -1;
|
2015-11-26 12:23:08 +00:00
|
|
|
qemuMonitorMigrationStats stats, expectedStats;
|
2013-10-02 14:43:35 +00:00
|
|
|
|
|
|
|
if (!test)
|
|
|
|
return -1;
|
|
|
|
|
2015-11-26 12:23:08 +00:00
|
|
|
memset(&expectedStats, 0, sizeof(expectedStats));
|
2013-10-02 14:43:35 +00:00
|
|
|
|
2015-11-26 12:23:08 +00:00
|
|
|
expectedStats.status = QEMU_MONITOR_MIGRATION_STATUS_ACTIVE;
|
|
|
|
expectedStats.total_time = 47;
|
|
|
|
expectedStats.ram_total = 1611038720;
|
|
|
|
expectedStats.ram_remaining = 1605013504;
|
|
|
|
expectedStats.ram_transferred = 3625548;
|
2013-10-02 14:43:35 +00:00
|
|
|
|
|
|
|
if (qemuMonitorTestAddItem(test, "query-migrate",
|
|
|
|
"{"
|
|
|
|
" \"return\": {"
|
|
|
|
" \"status\": \"active\","
|
|
|
|
" \"total-time\": 47,"
|
|
|
|
" \"ram\": {"
|
|
|
|
" \"total\": 1611038720,"
|
|
|
|
" \"remaining\": 1605013504,"
|
|
|
|
" \"transferred\": 3625548"
|
|
|
|
" }"
|
|
|
|
" },"
|
|
|
|
" \"id\": \"libvirt-13\""
|
|
|
|
"}") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2015-11-26 12:23:08 +00:00
|
|
|
if (qemuMonitorJSONGetMigrationStats(qemuMonitorTestGetMonitor(test), &stats) < 0)
|
2013-10-02 14:43:35 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2015-11-26 12:23:08 +00:00
|
|
|
if (memcmp(&stats, &expectedStats, sizeof(stats)) != 0) {
|
2013-10-02 14:43:35 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
"Invalid migration status");
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
2014-03-25 06:53:44 +00:00
|
|
|
cleanup:
|
2013-10-02 14:43:35 +00:00
|
|
|
qemuMonitorTestFree(test);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-10-02 15:11:30 +00:00
|
|
|
static int
|
2014-11-13 18:29:14 +00:00
|
|
|
testHashEqualChardevInfo(const void *value1, const void *value2)
|
2013-10-02 15:11:30 +00:00
|
|
|
{
|
2014-11-13 18:29:14 +00:00
|
|
|
const qemuMonitorChardevInfo *info1 = value1;
|
|
|
|
const qemuMonitorChardevInfo *info2 = value2;
|
|
|
|
|
|
|
|
if (info1->state != info2->state)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (STRNEQ_NULLABLE(info1->ptyPath, info2->ptyPath))
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error:
|
|
|
|
fprintf(stderr, "\n"
|
|
|
|
"info1->state: %d info2->state: %d\n"
|
|
|
|
"info1->ptyPath: %s info2->ptyPath: %s\n",
|
|
|
|
info1->state, info2->state, info1->ptyPath, info2->ptyPath);
|
|
|
|
return -1;
|
2013-10-02 15:11:30 +00:00
|
|
|
}
|
|
|
|
|
2014-11-13 18:29:14 +00:00
|
|
|
|
2013-10-02 15:11:30 +00:00
|
|
|
static int
|
2014-11-13 15:17:21 +00:00
|
|
|
testQemuMonitorJSONqemuMonitorJSONGetChardevInfo(const void *data)
|
2013-10-02 15:11:30 +00:00
|
|
|
{
|
|
|
|
virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
|
|
|
|
qemuMonitorTestPtr test = qemuMonitorTestNewSimple(true, xmlopt);
|
|
|
|
int ret = -1;
|
2014-11-13 15:17:21 +00:00
|
|
|
virHashTablePtr info = NULL, expectedInfo = NULL;
|
2014-11-13 18:29:14 +00:00
|
|
|
qemuMonitorChardevInfo info0 = { NULL, VIR_DOMAIN_CHR_DEVICE_STATE_DEFAULT };
|
|
|
|
qemuMonitorChardevInfo info1 = { (char *) "/dev/pts/21", VIR_DOMAIN_CHR_DEVICE_STATE_CONNECTED };
|
|
|
|
qemuMonitorChardevInfo info2 = { (char *) "/dev/pts/20", VIR_DOMAIN_CHR_DEVICE_STATE_DEFAULT };
|
|
|
|
qemuMonitorChardevInfo info3 = { NULL, VIR_DOMAIN_CHR_DEVICE_STATE_DISCONNECTED };
|
2013-10-02 15:11:30 +00:00
|
|
|
|
|
|
|
if (!test)
|
|
|
|
return -1;
|
|
|
|
|
2015-04-28 01:16:13 +00:00
|
|
|
if (!(info = virHashCreate(32, qemuMonitorChardevInfoFree)) ||
|
2014-11-13 15:17:21 +00:00
|
|
|
!(expectedInfo = virHashCreate(32, NULL)))
|
2013-10-02 15:11:30 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2014-11-13 18:29:14 +00:00
|
|
|
if (virHashAddEntry(expectedInfo, "charserial1", &info1) < 0 ||
|
|
|
|
virHashAddEntry(expectedInfo, "charserial0", &info2) < 0 ||
|
|
|
|
virHashAddEntry(expectedInfo, "charmonitor", &info0) < 0 ||
|
|
|
|
virHashAddEntry(expectedInfo, "charserial2", &info3) < 0) {
|
2013-10-02 15:11:30 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
2014-11-13 15:17:21 +00:00
|
|
|
"Unable to create expectedInfo hash table");
|
2013-10-02 15:11:30 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (qemuMonitorTestAddItem(test, "query-chardev",
|
|
|
|
"{"
|
|
|
|
" \"return\": ["
|
|
|
|
" {"
|
|
|
|
" \"filename\": \"pty:/dev/pts/21\","
|
2014-11-13 18:29:14 +00:00
|
|
|
" \"label\": \"charserial1\","
|
|
|
|
" \"frontend-open\": true"
|
2013-10-02 15:11:30 +00:00
|
|
|
" },"
|
|
|
|
" {"
|
|
|
|
" \"filename\": \"pty:/dev/pts/20\","
|
|
|
|
" \"label\": \"charserial0\""
|
|
|
|
" },"
|
|
|
|
" {"
|
|
|
|
" \"filename\": \"unix:/var/lib/libvirt/qemu/gentoo.monitor,server\","
|
|
|
|
" \"label\": \"charmonitor\""
|
2014-11-13 18:29:14 +00:00
|
|
|
" },"
|
|
|
|
" {"
|
|
|
|
" \"filename\": \"unix:/path/to/socket,server\","
|
|
|
|
" \"label\": \"charserial2\","
|
|
|
|
" \"frontend-open\": false"
|
2013-10-02 15:11:30 +00:00
|
|
|
" }"
|
|
|
|
" ],"
|
|
|
|
" \"id\": \"libvirt-15\""
|
|
|
|
"}") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2014-11-13 15:17:21 +00:00
|
|
|
if (qemuMonitorJSONGetChardevInfo(qemuMonitorTestGetMonitor(test),
|
|
|
|
info) < 0)
|
2013-10-02 15:11:30 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2014-11-13 18:29:14 +00:00
|
|
|
if (!virHashEqual(info, expectedInfo, testHashEqualChardevInfo)) {
|
2013-10-02 15:11:30 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
"Hashtable is different to the expected one");
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
2014-03-25 06:53:44 +00:00
|
|
|
cleanup:
|
2014-11-13 15:17:21 +00:00
|
|
|
virHashFree(info);
|
|
|
|
virHashFree(expectedInfo);
|
2013-10-02 15:11:30 +00:00
|
|
|
qemuMonitorTestFree(test);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2016-10-31 21:22:59 +00:00
|
|
|
|
|
|
|
static int
|
|
|
|
testValidateGetBlockIoThrottle(virDomainBlockIoTuneInfo info,
|
|
|
|
virDomainBlockIoTuneInfo expectedInfo)
|
|
|
|
{
|
|
|
|
#define VALIDATE_IOTUNE(field) \
|
|
|
|
if (info.field != expectedInfo.field) { \
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, \
|
|
|
|
"info.%s=%llu != expected=%llu", \
|
|
|
|
#field, info.field, expectedInfo.field); \
|
|
|
|
return -1; \
|
|
|
|
} \
|
|
|
|
if (info.field##_max != expectedInfo.field##_max) { \
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, \
|
|
|
|
"info.%s_max=%llu != expected=%llu", \
|
|
|
|
#field, info.field##_max, expectedInfo.field##_max); \
|
|
|
|
return -1; \
|
|
|
|
} \
|
|
|
|
if (info.field##_max_length != expectedInfo.field##_max_length) { \
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, \
|
|
|
|
"info.%s_max_length=%llu != expected=%llu", \
|
|
|
|
#field, info.field##_max_length, \
|
|
|
|
expectedInfo.field##_max_length); \
|
|
|
|
return -1; \
|
|
|
|
}
|
|
|
|
VALIDATE_IOTUNE(total_bytes_sec);
|
|
|
|
VALIDATE_IOTUNE(read_bytes_sec);
|
|
|
|
VALIDATE_IOTUNE(write_bytes_sec);
|
|
|
|
VALIDATE_IOTUNE(total_iops_sec);
|
|
|
|
VALIDATE_IOTUNE(read_iops_sec);
|
|
|
|
VALIDATE_IOTUNE(write_iops_sec);
|
|
|
|
if (info.size_iops_sec != expectedInfo.size_iops_sec) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"info.size_iops_sec=%llu != expected=%llu",
|
|
|
|
info.size_iops_sec, expectedInfo.size_iops_sec);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (STRNEQ(info.group_name, expectedInfo.group_name)) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"info.group_name=%s != expected=%s",
|
|
|
|
info.group_name, expectedInfo.group_name);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
#undef VALIDATE_IOTUNE
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-10-02 16:46:42 +00:00
|
|
|
static int
|
|
|
|
testQemuMonitorJSONqemuMonitorJSONSetBlockIoThrottle(const void *data)
|
|
|
|
{
|
|
|
|
virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
|
|
|
|
qemuMonitorTestPtr test = qemuMonitorTestNewSimple(true, xmlopt);
|
|
|
|
int ret = -1;
|
|
|
|
virDomainBlockIoTuneInfo info, expectedInfo;
|
|
|
|
|
|
|
|
if (!test)
|
|
|
|
return -1;
|
|
|
|
|
2016-10-31 21:22:59 +00:00
|
|
|
expectedInfo = (virDomainBlockIoTuneInfo) {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, NULL, 15, 16, 17, 18, 19, 20};
|
|
|
|
if (VIR_STRDUP(expectedInfo.group_name, "group14") < 0)
|
|
|
|
return -1;
|
2013-10-02 16:46:42 +00:00
|
|
|
|
|
|
|
if (qemuMonitorTestAddItem(test, "query-block", queryBlockReply) < 0 ||
|
|
|
|
qemuMonitorTestAddItemParams(test, "block_set_io_throttle",
|
|
|
|
"{\"return\":{}}",
|
|
|
|
"device", "\"drive-virtio-disk1\"",
|
|
|
|
"bps", "1", "bps_rd", "2", "bps_wr", "3",
|
|
|
|
"iops", "4", "iops_rd", "5", "iops_wr", "6",
|
2014-12-03 13:42:27 +00:00
|
|
|
"bps_max", "7", "bps_rd_max", "8",
|
|
|
|
"bps_wr_max", "9",
|
|
|
|
"iops_max", "10", "iops_rd_max", "11",
|
|
|
|
"iops_wr_max", "12", "iops_size", "13",
|
2016-10-31 21:22:59 +00:00
|
|
|
"group", "\"group14\"",
|
|
|
|
"bps_max_length", "15",
|
|
|
|
"bps_rd_max_length", "16",
|
|
|
|
"bps_wr_max_length", "17",
|
|
|
|
"iops_max_length", "18",
|
|
|
|
"iops_rd_max_length", "19",
|
|
|
|
"iops_wr_max_length", "20",
|
2013-10-02 16:46:42 +00:00
|
|
|
NULL, NULL) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (qemuMonitorJSONGetBlockIoThrottle(qemuMonitorTestGetMonitor(test),
|
2016-05-20 06:30:45 +00:00
|
|
|
"drive-virtio-disk0", &info) < 0)
|
2013-10-02 16:46:42 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2016-10-31 21:22:59 +00:00
|
|
|
if (testValidateGetBlockIoThrottle(info, expectedInfo) < 0)
|
2013-10-02 16:46:42 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (qemuMonitorJSONSetBlockIoThrottle(qemuMonitorTestGetMonitor(test),
|
2016-09-18 16:02:50 +00:00
|
|
|
"drive-virtio-disk1", &info, true,
|
2016-10-31 21:22:59 +00:00
|
|
|
true, true) < 0)
|
2013-10-02 16:46:42 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = 0;
|
2014-03-25 06:53:44 +00:00
|
|
|
cleanup:
|
2016-10-31 21:22:59 +00:00
|
|
|
VIR_FREE(info.group_name);
|
|
|
|
VIR_FREE(expectedInfo.group_name);
|
2013-10-02 16:46:42 +00:00
|
|
|
qemuMonitorTestFree(test);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-10-02 16:55:42 +00:00
|
|
|
static int
|
|
|
|
testQemuMonitorJSONqemuMonitorJSONGetTargetArch(const void *data)
|
|
|
|
{
|
|
|
|
virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
|
|
|
|
qemuMonitorTestPtr test = qemuMonitorTestNewSimple(true, xmlopt);
|
|
|
|
int ret = -1;
|
|
|
|
char *arch;
|
|
|
|
|
|
|
|
if (!test)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (qemuMonitorTestAddItem(test, "query-target",
|
|
|
|
"{"
|
|
|
|
" \"return\": {"
|
|
|
|
" \"arch\": \"x86_64\""
|
|
|
|
" },"
|
|
|
|
" \"id\": \"libvirt-21\""
|
|
|
|
"}") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!(arch = qemuMonitorJSONGetTargetArch(qemuMonitorTestGetMonitor(test))))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (STRNEQ(arch, "x86_64")) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Unexpected architecture %s, expecting x86_64",
|
|
|
|
arch);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
2014-03-25 06:53:44 +00:00
|
|
|
cleanup:
|
2013-10-02 16:55:42 +00:00
|
|
|
VIR_FREE(arch);
|
|
|
|
qemuMonitorTestFree(test);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-10-02 17:03:53 +00:00
|
|
|
static int
|
|
|
|
testQemuMonitorJSONqemuMonitorJSONGetMigrationCapability(const void *data)
|
|
|
|
{
|
|
|
|
virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
|
|
|
|
qemuMonitorTestPtr test = qemuMonitorTestNewSimple(true, xmlopt);
|
|
|
|
int ret = -1;
|
|
|
|
int cap;
|
|
|
|
const char *reply =
|
|
|
|
"{"
|
|
|
|
" \"return\": ["
|
|
|
|
" {"
|
|
|
|
" \"state\": false,"
|
|
|
|
" \"capability\": \"xbzrle\""
|
|
|
|
" }"
|
|
|
|
" ],"
|
|
|
|
" \"id\": \"libvirt-22\""
|
|
|
|
"}";
|
|
|
|
|
|
|
|
if (!test)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (qemuMonitorTestAddItem(test, "query-migrate-capabilities", reply) < 0 ||
|
|
|
|
qemuMonitorTestAddItem(test, "migrate-set-capabilities",
|
|
|
|
"{\"return\":{}}") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
cap = qemuMonitorJSONGetMigrationCapability(qemuMonitorTestGetMonitor(test),
|
|
|
|
QEMU_MONITOR_MIGRATION_CAPS_XBZRLE);
|
|
|
|
if (cap != 1) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Unexpected capability: %d, expecting 1",
|
|
|
|
cap);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (qemuMonitorJSONSetMigrationCapability(qemuMonitorTestGetMonitor(test),
|
2014-11-10 13:46:26 +00:00
|
|
|
QEMU_MONITOR_MIGRATION_CAPS_XBZRLE,
|
|
|
|
true) < 0)
|
2013-10-02 17:03:53 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = 0;
|
2014-03-25 06:53:44 +00:00
|
|
|
cleanup:
|
2013-10-02 17:03:53 +00:00
|
|
|
qemuMonitorTestFree(test);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-10-02 16:23:17 +00:00
|
|
|
static int
|
|
|
|
testQemuMonitorJSONqemuMonitorJSONSendKey(const void *data)
|
|
|
|
{
|
|
|
|
virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
|
|
|
|
qemuMonitorTestPtr test = qemuMonitorTestNewSimple(true, xmlopt);
|
|
|
|
int ret = -1;
|
|
|
|
unsigned int keycodes[] = {43, 26, 46, 32};
|
|
|
|
|
|
|
|
if (!test)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (qemuMonitorTestAddItem(test, "send-key",
|
|
|
|
"{\"return\": {}, \"id\": \"libvirt-16\"}") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (qemuMonitorJSONSendKey(qemuMonitorTestGetMonitor(test),
|
|
|
|
0, keycodes, ARRAY_CARDINALITY(keycodes)) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = 0;
|
2014-03-25 06:53:44 +00:00
|
|
|
cleanup:
|
2013-10-02 16:23:17 +00:00
|
|
|
qemuMonitorTestFree(test);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2014-06-03 09:19:51 +00:00
|
|
|
static int
|
|
|
|
testQemuMonitorJSONqemuMonitorJSONSendKeyHoldtime(const void *data)
|
|
|
|
{
|
|
|
|
virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
|
|
|
|
qemuMonitorTestPtr test = qemuMonitorTestNewSimple(true, xmlopt);
|
|
|
|
int ret = -1;
|
|
|
|
unsigned int keycodes[] = {43, 26, 46, 32};
|
|
|
|
|
|
|
|
if (!test)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (qemuMonitorTestAddItemParams(test, "send-key",
|
|
|
|
"{\"return\":{}}",
|
|
|
|
"hold-time", "31337",
|
|
|
|
"keys", "[{\"type\":\"number\",\"data\":43},"
|
|
|
|
"{\"type\":\"number\",\"data\":26},"
|
|
|
|
"{\"type\":\"number\",\"data\":46},"
|
|
|
|
"{\"type\":\"number\",\"data\":32}]",
|
|
|
|
NULL, NULL) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (qemuMonitorJSONSendKey(qemuMonitorTestGetMonitor(test),
|
|
|
|
31337, keycodes,
|
|
|
|
ARRAY_CARDINALITY(keycodes)) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
|
|
|
qemuMonitorTestFree(test);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
blockjob: allow omitted arguments to QMP block-commit
We are about to turn on support for active block commit. Although
qemu 2.0 was the first version to mostly support it, that version
mis-handles 0-length files, and doesn't have anything available for
easy probing. But qemu 2.1 fixed bugs, and made life simpler by
letting the 'top' argument be optional. Unless someone begs for
active commit with qemu 2.0, for now we are just going to enable
it only by probing for qemu 2.1 behavior (anyone backporting active
commit can also backport the optional argument behavior). This
requires qemu.git commit 7676e2c597000eff3a7233b40cca768b358f9bc9.
Although all our actual uses of block-commit supply arguments for
both base and top, we can omit both arguments and use a bogus
device string to trigger an interesting behavior in qemu. All QMP
commands first do argument validation, failing with GenericError
if a mandatory argument is missing. Once that passes, the code
in the specific command gets to do further checking, and the qemu
developers made sure that if device is the only supplied argument,
then the block-commit code will look up the device first, with a
failure of DeviceNotFound, before attempting any further argument
validation (most other validations fail with GenericError). Thus,
the category of error class can reliably be used to decipher
whether the top argument was optional, which in turn implies a
working active commit. Since we expect our bogus device string to
trigger an error either way, the code is written to return a
distinct return value without spamming the logs.
* src/qemu/qemu_monitor.h (qemuMonitorSupportsActiveCommit): New
prototype.
* src/qemu/qemu_monitor.c (qemuMonitorSupportsActiveCommit):
Implement it.
* src/qemu/qemu_monitor_json.h (qemuMonitorJSONBlockCommit):
Allow NULL for top and base, for probing purposes.
* src/qemu/qemu_monitor_json.c (qemuMonitorJSONBlockCommit):
Likewise, implementing the probe.
* tests/qemumonitorjsontest.c (mymain): Enable...
(testQemuMonitorJSONqemuMonitorSupportsActiveCommit): ...a new test.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-06-17 03:42:49 +00:00
|
|
|
static int
|
|
|
|
testQemuMonitorJSONqemuMonitorSupportsActiveCommit(const void *data)
|
|
|
|
{
|
|
|
|
virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
|
|
|
|
qemuMonitorTestPtr test = qemuMonitorTestNewSimple(true, xmlopt);
|
|
|
|
int ret = -1;
|
|
|
|
const char *error1 =
|
|
|
|
"{"
|
|
|
|
" \"error\": {"
|
|
|
|
" \"class\": \"DeviceNotFound\","
|
|
|
|
" \"desc\": \"Device 'bogus' not found\""
|
|
|
|
" }"
|
|
|
|
"}";
|
|
|
|
const char *error2 =
|
|
|
|
"{"
|
|
|
|
" \"error\": {"
|
|
|
|
" \"class\": \"GenericError\","
|
|
|
|
" \"desc\": \"Parameter 'top' is missing\""
|
|
|
|
" }"
|
|
|
|
"}";
|
|
|
|
|
|
|
|
if (!test)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (qemuMonitorTestAddItemParams(test, "block-commit", error1,
|
|
|
|
"device", "\"bogus\"",
|
|
|
|
NULL, NULL) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!qemuMonitorSupportsActiveCommit(qemuMonitorTestGetMonitor(test)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (qemuMonitorTestAddItemParams(test, "block-commit", error2,
|
|
|
|
"device", "\"bogus\"",
|
|
|
|
NULL, NULL) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (qemuMonitorSupportsActiveCommit(qemuMonitorTestGetMonitor(test)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
|
|
|
qemuMonitorTestFree(test);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2014-03-23 03:51:13 +00:00
|
|
|
static int
|
|
|
|
testQemuMonitorJSONqemuMonitorJSONGetDumpGuestMemoryCapability(const void *data)
|
|
|
|
{
|
|
|
|
virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
|
|
|
|
qemuMonitorTestPtr test = qemuMonitorTestNewSimple(true, xmlopt);
|
|
|
|
int ret = -1;
|
|
|
|
int cap;
|
|
|
|
const char *reply =
|
|
|
|
"{"
|
|
|
|
" \"return\": {"
|
|
|
|
" \"formats\": ["
|
|
|
|
" \"elf\","
|
|
|
|
" \"kdump-zlib\","
|
|
|
|
" \"kdump-lzo\","
|
|
|
|
" \"kdump-snappy\""
|
|
|
|
" ]"
|
|
|
|
" },"
|
|
|
|
" \"id\": \"libvirt-9\""
|
|
|
|
"}";
|
|
|
|
|
|
|
|
if (!test)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (qemuMonitorTestAddItem(test, "query-dump-guest-memory-capability",
|
|
|
|
reply) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
cap = qemuMonitorJSONGetDumpGuestMemoryCapability(
|
|
|
|
qemuMonitorTestGetMonitor(test), "elf");
|
|
|
|
|
|
|
|
if (cap != 1) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Unexpected capability: %d, expecting 1",
|
|
|
|
cap);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
2014-03-25 06:53:44 +00:00
|
|
|
cleanup:
|
2014-03-23 03:51:13 +00:00
|
|
|
qemuMonitorTestFree(test);
|
|
|
|
return ret;
|
|
|
|
}
|
2013-07-22 11:07:23 +00:00
|
|
|
|
|
|
|
struct testCPUData {
|
|
|
|
const char *name;
|
|
|
|
virDomainXMLOptionPtr xmlopt;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
testQemuMonitorJSONGetCPUData(const void *opaque)
|
|
|
|
{
|
|
|
|
const struct testCPUData *data = opaque;
|
|
|
|
qemuMonitorTestPtr test = qemuMonitorTestNewSimple(true, data->xmlopt);
|
|
|
|
virCPUDataPtr cpuData = NULL;
|
|
|
|
char *jsonFile = NULL;
|
|
|
|
char *dataFile = NULL;
|
|
|
|
char *jsonStr = NULL;
|
|
|
|
char *actual = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (!test)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (virAsprintf(&jsonFile,
|
|
|
|
"%s/qemumonitorjsondata/qemumonitorjson-getcpu-%s.json",
|
|
|
|
abs_srcdir, data->name) < 0 ||
|
|
|
|
virAsprintf(&dataFile,
|
|
|
|
"%s/qemumonitorjsondata/qemumonitorjson-getcpu-%s.data",
|
|
|
|
abs_srcdir, data->name) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2016-05-26 15:01:52 +00:00
|
|
|
if (virTestLoadFile(jsonFile, &jsonStr) < 0)
|
2013-07-22 11:07:23 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-11-11 15:34:53 +00:00
|
|
|
if (qemuMonitorTestAddItem(test, "qom-list",
|
|
|
|
"{"
|
|
|
|
" \"return\": ["
|
|
|
|
" {"
|
|
|
|
" \"name\": \"filtered-features\","
|
|
|
|
" \"type\": \"X86CPUFeatureWordInfo\""
|
|
|
|
" },"
|
|
|
|
" {"
|
|
|
|
" \"name\": \"feature-words\","
|
|
|
|
" \"type\": \"X86CPUFeatureWordInfo\""
|
|
|
|
" }"
|
|
|
|
" ],"
|
|
|
|
" \"id\": \"libvirt-19\""
|
|
|
|
"}") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2013-07-22 11:07:23 +00:00
|
|
|
if (qemuMonitorTestAddItem(test, "qom-get", jsonStr) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2013-11-11 13:47:08 +00:00
|
|
|
if (qemuMonitorJSONGetGuestCPU(qemuMonitorTestGetMonitor(test),
|
|
|
|
VIR_ARCH_X86_64,
|
2017-03-13 10:00:48 +00:00
|
|
|
&cpuData, NULL) < 0)
|
2013-07-22 11:07:23 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2016-11-04 14:09:20 +00:00
|
|
|
if (!(actual = virCPUDataFormat(cpuData)))
|
2013-07-22 11:07:23 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2016-05-26 15:01:53 +00:00
|
|
|
if (virTestCompareToFile(actual, dataFile) < 0)
|
2013-07-22 11:07:23 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = 0;
|
2014-03-25 06:53:44 +00:00
|
|
|
cleanup:
|
2013-07-22 11:07:23 +00:00
|
|
|
VIR_FREE(jsonFile);
|
|
|
|
VIR_FREE(dataFile);
|
|
|
|
VIR_FREE(jsonStr);
|
|
|
|
VIR_FREE(actual);
|
2017-02-02 14:37:40 +00:00
|
|
|
virCPUDataFree(cpuData);
|
2013-07-22 11:07:23 +00:00
|
|
|
qemuMonitorTestFree(test);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-11-19 15:30:28 +00:00
|
|
|
static int
|
|
|
|
testQemuMonitorJSONGetNonExistingCPUData(const void *opaque)
|
|
|
|
{
|
|
|
|
virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr) opaque;
|
|
|
|
qemuMonitorTestPtr test = qemuMonitorTestNewSimple(true, xmlopt);
|
|
|
|
virCPUDataPtr cpuData = NULL;
|
|
|
|
int rv, ret = -1;
|
|
|
|
|
|
|
|
if (!test)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (qemuMonitorTestAddItem(test, "qom-list",
|
|
|
|
"{"
|
|
|
|
" \"id\": \"libvirt-7\","
|
|
|
|
" \"error\": {"
|
|
|
|
" \"class\": \"CommandNotFound\","
|
|
|
|
" \"desc\": \"The command qom-list has not been found\""
|
|
|
|
" }"
|
|
|
|
"}") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
rv = qemuMonitorJSONGetGuestCPU(qemuMonitorTestGetMonitor(test),
|
|
|
|
VIR_ARCH_X86_64,
|
2017-03-13 10:00:48 +00:00
|
|
|
&cpuData, NULL);
|
2013-11-19 15:30:28 +00:00
|
|
|
if (rv != -2) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Unexpected return value %d, expecting -2", rv);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cpuData) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Unexpected allocation of data = %p, expecting NULL",
|
|
|
|
cpuData);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
2014-03-25 06:53:44 +00:00
|
|
|
cleanup:
|
2013-11-19 15:30:28 +00:00
|
|
|
qemuMonitorTestFree(test);
|
2017-02-02 14:37:40 +00:00
|
|
|
virCPUDataFree(cpuData);
|
2013-11-19 15:30:28 +00:00
|
|
|
return ret;
|
|
|
|
}
|
2013-07-22 11:07:23 +00:00
|
|
|
|
2014-08-29 20:23:11 +00:00
|
|
|
static int
|
|
|
|
testQemuMonitorJSONGetIOThreads(const void *data)
|
|
|
|
{
|
|
|
|
virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
|
|
|
|
qemuMonitorTestPtr test = qemuMonitorTestNewSimple(true, xmlopt);
|
2015-03-25 15:59:37 +00:00
|
|
|
qemuMonitorIOThreadInfoPtr *info;
|
2014-08-29 20:23:11 +00:00
|
|
|
int ninfo = 0;
|
|
|
|
int ret = -1;
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
if (!test)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (qemuMonitorTestAddItem(test, "query-iothreads",
|
|
|
|
"{ "
|
|
|
|
" \"return\": [ "
|
|
|
|
" { "
|
|
|
|
" \"id\": \"iothread1\", "
|
|
|
|
" \"thread-id\": 30992 "
|
|
|
|
" }, "
|
|
|
|
" { "
|
|
|
|
" \"id\": \"iothread2\", "
|
|
|
|
" \"thread-id\": 30993 "
|
|
|
|
" } "
|
|
|
|
" ]"
|
|
|
|
"}") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if ((ninfo = qemuMonitorGetIOThreads(qemuMonitorTestGetMonitor(test),
|
|
|
|
&info)) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (ninfo != 2) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"ninfo %d is not 2", ninfo);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2015-04-27 18:16:54 +00:00
|
|
|
#define CHECK(i, wantiothread_id, wantthread_id) \
|
2014-08-29 20:23:11 +00:00
|
|
|
do { \
|
2015-04-27 18:16:54 +00:00
|
|
|
if (info[i]->iothread_id != (wantiothread_id)) { \
|
2014-08-29 20:23:11 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, \
|
2015-04-27 18:16:54 +00:00
|
|
|
"iothread_id %u is not %u", \
|
|
|
|
info[i]->iothread_id, (wantiothread_id)); \
|
2014-08-29 20:23:11 +00:00
|
|
|
goto cleanup; \
|
|
|
|
} \
|
|
|
|
if (info[i]->thread_id != (wantthread_id)) { \
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, \
|
|
|
|
"thread_id %d is not %d", \
|
|
|
|
info[i]->thread_id, (wantthread_id)); \
|
|
|
|
goto cleanup; \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
|
2015-04-27 18:16:54 +00:00
|
|
|
CHECK(0, 1, 30992);
|
|
|
|
CHECK(1, 2, 30993);
|
2014-08-29 20:23:11 +00:00
|
|
|
|
|
|
|
#undef CHECK
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
qemuMonitorTestFree(test);
|
|
|
|
for (i = 0; i < ninfo; i++)
|
2015-04-28 10:32:52 +00:00
|
|
|
VIR_FREE(info[i]);
|
2014-08-29 20:23:11 +00:00
|
|
|
VIR_FREE(info);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2016-07-29 16:08:06 +00:00
|
|
|
struct testCPUInfoData {
|
|
|
|
const char *name;
|
|
|
|
size_t maxvcpus;
|
|
|
|
virDomainXMLOptionPtr xmlopt;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static char *
|
|
|
|
testQemuMonitorCPUInfoFormat(qemuMonitorCPUInfoPtr vcpus,
|
|
|
|
size_t nvcpus)
|
|
|
|
{
|
|
|
|
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
|
|
|
qemuMonitorCPUInfoPtr vcpu;
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
for (i = 0; i < nvcpus; i++) {
|
|
|
|
vcpu = vcpus + i;
|
|
|
|
|
|
|
|
virBufferAsprintf(&buf, "[vcpu libvirt-id='%zu']\n", i);
|
|
|
|
virBufferAdjustIndent(&buf, 4);
|
|
|
|
|
2016-09-13 15:52:38 +00:00
|
|
|
virBufferAsprintf(&buf, "online=%s\n", vcpu->online ? "yes" : "no");
|
|
|
|
virBufferAsprintf(&buf, "hotpluggable=%s\n", vcpu->hotpluggable ? "yes" : "no");
|
|
|
|
|
2016-07-29 16:08:06 +00:00
|
|
|
if (vcpu->tid)
|
|
|
|
virBufferAsprintf(&buf, "thread-id='%llu'\n",
|
|
|
|
(unsigned long long) vcpu->tid);
|
|
|
|
|
|
|
|
if (vcpu->id != 0)
|
2016-11-22 09:21:46 +00:00
|
|
|
virBufferAsprintf(&buf, "enable-id='%d'\n", vcpu->id);
|
2016-07-29 16:08:06 +00:00
|
|
|
|
2016-11-22 08:32:11 +00:00
|
|
|
if (vcpu->qemu_id != -1)
|
|
|
|
virBufferAsprintf(&buf, "query-cpus-id='%d'\n", vcpu->qemu_id);
|
|
|
|
|
2016-07-29 16:08:06 +00:00
|
|
|
if (vcpu->type)
|
|
|
|
virBufferAsprintf(&buf, "type='%s'\n", vcpu->type);
|
|
|
|
|
|
|
|
if (vcpu->alias)
|
|
|
|
virBufferAsprintf(&buf, "alias='%s'\n", vcpu->alias);
|
|
|
|
if (vcpu->qom_path)
|
|
|
|
virBufferAsprintf(&buf, "qom_path='%s'\n", vcpu->qom_path);
|
|
|
|
|
|
|
|
if (vcpu->socket_id != -1 || vcpu->core_id != -1 ||
|
|
|
|
vcpu->thread_id != -1 || vcpu->vcpus != 0) {
|
|
|
|
virBufferAddLit(&buf, "topology:");
|
|
|
|
if (vcpu->socket_id != -1)
|
|
|
|
virBufferAsprintf(&buf, " socket='%d'", vcpu->socket_id);
|
|
|
|
if (vcpu->core_id != -1)
|
|
|
|
virBufferAsprintf(&buf, " core='%d'", vcpu->core_id);
|
|
|
|
if (vcpu->thread_id != -1)
|
|
|
|
virBufferAsprintf(&buf, " thread='%d'", vcpu->thread_id);
|
|
|
|
if (vcpu->vcpus != 0)
|
|
|
|
virBufferAsprintf(&buf, " vcpus='%u'", vcpu->vcpus);
|
|
|
|
virBufferAddLit(&buf, "\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
virBufferAdjustIndent(&buf, -4);
|
|
|
|
}
|
|
|
|
|
|
|
|
return virBufferContentAndReset(&buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
testQemuMonitorCPUInfo(const void *opaque)
|
|
|
|
{
|
|
|
|
const struct testCPUInfoData *data = opaque;
|
|
|
|
qemuMonitorTestPtr test = qemuMonitorTestNewSimple(true, data->xmlopt);
|
|
|
|
char *queryCpusFile = NULL;
|
|
|
|
char *queryHotpluggableFile = NULL;
|
|
|
|
char *dataFile = NULL;
|
|
|
|
char *queryCpusStr = NULL;
|
|
|
|
char *queryHotpluggableStr = NULL;
|
|
|
|
char *actual = NULL;
|
|
|
|
qemuMonitorCPUInfoPtr vcpus = NULL;
|
|
|
|
int rc;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (!test)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (virAsprintf(&queryCpusFile,
|
|
|
|
"%s/qemumonitorjsondata/qemumonitorjson-cpuinfo-%s-cpus.json",
|
|
|
|
abs_srcdir, data->name) < 0 ||
|
|
|
|
virAsprintf(&queryHotpluggableFile,
|
|
|
|
"%s/qemumonitorjsondata/qemumonitorjson-cpuinfo-%s-hotplug.json",
|
|
|
|
abs_srcdir, data->name) < 0 ||
|
|
|
|
virAsprintf(&dataFile,
|
|
|
|
"%s/qemumonitorjsondata/qemumonitorjson-cpuinfo-%s.data",
|
|
|
|
abs_srcdir, data->name) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virTestLoadFile(queryCpusFile, &queryCpusStr) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virTestLoadFile(queryHotpluggableFile, &queryHotpluggableStr) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (qemuMonitorTestAddItem(test, "query-hotpluggable-cpus",
|
|
|
|
queryHotpluggableStr) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (qemuMonitorTestAddItem(test, "query-cpus", queryCpusStr) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
rc = qemuMonitorGetCPUInfo(qemuMonitorTestGetMonitor(test),
|
|
|
|
&vcpus, data->maxvcpus, true);
|
|
|
|
|
|
|
|
if (rc < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
actual = testQemuMonitorCPUInfoFormat(vcpus, data->maxvcpus);
|
|
|
|
|
|
|
|
if (virTestCompareToFile(actual, dataFile) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(queryCpusFile);
|
|
|
|
VIR_FREE(queryHotpluggableFile);
|
|
|
|
VIR_FREE(dataFile);
|
|
|
|
VIR_FREE(queryCpusStr);
|
|
|
|
VIR_FREE(queryHotpluggableStr);
|
|
|
|
VIR_FREE(actual);
|
|
|
|
qemuMonitorCPUInfoFree(vcpus, data->maxvcpus);
|
|
|
|
qemuMonitorTestFree(test);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-08-20 12:31:29 +00:00
|
|
|
static int
|
|
|
|
mymain(void)
|
|
|
|
{
|
|
|
|
int ret = 0;
|
tests: Avoid use of virQEMUDriverCreateXMLConf(NULL)
We use the function to create a virDomainXMLOption object that is
required for some functions. However, we don't pass the driver
pointer to the object anywhere - rather than pass NULL. This
causes trouble later when parsing a domain XML and calling post
parse callbacks:
Program received signal SIGSEGV, Segmentation fault.
0x000000000043fa3e in qemuDomainDefPostParse (def=0x7d36c0, caps=0x7caf10, opaque=0x0) at qemu/qemu_domain.c:1043
1043 qemuCaps = virQEMUCapsCacheLookup(driver->qemuCapsCache, def->emulator);
(gdb) bt
#0 0x000000000043fa3e in qemuDomainDefPostParse (def=0x7d36c0, caps=0x7caf10, opaque=0x0) at qemu/qemu_domain.c:1043
#1 0x00007ffff2928bf9 in virDomainDefPostParse (def=0x7d36c0, caps=0x7caf10, xmlopt=0x7c82c0) at conf/domain_conf.c:4269
#2 0x00007ffff294de04 in virDomainDefParseXML (xml=0x7da8c0, root=0x7dab80, ctxt=0x7da980, caps=0x7caf10, xmlopt=0x7c82c0, flags=0) at conf/domain_conf.c:16400
#3 0x00007ffff294e5b5 in virDomainDefParseNode (xml=0x7da8c0, root=0x7dab80, caps=0x7caf10, xmlopt=0x7c82c0, flags=0) at conf/domain_conf.c:16582
#4 0x00007ffff294e424 in virDomainDefParse (xmlStr=0x0, filename=0x7c7ef0 "/home/zippy/work/libvirt/libvirt.git/tests/securityselinuxlabeldata/disks.xml", caps=0x7caf10, xmlopt=0x7c82c0, flags=0) at conf/domain_conf.c:16529
#5 0x00007ffff294e4b2 in virDomainDefParseFile (filename=0x7c7ef0 "/home/zippy/work/libvirt/libvirt.git/tests/securityselinuxlabeldata/disks.xml", caps=0x7caf10, xmlopt=0x7c82c0, flags=0) at conf/domain_conf.c:16553
#6 0x00000000004303ca in testSELinuxLoadDef (testname=0x53c929 "disks") at securityselinuxlabeltest.c:192
#7 0x00000000004309e8 in testSELinuxLabeling (opaque=0x53c929) at securityselinuxlabeltest.c:313
#8 0x0000000000431207 in virtTestRun (title=0x53c92f "Labelling \"disks\"", body=0x430964 <testSELinuxLabeling>, data=0x53c929) at testutils.c:211
#9 0x0000000000430c5d in mymain () at securityselinuxlabeltest.c:373
#10 0x00000000004325c2 in virtTestMain (argc=1, argv=0x7fffffffd7e8, func=0x430b4a <mymain>) at testutils.c:863
#11 0x0000000000430deb in main (argc=1, argv=0x7fffffffd7e8) at securityselinuxlabeltest.c:381
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
2015-09-22 14:27:57 +00:00
|
|
|
virQEMUDriver driver;
|
2013-09-18 15:28:31 +00:00
|
|
|
testQemuMonitorJSONSimpleFuncData simpleFunc;
|
2012-08-20 12:31:29 +00:00
|
|
|
|
2013-02-22 22:28:53 +00:00
|
|
|
#if !WITH_YAJL
|
2013-02-26 16:36:27 +00:00
|
|
|
fputs("libvirt not compiled with yajl, skipping this test\n", stderr);
|
2013-02-22 22:28:53 +00:00
|
|
|
return EXIT_AM_SKIP;
|
|
|
|
#endif
|
|
|
|
|
2013-02-22 22:42:39 +00:00
|
|
|
if (virThreadInitialize() < 0 ||
|
tests: Avoid use of virQEMUDriverCreateXMLConf(NULL)
We use the function to create a virDomainXMLOption object that is
required for some functions. However, we don't pass the driver
pointer to the object anywhere - rather than pass NULL. This
causes trouble later when parsing a domain XML and calling post
parse callbacks:
Program received signal SIGSEGV, Segmentation fault.
0x000000000043fa3e in qemuDomainDefPostParse (def=0x7d36c0, caps=0x7caf10, opaque=0x0) at qemu/qemu_domain.c:1043
1043 qemuCaps = virQEMUCapsCacheLookup(driver->qemuCapsCache, def->emulator);
(gdb) bt
#0 0x000000000043fa3e in qemuDomainDefPostParse (def=0x7d36c0, caps=0x7caf10, opaque=0x0) at qemu/qemu_domain.c:1043
#1 0x00007ffff2928bf9 in virDomainDefPostParse (def=0x7d36c0, caps=0x7caf10, xmlopt=0x7c82c0) at conf/domain_conf.c:4269
#2 0x00007ffff294de04 in virDomainDefParseXML (xml=0x7da8c0, root=0x7dab80, ctxt=0x7da980, caps=0x7caf10, xmlopt=0x7c82c0, flags=0) at conf/domain_conf.c:16400
#3 0x00007ffff294e5b5 in virDomainDefParseNode (xml=0x7da8c0, root=0x7dab80, caps=0x7caf10, xmlopt=0x7c82c0, flags=0) at conf/domain_conf.c:16582
#4 0x00007ffff294e424 in virDomainDefParse (xmlStr=0x0, filename=0x7c7ef0 "/home/zippy/work/libvirt/libvirt.git/tests/securityselinuxlabeldata/disks.xml", caps=0x7caf10, xmlopt=0x7c82c0, flags=0) at conf/domain_conf.c:16529
#5 0x00007ffff294e4b2 in virDomainDefParseFile (filename=0x7c7ef0 "/home/zippy/work/libvirt/libvirt.git/tests/securityselinuxlabeldata/disks.xml", caps=0x7caf10, xmlopt=0x7c82c0, flags=0) at conf/domain_conf.c:16553
#6 0x00000000004303ca in testSELinuxLoadDef (testname=0x53c929 "disks") at securityselinuxlabeltest.c:192
#7 0x00000000004309e8 in testSELinuxLabeling (opaque=0x53c929) at securityselinuxlabeltest.c:313
#8 0x0000000000431207 in virtTestRun (title=0x53c92f "Labelling \"disks\"", body=0x430964 <testSELinuxLabeling>, data=0x53c929) at testutils.c:211
#9 0x0000000000430c5d in mymain () at securityselinuxlabeltest.c:373
#10 0x00000000004325c2 in virtTestMain (argc=1, argv=0x7fffffffd7e8, func=0x430b4a <mymain>) at testutils.c:863
#11 0x0000000000430deb in main (argc=1, argv=0x7fffffffd7e8) at securityselinuxlabeltest.c:381
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
2015-09-22 14:27:57 +00:00
|
|
|
qemuTestDriverInit(&driver) < 0)
|
2013-02-22 22:42:39 +00:00
|
|
|
return EXIT_FAILURE;
|
2012-08-20 12:31:29 +00:00
|
|
|
|
|
|
|
virEventRegisterDefaultImpl();
|
|
|
|
|
tests: Avoid use of virQEMUDriverCreateXMLConf(NULL)
We use the function to create a virDomainXMLOption object that is
required for some functions. However, we don't pass the driver
pointer to the object anywhere - rather than pass NULL. This
causes trouble later when parsing a domain XML and calling post
parse callbacks:
Program received signal SIGSEGV, Segmentation fault.
0x000000000043fa3e in qemuDomainDefPostParse (def=0x7d36c0, caps=0x7caf10, opaque=0x0) at qemu/qemu_domain.c:1043
1043 qemuCaps = virQEMUCapsCacheLookup(driver->qemuCapsCache, def->emulator);
(gdb) bt
#0 0x000000000043fa3e in qemuDomainDefPostParse (def=0x7d36c0, caps=0x7caf10, opaque=0x0) at qemu/qemu_domain.c:1043
#1 0x00007ffff2928bf9 in virDomainDefPostParse (def=0x7d36c0, caps=0x7caf10, xmlopt=0x7c82c0) at conf/domain_conf.c:4269
#2 0x00007ffff294de04 in virDomainDefParseXML (xml=0x7da8c0, root=0x7dab80, ctxt=0x7da980, caps=0x7caf10, xmlopt=0x7c82c0, flags=0) at conf/domain_conf.c:16400
#3 0x00007ffff294e5b5 in virDomainDefParseNode (xml=0x7da8c0, root=0x7dab80, caps=0x7caf10, xmlopt=0x7c82c0, flags=0) at conf/domain_conf.c:16582
#4 0x00007ffff294e424 in virDomainDefParse (xmlStr=0x0, filename=0x7c7ef0 "/home/zippy/work/libvirt/libvirt.git/tests/securityselinuxlabeldata/disks.xml", caps=0x7caf10, xmlopt=0x7c82c0, flags=0) at conf/domain_conf.c:16529
#5 0x00007ffff294e4b2 in virDomainDefParseFile (filename=0x7c7ef0 "/home/zippy/work/libvirt/libvirt.git/tests/securityselinuxlabeldata/disks.xml", caps=0x7caf10, xmlopt=0x7c82c0, flags=0) at conf/domain_conf.c:16553
#6 0x00000000004303ca in testSELinuxLoadDef (testname=0x53c929 "disks") at securityselinuxlabeltest.c:192
#7 0x00000000004309e8 in testSELinuxLabeling (opaque=0x53c929) at securityselinuxlabeltest.c:313
#8 0x0000000000431207 in virtTestRun (title=0x53c92f "Labelling \"disks\"", body=0x430964 <testSELinuxLabeling>, data=0x53c929) at testutils.c:211
#9 0x0000000000430c5d in mymain () at securityselinuxlabeltest.c:373
#10 0x00000000004325c2 in virtTestMain (argc=1, argv=0x7fffffffd7e8, func=0x430b4a <mymain>) at testutils.c:863
#11 0x0000000000430deb in main (argc=1, argv=0x7fffffffd7e8) at securityselinuxlabeltest.c:381
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
2015-09-22 14:27:57 +00:00
|
|
|
#define DO_TEST(name) \
|
2016-05-26 15:01:50 +00:00
|
|
|
if (virTestRun(# name, testQemuMonitorJSON ## name, driver.xmlopt) < 0) \
|
2012-08-20 12:31:29 +00:00
|
|
|
ret = -1
|
|
|
|
|
2016-05-26 15:01:50 +00:00
|
|
|
#define DO_TEST_SIMPLE(CMD, FNC, ...) \
|
2013-09-18 15:28:31 +00:00
|
|
|
simpleFunc = (testQemuMonitorJSONSimpleFuncData) {.cmd = CMD, .func = FNC, \
|
tests: Avoid use of virQEMUDriverCreateXMLConf(NULL)
We use the function to create a virDomainXMLOption object that is
required for some functions. However, we don't pass the driver
pointer to the object anywhere - rather than pass NULL. This
causes trouble later when parsing a domain XML and calling post
parse callbacks:
Program received signal SIGSEGV, Segmentation fault.
0x000000000043fa3e in qemuDomainDefPostParse (def=0x7d36c0, caps=0x7caf10, opaque=0x0) at qemu/qemu_domain.c:1043
1043 qemuCaps = virQEMUCapsCacheLookup(driver->qemuCapsCache, def->emulator);
(gdb) bt
#0 0x000000000043fa3e in qemuDomainDefPostParse (def=0x7d36c0, caps=0x7caf10, opaque=0x0) at qemu/qemu_domain.c:1043
#1 0x00007ffff2928bf9 in virDomainDefPostParse (def=0x7d36c0, caps=0x7caf10, xmlopt=0x7c82c0) at conf/domain_conf.c:4269
#2 0x00007ffff294de04 in virDomainDefParseXML (xml=0x7da8c0, root=0x7dab80, ctxt=0x7da980, caps=0x7caf10, xmlopt=0x7c82c0, flags=0) at conf/domain_conf.c:16400
#3 0x00007ffff294e5b5 in virDomainDefParseNode (xml=0x7da8c0, root=0x7dab80, caps=0x7caf10, xmlopt=0x7c82c0, flags=0) at conf/domain_conf.c:16582
#4 0x00007ffff294e424 in virDomainDefParse (xmlStr=0x0, filename=0x7c7ef0 "/home/zippy/work/libvirt/libvirt.git/tests/securityselinuxlabeldata/disks.xml", caps=0x7caf10, xmlopt=0x7c82c0, flags=0) at conf/domain_conf.c:16529
#5 0x00007ffff294e4b2 in virDomainDefParseFile (filename=0x7c7ef0 "/home/zippy/work/libvirt/libvirt.git/tests/securityselinuxlabeldata/disks.xml", caps=0x7caf10, xmlopt=0x7c82c0, flags=0) at conf/domain_conf.c:16553
#6 0x00000000004303ca in testSELinuxLoadDef (testname=0x53c929 "disks") at securityselinuxlabeltest.c:192
#7 0x00000000004309e8 in testSELinuxLabeling (opaque=0x53c929) at securityselinuxlabeltest.c:313
#8 0x0000000000431207 in virtTestRun (title=0x53c92f "Labelling \"disks\"", body=0x430964 <testSELinuxLabeling>, data=0x53c929) at testutils.c:211
#9 0x0000000000430c5d in mymain () at securityselinuxlabeltest.c:373
#10 0x00000000004325c2 in virtTestMain (argc=1, argv=0x7fffffffd7e8, func=0x430b4a <mymain>) at testutils.c:863
#11 0x0000000000430deb in main (argc=1, argv=0x7fffffffd7e8) at securityselinuxlabeltest.c:381
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
2015-09-22 14:27:57 +00:00
|
|
|
.xmlopt = driver.xmlopt, __VA_ARGS__ }; \
|
2016-05-26 15:01:50 +00:00
|
|
|
if (virTestRun(# FNC, testQemuMonitorJSONSimpleFunc, &simpleFunc) < 0) \
|
2013-09-18 15:28:31 +00:00
|
|
|
ret = -1
|
|
|
|
|
2013-10-01 14:23:50 +00:00
|
|
|
#define DO_TEST_GEN(name, ...) \
|
tests: Avoid use of virQEMUDriverCreateXMLConf(NULL)
We use the function to create a virDomainXMLOption object that is
required for some functions. However, we don't pass the driver
pointer to the object anywhere - rather than pass NULL. This
causes trouble later when parsing a domain XML and calling post
parse callbacks:
Program received signal SIGSEGV, Segmentation fault.
0x000000000043fa3e in qemuDomainDefPostParse (def=0x7d36c0, caps=0x7caf10, opaque=0x0) at qemu/qemu_domain.c:1043
1043 qemuCaps = virQEMUCapsCacheLookup(driver->qemuCapsCache, def->emulator);
(gdb) bt
#0 0x000000000043fa3e in qemuDomainDefPostParse (def=0x7d36c0, caps=0x7caf10, opaque=0x0) at qemu/qemu_domain.c:1043
#1 0x00007ffff2928bf9 in virDomainDefPostParse (def=0x7d36c0, caps=0x7caf10, xmlopt=0x7c82c0) at conf/domain_conf.c:4269
#2 0x00007ffff294de04 in virDomainDefParseXML (xml=0x7da8c0, root=0x7dab80, ctxt=0x7da980, caps=0x7caf10, xmlopt=0x7c82c0, flags=0) at conf/domain_conf.c:16400
#3 0x00007ffff294e5b5 in virDomainDefParseNode (xml=0x7da8c0, root=0x7dab80, caps=0x7caf10, xmlopt=0x7c82c0, flags=0) at conf/domain_conf.c:16582
#4 0x00007ffff294e424 in virDomainDefParse (xmlStr=0x0, filename=0x7c7ef0 "/home/zippy/work/libvirt/libvirt.git/tests/securityselinuxlabeldata/disks.xml", caps=0x7caf10, xmlopt=0x7c82c0, flags=0) at conf/domain_conf.c:16529
#5 0x00007ffff294e4b2 in virDomainDefParseFile (filename=0x7c7ef0 "/home/zippy/work/libvirt/libvirt.git/tests/securityselinuxlabeldata/disks.xml", caps=0x7caf10, xmlopt=0x7c82c0, flags=0) at conf/domain_conf.c:16553
#6 0x00000000004303ca in testSELinuxLoadDef (testname=0x53c929 "disks") at securityselinuxlabeltest.c:192
#7 0x00000000004309e8 in testSELinuxLabeling (opaque=0x53c929) at securityselinuxlabeltest.c:313
#8 0x0000000000431207 in virtTestRun (title=0x53c92f "Labelling \"disks\"", body=0x430964 <testSELinuxLabeling>, data=0x53c929) at testutils.c:211
#9 0x0000000000430c5d in mymain () at securityselinuxlabeltest.c:373
#10 0x00000000004325c2 in virtTestMain (argc=1, argv=0x7fffffffd7e8, func=0x430b4a <mymain>) at testutils.c:863
#11 0x0000000000430deb in main (argc=1, argv=0x7fffffffd7e8) at securityselinuxlabeltest.c:381
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
2015-09-22 14:27:57 +00:00
|
|
|
simpleFunc = (testQemuMonitorJSONSimpleFuncData) {.xmlopt = driver.xmlopt, \
|
|
|
|
__VA_ARGS__ }; \
|
2016-05-26 15:01:50 +00:00
|
|
|
if (virTestRun(# name, testQemuMonitorJSON ## name, &simpleFunc) < 0) \
|
2013-10-01 14:23:50 +00:00
|
|
|
ret = -1
|
|
|
|
|
2013-07-22 11:07:23 +00:00
|
|
|
#define DO_TEST_CPU_DATA(name) \
|
|
|
|
do { \
|
tests: Avoid use of virQEMUDriverCreateXMLConf(NULL)
We use the function to create a virDomainXMLOption object that is
required for some functions. However, we don't pass the driver
pointer to the object anywhere - rather than pass NULL. This
causes trouble later when parsing a domain XML and calling post
parse callbacks:
Program received signal SIGSEGV, Segmentation fault.
0x000000000043fa3e in qemuDomainDefPostParse (def=0x7d36c0, caps=0x7caf10, opaque=0x0) at qemu/qemu_domain.c:1043
1043 qemuCaps = virQEMUCapsCacheLookup(driver->qemuCapsCache, def->emulator);
(gdb) bt
#0 0x000000000043fa3e in qemuDomainDefPostParse (def=0x7d36c0, caps=0x7caf10, opaque=0x0) at qemu/qemu_domain.c:1043
#1 0x00007ffff2928bf9 in virDomainDefPostParse (def=0x7d36c0, caps=0x7caf10, xmlopt=0x7c82c0) at conf/domain_conf.c:4269
#2 0x00007ffff294de04 in virDomainDefParseXML (xml=0x7da8c0, root=0x7dab80, ctxt=0x7da980, caps=0x7caf10, xmlopt=0x7c82c0, flags=0) at conf/domain_conf.c:16400
#3 0x00007ffff294e5b5 in virDomainDefParseNode (xml=0x7da8c0, root=0x7dab80, caps=0x7caf10, xmlopt=0x7c82c0, flags=0) at conf/domain_conf.c:16582
#4 0x00007ffff294e424 in virDomainDefParse (xmlStr=0x0, filename=0x7c7ef0 "/home/zippy/work/libvirt/libvirt.git/tests/securityselinuxlabeldata/disks.xml", caps=0x7caf10, xmlopt=0x7c82c0, flags=0) at conf/domain_conf.c:16529
#5 0x00007ffff294e4b2 in virDomainDefParseFile (filename=0x7c7ef0 "/home/zippy/work/libvirt/libvirt.git/tests/securityselinuxlabeldata/disks.xml", caps=0x7caf10, xmlopt=0x7c82c0, flags=0) at conf/domain_conf.c:16553
#6 0x00000000004303ca in testSELinuxLoadDef (testname=0x53c929 "disks") at securityselinuxlabeltest.c:192
#7 0x00000000004309e8 in testSELinuxLabeling (opaque=0x53c929) at securityselinuxlabeltest.c:313
#8 0x0000000000431207 in virtTestRun (title=0x53c92f "Labelling \"disks\"", body=0x430964 <testSELinuxLabeling>, data=0x53c929) at testutils.c:211
#9 0x0000000000430c5d in mymain () at securityselinuxlabeltest.c:373
#10 0x00000000004325c2 in virtTestMain (argc=1, argv=0x7fffffffd7e8, func=0x430b4a <mymain>) at testutils.c:863
#11 0x0000000000430deb in main (argc=1, argv=0x7fffffffd7e8) at securityselinuxlabeltest.c:381
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
2015-09-22 14:27:57 +00:00
|
|
|
struct testCPUData data = { name, driver.xmlopt }; \
|
2013-07-22 11:07:23 +00:00
|
|
|
const char *label = "GetCPUData(" name ")"; \
|
2016-05-26 15:01:50 +00:00
|
|
|
if (virTestRun(label, testQemuMonitorJSONGetCPUData, &data) < 0) \
|
2013-07-22 11:07:23 +00:00
|
|
|
ret = -1; \
|
|
|
|
} while (0)
|
|
|
|
|
2016-07-29 16:08:06 +00:00
|
|
|
#define DO_TEST_CPU_INFO(name, maxvcpus) \
|
|
|
|
do { \
|
|
|
|
struct testCPUInfoData data = {name, maxvcpus, driver.xmlopt}; \
|
|
|
|
if (virTestRun("GetCPUInfo(" name ")", testQemuMonitorCPUInfo, \
|
|
|
|
&data) < 0) \
|
|
|
|
ret = -1; \
|
|
|
|
} while (0)
|
|
|
|
|
2012-08-20 12:31:29 +00:00
|
|
|
DO_TEST(GetStatus);
|
2012-08-15 14:04:09 +00:00
|
|
|
DO_TEST(GetVersion);
|
2012-08-15 15:18:41 +00:00
|
|
|
DO_TEST(GetMachines);
|
2012-08-20 14:58:20 +00:00
|
|
|
DO_TEST(GetCPUDefinitions);
|
2012-08-22 09:25:20 +00:00
|
|
|
DO_TEST(GetCommands);
|
2013-04-26 11:13:05 +00:00
|
|
|
DO_TEST(GetTPMModels);
|
2013-04-26 17:13:45 +00:00
|
|
|
DO_TEST(GetCommandLineOptionParameters);
|
2016-09-27 13:49:05 +00:00
|
|
|
if (qemuMonitorJSONTestAttachChardev(driver.xmlopt) < 0)
|
|
|
|
ret = -1;
|
2013-03-12 18:57:48 +00:00
|
|
|
DO_TEST(DetachChardev);
|
2013-06-24 17:51:56 +00:00
|
|
|
DO_TEST(GetListPaths);
|
2013-07-03 18:15:07 +00:00
|
|
|
DO_TEST(GetObjectProperty);
|
2013-07-03 18:42:40 +00:00
|
|
|
DO_TEST(SetObjectProperty);
|
2013-07-19 13:01:38 +00:00
|
|
|
DO_TEST(GetDeviceAliases);
|
2013-09-18 13:11:06 +00:00
|
|
|
DO_TEST(CPU);
|
2013-11-19 15:30:28 +00:00
|
|
|
DO_TEST(GetNonExistingCPUData);
|
2014-08-29 20:23:11 +00:00
|
|
|
DO_TEST(GetIOThreads);
|
2013-09-18 15:28:31 +00:00
|
|
|
DO_TEST_SIMPLE("qmp_capabilities", qemuMonitorJSONSetCapabilities);
|
2013-10-01 14:28:51 +00:00
|
|
|
DO_TEST_SIMPLE("system_powerdown", qemuMonitorJSONSystemPowerdown);
|
2013-09-18 15:28:31 +00:00
|
|
|
DO_TEST_SIMPLE("system_reset", qemuMonitorJSONSystemReset);
|
|
|
|
DO_TEST_SIMPLE("migrate_cancel", qemuMonitorJSONMigrateCancel);
|
|
|
|
DO_TEST_SIMPLE("inject-nmi", qemuMonitorJSONInjectNMI);
|
|
|
|
DO_TEST_SIMPLE("system_wakeup", qemuMonitorJSONSystemWakeup);
|
|
|
|
DO_TEST_SIMPLE("nbd-server-stop", qemuMonitorJSONNBDServerStop);
|
2014-08-13 12:28:24 +00:00
|
|
|
DO_TEST_SIMPLE("rtc-reset-reinjection", qemuMonitorJSONRTCResetReinjection);
|
2013-10-01 14:23:50 +00:00
|
|
|
DO_TEST_GEN(qemuMonitorJSONSetLink);
|
|
|
|
DO_TEST_GEN(qemuMonitorJSONBlockResize);
|
|
|
|
DO_TEST_GEN(qemuMonitorJSONSetVNCPassword);
|
|
|
|
DO_TEST_GEN(qemuMonitorJSONSetPassword);
|
|
|
|
DO_TEST_GEN(qemuMonitorJSONExpirePassword);
|
|
|
|
DO_TEST_GEN(qemuMonitorJSONSetBalloon);
|
|
|
|
DO_TEST_GEN(qemuMonitorJSONSetCPU);
|
|
|
|
DO_TEST_GEN(qemuMonitorJSONEjectMedia);
|
|
|
|
DO_TEST_GEN(qemuMonitorJSONChangeMedia);
|
|
|
|
DO_TEST_GEN(qemuMonitorJSONSaveVirtualMemory);
|
|
|
|
DO_TEST_GEN(qemuMonitorJSONSavePhysicalMemory);
|
|
|
|
DO_TEST_GEN(qemuMonitorJSONSetMigrationSpeed);
|
|
|
|
DO_TEST_GEN(qemuMonitorJSONSetMigrationDowntime);
|
|
|
|
DO_TEST_GEN(qemuMonitorJSONMigrate);
|
|
|
|
DO_TEST_GEN(qemuMonitorJSONDump);
|
|
|
|
DO_TEST_GEN(qemuMonitorJSONGraphicsRelocate);
|
|
|
|
DO_TEST_GEN(qemuMonitorJSONAddNetdev);
|
|
|
|
DO_TEST_GEN(qemuMonitorJSONRemoveNetdev);
|
|
|
|
DO_TEST_GEN(qemuMonitorJSONDelDevice);
|
|
|
|
DO_TEST_GEN(qemuMonitorJSONAddDevice);
|
|
|
|
DO_TEST_GEN(qemuMonitorJSONSetDrivePassphrase);
|
|
|
|
DO_TEST_GEN(qemuMonitorJSONDriveMirror);
|
|
|
|
DO_TEST_GEN(qemuMonitorJSONBlockCommit);
|
|
|
|
DO_TEST_GEN(qemuMonitorJSONDrivePivot);
|
|
|
|
DO_TEST_GEN(qemuMonitorJSONScreendump);
|
|
|
|
DO_TEST_GEN(qemuMonitorJSONOpenGraphics);
|
|
|
|
DO_TEST_GEN(qemuMonitorJSONNBDServerStart);
|
|
|
|
DO_TEST_GEN(qemuMonitorJSONNBDServerAdd);
|
|
|
|
DO_TEST_GEN(qemuMonitorJSONDetachCharDev);
|
2013-10-02 10:02:53 +00:00
|
|
|
DO_TEST(qemuMonitorJSONGetBalloonInfo);
|
2013-10-02 12:39:10 +00:00
|
|
|
DO_TEST(qemuMonitorJSONGetBlockInfo);
|
2013-10-02 13:08:02 +00:00
|
|
|
DO_TEST(qemuMonitorJSONGetBlockStatsInfo);
|
2013-10-02 14:01:46 +00:00
|
|
|
DO_TEST(qemuMonitorJSONGetMigrationCacheSize);
|
2016-06-20 13:47:46 +00:00
|
|
|
DO_TEST(qemuMonitorJSONGetMigrationParams);
|
2015-11-26 12:23:08 +00:00
|
|
|
DO_TEST(qemuMonitorJSONGetMigrationStats);
|
2014-11-13 15:17:21 +00:00
|
|
|
DO_TEST(qemuMonitorJSONGetChardevInfo);
|
2013-10-02 16:46:42 +00:00
|
|
|
DO_TEST(qemuMonitorJSONSetBlockIoThrottle);
|
2013-10-02 16:55:42 +00:00
|
|
|
DO_TEST(qemuMonitorJSONGetTargetArch);
|
2013-10-02 17:03:53 +00:00
|
|
|
DO_TEST(qemuMonitorJSONGetMigrationCapability);
|
2016-07-08 13:36:27 +00:00
|
|
|
DO_TEST(qemuMonitorJSONQueryCPUs);
|
2013-10-02 09:56:43 +00:00
|
|
|
DO_TEST(qemuMonitorJSONGetVirtType);
|
2013-10-02 16:23:17 +00:00
|
|
|
DO_TEST(qemuMonitorJSONSendKey);
|
2014-03-23 03:51:13 +00:00
|
|
|
DO_TEST(qemuMonitorJSONGetDumpGuestMemoryCapability);
|
2014-06-03 09:19:51 +00:00
|
|
|
DO_TEST(qemuMonitorJSONSendKeyHoldtime);
|
blockjob: allow omitted arguments to QMP block-commit
We are about to turn on support for active block commit. Although
qemu 2.0 was the first version to mostly support it, that version
mis-handles 0-length files, and doesn't have anything available for
easy probing. But qemu 2.1 fixed bugs, and made life simpler by
letting the 'top' argument be optional. Unless someone begs for
active commit with qemu 2.0, for now we are just going to enable
it only by probing for qemu 2.1 behavior (anyone backporting active
commit can also backport the optional argument behavior). This
requires qemu.git commit 7676e2c597000eff3a7233b40cca768b358f9bc9.
Although all our actual uses of block-commit supply arguments for
both base and top, we can omit both arguments and use a bogus
device string to trigger an interesting behavior in qemu. All QMP
commands first do argument validation, failing with GenericError
if a mandatory argument is missing. Once that passes, the code
in the specific command gets to do further checking, and the qemu
developers made sure that if device is the only supplied argument,
then the block-commit code will look up the device first, with a
failure of DeviceNotFound, before attempting any further argument
validation (most other validations fail with GenericError). Thus,
the category of error class can reliably be used to decipher
whether the top argument was optional, which in turn implies a
working active commit. Since we expect our bogus device string to
trigger an error either way, the code is written to return a
distinct return value without spamming the logs.
* src/qemu/qemu_monitor.h (qemuMonitorSupportsActiveCommit): New
prototype.
* src/qemu/qemu_monitor.c (qemuMonitorSupportsActiveCommit):
Implement it.
* src/qemu/qemu_monitor_json.h (qemuMonitorJSONBlockCommit):
Allow NULL for top and base, for probing purposes.
* src/qemu/qemu_monitor_json.c (qemuMonitorJSONBlockCommit):
Likewise, implementing the probe.
* tests/qemumonitorjsontest.c (mymain): Enable...
(testQemuMonitorJSONqemuMonitorSupportsActiveCommit): ...a new test.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-06-17 03:42:49 +00:00
|
|
|
DO_TEST(qemuMonitorSupportsActiveCommit);
|
2012-08-20 12:31:29 +00:00
|
|
|
|
2013-07-22 11:07:23 +00:00
|
|
|
DO_TEST_CPU_DATA("host");
|
|
|
|
DO_TEST_CPU_DATA("full");
|
2016-05-20 09:17:11 +00:00
|
|
|
DO_TEST_CPU_DATA("ecx");
|
2013-07-22 11:07:23 +00:00
|
|
|
|
2016-07-29 16:08:06 +00:00
|
|
|
DO_TEST_CPU_INFO("x86-basic-pluggable", 8);
|
2016-08-23 21:05:52 +00:00
|
|
|
DO_TEST_CPU_INFO("x86-full", 11);
|
2016-07-29 16:08:06 +00:00
|
|
|
|
2016-07-29 17:24:22 +00:00
|
|
|
DO_TEST_CPU_INFO("ppc64-basic", 24);
|
|
|
|
DO_TEST_CPU_INFO("ppc64-hotplug-1", 24);
|
|
|
|
DO_TEST_CPU_INFO("ppc64-hotplug-2", 24);
|
2016-07-29 17:44:43 +00:00
|
|
|
DO_TEST_CPU_INFO("ppc64-hotplug-4", 24);
|
2016-07-29 17:55:29 +00:00
|
|
|
DO_TEST_CPU_INFO("ppc64-no-threads", 16);
|
2016-07-29 17:24:22 +00:00
|
|
|
|
tests: Avoid use of virQEMUDriverCreateXMLConf(NULL)
We use the function to create a virDomainXMLOption object that is
required for some functions. However, we don't pass the driver
pointer to the object anywhere - rather than pass NULL. This
causes trouble later when parsing a domain XML and calling post
parse callbacks:
Program received signal SIGSEGV, Segmentation fault.
0x000000000043fa3e in qemuDomainDefPostParse (def=0x7d36c0, caps=0x7caf10, opaque=0x0) at qemu/qemu_domain.c:1043
1043 qemuCaps = virQEMUCapsCacheLookup(driver->qemuCapsCache, def->emulator);
(gdb) bt
#0 0x000000000043fa3e in qemuDomainDefPostParse (def=0x7d36c0, caps=0x7caf10, opaque=0x0) at qemu/qemu_domain.c:1043
#1 0x00007ffff2928bf9 in virDomainDefPostParse (def=0x7d36c0, caps=0x7caf10, xmlopt=0x7c82c0) at conf/domain_conf.c:4269
#2 0x00007ffff294de04 in virDomainDefParseXML (xml=0x7da8c0, root=0x7dab80, ctxt=0x7da980, caps=0x7caf10, xmlopt=0x7c82c0, flags=0) at conf/domain_conf.c:16400
#3 0x00007ffff294e5b5 in virDomainDefParseNode (xml=0x7da8c0, root=0x7dab80, caps=0x7caf10, xmlopt=0x7c82c0, flags=0) at conf/domain_conf.c:16582
#4 0x00007ffff294e424 in virDomainDefParse (xmlStr=0x0, filename=0x7c7ef0 "/home/zippy/work/libvirt/libvirt.git/tests/securityselinuxlabeldata/disks.xml", caps=0x7caf10, xmlopt=0x7c82c0, flags=0) at conf/domain_conf.c:16529
#5 0x00007ffff294e4b2 in virDomainDefParseFile (filename=0x7c7ef0 "/home/zippy/work/libvirt/libvirt.git/tests/securityselinuxlabeldata/disks.xml", caps=0x7caf10, xmlopt=0x7c82c0, flags=0) at conf/domain_conf.c:16553
#6 0x00000000004303ca in testSELinuxLoadDef (testname=0x53c929 "disks") at securityselinuxlabeltest.c:192
#7 0x00000000004309e8 in testSELinuxLabeling (opaque=0x53c929) at securityselinuxlabeltest.c:313
#8 0x0000000000431207 in virtTestRun (title=0x53c92f "Labelling \"disks\"", body=0x430964 <testSELinuxLabeling>, data=0x53c929) at testutils.c:211
#9 0x0000000000430c5d in mymain () at securityselinuxlabeltest.c:373
#10 0x00000000004325c2 in virtTestMain (argc=1, argv=0x7fffffffd7e8, func=0x430b4a <mymain>) at testutils.c:863
#11 0x0000000000430deb in main (argc=1, argv=0x7fffffffd7e8) at securityselinuxlabeltest.c:381
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
2015-09-22 14:27:57 +00:00
|
|
|
qemuTestDriverFree(&driver);
|
2012-08-20 12:31:29 +00:00
|
|
|
|
|
|
|
return (ret == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
VIRT_TEST_MAIN(mymain)
|