diff --git a/autotools/build-bash-completion b/autotools/build-bash-completion
index 79258c2cc2b1e9f9e0a9a463182053599a169355..bcb1239d883c3785d22f7107840093b5e62df9c6 100755
--- a/autotools/build-bash-completion
+++ b/autotools/build-bash-completion
@@ -40,43 +40,6 @@ from ganeti import build
 from ganeti import _autoconf
 
 
-class ShellWriter:
-  """Helper class to write scripts with indentation.
-
-  """
-  INDENT_STR = "  "
-
-  def __init__(self, fh):
-    self._fh = fh
-    self._indent = 0
-
-  def IncIndent(self):
-    """Increase indentation level by 1.
-
-    """
-    self._indent += 1
-
-  def DecIndent(self):
-    """Decrease indentation level by 1.
-
-    """
-    assert self._indent > 0
-    self._indent -= 1
-
-  def Write(self, txt, *args):
-    """Write line to output file.
-
-    """
-    self._fh.write(self._indent * self.INDENT_STR)
-
-    if args:
-      self._fh.write(txt % args)
-    else:
-      self._fh.write(txt)
-
-    self._fh.write("\n")
-
-
 def WritePreamble(sw):
   """Writes the script preamble.
 
@@ -630,7 +593,7 @@ def GetCommands(filename, module):
 
 def main():
   buf = StringIO()
-  sw = ShellWriter(buf)
+  sw = utils.ShellWriter(buf)
 
   WritePreamble(sw)
 
diff --git a/lib/utils.py b/lib/utils.py
index 40f8fc460c1e0ccc2d20e69036a5cfb8c09ea317..6caa0fef5a0b08e1bf8e243bdbc17f1b41901425 100644
--- a/lib/utils.py
+++ b/lib/utils.py
@@ -1548,6 +1548,48 @@ def ShellQuoteArgs(args):
   return ' '.join([ShellQuote(i) for i in args])
 
 
+class ShellWriter:
+  """Helper class to write scripts with indentation.
+
+  """
+  INDENT_STR = "  "
+
+  def __init__(self, fh):
+    """Initializes this class.
+
+    """
+    self._fh = fh
+    self._indent = 0
+
+  def IncIndent(self):
+    """Increase indentation level by 1.
+
+    """
+    self._indent += 1
+
+  def DecIndent(self):
+    """Decrease indentation level by 1.
+
+    """
+    assert self._indent > 0
+    self._indent -= 1
+
+  def Write(self, txt, *args):
+    """Write line to output file.
+
+    """
+    assert self._indent >= 0
+
+    self._fh.write(self._indent * self.INDENT_STR)
+
+    if args:
+      self._fh.write(txt % args)
+    else:
+      self._fh.write(txt)
+
+    self._fh.write("\n")
+
+
 def ListVisibleFiles(path):
   """Returns a list of visible files in a directory.
 
diff --git a/test/ganeti.utils_unittest.py b/test/ganeti.utils_unittest.py
index 91c269d68ea2efe10650267a45fdd70a690d6992..5ff5fc9f77c7236a2718ff25cc1de864c605cdc3 100755
--- a/test/ganeti.utils_unittest.py
+++ b/test/ganeti.utils_unittest.py
@@ -38,6 +38,7 @@ import time
 import unittest
 import warnings
 import OpenSSL
+from cStringIO import StringIO
 
 import testutils
 from ganeti import constants
@@ -2242,5 +2243,48 @@ class TestIgnoreProcessNotFound(unittest.TestCase):
     self.assertFalse(utils.IgnoreProcessNotFound(os.kill, pid, 0))
 
 
+class TestShellWriter(unittest.TestCase):
+  def test(self):
+    buf = StringIO()
+    sw = utils.ShellWriter(buf)
+    sw.Write("#!/bin/bash")
+    sw.Write("if true; then")
+    sw.IncIndent()
+    try:
+      sw.Write("echo true")
+
+      sw.Write("for i in 1 2 3")
+      sw.Write("do")
+      sw.IncIndent()
+      try:
+        self.assertEqual(sw._indent, 2)
+        sw.Write("date")
+      finally:
+        sw.DecIndent()
+      sw.Write("done")
+    finally:
+      sw.DecIndent()
+    sw.Write("echo %s", utils.ShellQuote("Hello World"))
+    sw.Write("exit 0")
+
+    self.assertEqual(sw._indent, 0)
+
+    output = buf.getvalue()
+
+    self.assert_(output.endswith("\n"))
+
+    lines = output.splitlines()
+    self.assertEqual(len(lines), 9)
+    self.assertEqual(lines[0], "#!/bin/bash")
+    self.assert_(re.match(r"^\s+date$", lines[5]))
+    self.assertEqual(lines[7], "echo 'Hello World'")
+
+  def testEmpty(self):
+    buf = StringIO()
+    sw = utils.ShellWriter(buf)
+    sw = None
+    self.assertEqual(buf.getvalue(), "")
+
+
 if __name__ == '__main__':
   testutils.GanetiTestProgram()