Statistics
| Branch: | Tag: | Revision:

root / src / Ganeti / HTools / Backend / Luxi.hs @ d605e261

History | View | Annotate | Download (11.7 kB)

1 6583e677 Iustin Pop
{-| Implementation of the LUXI loader.
2 53ec9022 Iustin Pop
3 53ec9022 Iustin Pop
-}
4 53ec9022 Iustin Pop
5 53ec9022 Iustin Pop
{-
6 53ec9022 Iustin Pop
7 72747d91 Iustin Pop
Copyright (C) 2009, 2010, 2011, 2012, 2013 Google Inc.
8 53ec9022 Iustin Pop
9 53ec9022 Iustin Pop
This program is free software; you can redistribute it and/or modify
10 53ec9022 Iustin Pop
it under the terms of the GNU General Public License as published by
11 53ec9022 Iustin Pop
the Free Software Foundation; either version 2 of the License, or
12 53ec9022 Iustin Pop
(at your option) any later version.
13 53ec9022 Iustin Pop
14 53ec9022 Iustin Pop
This program is distributed in the hope that it will be useful, but
15 53ec9022 Iustin Pop
WITHOUT ANY WARRANTY; without even the implied warranty of
16 53ec9022 Iustin Pop
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 53ec9022 Iustin Pop
General Public License for more details.
18 53ec9022 Iustin Pop
19 53ec9022 Iustin Pop
You should have received a copy of the GNU General Public License
20 53ec9022 Iustin Pop
along with this program; if not, write to the Free Software
21 53ec9022 Iustin Pop
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 53ec9022 Iustin Pop
02110-1301, USA.
23 53ec9022 Iustin Pop
24 53ec9022 Iustin Pop
-}
25 53ec9022 Iustin Pop
26 879d9290 Iustin Pop
module Ganeti.HTools.Backend.Luxi
27 ebf38064 Iustin Pop
  ( loadData
28 ebf38064 Iustin Pop
  , parseData
29 ebf38064 Iustin Pop
  ) where
