Browse Source

[1414] use default value for secondary_zones/class

and provide better error for missing name
Jelte Jansen 13 years ago
parent
commit
936855eb6f
2 changed files with 71 additions and 17 deletions
  1. 46 11
      src/bin/zonemgr/tests/zonemgr_test.py
  2. 25 6
      src/bin/zonemgr/zonemgr.py.in

+ 46 - 11
src/bin/zonemgr/tests/zonemgr_test.py

@@ -53,8 +53,10 @@ class FakeConfig:
         self.zone_list = []
         self.zone_list = []
         self.set_zone_list_from_name_classes([ZONE_NAME_CLASS1_IN,
         self.set_zone_list_from_name_classes([ZONE_NAME_CLASS1_IN,
                                               ZONE_NAME_CLASS2_CH])
                                               ZONE_NAME_CLASS2_CH])
+
     def set_zone_list_from_name_classes(self, zones):
     def set_zone_list_from_name_classes(self, zones):
         self.zone_list = map(lambda nc: {"name": nc[0], "class": nc[1]}, zones)
         self.zone_list = map(lambda nc: {"name": nc[0], "class": nc[1]}, zones)
+
     def get(self, name):
     def get(self, name):
         if name == 'lowerbound_refresh':
         if name == 'lowerbound_refresh':
             return LOWERBOUND_REFRESH
             return LOWERBOUND_REFRESH
@@ -71,6 +73,22 @@ class FakeConfig:
         else:
         else:
             raise ValueError('Uknown config option')
             raise ValueError('Uknown config option')
 
 
+class FakeCCSession:
+    def __init__(self):
+        self.config = FakeConfig()
+
+    def get_full_config(self):
+        return {'lowerbound_refresh': LOWERBOUND_REFRESH,
+                'lowerbound_retry': LOWERBOUND_RETRY,
+                'max_transfer_timeout': MAX_TRANSFER_TIMEOUT,
+                'refresh_jitter': REFRESH_JITTER,
+                'reload_jitter': RELOAD_JITTER,
+                'secondary_zones': [] }
+
+    def get_default_value(self, identifier):
+        return "IN"
+
+
 class MyZonemgrRefresh(ZonemgrRefresh):
 class MyZonemgrRefresh(ZonemgrRefresh):
     def __init__(self):
     def __init__(self):
         self._master_socket, self._slave_socket = socket.socketpair()
         self._master_socket, self._slave_socket = socket.socketpair()
@@ -92,7 +110,7 @@ class MyZonemgrRefresh(ZonemgrRefresh):
         sqlite3_ds.get_zone_soa = get_zone_soa
         sqlite3_ds.get_zone_soa = get_zone_soa
 
 
         ZonemgrRefresh.__init__(self, MySession(), "initdb.file",
         ZonemgrRefresh.__init__(self, MySession(), "initdb.file",
-            self._slave_socket, FakeConfig())
+            self._slave_socket, FakeCCSession())
         current_time = time.time()
         current_time = time.time()
         self._zonemgr_refresh_info = {
         self._zonemgr_refresh_info = {
          ('example.net.', 'IN'): {
          ('example.net.', 'IN'): {
@@ -112,6 +130,7 @@ class TestZonemgrRefresh(unittest.TestCase):
         self.stderr_backup = sys.stderr
         self.stderr_backup = sys.stderr
         sys.stderr = open(os.devnull, 'w')
         sys.stderr = open(os.devnull, 'w')
         self.zone_refresh = MyZonemgrRefresh()
         self.zone_refresh = MyZonemgrRefresh()
+        self.cc_session = FakeCCSession()
 
 
     def test_random_jitter(self):
     def test_random_jitter(self):
         max = 100025.120
         max = 100025.120
@@ -458,7 +477,23 @@ class TestZonemgrRefresh(unittest.TestCase):
                     "secondary_zones": [ { "name": "example.net.",
                     "secondary_zones": [ { "name": "example.net.",
                                            "class": "IN" } ]
                                            "class": "IN" } ]
                 }
                 }
-        self.zone_refresh.update_config_data(config_data)
+        self.zone_refresh.update_config_data(config_data, self.cc_session)
+        self.assertTrue(("example.net.", "IN") in
+                        self.zone_refresh._zonemgr_refresh_info)
+
+        # make sure it does fail if we don't provide a name
+        config_data = {
+                    "secondary_zones": [ { "class": "IN" } ]
+                }
+        self.assertRaises(ZonemgrException,
+                          self.zone_refresh.update_config_data,
+                          config_data, self.cc_session)
+
+        # But not if we don't provide a class
+        config_data = {
+                    "secondary_zones": [ { "name": "example.net." } ]
+                }
+        self.zone_refresh.update_config_data(config_data, self.cc_session)
         self.assertTrue(("example.net.", "IN") in
         self.assertTrue(("example.net.", "IN") in
                         self.zone_refresh._zonemgr_refresh_info)
                         self.zone_refresh._zonemgr_refresh_info)
 
 
@@ -471,7 +506,7 @@ class TestZonemgrRefresh(unittest.TestCase):
                     "reload_jitter" : 0.75,
                     "reload_jitter" : 0.75,
                     "secondary_zones": []
                     "secondary_zones": []
                 }
                 }
