[node-patches] Change in ovirt-node[master]: console: Capture console output

fabiand at fedoraproject.org fabiand at fedoraproject.org
Wed Feb 27 09:30:29 UTC 2013


Fabian Deutsch has uploaded a new change for review.

Change subject: console: Capture console output
......................................................................

console: Capture console output

Sometimes transaction elements would call functions which wrote to
stderr/stdout, this scrambled the screen.
Now this output from transaction elements is captured (for a later
usage) to prevent the scramblind of the screen contents.

Change-Id: I78739975bf9290f650e1b163d68aedd0ce4ebf79
Signed-off-by: Fabian Deutsch <fabiand at fedoraproject.org>
---
M scripts/tui/src/ovirt/node/installer/progress_page.py
M scripts/tui/src/ovirt/node/ui/__init__.py
M scripts/tui/src/ovirt/node/utils/console.py
3 files changed, 84 insertions(+), 5 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-node refs/changes/78/12478/1

diff --git a/scripts/tui/src/ovirt/node/installer/progress_page.py b/scripts/tui/src/ovirt/node/installer/progress_page.py
index 412f404..5a49308 100644
--- a/scripts/tui/src/ovirt/node/installer/progress_page.py
+++ b/scripts/tui/src/ovirt/node/installer/progress_page.py
@@ -20,6 +20,7 @@
 # also available at http://www.gnu.org/copyleft/gpl.html.
 from ovirt.node import plugins, ui, utils
 from ovirt.node.config import defaults
+from ovirt.node.utils import console
 import threading
 import time
 
@@ -103,19 +104,29 @@
                 def do_commit():
                     tx_element.commit()
 
-                self.progress_plugin.dry_or(do_commit)
+                with console.CaptureOutput() as captured:
+                    # Sometimes a tx_element is wrapping some code that
+                    # writes to stdout/stderr which scrambles the screen,
+                    # therefore we are capturing this
+                    self.progress_plugin.dry_or(do_commit)
 
                 progressbar.current(int(100.0 / txlen * idx))
                 log_lines[-1] = "%s (Done)" % log_lines[-1]
                 log.text("\n".join(log_lines))
+
         except Exception as e:
             msg = "Exception: %s" % repr(e)
-            self.logger.warning(msg, exc_info=True)
+            self.logger.debug(msg, exc_info=True)
             log.text(msg)
-            raise
+
         finally:
             self.progress_plugin.widgets["action.reboot"].enabled(True)
 
+        if captured.stderr.getvalue():
+            se = captured.stderr.getvalue()
+            if se:
+                log.text("Stderr: %s" % se)
+
         # We enforce a redraw, because this the non-mainloop thread
         self.progress_plugin.application.ui.force_redraw()
 
diff --git a/scripts/tui/src/ovirt/node/ui/__init__.py b/scripts/tui/src/ovirt/node/ui/__init__.py
index 7237ff2..202b23b 100644
--- a/scripts/tui/src/ovirt/node/ui/__init__.py
+++ b/scripts/tui/src/ovirt/node/ui/__init__.py
@@ -19,6 +19,7 @@
 # MA  02110-1301, USA.  A copy of the GNU General Public License is
 # also available at http://www.gnu.org/copyleft/gpl.html.
 from ovirt.node import base
+from ovirt.node.utils import console
 
 """
 This contains abstract UI Elements
@@ -723,7 +724,11 @@
                 txt = "(%s/%s) %s" % (idx + 1, len(self.transaction),
                                       tx_element.title)
                 self.add_update(txt)
-                self.plugin.dry_or(lambda: tx_element.commit())
+                with console.CaptureOutput() as captured:
+                    # Sometimes a tx_element is wrapping some code that
+                    # writes to stdout/stderr which scrambles the screen,
+                    # therefore we are capturing this
+                    self.plugin.dry_or(lambda: tx_element.commit())
             self.add_update("\nAll changes were applied successfully.")
         except Exception as e:
             self.logger.info("An exception during the transaction: %s" % e,
@@ -731,6 +736,11 @@
             self.add_update("\nAn error occurred while applying the changes:")
             self.add_update("%s" % e)
 
+        if captured.stderr.getvalue():
+            se = captured.stderr.getvalue()
+            if se:
+                self.add_update("Stderr: %s" % se)
+
 
 class AbstractUIBuilder(base.Base):
     """An abstract class
