Revision 84835174

b/htools/Ganeti/Confd/Server.hs
137 137
nodeRole :: ConfigData -> String -> Result ConfdNodeRole
138 138
nodeRole cfg name =
139 139
  let cmaster = clusterMasterNode . configCluster $ cfg
140
      mnode = M.lookup name . configNodes $ cfg
140
      mnode = M.lookup name . fromContainer . configNodes $ cfg
141 141
  in case mnode of
142 142
       Nothing -> Bad "Node not found"
143 143
       Just node | cmaster == name -> Ok NodeRoleMaster
......
194 194
  -- versions of the library
195 195
  return (ReplyStatusOk, J.showJSON $
196 196
          M.foldlWithKey (\accu _ n -> nodePrimaryIp n:accu) []
197
          (configNodes (fst cdata)))
197
          (fromContainer . configNodes . fst $ cdata))
198 198

  
199 199
buildResponse cdata (ConfdRequest { confdRqType = ReqMcPipList }) =
200 200
  -- note: we use foldlWithKey because that's present accross more
......
203 203
          M.foldlWithKey (\accu _ n -> if nodeMasterCandidate n
204 204
                                         then nodePrimaryIp n:accu
205 205
                                         else accu) []
206
          (configNodes (fst cdata)))
206
          (fromContainer . configNodes . fst $ cdata))
207 207

  
208 208
buildResponse (cfg, linkipmap)
209 209
              req@(ConfdRequest { confdRqType = ReqInstIpsList }) = do
......
234 234
                 _ -> fail $ "Invalid query type " ++ show (confdRqQuery req)
235 235
  node <- getNode cfg node_name
236 236
  let minors = concatMap (getInstMinorsForNode (nodeName node)) .
237
               M.elems . configInstances $ cfg
237
               M.elems . fromContainer . configInstances $ cfg
238 238
      encoded = [J.JSArray [J.showJSON a, J.showJSON b, J.showJSON c,
239 239
                             J.showJSON d, J.showJSON e, J.showJSON f] |
240 240
                 (a, b, c, d, e, f) <- minors]
b/htools/Ganeti/Config.hs
92 92
-- | Get instances of a given node.
93 93
getNodeInstances :: ConfigData -> String -> ([Instance], [Instance])
94 94
getNodeInstances cfg nname =
95
    let all_inst = M.elems . configInstances $ cfg
95
    let all_inst = M.elems . fromContainer . configInstances $ cfg
96 96
        pri_inst = filter ((== nname) . instPrimaryNode) all_inst
97 97
        sec_inst = filter ((nname `S.member`) . instSecondaryNodes) all_inst
98 98
    in (pri_inst, sec_inst)
......
100 100
-- | Returns the default cluster link.
101 101
getDefaultNicLink :: ConfigData -> String
102 102
getDefaultNicLink =
103
  nicpLink . (M.! C.ppDefault) . clusterNicparams . configCluster
103
  nicpLink . (M.! C.ppDefault) . fromContainer .
104
  clusterNicparams . configCluster
104 105

  
105 106
-- | Returns instances of a given link.
106 107
getInstancesIpByLink :: LinkIpMap -> String -> [String]
......
123 124

  
124 125
-- | Looks up a node.
125 126
getNode :: ConfigData -> String -> Result Node
126
getNode cfg name = getItem "Node" name (configNodes cfg)
127
getNode cfg name = getItem "Node" name (fromContainer $ configNodes cfg)
127 128

  
128 129
-- | Looks up an instance.
129 130
getInstance :: ConfigData -> String -> Result Instance
130
getInstance cfg name = getItem "Instance" name (configInstances cfg)
131
getInstance cfg name =
132
  getItem "Instance" name (fromContainer $ configInstances cfg)
131 133

  
132 134
-- | Looks up an instance's primary node.
133 135
getInstPrimaryNode :: ConfigData -> String -> Result Node
......
183 185
buildLinkIpInstnameMap :: ConfigData -> LinkIpMap
184 186
buildLinkIpInstnameMap cfg =
185 187
  let cluster = configCluster cfg
186
      instances = M.elems . configInstances $ cfg
187
      defparams = (M.!) (clusterNicparams cluster) C.ppDefault
188
      instances = M.elems . fromContainer . configInstances $ cfg
189
      defparams = (M.!) (fromContainer $ clusterNicparams cluster) C.ppDefault
188 190
      nics = concatMap (\i -> [(instName i, nic) | nic <- instNics i])
