Revision 942403e6 Ganeti/HTools/IAlloc.hs

b/Ganeti/HTools/IAlloc.hs
11 11
import Data.Either ()
12 12
import Data.Maybe
13 13
import Control.Monad
14
import Text.JSON
14
import Text.JSON (JSObject, JSValue(JSBool, JSString, JSArray),
15
                  makeObj, encodeStrict, decodeStrict,
16
                  fromJSObject, toJSString)
15 17
import Text.Printf (printf)
16 18
import Ganeti.HTools.Utils
19
import qualified Ganeti.HTools.Node as Node
20
import qualified Ganeti.HTools.Instance as Instance
17 21

  
18 22
data RqType
19 23
    = Allocate
20 24
    | Relocate
21
    deriving (Show)
25
    deriving (Eq, Show)
22 26

  
23
parseInstance :: String -> JSObject JSValue -> Either String String
27
data Request
28
    = RqAlloc String String String
29
    | RqReloc String String String
30

  
31
parseInstance :: String -> JSObject JSValue -> Result String
24 32
parseInstance n a =
25
    let name = Right n
33
    let name = Ok n
26 34
        disk = case getIntElement "disk_usage" a of
27
                 Left _ -> let all_d = getListElement "disks" a `combineEithers`
28
                                       asObjectList
29
                               szd = all_d `combineEithers`
30
                                     (ensureEitherList .
31
                                      map (getIntElement "size"))
32
                               sze = applyEither1 (map (+128)) szd
33
                               szf = applyEither1 sum sze
35
                 Bad _ -> let all_d = getListElement "disks" a >>= asObjectList
36
                              szd = all_d >>=
37
                                    (sequence .
38
                                     map (getIntElement "size"))
39
                              sze = liftM (map (+128)) szd
40
                              szf = liftM sum sze
34 41
                           in szf
35
                 Right x -> Right x
42
                 x@(Ok _) -> x
36 43
        nodes = getListElement "nodes" a
37
        pnode = eitherListHead nodes
38
                `combineEithers` readEitherString
39
        snode = applyEither1 (head . tail) nodes
40
                `combineEithers` readEitherString
44
        pnode = liftM head nodes >>= readEitherString
45
        snode = liftM (head . tail) nodes >>= readEitherString
41 46
        mem = getIntElement "memory" a
42
        running = Right "running" --getStringElement "status" a
47
        running = Ok "running" --getStringElement "status" a
43 48
    in
44
      concatEitherElems name $
45
                  concatEitherElems (show `applyEither1` mem) $
46
                  concatEitherElems (show `applyEither1` disk) $
47
                  concatEitherElems running $
48
                  concatEitherElems pnode snode
49
      name |+ (show `liftM` mem) |+
50
              (show `liftM` disk) |+ running |+ pnode |+ snode
49 51

  
50
parseNode :: String -> JSObject JSValue -> Either String String
52
parseNode :: String -> JSObject JSValue -> Result String
51 53
parseNode n a =
52
    let name = Right n
54
    let name = Ok n
53 55
        mtotal = getIntElement "total_memory" a
54 56
        mnode = getIntElement "reserved_memory" a
55 57
        mfree = getIntElement "free_memory" a
56 58
        dtotal = getIntElement "total_disk" a
57 59
        dfree = getIntElement "free_disk" a
58
    in concatEitherElems name $
59
       concatEitherElems (show `applyEither1` mtotal) $
60
       concatEitherElems (show `applyEither1` mnode) $
61
       concatEitherElems (show `applyEither1` mfree) $
62
       concatEitherElems (show `applyEither1` dtotal)
63
                             (show `applyEither1` dfree)
60
    in name |+ (show `liftM` mtotal) |+
61
              (show `liftM` mnode) |+
62
              (show `liftM` mfree) |+
63
              (show `liftM` dtotal) |+
64
              (show `liftM` dfree)
64 65

  
65
validateRequest :: String -> Either String RqType
66
validateRequest :: String -> Result RqType
66 67
validateRequest rq =
67 68
    case rq of
68
      "allocate" -> Right Allocate
69
      "relocate" -> Right Relocate
70
      _ -> Left ("Invalid request type '" ++ rq ++ "'")
69
      "allocate" -> Ok Allocate
70
      "relocate" -> Ok Relocate
71
      _ -> Bad ("Invalid request type '" ++ rq ++ "'")
71 72

  
72
parseData :: String -> Either String (String, String)
73
parseData :: String -> Result Request
73 74
parseData body =
74
    let
75
        decoded = resultToEither $ decodeStrict body
76
        obj = decoded -- decoded `combineEithers` fromJSObject
75
    do
76
      decoded <- fromJResult $ decodeStrict body
77
      let obj = decoded -- decoded `combineEithers` fromJSObject
77 78
        -- request parser
78
        request = obj `combineEithers` getObjectElement "request"
79
        rname = request `combineEithers` getStringElement "name"
80
        rtype = request `combineEithers` getStringElement "type"
81
                `combineEithers` validateRequest
82
        -- existing intstance parsing
83
        ilist = obj `combineEithers` getObjectElement "instances"
84
        idata = applyEither1 fromJSObject ilist
85
        iobj = idata `combineEithers` (ensureEitherList .
86
                                       map (\(x,y) ->
87
                                           asJSObject y `combineEithers`
88
                                                      parseInstance x))
89
        ilines = iobj `combineEithers` (Right . unlines)
90
        -- existing node parsing
91
        nlist = obj `combineEithers` getObjectElement "nodes"
92
        ndata = applyEither1 fromJSObject nlist
93
        nobj = ndata `combineEithers` (ensureEitherList .
94
                                       map (\(x,y) ->
95
                                           asJSObject y `combineEithers`
96
                                                      parseNode x))
97
        nlines = nobj `combineEithers` (Right . unlines)
98
    in applyEither2 (,) nlines ilines
79
      request <- getObjectElement "request" obj
80
      rname <- getStringElement "name" request
81
      rtype <-  getStringElement "type" request >>= validateRequest
82
      inew <- (\x -> if x == Allocate then parseInstance rname request
83
                     else Ok "") rtype
84
      -- existing intstance parsing
85
      ilist <- getObjectElement "instances" obj
86
      let idata = fromJSObject ilist
87
      iobj <- (sequence . map (\(x,y) -> asJSObject y >>= parseInstance x))
88
              idata
89
      let ilines = unlines iobj
90
      -- existing node parsing
91
      nlist <- getObjectElement "nodes" obj
92
      let ndata = fromJSObject nlist
93
      nobj <- (sequence . map (\(x,y) -> asJSObject y >>= parseNode x))
94
              ndata
95
      let nlines = unlines nobj
96
      return $ (\ r nl il inew rnam ->
97
                    case r of
98
                      Allocate -> RqAlloc inew nl il
99
                      Relocate -> RqReloc rnam nl il)
100
                 rtype nlines ilines inew rname
101

  
99 102

  
100 103
formatResponse :: Bool -> String -> [String] -> String
101 104
formatResponse success info nodes =

Also available in: Unified diff