[libvirt] [PATCH v3 2/2] virsh: Allow users to reedit rejected XML

Michal Privoznik mprivozn at redhat.com
Fri Jun 1 13:01:07 UTC 2012


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.
---
 tools/console.c    |   40 ++++++++++++++++++++++-------------
 tools/console.h    |    2 +
 tools/virsh-edit.c |   38 ++++++++++++++++++++++++++++++----
 tools/virsh.c      |   57 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 117 insertions(+), 20 deletions(-)

diff --git a/tools/console.c b/tools/console.c
index 34fde05..90e54e3 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 2b5440c..1feea9e 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 b50946e..ef47f9d 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 4af5334..574b92f 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
  * ---------------
-- 
1.7.8.5




More information about the libvir-list mailing list