From: Guido Trotter Date: Tue, 8 Jul 2008 16:31:55 +0000 (+0000) Subject: LogicalUnit: add ExpandNames function X-Git-Tag: v2.0.0alpha0~306 X-Git-Url: https://code.grnet.gr/git/ganeti-local/commitdiff_plain/d465bdc8658071c5b81f4bdc272758b388b4e8dc LogicalUnit: add ExpandNames function New concurrent LUs will need to call ExpandNames so that any names passed in by the user are canonicalized, and can be used by hooks, locking and other parts of the code. This was done in CheckPrereq before, but it's now splitted out, as it's needed for locking, which in turn CheckPrereq needs. Old LUs can be converted gradually. Reviewed-by: iustinp --- diff --git a/lib/cmdlib.py b/lib/cmdlib.py index 689d7e6..e7edabe 100644 --- a/lib/cmdlib.py +++ b/lib/cmdlib.py @@ -50,8 +50,8 @@ class LogicalUnit(object): """Logical Unit base class. Subclasses must follow these rules: - - implement CheckPrereq which also fills in the opcode instance - with all the fields (even if as None) + - implement ExpandNames + - implement CheckPrereq - implement Exec - implement BuildHooksEnv - redefine HPATH and HTYPE @@ -82,6 +82,7 @@ class LogicalUnit(object): self.cfg = context.cfg self.sstore = sstore self.context = context + self.needed_locks = None self.__ssh = None for attr_name in self._OP_REQP: @@ -109,6 +110,46 @@ class LogicalUnit(object): ssh = property(fget=__GetSSH) + def ExpandNames(self): + """Expand names for this LU. + + This method is called before starting to execute the opcode, and it should + update all the parameters of the opcode to their canonical form (e.g. a + short node name must be fully expanded after this method has successfully + completed). This way locking, hooks, logging, ecc. can work correctly. + + LUs which implement this method must also populate the self.needed_locks + member, as a dict with lock levels as keys, and a list of needed lock names + as values. Rules: + - Use an empty dict if you don't need any lock + - If you don't need any lock at a particular level omit that level + - Don't put anything for the BGL level + - If you want all locks at a level use None as a value + (this reflects what LockSet does, and will be replaced before + CheckPrereq with the full list of nodes that have been locked) + + Examples: + # Acquire all nodes and one instance + self.needed_locks = { + locking.LEVEL_NODE: None, + locking.LEVEL_INSTANCES: ['instance1.example.tld'], + } + # Acquire just two nodes + self.needed_locks = { + locking.LEVEL_NODE: ['node1.example.tld', 'node2.example.tld'], + } + # Acquire no locks + self.needed_locks = {} # No, you can't leave it to the default value None + + """ + # The implementation of this method is mandatory only if the new LU is + # concurrent, so that old LUs don't need to be changed all at the same + # time. + if self.REQ_BGL: + self.needed_locks = {} # Exclusive LUs don't need locks. + else: + raise NotImplementedError + def CheckPrereq(self): """Check prerequisites for this LU. @@ -121,9 +162,7 @@ class LogicalUnit(object): not fulfilled. Its return value is ignored. This method should also update all the parameters of the opcode to - their canonical form; e.g. a short node name must be fully - expanded after this method has successfully completed (so that - hooks, logging, etc. work correctly). + their canonical form if it hasn't been done by ExpandNames before. """ raise NotImplementedError diff --git a/lib/mcpu.py b/lib/mcpu.py index 6bd0542..0d9e703 100644 --- a/lib/mcpu.py +++ b/lib/mcpu.py @@ -150,6 +150,7 @@ class Processor(object): try: self.exclusive_BGL = lu_class.REQ_BGL lu = lu_class(self, op, self.context, sstore) + lu.ExpandNames() result = self._ExecLU(lu) finally: self.context.glm.release(locking.LEVEL_CLUSTER)