Statistics
| Branch: | Tag: | Revision:

root / Ganeti / HTools / Rapi.hs @ f9fc7a63

History | View | Annotate | Download (3.1 kB)

1 a7654563 Iustin Pop
{-| Implementation of the RAPI client interface.
2 a7654563 Iustin Pop
3 a7654563 Iustin Pop
-}
4 a7654563 Iustin Pop
5 669d7e3d Iustin Pop
module Ganeti.HTools.Rapi
6 dd4c56ed Iustin Pop
    (
7 040afc35 Iustin Pop
      loadData
8 dd4c56ed Iustin Pop
    ) where
9 a7654563 Iustin Pop
10 a7654563 Iustin Pop
import Network.Curl
11 b8b9a53c Iustin Pop
import Network.Curl.Types ()
12 a7654563 Iustin Pop
import Network.Curl.Code
13 e015b554 Iustin Pop
import Data.List
14 a7654563 Iustin Pop
import Control.Monad
15 942403e6 Iustin Pop
import Text.JSON (JSObject, JSValue)
16 a7654563 Iustin Pop
import Text.Printf (printf)
17 040afc35 Iustin Pop
18 9ba5c28f Iustin Pop
import Ganeti.HTools.Utils
19 040afc35 Iustin Pop
import Ganeti.HTools.Loader
20 e4c5beaf Iustin Pop
import Ganeti.HTools.Types
21 040afc35 Iustin Pop
import qualified Ganeti.HTools.Node as Node
22 040afc35 Iustin Pop
import qualified Ganeti.HTools.Instance as Instance
23 a7654563 Iustin Pop
24 ba00ad4d Iustin Pop
-- | Read an URL via curl and return the body if successful
25 ba00ad4d Iustin Pop
getUrl :: (Monad m) => String -> IO (m String)
26 a7654563 Iustin Pop
getUrl url = do
27 a7654563 Iustin Pop
  (code, body) <- curlGetString url [CurlSSLVerifyPeer False,
28 a7654563 Iustin Pop
                                     CurlSSLVerifyHost 0]
29 a7654563 Iustin Pop
  return (case code of
30 ba00ad4d Iustin Pop
            CurlOK -> return body
31 ba00ad4d Iustin Pop
            _ -> fail $ printf "Curl error for '%s', error %s"
32 aab26f2d Iustin Pop
                 url (show code))
33 aab26f2d Iustin Pop
34 e015b554 Iustin Pop
-- | Append the default port if not passed in
35 e015b554 Iustin Pop
formatHost :: String -> String
36 e015b554 Iustin Pop
formatHost master =
37 e015b554 Iustin Pop
    if elem ':' master then  master
38 e015b554 Iustin Pop
    else "https://" ++ master ++ ":5080"
39 e015b554 Iustin Pop
40 040afc35 Iustin Pop
getInstances :: NameAssoc
41 040afc35 Iustin Pop
             -> String
42 040afc35 Iustin Pop
             -> Result [(String, Instance.Instance)]
43 040afc35 Iustin Pop
getInstances ktn body = do
44 040afc35 Iustin Pop
  arr <- loadJSArray body
45 040afc35 Iustin Pop
  ilist <- mapM (parseInstance ktn) arr
46 040afc35 Iustin Pop
  return ilist
47 a7654563 Iustin Pop
48 040afc35 Iustin Pop
getNodes :: String -> Result [(String, Node.Node)]
49 040afc35 Iustin Pop
getNodes body = do
50 040afc35 Iustin Pop
  arr <- loadJSArray body
51 040afc35 Iustin Pop
  nlist <- mapM parseNode arr
52 040afc35 Iustin Pop
  return nlist
53 a7654563 Iustin Pop
54 608efcce Iustin Pop
parseInstance :: [(String, Ndx)]
55 040afc35 Iustin Pop
              -> JSObject JSValue
56 040afc35 Iustin Pop
              -> Result (String, Instance.Instance)
57 040afc35 Iustin Pop
parseInstance ktn a = do
58 040afc35 Iustin Pop
  name <- fromObj "name" a
59 040afc35 Iustin Pop
  disk <- fromObj "disk_usage" a
60 040afc35 Iustin Pop
  mem <- fromObj "beparams" a >>= fromObj "memory"
61 040afc35 Iustin Pop
  pnode <- fromObj "pnode" a >>= lookupNode ktn name
62 e4c5beaf Iustin Pop
  snodes <- fromObj "snodes" a
63 040afc35 Iustin Pop
  snode <- (if null snodes then return Node.noSecondary
64 040afc35 Iustin Pop
            else readEitherString (head snodes) >>= lookupNode ktn name)
65 040afc35 Iustin Pop
  running <- fromObj "status" a
66 2727257a Iustin Pop
  let inst = Instance.create name mem disk running pnode snode
67 040afc35 Iustin Pop
  return (name, inst)
68 a7654563 Iustin Pop
69 040afc35 Iustin Pop
parseNode :: JSObject JSValue -> Result (String, Node.Node)
70 040afc35 Iustin Pop
parseNode a = do
71 040afc35 Iustin Pop
    name <- fromObj "name" a
72 040afc35 Iustin Pop
    offline <- fromObj "offline" a
73 040afc35 Iustin Pop
    node <- (case offline of
74 2727257a Iustin Pop
               True -> return $ Node.create name 0 0 0 0 0 True
75 040afc35 Iustin Pop
               _ -> do
76 040afc35 Iustin Pop
                 drained <- fromObj "drained" a
77 040afc35 Iustin Pop
                 mtotal <- fromObj "mtotal" a
78 040afc35 Iustin Pop
                 mnode <- fromObj "mnode" a
79 040afc35 Iustin Pop
                 mfree <- fromObj "mfree" a
80 040afc35 Iustin Pop
                 dtotal <- fromObj "dtotal" a
81 040afc35 Iustin Pop
                 dfree <- fromObj "dfree" a
82 2727257a Iustin Pop
                 return $ Node.create name mtotal mnode mfree
83 040afc35 Iustin Pop
                        dtotal dfree (offline || drained))
84 040afc35 Iustin Pop
    return (name, node)
85 00b15752 Iustin Pop
86 a8946537 Iustin Pop
loadData :: String -- ^ Cluster or URL to use as source
87 e3a684c5 Iustin Pop
         -> IO (Result (Node.AssocList, Instance.AssocList))
88 040afc35 Iustin Pop
loadData master = do -- IO monad
89 040afc35 Iustin Pop
  let url = formatHost master
90 040afc35 Iustin Pop
  node_body <- getUrl $ printf "%s/2/nodes?bulk=1" url
91 040afc35 Iustin Pop
  inst_body <- getUrl $ printf "%s/2/instances?bulk=1" url
92 040afc35 Iustin Pop
  return $ do -- Result monad
93 040afc35 Iustin Pop
    node_data <- node_body >>= getNodes
94 497e30a1 Iustin Pop
    let (node_names, node_idx) = assignIndices node_data
95 040afc35 Iustin Pop
    inst_data <- inst_body >>= getInstances node_names
96 e3a684c5 Iustin Pop
    let (_, inst_idx) = assignIndices inst_data
97 e3a684c5 Iustin Pop
    return (node_idx, inst_idx)