Browse Source

modify zonemgr code and unittest according to review opinions

git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac289@2680 e5f2f494-b856-4b98-b285-d166d9295462
Jerry 14 years ago
parent
commit
646dd51b96
2 changed files with 256 additions and 176 deletions
  1. 167 132
      src/bin/zonemgr/tests/zonemgr_test.py
  2. 89 44
      src/bin/zonemgr/zonemgr.py.in

+ 167 - 132
src/bin/zonemgr/tests/zonemgr_test.py

@@ -13,7 +13,7 @@
 # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
 # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
 # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 
-'''Tests for the ZoneMgrRefreshInfo and ZoneMgr classes '''
+'''Tests for the ZonemgrRefresh and Zonemgr classes '''
 
 
 
 
 import unittest
 import unittest
@@ -21,9 +21,11 @@ import os
 import tempfile
 import tempfile
 from zonemgr import *
 from zonemgr import *
 
 
-ZONE_NAME_CLASS1 = ("sd.cn.", "IN")
-ZONE_NAME_CLASS2 = ("tw.cn", "IN")
-ZONE_NAME_CLASS3 = ("example.com", "IN")
+ZONE_NAME_CLASS1_IN = ("sd.cn.", "IN")
+ZONE_NAME_CLASS2_CH = ("tw.cn", "CH")
+ZONE_NAME_CLASS3_IN = ("example.com", "IN")
+ZONE_NAME_CLASS1_CH = ("sd.cn.", "CH")
+ZONE_NAME_CLASS2_IN = ("tw.cn", "IN")
 
 
 class ZonemgrTestException(Exception):
 class ZonemgrTestException(Exception):
     pass
     pass
@@ -36,7 +38,7 @@ class MySession():
         if module_name not in ("Auth", "Xfrin"):
         if module_name not in ("Auth", "Xfrin"):
             raise ZonemgrTestException("module name not exist")
             raise ZonemgrTestException("module name not exist")
 
 
-class MyZoneMgrRefreshInfo(ZoneMgrRefreshInfo):
+class MyZonemgrRefresh(ZonemgrRefresh):
     def __init__(self):
     def __init__(self):
         self._cc = MySession()
         self._cc = MySession()
         self._db_file = "initdb.file"
         self._db_file = "initdb.file"
@@ -46,26 +48,28 @@ class MyZoneMgrRefreshInfo(ZoneMgrRefreshInfo):
          'next_refresh_time': 1280481598.822153, 
          'next_refresh_time': 1280481598.822153, 
          'zone_soa_rdata': 'a.dns.cn. root.cnnic.cn. 2009073105 7200 3600 2419200 21600', 
          'zone_soa_rdata': 'a.dns.cn. root.cnnic.cn. 2009073105 7200 3600 2419200 21600', 
          'zone_state': 0},
          'zone_state': 0},
-         ('tw.cn', 'IN'): {
+         ('tw.cn', 'CH'): {
          'last_refresh_time': 1280474399.116421, 
          'last_refresh_time': 1280474399.116421, 
          'next_refresh_time': 1280481599.116433, 
          'next_refresh_time': 1280481599.116433, 
          'zone_soa_rdata': 'a.dns.cn. root.cnnic.cn. 2009073112 7200 3600 2419200 21600', 
          'zone_soa_rdata': 'a.dns.cn. root.cnnic.cn. 2009073112 7200 3600 2419200 21600', 
          'zone_state': 0}
          'zone_state': 0}
         } 
         } 
 
 
-class TestZoneMgrRefreshInfo(unittest.TestCase):
+class TestZonemgrRefresh(unittest.TestCase):
     def setUp(self):
     def setUp(self):
         self.stdout_backup = sys.stdout
         self.stdout_backup = sys.stdout
         sys.stdout = open(os.devnull, 'w')
         sys.stdout = open(os.devnull, 'w')
-        self.zoneinfo = MyZoneMgrRefreshInfo()
+        self.zone_refresh = MyZonemgrRefresh()
 
 
     def test_random_jitter(self):
     def test_random_jitter(self):
         max = 100025.120
         max = 100025.120
         jitter = 0
         jitter = 0
-        self.assertEqual(max, self.zoneinfo._random_jitter(max, jitter))
+        self.assertEqual(max, self.zone_refresh._random_jitter(max, jitter))
         jitter = max / 4
         jitter = max / 4
-        self.assertTrue((3 * max / 4) <= self.zoneinfo._random_jitter(max, jitter)) 
-        self.assertTrue(self.zoneinfo._random_jitter(max, jitter) <= max) 
+        for i in range (0, 150):
+            self.assertTrue((3 * max / 4) <= self.zone_refresh._random_jitter(max, jitter)) 
+            self.assertTrue(self.zone_refresh._random_jitter(max, jitter) <= max) 
+            i += 1;
 
 
     def test_get_current_time(self):
     def test_get_current_time(self):
         pass
         pass
@@ -74,37 +78,39 @@ class TestZoneMgrRefreshInfo(unittest.TestCase):
         max = 3600
         max = 3600
         jitter = 900
         jitter = 900
         time1 = time.time()
         time1 = time.time()
-        self.zoneinfo._set_zone_timer(ZONE_NAME_CLASS1, 3600, 900)
+        self.zone_refresh._set_zone_timer(ZONE_NAME_CLASS1_IN, 3600, 900)
         time2 = time.time()
         time2 = time.time()
-        zone_timeout = float(self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["next_refresh_time"])
+        zone_timeout = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["next_refresh_time"]
         self.assertTrue((3600 - 900) <= (zone_timeout - time1))
         self.assertTrue((3600 - 900) <= (zone_timeout - time1))
         self.assertTrue((zone_timeout - time2) <= 3600)
         self.assertTrue((zone_timeout - time2) <= 3600)
 
 
     def test_set_zone_refresh_timer(self):
     def test_set_zone_refresh_timer(self):
         time1 = time.time()
         time1 = time.time()
-        self.zoneinfo._set_zone_refresh_timer(ZONE_NAME_CLASS1)
-        zone_timeout = self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["next_refresh_time"]
+        self.zone_refresh._set_zone_refresh_timer(ZONE_NAME_CLASS1_IN)
+        zone_timeout = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["next_refresh_time"]
         time2 = time.time()
         time2 = time.time()
         self.assertTrue((time1 + 7200 * 3 / 4) <= zone_timeout)
         self.assertTrue((time1 + 7200 * 3 / 4) <= zone_timeout)
         self.assertTrue(zone_timeout <= time2 + 7200)
         self.assertTrue(zone_timeout <= time2 + 7200)
         
         
     def test_set_zone_retry_timer(self):
     def test_set_zone_retry_timer(self):
         time1 = time.time()
         time1 = time.time()
-        self.zoneinfo._set_zone_retry_timer(ZONE_NAME_CLASS1)
-        zone_timeout = self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["next_refresh_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"]
         time2 = time.time()
         time2 = time.time()
         self.assertTrue((time1 + 3600 * 3 / 4) <= zone_timeout)
         self.assertTrue((time1 + 3600 * 3 / 4) <= zone_timeout)
         self.assertTrue(zone_timeout <= time2 + 3600)
         self.assertTrue(zone_timeout <= time2 + 3600)
 
 
     def test_zone_not_exist(self):
     def test_zone_not_exist(self):
-        self.assertFalse(self.zoneinfo._zone_not_exist(ZONE_NAME_CLASS1))
-        self.assertFalse(self.zoneinfo._zone_not_exist(ZONE_NAME_CLASS2))
-        self.assertTrue(self.zoneinfo._zone_not_exist(ZONE_NAME_CLASS3))
+        self.assertFalse(self.zone_refresh._zone_not_exist(ZONE_NAME_CLASS1_IN))
+        self.assertTrue(self.zone_refresh._zone_not_exist(ZONE_NAME_CLASS1_CH))
+        self.assertFalse(self.zone_refresh._zone_not_exist(ZONE_NAME_CLASS2_CH))
+        self.assertTrue(self.zone_refresh._zone_not_exist(ZONE_NAME_CLASS2_IN))
+        self.assertTrue(self.zone_refresh._zone_not_exist(ZONE_NAME_CLASS3_IN))
 
 
     def test_set_zone_notify_timer(self):
     def test_set_zone_notify_timer(self):
         time1 = time.time()
         time1 = time.time()
