Browse Source

[1165] catch some exceptions that could be raised due to configuration error
and log messages for them. this is necessary to gracefully die due to
broken config data in b10-config.db at startup time.

JINMEI Tatuya 13 years ago
parent
commit
1e32824c93

+ 3 - 3
src/bin/xfrout/tests/xfrout_test.py.in

@@ -745,7 +745,7 @@ class TestUnixSockServer(unittest.TestCase):
                                                'action': 'ACCEPT'}]})
                                                'action': 'ACCEPT'}]})
         self.check_loaded_ACL(self.unix._acl)
         self.check_loaded_ACL(self.unix._acl)
         # Pass a wrong data there and check it does not replace the old one
         # Pass a wrong data there and check it does not replace the old one
-        self.assertRaises(isc.acl.acl.LoaderError,
+        self.assertRaises(XfroutConfigError,
                           self.unix.update_config_data,
                           self.unix.update_config_data,
                           {'transfer_acl': ['Something bad']})
                           {'transfer_acl': ['Something bad']})
         self.check_loaded_ACL(self.unix._acl)
         self.check_loaded_ACL(self.unix._acl)
@@ -792,7 +792,7 @@ class TestUnixSockServer(unittest.TestCase):
         self.assertEqual({}, self.unix._zone_config[('IN', 'example.org.')])
         self.assertEqual({}, self.unix._zone_config[('IN', 'example.org.')])
 
 
         # Duplicate data: should be rejected with an exception
         # Duplicate data: should be rejected with an exception
