Browse Source

[2676] Error handling in the rpc_call

Michal 'vorner' Vaner 12 years ago
parent
commit
6667c5c348

+ 29 - 0
src/lib/python/isc/config/ccsession.py

@@ -51,6 +51,31 @@ logger = isc.log.Logger("config")
 
 class ModuleCCSessionError(Exception): pass
 
+class RPCError(ModuleCCSessionError):
+    """
+    An exception raised by rpc_call in case the remote side reports
+    an error. It can be used to distinguish remote errors from protocol errors.
+    Also, it holds the code as well as the error message.
+    """
+    def __init__(self, code, message):
+        ModuleCCSessionError.__init__(self, message)
+        self.__code = code
+
+    def code(self):
+        """
+        The code as sent over the CC.
+        """
+        return self.__code
+
+class RPCRecipientMissing(RPCError):
+    """
+    Special version of the RPCError, for cases the recipient of the call
+    isn't connected to the bus. The code is always
+    isc.cc.proto_defs.CC_REPLY_NO_RECPT.
+    """
+    def __init__(self, message):
+        RPCError.__init__(self, CC_REPLY_NO_RECPT, message)
+
 def parse_answer(msg):
     """Returns a tuple (rcode, value), where value depends on the
        command that was called. If rcode != 0, value is a string
@@ -484,6 +509,10 @@ class ModuleCCSession(ConfigData):
         # works)
         reply, rheaders = self._session.group_recvmsg(nonblock=False, seq=seq)
         code, value = parse_answer(reply)
+        if code == CC_REPLY_NO_RECPT:
+            raise RPCRecipientMissing(value)
+        elif code != 0:
+            raise RPCError(code, value)
         return value
 
 class UIModuleCCSession(MultiConfigData):

+ 13 - 0
src/lib/python/isc/config/tests/ccsession_test.py

@@ -335,6 +335,19 @@ class TestModuleCCSession(unittest.TestCase):
         """
         self.assertRaises(ModuleCCSessionError, self.rpc_check, ["Nonsense"])
 
+    def test_rpc_call_error(self):
+        """
+        Test it raises an exception when the remote side reports an error.
+        """
+        self.assertRaises(RPCError, self.rpc_check, {"result": [1, "Error"]})
+
+    def test_rpc_call_no_recpt(self):
+        """
+        Test RPC raises an error when the recipient is not there.
+        """
+        self.assertRaises(RPCRecipientMissing, self.rpc_check,
+                          {"result": [-1, "Error"]})
+
     def my_config_handler_ok(self, new_config):
         return isc.config.ccsession.create_answer(0)