-        self.zoneinfo._set_zone_notify_timer(ZONE_NAME_CLASS1)
-        zone_timeout = self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["next_refresh_time"]
+        self.zone_refresh._set_zone_notify_timer(ZONE_NAME_CLASS1_IN)
+        zone_timeout = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["next_refresh_time"]
         time2 = time.time()
         time2 = time.time()
         self.assertTrue(time1 <= zone_timeout)
         self.assertTrue(time1 <= zone_timeout)
         self.assertTrue(zone_timeout <= time2)
         self.assertTrue(zone_timeout <= time2)
@@ -112,20 +118,22 @@ class TestZoneMgrRefreshInfo(unittest.TestCase):
     def test_zone_is_expired(self):
     def test_zone_is_expired(self):
         current_time = time.time()
         current_time = time.time()
         zone_expired_time = 2419200
         zone_expired_time = 2419200
-        self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["last_refresh_time"] = \
+        self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["last_refresh_time"] = \
                                                   current_time - zone_expired_time - 1
                                                   current_time - zone_expired_time - 1
-        self.assertTrue(self.zoneinfo._zone_is_expired(ZONE_NAME_CLASS1))
-        self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["last_refresh_time"] = \
+        self.assertTrue(self.zone_refresh._zone_is_expired(ZONE_NAME_CLASS1_IN))
+        self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["last_refresh_time"] = \
                                                   current_time - zone_expired_time + 1
                                                   current_time - zone_expired_time + 1
-        self.assertFalse(self.zoneinfo._zone_is_expired(ZONE_NAME_CLASS1))
-        self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["zone_state"] = ZONE_EXPIRED
-        self.assertTrue(self.zoneinfo._zone_is_expired(ZONE_NAME_CLASS1))
+        self.assertFalse(self.zone_refresh._zone_is_expired(ZONE_NAME_CLASS1_IN))
+        self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_state"] = ZONE_EXPIRED
+        self.assertTrue(self.zone_refresh._zone_is_expired(ZONE_NAME_CLASS1_IN))
 
 
     def test_get_zone_soa_rdata(self):
     def test_get_zone_soa_rdata(self):
         soa_rdata1  = 'a.dns.cn. root.cnnic.cn. 2009073105 7200 3600 2419200 21600' 
         soa_rdata1  = 'a.dns.cn. root.cnnic.cn. 2009073105 7200 3600 2419200 21600' 
         soa_rdata2  = 'a.dns.cn. root.cnnic.cn. 2009073112 7200 3600 2419200 21600' 
         soa_rdata2  = 'a.dns.cn. root.cnnic.cn. 2009073112 7200 3600 2419200 21600' 
-        self.assertEqual(soa_rdata1, self.zoneinfo._get_zone_soa_rdata(ZONE_NAME_CLASS1))
-        self.assertEqual(soa_rdata2, self.zoneinfo._get_zone_soa_rdata(ZONE_NAME_CLASS2))
+        self.assertEqual(soa_rdata1, self.zone_refresh._get_zone_soa_rdata(ZONE_NAME_CLASS1_IN))
+        self.assertRaises(KeyError, self.zone_refresh._get_zone_soa_rdata, ZONE_NAME_CLASS1_CH)
+        self.assertEqual(soa_rdata2, self.zone_refresh._get_zone_soa_rdata(ZONE_NAME_CLASS2_CH))
+        self.assertRaises(KeyError, self.zone_refresh._get_zone_soa_rdata, ZONE_NAME_CLASS2_IN)
          
          
     def test_zonemgr_reload_zone(self):
     def test_zonemgr_reload_zone(self):
         soa_rdata = 'a.dns.cn. root.cnnic.cn. 2009073106 1800 900 2419200 21600'
         soa_rdata = 'a.dns.cn. root.cnnic.cn. 2009073106 1800 900 2419200 21600'
@@ -134,82 +142,106 @@ class TestZoneMgrRefreshInfo(unittest.TestCase):
                     'a.dns.cn. root.cnnic.cn. 2009073106 1800 900 2419200 21600')
                     'a.dns.cn. root.cnnic.cn. 2009073106 1800 900 2419200 21600')
         sqlite3_ds.get_zone_soa = get_zone_soa
         sqlite3_ds.get_zone_soa = get_zone_soa
 
 
-        self.zoneinfo._zonemgr_reload_zone(ZONE_NAME_CLASS1)
-        self.assertEqual(soa_rdata, self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["zone_soa_rdata"])
+        self.zone_refresh.zonemgr_reload_zone(ZONE_NAME_CLASS1_IN)
+        self.assertEqual(soa_rdata, self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_soa_rdata"])
 
 
     def test_get_zone_notifier_master(self):
     def test_get_zone_notifier_master(self):
         notify_master = "192.168.1.1"
         notify_master = "192.168.1.1"
-        self.assertEqual(None, self.zoneinfo._get_zone_notifier_master(ZONE_NAME_CLASS1))
-        self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["notify_master"] = notify_master
-        self.assertEqual(notify_master, self.zoneinfo._get_zone_notifier_master(ZONE_NAME_CLASS1))
+        self.assertEqual(None, self.zone_refresh._get_zone_notifier_master(ZONE_NAME_CLASS1_IN))
+        self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["notify_master"] = notify_master
+        self.assertEqual(notify_master, self.zone_refresh._get_zone_notifier_master(ZONE_NAME_CLASS1_IN))
 
 
     def test_set_zone_notifier_master(self):
     def test_set_zone_notifier_master(self):
         notify_master = "192.168.1.1"
         notify_master = "192.168.1.1"
-        self.zoneinfo._set_zone_notifier_master(ZONE_NAME_CLASS1, notify_master)
-        self.assertEqual(self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]\
+        self.zone_refresh._set_zone_notifier_master(ZONE_NAME_CLASS1_IN, notify_master)
+        self.assertEqual(self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]\
                                                                 ["notify_master"], notify_master)
                                                                 ["notify_master"], notify_master)
 
 
     def test_clear_zone_notifier_master(self):
     def test_clear_zone_notifier_master(self):
         notify_master = "192.168.1.1"
         notify_master = "192.168.1.1"
-        self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["notify_master"] = notify_master
-        self.zoneinfo._clear_zone_notifier_master(ZONE_NAME_CLASS1)
-        self.assertFalse("notify_master" in self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1].keys())
-        self.zoneinfo._clear_zone_notifier_master(ZONE_NAME_CLASS2)
-        self.assertFalse("notify_master" in self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS2].keys())
+        self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["notify_master"] = notify_master
+        self.zone_refresh._clear_zone_notifier_master(ZONE_NAME_CLASS1_IN)
+        self.assertFalse("notify_master" in self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN].keys())
+        self.zone_refresh._clear_zone_notifier_master(ZONE_NAME_CLASS2_CH)
+        self.assertFalse("notify_master" in self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS2_CH].keys())
 
 
     def test_get_zone_state(self):
     def test_get_zone_state(self):
-        self.assertEqual(ZONE_OK, self.zoneinfo._get_zone_state(ZONE_NAME_CLASS2))
-        self.assertEqual(ZONE_OK, self.zoneinfo._get_zone_state(ZONE_NAME_CLASS2))
+        self.assertEqual(ZONE_OK, self.zone_refresh._get_zone_state(ZONE_NAME_CLASS1_IN))
+        self.assertEqual(ZONE_OK, self.zone_refresh._get_zone_state(ZONE_NAME_CLASS2_CH))
 
 
     def test_set_zone_state(self):
     def test_set_zone_state(self):
-        self.zoneinfo._set_zone_state(ZONE_NAME_CLASS1, ZONE_REFRESHING)
-        self.zoneinfo._set_zone_state(ZONE_NAME_CLASS2, ZONE_EXPIRED)
+        self.zone_refresh._set_zone_state(ZONE_NAME_CLASS1_IN, ZONE_REFRESHING)
+        self.zone_refresh._set_zone_state(ZONE_NAME_CLASS2_CH, ZONE_EXPIRED)
         self.assertEqual(ZONE_REFRESHING, \
         self.assertEqual(ZONE_REFRESHING, \
-                self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["zone_state"])
+                self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_state"])
         self.assertEqual(ZONE_EXPIRED, \
         self.assertEqual(ZONE_EXPIRED, \
-                self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS2]["zone_state"])
+                self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS2_CH]["zone_state"])
 
 
     def test_get_zone_refresh_timeout(self):
     def test_get_zone_refresh_timeout(self):
         current_time = time.time()
         current_time = time.time()
