Openvz traffic0

This commit is contained in:
Marc 2014-07-14 14:56:48 +00:00
parent bc398644b7
commit 121e1a4b1c
11 changed files with 101 additions and 81 deletions

View File

@ -29,10 +29,12 @@ class MailmanTraffic(ServiceMonitor):
"echo %(object_id)s $(( ${SIZE}*${SUBSCRIBERS} ))" % context) "echo %(object_id)s $(( ${SIZE}*${SUBSCRIBERS} ))" % context)
def get_context(self, mail_list): def get_context(self, mail_list):
last_date = timezone.localtime(self.get_last_date(mail_list.pk))
current_date = timezone.localtime(self.current_date)
return { return {
'mailman_log': settings.LISTS_MAILMAN_POST_LOG_PATH, 'mailman_log': settings.LISTS_MAILMAN_POST_LOG_PATH,
'list_name': mail_list.name, 'list_name': mail_list.name,
'object_id': mail_list.pk, 'object_id': mail_list.pk,
'last_date': timezone.localtime(self.get_last_date(mail_list)).strftime("%b %d %H:%M:%S"), 'last_date': last_date.strftime("%b %d %H:%M:%S"),
'current_date': timezone.localtime(self.get_current_date()).strftime("%b %d %H:%M:%S"), 'current_date': current_date.strftime("%b %d %H:%M:%S"),
} }

View File

@ -2,6 +2,7 @@ from django.contrib import admin
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.utils.html import escape from django.utils.html import escape
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from djcelery.humanize import naturaldate
from orchestra.admin.html import monospace_format from orchestra.admin.html import monospace_format
from orchestra.admin.utils import link from orchestra.admin.utils import link
@ -30,7 +31,7 @@ class RouteAdmin(admin.ModelAdmin):
def display_model(self, route): def display_model(self, route):
try: try:
return route.backend_class().model return escape(route.backend_class().model)
except KeyError: except KeyError:
return "<span style='color: red;'>NOT AVAILABLE</span>" return "<span style='color: red;'>NOT AVAILABLE</span>"
display_model.short_description = _("model") display_model.short_description = _("model")
@ -61,7 +62,9 @@ class BackendOperationInline(admin.TabularInline):
try: try:
return link('instance')(self, operation) return link('instance')(self, operation)
except: except:
return _("deleted %s %s") % (operation.content_type, operation.object_id) return _("deleted {0} {1}").format(
escape(operation.content_type), escape(operation.object_id)
)
instance_link.allow_tags = True instance_link.allow_tags = True
instance_link.short_description = _("Instance") instance_link.short_description = _("Instance")
@ -71,8 +74,8 @@ class BackendOperationInline(admin.TabularInline):
class BackendLogAdmin(admin.ModelAdmin): class BackendLogAdmin(admin.ModelAdmin):
list_display = ( list_display = (
'id', 'backend', 'server_link', 'display_state', 'exit_code', 'created', 'id', 'backend', 'server_link', 'display_state', 'exit_code',
'execution_time', 'display_created', 'execution_time',
) )
list_display_links = ('id', 'backend') list_display_links = ('id', 'backend')
list_filter = ('state', 'backend') list_filter = ('state', 'backend')
@ -80,14 +83,10 @@ class BackendLogAdmin(admin.ModelAdmin):
inlines = [BackendOperationInline] inlines = [BackendOperationInline]
fields = [ fields = [
'backend', 'server', 'state', 'mono_script', 'mono_stdout', 'mono_stderr', 'backend', 'server', 'state', 'mono_script', 'mono_stdout', 'mono_stderr',
'mono_traceback', 'exit_code', 'task_id', 'created', 'last_update', 'mono_traceback', 'exit_code', 'task_id', 'display_created',
'execution_time' 'display_last_update', 'execution_time'
]
readonly_fields = [
'backend', 'server', 'state', 'mono_script', 'mono_stdout', 'mono_stderr',
'mono_traceback', 'exit_code', 'task_id', 'created', 'last_update',
'execution_time'
] ]
readonly_fields = fields
def server_link(self, log): def server_link(self, log):
url = reverse('admin:orchestration_server_change', args=(log.server.pk,)) url = reverse('admin:orchestration_server_change', args=(log.server.pk,))
@ -118,6 +117,20 @@ class BackendLogAdmin(admin.ModelAdmin):
return monospace_format(escape(log.traceback)) return monospace_format(escape(log.traceback))
mono_traceback.short_description = _("traceback") mono_traceback.short_description = _("traceback")
def display_last_update(self, log):
return '<div title="{0}">{1}</div>'.format(
escape(str(log.last_update)), escape(naturaldate(log.last_update)),
)
display_last_update.short_description = _("last update")
display_last_update.allow_tags = True
def display_created(self, log):
return '<div title="{0}">{1}</div>'.format(
escape(str(log.created)), escape(naturaldate(log.created)),
)
display_created.short_description = _("created")
display_created.allow_tags = True
def get_queryset(self, request): def get_queryset(self, request):
""" Order by structured name and imporve performance """ """ Order by structured name and imporve performance """
qs = super(BackendLogAdmin, self).get_queryset(request) qs = super(BackendLogAdmin, self).get_queryset(request)

