diff --git a/Ganeti/HTools/CLI.hs b/Ganeti/HTools/CLI.hs
index 696333aed6d001e13ce19ffd24f1f27e04574b81..cfffee3e724c30b115304b6145100e4b8484ed50 100644
--- a/Ganeti/HTools/CLI.hs
+++ b/Ganeti/HTools/CLI.hs
@@ -39,8 +39,7 @@ module Ganeti.HTools.CLI
     , oOneline
     , oNoHeaders
     , oOutputDir
-    , oNodeFile
-    , oInstFile
+    , oDataFile
     , oNodeSim
     , oRapiMaster
     , oLuxiSocket
@@ -89,10 +88,7 @@ data Options = Options
     , optOneline     :: Bool           -- ^ Switch output to a single line
     , optOutPath     :: FilePath       -- ^ Path to the output directory
     , optNoHeaders   :: Bool           -- ^ Do not show a header line
-    , optNodeFile    :: FilePath       -- ^ Path to the nodes file
-    , optNodeSet     :: Bool           -- ^ The nodes have been set by options
-    , optInstFile    :: FilePath       -- ^ Path to the instances file
-    , optInstSet     :: Bool           -- ^ The insts have been set by options
+    , optDataFile    :: Maybe FilePath -- ^ Path to the cluster data file
     , optNodeSim     :: Maybe String   -- ^ Cluster simulation mode
     , optMaxLength   :: Int            -- ^ Stop after this many steps
     , optMaster      :: String         -- ^ Collect data from RAPI
@@ -122,10 +118,7 @@ defaultOptions  = Options
  , optOneline     = False
  , optNoHeaders   = False
  , optOutPath     = "."
- , optNodeFile    = "nodes"
- , optNodeSet     = False
- , optInstFile    = "instances"
- , optInstSet     = False
+ , optDataFile    = Nothing
  , optNodeSim     = Nothing
  , optMaxLength   = -1
  , optMaster      = ""
@@ -186,17 +179,10 @@ oOutputDir = Option "d" ["output-dir"]
              (ReqArg (\ d opts -> Ok opts { optOutPath = d }) "PATH")
              "directory in which to write output files"
 
-oNodeFile :: OptType
-oNodeFile = Option "n" ["nodes"]
-            (ReqArg (\ f o -> Ok o { optNodeFile = f,
-                                     optNodeSet = True }) "FILE")
-            "the node list FILE"
-
-oInstFile :: OptType
-oInstFile = Option "i" ["instances"]
-            (ReqArg (\ f o -> Ok o { optInstFile = f,
-                                     optInstSet = True }) "FILE")
-            "the instance list FILE"
+oDataFile :: OptType
+oDataFile = Option "t" ["text-data"]
+            (ReqArg (\ f o -> Ok o { optDataFile = Just f }) "FILE")
+            "the cluster data FILE"
 
 oNodeSim :: OptType
 oNodeSim = Option "" ["simulate"]
diff --git a/Ganeti/HTools/ExtLoader.hs b/Ganeti/HTools/ExtLoader.hs
index 94c787bd08aff7ed0a9ec0c343cd1be9c2312dc0..a54da1abb038c1146b60f0320b7427cfa6eb8cc1 100644
--- a/Ganeti/HTools/ExtLoader.hs
+++ b/Ganeti/HTools/ExtLoader.hs
@@ -35,7 +35,6 @@ module Ganeti.HTools.ExtLoader
 
 import Data.Maybe (isJust, fromJust)
 import Monad
-import System.Posix.Env
 import System.IO
 import System
 import Text.Printf (printf, hPrintf)
@@ -54,15 +53,6 @@ import Ganeti.HTools.Types
 import Ganeti.HTools.CLI
 import Ganeti.HTools.Utils (sepSplit, tryRead)
 
--- | Parse the environment and return the node\/instance names.
---
--- This also hardcodes here the default node\/instance file names.
-parseEnv :: () -> IO (String, String)
-parseEnv () = do
-  a <- getEnvDefault "HTOOLS_NODES" "nodes"
-  b <- getEnvDefault "HTOOLS_INSTANCES" "instances"
-  return (a, b)
-
 -- | Error beautifier
 wrapIO :: IO (Result a) -> IO (Result a)
 wrapIO = flip catch (return . Bad . show)