-        self.assertFalse("refresh_timeout" in self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1].keys())
-        self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["refresh_timeout"] = current_time
-        self.assertEqual(current_time, self.zoneinfo._get_zone_refresh_timeout(ZONE_NAME_CLASS1))
+        self.assertFalse("refresh_timeout" in self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN].keys())
+        self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["refresh_timeout"] = current_time
+        self.assertEqual(current_time, self.zone_refresh._get_zone_refresh_timeout(ZONE_NAME_CLASS1_IN))
 
 
     def test_set_zone_refresh_timeout(self):
     def test_set_zone_refresh_timeout(self):
         current_time = time.time()
         current_time = time.time()
-        self.zoneinfo._set_zone_refresh_timeout(ZONE_NAME_CLASS1, current_time)
-        refresh_time = self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["refresh_timeout"]
+        self.zone_refresh._set_zone_refresh_timeout(ZONE_NAME_CLASS1_IN, current_time)
+        refresh_time = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["refresh_timeout"]
         self.assertEqual(current_time, refresh_time) 
         self.assertEqual(current_time, refresh_time) 
 
 
     def test_get_zone_next_refresh_time(self):
     def test_get_zone_next_refresh_time(self):
         current_time = time.time()
         current_time = time.time()
-        self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["next_refresh_time"] = current_time
-        self.assertEqual(current_time, self.zoneinfo._get_zone_next_refresh_time(ZONE_NAME_CLASS1))
+        self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["next_refresh_time"] = current_time
+        self.assertEqual(current_time, self.zone_refresh._get_zone_next_refresh_time(ZONE_NAME_CLASS1_IN))
 
 
     def test_set_zone_next_refresh_time(self):
     def test_set_zone_next_refresh_time(self):
         current_time = time.time()
         current_time = time.time()
-        self.zoneinfo._set_zone_next_refresh_time(ZONE_NAME_CLASS1, current_time)
-        next_refresh_time = self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["next_refresh_time"]
+        self.zone_refresh._set_zone_next_refresh_time(ZONE_NAME_CLASS1_IN, current_time)
+        next_refresh_time = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["next_refresh_time"]
         self.assertEqual(current_time, next_refresh_time)
         self.assertEqual(current_time, next_refresh_time)
 
 
     def test_get_zone_last_refresh_time(self):
     def test_get_zone_last_refresh_time(self):
         current_time = time.time()
         current_time = time.time()
-        self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["last_refresh_time"] = current_time
-        self.assertEqual(current_time, self.zoneinfo._get_zone_last_refresh_time(ZONE_NAME_CLASS1))
+        self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["last_refresh_time"] = current_time
+        self.assertEqual(current_time, self.zone_refresh._get_zone_last_refresh_time(ZONE_NAME_CLASS1_IN))
 
 
     def test_set_zone_last_refresh_time(self):
     def test_set_zone_last_refresh_time(self):
         current_time = time.time()
         current_time = time.time()
-        self.zoneinfo._set_zone_last_refresh_time(ZONE_NAME_CLASS1, current_time)
-        last_refresh_time = self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["last_refresh_time"]
+        self.zone_refresh._set_zone_last_refresh_time(ZONE_NAME_CLASS1_IN, current_time)
+        last_refresh_time = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["last_refresh_time"]
         self.assertEqual(current_time, last_refresh_time) 
         self.assertEqual(current_time, last_refresh_time) 
 
 
     def test_send_command(self):
     def test_send_command(self):
-        self.assertRaises(ZonemgrTestException, self.zoneinfo._send_command, "Unknown", "Notify", None)
+        self.assertRaises(ZonemgrTestException, self.zone_refresh._send_command, "Unknown", "Notify", None)
 
 
     def test_zone_mgr_is_empty(self):
     def test_zone_mgr_is_empty(self):
-        self.assertFalse(self.zoneinfo._zone_mgr_is_empty())
-        self.zoneinfo._zonemgr_refresh_info = {} 
-        self.assertTrue(self.zoneinfo._zone_mgr_is_empty())
+        self.assertFalse(self.zone_refresh._zone_mgr_is_empty())
+        self.zone_refresh._zonemgr_refresh_info = {} 
+        self.assertTrue(self.zone_refresh._zone_mgr_is_empty())
+
+    def test_zonemgr_add_zone(self):
+        soa_rdata = 'a.dns.cn. root.cnnic.cn. 2009073106 1800 900 2419200 21600'
+
+        def get_zone_soa(zone_name, db_file):
+            return (1, 2, 'sd.cn.', 'cn.sd.', 21600, 'SOA', None, 
+                    'a.dns.cn. root.cnnic.cn. 2009073106 1800 900 2419200 21600')
+
+        sqlite3_ds.get_zone_soa = get_zone_soa
+
+        self.zone_refresh._zonemgr_refresh_info = {}
+        self.zone_refresh.zonemgr_add_zone(ZONE_NAME_CLASS1_IN)
+        self.assertEqual(1, len(self.zone_refresh._zonemgr_refresh_info))
+        zone_soa_rdata = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_soa_rdata"]
+        self.assertEqual(soa_rdata, zone_soa_rdata) 
+        self.assertEqual(ZONE_OK, self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_state"])
+        self.assertTrue("last_refresh_time" in self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN].keys())
+        self.assertTrue("next_refresh_time" in self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN].keys())
+
+        def get_zone_soa2(zone_name, db_file):
+            return None
+        sqlite3_ds.get_zone_soa = get_zone_soa2
+        self.assertRaises(ZonemgrException, self.zone_refresh.zonemgr_add_zone, \
+                                          ZONE_NAME_CLASS1_IN)
 
 
     def test_build_zonemgr_refresh_info(self):
     def test_build_zonemgr_refresh_info(self):
         soa_rdata = 'a.dns.cn. root.cnnic.cn. 2009073106 1800 900 2419200 21600'
         soa_rdata = 'a.dns.cn. root.cnnic.cn. 2009073106 1800 900 2419200 21600'
@@ -224,26 +256,26 @@ class TestZoneMgrRefreshInfo(unittest.TestCase):
         sqlite3_ds.get_zones_info = get_zones_info
         sqlite3_ds.get_zones_info = get_zones_info
         sqlite3_ds.get_zone_soa = get_zone_soa
         sqlite3_ds.get_zone_soa = get_zone_soa
 
 
-        self.zoneinfo._zonemgr_refresh_info = {}
-        self.zoneinfo._build_zonemgr_refresh_info()
-        self.assertEqual(1, len(self.zoneinfo._zonemgr_refresh_info))
-        zone_soa_rdata = self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["zone_soa_rdata"]
+        self.zone_refresh._zonemgr_refresh_info = {}
+        self.zone_refresh._build_zonemgr_refresh_info()
+        self.assertEqual(1, len(self.zone_refresh._zonemgr_refresh_info))
+        zone_soa_rdata = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_soa_rdata"]
         self.assertEqual(soa_rdata, zone_soa_rdata) 
         self.assertEqual(soa_rdata, zone_soa_rdata) 
-        self.assertEqual(ZONE_OK, self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["zone_state"])
-        self.assertTrue("last_refresh_time" in self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1].keys())
-        self.assertTrue("next_refresh_time" in self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1].keys())
+        self.assertEqual(ZONE_OK, self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_state"])
+        self.assertTrue("last_refresh_time" in self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN].keys())
+        self.assertTrue("next_refresh_time" in self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN].keys())
 
 
     def test_zone_handle_notify(self):
     def test_zone_handle_notify(self):
-        self.zoneinfo.zone_handle_notify(ZONE_NAME_CLASS1,"127.0.0.1")
-        notify_master = self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["notify_master"]
+        self.zone_refresh.zone_handle_notify(ZONE_NAME_CLASS1_IN,"127.0.0.1")
+        notify_master = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["notify_master"]
         self.assertEqual("127.0.0.1", notify_master) 
         self.assertEqual("127.0.0.1", notify_master) 
