mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-24 05:25:18 +00:00
save: add virsh commands for manipulating save files
Now you can edit a saved state file even if you forgot to grab a dumpxml file prior to saving a domain. Plus, in-place editing feels so much nicer. * tools/virsh.c (cmdSaveImageDumpxml, cmdSaveImageDefine) (cmdSaveImageEdit): New commands. * tools/virsh.pod (save-image-dumpxml, save-image-define) (save-image-edit): Document them.
This commit is contained in:
parent
0696becacf
commit
bfb485ced2
178
tools/virsh.c
178
tools/virsh.c
@ -1659,6 +1659,178 @@ cleanup:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* "save-image-dumpxml" command
|
||||||
|
*/
|
||||||
|
static const vshCmdInfo info_save_image_dumpxml[] = {
|
||||||
|
{"help", N_("saved state domain information in XML")},
|
||||||
|
{"desc", N_("Output the domain information for a saved state file,\n"
|
||||||
|
"as an XML dump to stdout.")},
|
||||||
|
{NULL, NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
static const vshCmdOptDef opts_save_image_dumpxml[] = {
|
||||||
|
{"file", VSH_OT_DATA, VSH_OFLAG_REQ, N_("saved state file to read")},
|
||||||
|
{"security-info", VSH_OT_BOOL, 0, N_("include security sensitive information in XML dump")},
|
||||||
|
{NULL, 0, 0, NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool
|
||||||
|
cmdSaveImageDumpxml(vshControl *ctl, const vshCmd *cmd)
|
||||||
|
{
|
||||||
|
const char *file = NULL;
|
||||||
|
bool ret = false;
|
||||||
|
int flags = 0;
|
||||||
|
char *xml = NULL;
|
||||||
|
|
||||||
|
if (vshCommandOptBool(cmd, "security-info"))
|
||||||
|
flags |= VIR_DOMAIN_XML_SECURE;
|
||||||
|
|
||||||
|
if (!vshConnectionUsability(ctl, ctl->conn))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (vshCommandOptString(cmd, "file", &file) <= 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
xml = virDomainSaveImageGetXMLDesc(ctl->conn, file, flags);
|
||||||
|
if (!xml)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
vshPrint(ctl, "%s", xml);
|
||||||
|
ret = true;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
VIR_FREE(xml);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* "save-image-define" command
|
||||||
|
*/
|
||||||
|
static const vshCmdInfo info_save_image_define[] = {
|
||||||
|
{"help", N_("redefine the XML for a domain's saved state file")},
|
||||||
|
{"desc", N_("Replace the domain XML associated with a saved state file")},
|
||||||
|
{NULL, NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
static const vshCmdOptDef opts_save_image_define[] = {
|
||||||
|
{"file", VSH_OT_DATA, VSH_OFLAG_REQ, N_("saved state file to modify")},
|
||||||
|
{"xml", VSH_OT_STRING, VSH_OFLAG_REQ,
|
||||||
|
N_("filename containing updated XML for the target")},
|
||||||
|
{NULL, 0, 0, NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool
|
||||||
|
cmdSaveImageDefine(vshControl *ctl, const vshCmd *cmd)
|
||||||
|
{
|
||||||
|
const char *file = NULL;
|
||||||
|
bool ret = false;
|
||||||
|
const char *xmlfile = NULL;
|
||||||
|
char *xml = NULL;
|
||||||
|
|
||||||
|
if (!vshConnectionUsability(ctl, ctl->conn))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (vshCommandOptString(cmd, "file", &file) <= 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (vshCommandOptString(cmd, "xml", &xmlfile) <= 0) {
|
||||||
|
vshError(ctl, "%s", _("malformed or missing xml argument"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virFileReadAll(xmlfile, 8192, &xml) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (virDomainSaveImageDefineXML(ctl->conn, file, xml, 0) < 0) {
|
||||||
|
vshError(ctl, _("Failed to update %s"), file);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
vshPrint(ctl, _("State file %s updated.\n"), file);
|
||||||
|
ret = true;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
VIR_FREE(xml);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* "save-image-edit" command
|
||||||
|
*/
|
||||||
|
static const vshCmdInfo info_save_image_edit[] = {
|
||||||
|
{"help", N_("edit XML for a domain's saved state file")},
|
||||||
|
{"desc", N_("Edit the domain XML associated with a saved state file")},
|
||||||
|
{NULL, NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
static const vshCmdOptDef opts_save_image_edit[] = {
|
||||||
|
{"file", VSH_OT_DATA, VSH_OFLAG_REQ, N_("saved state file to edit")},
|
||||||
|
{NULL, 0, 0, NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool
|
||||||
|
cmdSaveImageEdit(vshControl *ctl, const vshCmd *cmd)
|
||||||
|
{
|
||||||
|
const char *file = NULL;
|
||||||
|
bool ret = false;
|
||||||
|
char *tmp = NULL;
|
||||||
|
char *doc = NULL;
|
||||||
|
char *doc_edited = NULL;
|
||||||
|
int flags = VIR_DOMAIN_XML_SECURE;
|
||||||
|
|
||||||
|
if (!vshConnectionUsability(ctl, ctl->conn))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (vshCommandOptString(cmd, "file", &file) <= 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* Get the XML configuration of the saved image. */
|
||||||
|
doc = virDomainSaveImageGetXMLDesc(ctl->conn, file, flags);
|
||||||
|
if (!doc)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
/* Create and open the temporary file. */
|
||||||
|
tmp = editWriteToTempFile(ctl, doc);
|
||||||
|
if (!tmp)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
/* Start the editor. */
|
||||||
|
if (editFile(ctl, tmp) == -1)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
/* Read back the edited file. */
|
||||||
|
doc_edited = editReadBackFile(ctl, tmp);
|
||||||
|
if (!doc_edited)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
/* Compare original XML with edited. Has it changed at all? */
|
||||||
|
if (STREQ(doc, doc_edited)) {
|
||||||
|
vshPrint(ctl, _("Saved image %s XML configuration not changed.\n"),
|
||||||
|
file);
|
||||||
|
ret = true;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Everything checks out, so redefine the xml. */
|
||||||
|
if (virDomainSaveImageDefineXML(ctl->conn, file, doc_edited, 0) < 0) {
|
||||||
|
vshError(ctl, _("Failed to update %s"), file);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
vshPrint(ctl, _("State file %s edited.\n"), file);
|
||||||
|
ret = true;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
VIR_FREE(doc);
|
||||||
|
VIR_FREE(doc_edited);
|
||||||
|
if (tmp) {
|
||||||
|
unlink(tmp);
|
||||||
|
VIR_FREE(tmp);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* "managedsave" command
|
* "managedsave" command
|
||||||
*/
|
*/
|
||||||
@ -12178,6 +12350,12 @@ static const vshCmdDef domManagementCmds[] = {
|
|||||||
{"restore", cmdRestore, opts_restore, info_restore, 0},
|
{"restore", cmdRestore, opts_restore, info_restore, 0},
|
||||||
{"resume", cmdResume, opts_resume, info_resume, 0},
|
{"resume", cmdResume, opts_resume, info_resume, 0},
|
||||||
{"save", cmdSave, opts_save, info_save, 0},
|
{"save", cmdSave, opts_save, info_save, 0},
|
||||||
|
{"save-image-define", cmdSaveImageDefine, opts_save_image_define,
|
||||||
|
info_save_image_define, 0},
|
||||||
|
{"save-image-dumpxml", cmdSaveImageDumpxml, opts_save_image_dumpxml,
|
||||||
|
info_save_image_dumpxml, 0},
|
||||||
|
{"save-image-edit", cmdSaveImageEdit, opts_save_image_edit,
|
||||||
|
info_save_image_edit, 0},
|
||||||
{"schedinfo", cmdSchedinfo, opts_schedinfo, info_schedinfo, 0},
|
{"schedinfo", cmdSchedinfo, opts_schedinfo, info_schedinfo, 0},
|
||||||
{"screenshot", cmdScreenshot, opts_screenshot, info_screenshot, 0},
|
{"screenshot", cmdScreenshot, opts_screenshot, info_screenshot, 0},
|
||||||
{"setmaxmem", cmdSetmaxmem, opts_setmaxmem, info_setmaxmem, 0},
|
{"setmaxmem", cmdSetmaxmem, opts_setmaxmem, info_setmaxmem, 0},
|
||||||
|
@ -646,6 +646,37 @@ between the creation and restore point. For a more complete system
|
|||||||
restore point, where the disk state is saved alongside the memory
|
restore point, where the disk state is saved alongside the memory
|
||||||
state, see the B<snapshot> family of commands.
|
state, see the B<snapshot> family of commands.
|
||||||
|
|
||||||
|
=item B<save-image-define> I<file> I<xml>
|
||||||
|
|
||||||
|
Update the domain XML that will be used when I<file> is later
|
||||||
|
used in the B<restore> command. The I<xml> argument must be a file
|
||||||
|
name containing the alternative XML, with changes only in the
|
||||||
|
host-specific portions of the domain XML. For example, it can
|
||||||
|
be used to account for file naming differences resulting from creating
|
||||||
|
disk snapshots of underlying storage after the guest was saved.
|
||||||
|
|
||||||
|
=item B<save-image-dumpxml> I<file> [I<--security-info>]
|
||||||
|
|
||||||
|
Extract the domain XML that was in effect at the time the saved state
|
||||||
|
file I<file> was created with the B<save> command. Using
|
||||||
|
I<--security-info> will also include security sensitive information.
|
||||||
|
|
||||||
|
=item B<save-image-edit> I<file>
|
||||||
|
|
||||||
|
Edit the XML configuration associated with a saved state file I<file>
|
||||||
|
created by the B<save> command.
|
||||||
|
|
||||||
|
This is equivalent to:
|
||||||
|
|
||||||
|
virsh save-image-dumpxml state-file > state-file.xml
|
||||||
|
vi state-file.xml (or make changes with your other text editor)
|
||||||
|
virsh save-image-define state-file state-file-xml
|
||||||
|
|
||||||
|
except that it does some error checking.
|
||||||
|
|
||||||
|
The editor used can be supplied by the C<$VISUAL> or C<$EDITOR> environment
|
||||||
|
variables, and defaults to C<vi>.
|
||||||
|
|
||||||
=item B<schedinfo> [I<--set> B<parameter=value>] I<domain-id> [[I<--config>]
|
=item B<schedinfo> [I<--set> B<parameter=value>] I<domain-id> [[I<--config>]
|
||||||
[I<--live>] | [I<--current>]]
|
[I<--live>] | [I<--current>]]
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user