-        self.zone_refresh.update_config_data(config_data)
+        self.zone_refresh.update_config_data(config_data, self.cc_session)
         self.assertEqual(60, self.zone_refresh._lowerbound_refresh)
         self.assertEqual(60, self.zone_refresh._lowerbound_refresh)
         self.assertEqual(30, self.zone_refresh._lowerbound_retry)
         self.assertEqual(30, self.zone_refresh._lowerbound_retry)
         self.assertEqual(19800, self.zone_refresh._max_transfer_timeout)
         self.assertEqual(19800, self.zone_refresh._max_transfer_timeout)
@@ -482,7 +517,7 @@ class TestZonemgrRefresh(unittest.TestCase):
         config_data = {
         config_data = {
                     "reload_jitter" : 0.35,
                     "reload_jitter" : 0.35,
                 }
                 }
-        self.zone_refresh.update_config_data(config_data)
+        self.zone_refresh.update_config_data(config_data, self.cc_session)
         self.assertEqual(60, self.zone_refresh._lowerbound_refresh)
         self.assertEqual(60, self.zone_refresh._lowerbound_refresh)
         self.assertEqual(30, self.zone_refresh._lowerbound_retry)
         self.assertEqual(30, self.zone_refresh._lowerbound_retry)
         self.assertEqual(19800, self.zone_refresh._max_transfer_timeout)
         self.assertEqual(19800, self.zone_refresh._max_transfer_timeout)
@@ -500,7 +535,7 @@ class TestZonemgrRefresh(unittest.TestCase):
                     "secondary_zones": [ { "name": "doesnotexist",
                     "secondary_zones": [ { "name": "doesnotexist",
                                            "class": "IN" } ]
                                            "class": "IN" } ]
                 }
                 }
-        self.zone_refresh.update_config_data(config_data)
+        self.zone_refresh.update_config_data(config_data, self.cc_session)
         name_class = ("doesnotexist.", "IN")
         name_class = ("doesnotexist.", "IN")
         self.assertTrue(self.zone_refresh._zonemgr_refresh_info[name_class]["zone_soa_rdata"]
         self.assertTrue(self.zone_refresh._zonemgr_refresh_info[name_class]["zone_soa_rdata"]
                         is None)
                         is None)
@@ -520,7 +555,7 @@ class TestZonemgrRefresh(unittest.TestCase):
                     "reload_jitter" : 0.75,
                     "reload_jitter" : 0.75,
                     "secondary_zones": []
                     "secondary_zones": []
                 }
                 }
-        self.zone_refresh.update_config_data(config_data)
+        self.zone_refresh.update_config_data(config_data, self.cc_session)
         self.assertEqual(60, self.zone_refresh._lowerbound_refresh)
         self.assertEqual(60, self.zone_refresh._lowerbound_refresh)
         self.assertEqual(30, self.zone_refresh._lowerbound_retry)
         self.assertEqual(30, self.zone_refresh._lowerbound_retry)
         self.assertEqual(19800, self.zone_refresh._max_transfer_timeout)
         self.assertEqual(19800, self.zone_refresh._max_transfer_timeout)