-        zone_timeout = float(self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["next_refresh_time"])
+        zone_timeout = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["next_refresh_time"]
         current_time = time.time()
         current_time = time.time()
         self.assertTrue(zone_timeout <= current_time)
         self.assertTrue(zone_timeout <= current_time)
-        self.assertRaises(ZonemgrException, self.zoneinfo.zone_handle_notify,\
-                          "org.cn.", "127.0.0.1")
-        self.assertRaises(ZonemgrException, self.zoneinfo.zone_handle_notify,\
-                          ZONE_NAME_CLASS3, "127.0.0.1")
+        self.assertRaises(ZonemgrException, self.zone_refresh.zone_handle_notify,\
+                          ("org.cn.", "IN"), "127.0.0.1")
+        self.assertRaises(ZonemgrException, self.zone_refresh.zone_handle_notify,\
+                          ZONE_NAME_CLASS3_IN, "127.0.0.1")
 
 
     def test_zone_refresh_success(self):
     def test_zone_refresh_success(self):
         soa_rdata = 'a.dns.cn. root.cnnic.cn. 2009073106 1800 900 2419200 21600'
         soa_rdata = 'a.dns.cn. root.cnnic.cn. 2009073106 1800 900 2419200 21600'
@@ -252,99 +284,103 @@ class TestZoneMgrRefreshInfo(unittest.TestCase):
                     'a.dns.cn. root.cnnic.cn. 2009073106 1800 900 2419200 21600')
                     'a.dns.cn. root.cnnic.cn. 2009073106 1800 900 2419200 21600')
         sqlite3_ds.get_zone_soa = get_zone_soa
         sqlite3_ds.get_zone_soa = get_zone_soa
         time1 = time.time()
         time1 = time.time()
-        self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["zone_state"] = ZONE_REFRESHING
-        self.zoneinfo.zone_refresh_success(ZONE_NAME_CLASS1)
+        self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_state"] = ZONE_REFRESHING
+        self.zone_refresh.zone_refresh_success(ZONE_NAME_CLASS1_IN)
         time2 = time.time()
         time2 = time.time()
-        zone_soa_rdata = self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["zone_soa_rdata"]
+        zone_soa_rdata = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_soa_rdata"]
         self.assertEqual(soa_rdata, zone_soa_rdata) 
         self.assertEqual(soa_rdata, zone_soa_rdata) 
-        next_refresh_time = self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["next_refresh_time"]
+        next_refresh_time = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["next_refresh_time"]
         self.assertTrue((time1 + 3 * 1800 / 4) <= next_refresh_time) 
         self.assertTrue((time1 + 3 * 1800 / 4) <= next_refresh_time) 
         self.assertTrue(next_refresh_time <= time2 + 1800)
         self.assertTrue(next_refresh_time <= time2 + 1800)
-        self.assertEqual(ZONE_OK, self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["zone_state"])
-        last_refresh_time = self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["last_refresh_time"]
+        self.assertEqual(ZONE_OK, self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_state"])
+        last_refresh_time = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["last_refresh_time"]
         self.assertTrue(time1 <= last_refresh_time)
         self.assertTrue(time1 <= last_refresh_time)
         self.assertTrue(last_refresh_time <= time2)
         self.assertTrue(last_refresh_time <= time2)
-        self.assertRaises(ZonemgrException, self.zoneinfo.zone_refresh_success, "org.cn.")
-        self.assertRaises(ZonemgrException, self.zoneinfo.zone_refresh_success, ZONE_NAME_CLASS3) 
+        self.assertRaises(ZonemgrException, self.zone_refresh.zone_refresh_success, ("org.cn.", "CH"))
+        self.assertRaises(ZonemgrException, self.zone_refresh.zone_refresh_success, ZONE_NAME_CLASS3_IN) 
 
 
     def test_zone_refresh_fail(self):
     def test_zone_refresh_fail(self):
         soa_rdata = 'a.dns.cn. root.cnnic.cn. 2009073105 7200 3600 2419200 21600' 
         soa_rdata = 'a.dns.cn. root.cnnic.cn. 2009073105 7200 3600 2419200 21600' 
         time1 = time.time()
         time1 = time.time()
-        self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["zone_state"] = ZONE_REFRESHING
-        self.zoneinfo.zone_refresh_fail(ZONE_NAME_CLASS1)
+        self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_state"] = ZONE_REFRESHING
+        self.zone_refresh.zone_refresh_fail(ZONE_NAME_CLASS1_IN)
         time2 = time.time()
         time2 = time.time()
-        zone_soa_rdata = self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["zone_soa_rdata"]
+        zone_soa_rdata = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_soa_rdata"]
         self.assertEqual(soa_rdata, zone_soa_rdata)
         self.assertEqual(soa_rdata, zone_soa_rdata)
-        next_refresh_time = self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["next_refresh_time"]
+        next_refresh_time = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["next_refresh_time"]
         self.assertTrue((time1 + 3 * 3600 / 4) <= next_refresh_time)
         self.assertTrue((time1 + 3 * 3600 / 4) <= next_refresh_time)
         self.assertTrue(next_refresh_time <= time2 + 3600)
         self.assertTrue(next_refresh_time <= time2 + 3600)
-        self.assertEqual(ZONE_OK, self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["zone_state"])
-        self.assertRaises(ZonemgrException, self.zoneinfo.zone_refresh_fail, "org.cn.")
-        self.assertRaises(ZonemgrException, self.zoneinfo.zone_refresh_fail, ZONE_NAME_CLASS3) 
+        self.assertEqual(ZONE_OK, self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_state"])
+        self.assertRaises(ZonemgrException, self.zone_refresh.zone_refresh_fail, ("org.cn.", "CH"))
+        self.assertRaises(ZonemgrException, self.zone_refresh.zone_refresh_fail, ZONE_NAME_CLASS3_IN) 
 
 
     def test_find_need_do_refresh_zone(self):
     def test_find_need_do_refresh_zone(self):
         time1 = time.time()
         time1 = time.time()
-        self.zoneinfo._zonemgr_refresh_info = { 
+        self.zone_refresh._zonemgr_refresh_info = { 
                 ("sd.cn.","IN"):{
                 ("sd.cn.","IN"):{
                     'last_refresh_time': time1,
                     'last_refresh_time': time1,
                     'next_refresh_time': time1 + 7200, 
                     'next_refresh_time': time1 + 7200, 
                     'zone_soa_rdata': 'a.dns.cn. root.cnnic.cn. 2009073105 7200 3600 2419200 21600', 
                     'zone_soa_rdata': 'a.dns.cn. root.cnnic.cn. 2009073105 7200 3600 2419200 21600', 
                     'zone_state': ZONE_OK},
                     'zone_state': ZONE_OK},
-                ("tw.cn","IN"):{
+                ("tw.cn","CH"):{
                     'last_refresh_time': time1 - 7200, 
                     'last_refresh_time': time1 - 7200, 
                     'next_refresh_time': time1, 
                     'next_refresh_time': time1, 
                     'refresh_timeout': time1 + MAX_TRANSFER_TIMEOUT, 
                     'refresh_timeout': time1 + MAX_TRANSFER_TIMEOUT, 
                     'zone_soa_rdata': 'a.dns.cn. root.cnnic.cn. 2009073112 7200 3600 2419200 21600', 
                     'zone_soa_rdata': 'a.dns.cn. root.cnnic.cn. 2009073112 7200 3600 2419200 21600', 
                     'zone_state': ZONE_REFRESHING}
                     'zone_state': ZONE_REFRESHING}
                 }
                 }
-        zone_need_refresh = self.zoneinfo._find_need_do_refresh_zone()
-        self.assertEqual(ZONE_NAME_CLASS1, zone_need_refresh)
+        zone_need_refresh = self.zone_refresh._find_need_do_refresh_zone()
+        self.assertEqual(ZONE_NAME_CLASS1_IN, zone_need_refresh)
 
 
-        self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["last_refresh_time"] = time1 - 2419200
-        self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["zone_state"] = ZONE_EXPIRED
-        zone_need_refresh = self.zoneinfo._find_need_do_refresh_zone()
+        self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["last_refresh_time"] = time1 - 2419200
+        self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_state"] = ZONE_EXPIRED
+        zone_need_refresh = self.zone_refresh._find_need_do_refresh_zone()
         self.assertEqual(None, zone_need_refresh)
         self.assertEqual(None, zone_need_refresh)
 
 
-        self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["zone_state"] = ZONE_REFRESHING
-        self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["notify_master"] = "192.168.0.1"
-        zone_need_refresh = self.zoneinfo._find_need_do_refresh_zone()
-        self.assertEqual(ZONE_NAME_CLASS1, zone_need_refresh)
-        self.assertEqual(ZONE_EXPIRED, self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["zone_state"])
+        self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_state"] = ZONE_REFRESHING
+        self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["notify_master"] = "192.168.0.1"
+        zone_need_refresh = self.zone_refresh._find_need_do_refresh_zone()
+        self.assertEqual(ZONE_NAME_CLASS1_IN, zone_need_refresh)
+        self.assertEqual(ZONE_EXPIRED, self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_state"])
 
 
-        self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS2]["refresh_timeout"] = time1 
-        zone_need_refresh = self.zoneinfo._find_need_do_refresh_zone()
-        self.assertEqual(ZONE_NAME_CLASS2, zone_need_refresh)
+        self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS2_CH]["refresh_timeout"] = time1 
+        zone_need_refresh = self.zone_refresh._find_need_do_refresh_zone()
+        self.assertEqual(ZONE_NAME_CLASS2_CH, zone_need_refresh)
 
 
     def test_do_refresh(self):
     def test_do_refresh(self):
         time1 = time.time()
         time1 = time.time()
-        self.zoneinfo._zonemgr_refresh_info = {
+        self.zone_refresh._zonemgr_refresh_info = {
                 ("sd.cn.", "IN"):{
                 ("sd.cn.", "IN"):{
                     'last_refresh_time': time1 - 7200,
                     'last_refresh_time': time1 - 7200,
                     'next_refresh_time': time1 - 1, 
                     'next_refresh_time': time1 - 1, 
                     'zone_soa_rdata': 'a.dns.cn. root.cnnic.cn. 2009073105 7200 3600 2419200 21600', 
                     'zone_soa_rdata': 'a.dns.cn. root.cnnic.cn. 2009073105 7200 3600 2419200 21600', 
                     'zone_state': ZONE_OK}
                     'zone_state': ZONE_OK}
                 }
                 }
-        self.zoneinfo._do_refresh(ZONE_NAME_CLASS1)
+        self.zone_refresh._do_refresh(ZONE_NAME_CLASS1_IN)
         time2 = time.time()
         time2 = time.time()
-        zone_state = self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["zone_state"]
+        zone_state = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_state"]
         self.assertEqual(ZONE_REFRESHING, zone_state)
         self.assertEqual(ZONE_REFRESHING, zone_state)
-        refresh_timeout = self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["refresh_timeout"] 
+        refresh_timeout = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["refresh_timeout"] 
         self.assertTrue(time1 + MAX_TRANSFER_TIMEOUT <= refresh_timeout)
         self.assertTrue(time1 + MAX_TRANSFER_TIMEOUT <= refresh_timeout)
         self.assertTrue(time2 + MAX_TRANSFER_TIMEOUT >= refresh_timeout) 
         self.assertTrue(time2 + MAX_TRANSFER_TIMEOUT >= refresh_timeout) 
 
 
-        self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["notify_master"] = "127.0.0.1"
-        self.zoneinfo._do_refresh(ZONE_NAME_CLASS1)
+        self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["notify_master"] = "127.0.0.1"
+        self.zone_refresh._do_refresh(ZONE_NAME_CLASS1_IN)
         time2 = time.time()
         time2 = time.time()
-        zone_state = self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["zone_state"]
+        zone_state = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_state"]
         self.assertEqual(ZONE_REFRESHING, zone_state) 
         self.assertEqual(ZONE_REFRESHING, zone_state) 
-        refrsh_timeout = self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["refresh_timeout"] 
+        refresh_timeout = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["refresh_timeout"] 
         self.assertTrue(time1 + MAX_TRANSFER_TIMEOUT <= refresh_timeout)
         self.assertTrue(time1 + MAX_TRANSFER_TIMEOUT <= refresh_timeout)
         self.assertTrue(time2 + MAX_TRANSFER_TIMEOUT >= refresh_timeout)
         self.assertTrue(time2 + MAX_TRANSFER_TIMEOUT >= refresh_timeout)
-        self.assertFalse("notify_master" in self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1].keys())
+        self.assertFalse("notify_master" in self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN].keys())
 
 
     def test_run_timer(self):
     def test_run_timer(self):
