Implement transport of ganeti errors across luxi
authorIustin Pop <iustin@google.com>
Wed, 15 Oct 2008 10:51:51 +0000 (10:51 +0000)
committerIustin Pop <iustin@google.com>
Wed, 15 Oct 2008 10:51:51 +0000 (10:51 +0000)
This patch adds a generic method to identify the ganeti error given its
class name, and implements this across the luxi protocol.

Reviewed-by: imsnah

daemons/ganeti-masterd
lib/errors.py
lib/luxi.py

index 06886f3..6fdf4e7 100755 (executable)
@@ -167,6 +167,9 @@ class ClientRqHandler(SocketServer.BaseRequestHandler):
       try:
         result = self._ops.handle_request(method, args)
         success = True
+      except errors.GenericError, err:
+        success = False
+        result = (err.__class__.__name__, err.args)
       except:
         logging.error("Unexpected exception", exc_info=True)
         err = sys.exc_info()
index bbf13f1..006da8e 100644 (file)
@@ -241,3 +241,25 @@ class JobQueueError(GenericError):
   """Job queue error.
 
   """
+
+
+# errors should be added above
+
+
+def GetErrorClass(name):
+  """Return the class of an exception.
+
+  Given the class name, return the class itself.
+
+  @type name: str
+  @param name: the exception name
+  @rtype: class
+  @return: the actual class, or None if not found
+
+  """
+  item = globals().get(name, None)
+  if item is not None:
+    if not (isinstance(item, type(Exception)) and
+            issubclass(item, GenericError)):
+      item = None
+  return item
index 541e059..9117253 100644 (file)
@@ -36,6 +36,7 @@ import errno
 
 from ganeti import serializer
 from ganeti import constants
+from ganeti import errors
 
 
 KEY_METHOD = 'method'
@@ -275,11 +276,20 @@ class Client(object):
         KEY_RESULT not in data):
       raise DecodingError("Invalid response from server: %s" % str(data))
 
+    result = data[KEY_RESULT]
+
     if not data[KEY_SUCCESS]:
       # TODO: decide on a standard exception
-      raise RequestError(data[KEY_RESULT])
+      if (isinstance(result, (tuple, list)) and len(result) == 2 and
+          isinstance(result[1], (tuple, list))):
+        # custom ganeti errors
+        err_class = errors.GetErrorClass(result[0])
+        if err_class is not None:
+          raise err_class, tuple(result[1])
+
+      raise RequestError(result)
 
-    return data[KEY_RESULT]
+    return result
 
   def SubmitJob(self, ops):
     ops_state = map(lambda op: op.__getstate__(), ops)