""" 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