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

Michal Privoznik mprivozn at redhat.com
Wed May 9 13:36:26 UTC 2012


If users {net-,pool-,}edit but make a mistake in XML all changes
are permanently lost. However, if virsh is running in interactive
mode we can as user if he wants to re-edit the file and correct
the mistakes.
---
 tools/console.c |   40 +++++++++++++++++++++++++---------------
 tools/console.h |    1 +
 tools/virsh.c   |   41 +++++++++++++++++++++++++++++++++++------
 3 files changed, 61 insertions(+), 21 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..97c97cd 100644
--- a/tools/console.h
+++ b/tools/console.h
@@ -30,6 +30,7 @@ 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.c b/tools/virsh.c
index dd9292a..3537e2e 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>
@@ -15806,11 +15807,14 @@ cmdEdit (vshControl *ctl, const vshCmd *cmd)
 {
     bool ret = false;
     virDomainPtr dom = NULL;
+    virDomainPtr dom_edited = NULL;
     char *tmp = NULL;
     char *doc = NULL;
     char *doc_edited = NULL;
     char *doc_reread = NULL;
     unsigned int flags = VIR_DOMAIN_XML_SECURE | VIR_DOMAIN_XML_INACTIVE;
+    int c = 0;
+    struct termios ttyattr;
 
     if (!vshConnectionUsability(ctl, ctl->conn))
         goto cleanup;
@@ -15828,6 +15832,7 @@ cmdEdit (vshControl *ctl, const vshCmd *cmd)
     tmp = editWriteToTempFile (ctl, doc);
     if (!tmp) goto cleanup;
 
+reedit:
     /* Start the editor. */
     if (editFile (ctl, tmp) == -1) goto cleanup;
 
@@ -15858,19 +15863,43 @@ cmdEdit (vshControl *ctl, const vshCmd *cmd)
     }
 
     /* Everything checks out, so redefine the domain. */
-    virDomainFree (dom);
-    dom = virDomainDefineXML(ctl->conn, doc_edited);
-    if (!dom)
-        goto cleanup;
+    dom_edited = virDomainDefineXML(ctl->conn, doc_edited);
+    if (!dom_edited) {
+        /* Redefine failed. If we are in interactive mode ask user
+         * if he wants to re-edit the XML. */
+        if (!ctl->imode ||
+            vshMakeStdinRaw(&ttyattr, false) < 0)
+            goto cleanup;
+
+        virshReportError(ctl);
+
+        while (true) {
+            vshPrint(ctl, "\rFailed. Try again? (y/Y/n/N) [Y]:");
+            c = getchar();
+            c = c_toupper(c);
+            if (c == '\n' || c == '\r' || c == 'Y' || c == 'N')
+                break;
+        }
+
+        tcsetattr(STDIN_FILENO, TCSAFLUSH, &ttyattr);
+
+        if (c == 'N')
+            goto cleanup;
+
+        vshPrint(ctl, "\r\n");
+        goto reedit;
+    }
 
     vshPrint (ctl, _("Domain %s XML configuration edited.\n"),
               virDomainGetName(dom));
 
     ret = true;
 
- cleanup:
+cleanup:
     if (dom)
-        virDomainFree (dom);
+        virDomainFree(dom);
+    if (dom_edited)
+        virDomainFree(dom_edited);
 
     VIR_FREE(doc);
     VIR_FREE(doc_edited);
-- 
1.7.8.5




More information about the libvir-list mailing list