diff --git a/htest/Test/Ganeti/Utils.hs b/htest/Test/Ganeti/Utils.hs
index 461d1b27eb959852aea3af82d60d6440e92a0937..cb357a14cd9632675d4923a28007e8c8c18cd0db 100644
--- a/htest/Test/Ganeti/Utils.hs
+++ b/htest/Test/Ganeti/Utils.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TemplateHaskell, CPP #-}
 {-# OPTIONS_GHC -fno-warn-orphans #-}
 
 {-| Unittests for ganeti-htools.
@@ -34,11 +34,15 @@ import Test.HUnit
 import Data.Char (isSpace)
 import Data.List
 import qualified Text.JSON as J
+#ifndef NO_REGEX_PCRE
+import Text.Regex.PCRE
+#endif
 
 import Test.Ganeti.TestHelper
 import Test.Ganeti.TestCommon
 
 import Ganeti.BasicTypes
+import qualified Ganeti.Constants as C
 import qualified Ganeti.JSON as JSON
 import Ganeti.Utils
 
@@ -219,6 +223,14 @@ prop_rStripSpace (NonEmpty str) =
               rStripSpace "" ==? ""
           ]
 
+#ifndef NO_REGEX_PCRE
+-- | Tests that the newUUID function produces valid UUIDs.
+case_new_uuid :: Assertion
+case_new_uuid = do
+  uuid <- newUUID
+  assertBool "newUUID" $ uuid =~ C.uuidRegex
+#endif
+
 -- | Test list for the Utils module.
 testSuite "Utils"
             [ 'prop_commaJoinSplit
@@ -235,4 +247,7 @@ testSuite "Utils"
             , 'prop_niceSort_numbers
             , 'prop_niceSortKey_equiv
             , 'prop_rStripSpace
+#ifndef NO_REGEX_PCRE
+            , 'case_new_uuid
+#endif
             ]
diff --git a/htools/Ganeti/Utils.hs b/htools/Ganeti/Utils.hs
index 9f7e9c579cce17d98f25fbe5ac26464ab005b5d9..eed65dd59faca26c302a795964772fa4dd937090 100644
--- a/htools/Ganeti/Utils.hs
+++ b/htools/Ganeti/Utils.hs
@@ -44,6 +44,7 @@ module Ganeti.Utils
   , exitWhen
   , exitUnless
   , rStripSpace
+  , newUUID
   ) where
 
 import Data.Char (toUpper, isAlphaNum, isDigit, isSpace)
@@ -53,6 +54,7 @@ import Data.List
 import Debug.Trace
 
 import Ganeti.BasicTypes
+import qualified Ganeti.Constants as C
 import System.IO
 import System.Exit
 
@@ -277,3 +279,11 @@ niceSortKey keyfn =
 -- expensive, should only be run on small strings.
 rStripSpace :: String -> String
 rStripSpace = reverse . dropWhile isSpace . reverse
+
+-- | Returns a random UUID.
+-- This is a Linux-specific method as it uses the /proc filesystem.
+newUUID :: IO String
+newUUID = do
+  contents <- readFile C.randomUuidFile
+  let stripNewlines = reverse . dropWhile (=='\n') . reverse
+  return $! stripNewlines $ take 128 contents
diff --git a/lib/constants.py b/lib/constants.py
index 900b4bc476636a96e538008a8c555f47a708ccba..2d106f193f7d601f62a9df69987bd1e4da18fdd5 100644
--- a/lib/constants.py
+++ b/lib/constants.py
@@ -2210,5 +2210,11 @@ NDS_NODE_DAEMON_CERTIFICATE = "node_daemon_certificate"
 NDS_SSCONF = "ssconf"
 NDS_START_NODE_DAEMON = "start_node_daemon"
 
+# Path generating random UUID
+RANDOM_UUID_FILE = "/proc/sys/kernel/random/uuid"
+
+# Regex string for verifying a UUID
+UUID_REGEX = "^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$"
+
 # Do not re-export imported modules
 del re, _vcsversion, _autoconf, socket, pathutils, compat
diff --git a/lib/utils/__init__.py b/lib/utils/__init__.py
index ab7225ff69ac60bf0f1d7cba0d7c7b6519f5d3a8..69cc0a3f9852accb5d975e4ecadc0af0386c2478 100644
--- a/lib/utils/__init__.py
+++ b/lib/utils/__init__.py
@@ -59,8 +59,7 @@ from ganeti.utils.x509 import *
 
 _VALID_SERVICE_NAME_RE = re.compile("^[-_.a-zA-Z0-9]{1,128}$")
 
-UUID_RE = re.compile("^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-"
-                     "[a-f0-9]{4}-[a-f0-9]{12}$")
+UUID_RE = re.compile(constants.UUID_REGEX)
 
 
 def ForceDictType(target, key_types, allowed_values=None):
diff --git a/lib/utils/io.py b/lib/utils/io.py
index bb0a1237c5a5e95999c042f818027369eaaace2c..f9675a8478e0660f5f11b2f9bf50e9b898550a8b 100644
--- a/lib/utils/io.py
+++ b/lib/utils/io.py
@@ -35,10 +35,6 @@ from ganeti import constants
 from ganeti import pathutils
 from ganeti.utils import filelock
 
-
-#: Path generating random UUID
-_RANDOM_UUID_FILE = "/proc/sys/kernel/random/uuid"
-
 #: Directory used by fsck(8) to store recovered data, usually at a file
 #: system's root directory
 _LOST_AND_FOUND = "lost+found"
@@ -1029,7 +1025,7 @@ def NewUUID():
   @rtype: str
 
   """
-  return ReadFile(_RANDOM_UUID_FILE, size=128).rstrip("\n")
+  return ReadFile(constants.RANDOM_UUID_FILE, size=128).rstrip("\n")
 
 
 class TemporaryFileManager(object):