Skip to content
Snippets Groups Projects
Commit be0cb2d7 authored by Michele Tartara's avatar Michele Tartara
Browse files

Properly export errors while reading job list


In case of problems while reading the job list from disk (such as permission
errors) confd would silently fail, writing a warning on the log file but
sending an empty list and no error message to the client.

Also, tests have been updated in accordance to the new interface of the modified
functions.

This commit fixes this problem [Issue 405].

Signed-off-by: default avatarMichele Tartara <mtartara@google.com>
Reviewed-by: default avatarGuido Trotter <ultrotter@google.com>
parent 3e02cd3c
No related branches found
No related tags found
No related merge requests found
...@@ -231,24 +231,28 @@ determineJobDirectories rootdir archived = do ...@@ -231,24 +231,28 @@ determineJobDirectories rootdir archived = do
return $ rootdir:other return $ rootdir:other
-- | Computes the list of all jobs in the given directories. -- | Computes the list of all jobs in the given directories.
getJobIDs :: [FilePath] -> IO [JobId] getJobIDs :: [FilePath] -> IO (Either IOError [JobId])
getJobIDs = liftM concat . mapM getDirJobIDs getJobIDs paths = liftM (fmap concat . sequence) (mapM getDirJobIDs paths)
-- | Sorts the a list of job IDs. -- | Sorts the a list of job IDs.
sortJobIDs :: [JobId] -> [JobId] sortJobIDs :: [JobId] -> [JobId]
sortJobIDs = sortBy (comparing fromJobId) sortJobIDs = sortBy (comparing fromJobId)
-- | Computes the list of jobs in a given directory. -- | Computes the list of jobs in a given directory.
getDirJobIDs :: FilePath -> IO [JobId] getDirJobIDs :: FilePath -> IO (Either IOError [JobId])
getDirJobIDs path = do getDirJobIDs path = do
contents <- getDirectoryContents path `Control.Exception.catch` either_contents <-
ignoreIOError [] False try (getDirectoryContents path) :: IO (Either IOError [FilePath])
("Failed to list job directory " ++ path) case either_contents of
let jids = foldl (\ids file -> Left e -> do
case parseJobFileId file of logWarning $ "Failed to list job directory " ++ path ++ ": " ++ show e
Nothing -> ids return $ Left e
Just new_id -> new_id:ids) [] contents Right contents -> do
return $ reverse jids let jids = foldl (\ids file ->
case parseJobFileId file of
Nothing -> ids
Just new_id -> new_id:ids) [] contents
return . Right $ reverse jids
-- | Reads the job data from disk. -- | Reads the job data from disk.
readJobDataFromDisk :: FilePath -> Bool -> JobId -> IO (Maybe (String, Bool)) readJobDataFromDisk :: FilePath -> Bool -> JobId -> IO (Maybe (String, Bool))
......
...@@ -53,7 +53,7 @@ module Ganeti.Query.Query ...@@ -53,7 +53,7 @@ module Ganeti.Query.Query
) where ) where
import Control.DeepSeq import Control.DeepSeq
import Control.Monad (filterM, liftM, foldM) import Control.Monad (filterM, foldM)
import Control.Monad.Trans (lift) import Control.Monad.Trans (lift)
import Data.List (intercalate) import Data.List (intercalate)
import Data.Maybe (fromMaybe) import Data.Maybe (fromMaybe)
...@@ -218,9 +218,14 @@ queryJobs cfg live fields qfilter = ...@@ -218,9 +218,14 @@ queryJobs cfg live fields qfilter =
Bad msg -> resultT . Bad $ GenericError msg Bad msg -> resultT . Bad $ GenericError msg
Ok [] -> if live Ok [] -> if live
-- we can check the filesystem for actual jobs -- we can check the filesystem for actual jobs
then lift $ liftM sortJobIDs then do
(determineJobDirectories rootdir want_arch >>= maybeJobIDs <-
getJobIDs) lift (determineJobDirectories rootdir want_arch
>>= getJobIDs)
case maybeJobIDs of
Left e -> (resultT . Bad) . BlockDeviceError $
"Unable to fetch the job list: " ++ show e
Right jobIDs -> resultT . Ok $ sortJobIDs jobIDs
-- else we shouldn't look at the filesystem... -- else we shouldn't look at the filesystem...
else return [] else return []
Ok v -> resultT $ Ok v Ok v -> resultT $ Ok v
......
...@@ -176,18 +176,27 @@ case_JobStatusPri_py_equiv = do ...@@ -176,18 +176,27 @@ case_JobStatusPri_py_equiv = do
-- | Tests listing of Job ids. -- | Tests listing of Job ids.
prop_ListJobIDs :: Property prop_ListJobIDs :: Property
prop_ListJobIDs = monadicIO $ do prop_ListJobIDs = monadicIO $ do
let extractJobIDs jIDs = do
either_jobs <- jIDs
case either_jobs of
Right j -> return j
Left e -> fail $ show e
isLeft e =
case e of
Left _ -> True
_ -> False
jobs <- pick $ resize 10 (listOf1 genJobId `suchThat` (\l -> l == nub l)) jobs <- pick $ resize 10 (listOf1 genJobId `suchThat` (\l -> l == nub l))
(e, f, g) <- (e, f, g) <-
run . withSystemTempDirectory "jqueue-test." $ \tempdir -> do run . withSystemTempDirectory "jqueue-test." $ \tempdir -> do
empty_dir <- getJobIDs [tempdir] empty_dir <- extractJobIDs $ getJobIDs [tempdir]
mapM_ (\jid -> writeFile (tempdir </> jobFileName jid) "") jobs mapM_ (\jid -> writeFile (tempdir </> jobFileName jid) "") jobs
full_dir <- getJobIDs [tempdir] full_dir <- extractJobIDs $ getJobIDs [tempdir]
invalid_dir <- getJobIDs [tempdir </> "no-such-dir"] invalid_dir <- getJobIDs [tempdir </> "no-such-dir"]
return (empty_dir, sortJobIDs full_dir, invalid_dir) return (empty_dir, sortJobIDs full_dir, invalid_dir)
stop $ conjoin [ printTestCase "empty directory" $ e ==? [] stop $ conjoin [ printTestCase "empty directory" $ e ==? []
, printTestCase "directory with valid names" $ , printTestCase "directory with valid names" $
f ==? sortJobIDs jobs f ==? sortJobIDs jobs
, printTestCase "invalid directory" $ g ==? [] , printTestCase "invalid directory" $ isLeft g
] ]
-- | Tests loading jobs from disk. -- | Tests loading jobs from disk.
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment