|
@@ -37,10 +37,12 @@
|
|
|
#include "qapi/qapi-commands-block.h"
|
|
|
#include "qapi/qmp/qdict.h"
|
|
|
#include "qapi/error.h"
|
|
|
+#include "qapi/qmp/qerror.h"
|
|
|
#include "qemu/config-file.h"
|
|
|
#include "qemu/option.h"
|
|
|
#include "sysemu/sysemu.h"
|
|
|
#include "monitor/monitor.h"
|
|
|
+#include "monitor/hmp.h"
|
|
|
#include "block/block_int.h"
|
|
|
#include "block/block-hmp-cmds.h"
|
|
|
|
|
@@ -187,3 +189,61 @@ void hmp_commit(Monitor *mon, const QDict *qdict)
|
|
|
error_report("'commit' error for '%s': %s", device, strerror(-ret));
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+void hmp_drive_mirror(Monitor *mon, const QDict *qdict)
|
|
|
+{
|
|
|
+ const char *filename = qdict_get_str(qdict, "target");
|
|
|
+ const char *format = qdict_get_try_str(qdict, "format");
|
|
|
+ bool reuse = qdict_get_try_bool(qdict, "reuse", false);
|
|
|
+ bool full = qdict_get_try_bool(qdict, "full", false);
|
|
|
+ Error *err = NULL;
|
|
|
+ DriveMirror mirror = {
|
|
|
+ .device = (char *)qdict_get_str(qdict, "device"),
|
|
|
+ .target = (char *)filename,
|
|
|
+ .has_format = !!format,
|
|
|
+ .format = (char *)format,
|
|
|
+ .sync = full ? MIRROR_SYNC_MODE_FULL : MIRROR_SYNC_MODE_TOP,
|
|
|
+ .has_mode = true,
|
|
|
+ .mode = reuse ? NEW_IMAGE_MODE_EXISTING : NEW_IMAGE_MODE_ABSOLUTE_PATHS,
|
|
|
+ .unmap = true,
|
|
|
+ };
|
|
|
+
|
|
|
+ if (!filename) {
|
|
|
+ error_setg(&err, QERR_MISSING_PARAMETER, "target");
|
|
|
+ hmp_handle_error(mon, err);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ qmp_drive_mirror(&mirror, &err);
|
|
|
+ hmp_handle_error(mon, err);
|
|
|
+}
|
|
|
+
|
|
|
+void hmp_drive_backup(Monitor *mon, const QDict *qdict)
|
|
|
+{
|
|
|
+ const char *device = qdict_get_str(qdict, "device");
|
|
|
+ const char *filename = qdict_get_str(qdict, "target");
|
|
|
+ const char *format = qdict_get_try_str(qdict, "format");
|
|
|
+ bool reuse = qdict_get_try_bool(qdict, "reuse", false);
|
|
|
+ bool full = qdict_get_try_bool(qdict, "full", false);
|
|
|
+ bool compress = qdict_get_try_bool(qdict, "compress", false);
|
|
|
+ Error *err = NULL;
|
|
|
+ DriveBackup backup = {
|
|
|
+ .device = (char *)device,
|
|
|
+ .target = (char *)filename,
|
|
|
+ .has_format = !!format,
|
|
|
+ .format = (char *)format,
|
|
|
+ .sync = full ? MIRROR_SYNC_MODE_FULL : MIRROR_SYNC_MODE_TOP,
|
|
|
+ .has_mode = true,
|
|
|
+ .mode = reuse ? NEW_IMAGE_MODE_EXISTING : NEW_IMAGE_MODE_ABSOLUTE_PATHS,
|
|
|
+ .has_compress = !!compress,
|
|
|
+ .compress = compress,
|
|
|
+ };
|
|
|
+
|
|
|
+ if (!filename) {
|
|
|
+ error_setg(&err, QERR_MISSING_PARAMETER, "target");
|
|
|
+ hmp_handle_error(mon, err);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ qmp_drive_backup(&backup, &err);
|
|
|
+ hmp_handle_error(mon, err);
|
|
|
+}
|