Skip to content
Snippets Groups Projects
Commit 04864530 authored by Guido Trotter's avatar Guido Trotter
Browse files

Processor: acquire the BGL for LUs requiring it

If a LU required the BGL (all LUs do, right now, by default) we'll
acquire it in the Processor before starting them. For LUs that don't
we'll still acquire it, but in a shared fashion, so that they cannot run
together with LUs that do.

We'll also note down whether we own the BGL exclusively, and if we don't
and we try to chain a LU that does, we'll fail.

More work will need to be done, of course, to convert LUs not to require
the BGL, but this basic infrastructure should guarantee the coexistance
of the old and new world for the time being.

Reviewed-by: iustinp
parent 1c901d13
No related branches found
No related tags found
No related merge requests found
......@@ -37,6 +37,7 @@ from ganeti import cmdlib
from ganeti import config
from ganeti import ssconf
from ganeti import logger
from ganeti import locking
class Processor(object):
......@@ -98,6 +99,7 @@ class Processor(object):
"""
self.context = context
self._feedback_fn = feedback
self.exclusive_BGL = False
def ExecOpCode(self, op):
"""Execute an opcode.
......@@ -120,24 +122,31 @@ class Processor(object):
sstore = ssconf.SimpleStore()
write_count = self.context.cfg.write_count
lu = lu_class(self, op, self.context.cfg, sstore)
lu.CheckPrereq()
hm = HooksMaster(rpc.call_hooks_runner, self, lu)
h_results = hm.RunPhase(constants.HOOKS_PHASE_PRE)
lu.HooksCallBack(constants.HOOKS_PHASE_PRE,
h_results, self._feedback_fn, None)
# Acquire the Big Ganeti Lock exclusively if this LU requires it, and in a
# shared fashion otherwise (to prevent concurrent run with an exclusive LU.
self.context.GLM.acquire(locking.LEVEL_CLUSTER, [locking.BGL],
shared=not lu_class.REQ_BGL)
try:
result = lu.Exec(self._feedback_fn)
h_results = hm.RunPhase(constants.HOOKS_PHASE_POST)
result = lu.HooksCallBack(constants.HOOKS_PHASE_POST,
h_results, self._feedback_fn, result)
finally:
if lu.cfg is not None:
# we use lu.cfg and not self.cfg as for init cluster, self.cfg
# is None but lu.cfg has been recently initialized in the
# lu.Exec method
if write_count != lu.cfg.write_count:
self.exclusive_BGL = lu_class.REQ_BGL
lu = lu_class(self, op, self.context.cfg, sstore)
lu.CheckPrereq()
hm = HooksMaster(rpc.call_hooks_runner, self, lu)
h_results = hm.RunPhase(constants.HOOKS_PHASE_PRE)
lu.HooksCallBack(constants.HOOKS_PHASE_PRE, h_results,
self._feedback_fn, None)
try:
result = lu.Exec(self._feedback_fn)
h_results = hm.RunPhase(constants.HOOKS_PHASE_POST)
result = lu.HooksCallBack(constants.HOOKS_PHASE_POST, h_results,
self._feedback_fn, result)
finally:
# FIXME: This needs locks if not lu_class.REQ_BGL
if write_count != self.context.cfg.write_count:
hm.RunConfigUpdate()
finally:
self.context.GLM.release(locking.LEVEL_CLUSTER)
self.exclusive_BGL = False
return result
......@@ -158,6 +167,10 @@ class Processor(object):
if lu_class is None:
raise errors.OpCodeUnknown("Unknown opcode")
if lu_class.REQ_BGL and not self.exclusive_BGL:
raise errors.ProgrammerError("LUs which require the BGL cannot"
" be chained to granular ones.")
if lu_class.REQ_WSSTORE:
sstore = ssconf.WritableSimpleStore()
else:
......
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