Facter.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. #!/usr/bin/env python2.6
  2. '''
  3. Licensed to the Apache Software Foundation (ASF) under one
  4. or more contributor license agreements. See the NOTICE file
  5. distributed with this work for additional information
  6. regarding copyright ownership. The ASF licenses this file
  7. to you under the Apache License, Version 2.0 (the
  8. "License"); you may not use this file except in compliance
  9. with the License. You may obtain a copy of the License at
  10. http://www.apache.org/licenses/LICENSE-2.0
  11. Unless required by applicable law or agreed to in writing, software
  12. distributed under the License is distributed on an "AS IS" BASIS,
  13. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. See the License for the specific language governing permissions and
  15. limitations under the License.
  16. '''
  17. import logging
  18. import os
  19. import getpass
  20. import platform
  21. import re
  22. import shlex
  23. import socket
  24. import multiprocessing
  25. import subprocess
  26. import time
  27. import uuid
  28. import hostname
  29. log = logging.getLogger()
  30. # selinux command
  31. GET_SE_LINUX_ST_CMD = "/usr/sbin/sestatus"
  32. GET_IFCONFIG_CMD = "ifconfig"
  33. GET_UPTIME_CMD = "cat /proc/uptime"
  34. GET_MEMINFO_CMD = "cat /proc/meminfo"
  35. class Facter():
  36. def __init__(self):
  37. self.DATA_IFCONFIG_OUTPUT = Facter.setDataIfConfigOutput()
  38. self.DATA_UPTIME_OUTPUT = Facter.setDataUpTimeOutput()
  39. self.DATA_MEMINFO_OUTPUT = Facter.setMemInfoOutput()
  40. @staticmethod
  41. def setDataIfConfigOutput():
  42. try:
  43. result = os.popen(GET_IFCONFIG_CMD).read()
  44. return result
  45. except OSError:
  46. log.warn("Can't execute {0}".format(GET_IFCONFIG_CMD))
  47. return ""
  48. @staticmethod
  49. def setDataUpTimeOutput():
  50. try:
  51. result = os.popen(GET_UPTIME_CMD).read()
  52. return result
  53. except OSError:
  54. log.warn("Can't execute {0}".format(GET_UPTIME_CMD))
  55. return ""
  56. @staticmethod
  57. def setMemInfoOutput():
  58. try:
  59. result = os.popen(GET_MEMINFO_CMD).read()
  60. return result
  61. except OSError:
  62. log.warn("Can't execute {0}".format(GET_MEMINFO_CMD))
  63. return ""
  64. # Returns the currently running user id
  65. def getId(self):
  66. return getpass.getuser()
  67. # Returns the OS name
  68. def getKernel(self):
  69. return platform.system()
  70. # Returns the FQDN of the host
  71. def getFqdn(self):
  72. return socket.getfqdn()
  73. # Returns the host's primary DNS domain name
  74. def getDomain(self):
  75. fqdn = self.getFqdn()
  76. hostname = self.getHostname()
  77. domain = fqdn.replace(hostname, "", 1)
  78. domain = domain.replace(".", "", 1)
  79. return domain
  80. # Returns the short hostname
  81. def getHostname(self):
  82. return hostname.hostname()
  83. # Returns the CPU hardware architecture
  84. def getArchitecture(self):
  85. result = platform.processor()
  86. if result == '':
  87. return 'OS NOT SUPPORTED'
  88. else:
  89. return result
  90. # Returns the name of the OS
  91. def getOperatingSystem(self):
  92. dist = platform.linux_distribution()
  93. operatingSystem = dist[0].lower()
  94. if os.path.exists('/etc/oracle-release'):
  95. return 'OracleLinux'
  96. elif operatingSystem.startswith('suse linux enterprise server'):
  97. return 'SLES'
  98. elif operatingSystem.startswith('red hat enterprise linux server'):
  99. return 'RedHat'
  100. elif operatingSystem != '':
  101. return operatingSystem
  102. else:
  103. return 'OS NOT SUPPORTED'
  104. # Returns the OS version
  105. def getOperatingSystemRelease(self):
  106. dist = platform.linux_distribution()
  107. if dist[1] != '':
  108. return dist[1]
  109. else:
  110. return 'OS NOT SUPPORTED'
  111. # Returns the OS TimeZone
  112. def getTimeZone(self):
  113. return time.tzname[time.daylight - 1]
  114. # Returns the CPU count
  115. def getProcessorcount(self):
  116. return multiprocessing.cpu_count()
  117. # Returns the Kernel release
  118. def getKernelRelease(self):
  119. return platform.release()
  120. # Returns the Kernel release version
  121. def getKernelVersion(self):
  122. kernel_release = platform.release()
  123. return kernel_release.split('-', 1)[0]
  124. # Returns the major kernel release version
  125. def getKernelMajVersion(self):
  126. return '.'.join(self.getKernelVersion().split('.', 2)[0:2])
  127. def getMacAddress(self):
  128. mac = uuid.getnode()
  129. if uuid.getnode() == mac:
  130. mac = ':'.join('%02X' % ((mac >> 8 * i) & 0xff) for i in reversed(xrange(6)))
  131. else:
  132. mac = 'UNKNOWN'
  133. return mac
  134. # Returns the operating system family
  135. def getOsFamily(self):
  136. os_family = self.getOperatingSystem().lower()
  137. if os_family in ['redhat', 'fedora', 'centos', 'oraclelinux', 'ascendos',
  138. 'amazon', 'xenserver', 'oel', 'ovs', 'cloudlinux',
  139. 'slc', 'scientific', 'psbm']:
  140. os_family = 'RedHat'
  141. elif os_family in ['ubuntu', 'debian']:
  142. os_family = 'Debian'
  143. elif os_family in ['sles', 'sled', 'opensuse', 'suse']:
  144. os_family = 'Suse'
  145. elif os_family == '':
  146. os_family = 'OS NOT SUPPORTED'
  147. else:
  148. os_family = self.getOperatingSystem()
  149. return os_family
  150. def isSeLinux(self):
  151. try:
  152. retcode, out, err = run_os_command(GET_SE_LINUX_ST_CMD)
  153. se_status = re.search('(enforcing|permissive|enabled)', out)
  154. if se_status:
  155. return True
  156. except OSError:
  157. log.warn("Could not run {0}: OK".format(GET_SE_LINUX_ST_CMD))
  158. return False
  159. # Function that returns list of values that matches
  160. # Return empty str if no matches
  161. def data_return_list(self, patern, data):
  162. full_list = re.findall(patern, data)
  163. result = ""
  164. for i in full_list:
  165. result = result + i + ","
  166. result = re.sub(r',$', "", result)
  167. return result
  168. def data_return_first(self, patern, data):
  169. full_list = re.findall(patern, data)
  170. result = ""
  171. if full_list:
  172. result = full_list[0]
  173. return result
  174. #Convert kB to GB
  175. def convertSizeKbToGb(self, size):
  176. return "%0.2f GB" % round(float(size) / (1024.0 * 1024.0), 2)
  177. # Return first ip adress
  178. def getIpAddress(self):
  179. result = self.data_return_first("(?: inet addr:)(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})",
  180. self.DATA_IFCONFIG_OUTPUT)
  181. if result == '':
  182. log.warn("Can't get an ip address from {0}".format(self.DATA_IFCONFIG_OUTPUT))
  183. return 'OS NOT SUPPORTED'
  184. else:
  185. return result
  186. # Return netmask
  187. def getNetmask(self):
  188. result = self.data_return_first("(?: Mask:)(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})",
  189. self.DATA_IFCONFIG_OUTPUT)
  190. if result == '':
  191. log.warn("Can't get a netmask from {0}".format(self.DATA_IFCONFIG_OUTPUT))
  192. return 'OS NOT SUPPORTED'
  193. else:
  194. return result
  195. # Return interfaces
  196. def getInterfaces(self):
  197. result = self.data_return_list("(\w+)(?:.*Link encap:)", self.DATA_IFCONFIG_OUTPUT)
  198. if result == '':
  199. log.warn("Can't get a network interfaces list from {0}".format(self.DATA_IFCONFIG_OUTPUT))
  200. return 'OS NOT SUPPORTED'
  201. else:
  202. return result
  203. # Return uptime seconds
  204. def getUptimeSeconds(self):
  205. try:
  206. return int(self.data_return_first("\d+", self.DATA_UPTIME_OUTPUT))
  207. except ValueError:
  208. log.warn("Can't get an uptime value from {0}".format(self.DATA_UPTIME_OUTPUT))
  209. return 0
  210. # Return uptime hours
  211. def getUptimeHours(self):
  212. return self.getUptimeSeconds() / (60 * 60)
  213. # Return uptime days
  214. def getUptimeDays(self):
  215. return self.getUptimeSeconds() / (60 * 60 * 24)
  216. # Return memoryfree
  217. def getMemoryFree(self):
  218. #:memoryfree_mb => "MemFree",
  219. try:
  220. return int(self.data_return_first("MemFree:.*?(\d+) .*", self.DATA_MEMINFO_OUTPUT))
  221. except ValueError:
  222. log.warn("Can't get free memory size from {0}".format(self.DATA_MEMINFO_OUTPUT))
  223. return 0
  224. # Return memorytotal
  225. def getMemoryTotal(self):
  226. try:
  227. return int(self.data_return_first("MemTotal:.*?(\d+) .*", self.DATA_MEMINFO_OUTPUT))
  228. except ValueError:
  229. log.warn("Can't get total memory size from {0}".format(self.DATA_MEMINFO_OUTPUT))
  230. return 0
  231. # Return swapfree
  232. def getSwapFree(self):
  233. #:swapfree_mb => "SwapFree"
  234. try:
  235. return int(self.data_return_first("SwapFree:.*?(\d+) .*", self.DATA_MEMINFO_OUTPUT))
  236. except ValueError:
  237. log.warn("Can't get free swap memory size from {0}".format(self.DATA_MEMINFO_OUTPUT))
  238. return 0
  239. # Return swapsize
  240. def getSwapSize(self):
  241. #:swapsize_mb => "SwapTotal",
  242. try:
  243. return int(self.data_return_first("SwapTotal:.*?(\d+) .*", self.DATA_MEMINFO_OUTPUT))
  244. except ValueError:
  245. log.warn("Can't get total swap memory size from {0}".format(self.DATA_MEMINFO_OUTPUT))
  246. return 0
  247. # Return memorysize
  248. def getMemorySize(self):
  249. #:memorysize_mb => "MemTotal"
  250. try:
  251. return int(self.data_return_first("MemTotal:.*?(\d+) .*", self.DATA_MEMINFO_OUTPUT))
  252. except ValueError:
  253. log.warn("Can't get memory size from {0}".format(self.DATA_MEMINFO_OUTPUT))
  254. return 0
  255. def facterInfo(self):
  256. facterInfo = {}
  257. facterInfo['id'] = self.getId()
  258. facterInfo['kernel'] = self.getKernel()
  259. facterInfo['domain'] = self.getDomain()
  260. facterInfo['fqdn'] = self.getFqdn()
  261. facterInfo['hostname'] = self.getHostname()
  262. facterInfo['macaddress'] = self.getMacAddress()
  263. facterInfo['architecture'] = self.getArchitecture()
  264. facterInfo['operatingsystem'] = self.getOperatingSystem()
  265. facterInfo['operatingsystemrelease'] = self.getOperatingSystemRelease()
  266. facterInfo['physicalprocessorcount'] = self.getProcessorcount()
  267. facterInfo['processorcount'] = self.getProcessorcount()
  268. facterInfo['timezone'] = self.getTimeZone()
  269. facterInfo['hardwareisa'] = self.getArchitecture()
  270. facterInfo['hardwaremodel'] = self.getArchitecture()
  271. facterInfo['kernelrelease'] = self.getKernelRelease()
  272. facterInfo['kernelversion'] = self.getKernelVersion()
  273. facterInfo['osfamily'] = self.getOsFamily()
  274. facterInfo['selinux'] = self.isSeLinux()
  275. facterInfo['kernelmajversion'] = self.getKernelMajVersion()
  276. facterInfo['ipaddress'] = self.getIpAddress()
  277. facterInfo['netmask'] = self.getNetmask()
  278. facterInfo['interfaces'] = self.getInterfaces()
  279. facterInfo['uptime_seconds'] = str(self.getUptimeSeconds())
  280. facterInfo['uptime_hours'] = str(self.getUptimeHours())
  281. facterInfo['uptime_days'] = str(self.getUptimeDays())
  282. facterInfo['memorysize'] = self.getMemorySize()
  283. facterInfo['memoryfree'] = self.getMemoryFree()
  284. facterInfo['swapsize'] = self.convertSizeKbToGb(self.getSwapSize())
  285. facterInfo['swapfree'] = self.convertSizeKbToGb(self.getSwapFree())
  286. facterInfo['memorytotal'] = self.getMemoryTotal()
  287. return facterInfo
  288. def run_os_command(cmd):
  289. if type(cmd) == str:
  290. cmd = shlex.split(cmd)
  291. process = subprocess.Popen(cmd,
  292. stdout=subprocess.PIPE,
  293. stdin=subprocess.PIPE,
  294. stderr=subprocess.PIPE
  295. )
  296. (stdoutdata, stderrdata) = process.communicate()
  297. return process.returncode, stdoutdata, stderrdata
  298. def main(argv=None):
  299. print Facter().facterInfo()
  300. if __name__ == '__main__':
  301. main()