Statistics
| Branch: | Tag: | Revision:

root / src / Ganeti / Runtime.hs @ 53822ec4

History | View | Annotate | Download (5.6 kB)

1 7946c25d Iustin Pop
{-| Implementation of the runtime configuration details.
2 7946c25d Iustin Pop
3 7946c25d Iustin Pop
-}
4 7946c25d Iustin Pop
5 7946c25d Iustin Pop
{-
6 7946c25d Iustin Pop
7 9411474b Iustin Pop
Copyright (C) 2011, 2012, 2013 Google Inc.
8 7946c25d Iustin Pop
9 7946c25d Iustin Pop
This program is free software; you can redistribute it and/or modify
10 7946c25d Iustin Pop
it under the terms of the GNU General Public License as published by
11 7946c25d Iustin Pop
the Free Software Foundation; either version 2 of the License, or
12 7946c25d Iustin Pop
(at your option) any later version.
13 7946c25d Iustin Pop
14 7946c25d Iustin Pop
This program is distributed in the hope that it will be useful, but
15 7946c25d Iustin Pop
WITHOUT ANY WARRANTY; without even the implied warranty of
16 7946c25d Iustin Pop
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 7946c25d Iustin Pop
General Public License for more details.
18 7946c25d Iustin Pop
19 7946c25d Iustin Pop
You should have received a copy of the GNU General Public License
20 7946c25d Iustin Pop
along with this program; if not, write to the Free Software
21 7946c25d Iustin Pop
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 7946c25d Iustin Pop
02110-1301, USA.
23 7946c25d Iustin Pop
24 7946c25d Iustin Pop
-}
25 7946c25d Iustin Pop
26 7946c25d Iustin Pop
module Ganeti.Runtime
27 7946c25d Iustin Pop
  ( GanetiDaemon(..)
28 7946c25d Iustin Pop
  , MiscGroup(..)
29 7946c25d Iustin Pop
  , GanetiGroup(..)
30 7946c25d Iustin Pop
  , RuntimeEnts
31 7946c25d Iustin Pop
  , daemonName
32 7946c25d Iustin Pop
  , daemonUser
33 7946c25d Iustin Pop
  , daemonGroup
34 7946c25d Iustin Pop
  , daemonLogFile
35 7946c25d Iustin Pop
  , daemonPidFile
36 7946c25d Iustin Pop
  , getEnts
37 7946c25d Iustin Pop
  , verifyDaemonUser
38 7946c25d Iustin Pop
  ) where
39 7946c25d Iustin Pop
40 7946c25d Iustin Pop
import Control.Exception
41 7946c25d Iustin Pop
import Control.Monad
42 7946c25d Iustin Pop
import qualified Data.Map as M
43 7946c25d Iustin Pop
import System.Exit
44 7946c25d Iustin Pop
import System.FilePath
45 7946c25d Iustin Pop
import System.IO
46 7946c25d Iustin Pop
import System.IO.Error
47 7946c25d Iustin Pop
import System.Posix.Types
48 7946c25d Iustin Pop
import System.Posix.User
49 7946c25d Iustin Pop
import Text.Printf
50 7946c25d Iustin Pop
51 7946c25d Iustin Pop
import qualified Ganeti.Constants as C
52 9eeb0aa5 Michael Hanselmann
import qualified Ganeti.Path as Path
53 7946c25d Iustin Pop
import Ganeti.BasicTypes
54 7946c25d Iustin Pop
55 7946c25d Iustin Pop
data GanetiDaemon = GanetiMasterd
56 7946c25d Iustin Pop
                  | GanetiNoded
57 7946c25d Iustin Pop
                  | GanetiRapi
58 7946c25d Iustin Pop
                  | GanetiConfd
59 f511082f Michele Tartara
                  | GanetiMond
60 7946c25d Iustin Pop
                    deriving (Show, Enum, Bounded, Eq, Ord)
61 7946c25d Iustin Pop
62 7946c25d Iustin Pop
data MiscGroup = DaemonsGroup
63 7946c25d Iustin Pop
               | AdminGroup
64 7946c25d Iustin Pop
                 deriving (Show, Enum, Bounded, Eq, Ord)
65 7946c25d Iustin Pop
66 7946c25d Iustin Pop
data GanetiGroup = DaemonGroup GanetiDaemon
67 7946c25d Iustin Pop
                 | ExtraGroup MiscGroup
