sysinfo.py 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. # Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
  2. #
  3. # Permission to use, copy, modify, and distribute this software for any
  4. # purpose with or without fee is hereby granted, provided that the above
  5. # copyright notice and this permission notice appear in all copies.
  6. #
  7. # THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SYSTEMS CONSORTIUM
  8. # DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
  9. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
  10. # INTERNET SYSTEMS CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
  11. # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
  12. # FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
  13. # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
  14. # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. '''This module returns system information.'''
  16. import os
  17. import sys
  18. import re
  19. import subprocess
  20. import os.path
  21. import platform
  22. class SysInfo:
  23. def __init__(self):
  24. self._num_processors = -1
  25. self._endianness = 'Unknown'
  26. self._hostname = ''
  27. self._platform_name = 'Unknown'
  28. self._platform_version = 'Unknown'
  29. self._platform_machine = 'Unknown'
  30. self._platform_is_smp = False
  31. self._uptime = -1
  32. self._loadavg = [-1.0, -1.0, -1.0]
  33. self._mem_total = -1
  34. self._mem_free = -1
  35. self._mem_cached = -1
  36. self._mem_buffers = -1
  37. self._mem_swap_total = -1
  38. self._mem_swap_free = -1
  39. self._platform_distro = 'Unknown'
  40. self._net_interfaces = 'Unknown'
  41. self._net_routing_table = 'Unknown'
  42. self._net_stats = 'Unknown'
  43. self._net_connections = 'Unknown'
  44. def get_num_processors(self):
  45. """Returns the number of processors. This is the number of
  46. hyperthreads when hyper-threading is enabled.
  47. """
  48. return self._num_processors
  49. def get_endianness(self):
  50. """Returns 'big' or 'little'."""
  51. return self._endianness
  52. def get_platform_hostname(self):
  53. """Returns the hostname of the system."""
  54. return self._hostname
  55. def get_platform_name(self):
  56. """Returns the platform name (uname -s)."""
  57. return self._platform_name
  58. def get_platform_version(self):
  59. """Returns the platform version (uname -v)."""
  60. return self._platform_version
  61. def get_platform_machine(self):
  62. """Returns the platform machine architecture."""
  63. return self._platform_machine
  64. def get_platform_is_smp(self):
  65. """Returns True if an SMP kernel is being used, False otherwise."""
  66. return self._platform_is_smp
  67. def get_platform_distro(self):
  68. """Returns the name of the OS distribution in use."""
  69. return self._platform_distro
  70. def get_uptime(self):
  71. """Returns the uptime in seconds."""
  72. return self._uptime
  73. def get_loadavg(self):
  74. """Returns the load average as 3 floating point values in an array."""
  75. return self._loadavg
  76. def get_mem_total(self):
  77. """Returns the total amount of memory in bytes."""
  78. return self._mem_total
  79. def get_mem_free(self):
  80. """Returns the amount of free memory in bytes."""
  81. return self._mem_free
  82. def get_mem_cached(self):
  83. """Returns the amount of cached memory in bytes."""
  84. return self._mem_cached
  85. def get_mem_buffers(self):
  86. """Returns the amount of buffer in bytes."""
  87. return self._mem_buffers
  88. def get_mem_swap_total(self):
  89. """Returns the total amount of swap in bytes."""
  90. return self._mem_swap_total
  91. def get_mem_swap_free(self):
  92. """Returns the amount of free swap in bytes."""
  93. return self._mem_swap_free
  94. def get_net_interfaces(self):
  95. """Returns information about network interfaces (as a multi-line string)."""
  96. return self._net_interfaces
  97. def get_net_routing_table(self):
  98. """Returns information about network routing table (as a multi-line string)."""
  99. return self._net_routing_table
  100. def get_net_stats(self):
  101. """Returns network statistics (as a multi-line string)."""
  102. return self._net_stats
  103. def get_net_connections(self):
  104. """Returns network connection information (as a multi-line string)."""
  105. return self._net_connections
  106. class SysInfoLinux(SysInfo):
  107. """Linux implementation of the SysInfo class.
  108. See the base class documentation for more information.
  109. """
  110. def __init__(self):
  111. self._num_processors = os.sysconf('SC_NPROCESSORS_CONF')
  112. self._endianness = sys.byteorder
  113. with open('/proc/sys/kernel/hostname') as f:
  114. self._hostname = f.read().strip()
  115. u = os.uname()
  116. self._platform_name = u[0]
  117. self._platform_version = u[2]
  118. self._platform_machine = u[4]
  119. with open('/proc/version') as f:
  120. self._platform_is_smp = ' SMP ' in f.read().strip()
  121. with open('/proc/uptime') as f:
  122. u = f.read().strip().split(' ')
  123. self._uptime = int(round(float(u[0])))
  124. with open('/proc/loadavg') as f:
  125. l = f.read().strip().split(' ')
  126. self._loadavg = [float(l[0]), float(l[1]), float(l[2])]
  127. with open('/proc/meminfo') as f:
  128. m = f.readlines()
  129. for line in m:
  130. r = re.match('^MemTotal:\s+(.*)\s*kB', line)
  131. if r:
  132. self._mem_total = int(r.group(1).strip()) * 1024
  133. continue
  134. r = re.match('^MemFree:\s+(.*)\s*kB', line)
  135. if r:
  136. self._mem_free = int(r.group(1).strip()) * 1024
  137. continue
  138. r = re.match('^Cached:\s+(.*)\s*kB', line)
  139. if r:
  140. self._mem_cached = int(r.group(1).strip()) * 1024
  141. continue
  142. r = re.match('^Buffers:\s+(.*)\s*kB', line)
  143. if r:
  144. self._mem_buffers = int(r.group(1).strip()) * 1024
  145. continue
  146. r = re.match('^SwapTotal:\s+(.*)\s*kB', line)
  147. if r:
  148. self._mem_swap_total = int(r.group(1).strip()) * 1024
  149. continue
  150. r = re.match('^SwapFree:\s+(.*)\s*kB', line)
  151. if r:
  152. self._mem_swap_free = int(r.group(1).strip()) * 1024
  153. continue
  154. self._platform_distro = None
  155. try:
  156. s = subprocess.check_output(['lsb_release', '-a'])
  157. for line in s.decode('utf-8').split('\n'):
  158. r = re.match('^Description:(.*)', line)
  159. if r:
  160. self._platform_distro = r.group(1).strip()
  161. break
  162. except (subprocess.CalledProcessError, OSError):
  163. pass
  164. if self._platform_distro is None:
  165. files = ['/etc/debian_release',
  166. '/etc/debian_version',
  167. '/etc/SuSE-release',
  168. '/etc/UnitedLinux-release',
  169. '/etc/mandrake-release',
  170. '/etc/gentoo-release',
  171. '/etc/fedora-release',
  172. '/etc/redhat-release',
  173. '/etc/redhat_version',
  174. '/etc/slackware-release',
  175. '/etc/slackware-version',
  176. '/etc/arch-release',
  177. '/etc/lsb-release',
  178. '/etc/mageia-release']
  179. for fn in files:
  180. if os.path.exists(fn):
  181. with open(fn) as f:
  182. self._platform_distro = f.read().strip()
  183. break
  184. if self._platform_distro is None:
  185. self._platform_distro = 'Unknown'
  186. self._net_interfaces = None
  187. try:
  188. s = subprocess.check_output(['ip', 'addr'])
  189. self._net_interfaces = s.decode('utf-8')
  190. except (subprocess.CalledProcessError, OSError):
  191. pass
  192. if self._net_interfaces is None:
  193. self._net_interfaces = 'Unknown'
  194. self._net_routing_table = None
  195. try:
  196. s = subprocess.check_output(['ip', 'route'])
  197. self._net_routing_table = s.decode('utf-8')
  198. self._net_routing_table += '\n'
  199. s = subprocess.check_output(['ip', '-f', 'inet6', 'route'])
  200. self._net_routing_table += s.decode('utf-8')
  201. except (subprocess.CalledProcessError, OSError):
  202. pass
  203. if self._net_routing_table is None:
  204. self._net_routing_table = 'Unknown'
  205. self._net_stats = None
  206. try:
  207. s = subprocess.check_output(['netstat', '-s'])
  208. self._net_stats = s.decode('utf-8')
  209. except (subprocess.CalledProcessError, OSError):
  210. pass
  211. if self._net_stats is None:
  212. self._net_stats = 'Unknown'
  213. self._net_connections = None
  214. try:
  215. s = subprocess.check_output(['netstat', '-apn'])
  216. self._net_connections = s.decode('utf-8')
  217. except (subprocess.CalledProcessError, OSError):
  218. pass
  219. if self._net_connections is None:
  220. self._net_connections = 'Unknown'
  221. def SysInfoFromFactory():
  222. osname = platform.system()
  223. if osname == 'Linux':
  224. return SysInfoLinux()
  225. else:
  226. return SysInfo()