Statistics
| Branch: | Tag: | Revision:

root / src / Ganeti / Errors.hs @ b9202225

History | View | Annotate | Download (6.5 kB)

1 ef3ad027 Iustin Pop
{-# LANGUAGE TemplateHaskell #-}
2 ef3ad027 Iustin Pop
3 ef3ad027 Iustin Pop
{-| Implementation of the Ganeti error types.
4 ef3ad027 Iustin Pop
5 ef3ad027 Iustin Pop
This module implements our error hierarchy. Currently we implement one
6 ef3ad027 Iustin Pop
identical to the Python one; later we might one to have separate ones
7 ef3ad027 Iustin Pop
for frontend (clients), master and backend code.
8 ef3ad027 Iustin Pop
9 ef3ad027 Iustin Pop
-}
10 ef3ad027 Iustin Pop
11 ef3ad027 Iustin Pop
{-
12 ef3ad027 Iustin Pop
13 ef3ad027 Iustin Pop
Copyright (C) 2012 Google Inc.
14 ef3ad027 Iustin Pop
15 ef3ad027 Iustin Pop
This program is free software; you can redistribute it and/or modify
16 ef3ad027 Iustin Pop
it under the terms of the GNU General Public License as published by
17 ef3ad027 Iustin Pop
the Free Software Foundation; either version 2 of the License, or
18 ef3ad027 Iustin Pop
(at your option) any later version.
19 ef3ad027 Iustin Pop
20 ef3ad027 Iustin Pop
This program is distributed in the hope that it will be useful, but
21 ef3ad027 Iustin Pop
WITHOUT ANY WARRANTY; without even the implied warranty of
22 ef3ad027 Iustin Pop
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23 ef3ad027 Iustin Pop
General Public License for more details.
24 ef3ad027 Iustin Pop
25 ef3ad027 Iustin Pop
You should have received a copy of the GNU General Public License
26 ef3ad027 Iustin Pop
along with this program; if not, write to the Free Software
27 ef3ad027 Iustin Pop
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
28 ef3ad027 Iustin Pop
02110-1301, USA.
29 ef3ad027 Iustin Pop
30 ef3ad027 Iustin Pop
-}
31 ef3ad027 Iustin Pop
32 ef3ad027 Iustin Pop
module Ganeti.Errors
33 ef3ad027 Iustin Pop
  ( ErrorCode(..)
34 ef3ad027 Iustin Pop
  , GanetiException(..)
35 ef3ad027 Iustin Pop
  , ErrorResult
36 7adb7dff Iustin Pop
  , errToResult
37 f56fc1a6 Iustin Pop
  , errorExitCode
38 7adb7dff Iustin Pop
  , excName
39 f56fc1a6 Iustin Pop
  , formatError
40 9491766c Hrvoje Ribicic
  , maybeToError
41 ef3ad027 Iustin Pop
  ) where
42 ef3ad027 Iustin Pop
43 ed5a07f2 Petr Pudlak
import Control.Monad.Error (Error(..))
44 ef3ad027 Iustin Pop
import Text.JSON hiding (Result, Ok)
45 f56fc1a6 Iustin Pop
import System.Exit
46 ef3ad027 Iustin Pop
47 ef3ad027 Iustin Pop
import Ganeti.THH
48 ef3ad027 Iustin Pop
import Ganeti.BasicTypes
49 ef3ad027 Iustin Pop
import qualified Ganeti.Constants as C
50 ef3ad027 Iustin Pop
51 ef3ad027 Iustin Pop
-- | Error code types for 'OpPrereqError'.
52 ef3ad027 Iustin Pop
$(declareSADT "ErrorCode"
53 ef3ad027 Iustin Pop
  [ ("ECodeResolver",  'C.errorsEcodeResolver)
54 ef3ad027 Iustin Pop
  , ("ECodeNoRes",     'C.errorsEcodeNores)
55 6bee863c Michael Hanselmann
  , ("ECodeTempNoRes", 'C.errorsEcodeTempNores)
56 ef3ad027 Iustin Pop
  , ("ECodeInval",     'C.errorsEcodeInval)
57 ef3ad027 Iustin Pop
  , ("ECodeState",     'C.errorsEcodeState)
58 ef3ad027 Iustin Pop
  , ("ECodeNoEnt",     'C.errorsEcodeNoent)
59 ef3ad027 Iustin Pop
  , ("ECodeExists",    'C.errorsEcodeExists)
60 ef3ad027 Iustin Pop
  , ("ECodeNotUnique", 'C.errorsEcodeNotunique)
61 ef3ad027 Iustin Pop
  , ("ECodeFault",     'C.errorsEcodeFault)
62 ef3ad027 Iustin Pop
  , ("ECodeEnviron",   'C.errorsEcodeEnviron)
63 ef3ad027 Iustin Pop
  ])
64 ef3ad027 Iustin Pop
$(makeJSONInstance ''ErrorCode)
65 ef3ad027 Iustin Pop
66 ef3ad027 Iustin Pop
$(genException "GanetiException"
67 ef3ad027 Iustin Pop
  [ ("GenericError", [excErrMsg])
68 ef3ad027 Iustin Pop
  , ("LockError", [excErrMsg])
69 ef3ad027 Iustin Pop
  , ("PidFileLockError", [excErrMsg])
70 ef3ad027 Iustin Pop
  , ("HypervisorError", [excErrMsg])
71 ef3ad027 Iustin Pop
  , ("ProgrammerError", [excErrMsg])
72 ef3ad027 Iustin Pop
  , ("BlockDeviceError", [excErrMsg])
73 ef3ad027 Iustin Pop
  , ("ConfigurationError", [excErrMsg])
74 86a24969 Dato Simó
  , ("ConfigVersionMismatch", [ ("expVer", [t| Int |])
75 86a24969 Dato Simó
                              , ("actVer", [t| Int |])])
76 ef3ad027 Iustin Pop
  , ("ReservationError", [excErrMsg])
77 ef3ad027 Iustin Pop
  , ("RemoteError", [excErrMsg])
78 ef3ad027 Iustin Pop
  , ("SignatureError", [excErrMsg])
79 ef3ad027 Iustin Pop
  , ("ParameterError", [excErrMsg])
80 ef3ad027 Iustin Pop
  , ("ResultValidationError", [excErrMsg])
81 ef3ad027 Iustin Pop
  , ("OpPrereqError", [excErrMsg, ("errCode", [t| ErrorCode |])])
82 ef3ad027 Iustin Pop
  , ("OpExecError", [excErrMsg])
83 ef3ad027 Iustin Pop
  , ("OpResultError", [excErrMsg])
84 ef3ad027 Iustin Pop
  , ("OpCodeUnknown", [excErrMsg])
85 ef3ad027 Iustin Pop
  , ("JobLost", [excErrMsg])
86 ef3ad027 Iustin Pop
  , ("JobFileCorrupted", [excErrMsg])
87 ef3ad027 Iustin Pop
  , ("ResolverError", [ ("errHostname", [t| String |])
88 ef3ad027 Iustin Pop
                      , ("errResolverCode", [t| Int |])
89 ef3ad027 Iustin Pop
                      , ("errResolverMsg", [t| String |])])
90 ef3ad027 Iustin Pop
  , ("HooksFailure", [excErrMsg])
91 ef3ad027 Iustin Pop
  , ("HooksAbort", [("errs", [t| [(String, String, String)] |])])
92 ef3ad027 Iustin Pop
  , ("UnitParseError", [excErrMsg])
93 ef3ad027 Iustin Pop
  , ("ParseError", [excErrMsg])
94 ef3ad027 Iustin Pop
  , ("TypeEnforcementError", [excErrMsg])
95 bca39f5c Iustin Pop
  , ("X509CertError", [ ("certFileName", [t| String |])
96 bca39f5c Iustin Pop
                      , excErrMsg ])
97 ef3ad027 Iustin Pop
  , ("TagError", [excErrMsg])
98 ef3ad027 Iustin Pop
  , ("CommandError", [excErrMsg])
99 ef3ad027 Iustin Pop
  , ("StorageError", [excErrMsg])
100 ef3ad027 Iustin Pop
  , ("InotifyError", [excErrMsg])
101 ef3ad027 Iustin Pop
  , ("JobQueueError", [excErrMsg])
102 ef3ad027 Iustin Pop
  , ("JobQueueDrainError", [excErrMsg])
103 ef3ad027 Iustin Pop
  , ("JobQueueFull", [])
104 ef3ad027 Iustin Pop
  , ("ConfdMagicError", [excErrMsg])
105 ef3ad027 Iustin Pop
  , ("ConfdClientError", [excErrMsg])
106 ef3ad027 Iustin Pop
  , ("UdpDataSizeError", [excErrMsg])
107 ef3ad027 Iustin Pop
  , ("NoCtypesError", [excErrMsg])
108 ef3ad027 Iustin Pop
  , ("IPAddressError", [excErrMsg])
109 ef3ad027 Iustin Pop
  , ("LuxiError", [excErrMsg])
110 ef3ad027 Iustin Pop
  , ("QueryFilterParseError", [excErrMsg]) -- not consistent with Python
111 ef3ad027 Iustin Pop
  , ("RapiTestResult", [excErrMsg])
112 ef3ad027 Iustin Pop
  , ("FileStoragePathError", [excErrMsg])
113 ef3ad027 Iustin Pop
  ])
114 ef3ad027 Iustin Pop
115 ed5a07f2 Petr Pudlak
instance Error GanetiException where
116 ed5a07f2 Petr Pudlak
  strMsg = mkFromString
117 ed5a07f2 Petr Pudlak
118 ef3ad027 Iustin Pop
instance JSON GanetiException where
119 ef3ad027 Iustin Pop
  showJSON = saveGanetiException
120 ef3ad027 Iustin Pop
  readJSON = loadGanetiException
121 ef3ad027 Iustin Pop
122 ef3ad027 Iustin Pop
instance FromString GanetiException where
123 ef3ad027 Iustin Pop
  mkFromString = GenericError
124 ef3ad027 Iustin Pop
125 ef3ad027 Iustin Pop
-- | Error monad using 'GanetiException' type alias.
126 ef3ad027 Iustin Pop
type ErrorResult = GenericResult GanetiException
127 ef3ad027 Iustin Pop
128 ef3ad027 Iustin Pop
$(genStrOfOp ''GanetiException "excName")
129 f56fc1a6 Iustin Pop
130 f56fc1a6 Iustin Pop
-- | Returns the exit code of a program that should be used if we got
131 f56fc1a6 Iustin Pop
-- back an exception from masterd.
132 f56fc1a6 Iustin Pop
errorExitCode :: GanetiException -> ExitCode
133 f56fc1a6 Iustin Pop
errorExitCode (ConfigurationError {}) = ExitFailure 2
134 f56fc1a6 Iustin Pop
errorExitCode _ = ExitFailure 1
135 f56fc1a6 Iustin Pop
136 f56fc1a6 Iustin Pop
-- | Formats an exception.
137 f56fc1a6 Iustin Pop
formatError :: GanetiException -> String
138 f56fc1a6 Iustin Pop
formatError (ConfigurationError msg) =
139 f56fc1a6 Iustin Pop
  "Corrup configuration file: " ++ msg ++ "\nAborting."
140 f56fc1a6 Iustin Pop
formatError (HooksAbort errs) =
141 f56fc1a6 Iustin Pop
  unlines $
142 f56fc1a6 Iustin Pop
  "Failure: hooks execution failed:":
143 f56fc1a6 Iustin Pop
  map (\(node, script, out) ->
144 f56fc1a6 Iustin Pop
         "  node: " ++ node ++ ", script: " ++ script ++
145 f56fc1a6 Iustin Pop
                    if null out
146 f56fc1a6 Iustin Pop
                      then " (no output)"
147 f56fc1a6 Iustin Pop
                      else ", output: " ++ out
148 f56fc1a6 Iustin Pop
      ) errs
149 f56fc1a6 Iustin Pop
formatError (HooksFailure msg) =
150 f56fc1a6 Iustin Pop
  "Failure: hooks general failure: " ++ msg
151 f56fc1a6 Iustin Pop
formatError (ResolverError host _ _) =
152 f56fc1a6 Iustin Pop
  -- FIXME: in Python, this uses the system hostname to format the
153 f56fc1a6 Iustin Pop
  -- error differently if we are failing to resolve our own hostname
154 f56fc1a6 Iustin Pop
  "Failure: can't resolve hostname " ++ host
155 f56fc1a6 Iustin Pop
formatError (OpPrereqError msg code) =
156 f56fc1a6 Iustin Pop
  "Failure: prerequisites not met for this" ++
157 f56fc1a6 Iustin Pop
  " operation:\nerror type: " ++ show code ++ ", error details:\n" ++ msg
158 f56fc1a6 Iustin Pop
formatError (OpExecError msg) =
159 f56fc1a6 Iustin Pop
  "Failure: command execution error:\n" ++ msg
160 f56fc1a6 Iustin Pop
formatError (TagError msg) =
161 f56fc1a6 Iustin Pop
  "Failure: invalid tag(s) given:\n" ++ msg
162 f56fc1a6 Iustin Pop
formatError (JobQueueDrainError _)=
163 f56fc1a6 Iustin Pop
  "Failure: the job queue is marked for drain and doesn't accept new requests"
164 f56fc1a6 Iustin Pop
formatError JobQueueFull =
165 f56fc1a6 Iustin Pop
  "Failure: the job queue is full and doesn't accept new" ++
166 f56fc1a6 Iustin Pop
  " job submissions until old jobs are archived"
167 f56fc1a6 Iustin Pop
formatError (TypeEnforcementError msg) =
168 f56fc1a6 Iustin Pop
  "Parameter Error: " ++ msg
169 f56fc1a6 Iustin Pop
formatError (ParameterError msg) =
170 f56fc1a6 Iustin Pop
  "Failure: unknown/wrong parameter name '" ++ msg ++ "'"
171 f56fc1a6 Iustin Pop
formatError (JobLost msg) =
172 f56fc1a6 Iustin Pop
  "Error checking job status: " ++ msg
173 f56fc1a6 Iustin Pop
formatError (QueryFilterParseError msg) =
174 f56fc1a6 Iustin Pop
  -- FIXME: in Python, this has a more complex error message
175 f56fc1a6 Iustin Pop
  "Error while parsing query filter: " ++ msg
176 f56fc1a6 Iustin Pop
formatError (GenericError msg) =
177 f56fc1a6 Iustin Pop
  "Unhandled Ganeti error: " ++ msg
178 f56fc1a6 Iustin Pop
formatError err =
179 f56fc1a6 Iustin Pop
  "Unhandled exception: " ++ show err
180 7adb7dff Iustin Pop
181 7adb7dff Iustin Pop
-- | Convert from an 'ErrorResult' to a standard 'Result'.
182 7adb7dff Iustin Pop
errToResult :: ErrorResult a -> Result a
183 7adb7dff Iustin Pop
errToResult (Ok a)  = Ok a
184 7adb7dff Iustin Pop
errToResult (Bad e) = Bad $ formatError e
185 9491766c Hrvoje Ribicic
186 9491766c Hrvoje Ribicic
-- | Convert from a 'Maybe' to a an 'ErrorResult'.
187 9491766c Hrvoje Ribicic
maybeToError :: String -> Maybe a -> ErrorResult a
188 9491766c Hrvoje Ribicic
maybeToError _ (Just a) = Ok a
189 9491766c Hrvoje Ribicic
maybeToError m  Nothing = Bad $ GenericError m