self._cc.get_default_value('zones'))
self._cc.start()
+ # Internal attributes derived from other modules. They will be
+ # initialized via dd_remote_xxx below and will be kept updated
+ # through their callbacks. They are defined as 'protected' so tests
+ # can examine them; but they are essentially private to the class.
+ #
# Datasource client used for handling update requests: when set,
# should a tuple of RRClass and DataSourceClient. Constructed and
# maintained based on auth configuration.
self._secondary_zones = None
# Get necessary configurations from remote modules.
- self._cc.add_remote_config_by_name(AUTH_MODULE_NAME,
- self.__auth_config_handler)
- self._cc.add_remote_config_by_name(ZONEMGR_MODULE_NAME,
- self.__zonemgr_config_handler)
+ try:
+ mods = [(AUTH_MODULE_NAME, self.__auth_config_handler),
+ (ZONEMGR_MODULE_NAME, self.__zonemgr_config_handler)]
+ for mod in mods:
+ self._cc.add_remote_config_by_name(mod[0], mod[1])
+ except ModuleCCSessionError as ex:
+ logger.error(DDNS_GET_REMOTE_CONFIG_FAIL, mod[0], ex)
+ raise ex # propagte it and die for now
+ # This should succeed as long as cfgmgr is up.
isc.server_common.tsig_keyring.init_keyring(self._cc)
self._shutdown = False
uses for the underlying data source and on which b10-ddns needs to
make updates. b10-ddns then updated its internal setup so further
updates would be made on the new DB.
+
+% DDNS_GET_REMOTE_CONFIG_FAIL failed to get %1 module configuration: %2
+b10-ddns tried to get configuration of some remote modules for its
+operation, but it failed. The most likely cause of this is that the
+remote module has not fully started up and b10-ddns couldn't get the
+configuration in a timely fashion. In the current implementation
+b10-ddns considers it a fatal error and terminates; however, as long
+as b10-ddns is configured as a "dispensable" component (which is the
+default), the parent bind10 process will restart it, and getting the
+remote configuration will eventually (and soon) succeed. This is not
+the optimal behavior, but should be sufficient in practice. If it
+really causes an operational trouble other than having a few of this
+log messages, please submit a bug report; there can be several ways to
+make it more sophisticated. Another, less likely reason for having
+this error is because the remote modules are not actually configured
+to run. If that's the case fixing the configuration should solve the
+problem - either by making sure the remote module will run or by not
+running b10-ddns (without these remote modules b10-ddns is not
+functional, so there's no point in running it in this case).
from isc.datasrc import DataSourceClient
from isc.config import module_spec_from_file
from isc.config.config_data import ConfigData
-from isc.config.ccsession import create_answer
+from isc.config.ccsession import create_answer, ModuleCCSessionError
from isc.server_common.dns_tcp import DNSTCPContext
import ddns
import errno
# Attributes to handle (faked) remote configurations
self.__callbacks = {} # record callbacks for updates to remote confs
+ self._raise_mods = set() # set of modules that triggers exception
+ # on add_remote. settable by tests.
self._auth_config = {} # faked auth cfg, settable by tests
self._zonemgr_config = {} # faked zonemgr cfg, settable by tests
return FakeSocket(1)
def add_remote_config_by_name(self, module_name, update_callback=None):
+ if module_name in self._raise_mods:
+ raise ModuleCCSessionError('Failure requesting remote config data')
if update_callback is not None:
self.__callbacks[module_name] = update_callback
if module_name is 'Auth':
self.assertEqual({(TEST_ZONE_NAME, TEST_RRCLASS)},
self.ddns_server._secondary_zones)
+ def test_remote_config_fail(self):
+ # If getting config of Auth or Zonemgr fails on construction of
+ # DDNServer, it should result in ModuleCCSessionError.
+ self.__cc_session._raise_mods.add('Auth')
+ self.assertRaises(ModuleCCSessionError, ddns.DDNSServer,
+ self.__cc_session)
+
+ self.__cc_session._raise_mods = {'Zonemgr'}
+ self.assertRaises(ModuleCCSessionError, ddns.DDNSServer,
+ self.__cc_session)
+
def test_shutdown_command(self):
'''Test whether the shutdown command works'''
self.assertFalse(self.ddns_server._shutdown)