Emit a warning for each instance with a mirrored disk template that has
its primary and secondary nodes living in different node groups.

Signed-off-by: Adeodato Simo <[email protected]>
---
 lib/cmdlib.py |   26 ++++++++++++++++++++++++++
 1 files changed, 26 insertions(+), 0 deletions(-)

diff --git a/lib/cmdlib.py b/lib/cmdlib.py
index cfed46f..e2d9566 100644
--- a/lib/cmdlib.py
+++ b/lib/cmdlib.py
@@ -1219,6 +1219,7 @@ class LUVerifyCluster(LogicalUnit):
   EINSTANCEMISSINGDISK = (TINSTANCE, "EINSTANCEMISSINGDISK")
   EINSTANCEFAULTYDISK = (TINSTANCE, "EINSTANCEFAULTYDISK")
   EINSTANCEWRONGNODE = (TINSTANCE, "EINSTANCEWRONGNODE")
+  EINSTANCESPLITGROUPS = (TINSTANCE, "EINSTANCESPLITGROUPS")
   ENODEDRBD = (TNODE, "ENODEDRBD")
   ENODEDRBDHELPER = (TNODE, "ENODEDRBDHELPER")
   ENODEFILECHECK = (TNODE, "ENODEFILECHECK")
@@ -2067,9 +2068,11 @@ class LUVerifyCluster(LogicalUnit):
     cluster = self.cfg.GetClusterInfo()
     nodelist = utils.NiceSort(self.cfg.GetNodeList())
     nodeinfo = [self.cfg.GetNodeInfo(nname) for nname in nodelist]
+    nodeinfo_byname = dict(zip(nodelist, nodeinfo))
     instancelist = utils.NiceSort(self.cfg.GetInstanceList())
     instanceinfo = dict((iname, self.cfg.GetInstanceInfo(iname))
                         for iname in instancelist)
+    groupinfo = self.cfg.GetAllNodeGroupsInfo()
     i_non_redundant = [] # Non redundant instances
     i_non_a_balanced = [] # Non auto-balanced instances
     n_offline = 0 # Count of offline nodes
@@ -2254,11 +2257,34 @@ class LUVerifyCluster(LogicalUnit):
       # FIXME: does not support file-backed instances
       if not inst_config.secondary_nodes:
         i_non_redundant.append(instance)
+
       _ErrorIf(len(inst_config.secondary_nodes) > 1, self.EINSTANCELAYOUT,
                instance, "instance has multiple secondary nodes: %s",
                utils.CommaJoin(inst_config.secondary_nodes),
                code=self.ETYPE_WARNING)
 
+      if inst_config.disk_template in constants.DTS_NET_MIRROR:
+        pnode = inst_config.primary_node
+        instance_nodes = [pnode] + utils.NiceSort(inst_config.secondary_nodes)
+        instance_groups = {}
+
+        for node in instance_nodes:
+          nodes = instance_groups.setdefault(nodeinfo_byname[node].group, [])
+          nodes.append(node)
+
+        if len(instance_groups) > 1:
+          pretty_node_groups = [
+              "%s (group %s)" % (utils.CommaJoin(nodes), groupinfo[group].name)
+              # Sort so that we always list the primary node first.
+              for group, nodes in sorted(instance_groups.items(),
+                                         key=lambda x: pnode in x[1],
+                                         reverse=True)]
+
+          self._Error(self.EINSTANCESPLITGROUPS, instance,
+                      "instance has primary and secondary nodes in different"
+                      " groups: %s", utils.CommaJoin(pretty_node_groups),
+                      code=self.ETYPE_WARNING)
+
       if not cluster.FillBE(inst_config)[constants.BE_AUTO_BALANCE]:
         i_non_a_balanced.append(instance)
 
-- 
1.7.3.1

Reply via email to