30 53ec9022 Iustin Pop
31 53ec9022 Iustin Pop
import qualified Control.Exception as E
32 7adb7dff Iustin Pop
import Control.Monad (liftM)
33 53ec9022 Iustin Pop
import Text.JSON.Types
34 39420403 Iustin Pop
import qualified Text.JSON
35 53ec9022 Iustin Pop
36 01e52493 Iustin Pop
import Ganeti.BasicTypes
37 7adb7dff Iustin Pop
import Ganeti.Errors
38 6583e677 Iustin Pop
import qualified Ganeti.Luxi as L
39 4cab6703 Iustin Pop
import qualified Ganeti.Query.Language as Qlang
40 53ec9022 Iustin Pop
import Ganeti.HTools.Loader
41 53ec9022 Iustin Pop
import Ganeti.HTools.Types
42 a679e9dc Iustin Pop
import qualified Ganeti.HTools.Group as Group
43 53ec9022 Iustin Pop
import qualified Ganeti.HTools.Node as Node
44 53ec9022 Iustin Pop
import qualified Ganeti.HTools.Instance as Instance
45 f3baf5ef Iustin Pop
import Ganeti.JSON
46 53ec9022 Iustin Pop
47 3603605a Iustin Pop
{-# ANN module "HLint: ignore Eta reduce" #-}
48 3603605a Iustin Pop
49 53ec9022 Iustin Pop
-- * Utility functions
50 53ec9022 Iustin Pop
51 92678b3c Iustin Pop
-- | Get values behind \"data\" part of the result.
52 92678b3c Iustin Pop
getData :: (Monad m) => JSValue -> m JSValue
53 d12f50b2 Iustin Pop
getData (JSObject o) = fromObj (fromJSObject o) "data"
54 d12f50b2 Iustin Pop
getData x = fail $ "Invalid input, expected dict entry but got " ++ show x
55 d12f50b2 Iustin Pop
56 d12f50b2 Iustin Pop
-- | Converts a (status, value) into m value, if possible.
57 d12f50b2 Iustin Pop
parseQueryField :: (Monad m) => JSValue -> m (JSValue, JSValue)
58 d12f50b2 Iustin Pop
parseQueryField (JSArray [status, result]) = return (status, result)
59 d12f50b2 Iustin Pop
parseQueryField o =
60 ebf38064 Iustin Pop
  fail $ "Invalid query field, expected (status, value) but got " ++ show o
61 d12f50b2 Iustin Pop
62 d12f50b2 Iustin Pop
-- | Parse a result row.
63 d12f50b2 Iustin Pop
parseQueryRow :: (Monad m) => JSValue -> m [(JSValue, JSValue)]
64 d12f50b2 Iustin Pop
parseQueryRow (JSArray arr) = mapM parseQueryField arr
65 d12f50b2 Iustin Pop
parseQueryRow o =
66 ebf38064 Iustin Pop
  fail $ "Invalid query row result, expected array but got " ++ show o
67 d12f50b2 Iustin Pop
68 d12f50b2 Iustin Pop
-- | Parse an overall query result and get the [(status, value)] list
69 d12f50b2 Iustin Pop
-- for each element queried.
70 d12f50b2 Iustin Pop
parseQueryResult :: (Monad m) => JSValue -> m [[(JSValue, JSValue)]]
71 d12f50b2 Iustin Pop
parseQueryResult (JSArray arr) = mapM parseQueryRow arr
72 d12f50b2 Iustin Pop
parseQueryResult o =
73 ebf38064 Iustin Pop
  fail $ "Invalid query result, expected array but got " ++ show o
74 92678b3c Iustin Pop
75 92678b3c Iustin Pop
-- | Prepare resulting output as parsers expect it.
76 260d0bda Agata Murawska
extractArray :: (Monad m) => JSValue -> m [[(JSValue, JSValue)]]
77 d12f50b2 Iustin Pop
extractArray v =
78 260d0bda Agata Murawska
  getData v >>= parseQueryResult
79 260d0bda Agata Murawska
80 260d0bda Agata Murawska
-- | Testing result status for more verbose error message.
81 260d0bda Agata Murawska
fromJValWithStatus :: (Text.JSON.JSON a, Monad m) => (JSValue, JSValue) -> m a
82 260d0bda Agata Murawska
fromJValWithStatus (st, v) = do
83 ebf38064 Iustin Pop
  st' <- fromJVal st
84 62377cf5 Iustin Pop
  Qlang.checkRS st' v >>= fromJVal
85 92678b3c Iustin Pop
86 0ec8cce2 Bernardo Dal Seno
annotateConvert :: String -> String -> String -> Result a -> Result a
87 0ec8cce2 Bernardo Dal Seno
annotateConvert otype oname oattr =
88 0ec8cce2 Bernardo Dal Seno
  annotateResult $ otype ++ " '" ++ oname ++
89 0ec8cce2 Bernardo Dal Seno
    "', error while reading attribute '" ++ oattr ++ "'"
90 0ec8cce2 Bernardo Dal Seno
91 39420403 Iustin Pop
-- | Annotate errors when converting values with owner/attribute for
92 39420403 Iustin Pop
-- better debugging.
93 39420403 Iustin Pop
genericConvert :: (Text.JSON.JSON a) =>
94 260d0bda Agata Murawska
                  String             -- ^ The object type
95 260d0bda Agata Murawska
               -> String             -- ^ The object name
96 260d0bda Agata Murawska
               -> String             -- ^ The attribute we're trying to convert
97 260d0bda Agata Murawska
               -> (JSValue, JSValue) -- ^ The value we're trying to convert
98 260d0bda Agata Murawska
               -> Result a           -- ^ The annotated result
99 39420403 Iustin Pop
genericConvert otype oname oattr =
100 0ec8cce2 Bernardo Dal Seno
  annotateConvert otype oname oattr . fromJValWithStatus
101 0ec8cce2 Bernardo Dal Seno
102 0ec8cce2 Bernardo Dal Seno
convertArrayMaybe :: (Text.JSON.JSON a) =>
103 0ec8cce2 Bernardo Dal Seno
                  String             -- ^ The object type
104 0ec8cce2 Bernardo Dal Seno
               -> String             -- ^ The object name
105 0ec8cce2 Bernardo Dal Seno
               -> String             -- ^ The attribute we're trying to convert
106 0ec8cce2 Bernardo Dal Seno
               -> (JSValue, JSValue) -- ^ The value we're trying to convert
107 0ec8cce2 Bernardo Dal Seno
               -> Result [Maybe a]   -- ^ The annotated result
108 0ec8cce2 Bernardo Dal Seno
convertArrayMaybe otype oname oattr (st, v) = do
109 0ec8cce2 Bernardo Dal Seno
  st' <- fromJVal st
110 0ec8cce2 Bernardo Dal Seno
  Qlang.checkRS st' v >>=
111 0ec8cce2 Bernardo Dal Seno
    annotateConvert otype oname oattr . arrayMaybeFromJVal
112 39420403 Iustin Pop
113 53ec9022 Iustin Pop
-- * Data querying functionality
114 53ec9022 Iustin Pop
115 53ec9022 Iustin Pop
-- | The input data for node query.
116 683b1ca7 Iustin Pop
queryNodesMsg :: L.LuxiOp
117 53ec9022 Iustin Pop
queryNodesMsg =
118 1283cc38 Iustin Pop
  L.Query (Qlang.ItemTypeOpCode Qlang.QRNode)
119 1283cc38 Iustin Pop
     ["name", "mtotal", "mnode", "mfree", "dtotal", "dfree",
120 c8c071cb Bernardo Dal Seno
      "ctotal", "cnos", "offline", "drained", "vm_capable",
121 c324da14 Bernardo Dal Seno
      "ndp/spindle_count", "group.uuid", "tags",
122 96f9b0a6 Bernardo Dal Seno
      "ndp/exclusive_storage", "sptotal", "spfree"] Qlang.EmptyFilter
123 53ec9022 Iustin Pop
124 53ec9022 Iustin Pop
-- | The input data for instance query.
125 683b1ca7 Iustin Pop
queryInstancesMsg :: L.LuxiOp
126 53ec9022 Iustin Pop
queryInstancesMsg =
127 1283cc38 Iustin Pop
  L.Query (Qlang.ItemTypeOpCode Qlang.QRInstance)
128 1283cc38 Iustin Pop
     ["name", "disk_usage", "be/memory", "be/vcpus",
129 1283cc38 Iustin Pop
      "status", "pnode", "snodes", "tags", "oper_ram",
130 1283cc38 Iustin Pop
      "be/auto_balance", "disk_template",
131 0ec8cce2 Bernardo Dal Seno
      "be/spindle_use", "disk.sizes", "disk.spindles"] Qlang.EmptyFilter
132 53ec9022 Iustin Pop
133 a679e9dc Iustin Pop
-- | The input data for cluster query.
134 683b1ca7 Iustin Pop
queryClusterInfoMsg :: L.LuxiOp
135 683b1ca7 Iustin Pop
queryClusterInfoMsg = L.QueryClusterInfo
136 f89235f1 Iustin Pop
137 a679e9dc Iustin Pop
-- | The input data for node group query.
138 a679e9dc Iustin Pop
queryGroupsMsg :: L.LuxiOp
139 a679e9dc Iustin Pop
queryGroupsMsg =
140 1283cc38 Iustin Pop
  L.Query (Qlang.ItemTypeOpCode Qlang.QRGroup)
141 1283cc38 Iustin Pop
     ["uuid", "name", "alloc_policy", "ipolicy", "tags"]
142 1283cc38 Iustin Pop
     Qlang.EmptyFilter
143 a679e9dc Iustin Pop
144 179c0828 Iustin Pop
-- | Wraper over 'callMethod' doing node query.
145 6583e677 Iustin Pop
queryNodes :: L.Client -> IO (Result JSValue)
146 7adb7dff Iustin Pop
queryNodes = liftM errToResult . L.callMethod queryNodesMsg
147 53ec9022 Iustin Pop
148 179c0828 Iustin Pop
-- | Wraper over 'callMethod' doing instance query.
149 6583e677 Iustin Pop
queryInstances :: L.Client -> IO (Result JSValue)
150 7adb7dff Iustin Pop
queryInstances = liftM errToResult . L.callMethod queryInstancesMsg
151 53ec9022 Iustin Pop
152 179c0828 Iustin Pop
-- | Wrapper over 'callMethod' doing cluster information query.
153 f89235f1 Iustin Pop
queryClusterInfo :: L.Client -> IO (Result JSValue)
154 7adb7dff Iustin Pop
queryClusterInfo = liftM errToResult . L.callMethod queryClusterInfoMsg
155 f89235f1 Iustin Pop
156 a679e9dc Iustin Pop
-- | Wrapper over callMethod doing group query.
157 a679e9dc Iustin Pop
queryGroups :: L.Client -> IO (Result JSValue)
158 7adb7dff Iustin Pop
queryGroups = liftM errToResult . L.callMethod queryGroupsMsg
159 a679e9dc Iustin Pop
160 53ec9022 Iustin Pop
-- | Parse a instance list in JSON format.
161 53ec9022 Iustin Pop
getInstances :: NameAssoc
162 53ec9022 Iustin Pop
             -> JSValue
163 53ec9022 Iustin Pop
             -> Result [(String, Instance.Instance)]
164 92678b3c Iustin Pop
getInstances ktn arr = extractArray arr >>= mapM (parseInstance ktn)
165 53ec9022 Iustin Pop
166 53ec9022 Iustin Pop
-- | Construct an instance from a JSON object.
167 6ff78049 Iustin Pop
parseInstance :: NameAssoc
168 260d0bda Agata Murawska
              -> [(JSValue, JSValue)]
169 53ec9022 Iustin Pop
              -> Result (String, Instance.Instance)
170 260d0bda Agata Murawska
parseInstance ktn [ name, disk, mem, vcpus
171 260d0bda Agata Murawska
                  , status, pnode, snodes, tags, oram
172 0ec8cce2 Bernardo Dal Seno
                  , auto_balance, disk_template, su
173 0ec8cce2 Bernardo Dal Seno
                  , dsizes, dspindles ] = do
174 260d0bda Agata Murawska
  xname <- annotateResult "Parsing new instance" (fromJValWithStatus name)
175 39420403 Iustin Pop
  let convert a = genericConvert "Instance" xname a
176 39420403 Iustin Pop
  xdisk <- convert "disk_usage" disk
177 3603605a Iustin Pop
  xmem <- case oram of -- FIXME: remove the "guessing"
178 3603605a Iustin Pop
            (_, JSRational _ _) -> convert "oper_ram" oram
179 3603605a Iustin Pop
            _ -> convert "be/memory" mem
180 39420403 Iustin Pop
  xvcpus <- convert "be/vcpus" vcpus
181 39420403 Iustin Pop
  xpnode <- convert "pnode" pnode >>= lookupNode ktn xname
182 72747d91 Iustin Pop
  xsnodes <- convert "snodes" snodes::Result [String]
183 72747d91 Iustin Pop
  snode <- case xsnodes of
184 72747d91 Iustin Pop
             [] -> return Node.noSecondary
185 72747d91 Iustin Pop
             x:_ -> lookupNode ktn xname x
186 39420403 Iustin Pop
  xrunning <- convert "status" status
187 39420403 Iustin Pop
  xtags <- convert "tags" tags
188 6880526c Iustin Pop
  xauto_balance <- convert "auto_balance" auto_balance
189 b3c5e8de Iustin Pop
  xdt <- convert "disk_template" disk_template
190 ec629280 René Nussbaumer
  xsu <- convert "be/spindle_use" su
191 0ec8cce2 Bernardo Dal Seno
  xdsizes <- convert "disk.sizes" dsizes
192 0ec8cce2 Bernardo Dal Seno
  xdspindles <- convertArrayMaybe "Instance" xname "disk.spindles" dspindles
193 0ec8cce2 Bernardo Dal Seno
  let disks = zipWith Instance.Disk xdsizes xdspindles
194 0ec8cce2 Bernardo Dal Seno
      inst = Instance.create xname xmem xdisk disks
195 2724417c Bernardo Dal Seno
             xvcpus xrunning xtags xauto_balance xpnode snode xdt xsu []
196 53ec9022 Iustin Pop
  return (xname, inst)
197 53ec9022 Iustin Pop
198 53ec9022 Iustin Pop
parseInstance _ v = fail ("Invalid instance query result: " ++ show v)
199 53ec9022 Iustin Pop
200 53ec9022 Iustin Pop
-- | Parse a node list in JSON format.
201 10ef6b4e Iustin Pop
getNodes :: NameAssoc -> JSValue -> Result [(String, Node.Node)]
202 92678b3c Iustin Pop
getNodes ktg arr = extractArray arr >>= mapM (parseNode ktg)
203 53ec9022 Iustin Pop
204 53ec9022 Iustin Pop
-- | Construct a node from a JSON object.
205 260d0bda Agata Murawska
parseNode :: NameAssoc -> [(JSValue, JSValue)] -> Result (String, Node.Node)
206 260d0bda Agata Murawska
parseNode ktg [ name, mtotal, mnode, mfree, dtotal, dfree
207 c8c071cb Bernardo Dal Seno
              , ctotal, cnos, offline, drained, vm_capable, spindles, g_uuid
208 96f9b0a6 Bernardo Dal Seno
              , tags, excl_stor, sptotal, spfree ]
209 53ec9022 Iustin Pop
    = do
210 260d0bda Agata Murawska
  xname <- annotateResult "Parsing new node" (fromJValWithStatus name)
211 39420403 Iustin Pop
  let convert a = genericConvert "Node" xname a
212 39420403 Iustin Pop
  xoffline <- convert "offline" offline
213 39420403 Iustin Pop
  xdrained <- convert "drained" drained
214 39420403 Iustin Pop
  xvm_capable <- convert "vm_capable" vm_capable
215 39420403 Iustin Pop
  xgdx   <- convert "group.uuid" g_uuid >>= lookupGroup ktg xname
216 f33c06b8 Klaus Aehlig
  xtags <- convert "tags" tags
217 c324da14 Bernardo Dal Seno
  xexcl_stor <- convert "exclusive_storage" excl_stor
218 8c72f711 Bernardo Dal Seno
  let live = not xoffline && not xdrained && xvm_capable
219 8c72f711 Bernardo Dal Seno
      lvconvert def n d = eitherLive live def $ convert n d
220 96f9b0a6 Bernardo Dal Seno
  xsptotal <- if xexcl_stor
221 96f9b0a6 Bernardo Dal Seno
              then lvconvert 0 "sptotal" sptotal
222 96f9b0a6 Bernardo Dal Seno
              else convert "spindles" spindles
223 96f9b0a6 Bernardo Dal Seno
  xspfree <- lvconvert 0 "spfree" spfree
224 8c72f711 Bernardo Dal Seno
  xmtotal <- lvconvert 0.0 "mtotal" mtotal
225 8c72f711 Bernardo Dal Seno
  xmnode <- lvconvert 0 "mnode" mnode
226 8c72f711 Bernardo Dal Seno
  xmfree <- lvconvert 0 "mfree" mfree
227 8c72f711 Bernardo Dal Seno
  xdtotal <- lvconvert 0.0 "dtotal" dtotal
228 8c72f711 Bernardo Dal Seno
  xdfree <- lvconvert 0 "dfree" dfree
229 8c72f711 Bernardo Dal Seno
  xctotal <- lvconvert 0.0 "ctotal" ctotal
230 c8c071cb Bernardo Dal Seno
  xcnos <- lvconvert 0 "cnos" cnos
231 8c72f711 Bernardo Dal Seno
  let node = flip Node.setNodeTags xtags $
232 8c72f711 Bernardo Dal Seno
             Node.create xname xmtotal xmnode xmfree xdtotal xdfree
233 c8c071cb Bernardo Dal Seno
             xctotal xcnos (not live) xsptotal xspfree xgdx xexcl_stor
234 53ec9022 Iustin Pop
  return (xname, node)
235 53ec9022 Iustin Pop
236 10ef6b4e Iustin Pop
parseNode _ v = fail ("Invalid node query result: " ++ show v)
237 53ec9022 Iustin Pop
238 179c0828 Iustin Pop
-- | Parses the cluster tags.
239 f40fe08c Klaus Aehlig
getClusterData :: JSValue -> Result ([String], IPolicy, String)
240 e77bc89b Iustin Pop
getClusterData (JSObject obj) = do
241 f89235f1 Iustin Pop
  let errmsg = "Parsing cluster info"
242 e77bc89b Iustin Pop
      obj' = fromJSObject obj
243 e77bc89b Iustin Pop
  ctags <- tryFromObj errmsg obj' "tags"
244 e77bc89b Iustin Pop
  cpol <- tryFromObj errmsg obj' "ipolicy"
245 f40fe08c Klaus Aehlig
  master <- tryFromObj errmsg obj' "master"
246 f40fe08c Klaus Aehlig
  return (ctags, cpol, master)
247 e77bc89b Iustin Pop
248 5b11f8db Iustin Pop
getClusterData _ = Bad "Cannot parse cluster info, not a JSON record"
249 f89235f1 Iustin Pop
250 179c0828 Iustin Pop
-- | Parses the cluster groups.
251 a679e9dc Iustin Pop
getGroups :: JSValue -> Result [(String, Group.Group)]
252 92678b3c Iustin Pop
getGroups jsv = extractArray jsv >>= mapM parseGroup
253 a679e9dc Iustin Pop
254 179c0828 Iustin Pop
-- | Parses a given group information.
255 260d0bda Agata Murawska
parseGroup :: [(JSValue, JSValue)] -> Result (String, Group.Group)
256 6b6e335b Dato Simó
parseGroup [uuid, name, apol, ipol, tags] = do
257 260d0bda Agata Murawska
  xname <- annotateResult "Parsing new group" (fromJValWithStatus name)
258 39420403 Iustin Pop
  let convert a = genericConvert "Group" xname a
259 39420403 Iustin Pop
  xuuid <- convert "uuid" uuid
260 39420403 Iustin Pop
  xapol <- convert "alloc_policy" apol
261 6cff91f5 Iustin Pop
  xipol <- convert "ipolicy" ipol
262 6b6e335b Dato Simó
  xtags <- convert "tags" tags
263 c8b199db Thomas Thrainer
  -- TODO: parse networks to which this group is connected
264 c8b199db Thomas Thrainer
  return (xuuid, Group.create xname xuuid xapol [] xipol xtags)
265 a679e9dc Iustin Pop
266 a679e9dc Iustin Pop
parseGroup v = fail ("Invalid group query result: " ++ show v)
267 a679e9dc Iustin Pop
268 53ec9022 Iustin Pop
-- * Main loader functionality
269 53ec9022 Iustin Pop
270 525bfb36 Iustin Pop
-- | Builds the cluster data by querying a given socket name.
271 b3f0710c Iustin Pop
readData :: String -- ^ Unix socket to use as source
272 a679e9dc Iustin Pop
         -> IO (Result JSValue, Result JSValue, Result JSValue, Result JSValue)
273 b3f0710c Iustin Pop
readData master =
274 53ec9022 Iustin Pop
  E.bracket
275 d605e261 Petr Pudlak
       (L.getLuxiClient master)
276 6583e677 Iustin Pop
       L.closeClient
277 53ec9022 Iustin Pop
       (\s -> do
278 53ec9022 Iustin Pop
          nodes <- queryNodes s
279 53ec9022 Iustin Pop
          instances <- queryInstances s
280 f89235f1 Iustin Pop
          cinfo <- queryClusterInfo s
281 a679e9dc Iustin Pop
          groups <- queryGroups s
282 a679e9dc Iustin Pop
          return (groups, nodes, instances, cinfo)
283 53ec9022 Iustin Pop
       )
284 b3f0710c Iustin Pop
285 525bfb36 Iustin Pop
-- | Converts the output of 'readData' into the internal cluster
286 525bfb36 Iustin Pop
-- representation.
287 a679e9dc Iustin Pop
parseData :: (Result JSValue, Result JSValue, Result JSValue, Result JSValue)
288 f4f6eb0b Iustin Pop
          -> Result ClusterData
289 a679e9dc Iustin Pop
parseData (groups, nodes, instances, cinfo) = do
290 a679e9dc Iustin Pop
  group_data <- groups >>= getGroups
291 10ef6b4e Iustin Pop
  let (group_names, group_idx) = assignIndices group_data
292 10ef6b4e Iustin Pop
  node_data <- nodes >>= getNodes group_names
293 b3f0710c Iustin Pop
  let (node_names, node_idx) = assignIndices node_data
294 b3f0710c Iustin Pop
  inst_data <- instances >>= getInstances node_names
295 b3f0710c Iustin Pop
  let (_, inst_idx) = assignIndices inst_data
296 f40fe08c Klaus Aehlig
  (ctags, cpol, master) <- cinfo >>= getClusterData
297 f40fe08c Klaus Aehlig
  node_idx' <- setMaster node_names node_idx master
298 f40fe08c Klaus Aehlig
  return (ClusterData group_idx node_idx' inst_idx ctags cpol)
299 b3f0710c Iustin Pop
300 525bfb36 Iustin Pop
-- | Top level function for data loading.
301 b3f0710c Iustin Pop
loadData :: String -- ^ Unix socket to use as source
302 f4f6eb0b Iustin Pop
         -> IO (Result ClusterData)
303 2a8e2dc9 Iustin Pop
loadData = fmap parseData . readData