Commit b768099e authored by Iustin Pop's avatar Iustin Pop
Browse files

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: default avatarIustin Pop <iustin@google.com>
Reviewed-by: default avatarMichael Hanselmann <hansmi@google.com>
parent 78ff9e8f
......@@ -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):
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment