diff --git a/htools/Ganeti/BasicTypes.hs b/htools/Ganeti/BasicTypes.hs
index ec3e138af7a8d4076671ef75c5f17265fd328a1f..55bab28588848679f353d45b50d5fe458657c65d 100644
--- a/htools/Ganeti/BasicTypes.hs
+++ b/htools/Ganeti/BasicTypes.hs
@@ -26,9 +26,19 @@ module Ganeti.BasicTypes
   , eitherToResult
   , annotateResult
   , annotateIOError
+  , select
+  , LookupResult(..)
+  , MatchPriority(..)
+  , lookupName
+  , goodLookupResult
+  , goodMatchPriority
+  , prefixMatch
+  , compareNameComponent
   ) where
 
 import Control.Monad
+import Data.Function
+import Data.List
 
 -- | This is similar to the JSON library Result type - /very/ similar,
 -- but we want to use it in multiple places, so we abstract it into a
@@ -78,3 +88,85 @@ annotateResult _ v = v
 annotateIOError :: String -> IOError -> IO (Result a)
 annotateIOError description exc =
   return . Bad $ description ++ ": " ++ show exc
+
+-- * Misc functionality
+
+-- | Return the first result with a True condition, or the default otherwise.
+select :: a            -- ^ default result
+       -> [(Bool, a)]  -- ^ list of \"condition, result\"
+       -> a            -- ^ first result which has a True condition, or default
+select def = maybe def snd . find fst
+
+-- * Lookup of partial names functionality
+
+-- | The priority of a match in a lookup result.
+data MatchPriority = ExactMatch
+                   | MultipleMatch
+                   | PartialMatch
+                   | FailMatch
+                   deriving (Show, Read, Enum, Eq, Ord)
+
+-- | The result of a name lookup in a list.
+data LookupResult = LookupResult
+  { lrMatchPriority :: MatchPriority -- ^ The result type
+  -- | Matching value (for ExactMatch, PartialMatch), Lookup string otherwise
+  , lrContent :: String
+  } deriving (Show, Read)
+
+-- | Lookup results have an absolute preference ordering.
+instance Eq LookupResult where
+  (==) = (==) `on` lrMatchPriority
+
+instance Ord LookupResult where
+  compare = compare `on` lrMatchPriority
+
+-- | Check for prefix matches in names.
+-- Implemented in Ganeti core utils.text.MatchNameComponent
+-- as the regexp r"^%s(\..*)?$" % re.escape(key)
+prefixMatch :: String  -- ^ Lookup
+            -> String  -- ^ Full name
+            -> Bool    -- ^ Whether there is a prefix match
+prefixMatch = isPrefixOf . (++ ".")
+
+-- | Is the lookup priority a "good" one?
+goodMatchPriority :: MatchPriority -> Bool
+goodMatchPriority ExactMatch = True
+goodMatchPriority PartialMatch = True
+goodMatchPriority _ = False
+
+-- | Is the lookup result an actual match?
+goodLookupResult :: LookupResult -> Bool
+goodLookupResult = goodMatchPriority . lrMatchPriority
+
+-- | Compares a canonical name and a lookup string.
+compareNameComponent :: String        -- ^ Canonical (target) name
+                     -> String        -- ^ Partial (lookup) name
+                     -> LookupResult  -- ^ Result of the lookup
+compareNameComponent cnl lkp =
+  select (LookupResult FailMatch lkp)
+  [ (cnl == lkp          , LookupResult ExactMatch cnl)
+  , (prefixMatch lkp cnl , LookupResult PartialMatch cnl)
+  ]
+
+-- | Lookup a string and choose the best result.
+chooseLookupResult :: String       -- ^ Lookup key
+                   -> String       -- ^ String to compare to the lookup key
+                   -> LookupResult -- ^ Previous result
+                   -> LookupResult -- ^ New result
+chooseLookupResult lkp cstr old =
+  -- default: use class order to pick the minimum result
+  select (min new old)
+  -- special cases:
+  -- short circuit if the new result is an exact match
+  [ (lrMatchPriority new == ExactMatch, new)
+  -- if both are partial matches generate a multiple match
+  , (partial2, LookupResult MultipleMatch lkp)
+  ] where new = compareNameComponent cstr lkp
+          partial2 = all ((PartialMatch==) . lrMatchPriority) [old, new]
+
+-- | Find the canonical name for a lookup string in a list of names.
+lookupName :: [String]      -- ^ List of keys
+           -> String        -- ^ Lookup string
+           -> LookupResult  -- ^ Result of the lookup
+lookupName l s = foldr (chooseLookupResult s)
+                       (LookupResult FailMatch s) l
diff --git a/htools/Ganeti/HTools/CLI.hs b/htools/Ganeti/HTools/CLI.hs
index 4636fd7a0446f24fafb3f372bc34dd8677a6e208..29f17288fcf6f3718ec000baa9c9a38b7cfe9876 100644
--- a/htools/Ganeti/HTools/CLI.hs
+++ b/htools/Ganeti/HTools/CLI.hs
@@ -100,7 +100,7 @@ import qualified Ganeti.HTools.Node as Node
 import qualified Ganeti.Constants as C
 import Ganeti.HTools.Types
 import Ganeti.HTools.Utils