68 7946c25d Iustin Pop
                   deriving (Show, Eq, Ord)
69 7946c25d Iustin Pop
70 7946c25d Iustin Pop
type RuntimeEnts = (M.Map GanetiDaemon UserID, M.Map GanetiGroup GroupID)
71 7946c25d Iustin Pop
72 7946c25d Iustin Pop
-- | Returns the daemon name for a given daemon.
73 7946c25d Iustin Pop
daemonName :: GanetiDaemon -> String
74 7946c25d Iustin Pop
daemonName GanetiMasterd = C.masterd
75 7946c25d Iustin Pop
daemonName GanetiNoded   = C.noded
76 7946c25d Iustin Pop
daemonName GanetiRapi    = C.rapi
77 7946c25d Iustin Pop
daemonName GanetiConfd   = C.confd
78 f511082f Michele Tartara
daemonName GanetiMond    = C.mond
79 7946c25d Iustin Pop
80 9411474b Iustin Pop
-- | Returns the log file base for a daemon.
81 9411474b Iustin Pop
daemonLogBase :: GanetiDaemon -> String
82 9411474b Iustin Pop
daemonLogBase GanetiMasterd = C.daemonsLogbaseGanetiMasterd
83 9411474b Iustin Pop
daemonLogBase GanetiNoded   = C.daemonsLogbaseGanetiNoded
84 9411474b Iustin Pop
daemonLogBase GanetiRapi    = C.daemonsLogbaseGanetiRapi
85 9411474b Iustin Pop
daemonLogBase GanetiConfd   = C.daemonsLogbaseGanetiConfd
86 f511082f Michele Tartara
daemonLogBase GanetiMond    = C.daemonsLogbaseGanetiMond
87 9411474b Iustin Pop
88 7946c25d Iustin Pop
-- | Returns the configured user name for a daemon.
89 7946c25d Iustin Pop
daemonUser :: GanetiDaemon -> String
90 7946c25d Iustin Pop
daemonUser GanetiMasterd = C.masterdUser
91 7946c25d Iustin Pop
daemonUser GanetiNoded   = C.nodedUser
92 7946c25d Iustin Pop
daemonUser GanetiRapi    = C.rapiUser
93 7946c25d Iustin Pop
daemonUser GanetiConfd   = C.confdUser
94 f511082f Michele Tartara
daemonUser GanetiMond    = C.mondUser
95 7946c25d Iustin Pop
96 7946c25d Iustin Pop
-- | Returns the configured group for a daemon.
97 7946c25d Iustin Pop
daemonGroup :: GanetiGroup -> String
98 7946c25d Iustin Pop
daemonGroup (DaemonGroup GanetiMasterd) = C.masterdGroup
99 7946c25d Iustin Pop
daemonGroup (DaemonGroup GanetiNoded)   = C.nodedGroup
100 7946c25d Iustin Pop
daemonGroup (DaemonGroup GanetiRapi)    = C.rapiGroup
101 7946c25d Iustin Pop
daemonGroup (DaemonGroup GanetiConfd)   = C.confdGroup
102 f511082f Michele Tartara
daemonGroup (DaemonGroup GanetiMond)    = C.mondGroup
103 7946c25d Iustin Pop
daemonGroup (ExtraGroup  DaemonsGroup)  = C.daemonsGroup
104 7946c25d Iustin Pop
daemonGroup (ExtraGroup  AdminGroup)    = C.adminGroup
105 7946c25d Iustin Pop
106 7946c25d Iustin Pop
-- | Returns the log file for a daemon.
107 29a30533 Iustin Pop
daemonLogFile :: GanetiDaemon -> IO FilePath
108 29a30533 Iustin Pop
daemonLogFile daemon = do
109 29a30533 Iustin Pop
  logDir <- Path.logDir
110 9411474b Iustin Pop
  return $ logDir </> daemonLogBase daemon <.> "log"
111 7946c25d Iustin Pop
112 7946c25d Iustin Pop
-- | Returns the pid file name for a daemon.
113 29a30533 Iustin Pop
daemonPidFile :: GanetiDaemon -> IO FilePath
114 29a30533 Iustin Pop
daemonPidFile daemon = do
115 29a30533 Iustin Pop
  runDir <- Path.runDir
116 29a30533 Iustin Pop
  return $ runDir </> daemonName daemon <.> "pid"
117 7946c25d Iustin Pop
118 7946c25d Iustin Pop
-- | All groups list. A bit hacking, as we can't enforce it's complete
119 7946c25d Iustin Pop
-- at compile time.
120 7946c25d Iustin Pop
allGroups :: [GanetiGroup]
121 7946c25d Iustin Pop
allGroups = map DaemonGroup [minBound..maxBound] ++
122 7946c25d Iustin Pop
            map ExtraGroup  [minBound..maxBound]
123 7946c25d Iustin Pop
124 7946c25d Iustin Pop
ignoreDoesNotExistErrors :: IO a -> IO (Result a)
125 7946c25d Iustin Pop
ignoreDoesNotExistErrors value = do
126 7946c25d Iustin Pop
  result <- tryJust (\e -> if isDoesNotExistError e
127 7946c25d Iustin Pop
                             then Just (show e)
128 7946c25d Iustin Pop
                             else Nothing) value
129 7946c25d Iustin Pop
  return $ eitherToResult result
130 7946c25d Iustin Pop
131 7946c25d Iustin Pop
-- | Computes the group/user maps.
132 7946c25d Iustin Pop
getEnts :: IO (Result RuntimeEnts)
133 7946c25d Iustin Pop
getEnts = do
134 7946c25d Iustin Pop
  users <- mapM (\daemon -> do
135 7946c25d Iustin Pop
                   entry <- ignoreDoesNotExistErrors .
136 7946c25d Iustin Pop
                            getUserEntryForName .
137 7946c25d Iustin Pop
                            daemonUser $ daemon
138 7946c25d Iustin Pop
                   return (entry >>= \e -> return (daemon, userID e))
139 7946c25d Iustin Pop
                ) [minBound..maxBound]
140 7946c25d Iustin Pop
  groups <- mapM (\group -> do
141 7946c25d Iustin Pop
                    entry <- ignoreDoesNotExistErrors .
142 7946c25d Iustin Pop
                             getGroupEntryForName .
143 7946c25d Iustin Pop
                             daemonGroup $ group
144 7946c25d Iustin Pop
                    return (entry >>= \e -> return (group, groupID e))
145 7946c25d Iustin Pop
                 ) allGroups
146 7946c25d Iustin Pop
  return $ do -- 'Result' monad
147 7946c25d Iustin Pop
    users'  <- sequence users
148 7946c25d Iustin Pop
    groups' <- sequence groups
149 7946c25d Iustin Pop
    let usermap = M.fromList users'
150 7946c25d Iustin Pop
        groupmap = M.fromList groups'
151 7946c25d Iustin Pop
    return (usermap, groupmap)
152 7946c25d Iustin Pop
153 7946c25d Iustin Pop
154 7946c25d Iustin Pop
-- | Checks whether a daemon runs as the right user.
155 7946c25d Iustin Pop
verifyDaemonUser :: GanetiDaemon -> RuntimeEnts -> IO ()
156 7946c25d Iustin Pop
verifyDaemonUser daemon ents = do
157 7946c25d Iustin Pop
  myuid <- getEffectiveUserID
158 7946c25d Iustin Pop
  -- note: we use directly ! as lookup failues shouldn't happen, due
159 7946c25d Iustin Pop
  -- to the above map construction
160 7946c25d Iustin Pop
  checkUidMatch (daemonName daemon) ((M.!) (fst ents) daemon) myuid
161 7946c25d Iustin Pop
162 7946c25d Iustin Pop
-- | Check that two UIDs are matching or otherwise exit.
163 7946c25d Iustin Pop
checkUidMatch :: String -> UserID -> UserID -> IO ()
164 7946c25d Iustin Pop
checkUidMatch name expected actual =
165 7946c25d Iustin Pop
  when (expected /= actual) $ do
166 7946c25d Iustin Pop
    hPrintf stderr "%s started using wrong user ID (%d), \
167 7946c25d Iustin Pop
                   \expected %d\n" name
168 7946c25d Iustin Pop
              (fromIntegral actual::Int)
169 7946c25d Iustin Pop
              (fromIntegral expected::Int) :: IO ()
170 7946c25d Iustin Pop
    exitWith $ ExitFailure C.exitFailure