Revision 36162faf

b/src/Ganeti/Query/Group.hs
4 4

  
5 5
{-
6 6

  
7
Copyright (C) 2012 Google Inc.
7
Copyright (C) 2012, 2013 Google Inc.
8 8

  
9 9
This program is free software; you can redistribute it and/or modify
10 10
it under the terms of the GNU General Public License as published by
......
24 24
-}
25 25

  
26 26
module Ganeti.Query.Group
27
  ( GroupRuntime(..)
28
  , groupFieldsMap
27
  ( Runtime(..)
28
  , fieldsMap
29 29
  ) where
30 30

  
31 31
import qualified Data.Map as Map
......
37 37
import Ganeti.Query.Types
38 38

  
39 39
-- | There is no runtime.
40
data GroupRuntime = GroupRuntime
40
data Runtime = Runtime
41 41

  
42
groupFields :: FieldList NodeGroup GroupRuntime
42
groupFields :: FieldList NodeGroup Runtime
43 43
groupFields =
44 44
  [ (FieldDefinition "alloc_policy" "AllocPolicy" QFTText
45 45
       "Allocation policy for group",
......
86 86
  tagsFields
87 87

  
88 88
-- | The group fields map.
89
groupFieldsMap :: FieldMap NodeGroup GroupRuntime
90
groupFieldsMap =
89
fieldsMap :: FieldMap NodeGroup Runtime
90
fieldsMap =
91 91
  Map.fromList $ map (\v@(f, _, _) -> (fdefName f, v)) groupFields
b/src/Ganeti/Query/Network.hs
4 4

  
5 5
{-
6 6

  
7
Copyright (C) 2012 Google Inc.
7
Copyright (C) 2012, 2013 Google Inc.
8 8

  
9 9
This program is free software; you can redistribute it and/or modify
10 10
it under the terms of the GNU General Public License as published by
......
27 27
  ( getGroupConnection
28 28
  , getNetworkUuid
29 29
  , instIsConnected
30
  , NetworkRuntime(..)
31
  , networkFieldsMap
30
  , Runtime(..)
31
  , fieldsMap
32 32
  ) where
33 33

  
34
-- FIXME: everything except NetworkRuntime(..) and networkFieldsMap
34
-- FIXME: everything except Runtime(..) and fieldsMap
35 35
-- is only exported for testing.
36 36

  
37 37
import qualified Data.Map as Map
......
46 46
import Ganeti.Query.Types
47 47
import Ganeti.Types
48 48

  
49
data NetworkRuntime = NetworkRuntime
49
-- | There is no actual runtime.
50
data Runtime = Runtime
50 51

  
51
networkFields :: FieldList Network NetworkRuntime
52
networkFields :: FieldList Network Runtime
52 53
networkFields =
53 54
  [ (FieldDefinition "name" "Name" QFTText "Network name",
54 55
     FieldSimple (rsNormal . networkName), QffNormal)
......
90 91
  tagsFields
91 92

  
92 93
-- | The group fields map.
93
networkFieldsMap :: FieldMap Network NetworkRuntime
94
networkFieldsMap =
94
fieldsMap :: FieldMap Network Runtime
95
fieldsMap =
95 96
  Map.fromList $ map (\v@(f, _, _) -> (fdefName f, v)) networkFields
96 97

  
97 98
-- TODO: the following fields are not implemented yet: external_reservations
b/src/Ganeti/Query/Node.hs
4 4

  
5 5
{-
6 6

  
7
Copyright (C) 2012 Google Inc.
7
Copyright (C) 2012, 2013 Google Inc.
8 8

  
9 9
This program is free software; you can redistribute it and/or modify
10 10
it under the terms of the GNU General Public License as published by
......
24 24
-}
25 25

  
26 26
module Ganeti.Query.Node
27
  ( NodeRuntime
28
  , nodeFieldsMap
29
  , maybeCollectLiveData
27
  ( Runtime
28
  , fieldsMap
29
  , collectLiveData
30 30
  ) where
31 31

  
32 32
import Control.Applicative
......
42 42
import Ganeti.Query.Common
43 43
import Ganeti.Query.Types
44 44

  
45
-- | NodeRuntime is the resulting type for NodeInfo call.
46
type NodeRuntime = Either RpcError RpcResultNodeInfo
45
-- | Runtime is the resulting type for NodeInfo call.
46
type Runtime = Either RpcError RpcResultNodeInfo
47 47

  
48 48
-- | List of node live fields.
49 49
nodeLiveFieldsDefs :: [(FieldName, FieldTitle, FieldType, String, FieldDoc)]
......
93 93
nodeLiveFieldExtract _ _ = J.JSNull
94 94

  
95 95
-- | Helper for extracting field from RPC result.
96
nodeLiveRpcCall :: FieldName -> NodeRuntime -> Node -> ResultEntry
96
nodeLiveRpcCall :: FieldName -> Runtime -> Node -> ResultEntry
97 97
nodeLiveRpcCall fname (Right res) _ =
98 98
  case nodeLiveFieldExtract fname res of
99 99
    J.JSNull -> rsNoData
......
103 103

  
104 104
-- | Builder for node live fields.
105 105
nodeLiveFieldBuilder :: (FieldName, FieldTitle, FieldType, String, FieldDoc)
106
                     -> FieldData Node NodeRuntime
106
                     -> FieldData Node Runtime
107 107
nodeLiveFieldBuilder (fname, ftitle, ftype, _, fdoc) =
108 108
  ( FieldDefinition fname ftitle ftype fdoc
109 109
  , FieldRuntime $ nodeLiveRpcCall fname
......
129 129
                  else rsNormal (nodePowered node)
130 130

  
131 131
-- | List of all node fields.
132
nodeFields :: FieldList Node NodeRuntime
132
nodeFields :: FieldList Node Runtime
133 133
nodeFields =
134 134
  [ (FieldDefinition "drained" "Drained" QFTBool "Whether node is drained",
135 135
     FieldSimple (rsNormal . nodeDrained), QffNormal)
......
208 208
  tagsFields
209 209

  
210 210
-- | The node fields map.
211
nodeFieldsMap :: FieldMap Node NodeRuntime
212
nodeFieldsMap =
211
fieldsMap :: FieldMap Node Runtime
212
fieldsMap =
213 213
  Map.fromList $ map (\v@(f, _, _) -> (fdefName f, v)) nodeFields
214 214

  
215 215
-- | Collect live data from RPC query if enabled.
216 216
--
217 217
-- FIXME: Check which fields we actually need and possibly send empty
218
-- hvs/vgs if no info from hypervisor/volume group respectively is
218
-- hvs\/vgs if no info from hypervisor\/volume group respectively is
219 219
-- required
220
maybeCollectLiveData:: Bool -> ConfigData -> [Node] -> IO [(Node, NodeRuntime)]
221
maybeCollectLiveData False _ nodes =
220
collectLiveData:: Bool -> ConfigData -> [Node] -> IO [(Node, Runtime)]
221
collectLiveData False _ nodes =
222 222
  return $ zip nodes (repeat $ Left (RpcResultError "Live data disabled"))
223
maybeCollectLiveData True cfg nodes = do
223
collectLiveData True cfg nodes = do
224 224
  let vgs = [clusterVolumeGroupName $ configCluster cfg]
225 225
      hvs = [getDefaultHypervisor cfg]
226 226
      step n (bn, gn, em) =
b/src/Ganeti/Query/Query.hs
70 70
import qualified Ganeti.Query.Export as Export
71 71
import Ganeti.Query.Filter
72 72
import qualified Ganeti.Query.Job as Query.Job
73
import Ganeti.Query.Group
73
import qualified Ganeti.Query.Group as Group
74 74
import Ganeti.Query.Language
75
import Ganeti.Query.Network
76
import Ganeti.Query.Node
75
import qualified Ganeti.Query.Network as Network
76
import qualified Ganeti.Query.Node as Node
77 77
import Ganeti.Query.Types
78 78
import Ganeti.Path
79 79
import Ganeti.Types
......
168 168

  
169 169
queryInner cfg live (Query (ItemTypeOpCode QRNode) fields qfilter) wanted =
170 170
  runResultT $ do
171
  cfilter <- resultT $ compileFilter nodeFieldsMap qfilter
172
  let selected = getSelectedFields nodeFieldsMap fields
171
  cfilter <- resultT $ compileFilter Node.fieldsMap qfilter
172
  let selected = getSelectedFields Node.fieldsMap fields
173 173
      (fdefs, fgetters, _) = unzip3 selected
174 174
      live' = live && needsLiveData fgetters
175 175
  nodes <- resultT $ case wanted of
......
182 182
                      nodes
183 183
  -- here we would run the runtime data gathering, then filter again
184 184
  -- the nodes, based on existing runtime data
185
  nruntimes <- lift $ maybeCollectLiveData live' cfg fnodes
185
  nruntimes <- lift $ Node.collectLiveData live' cfg fnodes
186 186
  let fdata = map (\(node, nrt) -> map (execGetter cfg nrt node) fgetters)
187 187
              nruntimes
188 188
  return QueryResult { qresFields = fdefs, qresData = fdata }
189 189

  
190 190
queryInner cfg _ (Query (ItemTypeOpCode QRGroup) fields qfilter) wanted =
191 191
  return $ do
192
  cfilter <- compileFilter groupFieldsMap qfilter
193
  let selected = getSelectedFields groupFieldsMap fields
192
  cfilter <- compileFilter Group.fieldsMap qfilter
193
  let selected = getSelectedFields Group.fieldsMap fields
194 194
      (fdefs, fgetters, _) = unzip3 selected
195 195
  groups <- case wanted of
196 196
              [] -> Ok . niceSortKey groupName .
......
199 199
  -- there is no live data for groups, so filtering is much simpler
200 200
  fgroups <- filterM (\n -> evaluateFilter cfg Nothing n cfilter) groups
201 201
  let fdata = map (\node ->
202
                       map (execGetter cfg GroupRuntime node) fgetters) fgroups
202
                     map (execGetter cfg Group.Runtime node) fgetters) fgroups
203 203
  return QueryResult { qresFields = fdefs, qresData = fdata }
204 204

  
205 205
queryInner cfg _ (Query (ItemTypeOpCode QRNetwork) fields qfilter) wanted =
206 206
  return $ do
207
  cfilter <- compileFilter networkFieldsMap qfilter
208
  let selected = getSelectedFields networkFieldsMap fields
207
  cfilter <- compileFilter Network.fieldsMap qfilter
208
  let selected = getSelectedFields Network.fieldsMap fields
209 209
      (fdefs, fgetters, _) = unzip3 selected
210 210
  networks <- case wanted of
211 211
                [] -> Ok . niceSortKey (fromNonEmpty . networkName) .
......
213 213
                _  -> mapM (getNetwork cfg) wanted
214 214
  fnetworks <- filterM (\n -> evaluateFilter cfg Nothing n cfilter) networks
215 215
  let fdata = map (\network ->
216
                   map (execGetter cfg NetworkRuntime network) fgetters)
216
                   map (execGetter cfg Network.Runtime network) fgetters)
217 217
                   fnetworks
218 218
  return QueryResult { qresFields = fdefs, qresData = fdata }
219 219

  
......
308 308
-- | Query fields call.
309 309
queryFields :: QueryFields -> ErrorResult QueryFieldsResult
310 310
queryFields (QueryFields (ItemTypeOpCode QRNode) fields) =
311
  Ok $ fieldsExtractor nodeFieldsMap fields
311
  Ok $ fieldsExtractor Node.fieldsMap fields
312 312

  
313 313
queryFields (QueryFields (ItemTypeOpCode QRGroup) fields) =
314
  Ok $ fieldsExtractor groupFieldsMap fields
314
  Ok $ fieldsExtractor Group.fieldsMap fields
315 315

  
316 316
queryFields (QueryFields (ItemTypeLuxi QRJob) fields) =
317 317
  Ok $ fieldsExtractor Query.Job.fieldsMap fields
b/test/hs/Test/Ganeti/Query/Query.hs
7 7

  
8 8
{-
9 9

  
10
Copyright (C) 2009, 2010, 2011, 2012 Google Inc.
10
Copyright (C) 2009, 2010, 2011, 2012, 2013 Google Inc.
11 11

  
12 12
This program is free software; you can redistribute it and/or modify
13 13
it under the terms of the GNU General Public License as published by
......
45 45
import Ganeti.BasicTypes
46 46
import Ganeti.Errors
47 47
import Ganeti.Query.Filter
48
import Ganeti.Query.Group
48
import qualified Ganeti.Query.Group as Group
49 49
import Ganeti.Query.Language
50
import Ganeti.Query.Node
50
import qualified Ganeti.Query.Node as Node
51 51
import Ganeti.Query.Query
52 52
import qualified Ganeti.Query.Job as Job
53 53

  
......
68 68
prop_queryNode_noUnknown :: Property
69 69
prop_queryNode_noUnknown =
70 70
  forAll (choose (0, maxNodes) >>= genEmptyCluster) $ \cluster ->
71
  forAll (elements (Map.keys nodeFieldsMap)) $ \field -> monadicIO $ do
71
  forAll (elements (Map.keys Node.fieldsMap)) $ \field -> monadicIO $ do
72 72
  QueryResult fdefs fdata <-
73 73
    run (query cluster False (Query (ItemTypeOpCode QRNode)
74 74
                              [field] EmptyFilter)) >>= resultProp
......
88 88
prop_queryNode_Unknown :: Property
89 89
prop_queryNode_Unknown =
90 90
  forAll (choose (0, maxNodes) >>= genEmptyCluster) $ \cluster ->
91
  forAll (arbitrary `suchThat` (`notElem` Map.keys nodeFieldsMap))
91
  forAll (arbitrary `suchThat` (`notElem` Map.keys Node.fieldsMap))
92 92
    $ \field -> monadicIO $ do
93 93
  QueryResult fdefs fdata <-
94 94
    run (query cluster False (Query (ItemTypeOpCode QRNode)
......
136 136
prop_queryNode_types =
137 137
  forAll (choose (0, maxNodes)) $ \numnodes ->
138 138
  forAll (genEmptyCluster numnodes) $ \cfg ->
139
  forAll (elements (Map.keys nodeFieldsMap)) $ \field -> monadicIO $ do
139
  forAll (elements (Map.keys Node.fieldsMap)) $ \field -> monadicIO $ do
140 140
  QueryResult fdefs fdata <-
141 141
    run (query cfg False (Query (ItemTypeOpCode QRNode)
142 142
                          [field] EmptyFilter)) >>= resultProp
......
160 160
              Ok (QueryFieldsResult v) -> return v
161 161
   let field_sort = compare `on` fdefName
162 162
   assertEqual "Mismatch in all fields list"
163
     (sortBy field_sort . map (\(f, _, _) -> f) $ Map.elems nodeFieldsMap)
163
     (sortBy field_sort . map (\(f, _, _) -> f) $ Map.elems Node.fieldsMap)
164 164
     (sortBy field_sort fdefs)
165 165

  
166 166
-- ** Group queries
......
168 168
prop_queryGroup_noUnknown :: Property
169 169
prop_queryGroup_noUnknown =
170 170
  forAll (choose (0, maxNodes) >>= genEmptyCluster) $ \cluster ->
171
   forAll (elements (Map.keys groupFieldsMap)) $ \field -> monadicIO $ do
171
   forAll (elements (Map.keys Group.fieldsMap)) $ \field -> monadicIO $ do
172 172
   QueryResult fdefs fdata <-
173 173
     run (query cluster False (Query (ItemTypeOpCode QRGroup)
174 174
                               [field] EmptyFilter)) >>=
......
188 188
prop_queryGroup_Unknown :: Property
189 189
prop_queryGroup_Unknown =
190 190
  forAll (choose (0, maxNodes) >>= genEmptyCluster) $ \cluster ->
191
  forAll (arbitrary `suchThat` (`notElem` Map.keys groupFieldsMap))
191
  forAll (arbitrary `suchThat` (`notElem` Map.keys Group.fieldsMap))
192 192
    $ \field -> monadicIO $ do
193 193
  QueryResult fdefs fdata <-
194 194
    run (query cluster False (Query (ItemTypeOpCode QRGroup)
......
212 212
prop_queryGroup_types =
213 213
  forAll (choose (0, maxNodes)) $ \numnodes ->
214 214
  forAll (genEmptyCluster numnodes) $ \cfg ->
215
  forAll (elements (Map.keys groupFieldsMap)) $ \field -> monadicIO $ do
215
  forAll (elements (Map.keys Group.fieldsMap)) $ \field -> monadicIO $ do
216 216
  QueryResult fdefs fdata <-
217 217
    run (query cfg False (Query (ItemTypeOpCode QRGroup)
218 218
                          [field] EmptyFilter)) >>= resultProp
......
232 232
              Ok (QueryFieldsResult v) -> return v
233 233
   let field_sort = compare `on` fdefName
234 234
   assertEqual "Mismatch in all fields list"
235
     (sortBy field_sort . map (\(f, _, _) -> f) $ Map.elems groupFieldsMap)
235
     (sortBy field_sort . map (\(f, _, _) -> f) $ Map.elems Group.fieldsMap)
236 236
     (sortBy field_sort fdefs)
237 237

  
238 238
-- ** Job queries

Also available in: Unified diff