diff --git a/htest/Test/Ganeti/Utils.hs b/htest/Test/Ganeti/Utils.hs
index baa5e099d95c05c01e9237693f3f30192643d941..461d1b27eb959852aea3af82d60d6440e92a0937 100644
--- a/htest/Test/Ganeti/Utils.hs
+++ b/htest/Test/Ganeti/Utils.hs
@@ -31,6 +31,7 @@ module Test.Ganeti.Utils (testUtils) where
 import Test.QuickCheck hiding (Result)
 import Test.HUnit
 
+import Data.Char (isSpace)
 import Data.List
 import qualified Text.JSON as J
 
@@ -202,6 +203,22 @@ prop_niceSortKey_equiv =
                                                     zip numbers names)
   ]
 
+-- | Tests 'rstripSpace'.
+prop_rStripSpace :: NonEmptyList Char -> Property
+prop_rStripSpace (NonEmpty str) =
+  forAll (resize 50 $ listOf1 (arbitrary `suchThat` isSpace)) $ \whitespace ->
+  conjoin [ printTestCase "arb. string last char is not space" $
+              case rStripSpace str of
+                [] -> True
+                xs -> not . isSpace $ last xs
+          , printTestCase "whitespace suffix is stripped" $
+              rStripSpace str ==? rStripSpace (str ++ whitespace)
+          , printTestCase "whitespace reduced to null" $
+              rStripSpace whitespace ==? ""
+          , printTestCase "idempotent on empty strings" $
+              rStripSpace "" ==? ""
+          ]
+
 -- | Test list for the Utils module.
 testSuite "Utils"
             [ 'prop_commaJoinSplit
@@ -217,4 +234,5 @@ testSuite "Utils"
             , 'prop_niceSort_generic
             , 'prop_niceSort_numbers
             , 'prop_niceSortKey_equiv
+            , 'prop_rStripSpace
             ]
diff --git a/htools/Ganeti/Ssconf.hs b/htools/Ganeti/Ssconf.hs
index 6853bb15a7c3da79d614c53bd88090e63d5564d0..20cfeb39632172d4b808172ffeac7aebf82b141a 100644
--- a/htools/Ganeti/Ssconf.hs
+++ b/htools/Ganeti/Ssconf.hs
@@ -38,7 +38,6 @@ import Ganeti.THH
 
 import Control.Exception
 import Control.Monad (liftM)
-import Data.Char (isSpace)
 import Data.Maybe (fromMaybe)
 import qualified Network.Socket as Socket
 import System.FilePath ((</>))
@@ -116,11 +115,6 @@ readSSConfFile optpath def key = do
             keyToFilename (fromMaybe dpath optpath) $ key
   return (liftM (take maxFileSize) result)
 
--- | Strip space characthers (including newline). As this is
--- expensive, should only be run on small strings.
-rstripSpace :: String -> String
-rstripSpace = reverse . dropWhile isSpace . reverse
-
 -- | Parses a string containing an IP family
 parseIPFamily :: Int -> Result Socket.Family
 parseIPFamily fam | fam == C.ip4Family = Ok Socket.AF_INET
@@ -131,5 +125,5 @@ parseIPFamily fam | fam == C.ip4Family = Ok Socket.AF_INET
 getPrimaryIPFamily :: Maybe FilePath -> IO (Result Socket.Family)
 getPrimaryIPFamily optpath = do
   result <- readSSConfFile optpath (Just (show C.ip4Family)) SSPrimaryIpFamily
-  return (liftM rstripSpace result >>=
+  return (liftM rStripSpace result >>=
           tryRead "Parsing af_family" >>= parseIPFamily)
diff --git a/htools/Ganeti/Utils.hs b/htools/Ganeti/Utils.hs
index 9636a34d2266124efa37a40bd74b6de8ce373dd8..9f7e9c579cce17d98f25fbe5ac26464ab005b5d9 100644
--- a/htools/Ganeti/Utils.hs
+++ b/htools/Ganeti/Utils.hs
@@ -43,9 +43,10 @@ module Ganeti.Utils
   , exitErr
   , exitWhen
   , exitUnless
+  , rStripSpace
   ) where
 
-import Data.Char (toUpper, isAlphaNum, isDigit)
+import Data.Char (toUpper, isAlphaNum, isDigit, isSpace)
 import Data.Function (on)
 import Data.List
 
@@ -271,3 +272,8 @@ niceSortKey :: (a -> String) -> [a] -> [a]
 niceSortKey keyfn =
   map snd . sortBy (compare `on` fst) .
   map (\s -> (fst . extractKey [] $ keyfn s, s))
+
+-- | Strip space characthers (including newline). As this is
+-- expensive, should only be run on small strings.
+rStripSpace :: String -> String
+rStripSpace = reverse . dropWhile isSpace . reverse