mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-22 04:25:18 +00:00
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;
|
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,
|
int vshRunConsole(virDomainPtr dom,
|
||||||
const char *dev_name,
|
const char *dev_name,
|
||||||
const char *escape_seq,
|
const char *escape_seq,
|
||||||
unsigned int flags)
|
unsigned int flags)
|
||||||
{
|
{
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
struct termios ttyattr, rawattr;
|
struct termios ttyattr;
|
||||||
void (*old_sigquit)(int);
|
void (*old_sigquit)(int);
|
||||||
void (*old_sigterm)(int);
|
void (*old_sigterm)(int);
|
||||||
void (*old_sigint)(int);
|
void (*old_sigint)(int);
|
||||||
@ -317,21 +340,8 @@ int vshRunConsole(virDomainPtr dom,
|
|||||||
result in it being echoed back already), and
|
result in it being echoed back already), and
|
||||||
also ensure Ctrl-C, etc is blocked, and misc
|
also ensure Ctrl-C, etc is blocked, and misc
|
||||||
other bits */
|
other bits */
|
||||||
if (tcgetattr(STDIN_FILENO, &ttyattr) < 0) {
|
if (vshMakeStdinRaw(&ttyattr, true) < 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));
|
|
||||||
goto resettty;
|
goto resettty;
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Trap all common signals so that we can safely restore
|
/* Trap all common signals so that we can safely restore
|
||||||
the original terminal settings on STDIN before the
|
the original terminal settings on STDIN before the
|
||||||
|
@ -30,6 +30,8 @@ int vshRunConsole(virDomainPtr dom,
|
|||||||
const char *escape_seq,
|
const char *escape_seq,
|
||||||
unsigned int flags);
|
unsigned int flags);
|
||||||
|
|
||||||
|
int vshMakeStdinRaw(struct termios *ttyattr, bool report_errors);
|
||||||
|
|
||||||
# endif /* !WIN32 */
|
# endif /* !WIN32 */
|
||||||
|
|
||||||
#endif /* __VIR_CONSOLE_H__ */
|
#endif /* __VIR_CONSOLE_H__ */
|
||||||
|
@ -55,6 +55,7 @@ do {
|
|||||||
char *doc = NULL;
|
char *doc = NULL;
|
||||||
char *doc_edited = NULL;
|
char *doc_edited = NULL;
|
||||||
char *doc_reread = NULL;
|
char *doc_reread = NULL;
|
||||||
|
char *msg = NULL;
|
||||||
|
|
||||||
/* Get the XML configuration of the object. */
|
/* Get the XML configuration of the object. */
|
||||||
doc = (EDIT_GET_XML);
|
doc = (EDIT_GET_XML);
|
||||||
@ -66,6 +67,7 @@ do {
|
|||||||
if (!tmp)
|
if (!tmp)
|
||||||
goto edit_cleanup;
|
goto edit_cleanup;
|
||||||
|
|
||||||
|
reedit:
|
||||||
/* Start the editor. */
|
/* Start the editor. */
|
||||||
if (editFile(ctl, tmp) == -1)
|
if (editFile(ctl, tmp) == -1)
|
||||||
goto edit_cleanup;
|
goto edit_cleanup;
|
||||||
@ -80,6 +82,9 @@ do {
|
|||||||
EDIT_NOT_CHANGED;
|
EDIT_NOT_CHANGED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
redefine:
|
||||||
|
msg = NULL;
|
||||||
|
|
||||||
/* Now re-read the object XML. Did someone else change it while
|
/* Now re-read the object XML. Did someone else change it while
|
||||||
* it was being edited? This also catches problems such as us
|
* it was being edited? This also catches problems such as us
|
||||||
* losing a connection or the object going away.
|
* losing a connection or the object going away.
|
||||||
@ -89,15 +94,38 @@ do {
|
|||||||
goto edit_cleanup;
|
goto edit_cleanup;
|
||||||
|
|
||||||
if (STRNEQ(doc, doc_reread)) {
|
if (STRNEQ(doc, doc_reread)) {
|
||||||
vshError(ctl, "%s", _("ERROR: the XML configuration "
|
msg = _("The XML configuration was changed by another user.");
|
||||||
"was changed by another user"));
|
VIR_FREE(doc);
|
||||||
goto edit_cleanup;
|
doc = doc_reread;
|
||||||
|
doc_reread = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Everything checks out, so redefine the object. */
|
/* Everything checks out, so redefine the object. */
|
||||||
EDIT_FREE;
|
EDIT_FREE;
|
||||||
if (!(EDIT_DEFINE))
|
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;
|
goto edit_cleanup;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
vshError(ctl, "%s", msg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#include <strings.h>
|
#include <strings.h>
|
||||||
|
#include <termios.h>
|
||||||
|
|
||||||
#include <libxml/parser.h>
|
#include <libxml/parser.h>
|
||||||
#include <libxml/tree.h>
|
#include <libxml/tree.h>
|
||||||
@ -654,6 +655,62 @@ vshReconnect(vshControl *ctl)
|
|||||||
ctl->useSnapshotOld = false;
|
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
|
* Commands
|
||||||
* ---------------
|
* ---------------
|
||||||
|
Loading…
x
Reference in New Issue
Block a user