@@ -540,16 +575,16 @@ class TestZonemgrRefresh(unittest.TestCase):
         config = FakeConfig()
         config = FakeConfig()
         config.zone_list = []
         config.zone_list = []
         # First, remove everything
         # First, remove everything
-        self.zone_refresh.update_config_data(config)
+        self.zone_refresh.update_config_data(config, self.cc_session)
         self.assertEqual(self.zone_refresh._zonemgr_refresh_info, {})
         self.assertEqual(self.zone_refresh._zonemgr_refresh_info, {})
         # Put something in
         # Put something in
         config.set_zone_list_from_name_classes([ZONE_NAME_CLASS1_IN])
         config.set_zone_list_from_name_classes([ZONE_NAME_CLASS1_IN])
-        self.zone_refresh.update_config_data(config)
+        self.zone_refresh.update_config_data(config, self.cc_session)
         self.assertTrue(("example.net.", "IN") in
         self.assertTrue(("example.net.", "IN") in
                         self.zone_refresh._zonemgr_refresh_info)
                         self.zone_refresh._zonemgr_refresh_info)
         # This one does not exist
         # This one does not exist
         config.set_zone_list_from_name_classes(["example.net", "CH"])
         config.set_zone_list_from_name_classes(["example.net", "CH"])
-        self.zone_refresh.update_config_data(config)
+        self.zone_refresh.update_config_data(config, self.cc_session)
         self.assertFalse(("example.net.", "CH") in
         self.assertFalse(("example.net.", "CH") in
                         self.zone_refresh._zonemgr_refresh_info)
                         self.zone_refresh._zonemgr_refresh_info)
         # Simply skip loading soa for the zone, the other configs should be updated successful
         # Simply skip loading soa for the zone, the other configs should be updated successful
@@ -557,7 +592,7 @@ class TestZonemgrRefresh(unittest.TestCase):
                         self.zone_refresh._zonemgr_refresh_info)
                         self.zone_refresh._zonemgr_refresh_info)
         # Make sure it works even when we "accidentally" forget the final dot
         # Make sure it works even when we "accidentally" forget the final dot
         config.set_zone_list_from_name_classes([("example.net", "IN")])
         config.set_zone_list_from_name_classes([("example.net", "IN")])
-        self.zone_refresh.update_config_data(config)
+        self.zone_refresh.update_config_data(config, self.cc_session)
         self.assertTrue(("example.net.", "IN") in
         self.assertTrue(("example.net.", "IN") in
                         self.zone_refresh._zonemgr_refresh_info)
                         self.zone_refresh._zonemgr_refresh_info)
 
 