+        """This case will run timer in daemon thread. 
+        The zone's next_refresh_time is less than now, so zonemgr will do zone refresh 
+        immediately. The zone's state will become "refreshing". 
+        Then closing the socket ,the timer will stop, and throw a ZonemgrException."""
         time1 = time.time()
         time1 = time.time()
-        self.zoneinfo._zonemgr_refresh_info = {
+        self.zone_refresh._zonemgr_refresh_info = {
                 ("sd.cn.", "IN"):{
                 ("sd.cn.", "IN"):{
                     'last_refresh_time': time1 - 7200,
                     'last_refresh_time': time1 - 7200,
                     'next_refresh_time': time1 - 1, 
                     'next_refresh_time': time1 - 1, 
@@ -352,17 +388,16 @@ class TestZoneMgrRefreshInfo(unittest.TestCase):
                     'zone_state': ZONE_OK}
                     'zone_state': ZONE_OK}
                 }
                 }
         master_socket, slave_socket = socket.socketpair(socket.AF_UNIX, socket.SOCK_STREAM)
         master_socket, slave_socket = socket.socketpair(socket.AF_UNIX, socket.SOCK_STREAM)
-        self.zoneinfo._socket = slave_socket
-        # Run timer in daemon thread
-        listener = threading.Thread(target = self.zoneinfo.run_timer, args = ())
+        self.zone_refresh._socket = slave_socket
+        listener = threading.Thread(target = self.zone_refresh.run_timer, args = ())
         listener.setDaemon(True)
         listener.setDaemon(True)
         listener.start()
         listener.start()
         slave_socket.close()
         slave_socket.close()
-        zone_state = self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1]["zone_state"]
-        self.assertTrue("refresh_timeout" in self.zoneinfo._zonemgr_refresh_info[ZONE_NAME_CLASS1].keys())
+        zone_state = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_state"]
+        self.assertTrue("refresh_timeout" in self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN].keys())
         self.assertTrue(zone_state == ZONE_REFRESHING)
         self.assertTrue(zone_state == ZONE_REFRESHING)
 
 
-        self.assertRaises(ZonemgrException, self.zoneinfo.run_timer)
+        self.assertRaises(ZonemgrException, self.zone_refresh.run_timer)
 
 
     def tearDown(self):
     def tearDown(self):
         sys.stdout = self.stdout_backup
         sys.stdout = self.stdout_backup
@@ -386,7 +421,7 @@ class MyZonemgr(Zonemgr):
         self._shutdown_event = threading.Event()
         self._shutdown_event = threading.Event()
         self._cc = MySession()
         self._cc = MySession()
         self._module_cc = MyCCSession()
         self._module_cc = MyCCSession()
-        self._config_data = {"zone_name" : "org.cn", "zone_class" : "IN", "master" : "127.0.0.1"}
+        self._config_data = {"zone_name" : "org.cn", "zone_class" : "CH", "master" : "127.0.0.1"}
 
 
     def _start_zone_refresh_timer(self):
     def _start_zone_refresh_timer(self):
         pass
         pass
@@ -397,7 +432,7 @@ class TestZonemgr(unittest.TestCase):
         self.zonemgr = MyZonemgr()
         self.zonemgr = MyZonemgr()
 
 
     def test_config_handler(self):
     def test_config_handler(self):
-        config_data1 = {"zone_name" : "sd.cn.", "zone_class" : "IN", "master" : "192.168.1.1"}
+        config_data1 = {"zone_name" : "sd.cn.", "zone_class" : "CH", "master" : "192.168.1.1"}
         self.zonemgr.config_handler(config_data1)
         self.zonemgr.config_handler(config_data1)
         self.assertEqual(config_data1, self.zonemgr._config_data)
         self.assertEqual(config_data1, self.zonemgr._config_data)
         config_data2 = {"zone_name" : "sd.cn.", "port" : "53", "master" : "192.168.1.1"}
         config_data2 = {"zone_name" : "sd.cn.", "port" : "53", "master" : "192.168.1.1"}
