From 90a6a70e424626d423f91a99117e236ffb94566c Mon Sep 17 00:00:00 2001 From: Rodrigo Lazo Date: Thu, 13 Oct 2011 10:27:27 -0300 Subject: [PATCH] version 0.2: support for snapshots added --- main.py | 29 +++++++++++-------- monitor/collector.py | 2 +- monitor/datastore.py | 11 +++++++- monitor/extra/plotting.py | 2 +- monitor/http_display.py | 60 ++++++++++++++++++++++++++++------------ monitor/www_templates/base.html | 14 ++++++++++ monitor/www_templates/index.html | 55 +++--------------------------------- 7 files changed, 91 insertions(+), 82 deletions(-) rewrite monitor/www_templates/index.html (100%) diff --git a/main.py b/main.py index 6c43e71..cd8a4c9 100755 --- a/main.py +++ b/main.py @@ -24,7 +24,7 @@ __author__ = "rlazo.paz@gmail.com (Rodrigo Lazo)" -__version__ = 0.1 +__version__ = 0.2 import argparse @@ -95,20 +95,27 @@ def main(): parser.add_argument('--collection-interval', metavar="SECONDS", type=int, default=30, help="Interval, in seconds, between data collections.") - parser.add_argument('--remote-servers', nargs="+", - help=("List, separated by spaces, of remote servers " - "(HOST:PORT) to monitor.")) - args = parser.parse_args() - #sources = (("localhost", 8080),) - sources = [x.split(':') for x in args.remote_servers] + group = parser.add_mutually_exclusive_group(required=True) + group.add_argument('--remote-servers', nargs="+", + help=("List, separated by spaces, of remote servers " + "(HOST:PORT) to monitor.")) + group.add_argument('--snapshot', metavar="SNAPSHOT-FILE", type=str, + help="Filename of the snapshot to load.") + args = parser.parse_args() - collector_p = Process(target=timed_collector, - args=(sources, args.collection_interval)) + if args.snapshot: + mstore = manager.get_store() + mstore.load(args.snapshot) + else: + sources = [x.split(':') for x in args.remote_servers] + collector_p = Process(target=timed_collector, + args=(sources, args.collection_interval)) + collector_p.start() displayer_p = Process(target=displayer, args=(args.http_port,)) - collector_p.start() displayer_p.start() - collector_p.join() + if not args.snapshot: + collector_p.join() displayer_p.join() diff --git a/monitor/collector.py b/monitor/collector.py index ea72525..14a706b 100755 --- a/monitor/collector.py +++ b/monitor/collector.py @@ -28,7 +28,7 @@ parallel request to http servers. """ __author__ = "rlazo.paz@gmail.com (Rodrigo Lazo)" -__version__ = 0.1 +__version__ = 0.2 import Queue diff --git a/monitor/datastore.py b/monitor/datastore.py index b51911f..72acc3b 100755 --- a/monitor/datastore.py +++ b/monitor/datastore.py @@ -42,7 +42,7 @@ otherwise, Python may complain about missing class declarations. """ __author__ = "rlazo.paz@gmail.com (Rodrigo Lazo)" -__version__ = 0.1 +__version__ = 0.2 import bisect @@ -157,6 +157,7 @@ class DataStore(object): def __init__(self): self._store = collections.defaultdict(dict) self._vars = set() + self._is_snapshot = False def insert(self, group, var, timestamp, value): """Inserts a single data point. @@ -244,6 +245,7 @@ class DataStore(object): with open(filename, 'rb') as fd: obj = cPickle.load(fd) self._store = obj + self._is_snapshot = True self._vars.clear() def dump(self, filename): @@ -260,6 +262,10 @@ class DataStore(object): fd.flush() os.fsync(fd.fileno()) + def dump_obj(self): + """Creates a snapshot of this objects and returns it as an object.""" + return cPickle.dumps(self._store) + def dump_as_text(self, filename): """Creates a human-readable snapshot of this object. @@ -278,6 +284,9 @@ class DataStore(object): fd.flush() os.fsync(fd.fileno()) + def is_snapshot(self): + return self._is_snapshot + def _update_vars(self, force=False): """Updates internal _vars cache.""" if not self._vars or force: diff --git a/monitor/extra/plotting.py b/monitor/extra/plotting.py index cdbec9a..c8e2b79 100755 --- a/monitor/extra/plotting.py +++ b/monitor/extra/plotting.py @@ -26,7 +26,7 @@ Requires matplotlib with cairo support built-in.""" __author__ = "rlazo.paz@gmail.com (Rodrigo Lazo)" -__version__ = 0.1 +__version__ = 0.2 import matplotlib diff --git a/monitor/http_display.py b/monitor/http_display.py index 55d1162..0a5315a 100755 --- a/monitor/http_display.py +++ b/monitor/http_display.py @@ -35,10 +35,12 @@ refer to its docstring. """ __author__ = "rlazo.paz@gmail.com (Rodrigo Lazo)" -__version__ = 0.1 +__version__ = 0.2 +from datetime import datetime import cherrypy +from cherrypy.lib.static import serve_fileobj from jinja2 import Environment, PackageLoader from datastore import DataStore, DataEntry, DataPoint # pylint: disable=W0611 @@ -69,9 +71,10 @@ class MonitorHttpHandler(object): Vars: title, timestamp, body. """ template = self.env.get_template('index.html') - return template.render({"title": "Monitoring", - "timestamp": str(datetime.now()), - "body": "

