Add function for generating UUIDs in the Haskell codebase
authorMichele Tartara <mtartara@google.com>
Thu, 20 Dec 2012 09:03:15 +0000 (09:03 +0000)
committerMichele Tartara <mtartara@google.com>
Thu, 20 Dec 2012 16:16:25 +0000 (17:16 +0100)
Its first use will be to generate the salt for ConfD requests of the Haskell
client, as in the Python client.

Unit test added as well.

Signed-off-by: Michele Tartara <mtartara@google.com>
Reviewed-by: Iustin Pop <iustin@google.com>

htest/Test/Ganeti/Utils.hs
htools/Ganeti/Utils.hs
lib/constants.py
lib/utils/__init__.py
lib/utils/io.py

index 461d1b2..cb357a1 100644 (file)
@@ -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
             ]
index 9f7e9c5..eed65dd 100644 (file)
@@ -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
index 900b4bc..2d106f1 100644 (file)
@@ -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
index ab7225f..69cc0a3 100644 (file)
@@ -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):
index bb0a123..f9675a8 100644 (file)
@@ -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):