backup: Add new qemu monitor bitmap

The upcoming virDomainBackup() API needs to take advantage of various
qcow2 bitmap manipulations as the basis to virDomainCheckpoints and
incremental backups.  Add four functions to expose
block-dirty-bitmap-{add,enable,disable,merge} (this is the
recently-added QEMU_CAPS_BITMAP_MERGE capability).

Signed-off-by: Eric Blake <eblake@redhat.com>
Acked-by: Peter Krempa <pkrempa@redhat.com>
This commit is contained in:
Eric Blake 2019-06-05 21:25:05 -05:00
parent 6abda7a445
commit ad1c17c8d5
5 changed files with 247 additions and 0 deletions

View File

@ -4488,3 +4488,54 @@ qemuMonitorGetCurrentMachineInfo(qemuMonitorPtr mon,
return qemuMonitorJSONGetCurrentMachineInfo(mon, info);
}
int
qemuMonitorAddBitmap(qemuMonitorPtr mon,
const char *node,
const char *bitmap,
bool persistent)
{
VIR_DEBUG("node=%s bitmap=%s persistent=%d", node, bitmap, persistent);
QEMU_CHECK_MONITOR(mon);
return qemuMonitorJSONAddBitmap(mon, node, bitmap, persistent);
}
int
qemuMonitorEnableBitmap(qemuMonitorPtr mon,
const char *node,
const char *bitmap)
{
VIR_DEBUG("node=%s bitmap=%s", node, bitmap);
QEMU_CHECK_MONITOR(mon);
return qemuMonitorJSONEnableBitmap(mon, node, bitmap);
}
int
qemuMonitorMergeBitmaps(qemuMonitorPtr mon,
const char *node,
const char *dst,
virJSONValuePtr *src)
{
VIR_DEBUG("node=%s dst=%s", node, dst);
QEMU_CHECK_MONITOR(mon);
return qemuMonitorJSONMergeBitmaps(mon, node, dst, src);
}
int
qemuMonitorDeleteBitmap(qemuMonitorPtr mon,
const char *node,
const char *bitmap)
{
VIR_DEBUG("node=%s bitmap=%s", node, bitmap);
QEMU_CHECK_MONITOR(mon);
return qemuMonitorJSONDeleteBitmap(mon, node, bitmap);
}

View File

@ -646,6 +646,25 @@ int qemuMonitorSetBalloon(qemuMonitorPtr mon,
unsigned long long newmem);
int qemuMonitorSetCPU(qemuMonitorPtr mon, int cpu, bool online);
int qemuMonitorAddBitmap(qemuMonitorPtr mon,
const char *node,
const char *bitmap,
bool persistent)
ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
int qemuMonitorEnableBitmap(qemuMonitorPtr mon,
const char *node,
const char *bitmap)
ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
int qemuMonitorMergeBitmaps(qemuMonitorPtr mon,
const char *node,
const char *dst,
virJSONValuePtr *src)
ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4);
int qemuMonitorDeleteBitmap(qemuMonitorPtr mon,
const char *node,
const char *bitmap)
ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
/* XXX should we pass the virDomainDiskDefPtr instead
* and hide dev_name details inside monitor. Reconsider

View File

@ -8510,3 +8510,122 @@ qemuMonitorJSONGetCurrentMachineInfo(qemuMonitorPtr mon,
virJSONValueFree(reply);
return ret;
}
int
qemuMonitorJSONAddBitmap(qemuMonitorPtr mon,
const char *node,
const char *bitmap,
bool persistent)
{
int ret = -1;
virJSONValuePtr cmd;
virJSONValuePtr reply = NULL;
if (!(cmd = qemuMonitorJSONMakeCommand("block-dirty-bitmap-add",
"s:node", node,
"s:name", bitmap,
"b:persistent", persistent,
NULL)))
return -1;
if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
goto cleanup;
if (qemuMonitorJSONCheckError(cmd, reply) < 0)
goto cleanup;
ret = 0;
cleanup:
virJSONValueFree(cmd);
virJSONValueFree(reply);
return ret;
}
int
qemuMonitorJSONEnableBitmap(qemuMonitorPtr mon,
const char *node,
const char *bitmap)
{
int ret = -1;
virJSONValuePtr cmd;
virJSONValuePtr reply = NULL;
if (!(cmd = qemuMonitorJSONMakeCommand("block-dirty-bitmap-enable",
"s:node", node,
"s:name", bitmap,
NULL)))
return -1;
if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
goto cleanup;
if (qemuMonitorJSONCheckError(cmd, reply) < 0)
goto cleanup;
ret = 0;
cleanup:
virJSONValueFree(cmd);
virJSONValueFree(reply);
return ret;
}
int
qemuMonitorJSONMergeBitmaps(qemuMonitorPtr mon,
const char *node,
const char *dst,
virJSONValuePtr *src)
{
int ret = -1;
virJSONValuePtr cmd;
virJSONValuePtr reply = NULL;
if (!(cmd = qemuMonitorJSONMakeCommand("block-dirty-bitmap-merge",
"s:node", node,
"s:target", dst,
"a:bitmaps", src,
NULL)))
goto cleanup;
if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
goto cleanup;
if (qemuMonitorJSONCheckError(cmd, reply) < 0)
goto cleanup;
ret = 0;
cleanup:
virJSONValueFree(*src);
*src = NULL;
virJSONValueFree(cmd);
virJSONValueFree(reply);
return ret;
}
int
qemuMonitorJSONDeleteBitmap(qemuMonitorPtr mon,
const char *node,
const char *bitmap)
{
int ret = -1;
virJSONValuePtr cmd;
virJSONValuePtr reply = NULL;
if (!(cmd = qemuMonitorJSONMakeCommand("block-dirty-bitmap-remove",
"s:node", node,
"s:name", bitmap,
NULL)))
return -1;
if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
goto cleanup;
if (qemuMonitorJSONCheckError(cmd, reply) < 0)
goto cleanup;
ret = 0;
cleanup:
virJSONValueFree(cmd);
virJSONValueFree(reply);
return ret;
}

View File

@ -580,5 +580,22 @@ int
qemuMonitorJSONGetCurrentMachineInfo(qemuMonitorPtr mon,
qemuMonitorCurrentMachineInfoPtr info)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
int qemuMonitorJSONAddBitmap(qemuMonitorPtr mon,
const char *node,
const char *bitmap,
bool persistent);
int qemuMonitorJSONEnableBitmap(qemuMonitorPtr mon,
const char *node,
const char *bitmap);
int qemuMonitorJSONMergeBitmaps(qemuMonitorPtr mon,
const char *node,
const char *dst,
virJSONValuePtr *src);
int qemuMonitorJSONDeleteBitmap(qemuMonitorPtr mon,
const char *node,
const char *bitmap);
#endif /* LIBVIRT_QEMU_MONITOR_JSON_H */

