root / htools / Ganeti / Errors.hs @ 37904802
History | View | Annotate | Download (6.1 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 | ef3ad027 | Iustin Pop | ) where |
41 | ef3ad027 | Iustin Pop | |
42 | ef3ad027 | Iustin Pop | import Text.JSON hiding (Result, Ok) |
43 | f56fc1a6 | Iustin Pop | import System.Exit |
44 | ef3ad027 | Iustin Pop | |
45 | ef3ad027 | Iustin Pop | import Ganeti.THH |
46 | ef3ad027 | Iustin Pop | import Ganeti.BasicTypes |
47 | ef3ad027 | Iustin Pop | import qualified Ganeti.Constants as C |
48 | ef3ad027 | Iustin Pop | |
49 | ef3ad027 | Iustin Pop | -- | Error code types for 'OpPrereqError'. |
50 | ef3ad027 | Iustin Pop | $(declareSADT "ErrorCode" |
51 | ef3ad027 | Iustin Pop | [ ("ECodeResolver", 'C.errorsEcodeResolver) |
52 | ef3ad027 | Iustin Pop | , ("ECodeNoRes", 'C.errorsEcodeNores) |
53 | ef3ad027 | Iustin Pop | , ("ECodeInval", 'C.errorsEcodeInval) |
54 | ef3ad027 | Iustin Pop | , ("ECodeState", 'C.errorsEcodeState) |
55 | ef3ad027 | Iustin Pop | , ("ECodeNoEnt", 'C.errorsEcodeNoent) |
56 | ef3ad027 | Iustin Pop | , ("ECodeExists", 'C.errorsEcodeExists) |
57 | ef3ad027 | Iustin Pop | , ("ECodeNotUnique", 'C.errorsEcodeNotunique) |
58 | ef3ad027 | Iustin Pop | , ("ECodeFault", 'C.errorsEcodeFault) |
59 | ef3ad027 | Iustin Pop | , ("ECodeEnviron", 'C.errorsEcodeEnviron) |
60 | ef3ad027 | Iustin Pop | ]) |
61 | ef3ad027 | Iustin Pop | $(makeJSONInstance ''ErrorCode) |
62 | ef3ad027 | Iustin Pop | |
63 | ef3ad027 | Iustin Pop | $(genException "GanetiException" |
64 | ef3ad027 | Iustin Pop | [ ("GenericError", [excErrMsg]) |
65 | ef3ad027 | Iustin Pop | , ("LockError", [excErrMsg]) |
66 | ef3ad027 | Iustin Pop | , ("PidFileLockError", [excErrMsg]) |
67 | ef3ad027 | Iustin Pop | , ("HypervisorError", [excErrMsg]) |
68 | ef3ad027 | Iustin Pop | , ("ProgrammerError", [excErrMsg]) |
69 | ef3ad027 | Iustin Pop | , ("BlockDeviceError", [excErrMsg]) |
70 | ef3ad027 | Iustin Pop | , ("ConfigurationError", [excErrMsg]) |
71 | 86a24969 | Dato Simó | , ("ConfigVersionMismatch", [ ("expVer", [t| Int |]) |
72 | 86a24969 | Dato Simó | , ("actVer", [t| Int |])]) |
73 | ef3ad027 | Iustin Pop | , ("ReservationError", [excErrMsg]) |
74 | ef3ad027 | Iustin Pop | , ("RemoteError", [excErrMsg]) |
75 | ef3ad027 | Iustin Pop | , ("SignatureError", [excErrMsg]) |
76 | ef3ad027 | Iustin Pop | , ("ParameterError", [excErrMsg]) |
77 | ef3ad027 | Iustin Pop | , ("ResultValidationError", [excErrMsg]) |
78 | ef3ad027 | Iustin Pop | , ("OpPrereqError", [excErrMsg, ("errCode", [t| ErrorCode |])]) |
79 | ef3ad027 | Iustin Pop | , ("OpExecError", [excErrMsg]) |
80 | ef3ad027 | Iustin Pop | , ("OpResultError", [excErrMsg]) |
81 | ef3ad027 | Iustin Pop | , ("OpCodeUnknown", [excErrMsg]) |
82 | ef3ad027 | Iustin Pop | , ("JobLost", [excErrMsg]) |
83 | ef3ad027 | Iustin Pop | , ("JobFileCorrupted", [excErrMsg]) |
84 | ef3ad027 | Iustin Pop | , ("ResolverError", [ ("errHostname", [t| String |]) |
85 | ef3ad027 | Iustin Pop | , ("errResolverCode", [t| Int |]) |
86 | ef3ad027 | Iustin Pop | , ("errResolverMsg", [t| String |])]) |
87 | ef3ad027 | Iustin Pop | , ("HooksFailure", [excErrMsg]) |
88 | ef3ad027 | Iustin Pop | , ("HooksAbort", [("errs", [t| [(String, String, String)] |])]) |
89 | ef3ad027 | Iustin Pop | , ("UnitParseError", [excErrMsg]) |
90 | ef3ad027 | Iustin Pop | , ("ParseError", [excErrMsg]) |
91 | ef3ad027 | Iustin Pop | , ("TypeEnforcementError", [excErrMsg]) |
92 | bca39f5c | Iustin Pop | , ("X509CertError", [ ("certFileName", [t| String |]) |
93 | bca39f5c | Iustin Pop | , excErrMsg ]) |
94 | ef3ad027 | Iustin Pop | , ("TagError", [excErrMsg]) |
95 | ef3ad027 | Iustin Pop | , ("CommandError", [excErrMsg]) |
96 | ef3ad027 | Iustin Pop | , ("StorageError", [excErrMsg]) |
97 | ef3ad027 | Iustin Pop | , ("InotifyError", [excErrMsg]) |
98 | ef3ad027 | Iustin Pop | , ("JobQueueError", [excErrMsg]) |
99 | ef3ad027 | Iustin Pop | , ("JobQueueDrainError", [excErrMsg]) |
100 | ef3ad027 | Iustin Pop | , ("JobQueueFull", []) |
101 | ef3ad027 | Iustin Pop | , ("ConfdMagicError", [excErrMsg]) |
102 | ef3ad027 | Iustin Pop | , ("ConfdClientError", [excErrMsg]) |
103 | ef3ad027 | Iustin Pop | , ("UdpDataSizeError", [excErrMsg]) |
104 | ef3ad027 | Iustin Pop | , ("NoCtypesError", [excErrMsg]) |
105 | ef3ad027 | Iustin Pop | , ("IPAddressError", [excErrMsg]) |
106 | ef3ad027 | Iustin Pop | , ("LuxiError", [excErrMsg]) |
107 | ef3ad027 | Iustin Pop | , ("QueryFilterParseError", [excErrMsg]) -- not consistent with Python |
108 | ef3ad027 | Iustin Pop | , ("RapiTestResult", [excErrMsg]) |
109 | ef3ad027 | Iustin Pop | , ("FileStoragePathError", [excErrMsg]) |
110 | ef3ad027 | Iustin Pop | ]) |
111 | ef3ad027 | Iustin Pop | |
112 | ef3ad027 | Iustin Pop | instance JSON GanetiException where |
113 | ef3ad027 | Iustin Pop | showJSON = saveGanetiException |
114 | ef3ad027 | Iustin Pop | readJSON = loadGanetiException |
115 | ef3ad027 | Iustin Pop | |
116 | ef3ad027 | Iustin Pop | instance FromString GanetiException where |
117 | ef3ad027 | Iustin Pop | mkFromString = GenericError |
118 | ef3ad027 | Iustin Pop | |
119 | ef3ad027 | Iustin Pop | -- | Error monad using 'GanetiException' type alias. |
120 | ef3ad027 | Iustin Pop | type ErrorResult = GenericResult GanetiException |
121 | ef3ad027 | Iustin Pop | |
122 | ef3ad027 | Iustin Pop | $(genStrOfOp ''GanetiException "excName") |
123 | f56fc1a6 | Iustin Pop | |
124 | f56fc1a6 | Iustin Pop | -- | Returns the exit code of a program that should be used if we got |
125 | f56fc1a6 | Iustin Pop | -- back an exception from masterd. |
126 | f56fc1a6 | Iustin Pop | errorExitCode :: GanetiException -> ExitCode |
127 | f56fc1a6 | Iustin Pop | errorExitCode (ConfigurationError {}) = ExitFailure 2 |
128 | f56fc1a6 | Iustin Pop | errorExitCode _ = ExitFailure 1 |
129 | f56fc1a6 | Iustin Pop | |
130 | f56fc1a6 | Iustin Pop | -- | Formats an exception. |
131 | f56fc1a6 | Iustin Pop | formatError :: GanetiException -> String |
132 | f56fc1a6 | Iustin Pop | formatError (ConfigurationError msg) = |
133 | f56fc1a6 | Iustin Pop | "Corrup configuration file: " ++ msg ++ "\nAborting." |
134 | f56fc1a6 | Iustin Pop | formatError (HooksAbort errs) = |
135 | f56fc1a6 | Iustin Pop | unlines $ |
136 | f56fc1a6 | Iustin Pop | "Failure: hooks execution failed:": |
137 | f56fc1a6 | Iustin Pop | map (\(node, script, out) -> |
138 | f56fc1a6 | Iustin Pop | " node: " ++ node ++ ", script: " ++ script ++ |
139 | f56fc1a6 | Iustin Pop | if null out |
140 | f56fc1a6 | Iustin Pop | then " (no output)" |
141 | f56fc1a6 | Iustin Pop | else ", output: " ++ out |
142 | f56fc1a6 | Iustin Pop | ) errs |
143 | f56fc1a6 | Iustin Pop | formatError (HooksFailure msg) = |
144 | f56fc1a6 | Iustin Pop | "Failure: hooks general failure: " ++ msg |
145 | f56fc1a6 | Iustin Pop | formatError (ResolverError host _ _) = |
146 | f56fc1a6 | Iustin Pop | -- FIXME: in Python, this uses the system hostname to format the |
147 | f56fc1a6 | Iustin Pop | -- error differently if we are failing to resolve our own hostname |
148 | f56fc1a6 | Iustin Pop | "Failure: can't resolve hostname " ++ host |
149 | f56fc1a6 | Iustin Pop | formatError (OpPrereqError msg code) = |
150 | f56fc1a6 | Iustin Pop | "Failure: prerequisites not met for this" ++ |
151 | f56fc1a6 | Iustin Pop | " operation:\nerror type: " ++ show code ++ ", error details:\n" ++ msg |
152 | f56fc1a6 | Iustin Pop | formatError (OpExecError msg) = |
153 | f56fc1a6 | Iustin Pop | "Failure: command execution error:\n" ++ msg |
154 | f56fc1a6 | Iustin Pop | formatError (TagError msg) = |
155 | f56fc1a6 | Iustin Pop | "Failure: invalid tag(s) given:\n" ++ msg |
156 | f56fc1a6 | Iustin Pop | formatError (JobQueueDrainError _)= |
157 | f56fc1a6 | Iustin Pop | "Failure: the job queue is marked for drain and doesn't accept new requests" |
158 | f56fc1a6 | Iustin Pop | formatError JobQueueFull = |
159 | f56fc1a6 | Iustin Pop | "Failure: the job queue is full and doesn't accept new" ++ |
160 | f56fc1a6 | Iustin Pop | " job submissions until old jobs are archived" |
161 | f56fc1a6 | Iustin Pop | formatError (TypeEnforcementError msg) = |
162 | f56fc1a6 | Iustin Pop | "Parameter Error: " ++ msg |
163 | f56fc1a6 | Iustin Pop | formatError (ParameterError msg) = |
164 | f56fc1a6 | Iustin Pop | "Failure: unknown/wrong parameter name '" ++ msg ++ "'" |
165 | f56fc1a6 | Iustin Pop | formatError (JobLost msg) = |
166 | f56fc1a6 | Iustin Pop | "Error checking job status: " ++ msg |
167 | f56fc1a6 | Iustin Pop | formatError (QueryFilterParseError msg) = |
168 | f56fc1a6 | Iustin Pop | -- FIXME: in Python, this has a more complex error message |
169 | f56fc1a6 | Iustin Pop | "Error while parsing query filter: " ++ msg |
170 | f56fc1a6 | Iustin Pop | formatError (GenericError msg) = |
171 | f56fc1a6 | Iustin Pop | "Unhandled Ganeti error: " ++ msg |
172 | f56fc1a6 | Iustin Pop | formatError err = |
173 | f56fc1a6 | Iustin Pop | "Unhandled exception: " ++ show err |
174 | 7adb7dff | Iustin Pop | |
175 | 7adb7dff | Iustin Pop | -- | Convert from an 'ErrorResult' to a standard 'Result'. |
176 | 7adb7dff | Iustin Pop | errToResult :: ErrorResult a -> Result a |
177 | 7adb7dff | Iustin Pop | errToResult (Ok a) = Ok a |
178 | 7adb7dff | Iustin Pop | errToResult (Bad e) = Bad $ formatError e |