View File

@ -31,7 +31,7 @@ class ServiceBackend(object):
def __unicode__(self): def __unicode__(self):
return type(self).__name__ return type(self).__name__
def __str__(self): def __str__(self):
return unicode(self) return unicode(self)

View File

@ -13,14 +13,14 @@ from . import settings
def BashSSH(backend, log, server, cmds): def BashSSH(backend, log, server, cmds):
from .models import BackendLog from .models import BackendLog
script = '\n\n'.join(['set -e'] + cmds + ['exit 0']) script = '\n\n'.join(['set -e', 'set -o pipefail'] + cmds + ['exit 0'])
script = script.replace('\r', '') script = script.replace('\r', '')
log.script = script log.script = script
log.save() log.save()
try: try:
# In order to avoid "Argument list too long" we while generate first a # Avoid "Argument list too long" on large scripts by genereting a file
# script file, then scp the escript and safely execute in remote # and scping it to the remote server
digest = hashlib.md5(script).hexdigest() digest = hashlib.md5(script).hexdigest()
path = os.path.join(settings.ORCHESTRATION_TEMP_SCRIPT_PATH, digest) path = os.path.join(settings.ORCHESTRATION_TEMP_SCRIPT_PATH, digest)
with open(path, 'w') as script_file: with open(path, 'w') as script_file:

View File