@@ -408,14 +443,14 @@ class TestZonemgr(unittest.TestCase):
         self.assertEqual("initdb.file", self.zonemgr.get_db_file())
         self.assertEqual("initdb.file", self.zonemgr.get_db_file())
     
     
     def test_parse_cmd_params(self):
     def test_parse_cmd_params(self):
-        params1 = {"zone_name" : "org.cn", "zone_class" : "IN", "master" : "127.0.0.1"}
-        answer1 = (("org.cn", "IN"), "127.0.0.1")
+        params1 = {"zone_name" : "org.cn", "zone_class" : "CH", "master" : "127.0.0.1"}
+        answer1 = (("org.cn", "CH"), "127.0.0.1")
         self.assertEqual(answer1, self.zonemgr._parse_cmd_params(params1, ZONE_NOTIFY_COMMAND))
         self.assertEqual(answer1, self.zonemgr._parse_cmd_params(params1, ZONE_NOTIFY_COMMAND))
-        params2 = {"zone_name" : "org.cn", "zone_class" : "IN"}
-        answer2 = ("org.cn", "IN")
+        params2 = {"zone_name" : "org.cn", "zone_class" : "CH"}
+        answer2 = ("org.cn", "CH")
         self.assertEqual(answer2, self.zonemgr._parse_cmd_params(params2, ZONE_XFRIN_SUCCESS_COMMAND))
         self.assertEqual(answer2, self.zonemgr._parse_cmd_params(params2, ZONE_XFRIN_SUCCESS_COMMAND))
         self.assertRaises(ZonemgrException, self.zonemgr._parse_cmd_params, params2, ZONE_NOTIFY_COMMAND)
         self.assertRaises(ZonemgrException, self.zonemgr._parse_cmd_params, params2, ZONE_NOTIFY_COMMAND)
-        params1 = {"zone_class" : "IN"}
+        params1 = {"zone_class" : "CH"}
         self.assertRaises(ZonemgrException, self.zonemgr._parse_cmd_params, params2, ZONE_NOTIFY_COMMAND)
         self.assertRaises(ZonemgrException, self.zonemgr._parse_cmd_params, params2, ZONE_NOTIFY_COMMAND)
 
 
     def tearDown(self):
     def tearDown(self):

+ 89 - 44
src/bin/zonemgr/zonemgr.py.in

@@ -56,11 +56,13 @@ __version__ = "BIND10"
 # define module name
 # define module name
 XFRIN_MODULE_NAME = 'Xfrin'
 XFRIN_MODULE_NAME = 'Xfrin'
 AUTH_MODULE_NAME = 'Auth'
 AUTH_MODULE_NAME = 'Auth'
+
 # define command name
 # define command name
 ZONE_XFRIN_FAILED_COMMAND = 'zone_xfrin_failed'
 ZONE_XFRIN_FAILED_COMMAND = 'zone_xfrin_failed'
 ZONE_XFRIN_SUCCESS_COMMAND = 'zone_new_data_ready'
 ZONE_XFRIN_SUCCESS_COMMAND = 'zone_new_data_ready'
 ZONE_REFRESH_COMMAND = 'refresh_from_zonemgr'
 ZONE_REFRESH_COMMAND = 'refresh_from_zonemgr'
 ZONE_NOTIFY_COMMAND = 'notify'
 ZONE_NOTIFY_COMMAND = 'notify'
+
 # define zone state
 # define zone state
 ZONE_OK = 0
 ZONE_OK = 0
 ZONE_REFRESHING = 1
 ZONE_REFRESHING = 1
@@ -73,11 +75,26 @@ LOWERBOUND_RETRY = 5
 # max zone transfer timeout
 # max zone transfer timeout
 MAX_TRANSFER_TIMEOUT = 14400
 MAX_TRANSFER_TIMEOUT = 14400
 
 
+# offsets of fields in the SOA RDATA
+REFRESH_OFFSET = 3
+RETRY_OFFSET = 4
+EXPIRED_OFFSET = 5
+
+# verbose mode
+VERBOSE_MODE = False
+
+def log_msg(msg):
+    if VERBOSE_MODE:
+        sys.stdout.write("[b10-zonemgr] %s\n" % str(msg))
+
 class ZonemgrException(Exception):
 class ZonemgrException(Exception):
     pass
     pass
 
 
-class ZoneMgrRefreshInfo:
-    """This class will maintain and manage zone refresh info"""
+class ZonemgrRefresh:
+    """This class will maintain and manage zone refresh info.
+    It also provides methods to keep track of zone timers and 
+    do zone refresh.
+    """
 
 
     def __init__(self, cc, db_file, slave_socket):
     def __init__(self, cc, db_file, slave_socket):
         self._cc = cc
         self._cc = cc
@@ -89,10 +106,12 @@ class ZoneMgrRefreshInfo:
     def _random_jitter(self, max, jitter):
     def _random_jitter(self, max, jitter):
         """Imposes some random jitters for refresh and
         """Imposes some random jitters for refresh and
         retry timers to avoid many zones need to do refresh
         retry timers to avoid many zones need to do refresh
-        at the same time."""
+        at the same time. 
+        The value should be between (max - jitter) and max.
+        """
         if 0 == jitter:
         if 0 == jitter:
             return max
             return max
-        return max - random.normalvariate(max, jitter) % jitter
+        return random.uniform(max - jitter, max)
 
 
     def _get_current_time(self):
     def _get_current_time(self):
         return time.time()
         return time.time()
@@ -106,18 +125,16 @@ class ZoneMgrRefreshInfo:
         """Set zone next refresh time after zone refresh success.
         """Set zone next refresh time after zone refresh success.
            now + refresh*3/4 <= next_refresh_time <= now + refresh
            now + refresh*3/4 <= next_refresh_time <= now + refresh
            """
            """
-        zone_refresh_time = float(self._get_zone_soa_rdata(zone_name_class).split(" ")[3])
-        if (zone_refresh_time < LOWERBOUND_REFRESH):
-            zone_refresh_time = LOWERBOUND_REFRESH
+        zone_refresh_time = float(self._get_zone_soa_rdata(zone_name_class).split(" ")[REFRESH_OFFSET])
+        zone_refresh_time = max(LOWERBOUND_REFRESH, zone_refresh_time)
         self._set_zone_timer(zone_name_class, zone_refresh_time, (1 * zone_refresh_time) / 4)
         self._set_zone_timer(zone_name_class, zone_refresh_time, (1 * zone_refresh_time) / 4)
 
 
     def _set_zone_retry_timer(self, zone_name_class):
     def _set_zone_retry_timer(self, zone_name_class):
         """Set zone next refresh time after zone refresh fail.
         """Set zone next refresh time after zone refresh fail.
            now + retry*3/4 <= next_refresh_time <= now + retry
            now + retry*3/4 <= next_refresh_time <= now + retry
            """
            """
-        zone_retry_time = float(self._get_zone_soa_rdata(zone_name_class).split(" ")[4])
-        if (zone_retry_time < LOWERBOUND_RETRY):
-            zone_retry_time = LOWERBOUND_RETRY
+        zone_retry_time = float(self._get_zone_soa_rdata(zone_name_class).split(" ")[RETRY_OFFSET])
+        zone_retry_time = max(LOWERBOUND_RETRY, zone_retry_time)
         self._set_zone_timer(zone_name_class, zone_retry_time, (1 * zone_retry_time) / 4)
         self._set_zone_timer(zone_name_class, zone_retry_time, (1 * zone_retry_time) / 4)
 
 
     def _set_zone_notify_timer(self, zone_name_class):
     def _set_zone_notify_timer(self, zone_name_class):
@@ -135,10 +152,10 @@ class ZoneMgrRefreshInfo:
     def zone_refresh_success(self, zone_name_class):
     def zone_refresh_success(self, zone_name_class):
         """Update zone info after zone refresh success"""
         """Update zone info after zone refresh success"""
         if (self._zone_not_exist(zone_name_class)):
         if (self._zone_not_exist(zone_name_class)):
