From 1c035cb359448b5363860df55509f217df18a22a Mon Sep 17 00:00:00 2001 From: Iustin Pop Date: Thu, 21 May 2009 01:26:51 +0100 Subject: [PATCH] Introduce nice errors on invalid input fields This patch switches from plain read to a wrapper over readsPrec that returns better error messages than the buildin 'Prelude: no parse'. --- Ganeti/HTools/Cluster.hs | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/Ganeti/HTools/Cluster.hs b/Ganeti/HTools/Cluster.hs index f78a8c0..543df7c 100644 --- a/Ganeti/HTools/Cluster.hs +++ b/Ganeti/HTools/Cluster.hs @@ -743,6 +743,16 @@ stripSuffix suffix lst = let sflen = length suffix in map (\ (key, name) -> (key, take ((length name) - sflen) name)) lst +-- | Safe 'read' function returning data encapsulated in a Result +tryRead :: (Monad m, Read a) => String -> String -> m a +tryRead name s = + let sols = readsPrec 0 s + in case sols of + (v, ""):[] -> return v + (_, e):[] -> fail $ name ++ ": leftover characters when parsing '" + ++ s ++ "': '" ++ e ++ "'" + _ -> fail $ name ++ ": cannot parse string '" ++ s ++ "'" + -- | Lookups a node into an assoc list lookupNode :: (Monad m) => String -> String -> [(String, Int)] -> m Int lookupNode node inst ktn = @@ -752,12 +762,16 @@ lookupNode node inst ktn = loadNode :: (Monad m) => [String] -> m (String, Node.Node) loadNode (name:tm:nm:fm:td:fd:fo:[]) = do - let new_node = - if any (== "?") [tm,nm,fm,td,fd] || fo == "Y" then - Node.create 0 0 0 0 0 True - else - Node.create (read tm) (read nm) (read fm) - (read td) (read fd) False + new_node <- + if any (== "?") [tm,nm,fm,td,fd] || fo == "Y" then + return $ Node.create 0 0 0 0 0 True + else do + vtm <- tryRead name tm + vnm <- tryRead name nm + vfm <- tryRead name fm + vtd <- tryRead name td + vfd <- tryRead name fd + return $ Node.create vtm vnm vfm vtd vfd False return (name, new_node) loadNode s = fail $ "Invalid/incomplete node data: '" ++ (show s) ++ "'" @@ -766,9 +780,11 @@ loadInst :: (Monad m) => loadInst ktn (name:mem:dsk:status:pnode:snode:[]) = do pidx <- lookupNode pnode name ktn sidx <- lookupNode snode name ktn + vmem <- tryRead name mem + vdsk <- tryRead name dsk when (sidx == pidx) $ fail $ "Instance " ++ name ++ " has same primary and secondary node - " ++ pnode - let newinst = Instance.create (read mem) (read dsk) status pidx sidx + let newinst = Instance.create vmem vdsk status pidx sidx return (name, newinst) loadInst _ s = fail $ "Invalid/incomplete instance data: '" ++ (show s) ++ "'" -- 1.7.10.4