On Thu, Feb 23, 2012 at 04:39:15PM +0100, Iustin Pop wrote:
> On Thu, Feb 23, 2012 at 02:55:39PM +0100, Guido Trotter wrote:
> > On Tue, Feb 21, 2012 at 1:21 PM, Iustin Pop <[email protected]> wrote:
> > > +-- | All groups list. A bit hacking, as we can't enforce it's complete
> > > +-- at compile time.
> > > +allGroups :: [GanetiGroup]
> > > +allGroups = map DaemonGroup [minBound..maxBound] ++
> > > +            map ExtraGroup  [minBound..maxBound]
> > > +
> > 
> > Where do minBound and maxBound come from?
> 
> They are standard functions on the Bounded typeclass
> (http://hackage.haskell.org/packages/archive/base/latest/doc/html/Prelude.html#t:Bounded).
> They are pretty basic, and the idio above is simply a way to get all
> groups. Looking back at it, maybe we should make this a set or make sure
> the list only holds unique entries.
> 
> > > +exceptionToResult :: IO a -> IO (Result a)
> > > +exceptionToResult value = do
> > > +  result <- tryJust (\e -> if isDoesNotExistError e
> > > +                             then Nothing
> > > +                             else Just (show e)) value
> > > +  case result of
> > > +    Left e  -> return $ Bad (show e)
> > > +    Right v -> return $ Ok v
> > > +
> > 
> > Seems to be a very specific exception to a very specific result. Would
> > it be possible to rename the function to something more specific?
> 
> Right. Indeed, this is more like 'ignoreDoesNotExistErrors' or such.
> I'll send interdiff.
> 
> > > +-- | Checks whether a daemon runs as the right user.
> > > +verifyDaemonUser :: GanetiDaemon -> RuntimeEnts -> IO ()
> > > +verifyDaemonUser daemon ents = do
> > > +  myuid <- getEffectiveUserID
> > > +  case M.lookup daemon (fst ents) of
> > > +    -- shouldn't happen, due to the above map construction
> > > +    Nothing -> hPutStrLn stderr $ "Internal error: user entry for daemon 
> > > " ++
> > > +                                  daemonName daemon ++ " not found"
> > > +
> > 
> > Should we use M.! since we don't expect lookup to fail? That will
> > throw an error in case of failure, but this is an error condition
> > anyway, right?
> 
> Yes; whether to use directly or try and handle a bit better the error is
> the same to me.
> 
> > > +    Just uid -> when (uid /= myuid) $ do
> > > +                  hPrintf stderr "%s started using wrong user ID (%d), \
> > > +                                 \expected %d\n" (daemonName daemon)
> > > +                                 (fromIntegral myuid::Int)
> > > +                                 (fromIntegral uid::Int) :: IO ()
> > > +                  exitWith $ ExitFailure C.exitFailure
> > 
> > Maybe we can abstract this to a different function?
> > assertUIDMatch myuid uid
> 
> Sure! But I wouldn't call it assert, since it's not about internal
> condition; rather, checkUIDMatch.
> 
> > > diff --git a/lib/daemon.py b/lib/daemon.py
> > > index 1e41b80..d5c12c7 100644
> > > --- a/lib/daemon.py
> > > +++ b/lib/daemon.py
> > > @@ -621,6 +621,7 @@ def _VerifyDaemonUser(daemon_name):
> > >     constants.NODED: getents.noded_uid,
> > >     constants.CONFD: getents.confd_uid,
> > >     }
> > > +  assert daemon_name in daemon_uids, "Invalid daemon %s" % daemon_name
> > >
> > 
> > This should go in independently of the haskell code, right?
> 
> Yep.
> 
> > >   return (daemon_uids[daemon_name] == running_uid, running_uid,
> > >           daemon_uids[daemon_name])
> > > diff --git a/lib/runtime.py b/lib/runtime.py
> > > index 5180486..b2db408 100644
> > > --- a/lib/runtime.py
> > > +++ b/lib/runtime.py
> > > @@ -171,7 +171,7 @@ def GetEnts(resolver=GetentResolver):
> > >   """Singleton wrapper around resolver instance.
> > >
> > >   As this method is accessed by multiple threads at the same time
> > > -  we need to take thread-safty carefully
> > > +  we need to take thread-safety carefully.
> > >
> > 
> > Please fix this in some different patch! :)
> 
> And yep.

OK, interdiff, except for the Python bits:


diff --git a/htools/Ganeti/Runtime.hs b/htools/Ganeti/Runtime.hs
index f9bb2ef..b6371d3 100644
--- a/htools/Ganeti/Runtime.hs
+++ b/htools/Ganeti/Runtime.hs
@@ -105,26 +105,24 @@ allGroups :: [GanetiGroup]
 allGroups = map DaemonGroup [minBound..maxBound] ++
             map ExtraGroup  [minBound..maxBound]
 
-exceptionToResult :: IO a -> IO (Result a)
-exceptionToResult value = do
+ignoreDoesNotExistErrors :: IO a -> IO (Result a)
+ignoreDoesNotExistErrors value = do
   result <- tryJust (\e -> if isDoesNotExistError e
-                             then Nothing
-                             else Just (show e)) value
-  case result of
-    Left e  -> return $ Bad (show e)
-    Right v -> return $ Ok v
+                             then Just (show e)
+                             else Nothing) value
+  return $ eitherToResult result
 
 -- | Computes the group/user maps.
 getEnts :: IO (Result RuntimeEnts)
 getEnts = do
   users <- mapM (\daemon -> do
-                   entry <- exceptionToResult .
+                   entry <- ignoreDoesNotExistErrors .
                             getUserEntryForName .
                             daemonUser $ daemon
                    return (entry >>= \e -> return (daemon, userID e))
                 ) [minBound..maxBound]
   groups <- mapM (\group -> do
-                    entry <- exceptionToResult .
+                    entry <- ignoreDoesNotExistErrors .
                              getGroupEntryForName .
                              daemonGroup $ group
                     return (entry >>= \e -> return (group, groupID e))
@@ -141,14 +139,16 @@ getEnts = do
 verifyDaemonUser :: GanetiDaemon -> RuntimeEnts -> IO ()
 verifyDaemonUser daemon ents = do
   myuid <- getEffectiveUserID
-  case M.lookup daemon (fst ents) of
-    -- shouldn't happen, due to the above map construction
-    Nothing -> hPutStrLn stderr $ "Internal error: user entry for daemon " ++
-                                  daemonName daemon ++ " not found"
-
-    Just uid -> when (uid /= myuid) $ do
-                  hPrintf stderr "%s started using wrong user ID (%d), \
-                                 \expected %d\n" (daemonName daemon)
-                                 (fromIntegral myuid::Int)
-                                 (fromIntegral uid::Int) :: IO ()
-                  exitWith $ ExitFailure C.exitFailure
+  -- note: we use directly ! as lookup failues shouldn't happen, due
+  -- to the above map construction
+  checkUidMatch (daemonName daemon) ((M.!) (fst ents) daemon) myuid
+
+-- | Check that two UIDs are matching or otherwise exit.
+checkUidMatch :: String -> UserID -> UserID -> IO ()
+checkUidMatch name expected actual =
+  when (expected /= actual) $ do
+    hPrintf stderr "%s started using wrong user ID (%d), \
+                   \expected %d\n" name
+              (fromIntegral actual::Int)
+              (fromIntegral expected::Int) :: IO ()
+    exitWith $ ExitFailure C.exitFailure

-- 
iustin

Reply via email to