|
@@ -0,0 +1,159 @@
|
|
|
+"""
|
|
|
+ This program is designed to inspect an application environment
|
|
|
+ This program should only be run on unix friendly systems
|
|
|
+
|
|
|
+"""
|
|
|
+from __future__ import division
|
|
|
+import os
|
|
|
+import subprocess
|
|
|
+from sets import Set
|
|
|
+import re
|
|
|
+
|
|
|
+class Analysis:
|
|
|
+ def __init__(self):
|
|
|
+ self.logs = []
|
|
|
+ pass
|
|
|
+ def post(self,object):
|
|
|
+ self.logs.append(object)
|
|
|
+"""
|
|
|
+ This class is designed to analyze environment variables. Environment variables can either be folders, files or simple values
|
|
|
+ The class returns a quantifiable assessment of the environment variables (expected 100%)
|
|
|
+"""
|
|
|
+class Env(Analysis):
|
|
|
+ def __init__(self,values):
|
|
|
+ Analysis.__init__(self)
|
|
|
+ self.values = values
|
|
|
+ """
|
|
|
+ This function evaluate the validity of an environment variable by returning a 1 or 0 (computable)
|
|
|
+ The function will use propositional logic (https://en.wikipedia.org/wiki/Propositional_calculus)
|
|
|
+ """
|
|
|
+ def evaluate(self,id):
|
|
|
+
|
|
|
+ if id in os.environ :
|
|
|
+ #
|
|
|
+ # We can inspect to make sure the environment variable is not a path or filename.
|
|
|
+ # Using propositional logic we proceed as follows:
|
|
|
+ # - (p) We determine if the value is an folder or file name (using regex)
|
|
|
+ # - (q) In case of a file or folder we check for existance
|
|
|
+ # The final result is a conjuction of p and q
|
|
|
+ #
|
|
|
+ value = os.environ[id]
|
|
|
+ expressions = [os.sep,'(\\.\w+)$']
|
|
|
+ p = sum([ re.search(xchar,value) is not None for xchar in expressions])
|
|
|
+ q = os.path.exists(value)
|
|
|
+
|
|
|
+ return int(p and q)
|
|
|
+ else:
|
|
|
+ return 0
|
|
|
+
|
|
|
+ def composite (self):
|
|
|
+ r = [ self.evaluate(id) for id in self.values] ;
|
|
|
+ N = len(r)
|
|
|
+ n = sum(r)
|
|
|
+ return n/N
|
|
|
+
|
|
|
+class Sandbox(Analysis):
|
|
|
+ def __init__(self,conf):
|
|
|
+ Analysis.__init__(self)
|
|
|
+ self.sandbox_path = conf['path']
|
|
|
+ self.requirements_path = conf['requirements']
|
|
|
+ def get_requirements (self):
|
|
|
+ f = open(self.requirements_path)
|
|
|
+ return [ name.replace('-',' ').replace('_',' ') for name in f.read().split('\n') if name != '']
|
|
|
+ """
|
|
|
+ This function will return the modules installed in the sandbox (virtual environment)
|
|
|
+ """
|
|
|
+ def get_sandbox_requirements(self):
|
|
|
+ cmd = ['freeze']
|
|
|
+ xchar = ''.join([os.sep]*2)
|
|
|
+ pip_vm = ''.join([self.sandbox_path,os.sep,'bin',os.sep,'pip']).replace(xchar,os.sep)
|
|
|
+ cmd = [pip_vm]+cmd
|
|
|
+ r = subprocess.check_output(cmd).split('\n')
|
|
|
+ return [row.replace('-',' ').replace('_',' ') for row in r if row.strip() != '']
|
|
|
+ def evaluate(self):
|
|
|
+ pass
|
|
|
+ """
|
|
|
+ This function returns the ratio of existing modules relative to the ones expected
|
|
|
+ """
|
|
|
+ def composite(self):
|
|
|
+ required_modules= self.get_requirements()
|
|
|
+ sandbox_modules = self.get_sandbox_requirements()
|
|
|
+ N = len(requirements)
|
|
|
+ n = len(Set(required_modules) - Set(sandbox_modules))
|
|
|
+ return n/N
|
|
|
+
|
|
|
+"""
|
|
|
+ This class performs the analysis of a list of processes and determines
|
|
|
+ The class provides a quantifiable measure of how many processes it found over all
|
|
|
+"""
|
|
|
+class Processes(Analysis):
|
|
|
+ def __init__(self,names):
|
|
|
+ Analysis.__init__(self)
|
|
|
+ self.names = names
|
|
|
+ def evaluate(self,name):
|
|
|
+ cmd = "".join(['ps aux |grep -E "^ {0,}',name,'" |wc -l'])
|
|
|
+ handler = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE)
|
|
|
+
|
|
|
+ return int(handler.communicate()[0].replace('\n','')) > 0
|
|
|
+ def composite(self):
|
|
|
+ r = [ self.evaluate(name) for name in self.names]
|
|
|
+ N = len(r)
|
|
|
+ n = sum(r)
|
|
|
+ return n/N
|
|
|
+"""
|
|
|
+ This class returns an application's both memory and cpu usage
|
|
|
+"""
|
|
|
+class DetailProcess(Analysis):
|
|
|
+ def __init__(self,names):
|
|
|
+ self.names = names;
|
|
|
+ def evaluate(self,name) :
|
|
|
+ cmd = "ps -eo pmem,pcpu,vsize,comm|grep :app$"
|
|
|
+ handler = subprocess.Popen(cmd.replace(":app",name),shell=True,stdout=subprocess.PIPE)
|
|
|
+ ostream = handler.communicate()[0].split(' ')
|
|
|
+ return [float(value) for value in ostream if value.strip() not in ['',name]] +[name]
|
|
|
+
|
|
|
+ def composite(self):
|
|
|
+ #value = self.evaluate(self.name)
|
|
|
+ #row= {"memory_usage":value[0],"cpu_usage":value[1]}
|
|
|
+ #return row
|
|
|
+ ma = [self.evaluate(name) for name in self.names]
|
|
|
+
|
|
|
+ return [{"memory_usage":row[0],"cpu_usage":row[1],"memory_available":row[2]/1000,"label":row[3]} for row in ma]
|
|
|
+"""
|
|
|
+ This class will require
|
|
|
+"""
|
|
|
+class QueueServer(Analysis):
|
|
|
+ def __init__(self,conf):
|
|
|
+ Analysis.__init__(self)
|
|
|
+ pass
|
|
|
+ def is_running(self):
|
|
|
+ p = Process(['rabbitmq-server'])
|
|
|
+ return p.composite()
|
|
|
+ def has_virtualhost(self,name):
|
|
|
+ return 0
|
|
|
+ def has_user(self,uid):
|
|
|
+ return 0
|
|
|
+ def composite(self):
|
|
|
+ if self.is_running() :
|
|
|
+ pass
|
|
|
+ else:
|
|
|
+ return [0,0,0]
|
|
|
+"""
|
|
|
+ Normalization will be required for the data produced by this class
|
|
|
+"""
|
|
|
+class DatabaseServer(Analysis):
|
|
|
+ def __init__(self,conf):
|
|
|
+ Analysis.__init__(self)
|
|
|
+ pass
|
|
|
+ def has_table(self,name):
|
|
|
+ pass
|
|
|
+ def has_fields(self,table,fields):
|
|
|
+ pass
|
|
|
+ def has_data(self,table):
|
|
|
+ pass
|
|
|
+"""
|
|
|
+ This function will return the number of test-cases of the last build.
|
|
|
+ The use of the returned number will have to be normalized if used in a dataset.
|
|
|
+"""
|
|
|
+#class TestCaseCount(Analysis):
|
|
|
+ #pass
|