From b768099e117139468031af5e5282d2cc1230e97d Mon Sep 17 00:00:00 2001 From: Iustin Pop <iustin@google.com> Date: Tue, 28 Jun 2011 14:24:45 +0200 Subject: [PATCH] Fix bug in recreate-disks for DRBD instances The new functionality in 2.4.2 for recreate-disks to change nodes is broken for DRBD instances: it simply changes the nodes without caring for the DRBD minors mapping, which will lead to conflicts in non-empty clusters. This patch changes Exec() method of this LU significantly, to both fix the DRBD minor usage and make sure that we don't have partial modification to the instance objects: - the first half of the method makes all the checks and computes the needed configuration changes - the second half then performs the configuration changes and recreates the disks This way, instances will either be fully modified or not at all; whether the disks are successfully recreate is another point, but at least we'll have the configuration sane. Signed-off-by: Iustin Pop <iustin@google.com> Reviewed-by: Michael Hanselmann <hansmi@google.com> --- lib/cmdlib.py | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/lib/cmdlib.py b/lib/cmdlib.py index 7ae8ee334..b3a40a265 100644 --- a/lib/cmdlib.py +++ b/lib/cmdlib.py @@ -5524,31 +5524,44 @@ class LUInstanceRecreateDisks(LogicalUnit): """Recreate the disks. """ - # change primary node, if needed - if self.op.nodes: - self.instance.primary_node = self.op.nodes[0] - self.LogWarning("Changing the instance's nodes, you will have to" - " remove any disks left on the older nodes manually") + instance = self.instance to_skip = [] - for idx, disk in enumerate(self.instance.disks): + mods = [] # keeps track of needed logical_id changes + + for idx, disk in enumerate(instance.disks): if idx not in self.op.disks: # disk idx has not been passed in to_skip.append(idx) continue # update secondaries for disks, if needed if self.op.nodes: if disk.dev_type == constants.LD_DRBD8: - # need to update the nodes + # need to update the nodes and minors assert len(self.op.nodes) == 2 - logical_id = list(disk.logical_id) - logical_id[0] = self.op.nodes[0] - logical_id[1] = self.op.nodes[1] - disk.logical_id = tuple(logical_id) + assert len(disk.logical_id) == 6 # otherwise disk internals + # have changed + (_, _, old_port, _, _, old_secret) = disk.logical_id + new_minors = self.cfg.AllocateDRBDMinor(self.op.nodes, instance.name) + new_id = (self.op.nodes[0], self.op.nodes[1], old_port, + new_minors[0], new_minors[1], old_secret) + assert len(disk.logical_id) == len(new_id) + mods.append((idx, new_id)) + + # now that we have passed all asserts above, we can apply the mods + # in a single run (to avoid partial changes) + for idx, new_id in mods: + instance.disks[idx].logical_id = new_id + + # change primary node, if needed + if self.op.nodes: + instance.primary_node = self.op.nodes[0] + self.LogWarning("Changing the instance's nodes, you will have to" + " remove any disks left on the older nodes manually") if self.op.nodes: - self.cfg.Update(self.instance, feedback_fn) + self.cfg.Update(instance, feedback_fn) - _CreateDisks(self, self.instance, to_skip=to_skip) + _CreateDisks(self, instance, to_skip=to_skip) class LUInstanceRename(LogicalUnit): -- GitLab