-            raise ZonemgrException("[b10-zonemgr] Zone %s doesn't \
-                                    belong to zonemgr" % zone_name_class[0])
+            raise ZonemgrException("[b10-zonemgr] Zone (%s, %s) doesn't \
+                                    belong to zonemgr" % zone_name_class)
             return
             return
-        self._zonemgr_reload_zone(zone_name_class)
+        self.zonemgr_reload_zone(zone_name_class)
         self._set_zone_refresh_timer(zone_name_class)
         self._set_zone_refresh_timer(zone_name_class)
         self._set_zone_state(zone_name_class, ZONE_OK)
         self._set_zone_state(zone_name_class, ZONE_OK)
         self._set_zone_last_refresh_time(zone_name_class, self._get_current_time())
         self._set_zone_last_refresh_time(zone_name_class, self._get_current_time())
@@ -146,8 +163,8 @@ class ZoneMgrRefreshInfo:
     def zone_refresh_fail(self, zone_name_class):
     def zone_refresh_fail(self, zone_name_class):
         """Update zone info after zone refresh fail"""
         """Update zone info after zone refresh fail"""
         if (self._zone_not_exist(zone_name_class)):
         if (self._zone_not_exist(zone_name_class)):
-            raise ZonemgrException("[b10-zonemgr] Zone %s doesn't \
-                                    belong to zonemgr" % zone_name_class[0])
+            raise ZonemgrException("[b10-zonemgr] Zone (%s, %s) doesn't \
+                                    belong to zonemgr" % zone_name_class)
             return
             return
         self._set_zone_state(zone_name_class, ZONE_OK)
         self._set_zone_state(zone_name_class, ZONE_OK)
         self._set_zone_retry_timer(zone_name_class)
         self._set_zone_retry_timer(zone_name_class)
@@ -155,25 +172,41 @@ class ZoneMgrRefreshInfo:
     def zone_handle_notify(self, zone_name_class, master):
     def zone_handle_notify(self, zone_name_class, master):
         """Handle zone notify"""
         """Handle zone notify"""
         if (self._zone_not_exist(zone_name_class)):
         if (self._zone_not_exist(zone_name_class)):
-            raise ZonemgrException("[b10-zonemgr] Notified zone %s doesn't \
-                                    belong to zonemgr" % zone_name_class[0])
+            raise ZonemgrException("[b10-zonemgr] Notified zone (%s, %s) doesn't \
+                                    belong to zonemgr" % zone_name_class)
             return
             return
         self._set_zone_notifier_master(zone_name_class, master)
         self._set_zone_notifier_master(zone_name_class, master)
         self._set_zone_notify_timer(zone_name_class)
         self._set_zone_notify_timer(zone_name_class)
 
 
+    def zonemgr_reload_zone(self, zone_name_class):
+        """ Reload a zone."""
+        zone_soa = sqlite3_ds.get_zone_soa(str(zone_name_class[0]), self._db_file)
+        self._zonemgr_refresh_info[zone_name_class]["zone_soa_rdata"] = zone_soa[7]
+
+    def zonemgr_add_zone(self, zone_name_class):
+        """ Add a zone into zone manager."""
+        zone_info = {}
+        zone_soa = sqlite3_ds.get_zone_soa(str(zone_name_class[0]), self._db_file)
+        if not zone_soa:
+            raise ZonemgrException("[b10-zonemgr] zone (%s, %s) doesn't have soa." % zone_name_class)
+        zone_info["zone_soa_rdata"] = zone_soa[7]
+        zone_info["zone_state"] = ZONE_OK
+        zone_info["last_refresh_time"] = self._get_current_time() 
+        zone_info["next_refresh_time"] = self._get_current_time() + \
+                                         float(zone_soa[7].split(" ")[REFRESH_OFFSET])
+        self._zonemgr_refresh_info[zone_name_class] = zone_info
+
     def _build_zonemgr_refresh_info(self):
     def _build_zonemgr_refresh_info(self):
         """ Build zonemgr refresh info map."""
         """ Build zonemgr refresh info map."""
+        log_msg("Start loading zone into zonemgr.")
         for zone_name, zone_class in sqlite3_ds.get_zones_info(self._db_file):
         for zone_name, zone_class in sqlite3_ds.get_zones_info(self._db_file):
-            zone_info = {}
-            zone_soa = sqlite3_ds.get_zone_soa(str(zone_name), self._db_file)
-            zone_info["zone_soa_rdata"] = zone_soa[7]
-            zone_info["zone_state"] = ZONE_OK
-            zone_info["last_refresh_time"] = self._get_current_time() 
-            zone_info["next_refresh_time"] = self._get_current_time() + float(zone_soa[7].split(" ")[3])
-            self._zonemgr_refresh_info[(zone_name, zone_class)] = zone_info
+            zone_name_class = (zone_name, zone_class)
+            self.zonemgr_add_zone(zone_name_class)
+        log_msg("Finish loading zone into zonemgr.")
 
 
     def _zone_is_expired(self, zone_name_class):
     def _zone_is_expired(self, zone_name_class):
-        zone_expired_time = float(self._get_zone_soa_rdata(zone_name_class).split(" ")[5])
+        """Judge whether a zone is expired or not."""
+        zone_expired_time = float(self._get_zone_soa_rdata(zone_name_class).split(" ")[EXPIRED_OFFSET])
         zone_last_refresh_time = self._get_zone_last_refresh_time(zone_name_class)
         zone_last_refresh_time = self._get_zone_last_refresh_time(zone_name_class)
         if (ZONE_EXPIRED == self._get_zone_state(zone_name_class) or
         if (ZONE_EXPIRED == self._get_zone_state(zone_name_class) or
             zone_last_refresh_time + zone_expired_time <= self._get_current_time()):
             zone_last_refresh_time + zone_expired_time <= self._get_current_time()):
@@ -184,10 +217,6 @@ class ZoneMgrRefreshInfo:
     def _get_zone_soa_rdata(self, zone_name_class):
     def _get_zone_soa_rdata(self, zone_name_class):
         return self._zonemgr_refresh_info[zone_name_class]["zone_soa_rdata"]
         return self._zonemgr_refresh_info[zone_name_class]["zone_soa_rdata"]
 
 
-    def _zonemgr_reload_zone(self, zone_name_class):
-        zone_soa = sqlite3_ds.get_zone_soa(str(zone_name_class[0]), self._db_file)
-        self._zonemgr_refresh_info[zone_name_class]["zone_soa_rdata"] = zone_soa[7]
-
     def _get_zone_last_refresh_time(self, zone_name_class):
     def _get_zone_last_refresh_time(self, zone_name_class):
         return self._zonemgr_refresh_info[zone_name_class]["last_refresh_time"]
         return self._zonemgr_refresh_info[zone_name_class]["last_refresh_time"]
 
 
@@ -228,7 +257,10 @@ class ZoneMgrRefreshInfo:
     def _send_command(self, module_name, command_name, params):
     def _send_command(self, module_name, command_name, params):
         """Send command between modules."""
         """Send command between modules."""
         msg = create_command(command_name, params)
         msg = create_command(command_name, params)
-        self._cc.group_sendmsg(msg, module_name)
+        try:
+            self._cc.group_sendmsg(msg, module_name)
+        except socket.error:
+            std.err.write("[b10-zonemgr] Failed to send to module %s, the session has been closed." % module_name) 
 
 
     def _find_need_do_refresh_zone(self):
     def _find_need_do_refresh_zone(self):
         """Find the first zone need do refresh, if no zone need
         """Find the first zone need do refresh, if no zone need
@@ -239,6 +271,7 @@ class ZoneMgrRefreshInfo:
             # Does the zone expired?
             # Does the zone expired?
             if (ZONE_EXPIRED != self._get_zone_state(zone_name_class) and 
             if (ZONE_EXPIRED != self._get_zone_state(zone_name_class) and 
                 self._zone_is_expired(zone_name_class)):
                 self._zone_is_expired(zone_name_class)):
+                log_msg("Zone (%s, %s) is expired." % zone_name_class)
                 self._set_zone_state(zone_name_class, ZONE_EXPIRED)
                 self._set_zone_state(zone_name_class, ZONE_EXPIRED)
 
 
             zone_state = self._get_zone_state(zone_name_class)
             zone_state = self._get_zone_state(zone_name_class)
