summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Franke <nobody@nowhere.ws>2012-01-11 09:49:53 +0100
committerChristian Franke <nobody@nowhere.ws>2012-01-11 09:49:53 +0100
commit9a94e0095a51981cc668ac0269667a307c45923c (patch)
tree76a92a43a24b0a7b376912e310353677c746c074
parentfff2edd3a10a7f9585d4a734740420256246b9b5 (diff)
add network_monitor
-rw-r--r--sublab_project/settings.py3
-rw-r--r--sublab_project/static/css/sublab.css12
-rw-r--r--sublab_project/sublab_monitor/__init__.py1
-rw-r--r--sublab_project/sublab_monitor/models.py3
-rw-r--r--sublab_project/sublab_monitor/storage.py63
-rw-r--r--sublab_project/sublab_monitor/tasks.py46
-rw-r--r--sublab_project/sublab_monitor/templates/sublab_monitor/host_status.html6
-rw-r--r--sublab_project/sublab_monitor/templatetags/__init__.py0
-rw-r--r--sublab_project/sublab_monitor/templatetags/host_status.py46
-rw-r--r--sublab_project/sublab_monitor/tests.py24
-rw-r--r--sublab_project/sublab_monitor/views.py1
-rw-r--r--sublab_project/templates/base.html25
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>
+ &nbsp;
+ <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>&nbsp;&nbsp;<span class="taifunoffline">Offline</span>
- </td>
+ {% host_status 'taifun' %}
</tr>
<tr>
- <td class="status">
- Trieste:
- </td>
- <td class="status">
- <span class="triesteonline">Online</span>&nbsp;&nbsp;<span class="triesteoffline">Offline</span>
- </td>
+ {% host_status 'trieste' %}
</tr>
<tr>
- <td class="status">
- Nautilus:
- </td>
- <td class="status">
- <span class="nautilusonline">Online</span>&nbsp;&nbsp;<span class="nautilusoffline">Offline</span>
- </td>
+ {% host_status 'nautilus' %}
</tr>
</table>
</div>