@@ -85,19 +75,15 @@ parseUtilisation line =
 loadExternalData :: Options
                  -> IO (Node.List, Instance.List, [String], String)
 loadExternalData opts = do
-  (env_node, env_inst) <- parseEnv ()
-  let nodef = if optNodeSet opts then optNodeFile opts
-              else env_node
-      instf = if optInstSet opts then optInstFile opts
-              else env_inst
-      mhost = optMaster opts
+  let mhost = optMaster opts
       lsock = optLuxi opts
+      tfile = optDataFile opts
       simdata = optNodeSim opts
       setRapi = mhost /= ""
       setLuxi = isJust lsock
       setSim = isJust simdata
-      setFiles = optNodeSet opts || optInstSet opts
-      allSet = filter id [setRapi, setLuxi, setFiles]
+      setFile = isJust tfile
+      allSet = filter id [setRapi, setLuxi, setFile]
       exTags = case optExTags opts of
                  Nothing -> []
                  Just etl -> map (++ ":") etl
@@ -128,7 +114,8 @@ loadExternalData opts = do
 #endif
           | setLuxi -> wrapIO $ Luxi.loadData $ fromJust lsock
           | setSim -> Simu.loadData $ fromJust simdata
-          | otherwise -> wrapIO $ Text.loadData nodef instf
+          | setFile -> wrapIO $ Text.loadData $ fromJust tfile
+          | otherwise -> return $ Bad "No backend selected! Exiting."
 
   let ldresult = input_data >>= Loader.mergeData util_data' exTags
   (loaded_nl, il, tags, csf) <-
diff --git a/Ganeti/HTools/Text.hs b/Ganeti/HTools/Text.hs
index f686d979120fed7bd40bfe9f96e4bb45b5b1531c..599c07cde97f0e393164bb13bb78888e1e7d9076 100644
--- a/Ganeti/HTools/Text.hs
+++ b/Ganeti/HTools/Text.hs
@@ -87,16 +87,19 @@ loadTabular lines_data convert_fn = do
   kerows <- mapM convert_fn rows
   return $ assignIndices kerows
 
--- | Builds the cluster data from node\/instance files.
-loadData :: String -- ^ Node data in string format
-         -> String -- ^ Instance data in string format
+-- | Builds the cluster data from text input.
+loadData :: String -- ^ Path to the text file
          -> IO (Result (Node.AssocList, Instance.AssocList, [String]))
-loadData nfile ifile = do -- IO monad
-  ndata <- readFile nfile
-  idata <- readFile ifile
+loadData afile = do -- IO monad
+  fdata <- readFile afile
+  let flines = lines fdata
+      (nlines, ilines) = break null flines
   return $ do
+    ifixed <- case ilines of
+                [] -> Bad "Invalid format of the input file (no instance data)"
+                _:xs -> Ok xs
     {- node file: name t_mem n_mem f_mem t_disk f_disk -}
-    (ktn, nl) <- loadTabular (lines ndata) loadNode
+    (ktn, nl) <- loadTabular nlines loadNode
     {- instance file: name mem disk status pnode snode -}
-    (_, il) <- loadTabular (lines idata) (loadInst ktn)
+    (_, il) <- loadTabular ifixed (loadInst ktn)
     return (nl, il, [])
diff --git a/hbal.hs b/hbal.hs
index 1c3f9fe49459f8b13ed30a091f519c14e1e08a94..ae4cb80c9b393546dd26feff640a50f91cd5a6b0 100644
--- a/hbal.hs
+++ b/hbal.hs
@@ -59,8 +59,7 @@ options =
     , oPrintInsts
     , oPrintCommands
     , oOneline
-    , oNodeFile
-    , oInstFile
+    , oDataFile
     , oRapiMaster
     , oLuxiSocket
     , oExecJobs
diff --git a/hspace.hs b/hspace.hs
index 20818a51d891e584b8510d0c46c525322ae05bd8..dcaf4001642a947fed753f966da5ddbb96bf6553 100644
--- a/hspace.hs
+++ b/hspace.hs
@@ -50,8 +50,7 @@ import Ganeti.HTools.ExtLoader
 options :: [OptType]
 options =
     [ oPrintNodes
-    , oNodeFile
-    , oInstFile
+    , oDataFile
     , oNodeSim
     , oRapiMaster
     , oLuxiSocket