@@ -247,7 +280,7 @@ class ZoneMgrRefreshInfo:
                 (not self._get_zone_notifier_master(zone_name_class))):
                 (not self._get_zone_notifier_master(zone_name_class))):
                 continue
                 continue
 
 
-            # If hasn't received refresh response within refresh timeout, skip the zone
+            # If hasn't received refresh response but are within refresh timeout, skip the zone
             if (ZONE_REFRESHING == zone_state and
             if (ZONE_REFRESHING == zone_state and
                 (self._get_zone_refresh_timeout(zone_name_class) > self._get_current_time())):
                 (self._get_zone_refresh_timeout(zone_name_class) > self._get_current_time())):
                 continue
                 continue
@@ -267,6 +300,7 @@ class ZoneMgrRefreshInfo:
     
     
     def _do_refresh(self, zone_name_class):
     def _do_refresh(self, zone_name_class):
         """Do zone refresh."""
         """Do zone refresh."""
+        log_msg("Do refresh for zone (%s, %s)." % zone_name_class)
         self._set_zone_state(zone_name_class, ZONE_REFRESHING)
         self._set_zone_state(zone_name_class, ZONE_REFRESHING)
         self._set_zone_refresh_timeout(zone_name_class, self._get_current_time() + MAX_TRANSFER_TIMEOUT) 
         self._set_zone_refresh_timeout(zone_name_class, self._get_current_time() + MAX_TRANSFER_TIMEOUT) 
         notify_master = self._get_zone_notifier_master(zone_name_class)
         notify_master = self._get_zone_notifier_master(zone_name_class)
@@ -310,7 +344,6 @@ class ZoneMgrRefreshInfo:
                     self._do_refresh(zone_need_refresh)
                     self._do_refresh(zone_need_refresh)
                     continue
                     continue
 
 
-
             """ Wait for the socket notification for a maximum time of timeout 
             """ Wait for the socket notification for a maximum time of timeout 
             in seconds (as float)."""
             in seconds (as float)."""
             try:
             try:
@@ -327,32 +360,35 @@ class ZoneMgrRefreshInfo:
                     raise ZonemgrException("[b10-zonemgr] Error with select(): %s\n" % err)
                     raise ZonemgrException("[b10-zonemgr] Error with select(): %s\n" % err)
                     break
                     break
 
 
-class Zonemgr:
 
 
-    def __init__(self, verbose = False):
+class Zonemgr:
+    """Zone manager class."""
+    def __init__(self):
         self._setup_session()
         self._setup_session()
         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_info = ZoneMgrRefreshInfo(self._cc, self._db_file, self._slave_socket)
+        self._zone_refresh= ZonemgrRefresh(self._cc, self._db_file, self._slave_socket)
         self._start_zone_refresh_timer()
         self._start_zone_refresh_timer()
 
 
         self._lock = threading.Lock()
         self._lock = threading.Lock()
         self._shutdown_event = threading.Event()
         self._shutdown_event = threading.Event()
-        self._verbose = verbose
 
 
     def _start_zone_refresh_timer(self):
     def _start_zone_refresh_timer(self):
         """Start a new thread to keep track of zone timers"""
         """Start a new thread to keep track of zone timers"""
-        listener = threading.Thread(target = self._zone_refresh_info.run_timer, args = ())
+        listener = threading.Thread(target = self._zone_refresh.run_timer, args = ())
         listener.setDaemon(True)
         listener.setDaemon(True)
         listener.start()
         listener.start()
 
 
     def _setup_session(self):
     def _setup_session(self):
+        """Setup two sessions for zonemgr, one(self._module_cc) is used for receiving 
+        commands and config data sent from other modules, another one (self._cc)
+        is used to send commands to proper modules."""
         self._cc = isc.cc.Session()
         self._cc = isc.cc.Session()
         self._module_cc = isc.config.ModuleCCSession(SPECFILE_LOCATION,
         self._module_cc = isc.config.ModuleCCSession(SPECFILE_LOCATION,
                                                   self.config_handler,
                                                   self.config_handler,
                                                   self.command_handler)
                                                   self.command_handler)
-        self._module_cc.add_remote_config(AUTH_SPECFILE_LOCATION);
+        self._module_cc.add_remote_config(AUTH_SPECFILE_LOCATION)
         self._config_data = self._module_cc.get_full_config()
         self._config_data = self._module_cc.get_full_config()
         self._module_cc.start()
         self._module_cc.start()
 
 
@@ -366,7 +402,9 @@ class Zonemgr:
         return db_file
         return db_file
 
 
     def shutdown(self):
     def shutdown(self):
-
+        """Shutdown the zonemgr process. the thread which is keeping track of zone
+        timers should be terminated.
+        """ 
         self._slave_socket.close()
         self._slave_socket.close()
         self._master_socket.close()
         self._master_socket.close()
 
 
@@ -378,6 +416,7 @@ class Zonemgr:
             th.join()
             th.join()
 
 
     def config_handler(self, new_config):
     def config_handler(self, new_config):
+        """Update config data."""
         answer = create_answer(0)
         answer = create_answer(0)
         for key in new_config:
         for key in new_config:
             if key not in self._config_data:
             if key not in self._config_data:
@@ -393,7 +432,7 @@ class Zonemgr:
 
 
         zone_class = args.get("zone_class")
         zone_class = args.get("zone_class")
         if not zone_class:
         if not zone_class:
-                raise ZonemgrException("zone class should be provided")
+            raise ZonemgrException("zone class should be provided")
 
 
         if (command != ZONE_NOTIFY_COMMAND):
         if (command != ZONE_NOTIFY_COMMAND):
             return (zone_name, zone_class)
             return (zone_name, zone_class)
@@ -406,27 +445,33 @@ class Zonemgr:
 
 
 
 
     def command_handler(self, command, args):
     def command_handler(self, command, args):
+        """Handle command receivd from command channel.
+        ZONE_NOTIFY_COMMAND is issued by Auth process; ZONE_XFRIN_SUCCESS_COMMAND 
+        and ZONE_XFRIN_FAILED_COMMAND are issued by Xfrin process; shutdown is issued
+        by a user or Boss process. """
         answer = create_answer(0)
         answer = create_answer(0)
         if command == ZONE_NOTIFY_COMMAND:
         if command == ZONE_NOTIFY_COMMAND:
             """ Handle Auth notify command"""
             """ Handle Auth notify command"""
+            # master is the source sender of the notify message.
             zone_name_class, master = self._parse_cmd_params(args, command)
             zone_name_class, master = self._parse_cmd_params(args, command)
+            log_msg("Received notify command for zone (%s, %s)." % zone_name_class)
             with self._lock:
             with self._lock:
-                self._zone_refresh_info.zone_handle_notify(zone_name_class, master)
+                self._zone_refresh.zone_handle_notify(zone_name_class, master)
             # Send notification to zonemgr timer thread
             # Send notification to zonemgr timer thread
             self._master_socket.send(b" ")
             self._master_socket.send(b" ")
 
 
         elif command == ZONE_XFRIN_SUCCESS_COMMAND:
         elif command == ZONE_XFRIN_SUCCESS_COMMAND:
-            """ Handle xfrin succes command"""
+            """ Handle xfrin success command"""
             zone_name_class = self._parse_cmd_params(args, command)
             zone_name_class = self._parse_cmd_params(args, command)
             with self._lock:
             with self._lock:
-                self._zone_refresh_info.zone_refresh_success(zone_name_class)
+                self._zone_refresh.zone_refresh_success(zone_name_class)
             self._master_socket.send(b" ")
             self._master_socket.send(b" ")
 
 
         elif command == ZONE_XFRIN_FAILED_COMMAND:
         elif command == ZONE_XFRIN_FAILED_COMMAND:
             """ Handle xfrin fail command"""
             """ Handle xfrin fail command"""
             zone_name_class = self._parse_cmd_params(args, command)
             zone_name_class = self._parse_cmd_params(args, command)
             with self._lock:
             with self._lock:
-                self._zone_refresh_info.zone_refresh_fail(zone_name_class)
+                self._zone_refresh.zone_refresh_fail(zone_name_class)
             self._master_socket.send(b" ")
             self._master_socket.send(b" ")
 
 
         elif command == "shutdown":
         elif command == "shutdown":