@ -1,7 +1,9 @@
from django.contrib import admin, messages from django.contrib import admin, messages
from django.contrib.contenttypes import generic from django.contrib.contenttypes import generic
from django.utils.functional import cached_property from django.utils.functional import cached_property
from django.utils.html import escape
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from djcelery.humanize import naturaldate
from orchestra.admin import ExtendedModelAdmin from orchestra.admin import ExtendedModelAdmin
from orchestra.admin.filters import UsedContentTypeFilter from orchestra.admin.filters import UsedContentTypeFilter
@ -100,6 +102,8 @@ def resource_inline_factory(resources):
form = ResourceForm form = ResourceForm
formset = ResourceInlineFormSet formset = ResourceInlineFormSet
can_delete = False can_delete = False
fields = ('verbose_name', 'used', 'display_last_update', 'allocated',)
readonly_fields = ('used', 'display_last_update',)
class Media: class Media:
css = { css = {
@ -109,6 +113,13 @@ def resource_inline_factory(resources):
def has_add_permission(self, *args, **kwargs): def has_add_permission(self, *args, **kwargs):
""" Hidde add another """ """ Hidde add another """
return False return False
def display_last_update(self, log):
return '<div title="{0}">{1}</div>'.format(
escape(str(log.last_update)), escape(naturaldate(log.last_update)),
)
display_last_update.short_description = _("last update")
display_last_update.allow_tags = True
return ResourceInline return ResourceInline

View File

@ -2,9 +2,9 @@ import datetime
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.utils import timezone from django.utils import timezone
from django.utils.functional import cached_property
from orchestra.apps.orchestration import ServiceBackend from orchestra.apps.orchestration import ServiceBackend
from orchestra.utils.functional import cached
class ServiceMonitor(ServiceBackend): class ServiceMonitor(ServiceBackend):
@ -23,18 +23,29 @@ class ServiceMonitor(ServiceBackend):
if backend != ServiceMonitor and ServiceMonitor in backend.__mro__: if backend != ServiceMonitor and ServiceMonitor in backend.__mro__:
yield backend yield backend
@cached @cached_property
def get_last_date(self, obj): def current_date(self):
return timezone.now()
@cached_property
def content_type(self):
app_label, model = self.model.split('.')
model = model.lower()
return ContentType.objects.get(app_label=app_label, model=model)
def get_last_data(self, object_id):
from .models import MonitorData from .models import MonitorData
try: try:
ct = ContentType.objects.get_for_model(type(obj)) return MonitorData.objects.filter(content_type=self.content_type,
return MonitorData.objects.filter(content_type=ct, object_id=obj.pk).latest().date object_id=object_id).latest()
except MonitorData.DoesNotExist: except MonitorData.DoesNotExist:
return self.get_current_date() - datetime.timedelta(days=1) return None
@cached def get_last_date(self, object_id):
def get_current_date(self): data = self.get_last_data(object_id)
return timezone.now() if data is None:
return self.current_date - datetime.timedelta(days=1)
return data.date
def store(self, log): def store(self, log):
""" object_id value """ """ object_id value """
@ -46,7 +57,7 @@ class ServiceMonitor(ServiceBackend):
line = line.strip() line = line.strip()
object_id, value = line.split() object_id, value = line.split()
MonitorData.objects.create(monitor=name, object_id=object_id, MonitorData.objects.create(monitor=name, object_id=object_id,
content_type=ct, value=value, date=self.get_current_date()) content_type=ct, value=value, date=self.current_date)
def execute(self, server): def execute(self, server):
log = super(ServiceMonitor, self).execute(server) log = super(ServiceMonitor, self).execute(server)

View File

@ -1,5 +1,7 @@
from django import forms from django import forms
from django.utils.html import escape
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from djcelery.humanize import naturaldate
from orchestra.forms.widgets import ShowTextWidget, ReadOnlyWidget from orchestra.forms.widgets import ShowTextWidget, ReadOnlyWidget
@ -9,8 +11,6 @@ class ResourceForm(forms.ModelForm):
required=False) required=False)
used = forms.IntegerField(label=_("Used"), widget=ShowTextWidget(), used = forms.IntegerField(label=_("Used"), widget=ShowTextWidget(),
required=False) required=False)
last_update = forms.DateTimeField(label=_("Last update"), widget=ShowTextWidget(),
required=False)
allocated = forms.IntegerField(label=_("Allocated")) allocated = forms.IntegerField(label=_("Allocated"))
class Meta: class Meta:

View File

