Parcourir la source

[2136] updated stats.py and added a related testcase

 - update last_update_time when initially updating statistics of stats
 - strict validation check of poll-interval
 - move the code requesting to boss inside of the main loop
Naoki Kambe il y a 12 ans
Parent
commit
613c10d9f1
2 fichiers modifiés avec 76 ajouts et 35 suppressions
  1. 45 30
      src/bin/stats/stats.py.in
  2. 31 5
      src/bin/stats/tests/b10-stats_test.py

+ 45 - 30
src/bin/stats/stats.py.in

@@ -159,42 +159,50 @@ class Stats:
         self.running = True
         logger.info(STATS_STARTING)
 
-        # request Bob to send statistics data
-        logger.debug(DBG_STATS_MESSAGING, STATS_SEND_REQUEST_BOSS)
-        cmd = isc.config.ccsession.create_command("getstats", None)
-        seq = self.cc_session.group_sendmsg(cmd, 'Boss')
-        try:
-            answer, env = self.cc_session.group_recvmsg(False, seq)
-            if answer:
-                rcode, args = isc.config.ccsession.parse_answer(answer)
-                if rcode == 0:
-                    errors = self.update_statistics_data(
-                        args["owner"], **args["data"])
-                    if errors:
-                        raise StatsError("boss spec file is incorrect: "
-                                         + ", ".join(errors))
-                    errors = self.update_statistics_data(
-                                self.module_name,
-                                last_update_time=get_datetime())
-                    if errors:
-                        raise StatsError("stats spec file is incorrect: "
-                                         + ", ".join(errors))
-        except isc.cc.session.SessionTimeout:
-            pass
-
         # initialized Statistics data
         errors = self.update_statistics_data(
             self.module_name,
             lname=self.cc_session.lname,
-            boot_time=get_datetime(_BASETIME)
+            boot_time=get_datetime(_BASETIME),
+            last_update_time=get_datetime()
             )
         if errors:
             raise StatsError("stats spec file is incorrect: "
                              + ", ".join(errors))
 
         try:
+            start_time = get_timestamp() - self.config['poll-interval']
             while self.running:
-                self.mccs.check_command(False)
+                if get_timestamp() - start_time >= self.config['poll-interval'] \
+                        and self.config['poll-interval'] > 0:
+                    # request Bob to send statistics data
+                    logger.debug(DBG_STATS_MESSAGING, STATS_SEND_REQUEST_BOSS)
+                    cmd = isc.config.ccsession.create_command("getstats", None)
+                    seq = self.cc_session.group_sendmsg(cmd, 'Boss')
+                    try:
+                        answer, env = self.cc_session.group_recvmsg(False, seq)
+                        if answer:
+                            rcode, args = isc.config.ccsession.parse_answer(answer)
+                            if rcode == 0:
+                                errors = self.update_statistics_data(
+                                    args["owner"], **args["data"])
+                                if errors:
+                                    raise StatsError("boss spec file is incorrect: "
+                                                     + ", ".join(errors))
+                                errors = self.update_statistics_data(
+                                            self.module_name,
+                                            last_update_time=get_datetime())
+                                if errors:
+                                    raise StatsError("stats spec file is incorrect: "
+                                                     + ", ".join(errors))
+                    except isc.cc.session.SessionTimeout:
+                        raise
+                    start_time = get_timestamp()
+                try:
+                    answer, env = self.cc_session.group_recvmsg(False)
+                    self.mccs.check_command_without_recvmsg(answer, env)
+                except isc.cc.session.SessionTimeout:
+                    pass
         finally:
             self.mccs.send_stopping()
 
@@ -204,11 +212,18 @@ class Stats:
         """
         logger.debug(DBG_STATS_MESSAGING, STATS_RECEIVED_NEW_CONFIG,
                      new_config)
-        # update to new config
-        if new_config and type(new_config) is dict:
-            # backup old config
-            self.old_config = self.config.copy()
-            self.config.update(new_config)
+        errors = []
+        if not self.mccs.get_module_spec().\
+                validate_config(False, new_config, errors):
+                return isc.config.ccsession.create_answer(
+                    1, ", ".join(errors))
+
+        if 'poll-interval' in new_config \
+                and new_config['poll-interval'] < 0:
+            return isc.config.ccsession.create_answer(
+                1, "Negative integer ignored")
+
+        self.config.update(new_config)
         return isc.config.create_answer(0)
 
     def command_handler(self, command, kwargs):

+ 31 - 5
src/bin/stats/tests/b10-stats_test.py

@@ -227,11 +227,6 @@ class TestStats(unittest.TestCase):
         self.stats_server = ThreadingServerManager(MyStats)
         self.stats = self.stats_server.server
         self.stats_server.run()
-        # test updating poll-interval
-        self.assertEqual(self.stats.config['poll-interval'], 60)
-        self.assertEqual(self.stats.config_handler({'poll-interval': 120}),
-                         isc.config.create_answer(0))
-        self.assertEqual(self.stats.config['poll-interval'], 120)
 
         # command_handler
         self.base.boss.server._started.wait()
@@ -438,6 +433,37 @@ class TestStats(unittest.TestCase):
         self.assertEqual(self.stats.statistics_data_bypid['Auth'][9998]['queries.tcp'], 1002)
         self.assertEqual(self.stats.statistics_data_bypid['Auth'][9998]['queries.udp'], 1003)
 
+    def test_config(self):
+        stats_server = ThreadingServerManager(MyStats)
+        stats = stats_server.server
+        # test updating poll-interval
+        self.assertEqual(stats.config['poll-interval'], 60)
+        self.assertEqual(stats.config_handler({'poll-interval': 120}),
+                         isc.config.create_answer(0))
+        self.assertEqual(stats.config['poll-interval'], 120)
+        self.assertEqual(stats.config_handler({'poll-interval': "foo"}),
+                         isc.config.create_answer(1, 'foo should be an integer'))
+        self.assertEqual(stats.config_handler({'poll-interval': -1}),
+                         isc.config.create_answer(1, 'Negative integer ignored'))
+        # unknown item
+        self.assertEqual(
+            stats.config_handler({'_UNKNOWN_KEY_': None}),
+            isc.config.ccsession.create_answer(
+                1, "unknown item _UNKNOWN_KEY_"))
+        # test no change if zero interval time
+        self.assertEqual(stats.config_handler({'poll-interval': 0}),
+                         isc.config.create_answer(0))
+        self.assertEqual(stats.config['poll-interval'], 0)
+        stats_server.run()
+        self.base.boss.server._started.wait()
+        self.base.boss.server._started.clear()
+        self.assertEqual(
+            send_command(
+                'show', 'Stats',
+                params={ 'owner' : 'Boss',
+                  'name'  : 'boot_time' }),
+            (0, {'Boss': {'boot_time': '1970-01-01T00:00:00Z'}}))
+
     def test_commands(self):
         # status
         self.assertEqual(self.stats.command_status(),