Add functions to check and fix cluster data
[ganeti-local] / Ganeti / HTools / Utils.hs
1 {-| Utility functions -}
2
3 module Ganeti.HTools.Utils
4     (
5       debug
6     , isLeft
7     , fromLeft
8     , fromRight
9     , sepSplit
10     , swapPairs
11     , varianceCoeff
12     , readData
13     ) where
14
15 import Data.Either
16 import Data.List
17 import Monad
18 import System
19 import System.IO
20
21 import Debug.Trace
22
23 -- | To be used only for debugging, breaks referential integrity.
24 debug :: Show a => a -> a
25 debug x = trace (show x) x
26
27 -- | Check if the given argument is Left something
28 isLeft :: Either a b -> Bool
29 isLeft val =
30     case val of
31       Left _ -> True
32       _ -> False
33
34 fromLeft :: Either a b -> a
35 fromLeft = either (\x -> x) (\_ -> undefined)
36
37 fromRight :: Either a b -> b
38 fromRight = either (\_ -> undefined) id
39
40 -- | Comma-join a string list.
41 commaJoin :: [String] -> String
42 commaJoin = intercalate ","
43
44 -- | Split a string on a separator and return an array.
45 sepSplit :: Char -> String -> [String]
46 sepSplit sep s
47     | x == "" && xs == [] = []
48     | xs == []            = [x]
49     | ys == []            = x:"":[]
50     | otherwise           = x:(sepSplit sep ys)
51     where (x, xs) = break (== sep) s
52           ys = drop 1 xs
53
54 -- | Partial application of sepSplit to @'.'@
55 commaSplit :: String -> [String]
56 commaSplit = sepSplit ','
57
58 -- | Swap a list of @(a, b)@ into @(b, a)@
59 swapPairs :: [(a, b)] -> [(b, a)]
60 swapPairs = map (\ (a, b) -> (b, a))
61
62 -- Simple and slow statistical functions, please replace with better versions
63
64 -- | Mean value of a list.
65 meanValue :: Floating a => [a] -> a
66 meanValue lst = (sum lst) / (fromIntegral $ length lst)
67
68 -- | Standard deviation.
69 stdDev :: Floating a => [a] -> a
70 stdDev lst =
71     let mv = meanValue lst
72         square = (^ (2::Int)) -- silences "defaulting the constraint..."
73         av = sum $ map square $ map (\e -> e - mv) lst
74         bv = sqrt (av / (fromIntegral $ length lst))
75     in bv
76
77 -- | Coefficient of variation.
78 varianceCoeff :: Floating a => [a] -> a
79 varianceCoeff lst = (stdDev lst) / (fromIntegral $ length lst)
80
81 -- | Get a Right result or print the error and exit
82 readData :: (String -> IO (Either String String)) -> String -> IO String
83 readData fn host = do
84   nd <- fn host
85   when (isLeft nd) $
86        do
87          putStrLn $ fromLeft nd
88          exitWith $ ExitFailure 1
89   return $ fromRight nd