diff options
-rw-r--r-- | sublab_project/settings.py | 3 | ||||
-rw-r--r-- | sublab_project/static/css/sublab.css | 12 | ||||
-rw-r--r-- | sublab_project/sublab_monitor/__init__.py | 1 | ||||
-rw-r--r-- | sublab_project/sublab_monitor/models.py | 3 | ||||
-rw-r--r-- | sublab_project/sublab_monitor/storage.py | 63 | ||||
-rw-r--r-- | sublab_project/sublab_monitor/tasks.py | 46 | ||||
-rw-r--r-- | sublab_project/sublab_monitor/templates/sublab_monitor/host_status.html | 6 | ||||
-rw-r--r-- | sublab_project/sublab_monitor/templatetags/__init__.py | 0 | ||||
-rw-r--r-- | sublab_project/sublab_monitor/templatetags/host_status.py | 46 | ||||
-rw-r--r-- | sublab_project/sublab_monitor/tests.py | 24 | ||||
-rw-r--r-- | sublab_project/sublab_monitor/views.py | 1 | ||||
-rw-r--r-- | sublab_project/templates/base.html | 25 |
12 files changed, 208 insertions, 22 deletions
diff --git a/sublab_project/settings.py b/sublab_project/settings.py index f2c804d..f45e84f 100644 --- a/sublab_project/settings.py +++ b/sublab_project/settings.py @@ -140,7 +140,8 @@ INSTALLED_APPS = ( 'accounts', 'redisession', 'sorl.thumbnail', - 'preview_admin' + 'preview_admin', + 'sublab_monitor' ) # A sample logging configuration. The only tangible logging diff --git a/sublab_project/static/css/sublab.css b/sublab_project/static/css/sublab.css index 9c5fa43..756f312 100644 --- a/sublab_project/static/css/sublab.css +++ b/sublab_project/static/css/sublab.css @@ -283,6 +283,18 @@ span.header { margin-right: 10px; } +span.green { + color: #00FF00; +} + +span.grey { + color: #222222; +} + +span.red { + color: #FF0000; +} + .member { line-height: 20px; font-weight: bold; diff --git a/sublab_project/sublab_monitor/__init__.py b/sublab_project/sublab_monitor/__init__.py new file mode 100644 index 0000000..1b8cfc0 --- /dev/null +++ b/sublab_project/sublab_monitor/__init__.py @@ -0,0 +1 @@ +from sublab_monitor.storage import Storage, StorageError diff --git a/sublab_project/sublab_monitor/models.py b/sublab_project/sublab_monitor/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/sublab_project/sublab_monitor/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/sublab_project/sublab_monitor/storage.py b/sublab_project/sublab_monitor/storage.py new file mode 100644 index 0000000..8b3e385 --- /dev/null +++ b/sublab_project/sublab_monitor/storage.py @@ -0,0 +1,63 @@ +import redis +import pickle +import sys + +# load some django settings here some day + + +class StorageError(Exception): + pass + + +def storage_error(typ): + return type('Storage%sError' % typ.__name__, (typ, StorageError), {}) + + +def raise_storage_error(): + typ, value, trace = sys.exc_info() + + raise storage_error(typ), value, trace + + +class Storage: + key_prefix = 'sublab_monitor.' + + def __init__(self, app_prefix): + self.key_prefix += '%s.' % app_prefix + + try: + self.redis = redis.StrictRedis() + except redis.RedisError: + raise_storage_error() + + def key(self, key): + return '%s%s' % (self.key_prefix, key) + + def get(self, key): + lookup_key = self.key(key) + + try: + entry = self.redis.get(lookup_key) + except redis.RedisError: + raise_storage_error() + + if entry is None: + return None + + try: + return pickle.loads(entry) + except pickle.PickleError: + raise_storage_error() + + def set(self, key, value): + lookup_key = self.key(key) + + try: + entry = pickle.dumps(value) + except pickle.PickleError: + raise_storage_error() + + try: + self.redis.set(lookup_key, entry) + except redis.RedisError: + raise_storage_error() diff --git a/sublab_project/sublab_monitor/tasks.py b/sublab_project/sublab_monitor/tasks.py new file mode 100644 index 0000000..33dcad6 --- /dev/null +++ b/sublab_project/sublab_monitor/tasks.py @@ -0,0 +1,46 @@ +"""Celery tasks. +""" +from datetime import timedelta +from celery.task import PeriodicTask +import subprocess + +import sublab_monitor + +class NetworkStatus(PeriodicTask): + """Periodic task for getting sublab network status + """ + hosts = { + 'taifun': '172.22.83.5', + 'trieste': '172.22.80.4', + 'nautilus': '172.22.80.7', + } + run_every = timedelta(minutes=4) + ignore_result = True + + def __init__(self, *args, **kwargs): + PeriodicTask.__init__(self, *args, **kwargs) + + + @staticmethod + def host_alive(host): + rc = subprocess.call(['ping', '-c', '2', '-W', '1', host]) + + if rc == 0: + return True + else: + return False + + def run(self, **kwargs): + """Ping all the hosts. + """ + self.logger = self.get_logger(**kwargs) + + results = {} + for host, target in self.hosts.items(): + results[host] = self.host_alive(target) + + storage = sublab_monitor.Storage('network_status') + for host, status in results.items(): + storage.set(host, status) + + return repr(results) diff --git a/sublab_project/sublab_monitor/templates/sublab_monitor/host_status.html b/sublab_project/sublab_monitor/templates/sublab_monitor/host_status.html new file mode 100644 index 0000000..5d26dd9 --- /dev/null +++ b/sublab_project/sublab_monitor/templates/sublab_monitor/host_status.html @@ -0,0 +1,6 @@ +<td class="status"> {{ hostname|capfirst }}: </td> +<td class="status"> + <span class="{{ status|yesno:"green,grey" }}">Online</span> + + <span class="{{ status|yesno:"grey,red,grey" }}">Offline</span> +</td> diff --git a/sublab_project/sublab_monitor/templatetags/__init__.py b/sublab_project/sublab_monitor/templatetags/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/sublab_project/sublab_monitor/templatetags/__init__.py diff --git a/sublab_project/sublab_monitor/templatetags/host_status.py b/sublab_project/sublab_monitor/templatetags/host_status.py new file mode 100644 index 0000000..e119f60 --- /dev/null +++ b/sublab_project/sublab_monitor/templatetags/host_status.py @@ -0,0 +1,46 @@ +from django import template +import sublab_monitor + +register = template.Library() + +class HostStatusNode(template.Node): + def __init__(self, host): + self.host = host + + def host_status(self, context): + if self not in context.render_context: + try: + context.render_context[self] = sublab_monitor.Storage('network_status') + except sublab_monitor.StorageError: + return None + + storage = context.render_context[self] + try: + return storage.get(self.host) + except sublab_monitor.StorageError: + return None + + def host_context(self, context): + context_data = { + 'hostname': self.host, + 'status': self.host_status(context) + } + + return template.context.Context(context_data, autoescape=context.autoescape) + + def render(self, context): + t = template.loader.get_template('sublab_monitor/host_status.html') + c = self.host_context(context) + return t.render(c) + +@register.tag +def host_status(parser, token): + try: + tag_name, host = token.split_contents() + except ValueError: + raise template.TemplateSyntaxError( + "%r tag requires a single argument" % token.contents.split()[0]) + if not host[0] == host[-1] and host[0] in ('"', "'"): + raise template.TemplateSyntaxError( + "%r tag's argument should be in quotes" % token.contents.split()[0]) + return HostStatusNode(host[1:-1]) diff --git a/sublab_project/sublab_monitor/tests.py b/sublab_project/sublab_monitor/tests.py new file mode 100644 index 0000000..c80bb61 --- /dev/null +++ b/sublab_project/sublab_monitor/tests.py @@ -0,0 +1,24 @@ +""" +This file demonstrates writing tests using the unittest module. These will pass +when you run "manage.py test". + +Replace this with more appropriate tests for your application. +""" + +from django.test import TestCase +from sublab_monitor.tasks import NetworkStatus + +class SimpleTest(TestCase): + def test_reachable(self): + """ + Tests that for reachable hosts host_alive() returns True + """ + self.assertEqual(NetworkStatus.host_alive('127.0.0.1'), True) + + def test_unreachable(self): + """ + Tests that for unreachable hosts host_alive() returns False + """ + # Hopefully, this DoD? IP will never be reachable on the + # Internet :) + self.assertEqual(NetworkStatus.host_alive('8.5.4.3'), False) diff --git a/sublab_project/sublab_monitor/views.py b/sublab_project/sublab_monitor/views.py new file mode 100644 index 0000000..60f00ef --- /dev/null +++ b/sublab_project/sublab_monitor/views.py @@ -0,0 +1 @@ +# Create your views here. diff --git a/sublab_project/templates/base.html b/sublab_project/templates/base.html index ccca784..41b7d59 100644 --- a/sublab_project/templates/base.html +++ b/sublab_project/templates/base.html @@ -1,3 +1,4 @@ +{% load host_status %} <!DOCTYPE HTML> <html> <head> @@ -13,9 +14,6 @@ {# <meta name="description" lang="en" content="$template_desc_en"> #} <link rel="stylesheet" href="{{ STATIC_URL }}css/sublab.css" type="text/css"> - <link rel="stylesheet" href="{{ STATIC_URL }}autogen/taifun.status.css" type="text/css"> - <link rel="stylesheet" href="{{ STATIC_URL }}autogen/trieste.status.css" type="text/css"> - <link rel="stylesheet" href="{{ STATIC_URL }}autogen/nautilus.status.css" type="text/css"> <link rel="shortcut icon" href="{{ STATIC_URL }}img/favicon.png"> {% block feeds %} @@ -92,28 +90,13 @@ <div class="status"> <table> <tr> - <td class="status"> - Taifun: - </td> - <td class="statusinfo"> - <span class="taifunonline">Online</span> <span class="taifunoffline">Offline</span> - </td> + {% host_status 'taifun' %} </tr> <tr> - <td class="status"> - Trieste: - </td> - <td class="status"> - <span class="triesteonline">Online</span> <span class="triesteoffline">Offline</span> - </td> + {% host_status 'trieste' %} </tr> <tr> - <td class="status"> - Nautilus: - </td> - <td class="status"> - <span class="nautilusonline">Online</span> <span class="nautilusoffline">Offline</span> - </td> + {% host_status 'nautilus' %} </tr> </table> </div> |