Browse Source

[master] Merge branch 'trac2297'

JINMEI Tatuya 12 years ago
parent
commit
59a449f506

+ 2 - 0
configure.ac

@@ -1299,6 +1299,7 @@ AC_OUTPUT([doc/version.ent
            src/bin/zonemgr/tests/zonemgr_test
            src/bin/zonemgr/run_b10-zonemgr.sh
            src/bin/sysinfo/sysinfo.py
+           src/bin/sysinfo/run_sysinfo.sh
            src/bin/stats/stats.py
            src/bin/stats/stats_httpd.py
            src/bin/bind10/bind10_src.py
@@ -1377,6 +1378,7 @@ AC_OUTPUT([doc/version.ent
            chmod +x src/bin/loadzone/run_loadzone.sh
            chmod +x src/bin/loadzone/tests/correct/correct_test.sh
            chmod +x src/bin/loadzone/tests/error/error_test.sh
+           chmod +x src/bin/sysinfo/run_sysinfo.sh
            chmod +x src/bin/usermgr/run_b10-cmdctl-usermgr.sh
            chmod +x src/bin/msgq/run_msgq.sh
            chmod +x src/bin/msgq/tests/msgq_test

+ 2 - 1
src/bin/sysinfo/.gitignore

@@ -1,3 +1,4 @@
 /isc-sysinfo
-/sysinfo.py
 /isc-sysinfo.1
+/run_sysinfo.sh
+/sysinfo.py

+ 1 - 0
src/bin/sysinfo/Makefile.am

@@ -1,4 +1,5 @@
 bin_SCRIPTS = isc-sysinfo
+noinst_SCRIPTS = run_sysinfo.sh
 
 CLEANFILES = isc-sysinfo sysinfo.pyc
 

+ 38 - 0
src/bin/sysinfo/run_sysinfo.sh.in

@@ -0,0 +1,38 @@
+#! /bin/sh
+
+# Copyright (C) 2012  Internet Systems Consortium.
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SYSTEMS CONSORTIUM
+# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+# INTERNET SYSTEMS CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+# FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+PYTHON_EXEC=${PYTHON_EXEC:-@PYTHON@}
+export PYTHON_EXEC
+
+SYSINFO_PATH=@abs_top_builddir@/src/bin/sysinfo
+
+# Note: we shouldn't need log_messages except for the seemingly necessary
+# dependency due to the automatic import in the isc package (its __init__.py
+# imports some other modules)
+PYTHONPATH=@abs_top_builddir@/src/lib/python:@abs_top_srcdir@/src/lib/python:@abs_top_builddir@/src/lib/python/isc/log_messages
+export PYTHONPATH
+
+# Likewise, we need only because isc.log requires some loadable modules.
+# sysinfo itself shouldn't need any of them.
+SET_ENV_LIBRARY_PATH=@SET_ENV_LIBRARY_PATH@
+if test $SET_ENV_LIBRARY_PATH = yes; then
+	@ENV_LIBRARY_PATH@=@abs_top_builddir@/src/lib/dns/.libs:@abs_top_builddir@/src/lib/dns/python/.libs:@abs_top_builddir@/src/lib/cryptolink/.libs:@abs_top_builddir@/src/lib/cc/.libs:@abs_top_builddir@/src/lib/config/.libs:@abs_top_builddir@/src/lib/log/.libs:@abs_top_builddir@/src/lib/acl/.libs:@abs_top_builddir@/src/lib/util/.libs:@abs_top_builddir@/src/lib/util/io/.libs:@abs_top_builddir@/src/lib/exceptions/.libs:@abs_top_builddir@/src/lib/datasrc/.libs:$@ENV_LIBRARY_PATH@
+	export @ENV_LIBRARY_PATH@
+fi
+
+cd ${SYSINFO_PATH}
+exec ${PYTHON_EXEC} -O sysinfo.py "$@"

+ 2 - 4
src/bin/sysinfo/sysinfo.py.in

@@ -22,11 +22,8 @@ ISC sysinfo program.
 
 import sys; sys.path.append ('@@PYTHONPATH@@')
 import getopt
-import isc.util.process
 from isc.sysinfo import *
 
-isc.util.process.rename()
-
 def usage():
     print("Usage: %s [-h] [-o <output-file>]" % sys.argv[0], \
               file=sys.stderr)
@@ -88,7 +85,8 @@ def main():
 
     write_value(f, ' + Machine name: %s\n', s.get_platform_machine)
     write_value(f, ' + Hostname: %s\n', s.get_platform_hostname)
-    write_value(f, ' + Uptime: %d seconds\n', s.get_uptime)
+    write_value(f, ' + Uptime: %d seconds', s.get_uptime)
+    write_value(f, ' (%s)\n', s.get_uptime_desc)
 
     write_value(f, ' + Loadavg: %f %f %f\n', s.get_loadavg)
 

+ 7 - 0
src/bin/tests/process_rename_test.py.in

@@ -39,6 +39,11 @@ class TestRename(unittest.TestCase):
         Then scan them by looking at the source text
         (without actually running them)
         """
+
+        # Scripts named in this list are not expected to be renamed and
+        # should be excluded from the scan.
+        EXCLUDED_SCRIPTS = ['isc-sysinfo']
+
         # Regexp to find all the *_SCRIPTS = something lines (except for
         # noinst_SCRIPTS, which are scripts for tests), including line
         # continuations (backslash and newline)
@@ -59,6 +64,8 @@ class TestRename(unittest.TestCase):
                 for (var, _) in lines.findall(re.sub(excluded_lines, '',
                                                      makefile)):
                     for (script, _) in scripts.findall(var):
+                        if script in EXCLUDED_SCRIPTS:
+                            continue
                         self.__scan(d, script, fun)
 
 if __name__ == "__main__":

+ 30 - 7
src/lib/python/isc/sysinfo/sysinfo.py

@@ -22,6 +22,7 @@ import subprocess
 import os.path
 import platform
 import time
+from datetime import timedelta
 
 class SysInfo:
     def __init__(self):
@@ -93,6 +94,18 @@ class SysInfo:
         """Returns the uptime in seconds."""
         return self._uptime
 
+    def get_uptime_desc(self):
+        """Returns the uptime in human readable form.
+
+        The format is the result of str() method of the standard library
+        datetime.timedelta class.  It returns None if _uptime is None.
+
+        """
+        if self._uptime is None:
+            return None
+
+        return str(timedelta(seconds=self._uptime))
+
     def get_loadavg(self):
         """Returns the load average as 3 floating point values in an array."""
         return self._loadavg
@@ -333,11 +346,11 @@ class SysInfoOpenBSD(SysInfoBSD):
             pass
 
         try:
+            # We use the size of free-list from the vmstat result.
             s = subprocess.check_output(['vmstat'])
             lines = s.decode('utf-8').split('\n')
             v = re.split('\s+', lines[2])
-            used = int(v[4]) * 1024
-            self._mem_free = self._mem_total - used
+            self._mem_free = int(v[5]) * 1024
         except (subprocess.CalledProcessError, OSError):
             pass
 
@@ -389,17 +402,27 @@ class SysInfoFreeBSD(SysInfoFreeBSDOSX):
         super().__init__()
 
         try:
-            s = subprocess.check_output(['sysctl', '-n', 'kern.smp.active'])
-            self._platform_is_smp = int(s.decode('utf-8').strip()) > 0
-        except (subprocess.CalledProcessError, OSError):
+            # There doesn't seem to be an easy way to reliably detect whether
+            # the kernel was built with SMP support on FreeBSD.  We use
+            # a sysctl variable that is only defined in SMP kernels.
+            # This assumption seems to hold for several recent versions of
+            # FreeBSD, but it may not always be so for future versions.
+            s = subprocess.check_output(['sysctl', '-n',
+                                         'kern.smp.forward_signal_enabled'])
+            self._platform_is_smp = True # the value doesn't matter
+        except subprocess.CalledProcessError:
+            # if this variable isn't defined we should see this exception.
+            # intepret it as an indication of non-SMP kernel.
+            self._platform_is_smp = False
+        except OSError:
             pass
 
         try:
+            # We use the size of free-list from the vmstat result.
             s = subprocess.check_output(['vmstat', '-H'])
             lines = s.decode('utf-8').split('\n')
             v = re.split('\s+', lines[2])
-            used = int(v[4]) * 1024
-            self._mem_free = self._mem_total - used
+            self._mem_free = int(v[5]) * 1024
         except (subprocess.CalledProcessError, OSError):
             pass
 

+ 53 - 12
src/lib/python/isc/sysinfo/tests/sysinfo_test.py

@@ -49,7 +49,7 @@ class MyLinuxFile:
         elif self._filename == '/proc/version':
             return 'An SMP version string'
         elif self._filename == '/proc/uptime':
-            return '86400.75 139993.71'
+            return '172800.75 139993.71'
         elif self._filename == '/proc/loadavg':
             return '0.1 0.2 0.3 0.4'
         else:
@@ -171,26 +171,33 @@ def _my_freebsd_os_sysconf(key):
 def _my_freebsd_platform_uname():
     return ('FreeBSD', 'freebsd', '8.2-RELEASE', '', 'i386')
 
-def _my_freebsd_osx_subprocess_check_output(command):
+def _my_freebsd_osx_subprocess_check_output(command, faked_output={}):
     '''subprocess output shared for freebsd and osx'''
     assert type(command) == list, 'command argument is not a list'
     if command == ['sysctl', '-n', 'kern.boottime']:
-        return bytes('{ sec = ' + str(int(time.time() - 76632)) + ', usec = 0 }\n', 'utf-8')
+        if 'boottime-sysctl' in faked_output:
+            return faked_output['boottime-sysctl']
+        return bytes('{ sec = ' + str(int(time.time() - 76632)) +
+                     ', usec = 0 }\n', 'utf-8')
     elif command == ['sysctl', '-n', 'vm.loadavg']:
         return b'{ 0.2 0.4 0.6 }\n'
     else:
         return _my_bsd_subprocess_check_output(command)
 
-def _my_freebsd_subprocess_check_output(command):
+def _my_freebsd_subprocess_check_output(command, faked_output):
     assert type(command) == list, 'command argument is not a list'
-    if command == ['sysctl', '-n', 'kern.smp.active']:
-        return b'1\n'
+    if command == ['sysctl', '-n', 'kern.smp.forward_signal_enabled']:
+        output = faked_output['smp-sysctl']
+        if isinstance(output, Exception):
+            raise output
+        return output
     elif command == ['vmstat', '-H']:
         return b' procs    memory       page                    disks    traps          cpu\n r b w    avm     fre  flt  re  pi  po  fr  sr wd0 cd0  int   sys   cs us sy id\n 0 0 0   343434  123456   47   0   0   0   0   0   2   0    2    80   14  0  1 99\n'
     elif command == ['swapctl', '-s', '-k']:
         return b'Total:         1013216    0\n'
     else:
-        freebsd_osx_output = _my_freebsd_osx_subprocess_check_output(command)
+        freebsd_osx_output = \
+            _my_freebsd_osx_subprocess_check_output(command, faked_output)
         if freebsd_osx_output is not None:
             return freebsd_osx_output
         else:
@@ -252,6 +259,7 @@ class SysInfoTest(unittest.TestCase):
         self.assertEqual('Unknown', s.get_platform_machine())
         self.assertFalse(s.get_platform_is_smp())
         self.assertEqual(None, s.get_uptime())
+        self.assertEqual(None, s.get_uptime_desc())
         self.assertEqual(None, s.get_loadavg())
         self.assertEqual(None, s.get_mem_total())
         self.assertEqual(None, s.get_mem_free())
@@ -267,7 +275,11 @@ class SysInfoTest(unittest.TestCase):
 
     def test_sysinfo_factory(self):
         """Test that SysInfoFromFactory returns a valid system-specific
-        SysInfo implementation."""
+        SysInfo implementation.
+
+        See sysinfo.SysInfoTestcase() for some of the parameters.
+
+        """
 
         old_platform_system = platform.system
         platform.system = _my_testcase_platform_system
@@ -281,6 +293,8 @@ class SysInfoTest(unittest.TestCase):
         self.assertEqual('Unknown', s.get_platform_machine())
         self.assertFalse(s.get_platform_is_smp())
         self.assertEqual(131072, s.get_uptime())
+        # We check that we do NOT add 's' to 'day' (because it's singular):
+        self.assertEqual('1 day, 12:24:32', s.get_uptime_desc())
         self.assertEqual(None, s.get_loadavg())
         self.assertEqual(None, s.get_mem_total())
         self.assertEqual(None, s.get_mem_free())
@@ -312,7 +326,10 @@ class SysInfoTest(unittest.TestCase):
         self.assertEqual(NPROCESSORS_LINUX, s.get_num_processors())
         self.assertEqual('myhostname', s.get_platform_hostname())
         self.assertTrue(s.get_platform_is_smp())
-        self.assertEqual(86401, s.get_uptime())
+        self.assertEqual(172801, s.get_uptime())
+        # We check that we add 's' to 'day', and that the mm part has an
+        # additional 0, i.e., not '0:0' but '0:00':
+        self.assertEqual('2 days, 0:00:01', s.get_uptime_desc())
         self.assertEqual((0.1, 0.2, 0.3), s.get_loadavg())
         self.assertEqual(3157884928, s.get_mem_total())
         self.assertEqual(891383808, s.get_mem_free())
@@ -366,7 +383,7 @@ class SysInfoTest(unittest.TestCase):
         self.assertEqual((0.7, 0.9, 0.8), s.get_loadavg())
         self.assertFalse(s.get_platform_is_smp())
         self.assertEqual(543214321, s.get_mem_total())
-        self.assertEqual(543214321 - (121212 * 1024), s.get_mem_free())
+        self.assertEqual(123456 * 1024, s.get_mem_free())
         self.assertEqual(566791168, s.get_mem_swap_total())
         self.assertEqual(566789120, s.get_mem_swap_free())
 
@@ -379,18 +396,42 @@ class SysInfoTest(unittest.TestCase):
         # with mock ones for testing.
         platform.system = _my_freebsd_platform_system
         os.sysconf = _my_freebsd_os_sysconf
-        subprocess.check_output = _my_freebsd_subprocess_check_output
+
+        # We use a lambda object so we can tweak the subprocess output during
+        # the tests later.
+        faked_process_output = { 'smp-sysctl': b'1\n' }
+        subprocess.check_output = lambda command : \
+            _my_freebsd_subprocess_check_output(command, faked_process_output)
+
         os.uname = _my_freebsd_platform_uname
 
         s = SysInfoFromFactory()
         self.assertEqual(NPROCESSORS_FREEBSD, s.get_num_processors())
         self.assertTrue(s.get_platform_is_smp())
 
+        # We check the kernel SMP support by the availability of a sysctl
+        # variable.  The value (especially a 0 value) shouldn't matter.
+        faked_process_output['smp-sysctl'] = b'0\n'
+        s = SysInfoFromFactory()
+        self.assertTrue(s.get_platform_is_smp())
+
+        # if the sysctl raises CalledProcessError, we treat it as non-SMP
+        # kernel.
+        faked_process_output['smp-sysctl'] = \
+            subprocess.CalledProcessError(1, 'sysctl')
+        s = SysInfoFromFactory()
+        self.assertFalse(s.get_platform_is_smp())
+
+        # if it results in OSError, no SMP information will be provided.
+        faked_process_output['smp-sysctl'] = OSError()
+        s = SysInfoFromFactory()
+        self.assertIsNone(s.get_platform_is_smp())
+
         self.check_bsd_values(s)
 
         self.assertEqual((0.2, 0.4, 0.6), s.get_loadavg())
         self.assertEqual(543214321, s.get_mem_total())
-        self.assertEqual(543214321 - (343434 * 1024), s.get_mem_free())
+        self.assertEqual(123456 * 1024, s.get_mem_free())
         self.assertEqual(1037533184, s.get_mem_swap_total())
         self.assertEqual(1037533184, s.get_mem_swap_free())