@@ -622,7 +657,7 @@ class TestZonemgr(unittest.TestCase):
         self.assertEqual(0.5, self.zonemgr._config_data.get("refresh_jitter"))
         self.assertEqual(0.5, self.zonemgr._config_data.get("refresh_jitter"))
         # The zone doesn't exist in database, simply skip loading soa for it and log an warning
         # The zone doesn't exist in database, simply skip loading soa for it and log an warning
         self.zonemgr._zone_refresh = ZonemgrRefresh(None, "initdb.file", None,
         self.zonemgr._zone_refresh = ZonemgrRefresh(None, "initdb.file", None,
-                                                    config_data1)
+                                                    FakeCCSession())
         config_data1["secondary_zones"] = [{"name": "nonexistent.example",
         config_data1["secondary_zones"] = [{"name": "nonexistent.example",
                                             "class": "IN"}]
                                             "class": "IN"}]
         self.assertEqual(self.zonemgr.config_handler(config_data1),
         self.assertEqual(self.zonemgr.config_handler(config_data1),

+ 25 - 6
src/bin/zonemgr/zonemgr.py.in

@@ -98,7 +98,7 @@ class ZonemgrRefresh:
     can be stopped by calling shutdown() in another thread.
     can be stopped by calling shutdown() in another thread.
     """
     """
 
 
-    def __init__(self, cc, db_file, slave_socket, config_data):
+    def __init__(self, cc, db_file, slave_socket, module_cc_session):
         self._cc = cc
         self._cc = cc
         self._check_sock = slave_socket
         self._check_sock = slave_socket
         self._db_file = db_file
         self._db_file = db_file
@@ -108,7 +108,8 @@ class ZonemgrRefresh:
         self._max_transfer_timeout = None
         self._max_transfer_timeout = None
         self._refresh_jitter = None
         self._refresh_jitter = None
         self._reload_jitter = None
         self._reload_jitter = None
-        self.update_config_data(config_data)
+        self.update_config_data(module_cc_session.get_full_config(),
+                                module_cc_session)
         self._running = False
         self._running = False
 
 
     def _random_jitter(self, max, jitter):
     def _random_jitter(self, max, jitter):
@@ -424,7 +425,7 @@ class ZonemgrRefresh:
         self._read_sock = None
         self._read_sock = None
         self._write_sock = None
         self._write_sock = None
 
 
-    def update_config_data(self, new_config):
+    def update_config_data(self, new_config, module_cc_session):
         """ update ZonemgrRefresh config """
         """ update ZonemgrRefresh config """
         # Get a new value, but only if it is defined (commonly used below)
         # Get a new value, but only if it is defined (commonly used below)
         # We don't use "value or default", because if value would be
         # We don't use "value or default", because if value would be
@@ -456,11 +457,29 @@ class ZonemgrRefresh:
             if secondary_zones is not None:
             if secondary_zones is not None:
                 # Add new zones
                 # Add new zones
                 for secondary_zone in new_config.get('secondary_zones'):
                 for secondary_zone in new_config.get('secondary_zones'):
+                    if 'name' not in secondary_zone:
+                        raise ZonemgrException("Secondary zone specified "
+                                               "without a name")
                     name = secondary_zone['name']
                     name = secondary_zone['name']
                     # Be tolerant to sclerotic users who forget the final dot
                     # Be tolerant to sclerotic users who forget the final dot
                     if name[-1] != '.':
                     if name[-1] != '.':
                         name = name + '.'
                         name = name + '.'
-                    name_class = (name, secondary_zone['class'])
+                    # Currently we use an explicit get_default_value call
+                    # in case the class hasn't been set. Alternatively, we
+                    # could use
+                    # module_cc_session.get_value('secondary_zones[INDEX]/class')
+                    # To get either the value that was set, or the default if
+                    # it wasn't set.
+                    # But the real solution would be to make new_config a type
+                    # that contains default values itself
+                    # (then this entire method can be simplified a lot, and we
+                    # wouldn't need direct access to the ccsession object)
+                    if 'class' in secondary_zone:
+                        name_class = (name, secondary_zone['class'])
+                    else:
+                        name_class = (name,
+                                      module_cc_session.get_default_value(
+                                        'secondary_zones/class'))
                     required[name_class] = True
                     required[name_class] = True
                     # Add it only if it isn't there already
                     # Add it only if it isn't there already
                     if not name_class in self._zonemgr_refresh_info:
                     if not name_class in self._zonemgr_refresh_info:
@@ -485,7 +504,7 @@ class Zonemgr:
         self._db_file = self.get_db_file()
         self._db_file = self.get_db_file()
         # Create socket pair for communicating between main thread and zonemgr timer thread
         # Create socket pair for communicating between main thread and zonemgr timer thread
         self._master_socket, self._slave_socket = socket.socketpair(socket.AF_UNIX, socket.SOCK_STREAM)
         self._master_socket, self._slave_socket = socket.socketpair(socket.AF_UNIX, socket.SOCK_STREAM)
-        self._zone_refresh = ZonemgrRefresh(self._cc, self._db_file, self._slave_socket, self._config_data)
+        self._zone_refresh = ZonemgrRefresh(self._cc, self._db_file, self._slave_socket, self._module_cc)
         self._zone_refresh.run_timer()
         self._zone_refresh.run_timer()
 
 
         self._lock = threading.Lock()
         self._lock = threading.Lock()
@@ -540,7 +559,7 @@ class Zonemgr:
         self._config_data_check(complete)
         self._config_data_check(complete)
         if self._zone_refresh is not None:
         if self._zone_refresh is not None:
             try:
             try:
-                self._zone_refresh.update_config_data(complete)
+                self._zone_refresh.update_config_data(complete, self._module_cc)
             except Exception as e:
             except Exception as e:
                 answer = create_answer(1, str(e))
                 answer = create_answer(1, str(e))
                 ok = False
                 ok = False