View File

@ -1337,6 +1337,9 @@ GEN_TEST_FUNC(qemuMonitorJSONBlockdevTrayOpen, "foodev", true)
GEN_TEST_FUNC(qemuMonitorJSONBlockdevTrayClose, "foodev")
GEN_TEST_FUNC(qemuMonitorJSONBlockdevMediumRemove, "foodev")
GEN_TEST_FUNC(qemuMonitorJSONBlockdevMediumInsert, "foodev", "newnode")
GEN_TEST_FUNC(qemuMonitorJSONAddBitmap, "node", "bitmap", true)
GEN_TEST_FUNC(qemuMonitorJSONEnableBitmap, "node", "bitmap")
GEN_TEST_FUNC(qemuMonitorJSONDeleteBitmap, "node", "bitmap")
static int
testQemuMonitorJSONqemuMonitorJSONNBDServerStart(const void *opaque)
@ -1376,6 +1379,40 @@ testQemuMonitorJSONqemuMonitorJSONNBDServerStart(const void *opaque)
return 0;
}
static int
testQemuMonitorJSONqemuMonitorJSONMergeBitmaps(const void *opaque)
{
const testGenericData *data = opaque;
virDomainXMLOptionPtr xmlopt = data->xmlopt;
VIR_AUTOPTR(qemuMonitorTest) test = NULL;
VIR_AUTOPTR(virJSONValue) arr = NULL;
if (!(test = qemuMonitorTestNewSchema(xmlopt, data->schema)))
return -1;
if (!(arr = virJSONValueNewArray()))
return -1;
if (virJSONValueArrayAppendString(arr, "b1") < 0 ||
virJSONValueArrayAppendString(arr, "b2") < 0)
return -1;
if (qemuMonitorTestAddItem(test, "block-dirty-bitmap-merge",
"{\"return\":{}}") < 0)
return -1;
if (qemuMonitorJSONMergeBitmaps(qemuMonitorTestGetMonitor(test),
"node", "dst", &arr) < 0)
return -1;
if (arr) {
virReportError(VIR_ERR_INTERNAL_ERROR, "arr should have been cleared");
return -1;
}
return 0;
}
static bool
testQemuMonitorJSONqemuMonitorJSONQueryCPUsEqual(struct qemuMonitorQueryCpusEntry *a,
struct qemuMonitorQueryCpusEntry *b)
@ -3019,6 +3056,9 @@ mymain(void)
DO_TEST_GEN(qemuMonitorJSONBlockdevTrayClose);
DO_TEST_GEN(qemuMonitorJSONBlockdevMediumRemove);
DO_TEST_GEN(qemuMonitorJSONBlockdevMediumInsert);
DO_TEST_GEN(qemuMonitorJSONAddBitmap);
DO_TEST_GEN(qemuMonitorJSONEnableBitmap);
DO_TEST_GEN(qemuMonitorJSONDeleteBitmap);
DO_TEST(qemuMonitorJSONGetBalloonInfo);
DO_TEST(qemuMonitorJSONGetBlockInfo);
DO_TEST(qemuMonitorJSONGetAllBlockStatsInfo);
@ -3035,6 +3075,7 @@ mymain(void)
DO_TEST(qemuMonitorJSONSendKeyHoldtime);
DO_TEST(qemuMonitorSupportsActiveCommit);
DO_TEST(qemuMonitorJSONNBDServerStart);
DO_TEST(qemuMonitorJSONMergeBitmaps);
DO_TEST_CPU_DATA("host");
DO_TEST_CPU_DATA("full");