Statistics
| Branch: | Tag: | Revision:

root / Ganeti / HTools / IAlloc.hs @ ed41c179

History | View | Annotate | Download (3.9 kB)

1
{-| Implementation of the iallocator interface.
2

    
3
-}
4

    
5
module Ganeti.HTools.IAlloc
6
    (
7
      parseData
8
    , formatResponse
9
    , RqType(..)
10
    , Request(..)
11
    ) where
12

    
13
import Data.Either ()
14
--import Data.Maybe
15
import Control.Monad
16
import Text.JSON (JSObject, JSValue(JSBool, JSString, JSArray),
17
                  makeObj, encodeStrict, decodeStrict,
18
                  fromJSObject, toJSString)
19
--import Text.Printf (printf)
20
import qualified Ganeti.HTools.Node as Node
21
import qualified Ganeti.HTools.Instance as Instance
22
import Ganeti.HTools.Loader
23
import Ganeti.HTools.Utils
24
import Ganeti.HTools.Types
25

    
26
data RqType
27
    = Allocate Instance.Instance Int
28
    | Relocate Int Int [Int]
29
    deriving (Show)
30

    
31
data Request = Request RqType NodeList InstanceList String
32
    deriving (Show)
33

    
34
parseBaseInstance :: String
35
                  -> JSObject JSValue
36
                  -> Result (String, Instance.Instance)
37
parseBaseInstance n a = do
38
  disk <- case fromObj "disk_usage" a of
39
            Bad _ -> do
40
                all_d <- fromObj "disks" a >>= asObjectList
41
                szd <- mapM (fromObj "size") all_d
42
                let sze = map (+128) szd
43
                    szf = (sum sze)::Int
44
                return szf
45
            x@(Ok _) -> x
46
  mem <- fromObj "memory" a
47
  let running = "running"
48
  return $ (n, Instance.create n mem disk running 0 0)
49

    
50
parseInstance :: NameAssoc
51
              -> String
52
              -> JSObject JSValue
53
              -> Result (String, Instance.Instance)
54
parseInstance ktn n a = do
55
    base <- parseBaseInstance n a
56
    nodes <- fromObj "nodes" a
57
    pnode <- readEitherString $ head nodes
58
    snode <- readEitherString $ (head . tail) nodes
59
    pidx <- lookupNode ktn n pnode
60
    sidx <- lookupNode ktn n snode
61
    return (n, Instance.setBoth (snd base) pidx sidx)
62

    
63
parseNode :: String -> JSObject JSValue -> Result (String, Node.Node)
64
parseNode n a = do
65
    let name = n
66
    mtotal <- fromObj "total_memory" a
67
    mnode <- fromObj "reserved_memory" a
68
    mfree <- fromObj "free_memory" a
69
    dtotal <- fromObj "total_disk" a
70
    dfree <- fromObj "free_disk" a
71
    offline <- fromObj "offline" a
72
    drained <- fromObj "offline" a
73
    return $ (name, Node.create n mtotal mnode mfree dtotal dfree
74
                      (offline || drained))
75

    
76
parseData :: String -> Result Request
77
parseData body = do
78
  decoded <- fromJResult $ decodeStrict body
79
  let obj = decoded
80
  -- request parser
81
  request <- fromObj "request" obj
82
  rname <- fromObj "name" request
83
  -- existing node parsing
84
  nlist <- fromObj "nodes" obj
85
  let ndata = fromJSObject nlist
86
  nobj <- (mapM (\(x,y) -> asJSObject y >>= parseNode x)) ndata
87
  let (ktn, nl) = assignIndices nobj
88
  -- existing instance parsing
89
  ilist <- fromObj "instances" obj
90
  let idata = fromJSObject ilist
91
  iobj <- (mapM (\(x,y) -> asJSObject y >>= parseInstance ktn x)) idata
92
  let (kti, il) = assignIndices iobj
93
  (map_n, map_i, csf) <- mergeData (nl, il)
94
  req_nodes <- fromObj "required_nodes" request
95
  optype <- fromObj "type" request
96
  rqtype <-
97
      case optype of
98
        "allocate" ->
99
            do
100
              inew <- parseBaseInstance rname request
101
              let io = snd inew
102
              return $ Allocate io req_nodes
103
        "relocate" ->
104
            do
105
              ridx <- lookupNode kti rname rname
106
              ex_nodes <- fromObj "relocate_from" request
107
              let ex_nodes' = map (stripSuffix $ length csf) ex_nodes
108
              ex_idex <- mapM (findByName map_n) ex_nodes'
109
              return $ Relocate ridx req_nodes ex_idex
110
        other -> fail $ ("Invalid request type '" ++ other ++ "'")
111
  return $ Request rqtype map_n map_i csf
112

    
113
formatResponse :: Bool -> String -> [String] -> String
114
formatResponse success info nodes =
115
    let
116
        e_success = ("success", JSBool success)
117
        e_info = ("info", JSString . toJSString $ info)
118
        e_nodes = ("nodes", JSArray $ map (JSString . toJSString) nodes)
119
    in encodeStrict $ makeObj [e_success, e_info, e_nodes]