2012-05-17 23:08:53 +08:00
|
|
|
/*
|
|
|
|
* virsh-edit.c: Implementation of generic virsh *-edit intelligence
|
|
|
|
*
|
2015-02-19 21:16:39 +08:00
|
|
|
* Copyright (C) 2012, 2015 Red Hat, Inc.
|
2012-05-17 23:08:53 +08:00
|
|
|
*
|
2012-07-27 17:39:53 +08: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-21 06:30:55 +08:00
|
|
|
* License along with this library. If not, see
|
2012-07-27 17:39:53 +08:00
|
|
|
* <http://www.gnu.org/licenses/>.
|
2012-05-17 23:08:53 +08:00
|
|
|
*
|
|
|
|
* Usage:
|
|
|
|
* Define macros:
|
|
|
|
* EDIT_GET_XML - expression which produces a pointer to XML string, e.g:
|
|
|
|
* #define EDIT_GET_XML virDomainGetXMLDesc(dom, flags)
|
|
|
|
*
|
|
|
|
* EDIT_NOT_CHANGED - this action is taken if the XML wasn't changed.
|
|
|
|
* Note, that you don't want to jump to cleanup but edit_cleanup label
|
|
|
|
* where temporary variables are free()-d and temporary file is deleted:
|
2016-11-04 22:22:26 +08:00
|
|
|
* #define EDIT_NOT_CHANGED vshPrintExtra (ctl, _("Domain %s XML not changed"), \
|
|
|
|
* virDomainGetName(dom)); \
|
2012-05-17 23:08:53 +08:00
|
|
|
* ret = true; goto edit_cleanup;
|
|
|
|
* Note that this is a statement.
|
|
|
|
*
|
|
|
|
* EDIT_DEFINE - expression which redefines the object. The edited XML from
|
|
|
|
* user is in 'doc_edited' variable. Don't overwrite the pointer to the
|
|
|
|
* object, as we may iterate once more over and therefore the pointer
|
|
|
|
* would be invalid. Hence assign object to a different variable.
|
|
|
|
* Moreover, this needs to be an expression where:
|
|
|
|
* - 0 is taken as error (our virDefine* APIs often return NULL on error)
|
|
|
|
* - everything else is taken as success
|
|
|
|
* For example:
|
|
|
|
* #define EDIT_DEFINE (dom_edited = virDomainDefineXML(ctl->conn, doc_edited))
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef EDIT_GET_XML
|
|
|
|
# error Missing EDIT_GET_XML definition
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef EDIT_NOT_CHANGED
|
|
|
|
# error Missing EDIT_NOT_CHANGED definition
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef EDIT_DEFINE
|
|
|
|
# error Missing EDIT_DEFINE definition
|
|
|
|
#endif
|
|
|
|
|
|
|
|
do {
|
|
|
|
char *tmp = NULL;
|
|
|
|
char *doc = NULL;
|
|
|
|
char *doc_edited = NULL;
|
|
|
|
char *doc_reread = NULL;
|
2012-06-07 11:13:57 +08:00
|
|
|
const char *msg = NULL;
|
2012-09-19 17:31:44 +08:00
|
|
|
bool edit_success = false;
|
2015-02-19 21:16:39 +08:00
|
|
|
bool relax_avail = false;
|
2012-05-17 23:08:53 +08:00
|
|
|
|
|
|
|
/* Get the XML configuration of the object. */
|
|
|
|
doc = (EDIT_GET_XML);
|
|
|
|
if (!doc)
|
|
|
|
goto edit_cleanup;
|
|
|
|
|
|
|
|
/* Create and open the temporary file. */
|
virsh: use common namespacing
Convert the exported items in virsh.h to use a common 'vsh' prefix.
* tools/virsh.h (VIRSH_MAX_XML_FILE): Rename...
(VSH_MAX_XML_FILE): ...and parenthesize.
(DIFF_MSEC, CTRL_CLOSE_BRACKET): Delete.
(vshUsage, vshInit, vshDeinit, vshParseArgv): Remove prototype.
(editWriteToTempFile, editFile, editReadBackFile, prettyCapacity)
(virshReportError): Rename...
(vshEditWriteToTempFile, vshEditFile, vshEditReadBackFile)
(vshPrettyCapacity, vshReportError): ...into vsh namespace.
(jobWatchTimeoutFunc): Move to virsh-domain.c.
* tools/virsh.c (vshCommandRun): Inline former DIFF_MSEC.
(main): Inline former CTRL_CLOSE_BRACKET.
(vshUsage, vshInit, vshDeinit, vshParseArgv): Make static.
(prettyCapacity, virshReportError, editWriteToTempFile, editFile):
Fix naming, and adjust usage.
(vshAskReedit, vshCommandRun, vshEventLoop, vshInit): Adjust
usage.
* tools/virsh-domain.c (cmdAttachDevice, cmdCPUCompare)
(cmdCPUBaseline, cmdCreate, cmdDefine, cmdDetachDevice)
(cmdUpdateDevice, cmdDesc, cmdUndefine, cmdStart, cmdVcpucount)
(cmdAttachDevice, cmdDomjobinfo): Likewise.
* tools/virsh-edit.c (do): Likewise.
* tools/virsh-interface.c (cmdInterfaceDefine): Likewise.
* tools/virsh-network.c (cmdNetworkCreate, cmdNetworkDefine):
Likewise.
* tools/virsh-nodedev.c (cmdNodeDeviceCreate): Likewise.
* tools/virsh-nwfilter.c (cmdNWFilterDefine): Likewise.
* tools/virsh-pool.c (cmdPoolCreate, cmdPoolDefine)
(cmdPoolDiscoverSources, cmdPoolList): Likewise.
* tools/virsh-secret.c (cmdSecretDefine): Likewise.
* tools/virsh-snapshot.c (cmdSnapshotCreate, vshSnapshotCreate)
(vshLookupSnapshot, cmdSnapshotEdit, cmdSnapshotCurrent)
(vshGetSnapshotParent): Likewise.
* tools/virsh-volume.c (cmdVolCreate, cmdVolCreateFrom)
(cmdVolInfo, cmdVolList): Likewise.
2012-08-19 12:10:17 +08:00
|
|
|
tmp = vshEditWriteToTempFile(ctl, doc);
|
2012-05-17 23:08:53 +08:00
|
|
|
if (!tmp)
|
|
|
|
goto edit_cleanup;
|
|
|
|
|
2014-03-25 14:53:59 +08:00
|
|
|
reedit:
|
2015-02-19 21:16:39 +08:00
|
|
|
|
|
|
|
#ifdef EDIT_RELAX
|
|
|
|
relax_avail = true;
|
|
|
|
#endif
|
|
|
|
|
2012-05-17 23:08:53 +08:00
|
|
|
/* Start the editor. */
|
virsh: use common namespacing
Convert the exported items in virsh.h to use a common 'vsh' prefix.
* tools/virsh.h (VIRSH_MAX_XML_FILE): Rename...
(VSH_MAX_XML_FILE): ...and parenthesize.
(DIFF_MSEC, CTRL_CLOSE_BRACKET): Delete.
(vshUsage, vshInit, vshDeinit, vshParseArgv): Remove prototype.
(editWriteToTempFile, editFile, editReadBackFile, prettyCapacity)
(virshReportError): Rename...
(vshEditWriteToTempFile, vshEditFile, vshEditReadBackFile)
(vshPrettyCapacity, vshReportError): ...into vsh namespace.
(jobWatchTimeoutFunc): Move to virsh-domain.c.
* tools/virsh.c (vshCommandRun): Inline former DIFF_MSEC.
(main): Inline former CTRL_CLOSE_BRACKET.
(vshUsage, vshInit, vshDeinit, vshParseArgv): Make static.
(prettyCapacity, virshReportError, editWriteToTempFile, editFile):
Fix naming, and adjust usage.
(vshAskReedit, vshCommandRun, vshEventLoop, vshInit): Adjust
usage.
* tools/virsh-domain.c (cmdAttachDevice, cmdCPUCompare)
(cmdCPUBaseline, cmdCreate, cmdDefine, cmdDetachDevice)
(cmdUpdateDevice, cmdDesc, cmdUndefine, cmdStart, cmdVcpucount)
(cmdAttachDevice, cmdDomjobinfo): Likewise.
* tools/virsh-edit.c (do): Likewise.
* tools/virsh-interface.c (cmdInterfaceDefine): Likewise.
* tools/virsh-network.c (cmdNetworkCreate, cmdNetworkDefine):
Likewise.
* tools/virsh-nodedev.c (cmdNodeDeviceCreate): Likewise.
* tools/virsh-nwfilter.c (cmdNWFilterDefine): Likewise.
* tools/virsh-pool.c (cmdPoolCreate, cmdPoolDefine)
(cmdPoolDiscoverSources, cmdPoolList): Likewise.
* tools/virsh-secret.c (cmdSecretDefine): Likewise.
* tools/virsh-snapshot.c (cmdSnapshotCreate, vshSnapshotCreate)
(vshLookupSnapshot, cmdSnapshotEdit, cmdSnapshotCurrent)
(vshGetSnapshotParent): Likewise.
* tools/virsh-volume.c (cmdVolCreate, cmdVolCreateFrom)
(cmdVolInfo, cmdVolList): Likewise.
2012-08-19 12:10:17 +08:00
|
|
|
if (vshEditFile(ctl, tmp) == -1)
|
2012-05-17 23:08:53 +08:00
|
|
|
goto edit_cleanup;
|
|
|
|
|
|
|
|
/* Read back the edited file. */
|
2013-06-25 21:10:27 +08:00
|
|
|
VIR_FREE(doc_edited);
|
virsh: use common namespacing
Convert the exported items in virsh.h to use a common 'vsh' prefix.
* tools/virsh.h (VIRSH_MAX_XML_FILE): Rename...
(VSH_MAX_XML_FILE): ...and parenthesize.
(DIFF_MSEC, CTRL_CLOSE_BRACKET): Delete.
(vshUsage, vshInit, vshDeinit, vshParseArgv): Remove prototype.
(editWriteToTempFile, editFile, editReadBackFile, prettyCapacity)
(virshReportError): Rename...
(vshEditWriteToTempFile, vshEditFile, vshEditReadBackFile)
(vshPrettyCapacity, vshReportError): ...into vsh namespace.
(jobWatchTimeoutFunc): Move to virsh-domain.c.
* tools/virsh.c (vshCommandRun): Inline former DIFF_MSEC.
(main): Inline former CTRL_CLOSE_BRACKET.
(vshUsage, vshInit, vshDeinit, vshParseArgv): Make static.
(prettyCapacity, virshReportError, editWriteToTempFile, editFile):
Fix naming, and adjust usage.
(vshAskReedit, vshCommandRun, vshEventLoop, vshInit): Adjust
usage.
* tools/virsh-domain.c (cmdAttachDevice, cmdCPUCompare)
(cmdCPUBaseline, cmdCreate, cmdDefine, cmdDetachDevice)
(cmdUpdateDevice, cmdDesc, cmdUndefine, cmdStart, cmdVcpucount)
(cmdAttachDevice, cmdDomjobinfo): Likewise.
* tools/virsh-edit.c (do): Likewise.
* tools/virsh-interface.c (cmdInterfaceDefine): Likewise.
* tools/virsh-network.c (cmdNetworkCreate, cmdNetworkDefine):
Likewise.
* tools/virsh-nodedev.c (cmdNodeDeviceCreate): Likewise.
* tools/virsh-nwfilter.c (cmdNWFilterDefine): Likewise.
* tools/virsh-pool.c (cmdPoolCreate, cmdPoolDefine)
(cmdPoolDiscoverSources, cmdPoolList): Likewise.
* tools/virsh-secret.c (cmdSecretDefine): Likewise.
* tools/virsh-snapshot.c (cmdSnapshotCreate, vshSnapshotCreate)
(vshLookupSnapshot, cmdSnapshotEdit, cmdSnapshotCurrent)
(vshGetSnapshotParent): Likewise.
* tools/virsh-volume.c (cmdVolCreate, cmdVolCreateFrom)
(cmdVolInfo, cmdVolList): Likewise.
2012-08-19 12:10:17 +08:00
|
|
|
doc_edited = vshEditReadBackFile(ctl, tmp);
|
2012-05-17 23:08:53 +08:00
|
|
|
if (!doc_edited)
|
|
|
|
goto edit_cleanup;
|
|
|
|
|
|
|
|
/* Compare original XML with edited. Has it changed at all? */
|
2014-11-13 22:20:51 +08:00
|
|
|
if (STREQ(doc, doc_edited))
|
2012-05-17 23:08:53 +08:00
|
|
|
EDIT_NOT_CHANGED;
|
|
|
|
|
2014-03-25 14:53:59 +08:00
|
|
|
redefine:
|
2012-05-18 18:21:06 +08:00
|
|
|
msg = NULL;
|
|
|
|
|
2012-05-17 23:08:53 +08:00
|
|
|
/* Now re-read the object XML. Did someone else change it while
|
|
|
|
* it was being edited? This also catches problems such as us
|
|
|
|
* losing a connection or the object going away.
|
|
|
|
*/
|
2013-06-25 21:10:27 +08:00
|
|
|
VIR_FREE(doc_reread);
|
2012-05-17 23:08:53 +08:00
|
|
|
doc_reread = (EDIT_GET_XML);
|
|
|
|
if (!doc_reread)
|
|
|
|
goto edit_cleanup;
|
|
|
|
|
|
|
|
if (STRNEQ(doc, doc_reread)) {
|
2012-05-18 18:21:06 +08:00
|
|
|
msg = _("The XML configuration was changed by another user.");
|
|
|
|
VIR_FREE(doc);
|
|
|
|
doc = doc_reread;
|
|
|
|
doc_reread = NULL;
|
2012-05-17 23:08:53 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Everything checks out, so redefine the object. */
|
2014-11-13 22:20:51 +08:00
|
|
|
if (!msg && !(EDIT_DEFINE))
|
2012-05-18 18:21:06 +08:00
|
|
|
msg = _("Failed.");
|
|
|
|
|
|
|
|
if (msg) {
|
2015-02-19 21:16:39 +08:00
|
|
|
int c = vshAskReedit(ctl, msg, relax_avail);
|
2012-05-18 18:21:06 +08:00
|
|
|
switch (c) {
|
|
|
|
case 'y':
|
|
|
|
goto reedit;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'f':
|
|
|
|
goto redefine;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'n':
|
|
|
|
goto edit_cleanup;
|
|
|
|
break;
|
|
|
|
|
2015-02-19 21:16:39 +08:00
|
|
|
#ifdef EDIT_RELAX
|
|
|
|
case 'i':
|
|
|
|
if (relax_avail) {
|
|
|
|
EDIT_RELAX;
|
|
|
|
relax_avail = false;
|
|
|
|
goto redefine;
|
|
|
|
}
|
2019-10-15 19:38:21 +08:00
|
|
|
G_GNUC_FALLTHROUGH;
|
2015-02-19 21:16:39 +08:00
|
|
|
#endif
|
|
|
|
|
2012-05-18 18:21:06 +08:00
|
|
|
default:
|
|
|
|
vshError(ctl, "%s", msg);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2012-05-17 23:08:53 +08:00
|
|
|
|
2012-09-19 17:31:44 +08:00
|
|
|
edit_success = true;
|
2012-05-17 23:08:53 +08:00
|
|
|
|
2014-03-25 14:53:59 +08:00
|
|
|
edit_cleanup:
|
2012-05-17 23:08:53 +08:00
|
|
|
VIR_FREE(doc);
|
|
|
|
VIR_FREE(doc_edited);
|
|
|
|
VIR_FREE(doc_reread);
|
|
|
|
if (tmp) {
|
2012-10-17 17:23:12 +08:00
|
|
|
unlink(tmp);
|
2012-05-17 23:08:53 +08:00
|
|
|
VIR_FREE(tmp);
|
|
|
|
}
|
2012-09-19 17:31:44 +08:00
|
|
|
|
|
|
|
if (!edit_success)
|
|
|
|
goto cleanup;
|
2012-05-17 23:08:53 +08:00
|
|
|
|
|
|
|
} while (0);
|
|
|
|
|
|
|
|
|
|
|
|
#undef EDIT_GET_XML
|
|
|
|
#undef EDIT_NOT_CHANGED
|
|
|
|
#undef EDIT_DEFINE
|