-        self.assertRaises(ValueError,
+        self.assertRaises(XfroutConfigError,
                           self.unix.update_config_data,
                           self.unix.update_config_data,
                           {'zone_config': [{'origin': 'example.com'},
                           {'zone_config': [{'origin': 'example.com'},
                                            {'origin': 'example.org'},
                                            {'origin': 'example.org'},
@@ -809,7 +809,7 @@ class TestUnixSockServer(unittest.TestCase):
         self.check_loaded_ACL(acl)
         self.check_loaded_ACL(acl)
 
 
         # invalid ACL syntax will be rejected with exception
         # invalid ACL syntax will be rejected with exception
-        self.assertRaises(isc.acl.acl.LoaderError,
+        self.assertRaises(XfroutConfigError,
                           self.unix.update_config_data,
                           self.unix.update_config_data,
                           {'zone_config': [{'origin': 'example.com',
                           {'zone_config': [{'origin': 'example.com',
                                             'transfer_acl':
                                             'transfer_acl':

+ 31 - 6
src/bin/xfrout/xfrout.py.in

@@ -48,11 +48,23 @@ except ImportError as e:
     # must keep running, so we warn about it and move forward.
     # must keep running, so we warn about it and move forward.
     log.error(XFROUT_IMPORT, str(e))
     log.error(XFROUT_IMPORT, str(e))
 
 
-from isc.acl.acl import ACCEPT, REJECT, DROP
+from isc.acl.acl import ACCEPT, REJECT, DROP, LoaderError
 from isc.acl.dns import REQUEST_LOADER
 from isc.acl.dns import REQUEST_LOADER
 
 
 isc.util.process.rename()
 isc.util.process.rename()
 
 
+class XfroutConfigError(Exception):
+    """An exception indicating an error in updating xfrout configuration.
+
+    This exception is raised when the xfrout process encouters an error in
+    handling configuration updates.  Not all syntax error can be caught
+    at the module-CC layer, so xfrout needs to (explicitly or implicitly)
+    validate the given configuration data itself.  When it finds an error
+    it raises this exception (either directly or by converting an exception
+    from other modules) as a unified error in configuration.
+    """
+    pass
+
 def init_paths():
 def init_paths():
     global SPECFILE_PATH
     global SPECFILE_PATH
     global AUTH_SPECFILE_PATH
     global AUTH_SPECFILE_PATH
@@ -583,7 +595,11 @@ class UnixSockServer(socketserver_mixin.NoPollMixIn,
         '''
         '''
         logger.info(XFROUT_NEW_CONFIG)
         logger.info(XFROUT_NEW_CONFIG)
         if 'transfer_acl' in new_config:
         if 'transfer_acl' in new_config:
-            self._acl = REQUEST_LOADER.load(new_config['transfer_acl'])
+            try:
+                self._acl = REQUEST_LOADER.load(new_config['transfer_acl'])
+            except LoaderError as e:
+                raise XfroutConfigError('Failed to parse transfer_acl: ' +
+                                        str(e))
         zone_config = new_config.get('zone_config')
         zone_config = new_config.get('zone_config')
         if zone_config is not None:
         if zone_config is not None:
             self._zone_config = self.__create_zone_config(zone_config)
             self._zone_config = self.__create_zone_config(zone_config)
@@ -608,14 +624,19 @@ class UnixSockServer(socketserver_mixin.NoPollMixIn,
 
 
             # reject duplicate config
             # reject duplicate config
             if config_key in new_config:
             if config_key in new_config:
-                raise ValueError('Duplicaet zone_config for ' +
+                raise XfroutConfigError('Duplicaet zone_config for ' +
-                                 str(zorigin) + '/' + str(zclass))
+                                        str(zorigin) + '/' + str(zclass))
 
 
             # create a new config entry, build any given (and known) config
             # create a new config entry, build any given (and known) config
             new_config[config_key] = {}
             new_config[config_key] = {}
             if 'transfer_acl' in zconf:
             if 'transfer_acl' in zconf:
-                new_config[config_key]['transfer_acl'] = \
+                try:
-                    REQUEST_LOADER.load(zconf['transfer_acl'])
+                    new_config[config_key]['transfer_acl'] = \
+                        REQUEST_LOADER.load(zconf['transfer_acl'])
+                except LoaderError as e:
+                    raise XfroutConfigError('Failed to parse transfer_acl ' +
+                                            'for ' + zorigin.to_text() + '/' +
+                                            zclass_str + ': ' + str(e))
         return new_config
         return new_config
 
 
     def set_tsig_key_ring(self, key_list):
     def set_tsig_key_ring(self, key_list):
@@ -785,6 +806,10 @@ if '__main__' == __name__:
         logger.INFO(XFROUT_STOPPED_BY_KEYBOARD)
         logger.INFO(XFROUT_STOPPED_BY_KEYBOARD)
     except SessionError as e:
     except SessionError as e:
         logger.error(XFROUT_CC_SESSION_ERROR, str(e))
         logger.error(XFROUT_CC_SESSION_ERROR, str(e))
+    except ModuleCCSessionError as e:
+        logger.error(XFROUT_MODULECC_SESSION_ERROR, str(e))
+    except XfroutConfigError as e:
+        logger.error(XFROUT_CONFIG_ERROR, str(e))
     except SessionTimeout as e:
     except SessionTimeout as e:
         logger.error(XFROUT_CC_SESSION_TIMEOUT_ERROR)
         logger.error(XFROUT_CC_SESSION_TIMEOUT_ERROR)
 
 

+ 11 - 0
src/bin/xfrout/xfrout_messages.mes

@@ -47,6 +47,17 @@ a valid TSIG key.
 There was a problem reading from the command and control channel. The
 There was a problem reading from the command and control channel. The
 most likely cause is that the msgq daemon is not running.
 most likely cause is that the msgq daemon is not running.
 
 
+% XFROUT_MODULECC_SESSION_ERROR error from module config/command module: %1
+There was a problem in the lower level module handling configuration and
+control commands.  This could happen for various reasons, but the most likely
+cause is that the configuration database contains a syntax error and xfrout
+fails to start at initialization.  Details error message from the module
+will also be displayed.
+
+% XFROUT_CONFIG_ERROR error found in configuration data: %1
+The xfrout process encoutered an error in installing configuration at
+startup time.  Error details are included in the log message.
+
 % XFROUT_CC_SESSION_TIMEOUT_ERROR timeout waiting for cc response
 % XFROUT_CC_SESSION_TIMEOUT_ERROR timeout waiting for cc response
 There was a problem reading a response from another module over the
 There was a problem reading a response from another module over the
 command and control channel. The most likely cause is that the
 command and control channel. The most likely cause is that the