Allow disk object to set their own physical ID
authorIustin Pop <iustin@google.com>
Tue, 17 Jun 2008 15:07:23 +0000 (15:07 +0000)
committerIustin Pop <iustin@google.com>
Tue, 17 Jun 2008 15:07:23 +0000 (15:07 +0000)
Currently, the way to customize a DRBD disk from (node name 1, node name
2, port) to (ip1, port, ip2, port) is to use the ConfigWriter method
SetDiskID. However, since this needs a ConfigWriter object, it can be
run only on the master, and therefore disk object can't be passed to
more than one node unchanged. This, coupled with the rpc layer
limitation that all nodes in a multi-node call receive the same
arguments, prevent any kind of multi-node operation that has disks as an
argument.

This patch takes the SetDiskID method from ConfigWriter and ports it to
the disk object itself, and instead of the full node configuration it
uses a simple {node_name: replication_ip} mapping for all the nodes
involved in the disk tree (currently we only pass primary and secondary
node since we don't support nested drbd devices).

This allows us to send disks to both the primary and secondary nodes at
once and perform synchronized drbd activation on primary/secondary
nodes.

Note that while for the 1.2 branch this will not change old methods, it
is worth to investigate and possible replace all such calls on the
master to the nodes themselves for the 2.0 branch.

Reviewed-by: ultrotter

lib/objects.py

index ae685eb..d3688b2 100644 (file)
@@ -392,6 +392,50 @@ class Disk(ConfigObject):
       raise errors.ProgrammerError("Disk.RecordGrow called for unsupported"
                                    " disk type %s" % self.dev_type)
 
+  def SetPhysicalID(self, target_node, nodes_ip):
+    """Convert the logical ID to the physical ID.
+
+    This is used only for drbd, which needs ip/port configuration.
+
+    The routine descends down and updates its children also, because
+    this helps when the only the top device is passed to the remote
+    node.
+
+    Arguments:
+      - target_node: the node we wish to configure for
+      - nodes_ip: a mapping of node name to ip
+
+    The target_node must exist in in nodes_ip, and must be one of the
+    nodes in the logical ID for each of the DRBD devices encountered
+    in the disk tree.
+
+    """
+    if self.children:
+      for child in self.children:
+        child.SetPhysicalID(target_node, nodes_ip)
+
+    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 = self.logical_id
+      if target_node not in (pnode, snode):
+        raise errors.ConfigurationError("DRBD device not knowing node %s" %
+                                        target_node)
+      pnode_ip = nodes_ip.get(pnode, None)
+      snode_ip = nodes_ip.get(snode, None)
+      if pnode_ip is None or snode_ip is None:
+        raise errors.ConfigurationError("Can't find primary or secondary node"
+                                        " for %s" % str(self))
+      if pnode == target_node:
+        self.physical_id = (pnode_ip, port,
+                            snode_ip, port)
+      else: # it must be secondary, we tested above
+        self.physical_id = (snode_ip, port,
+                            pnode_ip, port)
+    else:
+      self.physical_id = self.logical_id
+    return
+
   def ToDict(self):
     """Disk-specific conversion to standard python types.