diff options
1946 files changed, 349234 insertions, 0 deletions
diff --git a/Monitoring/.gitignore b/Monitoring/.gitignore new file mode 100644 index 0000000..f4733cc --- /dev/null +++ b/Monitoring/.gitignore @@ -0,0 +1,4 @@ +*.pyc +docs/ +/sandbox +catalog-v???.xml diff --git a/Monitoring/Makefile b/Monitoring/Makefile new file mode 100644 index 0000000..92b1d83 --- /dev/null +++ b/Monitoring/Makefile @@ -0,0 +1,57 @@ +DOC = docs +SRC = MonitoringService +GUISRC = gui +IM = ../information-model/ +TESTS = $(wildcard $(SRC)/*/test.py) +PY_SOURCES = $(filter-out $(TESTS), $(wildcard $(SRC)/*/*py)) +GUI_VERSION = 1.0 +GUI_PACKAGE = novi-ms-gui +GUI_DEBIAN = packaging/debian +GUI_INSTALL = packaging/Makefile +GUI_RUNNER = packaging/novigui + +GUI_DIRNAME = $(GUI_PACKAGE)-$(GUI_VERSION) +GUI_TARBALL = $(GUI_PACKAGE)_$(GUI_VERSION).orig.tar.gz +GUI_INSTALLDIR = /usr/share/novi-ms-gui +GUI_BUILDDIR = /tmp/guibuild + +PYTHON = /usr/bin/python2.7 +EPYDOC = /usr/bin/epydoc + +all: + make test + make $(DOC) + +$(DOC): $(PY_SOURCES) + mkdir -p $@ && \ + test -x $(EPYDOC) && $(EPYDOC) -v -o $@ -n MonSrv --graph all $(PY_SOURCES) + +distclean: + make clean + rm -rf $(DOC) + rm -rf $(GUI_BUILDDIR) + +test: $(TESTS) + for t in $(TESTS) ; do \ + PYTHONPATH=$(SRC) $(PYTHON) $$t ; \ + done + +clean: + find -name \*pyc | xargs rm -f + rm -rf $(GUIDST) + +$(GUI_BUILDDIR): + mkdir -p $@ + +$(GUI_BUILDDIR)/$(GUI_TARBALL): $(GUI_BUILDDIR) + make clean + cp -a $(GUISRC) $</$(GUI_DIRNAME) + cd $< && tar zfc $@ $(GUI_DIRNAME) + cp -a $(GUI_DEBIAN) $</$(GUI_DIRNAME) + cp $(GUI_INSTALL) $</$(GUI_DIRNAME) + cp $(GUI_RUNNER) $</$(GUI_DIRNAME) + cd $</$(GUI_DIRNAME) && debuild -us -uc + +standalonegui: + make $(GUI_BUILDDIR)/$(GUI_TARBALL) +# cp -a $(GUISRC) $(SRC) $(IM) $(GUIDST) diff --git a/Monitoring/MonitoringService/Credential/SshKeygen.py b/Monitoring/MonitoringService/Credential/SshKeygen.py new file mode 100644 index 0000000..6c8042d --- /dev/null +++ b/Monitoring/MonitoringService/Credential/SshKeygen.py @@ -0,0 +1,100 @@ +''' +Created on Jul 20, 2011 + +@author: steger +''' +from M2Crypto import RSA +from base64 import b64encode +from os import chmod, path +import stat + +# paramiko provides this functionality, so maybe we don't need this class. see paramiko.PKey + +class CannotSet(Exception): + pass + +class SshKeygen(object): + ''' + Generates a pair of RSA keys. + Enables saving the keys to the file system. + ''' + def __init__(self, bits = 1024, e = 65337): + ''' + Initiates the pair of RSA keys + @param bits: the length of the keys in bits + @type bits: integer + @param e: the exponent + @type e: integer + ''' + self.rsa = RSA.gen_key(bits, e, lambda: None) + + def _check_filename(self, filename): + if path.exists(filename): + raise Exception("File exists: %s" % filename) + + @property + def private(self): + ''' + @summary: return the private key in PEM format + @return: the private key in PEM format + @rtype: string + ''' + return self.rsa.as_pem(cipher = None) + + @private.setter + def private(self, value): + raise CannotSet + + @private.deleter + def private(self): + raise CannotSet + + @staticmethod + def _convert(rsa): + return b64encode('\x00\x00\x00\x07ssh-rsa%s%s' % (rsa.pub()[0], rsa.pub()[1])) + + @property + def public(self): + ''' + @summary: return the public key in base64 format conforming to the content of authorized_keys + @return: the public key in base64 format + @rtype: string + ''' + return self._convert(self.rsa) + + @public.setter + def public(self, value): + raise CannotSet + + @public.deleter + def public(self): + raise CannotSet + + def save_private_key(self, filename): + ''' + @summary: save the private key in the file system in a named file. + @param filename: the filename to store the private key. + @type filename: string + ''' + self._check_filename(filename) + self.rsa.save_key(filename, cipher = None) + chmod(filename, stat.S_IRUSR) + + def save_public_key(self, filename): + ''' + @summary: save the public key in the file system in a named file. + @param filename: the filename to store the public key. + @type filename: string + ''' + self._check_filename(filename) + with open(filename, "w") as f: + f.write("ssh-rsa %s" % self.public) + + @staticmethod + def convert_key_from_file(filename): + ''' + @summary: convert a private key stored in a file in PEM format and return the public key in base64 format conforming to the content of authorized_keys + @return: the public key in base64 format + @rtype: string + ''' + return SshKeygen._convert( RSA.load_key(file = filename) ) diff --git a/Monitoring/MonitoringService/Credential/__init__.py b/Monitoring/MonitoringService/Credential/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Monitoring/MonitoringService/Credential/__init__.py diff --git a/Monitoring/MonitoringService/Credential/credentialtypes.py b/Monitoring/MonitoringService/Credential/credentialtypes.py new file mode 100644 index 0000000..45da0de --- /dev/null +++ b/Monitoring/MonitoringService/Credential/credentialtypes.py @@ -0,0 +1,62 @@ +''' +Created on Oct 27, 2011 + +@author: steger, jozsef +@organization: ELTE +@contact: steger@complex.elte.hu +''' + +class Credential(object): + ''' + @summary: an empty credential to serve as an ancient class + @author: steger, jozsef + ''' + pass + +class UsernamePassword(Credential): + ''' + @summary: container for a pair of user name and password + @author: steger, jozsef + @ivar username: name of the user + @type username: str + @ivar password: password secret + @type password: str + ''' + + def __init__(self, username, password): + ''' + @summary: Constructor + @param username: the username + @type username: string + @param password: the password + @type password: string + ''' + self.username = username + self.password = password + +class UsernameRSAKey(Credential): + ''' + @summary: container for a triple of user name, private key and an optional password for the key + @author: steger, jozsef + @ivar username: name of the user + @type username: str + @ivar rsakey: a file name pointing to the user's private key secret + @type rsakey: str + @ivar password: password secret + @type password: str + ''' + + def __init__(self, username, rsakey, password = ""): + ''' + @summary: Constructor + @param username: the username + @type username: string + @param rsakey: the private key file + @type rsakey: string + @param password: the optional password to unlock the private key, default: "" + @type password: string + ''' + self.username = username + self.rsakey = rsakey + self.password = password +
\ No newline at end of file diff --git a/Monitoring/MonitoringService/Credential/test.py b/Monitoring/MonitoringService/Credential/test.py new file mode 100644 index 0000000..04a59f3 --- /dev/null +++ b/Monitoring/MonitoringService/Credential/test.py @@ -0,0 +1,46 @@ +''' +Created on Aug 10, 2011 + +@author: steger +''' +import unittest +from os import close, unlink +from tempfile import mkstemp +from subprocess import Popen, PIPE +from SshKeygen import SshKeygen + +class Test(unittest.TestCase): + sshkeygen = '/usr/bin/ssh-keygen' + + def test_sshkeygen(self): + # generate a pair of RSA keys + self.key = SshKeygen() + + # save keys in a file + fid, fn = mkstemp(suffix = "_rsa") + close(fid) + unlink(fn) + self.fn_private = fn + self.fn_public = "%s.pub" % fn + self.key.save_private_key(self.fn_private) + self.key.save_public_key(self.fn_public) + + # Test the base64 format of the public key. + # convert and compare private key using ssh-keygen + proc = Popen(args = [self.sshkeygen, '-y', '-f', self.fn_private], stdout = PIPE) + converted = str(proc.communicate(input = None)[0]) + expected = "ssh-rsa %s\n" % self.key.public + self.assertEqual(expected, converted, "Base64 encoded public RSA key differs from the one generated by %s" % self.sshkeygen) + + # Test SshKeygen objects convert_key_from_file method. + expected = self.key.public + converted = SshKeygen.convert_key_from_file(self.fn_private) + self.assertEqual(expected, converted, "Base64 encoded public RSA key generated from file %s differs from expected" % self.fn_private) + + # remove generated files + unlink(self.fn_private) + unlink(self.fn_public) + +if __name__ == "__main__": + #import sys;sys.argv = ['', 'Test.test_sshkeygen'] + unittest.main()
\ No newline at end of file diff --git a/Monitoring/MonitoringService/DataProcessing/Aggregator.py b/Monitoring/MonitoringService/DataProcessing/Aggregator.py new file mode 100644 index 0000000..49855fb --- /dev/null +++ b/Monitoring/MonitoringService/DataProcessing/Aggregator.py @@ -0,0 +1,288 @@ +''' +Created on Aug 10, 2011 + +@author: steger, gombos, matuszka +''' + +from DataProcessing.MeasurementLevel import Ordinal, Ratio, Interval #Nominal +from math import sqrt +from DataProcessing.DataReader import DataReader +from DataProcessing.DataHeader import DataHeader, DataHeaderCell +from DataProcessing.DataSource import DataSource +from DataProcessing.Data import Data +from DataProcessing.DataError import AggregatorError + +#FIXME: docs + +class Aggregator(DataSource): + ''' + classdocs + @cvar cn_count: the name of the column indicating the set size before aggregation + ''' + cn_count = 'Count' + + def __init__(self, datasource, cellrequest): + ''' + Constructor + @param datasource: table of records to manipulate with + @type datasource: DataSource + @param cellrequest: a column wise projection of the table is carried out, this column is kept + @type cellrequest: CellRequest + ''' + if not isinstance(datasource, DataSource): + raise AggregatorError("Wrong type of datasource %s" % datasource) + DataSource.__init__(self, dependency = datasource) + self._inputreader.extract(cellrequest = [cellrequest]) + for c in self._inputreader.headercells(): + break + if not c.dimension.level(self.dimension_compatible): + raise AggregatorError("The measurement level of input (%s) is not compatible with %s" % (c.dimension, self.name)) + header = DataHeader("%sAggregate(%s)" % (self.name, datasource.name)) + dimension = c.dimension + header.addColumn(DataHeaderCell(name = self.cn_count, dimension = dimension.manager["Countable"])) + self.cn_aggr = '%s(%s)' % (self.name, c.name) + header.addColumn(DataHeaderCell(name = self.cn_aggr, dimension = dimension, unit = c.unit)) + self._data = Data(datasource.um, header) + self._record = self._data.getTemplate(size = 1) +# self.um = datasource.um + self.source = datasource + + self._aggregate = None + +#FIXME: ez a ketto cucc tenyleg kell? + def __len__(self): + return len(self._data) + @property + def writelock(self): + return self._data.writelock + + + @property + def aggregate(self): + self.process() + return self._aggregate + + @property + def readerClass(self): + return DataReader + + @property + def dimension_compatible(self): + raise AggregatorError("dimension_compatible property is not implemented in %s" % self) + + +class Sum(Aggregator): + def __init__(self, datasource, cellrequest): + Aggregator.__init__(self, datasource, cellrequest) + self._aggregate = 0 + + @property + def dimension_compatible(self): + return Interval + + @property + def name(self): + return "Sum" + + def _process(self): + if self._inputreader.sourceCleared.isSet(): + self._inputreader.sourceCleared.clear() + self._aggregate = 0 + self._inputreader.rewind() + changed = True + else: + changed = False + for (x,) in self._inputreader: + self._aggregate += float(x) + changed = True + if changed: + self._data.clear() + self._record.update(name = self.cn_aggr, values = (self._aggregate,)) + self._record.update(name = self.cn_count, values = (len(self.source),)) + self._data.saveRecord(self._record) + return self.CLEARED | self.EXPANDED + re |