Statistics
| Branch: | Tag: | Revision:

root / htools / Ganeti / Config.hs @ c1c5aab1

History | View | Annotate | Download (6.9 kB)

1 eaa64cd8 Iustin Pop
{-| Implementation of the Ganeti configuration database.
2 eaa64cd8 Iustin Pop
3 eaa64cd8 Iustin Pop
-}
4 eaa64cd8 Iustin Pop
5 eaa64cd8 Iustin Pop
{-
6 eaa64cd8 Iustin Pop
7 eaa64cd8 Iustin Pop
Copyright (C) 2011, 2012 Google Inc.
8 eaa64cd8 Iustin Pop
9 eaa64cd8 Iustin Pop
This program is free software; you can redistribute it and/or modify
10 eaa64cd8 Iustin Pop
it under the terms of the GNU General Public License as published by
11 eaa64cd8 Iustin Pop
the Free Software Foundation; either version 2 of the License, or
12 eaa64cd8 Iustin Pop
(at your option) any later version.
13 eaa64cd8 Iustin Pop
14 eaa64cd8 Iustin Pop
This program is distributed in the hope that it will be useful, but
15 eaa64cd8 Iustin Pop
WITHOUT ANY WARRANTY; without even the implied warranty of
16 eaa64cd8 Iustin Pop
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 eaa64cd8 Iustin Pop
General Public License for more details.
18 eaa64cd8 Iustin Pop
19 eaa64cd8 Iustin Pop
You should have received a copy of the GNU General Public License
20 eaa64cd8 Iustin Pop
along with this program; if not, write to the Free Software
21 eaa64cd8 Iustin Pop
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 eaa64cd8 Iustin Pop
02110-1301, USA.
23 eaa64cd8 Iustin Pop
24 eaa64cd8 Iustin Pop
-}
25 eaa64cd8 Iustin Pop
26 eaa64cd8 Iustin Pop
module Ganeti.Config
27 eaa64cd8 Iustin Pop
    ( LinkIpMap
28 eaa64cd8 Iustin Pop
    , loadConfig
29 eaa64cd8 Iustin Pop
    , getNodeInstances
30 eaa64cd8 Iustin Pop
    , getDefaultNicLink
31 eaa64cd8 Iustin Pop
    , getInstancesIpByLink
32 eaa64cd8 Iustin Pop
    , getNode
33 eaa64cd8 Iustin Pop
    , getInstance
34 eaa64cd8 Iustin Pop
    , getInstPrimaryNode
35 d81ec8b7 Iustin Pop
    , getInstMinorsForNode
36 eaa64cd8 Iustin Pop
    , buildLinkIpInstnameMap
37 7b2ead5a Iustin Pop
    , instNodes
38 eaa64cd8 Iustin Pop
    ) where
