diff --git a/src/monitor.py b/src/monitor.py new file mode 100755 index 0000000..5ecbe61 --- /dev/null +++ b/src/monitor.py @@ -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 \ No newline at end of file diff --git a/src/monitor.pyc b/src/monitor.pyc new file mode 100644 index 0000000..098be59 Binary files /dev/null and b/src/monitor.pyc differ diff --git a/test/TestServerMonitor.py b/test/TestServerMonitor.py new file mode 100644 index 0000000..89174ec --- /dev/null +++ b/test/TestServerMonitor.py @@ -0,0 +1,19 @@ +from __future__ import division +import unittest +from monitor import Env, DetailProcess + +class TestMonitorServer(unittest.TestCase): + + def test_Environment(self): + """ + This test case is designed to test the existance of a resource set as an environment variable. This applies to files, folders (not values) + """ + p = Env(['PATH','HOME','SHELL']) + value = p.composite() + self.assertTrue(value > 0 and value == 2/3) + self.assertTrue(p.evaluate('PATH') == 0) + def test_RunningProcess(self): + p = DetailProcess(['rabbitmq-server','python']) + print p.composite() +if __name__ == '__main__' : + unittest.main() \ No newline at end of file