X-Git-Url: https://code.grnet.gr/git/ganeti-local/blobdiff_plain/ec629280ad3bb2b26d632754a12af8aeaf0bec2d..592601b3341e6b7dc44530282cb311c323ec6566:/htools/Ganeti/HTools/Rapi.hs diff --git a/htools/Ganeti/HTools/Rapi.hs b/htools/Ganeti/HTools/Rapi.hs index a754d08..710bfbb 100644 --- a/htools/Ganeti/HTools/Rapi.hs +++ b/htools/Ganeti/HTools/Rapi.hs @@ -30,15 +30,19 @@ module Ganeti.HTools.Rapi , parseData ) where +import Control.Exception +import Data.List (isPrefixOf) import Data.Maybe (fromMaybe) #ifndef NO_CURL import Network.Curl import Network.Curl.Types () #endif import Control.Monad +import Prelude hiding (catch) import Text.JSON (JSObject, fromJSObject, decodeStrict) import Text.JSON.Types (JSValue(..)) import Text.Printf (printf) +import System.FilePath import Ganeti.HTools.Loader import Ganeti.HTools.Types @@ -50,6 +54,10 @@ import qualified Ganeti.Constants as C {-# ANN module "HLint: ignore Eta reduce" #-} +-- | File method prefix. +filePrefix :: String +filePrefix = "file://" + -- | Read an URL via curl and return the body if successful. getUrl :: (Monad m) => String -> IO (m String) @@ -74,6 +82,12 @@ getUrl url = do url (show code)) #endif +-- | Helper to convert I/O errors in 'Bad' values. +ioErrToResult :: IO a -> IO (Result a) +ioErrToResult ioaction = + catch (ioaction >>= return . Ok) + (\e -> return . Bad . show $ (e::IOException)) + -- | Append the default port if not passed in. formatHost :: String -> String formatHost master = @@ -175,9 +189,9 @@ parseCluster obj = do return (tags, ipolicy) -- | Loads the raw cluster data from an URL. -readData :: String -- ^ Cluster or URL to use as source - -> IO (Result String, Result String, Result String, Result String) -readData master = do +readDataHttp :: String -- ^ Cluster or URL to use as source + -> IO (Result String, Result String, Result String, Result String) +readDataHttp master = do let url = formatHost master group_body <- getUrl $ printf "%s/2/groups?bulk=1" url node_body <- getUrl $ printf "%s/2/nodes?bulk=1" url @@ -185,6 +199,24 @@ readData master = do info_body <- getUrl $ printf "%s/2/info" url return (group_body, node_body, inst_body, info_body) +-- | Loads the raw cluster data from the filesystem. +readDataFile:: String -- ^ Path to the directory containing the files + -> IO (Result String, Result String, Result String, Result String) +readDataFile path = do + group_body <- ioErrToResult $ readFile $ path "groups.json" + node_body <- ioErrToResult $ readFile $ path "nodes.json" + inst_body <- ioErrToResult $ readFile $ path "instances.json" + info_body <- ioErrToResult $ readFile $ path "info.json" + return (group_body, node_body, inst_body, info_body) + +-- | Loads data via either 'readDataFile' or 'readDataHttp'. +readData :: String -- ^ URL to use as source + -> IO (Result String, Result String, Result String, Result String) +readData url = do + if filePrefix `isPrefixOf` url + then readDataFile (drop (length filePrefix) url) + else readDataHttp url + -- | Builds the cluster data from the raw Rapi content. parseData :: (Result String, Result String, Result String, Result String) -> Result ClusterData