-import Ganeti.HTools.Loader
+import Ganeti.BasicTypes
 
 -- * Constants
 
diff --git a/htools/Ganeti/HTools/Loader.hs b/htools/Ganeti/HTools/Loader.hs
index 5a5da6542a38a33236e3c39e1e82ad28044c148b..851c84bb9f83deffc22787eea9023f9477287d48 100644
--- a/htools/Ganeti/HTools/Loader.hs
+++ b/htools/Ganeti/HTools/Loader.hs
@@ -30,8 +30,6 @@ module Ganeti.HTools.Loader
   ( mergeData
   , checkData
   , assignIndices
-  , lookupName
-  , goodLookupResult
   , lookupNode
   , lookupInstance
   , lookupGroup
@@ -40,14 +38,9 @@ module Ganeti.HTools.Loader
   , Request(..)
   , ClusterData(..)
   , emptyCluster
-  , compareNameComponent
-  , prefixMatch
-  , LookupResult(..)
-  , MatchPriority(..)
   ) where
 
 import Data.List
-import Data.Function
 import qualified Data.Map as M
 import Text.Printf (printf)
 
@@ -57,6 +50,7 @@ import qualified Ganeti.HTools.Node as Node
 import qualified Ganeti.HTools.Group as Group
 import qualified Ganeti.HTools.Cluster as Cluster
 
+import Ganeti.BasicTypes
 import Ganeti.HTools.Types
 import Ganeti.HTools.Utils
 
@@ -94,27 +88,6 @@ data ClusterData = ClusterData
   , cdIPolicy   :: IPolicy       -- ^ The cluster instance policy
   } deriving (Show, Read, Eq)
 
--- | The priority of a match in a lookup result.
-data MatchPriority = ExactMatch
-                   | MultipleMatch
-                   | PartialMatch
-                   | FailMatch
-                   deriving (Show, Read, Enum, Eq, Ord)
-
--- | The result of a name lookup in a list.
-data LookupResult = LookupResult
-  { lrMatchPriority :: MatchPriority -- ^ The result type
-  -- | Matching value (for ExactMatch, PartialMatch), Lookup string otherwise
-  , lrContent :: String
-  } deriving (Show, Read)
-
--- | Lookup results have an absolute preference ordering.
-instance Eq LookupResult where
-  (==) = (==) `on` lrMatchPriority
-
-instance Ord LookupResult where
-  compare = compare `on` lrMatchPriority
-
 -- | An empty cluster.
 emptyCluster :: ClusterData
 emptyCluster = ClusterData Container.empty Container.empty Container.empty []
@@ -143,57 +116,6 @@ lookupGroup ktg nname gname =
     Nothing -> fail $ "Unknown group '" ++ gname ++ "' for node " ++ nname
     Just idx -> return idx
 
