Convert volume_list rpc to new style result
authorIustin Pop <iustin@google.com>
Tue, 9 Jun 2009 12:45:49 +0000 (14:45 +0200)
committerIustin Pop <iustin@google.com>
Mon, 15 Jun 2009 16:37:49 +0000 (18:37 +0200)
This is a big change, because we need to cleanup its users too.

The call and thus LUVerifyDisks LU used to differentiate between failure
at node level and failure at LV level, by returning different types in
the RPC result. This is way too complicated for our needs.

The patch changes to new style result (easy change), and then:
  - changes LUVerifyDisks.Exec() to return a tuple of 3-elements
    instead of 4-elements; we collapse the «nodes not reachable» and
    «nodes with LVM errors» in a single dict
  - changes gnt-cluster to parse 3-element results and simplifies the
    different by-error handling code

Note that the status is added in ganeti-noded, and not in the function
itself, as the function is used in other places too.

This was tested with down nodes and broken VGs.

Signed-off-by: Iustin Pop <iustin@google.com>
Reviewed-by: Guido Trotter <ultrotter@google.com>

daemons/ganeti-noded
lib/backend.py
lib/cmdlib.py
scripts/gnt-cluster

index 96a642b..0678d11 100755 (executable)
@@ -339,7 +339,7 @@ class NodeHttpServer(http.server.HttpServer):
 
     """
     vgname = params[0]
-    return backend.GetVolumeList(vgname)
+    return True, backend.GetVolumeList(vgname)
 
   @staticmethod
   def perspective_vg_list(params):
index b06e1f6..1d65729 100644 (file)
@@ -494,9 +494,7 @@ def GetVolumeList(vg_name):
                          "--separator=%s" % sep,
                          "-olv_name,lv_size,lv_attr", vg_name])
   if result.failed:
-    logging.error("Failed to list logical volumes, lvs output: %s",
-                  result.output)
-    return result.output
+    _Fail("Failed to list logical volumes, lvs output: %s", result.output)
 
   valid_line_re = re.compile("^ *([^|]+)\|([0-9.]+)\|([^|]{6})\|?$")
   for line in result.stdout.splitlines():
index 28e4abf..c4a13b9 100644 (file)
@@ -1289,8 +1289,13 @@ class LUVerifyDisks(NoHooksLU):
   def Exec(self, feedback_fn):
     """Verify integrity of cluster disks.
 
+    @rtype: tuple of three items
+    @return: a tuple of (dict of node-to-node_error, list of instances
+        which need activate-disks, dict of instance: (node, volume) for
+        missing volumes
+
     """
-    result = res_nodes, res_nlvm, res_instances, res_missing = [], {}, [], {}
+    result = res_nodes, res_instances, res_missing = {}, [], {}
 
     vg_name = self.cfg.GetVGName()
     nodes = utils.NiceSort(self.cfg.GetNodeList())
@@ -1317,24 +1322,17 @@ class LUVerifyDisks(NoHooksLU):
     to_act = set()
     for node in nodes:
       # node_volume
-      lvs = node_lvs[node]
-      if lvs.failed:
-        if not lvs.offline:
-          self.LogWarning("Connection to node %s failed: %s" %
-                          (node, lvs.data))
-        continue
-      lvs = lvs.data
-      if isinstance(lvs, basestring):
-        logging.warning("Error enumerating LVs on node %s: %s", node, lvs)
-        res_nlvm[node] = lvs
+      node_res = node_lvs[node]
+      if node_res.offline:
         continue
-      elif not isinstance(lvs, dict):
-        logging.warning("Connection to node %s failed or invalid data"
-                        " returned", node)
-        res_nodes.append(node)
+      msg = node_res.RemoteFailMsg()
+      if msg:
+        logging.warning("Error enumerating LVs on node %s: %s", node, msg)
+        res_nodes[node] = msg
         continue
 
-      for lv_name, (_, lv_inactive, lv_online) in lvs.iteritems():
+      lvs = node_res.payload
+      for lv_name, (_, lv_inactive, lv_online) in lvs.items():
         inst = nv_dict.pop((node, lv_name), None)
         if (not lv_online and inst is not None
             and inst.name not in res_instances):
index 15e0ce9..505ffa2 100755 (executable)
@@ -361,20 +361,16 @@ def VerifyDisks(opts, args):
   """
   op = opcodes.OpVerifyDisks()
   result = SubmitOpCode(op)
-  if not isinstance(result, (list, tuple)) or len(result) != 4:
+  if not isinstance(result, (list, tuple)) or len(result) != 3:
     raise errors.ProgrammerError("Unknown result type for OpVerifyDisks")
 
-  nodes, nlvm, instances, missing = result
+  bad_nodes, instances, missing = result
 
-  if nodes:
-    ToStdout("Nodes unreachable or with bad data:")
-    for name in nodes:
-      ToStdout("\t%s", name)
   retcode = constants.EXIT_SUCCESS
 
-  if nlvm:
-    for node, text in nlvm.iteritems():
-      ToStdout("Error on node %s: LVM error: %s",
+  if bad_nodes:
+    for node, text in bad_nodes.items():
+      ToStdout("Error gathering data on node %s: %s",
                node, utils.SafeEncode(text[-400:]))
       retcode |= 1
       ToStdout("You need to fix these nodes first before fixing instances")
@@ -394,7 +390,7 @@ def VerifyDisks(opts, args):
 
   if missing:
     for iname, ival in missing.iteritems():
-      all_missing = utils.all(ival, lambda x: x[0] in nlvm)
+      all_missing = utils.all(ival, lambda x: x[0] in bad_nodes)
       if all_missing:
         ToStdout("Instance %s cannot be verified as it lives on"
                  " broken nodes", iname)
@@ -402,7 +398,7 @@ def VerifyDisks(opts, args):
         ToStdout("Instance %s has missing logical volumes:", iname)
         ival.sort()
         for node, vol in ival:
-          if node in nlvm:
+          if node in bad_nodes:
             ToStdout("\tbroken node %s /dev/xenvg/%s", node, vol)
           else:
             ToStdout("\t%s /dev/xenvg/%s", node, vol)