Browse Source

[trac1153] set retry timer for empty zones
database

chenzhengzhang 13 years ago
parent
commit
ec8fed8c80
2 changed files with 33 additions and 16 deletions
  1. 19 7
      src/bin/zonemgr/tests/zonemgr_test.py
  2. 14 9
      src/bin/zonemgr/zonemgr.py.in

+ 19 - 7
src/bin/zonemgr/tests/zonemgr_test.py

@@ -152,6 +152,16 @@ class TestZonemgrRefresh(unittest.TestCase):
         self.assertTrue((time1 + 3600 * (1 - self.zone_refresh._refresh_jitter)) <= zone_timeout)
         self.assertTrue(zone_timeout <= time2 + 3600)
 
+        # No soa rdata
+        self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_soa_rdata"] = None
+        time3 = time.time()
+        self.zone_refresh._set_zone_retry_timer(ZONE_NAME_CLASS1_IN)
+        zone_timeout = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["next_refresh_time"]
+        time4 = time.time()
+        self.assertTrue((time3 + self.zone_refresh._lowerbound_retry * (1 - self.zone_refresh._refresh_jitter))
+                         <= zone_timeout)
+        self.assertTrue(zone_timeout <= time4 + self.zone_refresh._lowerbound_retry)
+
     def test_zone_not_exist(self):
         self.assertFalse(self.zone_refresh._zone_not_exist(ZONE_NAME_CLASS1_IN))
         self.assertTrue(self.zone_refresh._zone_not_exist(ZONE_NAME_CLASS1_CH))
@@ -305,7 +315,7 @@ class TestZonemgrRefresh(unittest.TestCase):
             return None
         sqlite3_ds.get_zone_soa = get_zone_soa2
         self.zone_refresh.zonemgr_add_zone(ZONE_NAME_CLASS2_IN)
-        self.assertFalse(ZONE_NAME_CLASS2_IN in self.zone_refresh._zonemgr_refresh_info)
+        self.assertTrue(self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS2_IN]["zone_soa_rdata"] is None)
         sqlite3_ds.get_zone_soa = old_get_zone_soa
 
     def test_zone_handle_notify(self):
@@ -482,8 +492,9 @@ class TestZonemgrRefresh(unittest.TestCase):
                                            "class": "IN" } ]
                 }
         self.zone_refresh.update_config_data(config_data)
-        self.assertFalse(("doesnotexist.", "IN")
-                         in self.zone_refresh._zonemgr_refresh_info)
+        name_class = ("doesnotexist.", "IN")
+        self.assertTrue(self.zone_refresh._zonemgr_refresh_info[name_class]["zone_soa_rdata"]
+                        is None)
         # The other configs should be updated successful
         self.assertEqual(61, self.zone_refresh._lowerbound_refresh)
         self.assertEqual(31, self.zone_refresh._lowerbound_retry)
@@ -532,7 +543,7 @@ class TestZonemgrRefresh(unittest.TestCase):
         self.zone_refresh.update_config_data(config)
         self.assertFalse(("example.net.", "CH") in
                         self.zone_refresh._zonemgr_refresh_info)
-        # Simply skip the zone, the other configs should be updated successful
+        # Simply skip loading soa for the zone, the other configs should be updated successful
         self.assertFalse(("example.net.", "IN") in
                         self.zone_refresh._zonemgr_refresh_info)
         # Make sure it works even when we "accidentally" forget the final dot
@@ -600,7 +611,7 @@ class TestZonemgr(unittest.TestCase):
         config_data3 = {"refresh_jitter" : 0.7}
         self.zonemgr.config_handler(config_data3)
         self.assertEqual(0.5, self.zonemgr._config_data.get("refresh_jitter"))