diff --git a/scripts/tui/src/ovirt/node/utils/console.py b/scripts/tui/src/ovirt/node/utils/console.py
index be3b02c..bdb22b4 100644
--- a/scripts/tui/src/ovirt/node/utils/console.py
+++ b/scripts/tui/src/ovirt/node/utils/console.py
@@ -19,6 +19,7 @@
 # MA  02110-1301, USA.  A copy of the GNU General Public License is
 # also available at http://www.gnu.org/copyleft/gpl.html.
 from ovirt.node import base
+import StringIO
 import sys
 import termios
 import traceback
@@ -83,7 +84,11 @@
             for idx, e in enumerate(self.transaction):
                 txt = "(%s/%s) %s" % (idx + 1, len(self.transaction), e.title)
                 self.add_update(txt)
-                self.plugin.dry_or(lambda: e.commit())
+                with CaptureOutput() as captured:
+                    # Sometimes a tx_element is wrapping some code that
+                    # writes to stdout/stderr which scrambles the screen,
+                    # therefore we are capturing this
+                    self.plugin.dry_or(lambda: e.commit())
             self.add_update("\nAll changes were applied successfully.")
         except Exception as e:
             self.add_update("\nAn error occurred while applying the changes:")
@@ -91,6 +96,11 @@
             self.logger.warning("'%s' on transaction '%s': %s - %s" %
                                 (type(e), self.transaction, e, e.message))
             self.logger.debug(str(traceback.format_exc()))
+
+        if captured.stderr.getvalue():
+            se = captured.stderr.getvalue()
+            if se:
+                self.add_update("Stderr: %s" % se)
 
 
 def getch():
@@ -114,3 +124,51 @@
     finally:
         termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
     return ch
+
+
+class CaptureOutput(base.Base):
+    """This context manager can be used to capture any output (from e.g. a
+    subprocess or wrongly configured loggers) to different streams
+
+    >>> import sys
+    >>> with CaptureOutput() as captured:
+    ...     sys.stdout.write("Hey!")
+    ...     sys.stderr.write("There!")
+    >>> captured.stdout.getvalue()
+    'Hey!'
+    >>> captured.stderr.getvalue()
+    'There!'
+    """
+
+    def __init__(self, stdout=None, stderr=None):
+        super(CaptureOutput, self).__init__()
+        self.stdout = stdout or StringIO.StringIO()
+        self.stderr = stderr or StringIO.StringIO()
+
+    def __enter__(self):
+        """Create redirections
+        """
+        self.logger.debug("Redirecting %s to %s" % (sys.stdout, self.stdout))
+        self.logger.debug("Redirecting %s to %s" % (sys.stderr, self.stderr))
+        self._stdout = sys.stdout
+        self._stderr = sys.stderr
+        sys.stdout = self.stdout
+        sys.stderr = self.stderr
+        return self
+
+    def __exit__(self, a, b, c):
+        """Remove all redirections
+        """
+        sys.stdout = self._stdout
+        sys.stderr = self._stderr
+        self.logger.debug("Removed redirections")
+        so = self.stdout.getvalue()
+        se = self.stderr.getvalue()
+        if so or se:
+            self.logger.info("Captured:")
+        else:
+            self.logger.info("Captured nothing")
+        if se:
+            self.logger.info("stderr: %s" % se)
+        if so:
+            self.logger.info("stdout: %s" % so)


--
To view, visit http://gerrit.ovirt.org/12478
To unsubscribe, visit http://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I78739975bf9290f650e1b163d68aedd0ce4ebf79
Gerrit-PatchSet: 1
Gerrit-Project: ovirt-node
Gerrit-Branch: master
Gerrit-Owner: Fabian Deutsch <fabiand at fedoraproject.org>



More information about the node-patches mailing list