Commit ed2a1231 authored by Tomek Mrugalski's avatar Tomek Mrugalski 🛰
parents 77e9624b 9276a6b3
...@@ -32,6 +32,15 @@ def usage(): ...@@ -32,6 +32,15 @@ def usage():
file=sys.stderr) file=sys.stderr)
exit(1) exit(1)
def write_value(out, fmt, call):
'''Helper function for standard value writing.
Writes the result from the call in the given format to out.
Does not write anything if the result of the call is None.
'''
value = call()
if value is not None:
out.write(fmt % value)
def main(): def main():
try: try:
opts, args = getopt.getopt(sys.argv[1:], "o:h", \ opts, args = getopt.getopt(sys.argv[1:], "o:h", \
...@@ -57,39 +66,39 @@ def main(): ...@@ -57,39 +66,39 @@ def main():
s = SysInfoFromFactory() s = SysInfoFromFactory()
f.write('BIND 10 ShowTech tool\n') f.write('ISC Sysinfo tool\n')
f.write('=====================\n') f.write('================\n')
f.write('\nCPU\n'); f.write('\nCPU\n');
f.write(' + Number of processors: %d\n' % (s.get_num_processors())) write_value(f, ' + Number of processors: %d\n', s.get_num_processors)
f.write(' + Endianness: %s\n' % (s.get_endianness())) write_value(f, ' + Endianness: %s\n', s.get_endianness)
f.write('\nPlatform\n'); f.write('\nPlatform\n');
f.write(' + Operating system: %s\n' % (s.get_platform_name())) write_value(f, ' + Operating system: %s\n', s.get_platform_name)
f.write(' + Distribution: %s\n' % (s.get_platform_distro())) write_value(f, ' + Distribution: %s\n', s.get_platform_distro)
f.write(' + Kernel version: %s\n' % (s.get_platform_version())) write_value(f, ' + Kernel version: %s\n', s.get_platform_version)
f.write(' + SMP kernel: ') if s.get_platform_is_smp() is not None:
if s.get_platform_is_smp(): f.write(' + SMP kernel: ')
f.write('yes') if s.get_platform_is_smp():
else: f.write('yes')
f.write('no') else:
f.write('\n') f.write('no')
f.write('\n')
f.write(' + Machine name: %s\n' % (s.get_platform_machine())) write_value(f, ' + Machine name: %s\n', s.get_platform_machine)
f.write(' + Hostname: %s\n' % (s.get_platform_hostname())) write_value(f, ' + Hostname: %s\n', s.get_platform_hostname)
f.write(' + Uptime: %d seconds\n' % (s.get_uptime())) write_value(f, ' + Uptime: %d seconds\n', s.get_uptime)
l = s.get_loadavg() write_value(f, ' + Loadavg: %f %f %f\n', s.get_loadavg)
f.write(' + Loadavg: %f %f %f\n' % (l[0], l[1], l[2]))
f.write('\nMemory\n'); f.write('\nMemory\n');
f.write(' + Total: %d bytes\n' % (s.get_mem_total())) write_value(f, ' + Total: %d bytes\n', s.get_mem_total)
f.write(' + Free: %d bytes\n' % (s.get_mem_free())) write_value(f, ' + Free: %d bytes\n', s.get_mem_free)
f.write(' + Cached: %d bytes\n' % (s.get_mem_cached())) write_value(f, ' + Cached: %d bytes\n', s.get_mem_cached)
f.write(' + Buffers: %d bytes\n' % (s.get_mem_buffers())) write_value(f, ' + Buffers: %d bytes\n', s.get_mem_buffers)
f.write(' + Swap total: %d bytes\n' % (s.get_mem_swap_total())) write_value(f, ' + Swap total: %d bytes\n', s.get_mem_swap_total)
f.write(' + Swap free: %d bytes\n' % (s.get_mem_swap_free())) write_value(f, ' + Swap free: %d bytes\n', s.get_mem_swap_free)
f.write('\n\nNetwork\n'); f.write('\n\nNetwork\n');
f.write('-------\n\n'); f.write('-------\n\n');
...@@ -97,19 +106,19 @@ def main(): ...@@ -97,19 +106,19 @@ def main():
f.write('Interfaces\n') f.write('Interfaces\n')
f.write('~~~~~~~~~~\n\n') f.write('~~~~~~~~~~\n\n')
f.write(s.get_net_interfaces()) write_value(f, '%s', s.get_net_interfaces)
f.write('\nRouting table\n') f.write('\nRouting table\n')
f.write('~~~~~~~~~~~~~\n\n') f.write('~~~~~~~~~~~~~\n\n')
f.write(s.get_net_routing_table()) write_value(f, '%s', s.get_net_routing_table)
f.write('\nStatistics\n') f.write('\nStatistics\n')
f.write('~~~~~~~~~~\n\n') f.write('~~~~~~~~~~\n\n')
f.write(s.get_net_stats()) write_value(f, '%s', s.get_net_stats)
f.write('\nConnections\n') f.write('\nConnections\n')
f.write('~~~~~~~~~~~\n\n') f.write('~~~~~~~~~~~\n\n')
f.write(s.get_net_connections()) write_value(f, '%s', s.get_net_connections)
try: try:
if os.getuid() != 0: if os.getuid() != 0:
......
...@@ -25,27 +25,31 @@ import time ...@@ -25,27 +25,31 @@ import time
class SysInfo: class SysInfo:
def __init__(self): def __init__(self):
self._num_processors = -1 self._num_processors = None
self._endianness = 'Unknown' self._endianness = 'Unknown'
self._hostname = '' self._hostname = ''
self._platform_name = 'Unknown' self._platform_name = 'Unknown'
self._platform_version = 'Unknown' self._platform_version = 'Unknown'
self._platform_machine = 'Unknown' self._platform_machine = 'Unknown'
self._platform_is_smp = False self._platform_is_smp = None
self._uptime = -1 self._uptime = None
self._loadavg = [-1.0, -1.0, -1.0] self._loadavg = None
self._mem_total = -1 self._mem_total = None
self._mem_free = -1 self._mem_free = None
self._mem_cached = -1 self._mem_swap_total = None
self._mem_buffers = -1 self._mem_swap_free = None
self._mem_swap_total = -1
self._mem_swap_free = -1
self._platform_distro = 'Unknown'
self._net_interfaces = 'Unknown\n' self._net_interfaces = 'Unknown\n'
self._net_routing_table = 'Unknown\n' self._net_routing_table = 'Unknown\n'
self._net_stats = 'Unknown\n' self._net_stats = 'Unknown\n'
self._net_connections = 'Unknown\n' self._net_connections = 'Unknown\n'
# The following are Linux speicific, and should eventually be removed
# from this level; for now we simply default to None (so they won't
# be printed)
self._platform_distro = None
self._mem_cached = None
self._mem_buffers = None
def get_num_processors(self): def get_num_processors(self):
"""Returns the number of processors. This is the number of """Returns the number of processors. This is the number of
hyperthreads when hyper-threading is enabled. hyperthreads when hyper-threading is enabled.
...@@ -77,7 +81,12 @@ class SysInfo: ...@@ -77,7 +81,12 @@ class SysInfo:
return self._platform_is_smp return self._platform_is_smp
def get_platform_distro(self): def get_platform_distro(self):
"""Returns the name of the OS distribution in use.""" """Returns the name of the OS distribution in use.
Note: the concept of 'distribution' is Linux specific. This shouldn't
be at this level.
"""
return self._platform_distro return self._platform_distro
def get_uptime(self): def get_uptime(self):
...@@ -164,7 +173,7 @@ class SysInfoLinux(SysInfoPOSIX): ...@@ -164,7 +173,7 @@ class SysInfoLinux(SysInfoPOSIX):
with open('/proc/loadavg') as f: with open('/proc/loadavg') as f:
l = f.read().strip().split(' ') l = f.read().strip().split(' ')
if len(l) >= 3: if len(l) >= 3:
self._loadavg = [float(l[0]), float(l[1]), float(l[2])] self._loadavg = (float(l[0]), float(l[1]), float(l[2]))
with open('/proc/meminfo') as f: with open('/proc/meminfo') as f:
m = f.readlines() m = f.readlines()
...@@ -276,8 +285,6 @@ class SysInfoBSD(SysInfoPOSIX): ...@@ -276,8 +285,6 @@ class SysInfoBSD(SysInfoPOSIX):
except (subprocess.CalledProcessError, OSError): except (subprocess.CalledProcessError, OSError):
pass pass
self._platform_distro = self._platform_name + ' ' + self._platform_version
try: try:
s = subprocess.check_output(['ifconfig']) s = subprocess.check_output(['ifconfig'])
self._net_interfaces = s.decode('utf-8') self._net_interfaces = s.decode('utf-8')
...@@ -296,6 +303,12 @@ class SysInfoBSD(SysInfoPOSIX): ...@@ -296,6 +303,12 @@ class SysInfoBSD(SysInfoPOSIX):
except (subprocess.CalledProcessError, OSError): except (subprocess.CalledProcessError, OSError):
self._net_connections = 'Warning: "netstat -an" command failed.\n' self._net_connections = 'Warning: "netstat -an" command failed.\n'
try:
s = subprocess.check_output(['netstat', '-nr'])
self._net_routing_table = s.decode('utf-8')
except (subprocess.CalledProcessError, OSError):
self._net_connections = 'Warning: "netstat -nr" command failed.\n'
class SysInfoOpenBSD(SysInfoBSD): class SysInfoOpenBSD(SysInfoBSD):
"""OpenBSD implementation of the SysInfo class. """OpenBSD implementation of the SysInfo class.
See the SysInfo class documentation for more information. See the SysInfo class documentation for more information.
...@@ -303,11 +316,6 @@ class SysInfoOpenBSD(SysInfoBSD): ...@@ -303,11 +316,6 @@ class SysInfoOpenBSD(SysInfoBSD):
def __init__(self): def __init__(self):
super().__init__() super().__init__()
# Don't know how to gather these
self._platform_is_smp = False
self._mem_cached = -1
self._mem_buffers = -1
try: try:
s = subprocess.check_output(['sysctl', '-n', 'kern.boottime']) s = subprocess.check_output(['sysctl', '-n', 'kern.boottime'])
t = s.decode('utf-8').strip() t = s.decode('utf-8').strip()
...@@ -320,7 +328,7 @@ class SysInfoOpenBSD(SysInfoBSD): ...@@ -320,7 +328,7 @@ class SysInfoOpenBSD(SysInfoBSD):
s = subprocess.check_output(['sysctl', '-n', 'vm.loadavg']) s = subprocess.check_output(['sysctl', '-n', 'vm.loadavg'])
l = s.decode('utf-8').strip().split(' ') l = s.decode('utf-8').strip().split(' ')
if len(l) >= 3: if len(l) >= 3:
self._loadavg = [float(l[0]), float(l[1]), float(l[2])] self._loadavg = (float(l[0]), float(l[1]), float(l[2]))
except (subprocess.CalledProcessError, OSError): except (subprocess.CalledProcessError, OSError):
pass pass
...@@ -343,29 +351,13 @@ class SysInfoOpenBSD(SysInfoBSD): ...@@ -343,29 +351,13 @@ class SysInfoOpenBSD(SysInfoBSD):
except (subprocess.CalledProcessError, OSError): except (subprocess.CalledProcessError, OSError):
pass pass
try: class SysInfoFreeBSDOSX(SysInfoBSD):
s = subprocess.check_output(['route', '-n', 'show']) """Shared code for the FreeBSD and OS X implementations of the SysInfo
self._net_routing_table = s.decode('utf-8') class. See the SysInfo class documentation for more information.
except (subprocess.CalledProcessError, OSError):
self._net_routing_table = 'Warning: "route -n show" command failed.\n'
class SysInfoFreeBSD(SysInfoBSD):
"""FreeBSD implementation of the SysInfo class.
See the SysInfo class documentation for more information.
""" """
def __init__(self): def __init__(self):
super().__init__() super().__init__()
# Don't know how to gather these
self._mem_cached = -1
self._mem_buffers = -1
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):
pass
try: try:
s = subprocess.check_output(['sysctl', '-n', 'kern.boottime']) s = subprocess.check_output(['sysctl', '-n', 'kern.boottime'])
t = s.decode('utf-8').strip() t = s.decode('utf-8').strip()
...@@ -385,7 +377,20 @@ class SysInfoFreeBSD(SysInfoBSD): ...@@ -385,7 +377,20 @@ class SysInfoFreeBSD(SysInfoBSD):
else: else:
la = l.split(' ') la = l.split(' ')
if len(la) >= 3: if len(la) >= 3:
self._loadavg = [float(la[0]), float(la[1]), float(la[2])] self._loadavg = (float(la[0]), float(la[1]), float(la[2]))
except (subprocess.CalledProcessError, OSError):
pass
class SysInfoFreeBSD(SysInfoFreeBSDOSX):
"""FreeBSD implementation of the SysInfo class.
See the SysInfo class documentation for more information.
"""
def __init__(self):
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): except (subprocess.CalledProcessError, OSError):
pass pass
...@@ -408,11 +413,57 @@ class SysInfoFreeBSD(SysInfoBSD): ...@@ -408,11 +413,57 @@ class SysInfoFreeBSD(SysInfoBSD):
except (subprocess.CalledProcessError, OSError): except (subprocess.CalledProcessError, OSError):
pass pass
class SysInfoOSX(SysInfoFreeBSDOSX):
"""OS X (Darwin) implementation of the SysInfo class.
See the SysInfo class documentation for more information.
"""
def __init__(self):
super().__init__()
# note; this call overrides the value already set when hw.physmem
# was read. However, on OSX, physmem is not necessarily the correct
# value. But since it does not fail and does work on most BSD's, it's
# left in the base class and overwritten here
self._mem_total = None
try: try:
s = subprocess.check_output(['netstat', '-nr']) s = subprocess.check_output(['sysctl', '-n', 'hw.memsize'])
self._net_routing_table = s.decode('utf-8') self._mem_total = int(s.decode('utf-8').strip())
except (subprocess.CalledProcessError, OSError): except (subprocess.CalledProcessError, OSError):
self._net_connections = 'Warning: "netstat -nr" command failed.\n' pass
try:
s = subprocess.check_output(['vm_stat'])
lines = s.decode('utf-8').split('\n')
# store all values in a dict
values = {}
page_size = None
page_size_re = re.compile('.*page size of ([0-9]+) bytes')
for line in lines:
page_size_m = page_size_re.match(line)
if page_size_m:
page_size = int(page_size_m.group(1))
else:
key, _, value = line.partition(':')
values[key] = value.strip()[:-1]
# Only calculate memory if page size is known
if page_size is not None:
self._mem_free = int(values['Pages free']) * page_size +\
int(values['Pages speculative']) * page_size
except (subprocess.CalledProcessError, OSError):
pass
try:
s = subprocess.check_output(['sysctl', '-n', 'vm.swapusage'])
l = s.decode('utf-8').strip()
r = re.match('^total = (\d+\.\d+)M\s+used = (\d+\.\d+)M\s+free = (\d+\.\d+)M', l)
if r:
self._mem_swap_total = float(r.group(1).strip()) * 1024
self._mem_swap_free = float(r.group(3).strip()) * 1024
except (subprocess.CalledProcessError, OSError):
pass
class SysInfoTestcase(SysInfo): class SysInfoTestcase(SysInfo):
def __init__(self): def __init__(self):
...@@ -429,6 +480,8 @@ def SysInfoFromFactory(): ...@@ -429,6 +480,8 @@ def SysInfoFromFactory():
return SysInfoOpenBSD() return SysInfoOpenBSD()
elif osname == 'FreeBSD': elif osname == 'FreeBSD':
return SysInfoFreeBSD() return SysInfoFreeBSD()
elif osname == 'Darwin':
return SysInfoOSX()
elif osname == 'BIND10Testcase': elif osname == 'BIND10Testcase':
return SysInfoTestcase() return SysInfoTestcase()
else: else:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment