aboutsummaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorMichal Privoznik <mprivozn@redhat.com>2012-05-18 12:21:06 +0200
committerMichal Privoznik <mprivozn@redhat.com>2012-06-02 10:42:54 +0200
commita7de05236986b16e086ad482ed3d190845cf6dd5 (patch)
treed55c04cd4b20974b07a288f51c843d77b27fa434 /tools
parentvirsh: Switch from generated cmd*Edit commands to nongenerated (diff)
downloadlibvirt-a7de05236986b16e086ad482ed3d190845cf6dd5.tar.gz
libvirt-a7de05236986b16e086ad482ed3d190845cf6dd5.tar.bz2
libvirt-a7de05236986b16e086ad482ed3d190845cf6dd5.zip
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.
Diffstat (limited to 'tools')
-rw-r--r--tools/console.c40
-rw-r--r--tools/console.h2
-rw-r--r--tools/virsh-edit.c38
-rw-r--r--tools/virsh.c57
4 files changed, 117 insertions, 20 deletions
diff --git a/tools/console.c b/tools/console.c
index 34fde05eb..90e54e36c 100644
--- a/tools/console.c
+++ b/tools/console.c
@@ -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
diff --git a/tools/console.h b/tools/console.h
index 2b5440c65..1feea9edc 100644
--- a/tools/console.h
+++ b/tools/console.h
@@ -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__ */
diff --git a/tools/virsh-edit.c b/tools/virsh-edit.c
index 41c97371d..aa59f25ae 100644
--- a/tools/virsh-edit.c
+++ b/tools/virsh-edit.c
@@ -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;
diff --git a/tools/virsh.c b/tools/virsh.c
index c5f6cd048..a934c1320 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -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
* ---------------