Openvz traffic0
This commit is contained in:
parent
bc398644b7
commit
121e1a4b1c
|
@ -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"),
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
}
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
|
Loading…
Reference in New Issue