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

Extend DRBD disks with shared secret attribute

This patch, which is similar to r1679 (Extend DRBD disks with minors
attribute), extends the logical and physical id of the DRBD disks with a
shared secret attribute. This is generated at disk creation time and
saved in the config file.

The generation of the secret is done so that we don't have duplicates in
the configuration (otherwise the goal of preventing cross-connection
will not be reached), so we add to config.py more than just a simple
call to utils.GenerateSecret().

The patch does not yet enable the use of the secrets.

Reviewed-by: imsnah
parent 191712c0
......@@ -804,11 +804,11 @@ class DRBD8(BaseDRBD):
if len(children) not in (0, 2):
raise ValueError("Invalid configuration data %s" % str(children))
if not isinstance(unique_id, (tuple, list)) or len(unique_id) != 5:
if not isinstance(unique_id, (tuple, list)) or len(unique_id) != 6:
raise ValueError("Invalid configuration data %s" % str(unique_id))
(self._lhost, self._lport,
self._rhost, self._rport,
self._aminor) = unique_id
self._aminor, self._secret) = unique_id
if (self._lhost is not None and self._lhost == self._rhost and
self._lport == self._rport):
raise ValueError("Invalid configuration data, same local/remote %s" %
......
......@@ -2923,13 +2923,15 @@ def _GenerateDRBD8Branch(cfg, primary, secondary, size, names, iv_name,
"""
port = cfg.AllocatePort()
vgname = cfg.GetVGName()
shared_secret = cfg.GenerateDRBDSecret()
dev_data = objects.Disk(dev_type=constants.LD_LV, size=size,
logical_id=(vgname, names[0]))
dev_meta = objects.Disk(dev_type=constants.LD_LV, size=128,
logical_id=(vgname, names[1]))
drbd_dev = objects.Disk(dev_type=constants.LD_DRBD8, size=size,
logical_id=(primary, secondary, port,
p_minor, s_minor),
p_minor, s_minor,
shared_secret),
children=[dev_data, dev_meta],
iv_name=iv_name)
return drbd_dev
......@@ -4050,10 +4052,12 @@ class LUReplaceDisks(LogicalUnit):
# create new devices on new_node
if pri_node == dev.logical_id[0]:
new_logical_id = (pri_node, new_node,
dev.logical_id[2], dev.logical_id[3], new_minor)
dev.logical_id[2], dev.logical_id[3], new_minor,
dev.logical_id[5])
else:
new_logical_id = (new_node, pri_node,
dev.logical_id[2], new_minor, dev.logical_id[4])
dev.logical_id[2], new_minor, dev.logical_id[4],
dev.logical_id[5])
iv_names[dev.iv_name] = (dev, dev.children, new_logical_id)
logging.debug("Allocated new_minor: %s, new_logical_id: %s", new_minor,
new_logical_id)
......@@ -4079,9 +4083,9 @@ class LUReplaceDisks(LogicalUnit):
done = 0
for dev in instance.disks:
cfg.SetDiskID(dev, pri_node)
# set the physical (unique in bdev terms) id to None, meaning
# detach from network
dev.physical_id = (None, None, None, None, dev.physical_id[4])
# set the network part of the physical (unique in bdev terms) id
# to None, meaning detach from network
dev.physical_id = (None, None, None, None) + dev.physical_id[4:]
# and 'find' the device, which will 'fix' it to match the
# standalone state
if rpc.call_blockdev_find(pri_node, dev):
......
......@@ -126,6 +126,25 @@ class ConfigWriter:
all_macs = self._AllMACs()
return mac in all_macs
@locking.ssynchronized(_config_lock, shared=1)
def GenerateDRBDSecret(self):
"""Generate a DRBD secret.
This checks the current disks for duplicates.
"""
self._OpenConfig()
all_secrets = self._AllDRBDSecrets()
retries = 64
while retries > 0:
secret = utils.GenerateSecret()
if secret not in all_secrets:
break
retries -= 1
else:
raise errors.ConfigurationError("Can't generate unique DRBD secret")
return secret
def _ComputeAllLVs(self):
"""Compute the list of all LVs.
......@@ -185,6 +204,25 @@ class ConfigWriter:
return result
def _AllDRBDSecrets(self):
"""Return all DRBD secrets present in the config.
"""
def helper(disk, result):
"""Recursively gather secrets from this disk."""
if disk.dev_type == constants.DT_DRBD8:
result.append(disk.logical_id[5])
if disk.children:
for child in disk.children:
helper(child, result)
result = []
for instance in self._config_data.instances.values():
for disk in instance.disks:
helper(disk, result)
return result
@locking.ssynchronized(_config_lock, shared=1)
def VerifyConfig(self):
"""Stub verify function.
......@@ -268,7 +306,7 @@ class ConfigWriter:
if disk.logical_id is None and disk.physical_id is not None:
return
if disk.dev_type == constants.LD_DRBD8:
pnode, snode, port, pminor, sminor = disk.logical_id
pnode, snode, port, pminor, sminor, secret = disk.logical_id
if node_name not in (pnode, snode):
raise errors.ConfigurationError("DRBD device not knowing node %s" %
node_name)
......@@ -280,9 +318,9 @@ class ConfigWriter:
p_data = (pnode_info.secondary_ip, port)
s_data = (snode_info.secondary_ip, port)
if pnode == node_name:
disk.physical_id = p_data + s_data + (pminor,)
disk.physical_id = p_data + s_data + (pminor, secret)
else: # it must be secondary, we tested above
disk.physical_id = s_data + p_data + (sminor,)
disk.physical_id = s_data + p_data + (sminor, secret)
else:
disk.physical_id = disk.logical_id
return
......@@ -354,8 +392,8 @@ class ConfigWriter:
"""
def _AppendUsedPorts(instance_name, disk, used):
if disk.dev_type == constants.LD_DRBD8 and len(disk.logical_id) == 5:
nodeA, nodeB, dummy, minorA, minorB = disk.logical_id
if disk.dev_type == constants.LD_DRBD8 and len(disk.logical_id) >= 5:
nodeA, nodeB, dummy, minorA, minorB = disk.logical_id[:5]
for node, port in ((nodeA, minorA), (nodeB, minorB)):
assert node in used, "Instance node not found in node list"
if port in used[node]:
......
......@@ -412,7 +412,7 @@ class Disk(ConfigObject):
if self.logical_id is None and self.physical_id is not None:
return
if self.dev_type in constants.LDS_DRBD:
pnode, snode, port, pminor, sminor = self.logical_id
pnode, snode, port, pminor, sminor, secret = self.logical_id
if target_node not in (pnode, snode):
raise errors.ConfigurationError("DRBD device not knowing node %s" %
target_node)
......@@ -424,9 +424,9 @@ class Disk(ConfigObject):
p_data = (pnode_ip, port)
s_data = (snode_ip, port)
if pnode == target_node:
self.physical_id = p_data + s_data + (pminor,)
self.physical_id = p_data + s_data + (pminor, secret)
else: # it must be secondary, we tested above
self.physical_id = s_data + p_data + (sminor,)
self.physical_id = s_data + p_data + (sminor, secret)
else:
self.physical_id = self.logical_id
return
......@@ -458,9 +458,10 @@ class Disk(ConfigObject):
obj.logical_id = tuple(obj.logical_id)
if obj.physical_id and isinstance(obj.physical_id, list):
obj.physical_id = tuple(obj.physical_id)
if obj.dev_type in constants.LDS_DRBD and len(obj.logical_id) == 3:
# old non-minor based disk type
obj.logical_id += (None, None)
if obj.dev_type in constants.LDS_DRBD:
# we need a tuple of length six here
if len(obj.logical_id) < 6:
obj.logical_id += (None,) * (6 - len(obj.logical_id))
return obj
def __str__(self):
......
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