From 36c381d7045383280c76903f255ddcf601d52b15 Mon Sep 17 00:00:00 2001
From: Guido Trotter <ultrotter@google.com>
Date: Tue, 8 Jul 2008 16:31:41 +0000
Subject: [PATCH] Processor: Move LU execution to its own method

This makes the try...finally code simplier, and helps adding a more
complex locking structure before the actual execution. It also fixes a
concurrency bug caused by the fact that write_count was read before
acquiring the BGL, and thus spurious config update hooks run could have
been triggered. This doesn't solve the issue of running config update
hooks for concurrent LUs.

Reviewed-by: iustinp
---
 lib/mcpu.py | 39 +++++++++++++++++++++++----------------
 1 file changed, 23 insertions(+), 16 deletions(-)

diff --git a/lib/mcpu.py b/lib/mcpu.py
index fab8b6279..6bd0542ce 100644
--- a/lib/mcpu.py
+++ b/lib/mcpu.py
@@ -101,6 +101,28 @@ class Processor(object):
     self._feedback_fn = feedback
     self.exclusive_BGL = False
 
+  def _ExecLU(self, lu):
+    """Logical Unit execution sequence.
+
+    """
+    write_count = self.context.cfg.write_count
+    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()
+
+    return result
+
   def ExecOpCode(self, op):
     """Execute an opcode.
 
@@ -121,8 +143,6 @@ class Processor(object):
     else:
       sstore = ssconf.SimpleStore()
 
-    write_count = self.context.cfg.write_count
-
     # 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],
@@ -130,20 +150,7 @@ class Processor(object):
     try:
       self.exclusive_BGL = lu_class.REQ_BGL
       lu = lu_class(self, op, self.context, 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()
+      result = self._ExecLU(lu)
     finally:
       self.context.glm.release(locking.LEVEL_CLUSTER)
       self.exclusive_BGL = False
-- 
GitLab