35 |
35 |
, lockLevel
|
36 |
36 |
) where
|
37 |
37 |
|
38 |
|
import Control.Monad ((>=>), liftM)
|
|
38 |
import Control.Monad ((>=>))
|
39 |
39 |
import Control.Monad.Base (MonadBase, liftBase)
|
40 |
40 |
import Control.Monad.Error (MonadError, catchError)
|
41 |
41 |
import Data.List (stripPrefix)
|
... | ... | |
44 |
44 |
|
45 |
45 |
import Ganeti.BasicTypes
|
46 |
46 |
import Ganeti.Errors (ResultG, GanetiException)
|
47 |
|
import Ganeti.JSON (readEitherString, fromJResultE, MaybeForJSON(..))
|
|
47 |
import Ganeti.JSON (readEitherString, fromJResultE)
|
48 |
48 |
import Ganeti.Locking.Allocation
|
49 |
49 |
import Ganeti.Locking.Types
|
50 |
50 |
import Ganeti.Logging.Lifted (MonadLog, logDebug, logEmergency)
|
... | ... | |
189 |
189 |
-- identifier file.
|
190 |
190 |
--
|
191 |
191 |
-- The JobId isn't enough to identify a client as the master daemon
|
192 |
|
-- also handles RPC calls that aren't jobs, but which use the configuration.
|
193 |
|
-- Therefore it's needed to include the identification for threads.
|
194 |
|
-- An alternative would be to use something like @Either JobId RpcCallId@.
|
195 |
|
--
|
196 |
|
-- FIXME: Python threads are only unique wrt running threads, so it's possible
|
197 |
|
-- that a new thread will get a thread id that has been used before by another
|
198 |
|
-- finished thread. Since we rely on threads releasing their locks anyway,
|
199 |
|
-- this isn't a big issue, but in the future it'd be better to have a unique
|
200 |
|
-- identifier for each operation.
|
|
192 |
-- also handles client calls that aren't jobs, but which use the configuration.
|
|
193 |
-- These taks are identified by a unique name, reported to WConfD as a string.
|
201 |
194 |
data ClientId = ClientId
|
202 |
|
{ ciJobId :: Maybe JobId
|
203 |
|
, ciThreadId :: Integer
|
|
195 |
{ ciIdentifier :: Either String JobId
|
204 |
196 |
, ciLockFile :: FilePath
|
205 |
197 |
}
|
206 |
198 |
deriving (Ord, Eq, Show)
|
207 |
199 |
|
|
200 |
-- | Obtain the ClientID from its JSON representation.
|
|
201 |
clientIdFromJSON :: J.JSValue -> J.Result ClientId
|
|
202 |
clientIdFromJSON (J.JSArray [J.JSString s, J.JSString lf]) =
|
|
203 |
J.Ok . ClientId (Left $ J.fromJSString s) $ J.fromJSString lf
|
|
204 |
clientIdFromJSON (J.JSArray [jsjid, J.JSString lf]) =
|
|
205 |
J.readJSON jsjid >>= \jid -> J.Ok (ClientId (Right jid) (J.fromJSString lf))
|
|
206 |
clientIdFromJSON x = J.Error $ "malformed client id: " ++ show x
|
|
207 |
|
208 |
208 |
instance J.JSON ClientId where
|
209 |
|
showJSON (ClientId jid tid lf) = J.showJSON (MaybeForJSON jid, tid, lf)
|
210 |
|
readJSON = liftM (\(MaybeForJSON jid, tid, lf) -> ClientId jid tid lf)
|
211 |
|
. J.readJSON
|
|
209 |
showJSON (ClientId (Left name) lf) = J.showJSON (name, lf)
|
|
210 |
showJSON (ClientId (Right jid) lf) = J.showJSON (jid, lf)
|
|
211 |
readJSON = clientIdFromJSON
|
212 |
212 |
|
213 |
213 |
-- | The type of lock Allocations in Ganeti. In Ganeti, the owner of
|
214 |
214 |
-- locks are jobs.
|