seee

"}) + references= self._get_default_references() + references.update({"title": "Monitoring", + "body": "

seee

"}) + return template.render(references) @cherrypy.expose def vars(self): @@ -84,9 +87,10 @@ class MonitorHttpHandler(object): Vars: title, timestamp, body. """ template = self.env.get_template('vars.html') - return template.render({"title": "List of monitored vars", - "timestamp": str(datetime.now()), - "vars" : self._store.list_vars()}) + references = self._get_default_references() + references.update({"title": "List of monitored vars", + "vars" : self._store.list_vars()}) + return template.render(references) @cherrypy.expose def hosts(self): @@ -99,9 +103,10 @@ class MonitorHttpHandler(object): Vars: title, timestamp, body. """ template = self.env.get_template('hosts.html') - return template.render({"title": "List of monitored vars", - "timestamp": str(datetime.now()), - "vars" : self._store.list_groups()}) + references = self._get_default_references() + references.update({"title": "List of monitored vars", + "vars" : self._store.list_groups()}) + return template.render(references) @cherrypy.expose def var(self, name): @@ -115,14 +120,14 @@ class MonitorHttpHandler(object): Template: simple.html Vars: title, timestamp, body. """ - references = {"title": "Historic Values of var: %s" % name, - "timestamp": str(datetime.now())} + template = self.env.get_template('var.html') + references = self._get_default_references() + references["title"] = "Historic Values of var: %s" % name data = self._store.get_var(name) if data: filename, _ = plotting.new_multigraph(data, name, self._static_path) references["filename"] = filename references["items"] = [{'hostname' : k, 'value': v.get_latest()} for k, v in data.iteritems()] - template = self.env.get_template('var.html') return template.render(references) @cherrypy.expose @@ -138,8 +143,9 @@ class MonitorHttpHandler(object): Template: simple.html Vars: title, timestamp, body. """ - references = {"title": "Historic Values of host: %s" % name, - "timestamp": str(datetime.now())} + template = self.env.get_template('host.html') + references = self._get_default_references() + references["title"] = "Historic Values of host: %s" % name data = self._store.get_group(name) if data: items = [] @@ -149,10 +155,30 @@ class MonitorHttpHandler(object): filename, _ = plotting.new_graph(tuples, k, self._static_path) items.append({'file': filename, 'value': values[-1]}) references["items"] = items - print data - template = self.env.get_template('host.html') return template.render(references) + @cherrypy.expose + def snapshot(self): + """Returns a snapshot of the state of the database.""" + filename = "snapshot-%s.pickle" % \ + datetime.strftime(datetime.now(), "%d%m%y-%H%M") + return serve_fileobj(self._store.dump_obj(), + disposition="attachment", + content_type="application/octet-stream", + name=filename) + + def _get_default_references(self): + """Returns a dic with basic references already set. + + Includes: + - timestamp (current timestamp). + - is_snapshot (if current data store is a snapshot) + """ + return {"timestamp": str(datetime.now()), + "is_snapshot": self._store.is_snapshot()} + + + def main(store, port, templates_path, static_path): """HTTP server starter. diff --git a/monitor/www_templates/base.html b/monitor/www_templates/base.html index c5bb694..700f9b1 100644 --- a/monitor/www_templates/base.html +++ b/monitor/www_templates/base.html @@ -5,6 +5,9 @@ - {{title}} - - - - -
- {{body}} - - +{% extends "base.html" %} +{% block body %} + {{body}} +{% endblock body %} -- 2.11.4.GIT