1 {-| Implementation of the Ganeti configuration database.
7 Copyright (C) 2011, 2012 Google Inc.
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
31 , getInstancesIpByLink
35 , buildLinkIpInstnameMap
38 import Data.List (foldl')
39 import qualified Data.Map as M
40 import qualified Text.JSON as J
42 import Ganeti.HTools.JSON
43 import Ganeti.BasicTypes
45 import qualified Ganeti.Constants as C
48 -- | Type alias for the link and ip map.
49 type LinkIpMap = M.Map String (M.Map String String)
51 -- | Reads the config file.
52 readConfig :: FilePath -> IO String
55 -- | Parses the configuration file.
56 parseConfig :: String -> Result ConfigData
57 parseConfig = fromJResult "parsing configuration" . J.decodeStrict
59 -- | Wrapper over 'readConfig' and 'parseConfig'.
60 loadConfig :: FilePath -> IO (Result ConfigData)
61 loadConfig = fmap parseConfig . readConfig
65 -- | Get instances of a given node.
66 getNodeInstances :: ConfigData -> String -> ([Instance], [Instance])
67 getNodeInstances cfg nname =
68 let all_inst = M.elems . configInstances $ cfg
69 pri_inst = filter ((== nname) . instPrimaryNode) all_inst
70 -- FIXME: actually compute the secondary nodes
72 in (pri_inst, sec_inst)
74 -- | Returns the default cluster link.
75 getDefaultNicLink :: ConfigData -> String
77 nicpLink . (M.! C.ppDefault) . clusterNicparams . configCluster
79 -- | Returns instances of a given link.
80 getInstancesIpByLink :: LinkIpMap -> String -> [String]
81 getInstancesIpByLink linkipmap link =
82 M.keys $ M.findWithDefault M.empty link linkipmap
85 getNode :: ConfigData -> String -> Result Node
87 maybe (Bad $ "Node " ++ name ++ " not found") Ok $
88 M.lookup name (configNodes cfg)
90 -- | Looks up an instance.
91 getInstance :: ConfigData -> String -> Result Instance
92 getInstance cfg name =
93 maybe (Bad $ "Instance " ++ name ++ " not found") Ok $
94 M.lookup name (configInstances cfg)
96 -- | Looks up an instance's primary node.
97 getInstPrimaryNode :: ConfigData -> String -> Result Node
98 getInstPrimaryNode cfg name =
99 getInstance cfg name >>= return . instPrimaryNode >>= getNode cfg
101 -- | Builds link -> ip -> instname map.
103 -- TODO: improve this by splitting it into multiple independent functions:
105 -- * abstract the \"fetch instance with filled params\" functionality
107 -- * abstsract the [instance] -> [(nic, instance_name)] part
110 buildLinkIpInstnameMap :: ConfigData -> LinkIpMap
111 buildLinkIpInstnameMap cfg =
112 let cluster = configCluster cfg
113 instances = M.elems . configInstances $ cfg
114 defparams = (M.!) (clusterNicparams cluster) C.ppDefault
115 nics = concatMap (\i -> [(instName i, nic) | nic <- instNics i])
117 in foldl' (\accum (iname, nic) ->
118 let pparams = nicNicparams nic
119 fparams = fillNICParams defparams pparams
120 link = nicpLink fparams
123 Just ip -> let oldipmap = M.findWithDefault (M.empty)
125 newipmap = M.insert ip iname oldipmap
126 in M.insert link newipmap accum