--- | Check for prefix matches in names.
--- Implemented in Ganeti core utils.text.MatchNameComponent
--- as the regexp r"^%s(\..*)?$" % re.escape(key)
-prefixMatch :: String  -- ^ Lookup
-            -> String  -- ^ Full name
-            -> Bool    -- ^ Whether there is a prefix match
-prefixMatch = isPrefixOf . (++ ".")
-
--- | Is the lookup priority a "good" one?
-goodMatchPriority :: MatchPriority -> Bool
-goodMatchPriority ExactMatch = True
-goodMatchPriority PartialMatch = True
-goodMatchPriority _ = False
-
--- | Is the lookup result an actual match?
-goodLookupResult :: LookupResult -> Bool
-goodLookupResult = goodMatchPriority . lrMatchPriority
-
--- | Compares a canonical name and a lookup string.
-compareNameComponent :: String        -- ^ Canonical (target) name
-                     -> String        -- ^ Partial (lookup) name
-                     -> LookupResult  -- ^ Result of the lookup
-compareNameComponent cnl lkp =
-  select (LookupResult FailMatch lkp)
-  [ (cnl == lkp          , LookupResult ExactMatch cnl)
-  , (prefixMatch lkp cnl , LookupResult PartialMatch cnl)
-  ]
-
--- | Lookup a string and choose the best result.
-chooseLookupResult :: String       -- ^ Lookup key
-                   -> String       -- ^ String to compare to the lookup key
-                   -> LookupResult -- ^ Previous result
-                   -> LookupResult -- ^ New result
-chooseLookupResult lkp cstr old =
-  -- default: use class order to pick the minimum result
-  select (min new old)
-  -- special cases:
-  -- short circuit if the new result is an exact match
-  [ (lrMatchPriority new == ExactMatch, new)
-  -- if both are partial matches generate a multiple match
-  , (partial2, LookupResult MultipleMatch lkp)
-  ] where new = compareNameComponent cstr lkp
-          partial2 = all ((PartialMatch==) . lrMatchPriority) [old, new]
-
--- | Find the canonical name for a lookup string in a list of names.
-lookupName :: [String]      -- ^ List of keys
-           -> String        -- ^ Lookup string
-           -> LookupResult  -- ^ Result of the lookup
-lookupName l s = foldr (chooseLookupResult s)
-                       (LookupResult FailMatch s) l
-
 -- | Given a list of elements (and their names), assign indices to them.
 assignIndices :: (Element a) =>
                  [(String, a)]
diff --git a/htools/Ganeti/HTools/QC.hs b/htools/Ganeti/HTools/QC.hs
index d056a9c95ceb5d0df0fb1d36cd8ab9cb05629053..c00e22d1523391b1b1907102f0f16b136958154b 100644
--- a/htools/Ganeti/HTools/QC.hs
+++ b/htools/Ganeti/HTools/QC.hs
@@ -56,6 +56,7 @@ import qualified Text.JSON as J
 import qualified Data.Map
 import qualified Data.IntMap as IntMap
 
+import qualified Ganeti.BasicTypes as BasicTypes
 import qualified Ganeti.OpCodes as OpCodes
 import qualified Ganeti.Jobs as Jobs
 import qualified Ganeti.Luxi as Luxi
@@ -1517,14 +1518,14 @@ prop_Loader_mergeData ns =
 -- | Check that compareNameComponent on equal strings works.
 prop_Loader_compareNameComponent_equal :: String -> Bool
 prop_Loader_compareNameComponent_equal s =
-  Loader.compareNameComponent s s ==
-    Loader.LookupResult Loader.ExactMatch s
+  BasicTypes.compareNameComponent s s ==
+    BasicTypes.LookupResult BasicTypes.ExactMatch s
 
 -- | Check that compareNameComponent on prefix strings works.
 prop_Loader_compareNameComponent_prefix :: NonEmptyList Char -> String -> Bool
 prop_Loader_compareNameComponent_prefix (NonEmpty s1) s2 =
-  Loader.compareNameComponent (s1 ++ "." ++ s2) s1 ==
-    Loader.LookupResult Loader.PartialMatch s1
+  BasicTypes.compareNameComponent (s1 ++ "." ++ s2) s1 ==
+    BasicTypes.LookupResult BasicTypes.PartialMatch s1
 
 testSuite "Loader"
             [ 'prop_Loader_lookupNode
diff --git a/htools/Ganeti/HTools/Utils.hs b/htools/Ganeti/HTools/Utils.hs
index aaf4fb093e17183f4dae10973b0c277ff1f64c61..2b21518c4177a51552ce357cc39e92507f5d2a4e 100644
--- a/htools/Ganeti/HTools/Utils.hs
+++ b/htools/Ganeti/HTools/Utils.hs
@@ -132,13 +132,6 @@ if' :: Bool -- ^ condition
 if' True x _ = x
 if' _    _ y = y
 
--- | Return the first result with a True condition, or the default otherwise.
-select :: a            -- ^ default result
-       -> [(Bool, a)]  -- ^ list of \"condition, result\"
-       -> a            -- ^ first result which has a True condition, or default
-select def = maybe def snd . find fst
-
-
 -- * Parsing utility functions
 
 -- | Parse results from readsPrec.