mirror of https://gitee.com/openkylin/libvirt.git
virsh: Allow users to reedit rejected XML
If users *-edit but make a mistake in XML all changes are permanently lost. However, if virsh is not running within a script we can ask user if he wants to re-edit the file and correct the mistakes.
This commit is contained in:
parent
0766783abb
commit
a7de052369
|
@ -298,13 +298,36 @@ vshGetEscapeChar(const char *s)
|
|||
return *s;
|
||||
}
|
||||
|
||||
int vshMakeStdinRaw(struct termios *ttyattr, bool report_errors) {
|
||||
struct termios rawattr;
|
||||
|
||||
if (tcgetattr(STDIN_FILENO, ttyattr) < 0) {
|
||||
if (report_errors)
|
||||
VIR_ERROR(_("unable to get tty attributes: %s"),
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
rawattr = *ttyattr;
|
||||
cfmakeraw(&rawattr);
|
||||
|
||||
if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &rawattr) < 0) {
|
||||
if (report_errors)
|
||||
VIR_ERROR(_("unable to set tty attributes: %s"),
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vshRunConsole(virDomainPtr dom,
|
||||
const char *dev_name,
|
||||
const char *escape_seq,
|
||||
unsigned int flags)
|
||||
{
|
||||
int ret = -1;
|
||||
struct termios ttyattr, rawattr;
|
||||
struct termios ttyattr;
|
||||
void (*old_sigquit)(int);
|
||||
void (*old_sigterm)(int);
|
||||
void (*old_sigint)(int);
|
||||
|
@ -317,21 +340,8 @@ int vshRunConsole(virDomainPtr dom,
|
|||
result in it being echoed back already), and
|
||||
also ensure Ctrl-C, etc is blocked, and misc
|
||||
other bits */
|
||||
if (tcgetattr(STDIN_FILENO, &ttyattr) < 0) {
|
||||
VIR_ERROR(_("unable to get tty attributes: %s"),
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
rawattr = ttyattr;
|
||||
cfmakeraw(&rawattr);
|
||||
|
||||
if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &rawattr) < 0) {
|
||||
VIR_ERROR(_("unable to set tty attributes: %s"),
|
||||
strerror(errno));
|
||||
if (vshMakeStdinRaw(&ttyattr, true) < 0)
|
||||
goto resettty;
|
||||
}
|
||||
|
||||
|
||||
/* Trap all common signals so that we can safely restore
|
||||
the original terminal settings on STDIN before the
|
||||
|
|
|
@ -30,6 +30,8 @@ int vshRunConsole(virDomainPtr dom,
|
|||
const char *escape_seq,
|
||||
unsigned int flags);
|
||||
|
||||
int vshMakeStdinRaw(struct termios *ttyattr, bool report_errors);
|
||||
|
||||
# endif /* !WIN32 */
|
||||
|
||||
#endif /* __VIR_CONSOLE_H__ */
|
||||
|
|
|
@ -55,6 +55,7 @@ do {
|
|||
char *doc = NULL;
|
||||
char *doc_edited = NULL;
|
||||
char *doc_reread = NULL;
|
||||
char *msg = NULL;
|
||||
|
||||
/* Get the XML configuration of the object. */
|
||||
doc = (EDIT_GET_XML);
|
||||
|
@ -66,6 +67,7 @@ do {
|
|||
if (!tmp)
|
||||
goto edit_cleanup;
|
||||
|
||||
reedit:
|
||||
/* Start the editor. */
|
||||
if (editFile(ctl, tmp) == -1)
|
||||
goto edit_cleanup;
|
||||
|
@ -80,6 +82,9 @@ do {
|
|||
EDIT_NOT_CHANGED;
|
||||
}
|
||||
|
||||
redefine:
|
||||
msg = NULL;
|
||||
|
||||
/* 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.
|
||||
|
@ -89,15 +94,38 @@ do {
|
|||
goto edit_cleanup;
|
||||
|
||||
if (STRNEQ(doc, doc_reread)) {
|
||||
vshError(ctl, "%s", _("ERROR: the XML configuration "
|
||||
"was changed by another user"));
|
||||
goto edit_cleanup;
|
||||
msg = _("The XML configuration was changed by another user.");
|
||||
VIR_FREE(doc);
|
||||
doc = doc_reread;
|
||||
doc_reread = NULL;
|
||||
}
|
||||
|
||||
/* Everything checks out, so redefine the object. */
|
||||
EDIT_FREE;
|
||||
if (!(EDIT_DEFINE))
|
||||
goto edit_cleanup;
|
||||
if (!msg && !(EDIT_DEFINE)) {
|
||||
msg = _("Failed.");
|
||||
}
|
||||
|
||||
if (msg) {
|
||||
int c = vshAskReedit(ctl, msg);
|
||||
switch (c) {
|
||||
case 'y':
|
||||
goto reedit;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
goto redefine;
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
goto edit_cleanup;
|
||||
break;
|
||||
|
||||
default:
|
||||
vshError(ctl, "%s", msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include <signal.h>
|
||||
#include <poll.h>
|
||||
#include <strings.h>
|
||||
#include <termios.h>
|
||||
|
||||
#include <libxml/parser.h>
|
||||
#include <libxml/tree.h>
|
||||
|
@ -654,6 +655,62 @@ vshReconnect(vshControl *ctl)
|
|||
ctl->useSnapshotOld = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* vshAskReedit:
|
||||
* @msg: Question to ask user
|
||||
*
|
||||
* Ask user if he wants to return to previously
|
||||
* edited file.
|
||||
*
|
||||
* Returns 'y' if he wants to
|
||||
* 'f' if he forcibly wants to
|
||||
* 'n' if he doesn't want to
|
||||
* -1 on error
|
||||
* 0 otherwise
|
||||
*/
|
||||
static int
|
||||
vshAskReedit(vshControl *ctl, const char *msg)
|
||||
{
|
||||
#ifndef WIN32
|
||||
int c = -1;
|
||||
struct termios ttyattr;
|
||||
|
||||
if (!isatty(STDIN_FILENO))
|
||||
return -1;
|
||||
|
||||
virshReportError(ctl);
|
||||
|
||||
if (vshMakeStdinRaw(&ttyattr, false) < 0)
|
||||
return -1;
|
||||
|
||||
while (true) {
|
||||
/* TRANSLATORS: For now, we aren't using LC_MESSAGES, and the user
|
||||
* choices really are limited to just 'y', 'n', 'f' and '?' */
|
||||
vshPrint(ctl, "\r%s %s", msg, _("Try again? [y,n,f,?]:"));
|
||||
c = c_tolower(getchar());
|
||||
|
||||
if (c == '?') {
|
||||
vshPrint(ctl, "\r\n%s", _("y - yes, start editor again\r\n"
|
||||
"n - no, throw away my changes\r\n"
|
||||
"f - force, try to redefine again\r\n"
|
||||
"? - print this help\r\n"));
|
||||
continue;
|
||||
} else if (c == 'y' || c == 'n' || c == 'f') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
tcsetattr(STDIN_FILENO, TCSAFLUSH, &ttyattr);
|
||||
|
||||
vshPrint(ctl, "\r\n");
|
||||
return c;
|
||||
#else
|
||||
vshDebug(ctl, VSH_ERR_WARNING, "%s", _("This function is not "
|
||||
"supported on WIN32 platform"));
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* ---------------
|
||||
* Commands
|
||||
* ---------------
|
||||
|
|
Loading…
Reference in New Issue