@ -101,10 +101,12 @@ class FTPTraffic(ServiceMonitor):
' | xargs echo %(object_id)s """ % context) ' | xargs echo %(object_id)s """ % context)
def get_context(self, user): def get_context(self, user):
last_date = timezone.localtime(self.get_last_date(user.pk))
current_date = timezone.localtime(self.current_date)
return { return {
'log_file': settings.USERS_FTP_LOG_PATH, 'log_file': settings.USERS_FTP_LOG_PATH,
'last_date': timezone.localtime(self.get_last_date(user)).strftime("%Y%m%d%H%M%S"), 'last_date': last_date.strftime("%Y%m%d%H%M%S"),
'current_date': timezone.localtime(self.get_current_date()).strftime("%Y%m%d%H%M%S"), 'current_date': current_date.strftime("%Y%m%d%H%M%S"),
'object_id': user.pk, 'object_id': user.pk,
'username': user.username, 'username': user.username,
} }

View File

@ -3,18 +3,32 @@ from django.utils.translation import ugettext_lazy as _
from orchestra.apps.resources import ServiceMonitor from orchestra.apps.resources import ServiceMonitor
class OpenVZDisk(ServiceMonitor):
model = 'vps.VPS'
resource = ServiceMonitor.DISK
class OpenVZMemory(ServiceMonitor):
model = 'vps.VPS'
resource = ServiceMonitor.MEMORY
class OpenVZTraffic(ServiceMonitor): class OpenVZTraffic(ServiceMonitor):
model = 'vps.VPS' model = 'vps.VPS'
resource = ServiceMonitor.TRAFFIC resource = ServiceMonitor.TRAFFIC
def process(self, line, obj):
""" diff with last stored value """
object_id, value = line.split()
last = self.get_last_data(object_id)
if not last or last.value > value:
return object_id, value
return object_id, value-last.value
def monitor(self, container):
""" Get OpenVZ container traffic on a Proxmox +2.0 cluster """
context = self.get_context(container)
self.append(
"CONF=$(grep -r 'HOSTNAME=\"%(hostname)s\"' /etc/pve/nodes/*/openvz/*.conf)" % context)
self.append('NODE=$(echo "${CONF}" | cut -d"/" -f5)')
self.append('CTID=$(echo "${CONF}" | cut -d"/" -f7 | cur -d"\." -f1)')
self.append(
"ssh root@${NODE} vzctl exec ${CTID} cat /proc/net/dev \\\n"
" | grep venet0 \\\n"
" | awk -F: '{print $2}' \\\n"
" | awk '{print $1+$9}'")
def get_context(self, container):
return {
'hostname': container.hostname,
}

View File

@ -219,9 +219,11 @@ class Apache2Traffic(ServiceMonitor):
}' %(log_file)s || echo 0; } | xargs echo %(object_id)s """ % context) }' %(log_file)s || echo 0; } | xargs echo %(object_id)s """ % context)
def get_context(self, site): def get_context(self, site):
last_date = timezone.localtime(self.get_last_date(site.pk))
current_date = timezone.localtime(self.current_date)
return { return {
'log_file': os.path.join(settings.WEBSITES_BASE_APACHE_LOGS, site.unique_name), 'log_file': os.path.join(settings.WEBSITES_BASE_APACHE_LOGS, site.unique_name),
'last_date': timezone.localtime(self.get_last_date(site)).strftime("%Y%m%d%H%M%S"), 'last_date': last_date.strftime("%Y%m%d%H%M%S"),
'current_date': timezone.localtime(self.get_current_date()).strftime("%Y%m%d%H%M%S"), 'current_date': current_date.strftime("%Y%m%d%H%M%S"),
'object_id': site.pk, 'object_id': site.pk,
} }

View File

@ -1,35 +0,0 @@
from __future__ import absolute_import
from datetime import datetime
from django.utils.timesince import timesince as django_timesince
from django.utils.timezone import is_aware, utc
# TODO deprecate in favour of celery timesince
def timesince(d, now=None, reversed=False):
""" Hack to provide second precision under 2 minutes """
if not now:
now = datetime.now(utc if is_aware(d) else None)
delta = (d - now) if reversed else (now - d)
s = django_timesince(d, now=now, reversed=reversed)
if len(s.split(' ')) is 2:
count, name = s.split(' ')
if name in ['minutes', 'minute']:
seconds = delta.seconds % 60
extension = '%(number)d %(type)s' % {'number': seconds, 'type': 'seconds'}
if int(count) is 0:
return extension
elif int(count) < 2:
s += ', %s' % extension
return s
def timeuntil(d, now=None):
"""
Like timesince, but returns a string measuring the time until
the given time.
"""
return timesince(d, now, reversed=True)