-        # The zone doesn't exist in database, simply skip it and log an error
+        # 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,
                                                     config_data1)
         config_data1["secondary_zones"] = [{"name": "nonexistent.example",
@@ -608,8 +619,9 @@ class TestZonemgr(unittest.TestCase):
         self.assertEqual(self.zonemgr.config_handler(config_data1),
                             {"result": [0]})
         # other configs should be updated successful
-        self.assertFalse(("nonexistent.example.", "IN") in
-                          self.zonemgr._zone_refresh._zonemgr_refresh_info)
+        name_class = ("nonexistent.example.", "IN")
+        self.assertTrue(self.zonemgr._zone_refresh._zonemgr_refresh_info[name_class]["zone_soa_rdata"]
+                        is None)
         self.assertEqual(0.1, self.zonemgr._config_data.get("refresh_jitter"))
 
     def test_get_db_file(self):

+ 14 - 9
src/bin/zonemgr/zonemgr.py.in

@@ -142,7 +142,10 @@ class ZonemgrRefresh:
         """Set zone next refresh time after zone refresh fail.
            now + retry - retry_jitter <= next_refresh_time <= now + retry
            """
-        zone_retry_time = float(self._get_zone_soa_rdata(zone_name_class).split(" ")[RETRY_OFFSET])
+        if (self._get_zone_soa_rdata(zone_name_class) is not None):
+            zone_retry_time = float(self._get_zone_soa_rdata(zone_name_class).split(" ")[RETRY_OFFSET])
+        else:
+            zone_retry_time = 0.0
         zone_retry_time = max(self._lowerbound_retry, zone_retry_time)
         self._set_zone_timer(zone_name_class, zone_retry_time, self._refresh_jitter * zone_retry_time)
 
@@ -174,7 +177,8 @@ class ZonemgrRefresh:
             raise ZonemgrException("[b10-zonemgr] Zone (%s, %s) doesn't "
                                    "belong to zonemgr" % zone_name_class)
         # Is zone expired?
-        if (self._zone_is_expired(zone_name_class)):
+        if ((self._get_zone_soa_rdata(zone_name_class) is not None) and
+            self._zone_is_expired(zone_name_class)):
             self._set_zone_state(zone_name_class, ZONE_EXPIRED)
         else:
             self._set_zone_state(zone_name_class, ZONE_OK)
@@ -200,15 +204,17 @@ class ZonemgrRefresh:
         logger.debug(DBG_ZONEMGR_BASIC, ZONEMGR_LOAD_ZONE, zone_name_class[0], zone_name_class[1])
         zone_info = {}
         zone_soa = sqlite3_ds.get_zone_soa(str(zone_name_class[0]), self._db_file)
-        if not zone_soa:
-            logger.error(ZONEMGR_NO_SOA, zone_name_class[0], zone_name_class[1])
-            return
-        zone_info["zone_soa_rdata"] = zone_soa[7]
+        if zone_soa is None:
+            logger.warn(ZONEMGR_NO_SOA, zone_name_class[0], zone_name_class[1])
+            zone_info["zone_soa_rdata"] = None
+            zone_reload_jitter = 0
+        else:
+            zone_info["zone_soa_rdata"] = zone_soa[7]
+            zone_reload_jitter = float(zone_soa[7].split(" ")[RETRY_OFFSET])
         zone_info["zone_state"] = ZONE_OK
         zone_info["last_refresh_time"] = self._get_current_time()
         self._zonemgr_refresh_info[zone_name_class] = zone_info
         # Imposes some random jitters to avoid many zones need to do refresh at the same time.
-        zone_reload_jitter = float(zone_soa[7].split(" ")[RETRY_OFFSET])
         zone_reload_jitter = max(self._lowerbound_retry, zone_reload_jitter)
         self._set_zone_timer(zone_name_class, zone_reload_jitter, self._reload_jitter * zone_reload_jitter)
 
@@ -457,8 +463,7 @@ class ZonemgrRefresh:
                 required[name_class] = True
                 # Add it only if it isn't there already
                 if not name_class in self._zonemgr_refresh_info:
-                    # If we are not able to find it in database, simply skip
-                    # it and log an error
+                    # If we are not able to find it in database, log an warning
                     self.zonemgr_add_zone(name_class)
             # Drop the zones that are no longer there
             # Do it in two phases, python doesn't like deleting while iterating