monitor.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. """
  2. This program is designed to inspect an application environment
  3. This program should only be run on unix friendly systems
  4. """
  5. from __future__ import division
  6. import os
  7. import subprocess
  8. from sets import Set
  9. class Analysis:
  10. def __init__(self):
  11. self.logs = []
  12. pass
  13. def post(self,object):
  14. self.logs.append(object)
  15. """
  16. This class is designed to analyze environment variables. Environment variables can either be folders, files or simple values
  17. The class returns a quantifiable assessment of the environment variables (expected 100%)
  18. """
  19. class Env(Analysis):
  20. def __init__(self,values):
  21. Analysis.__init__(self)
  22. self.values = values
  23. """
  24. This function evaluate the validity of an environment variable by returning a 1 or 0 (computable)
  25. The function will use propositional logic (https://en.wikipedia.org/wiki/Propositional_calculus)
  26. """
  27. def evaluate(self,id):
  28. if id in os.environ :
  29. #
  30. # We can inspect to make sure the environment variable is not a path or filename.
  31. # Using propositional logic we proceed as follows:
  32. # - (p) We determine if the value is an folder or file name (using regex)
  33. # - (q) In case of a file or folder we check for existance
  34. # The final result is a conjuction of p and q
  35. #
  36. value = os.environ[id]
  37. expressions = [os.sep,'(\\.\w+)$']
  38. p = sum([ re.search(xchar,value) is not None for xchar in expressions])
  39. q = os.path.exists(value)
  40. return int(p and q)
  41. else:
  42. return 0
  43. def composite (self):
  44. r = [ self.evaluate(id) for id in values] ;
  45. N = len(r)
  46. n = sum(r)
  47. return n/N
  48. class Sandbox(Analysis):
  49. def __init__(self,conf):
  50. Analysis.__init__(self)
  51. self.sandbox_path = conf['path']
  52. self.requirements_path = conf['requirements']
  53. def get_requirements (self):
  54. f = open(self.requirements_path)
  55. return [ name.replace('-',' ').replace('_',' ') for name in f.read().split('\n') name != '']
  56. """
  57. This function will return the modules installed in the sandbox (virtual environment)
  58. """
  59. def get_sandbox_requirements(self):
  60. cmd = ['freeze']
  61. xchar = ''.join([os.sep]*2)
  62. pip_vm = ''.join([self.sandbox_path,os.sep,'bin',os.sep,'pip']).replace(xchar,os.sep)
  63. cmd = [pip_vm]+cmd
  64. r = subprocess.check_output(cmd).split('\n')
  65. return [row.replace('-',' ').replace('_',' ') for row in r if row.strip() != '']
  66. def evaluate(self):
  67. pass
  68. """
  69. This function returns the ratio of existing modules relative to the ones expected
  70. """
  71. def composite(self):
  72. required_modules= self.get_requirements()
  73. sandbox_modules = self.get_sandbox_requirements()
  74. N = len(requirements)
  75. n = len(Set(required_modules) - Set(sandbox_modules))
  76. return n/N
  77. """
  78. This class performs the analysis of a list of processes and determines
  79. The class provides a quantifiable measure of how many processes it found over all
  80. """
  81. class Processes(Analysis):
  82. def __init__(self,names):
  83. Analysis.__init__(self)
  84. self.names = names
  85. def evaluate(self,name):
  86. cmd = "".join(['ps aux |grep -E "^ {0,}',name,'" |wc -l'])
  87. handler = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE)
  88. return int(handler.communicate()[0].replace('\n','')) > 0
  89. def composite(self):
  90. r = [ self.evaluate(name) for name in self.names]
  91. N = len(r)
  92. n = sum(r)
  93. return n/N
  94. """
  95. This class returns an application's both memory and cpu usage
  96. """
  97. class DetailProcess(Analysis):
  98. def __init__(self,name):
  99. self.name = name;
  100. def evaluate(self,name) :
  101. cmd = "ps -eo pmem,pcpu,vsize,comm|grep :app$"
  102. handler = subprocess.Popen(cmd.replace(":app",name),shell=True,stdout=subprocess.PIPE)
  103. ostream = handler.communicate()[0].split(' ')
  104. return [float(value) for value in ostream if value.strip() not in ['',name]]
  105. def composite(self):
  106. value = self.evaluate(self.name)
  107. #row= {"memory_usage":value[0],"cpu_usage":value[1]}
  108. return row
  109. """
  110. This class will require
  111. """
  112. class QueueServer(Analysis):
  113. def __init__(self,conf):
  114. Analysis.__init__(self)
  115. pass
  116. def is_running(self):
  117. p = Process(['rabbitmq-server'])
  118. return p.composite()
  119. def has_virtualhost(self,name):
  120. return 0
  121. def has_user(self,uid):
  122. return 0
  123. def composite(self):
  124. if self.is_running() :
  125. pass
  126. else:
  127. return [0,0,0]
  128. """
  129. Normalization will be required for the data produced by this class
  130. """
  131. class DatabaseServer(Analysis):
  132. def __init__(self,conf):
  133. Analysis.__init__(self)
  134. pass
  135. def has_table(self,name):
  136. pass
  137. def has_fields(self,table,fields):
  138. pass
  139. def has_data(self,table):
  140. pass
  141. """
  142. This function will return the number of test-cases of the last build.
  143. The use of the returned number will have to be normalized if used in a dataset.
  144. """
  145. class TestCaseCount(Analysis):
  146. pass