189 191
             instances
190 192
  in foldl' (\accum (iname, nic) ->
b/htools/Ganeti/HTools/JSON.hs
35 35
  , asObjectList
36 36
  , tryFromObj
37 37
  , toArray
38
  , Container(..)
38 39
  )
39 40
  where
40 41

  
42
import Control.Arrow (second)
41 43
import Control.Monad (liftM)
42 44
import Data.Maybe (fromMaybe)
45
import qualified Data.Map as Map
43 46
import Text.Printf (printf)
44 47

  
45 48
import qualified Text.JSON as J
......
132 135
toArray :: (Monad m) => J.JSValue -> m [J.JSValue]
133 136
toArray (J.JSArray arr) = return arr
134 137
toArray o = fail $ "Invalid input, expected array but got " ++ show o
138

  
139
-- * Container type (special type for JSON serialisation)
140

  
141
-- | The container type, a wrapper over Data.Map
142
newtype Container a = Container { fromContainer :: Map.Map String a }
143
  deriving (Show, Read, Eq)
144

  
145
-- | Container loader.
146
readContainer :: (Monad m, J.JSON a) =>
147
                 J.JSObject J.JSValue -> m (Container a)
148
readContainer obj = do
149
  let kjvlist = J.fromJSObject obj
150
  kalist <- mapM (\(k, v) -> fromKeyValue k v >>= \a -> return (k, a)) kjvlist
151
  return $ Container (Map.fromList kalist)
152

  
153
-- | Container dumper.
154
showContainer :: (J.JSON a) => Container a -> J.JSValue
155
showContainer =
156
  J.makeObj . map (second J.showJSON) . Map.toList . fromContainer
157

  
158
instance (J.JSON a) => J.JSON (Container a) where
159
  showJSON = showContainer
160
  readJSON (J.JSObject o) = readContainer o
161
  readJSON v = fail $ "Failed to load container, expected object but got "
162
               ++ show v
b/htools/Ganeti/THH.hs
54 54
                  , Container
55 55
                  ) where
56 56

  
57
import Control.Arrow
58 57
import Control.Monad (liftM, liftM2)
59 58
import Data.Char
60 59
import Data.List
61
import qualified Data.Map as M
62 60
import qualified Data.Set as Set
63 61
import Language.Haskell.TH
64 62

  
......
68 66

  
69 67
-- * Exported types
70 68

  
71
type Container = M.Map String
72

  
73 69
-- | Serialised field data type.
74 70
data Field = Field { fieldName        :: String
75 71
                   , fieldType        :: Q Type
......
155 151
       -> Q Exp   -- ^ The entire object in JSON object format
156 152
       -> Q Exp   -- ^ Resulting expression
157 153
loadFn (Field { fieldIsContainer = True }) expr _ =
158
  [| $expr >>= readContainer |]
154
  [| $expr |]
159 155
loadFn (Field { fieldRead = Just readfn }) expr o = [| $expr >>= $readfn $o |]
160 156
loadFn _ expr _ = expr
161 157

  
......
225 221
appFn f x | f == VarE 'id = x
226 222
          | otherwise = AppE f x
227 223

  
228
-- | Container loader
229
readContainer :: (Monad m, JSON.JSON a) =>
230
                 JSON.JSObject JSON.JSValue -> m (Container a)
231
readContainer obj = do
232
  let kjvlist = JSON.fromJSObject obj
233
  kalist <- mapM (\(k, v) -> fromKeyValue k v >>= \a -> return (k, a)) kjvlist
234
  return $ M.fromList kalist
235

  
236
-- | Container dumper
237
showContainer :: (JSON.JSON a) => Container a -> JSON.JSValue
238
showContainer = JSON.makeObj . map (second JSON.showJSON) . M.toList
239

  
240 224
-- * Template code for simple raw type-equivalent ADTs
241 225

  
242 226
-- | Generates a data type declaration.
......
639 623

  
640 624
saveObjectField :: Name -> Field -> Q Exp
641 625
saveObjectField fvar field
642
  | isContainer = [| [( $nameE , JSON.showJSON . showContainer $ $fvarE)] |]
626
  | isContainer = [| [( $nameE , JSON.showJSON $fvarE)] |]
643 627
  | fisOptional = [| case $(varE fvar) of
644 628
                      Nothing -> []
645 629
                      Just v -> [( $nameE, JSON.showJSON v)]

Also available in: Unified diff