39 eaa64cd8 Iustin Pop
40 eaa64cd8 Iustin Pop
import Data.List (foldl')
41 eaa64cd8 Iustin Pop
import qualified Data.Map as M
42 7b2ead5a Iustin Pop
import qualified Data.Set as S
43 eaa64cd8 Iustin Pop
import qualified Text.JSON as J
44 eaa64cd8 Iustin Pop
45 eaa64cd8 Iustin Pop
import Ganeti.HTools.JSON
46 eaa64cd8 Iustin Pop
import Ganeti.BasicTypes
47 eaa64cd8 Iustin Pop
48 eaa64cd8 Iustin Pop
import qualified Ganeti.Constants as C
49 eaa64cd8 Iustin Pop
import Ganeti.Objects
50 eaa64cd8 Iustin Pop
51 eaa64cd8 Iustin Pop
-- | Type alias for the link and ip map.
52 eaa64cd8 Iustin Pop
type LinkIpMap = M.Map String (M.Map String String)
53 eaa64cd8 Iustin Pop
54 eaa64cd8 Iustin Pop
-- | Reads the config file.
55 eaa64cd8 Iustin Pop
readConfig :: FilePath -> IO String
56 eaa64cd8 Iustin Pop
readConfig = readFile
57 eaa64cd8 Iustin Pop
58 eaa64cd8 Iustin Pop
-- | Parses the configuration file.
59 eaa64cd8 Iustin Pop
parseConfig :: String -> Result ConfigData
60 eaa64cd8 Iustin Pop
parseConfig = fromJResult "parsing configuration" . J.decodeStrict
61 eaa64cd8 Iustin Pop
62 eaa64cd8 Iustin Pop
-- | Wrapper over 'readConfig' and 'parseConfig'.
63 eaa64cd8 Iustin Pop
loadConfig :: FilePath -> IO (Result ConfigData)
64 eaa64cd8 Iustin Pop
loadConfig = fmap parseConfig . readConfig
65 eaa64cd8 Iustin Pop
66 eaa64cd8 Iustin Pop
-- * Query functions
67 eaa64cd8 Iustin Pop
68 7b2ead5a Iustin Pop
-- | Computes the nodes covered by a disk.
69 7b2ead5a Iustin Pop
computeDiskNodes :: Disk -> S.Set String
70 7b2ead5a Iustin Pop
computeDiskNodes dsk =
71 7b2ead5a Iustin Pop
  case diskLogicalId dsk of
72 7b2ead5a Iustin Pop
    LIDDrbd8 nodeA nodeB _ _ _ _ -> S.fromList [nodeA, nodeB]
73 7b2ead5a Iustin Pop
    _ -> S.empty
74 7b2ead5a Iustin Pop
75 7b2ead5a Iustin Pop
-- | Computes all disk-related nodes of an instance. For non-DRBD,
76 7b2ead5a Iustin Pop
-- this will be empty, for DRBD it will contain both the primary and
77 7b2ead5a Iustin Pop
-- the secondaries.
78 7b2ead5a Iustin Pop
instDiskNodes :: Instance -> S.Set String
79 7b2ead5a Iustin Pop
instDiskNodes = S.unions . map computeDiskNodes . instDisks
80 7b2ead5a Iustin Pop
81 7b2ead5a Iustin Pop
-- | Computes all nodes of an instance.
82 7b2ead5a Iustin Pop
instNodes :: Instance -> S.Set String
83 7b2ead5a Iustin Pop
instNodes inst = instPrimaryNode inst `S.insert` instDiskNodes inst
84 7b2ead5a Iustin Pop
85 7b2ead5a Iustin Pop
-- | Computes the secondary nodes of an instance. Since this is valid
86 7b2ead5a Iustin Pop
-- only for DRBD, we call directly 'instDiskNodes', skipping over the
87 7b2ead5a Iustin Pop
-- extra primary insert.
88 7b2ead5a Iustin Pop
instSecondaryNodes :: Instance -> S.Set String
89 7b2ead5a Iustin Pop
instSecondaryNodes inst =
90 7b2ead5a Iustin Pop
  instPrimaryNode inst `S.delete` instDiskNodes inst
91 7b2ead5a Iustin Pop
92 eaa64cd8 Iustin Pop
-- | Get instances of a given node.
93 eaa64cd8 Iustin Pop
getNodeInstances :: ConfigData -> String -> ([Instance], [Instance])
94 eaa64cd8 Iustin Pop
getNodeInstances cfg nname =
95 eaa64cd8 Iustin Pop
    let all_inst = M.elems . configInstances $ cfg
96 eaa64cd8 Iustin Pop
        pri_inst = filter ((== nname) . instPrimaryNode) all_inst
97 7b2ead5a Iustin Pop
        sec_inst = filter ((nname `S.member`) . instSecondaryNodes) all_inst
98 eaa64cd8 Iustin Pop
    in (pri_inst, sec_inst)
99 eaa64cd8 Iustin Pop
100 eaa64cd8 Iustin Pop
-- | Returns the default cluster link.
101 eaa64cd8 Iustin Pop
getDefaultNicLink :: ConfigData -> String
102 eaa64cd8 Iustin Pop
getDefaultNicLink =
103 eaa64cd8 Iustin Pop
  nicpLink . (M.! C.ppDefault) . clusterNicparams . configCluster
104 eaa64cd8 Iustin Pop
105 eaa64cd8 Iustin Pop
-- | Returns instances of a given link.
106 eaa64cd8 Iustin Pop
getInstancesIpByLink :: LinkIpMap -> String -> [String]
107 eaa64cd8 Iustin Pop
getInstancesIpByLink linkipmap link =
108 eaa64cd8 Iustin Pop
  M.keys $ M.findWithDefault M.empty link linkipmap
109 eaa64cd8 Iustin Pop
110 0fc8e521 Iustin Pop
-- | Generic lookup function that converts from a possible abbreviated
111 0fc8e521 Iustin Pop
-- name to a full name.
112 0fc8e521 Iustin Pop
getItem :: String -> String -> M.Map String a -> Result a
113 0fc8e521 Iustin Pop
getItem kind name allitems = do
114 0fc8e521 Iustin Pop
  let lresult = lookupName (M.keys allitems) name
115 0fc8e521 Iustin Pop
      err = \details -> Bad $ kind ++ " name " ++ name ++ " " ++ details
116 0fc8e521 Iustin Pop
  fullname <- case lrMatchPriority lresult of
117 0fc8e521 Iustin Pop
                PartialMatch -> Ok $ lrContent lresult
118 0fc8e521 Iustin Pop
                ExactMatch -> Ok $ lrContent lresult
119 0fc8e521 Iustin Pop
                MultipleMatch -> err "has multiple matches"
120 0fc8e521 Iustin Pop
                FailMatch -> err "not found"
121 0fc8e521 Iustin Pop
  maybe (err "not found after successfull match?!") Ok $
122 0fc8e521 Iustin Pop
        M.lookup fullname allitems
123 0fc8e521 Iustin Pop
124 eaa64cd8 Iustin Pop
-- | Looks up a node.
125 eaa64cd8 Iustin Pop
getNode :: ConfigData -> String -> Result Node
126 0fc8e521 Iustin Pop
getNode cfg name = getItem "Node" name (configNodes cfg)
127 eaa64cd8 Iustin Pop
128 eaa64cd8 Iustin Pop
-- | Looks up an instance.
129 eaa64cd8 Iustin Pop
getInstance :: ConfigData -> String -> Result Instance
130 0fc8e521 Iustin Pop
getInstance cfg name = getItem "Instance" name (configInstances cfg)
131 eaa64cd8 Iustin Pop
132 eaa64cd8 Iustin Pop
-- | Looks up an instance's primary node.
133 eaa64cd8 Iustin Pop
getInstPrimaryNode :: ConfigData -> String -> Result Node
134 eaa64cd8 Iustin Pop
getInstPrimaryNode cfg name =
135 eaa64cd8 Iustin Pop
  getInstance cfg name >>= return . instPrimaryNode >>= getNode cfg
136 eaa64cd8 Iustin Pop
137 d81ec8b7 Iustin Pop
-- | Filters DRBD minors for a given node.
138 d81ec8b7 Iustin Pop
getDrbdMinorsForNode :: String -> Disk -> [(Int, String)]
139 d81ec8b7 Iustin Pop
getDrbdMinorsForNode node disk =
140 d81ec8b7 Iustin Pop
  let child_minors = concatMap (getDrbdMinorsForNode node) (diskChildren disk)
141 d81ec8b7 Iustin Pop
      this_minors =
142 d81ec8b7 Iustin Pop
        case diskLogicalId disk of
143 d81ec8b7 Iustin Pop
          LIDDrbd8 nodeA nodeB _ minorA minorB _
144 d81ec8b7 Iustin Pop
            | nodeA == node -> [(minorA, nodeB)]
145 d81ec8b7 Iustin Pop
            | nodeB == node -> [(minorB, nodeA)]
146 d81ec8b7 Iustin Pop
          _ -> []
147 d81ec8b7 Iustin Pop
  in this_minors ++ child_minors
148 d81ec8b7 Iustin Pop
149 d81ec8b7 Iustin Pop
-- | String for primary role.
150 d81ec8b7 Iustin Pop
rolePrimary :: String
151 d81ec8b7 Iustin Pop
rolePrimary = "primary"
152 d81ec8b7 Iustin Pop
153 d81ec8b7 Iustin Pop
-- | String for secondary role.
154 d81ec8b7 Iustin Pop
roleSecondary :: String
155 d81ec8b7 Iustin Pop
roleSecondary = "secondary"
156 d81ec8b7 Iustin Pop
157 d81ec8b7 Iustin Pop
-- | Gets the list of DRBD minors for an instance that are related to
158 d81ec8b7 Iustin Pop
-- a given node.
159 d81ec8b7 Iustin Pop
getInstMinorsForNode :: String -> Instance
160 d81ec8b7 Iustin Pop
                     -> [(String, Int, String, String, String, String)]
161 d81ec8b7 Iustin Pop
getInstMinorsForNode node inst =
162 d81ec8b7 Iustin Pop
  let role = if node == instPrimaryNode inst
163 d81ec8b7 Iustin Pop
               then rolePrimary
164 d81ec8b7 Iustin Pop
               else roleSecondary
165 d81ec8b7 Iustin Pop
      iname = instName inst
166 d81ec8b7 Iustin Pop
  -- FIXME: the disk/ build there is hack-ish; unify this in a
167 d81ec8b7 Iustin Pop
  -- separate place, or reuse the iv_name (but that is deprecated on
168 d81ec8b7 Iustin Pop
  -- the Python side)
169 d81ec8b7 Iustin Pop
  in concatMap (\(idx, dsk) ->
170 d81ec8b7 Iustin Pop
            [(node, minor, iname, "disk/" ++ show idx, role, peer)
171 d81ec8b7 Iustin Pop
               | (minor, peer) <- getDrbdMinorsForNode node dsk]) .
172 d81ec8b7 Iustin Pop
     zip [(0::Int)..] . instDisks $ inst
173 d81ec8b7 Iustin Pop
174 eaa64cd8 Iustin Pop
-- | Builds link -> ip -> instname map.
175 eaa64cd8 Iustin Pop
--
176 eaa64cd8 Iustin Pop
-- TODO: improve this by splitting it into multiple independent functions:
177 eaa64cd8 Iustin Pop
--
178 eaa64cd8 Iustin Pop
-- * abstract the \"fetch instance with filled params\" functionality
179 eaa64cd8 Iustin Pop
--
180 eaa64cd8 Iustin Pop
-- * abstsract the [instance] -> [(nic, instance_name)] part
181 eaa64cd8 Iustin Pop
--
182 eaa64cd8 Iustin Pop
-- * etc.
183 eaa64cd8 Iustin Pop
buildLinkIpInstnameMap :: ConfigData -> LinkIpMap
184 eaa64cd8 Iustin Pop
buildLinkIpInstnameMap cfg =
185 eaa64cd8 Iustin Pop
  let cluster = configCluster cfg
186 eaa64cd8 Iustin Pop
      instances = M.elems . configInstances $ cfg
187 eaa64cd8 Iustin Pop
      defparams = (M.!) (clusterNicparams cluster) C.ppDefault
188 eaa64cd8 Iustin Pop
      nics = concatMap (\i -> [(instName i, nic) | nic <- instNics i])
189 eaa64cd8 Iustin Pop
             instances
190 eaa64cd8 Iustin Pop
  in foldl' (\accum (iname, nic) ->
191 eaa64cd8 Iustin Pop
               let pparams = nicNicparams nic
192 eaa64cd8 Iustin Pop
                   fparams = fillNICParams defparams pparams
193 eaa64cd8 Iustin Pop
                   link = nicpLink fparams
194 eaa64cd8 Iustin Pop
               in case nicIp nic of
195 eaa64cd8 Iustin Pop
                    Nothing -> accum
196 eaa64cd8 Iustin Pop
                    Just ip -> let oldipmap = M.findWithDefault (M.empty)
197 eaa64cd8 Iustin Pop
                                              link accum
198 eaa64cd8 Iustin Pop
                                   newipmap = M.insert ip iname oldipmap
199 eaa64cd8 Iustin Pop
                               in M.insert link newipmap accum
200 eaa64cd8 Iustin Pop
            ) M.empty nics