From: Michael Hanselmann Date: Wed, 22 Jul 2009 17:31:15 +0000 (+0200) Subject: Add new opcode to evacuate nodes X-Git-Tag: v2.1.0beta0~430^2~30 X-Git-Url: https://code.grnet.gr/git/ganeti-local/commitdiff_plain/7ffc5a860241a6221e4cd135a51c26e8d6b2ece5 Add new opcode to evacuate nodes Signed-off-by: Michael Hanselmann Reviewed-by: Guido Trotter --- diff --git a/doc/hooks.rst b/doc/hooks.rst index b2f05ce..ecd6c9e 100644 --- a/doc/hooks.rst +++ b/doc/hooks.rst @@ -145,6 +145,16 @@ Changes a node's parameters. :pre-execution: master node, the target node :post-execution: master node, the target node +OP_NODE_EVACUATE +++++++++++++++++ + +Relocate secondary instances from a node. + +:directory: node-evacuate +:env. vars: NEW_SECONDARY, NODE_NAME +:pre-execution: master node, target node +:post-execution: master node, target node + Instance operations ~~~~~~~~~~~~~~~~~~~ diff --git a/lib/cmdlib.py b/lib/cmdlib.py index 7d91a22..aeb22dc 100644 --- a/lib/cmdlib.py +++ b/lib/cmdlib.py @@ -5253,6 +5253,97 @@ class LUReplaceDisks(LogicalUnit): return env, nl, nl +class LUEvacuateNode(LogicalUnit): + """Relocate the secondary instances from a node. + + """ + HPATH = "node-evacuate" + HTYPE = constants.HTYPE_NODE + _OP_REQP = ["node_name"] + REQ_BGL = False + + def CheckArguments(self): + if not hasattr(self.op, "remote_node"): + self.op.remote_node = None + if not hasattr(self.op, "iallocator"): + self.op.iallocator = None + + TLReplaceDisks.CheckArguments(constants.REPLACE_DISK_CHG, + self.op.remote_node, + self.op.iallocator) + + def ExpandNames(self): + self.op.node_name = self.cfg.ExpandNodeName(self.op.node_name) + if self.op.node_name is None: + raise errors.OpPrereqError("Node '%s' not known" % self.op.node_name) + + self.needed_locks = {} + + # Declare node locks + if self.op.iallocator is not None: + self.needed_locks[locking.LEVEL_NODE] = locking.ALL_SET + + elif self.op.remote_node is not None: + remote_node = self.cfg.ExpandNodeName(self.op.remote_node) + if remote_node is None: + raise errors.OpPrereqError("Node '%s' not known" % + self.op.remote_node) + + self.op.remote_node = remote_node + + # Warning: do not remove the locking of the new secondary here + # unless DRBD8.AddChildren is changed to work in parallel; + # currently it doesn't since parallel invocations of + # FindUnusedMinor will conflict + self.needed_locks[locking.LEVEL_NODE] = [remote_node] + self.recalculate_locks[locking.LEVEL_NODE] = constants.LOCKS_APPEND + + else: + raise errors.OpPrereqError("Invalid parameters") + + # Create tasklets for replacing disks for all secondary instances on this + # node + names = [] + + for inst in _GetNodeSecondaryInstances(self.cfg, self.op.node_name): + logging.debug("Replacing disks for instance %s", inst.name) + names.append(inst.name) + + replacer = TLReplaceDisks(self, inst.name, constants.REPLACE_DISK_CHG, + self.op.iallocator, self.op.remote_node, []) + self.tasklets.append(replacer) + + self.instance_names = names + + # Declare instance locks + self.needed_locks[locking.LEVEL_INSTANCE] = self.instance_names + + def DeclareLocks(self, level): + # If we're not already locking all nodes in the set we have to declare the + # instance's primary/secondary nodes. + if (level == locking.LEVEL_NODE and + self.needed_locks[locking.LEVEL_NODE] is not locking.ALL_SET): + self._LockInstancesNodes() + + def BuildHooksEnv(self): + """Build hooks env. + + This runs on the master, the primary and all the secondaries. + + """ + env = { + "NODE_NAME": self.op.node_name, + } + + nl = [self.cfg.GetMasterNode()] + + if self.op.remote_node is not None: + env["NEW_SECONDARY"] = self.op.remote_node + nl.append(self.op.remote_node) + + return (env, nl, nl) + + class TLReplaceDisks(Tasklet): """Replaces disks for an instance. @@ -5423,6 +5514,8 @@ class TLReplaceDisks(Tasklet): This dispatches the disk replacement to the appropriate handler. """ + feedback_fn("Replacing disks for %s" % self.instance.name) + activate_disks = (not self.instance.admin_up) # Activate the instance disks if we're replacing them on a down instance diff --git a/lib/mcpu.py b/lib/mcpu.py index 78faa37..27e5ca3 100644 --- a/lib/mcpu.py +++ b/lib/mcpu.py @@ -57,6 +57,7 @@ class Processor(object): opcodes.OpRemoveNode: cmdlib.LURemoveNode, opcodes.OpSetNodeParams: cmdlib.LUSetNodeParams, opcodes.OpPowercycleNode: cmdlib.LUPowercycleNode, + opcodes.OpEvacuateNode: cmdlib.LUEvacuateNode, # instance lu opcodes.OpCreateInstance: cmdlib.LUCreateInstance, opcodes.OpReinstallInstance: cmdlib.LUReinstallInstance, diff --git a/lib/opcodes.py b/lib/opcodes.py index e7d34a8..e49d0be 100644 --- a/lib/opcodes.py +++ b/lib/opcodes.py @@ -350,6 +350,16 @@ class OpPowercycleNode(OpCode): "force", ] + +class OpEvacuateNode(OpCode): + """Relocate secondary instances from a node.""" + OP_ID = "OP_NODE_EVACUATE" + OP_DSC_FIELD = "node_name" + __slots__ = OpCode.__slots__ + [ + "node_name", "remote_node", "iallocator", + ] + + # instance opcodes class OpCreateInstance(OpCode):