2014-11-18 18:41:44 +00:00
|
|
|
from django.conf.urls import patterns, url
|
2014-07-10 15:19:06 +00:00
|
|
|
from django.contrib import admin, messages
|
2014-11-13 15:34:00 +00:00
|
|
|
from django.contrib.admin.utils import unquote
|
2015-05-01 17:23:22 +00:00
|
|
|
from django.contrib import contenttypes
|
2014-10-27 13:29:02 +00:00
|
|
|
from django.core.urlresolvers import reverse
|
2014-11-18 18:41:44 +00:00
|
|
|
from django.shortcuts import redirect
|
2014-07-08 15:19:15 +00:00
|
|
|
from django.utils.functional import cached_property
|
2014-11-13 15:34:00 +00:00
|
|
|
from django.utils.translation import ungettext, ugettext, ugettext_lazy as _
|
2014-07-08 15:19:15 +00:00
|
|
|
|
2014-07-10 15:19:06 +00:00
|
|
|
from orchestra.admin import ExtendedModelAdmin
|
2014-07-22 21:47:01 +00:00
|
|
|
from orchestra.admin.utils import insertattr, get_modeladmin, admin_link, admin_date
|
2015-04-05 10:46:24 +00:00
|
|
|
from orchestra.contrib.orchestration.models import Route
|
2014-07-10 10:03:22 +00:00
|
|
|
from orchestra.core import services
|
2015-05-06 19:30:13 +00:00
|
|
|
from orchestra.utils.db import database_ready
|
2015-04-16 13:15:21 +00:00
|
|
|
from orchestra.utils.functional import cached
|
2014-07-08 15:19:15 +00:00
|
|
|
|
2014-10-27 13:29:02 +00:00
|
|
|
from .actions import run_monitor
|
2014-07-08 15:19:15 +00:00
|
|
|
from .forms import ResourceForm
|
2014-07-09 16:17:43 +00:00
|
|
|
from .models import Resource, ResourceData, MonitorData
|
2014-07-08 15:19:15 +00:00
|
|
|
|
|
|
|
|
2014-07-10 15:19:06 +00:00
|
|
|
class ResourceAdmin(ExtendedModelAdmin):
|
2014-07-08 15:19:15 +00:00
|
|
|
list_display = (
|
2015-04-08 14:41:09 +00:00
|
|
|
'id', 'verbose_name', 'content_type', 'aggregation', 'on_demand',
|
2014-10-24 14:19:34 +00:00
|
|
|
'default_allocation', 'unit', 'crontab', 'is_active'
|
2014-07-08 15:19:15 +00:00
|
|
|
)
|
2014-10-24 14:19:34 +00:00
|
|
|
list_display_links = ('id', 'verbose_name')
|
|
|
|
list_editable = ('default_allocation', 'crontab', 'is_active',)
|
2015-04-21 14:14:07 +00:00
|
|
|
list_filter = (
|
|
|
|
('content_type', admin.RelatedOnlyFieldListFilter), 'aggregation', 'on_demand',
|
|
|
|
'disable_trigger'
|
|
|
|
)
|
2014-07-10 15:19:06 +00:00
|
|
|
fieldsets = (
|
|
|
|
(None, {
|
2015-04-08 14:41:09 +00:00
|
|
|
'fields': ('verbose_name', 'name', 'content_type', 'aggregation'),
|
2014-07-10 15:19:06 +00:00
|
|
|
}),
|
|
|
|
(_("Configuration"), {
|
2014-10-23 15:38:46 +00:00
|
|
|
'fields': ('unit', 'scale', 'on_demand', 'default_allocation', 'disable_trigger',
|
|
|
|
'is_active'),
|
2014-07-10 15:19:06 +00:00
|
|
|
}),
|
|
|
|
(_("Monitoring"), {
|
|
|
|
'fields': ('monitors', 'crontab'),
|
|
|
|
}),
|
|
|
|
)
|
2014-11-20 16:48:50 +00:00
|
|
|
actions = (run_monitor,)
|
|
|
|
change_view_actions = actions
|
2014-11-13 15:34:00 +00:00
|
|
|
change_readonly_fields = ('name', 'content_type')
|
2014-10-24 14:19:34 +00:00
|
|
|
prepopulated_fields = {'name': ('verbose_name',)}
|
2015-04-01 15:49:21 +00:00
|
|
|
list_select_related = ('content_type', 'crontab',)
|
2014-07-10 15:19:06 +00:00
|
|
|
|
2014-11-13 15:34:00 +00:00
|
|
|
def change_view(self, request, object_id, form_url='', extra_context=None):
|
|
|
|
""" Remaind user when monitor routes are not configured """
|
|
|
|
if request.method == 'GET':
|
|
|
|
resource = self.get_object(request, unquote(object_id))
|
|
|
|
backends = Route.objects.values_list('backend', flat=True)
|
|
|
|
not_routed = []
|
|
|
|
for monitor in resource.monitors:
|
|
|
|
if monitor not in backends:
|
|
|
|
not_routed.append(monitor)
|
|
|
|
if not_routed:
|
|
|
|
messages.warning(request, ungettext(
|
|
|
|
_("%(not_routed)s monitor doesn't have any configured route."),
|
|
|
|
_("%(not_routed)s monitors don't have any configured route."),
|
|
|
|
len(not_routed),
|
|
|
|
) % {
|
|
|
|
'not_routed': ', '.join(not_routed)
|
|
|
|
})
|
2014-11-20 16:48:50 +00:00
|
|
|
return super(ResourceAdmin, self).change_view(request, object_id, form_url=form_url,
|
|
|
|
extra_context=extra_context)
|
2014-11-13 15:34:00 +00:00
|
|
|
|
2014-07-08 15:19:15 +00:00
|
|
|
def save_model(self, request, obj, form, change):
|
|
|
|
super(ResourceAdmin, self).save_model(request, obj, form, change)
|
|
|
|
model = obj.content_type.model_class()
|
2014-07-18 15:32:27 +00:00
|
|
|
modeladmin = type(get_modeladmin(model))
|
2014-07-08 15:19:15 +00:00
|
|
|
resources = obj.content_type.resource_set.filter(is_active=True)
|
|
|
|
inlines = []
|
|
|
|
for inline in modeladmin.inlines:
|
2014-07-09 16:17:43 +00:00
|
|
|
if inline.model is ResourceData:
|
2014-07-08 15:19:15 +00:00
|
|
|
inline = resource_inline_factory(resources)
|
|
|
|
inlines.append(inline)
|
|
|
|
modeladmin.inlines = inlines
|
2014-07-10 10:03:22 +00:00
|
|
|
|
|
|
|
def formfield_for_dbfield(self, db_field, **kwargs):
|
|
|
|
""" filter service content_types """
|
|
|
|
if db_field.name == 'content_type':
|
2014-07-21 12:20:04 +00:00
|
|
|
models = [ model._meta.model_name for model in services.get() ]
|
2014-07-10 10:03:22 +00:00
|
|
|
kwargs['queryset'] = db_field.rel.to.objects.filter(model__in=models)
|
|
|
|
return super(ResourceAdmin, self).formfield_for_dbfield(db_field, **kwargs)
|
2014-07-08 15:19:15 +00:00
|
|
|
|
|
|
|
|
2014-10-27 13:29:02 +00:00
|
|
|
class ResourceDataAdmin(ExtendedModelAdmin):
|
2014-07-16 15:20:16 +00:00
|
|
|
list_display = (
|
2015-03-02 12:07:27 +00:00
|
|
|
'id', 'resource_link', 'content_object_link', 'allocated', 'display_used', 'display_unit',
|
2014-10-27 13:29:02 +00:00
|
|
|
'display_updated'
|
2014-07-16 15:20:16 +00:00
|
|
|
)
|
2014-07-08 15:19:15 +00:00
|
|
|
list_filter = ('resource',)
|
2014-10-27 13:29:02 +00:00
|
|
|
fields = (
|
2015-03-02 12:07:27 +00:00
|
|
|
'resource_link', 'content_type', 'content_object_link', 'display_updated', 'display_used',
|
2014-10-27 13:29:02 +00:00
|
|
|
'allocated', 'display_unit'
|
|
|
|
)
|
2014-11-17 14:17:33 +00:00
|
|
|
search_fields = ('object_id',)
|
2014-11-13 15:34:00 +00:00
|
|
|
readonly_fields = fields
|
2014-10-27 13:29:02 +00:00
|
|
|
actions = (run_monitor,)
|
|
|
|
change_view_actions = actions
|
|
|
|
ordering = ('-updated_at',)
|
2014-11-18 18:41:44 +00:00
|
|
|
list_select_related = ('resource__content_type',)
|
2014-11-20 16:48:50 +00:00
|
|
|
list_prefetch_related = ('content_object',)
|
2014-11-13 15:34:00 +00:00
|
|
|
|
2014-09-28 12:28:57 +00:00
|
|
|
resource_link = admin_link('resource')
|
2014-07-21 15:43:36 +00:00
|
|
|
content_object_link = admin_link('content_object')
|
2014-11-20 15:34:59 +00:00
|
|
|
content_object_link.admin_order_field = None
|
2014-10-27 13:29:02 +00:00
|
|
|
display_updated = admin_date('updated_at', short_description=_("Updated"))
|
|
|
|
|
2014-11-18 18:41:44 +00:00
|
|
|
def get_urls(self):
|
|
|
|
"""Returns the additional urls for the change view links"""
|
|
|
|
urls = super(ResourceDataAdmin, self).get_urls()
|
|
|
|
admin_site = self.admin_site
|
|
|
|
opts = self.model._meta
|
|
|
|
return patterns('',
|
|
|
|
url('^(\d+)/used-monitordata/$',
|
|
|
|
admin_site.admin_view(self.used_monitordata_view),
|
|
|
|
name='%s_%s_used_monitordata' % (opts.app_label, opts.model_name)
|
|
|
|
)
|
|
|
|
) + urls
|
|
|
|
|
2014-10-27 13:29:02 +00:00
|
|
|
def display_unit(self, data):
|
|
|
|
return data.unit
|
|
|
|
display_unit.short_description = _("Unit")
|
|
|
|
display_unit.admin_order_field = 'resource__unit'
|
2014-11-13 15:34:00 +00:00
|
|
|
|
|
|
|
def display_used(self, data):
|
2015-04-09 14:32:10 +00:00
|
|
|
if data.used is None:
|
2014-11-13 15:34:00 +00:00
|
|
|
return ''
|
2014-11-18 18:41:44 +00:00
|
|
|
url = reverse('admin:resources_resourcedata_used_monitordata', args=(data.pk,))
|
|
|
|
return '<a href="%s">%s</a>' % (url, data.used)
|
|
|
|
display_used.short_description = _("Used")
|
|
|
|
display_used.admin_order_field = 'used'
|
|
|
|
display_used.allow_tags = True
|
|
|
|
|
|
|
|
def has_add_permission(self, *args, **kwargs):
|
|
|
|
return False
|
|
|
|
|
|
|
|
def used_monitordata_view(self, request, object_id):
|
|
|
|
"""
|
|
|
|
Does the redirect on a separated view for performance reassons
|
|
|
|
(calculate this on a changelist is expensive)
|
|
|
|
"""
|
|
|
|
data = self.get_object(request, object_id)
|
2014-11-13 15:34:00 +00:00
|
|
|
ids = []
|
|
|
|
for dataset in data.get_monitor_datasets():
|
|
|
|
if isinstance(dataset, MonitorData):
|
|
|
|
ids.append(dataset.id)
|
|
|
|
else:
|
|
|
|
ids += dataset.values_list('id', flat=True)
|
|
|
|
url = reverse('admin:resources_monitordata_changelist')
|
|
|
|
url += '?id__in=%s' % ','.join(map(str, ids))
|
2014-11-18 18:41:44 +00:00
|
|
|
return redirect(url)
|
2014-07-08 15:19:15 +00:00
|
|
|
|
|
|
|
|
2014-10-27 13:29:02 +00:00
|
|
|
class MonitorDataAdmin(ExtendedModelAdmin):
|
|
|
|
list_display = ('id', 'monitor', 'display_created', 'value', 'content_object_link')
|
2014-07-08 15:19:15 +00:00
|
|
|
list_filter = ('monitor',)
|
2014-10-27 13:29:02 +00:00
|
|
|
add_fields = ('monitor', 'content_type', 'object_id', 'created_at', 'value')
|
|
|
|
fields = ('monitor', 'content_type', 'content_object_link', 'display_created', 'value')
|
|
|
|
change_readonly_fields = fields
|
2014-07-11 21:09:17 +00:00
|
|
|
|
2014-07-21 15:43:36 +00:00
|
|
|
content_object_link = admin_link('content_object')
|
2014-10-27 13:29:02 +00:00
|
|
|
display_created = admin_date('created_at', short_description=_("Created"))
|
2014-09-10 16:53:09 +00:00
|
|
|
|
|
|
|
def get_queryset(self, request):
|
|
|
|
queryset = super(MonitorDataAdmin, self).get_queryset(request)
|
|
|
|
return queryset.prefetch_related('content_object')
|
2014-07-08 15:19:15 +00:00
|
|
|
|
|
|
|
|
|
|
|
admin.site.register(Resource, ResourceAdmin)
|
2014-07-09 16:17:43 +00:00
|
|
|
admin.site.register(ResourceData, ResourceDataAdmin)
|
2014-07-08 15:19:15 +00:00
|
|
|
admin.site.register(MonitorData, MonitorDataAdmin)
|
|
|
|
|
|
|
|
|
|
|
|
# Mokey-patching
|
|
|
|
|
|
|
|
def resource_inline_factory(resources):
|
2015-05-01 18:18:13 +00:00
|
|
|
class ResourceInlineFormSet(contenttypes.forms.BaseGenericInlineFormSet):
|
2014-07-22 21:47:01 +00:00
|
|
|
def total_form_count(self, resources=resources):
|
2015-04-16 13:15:21 +00:00
|
|
|
return len(resources)
|
2015-03-20 15:13:08 +00:00
|
|
|
|
2015-04-16 13:15:21 +00:00
|
|
|
@cached
|
2015-03-20 15:13:08 +00:00
|
|
|
def get_queryset(self):
|
2015-03-23 15:36:51 +00:00
|
|
|
""" Filter disabled resources """
|
2015-03-20 15:13:08 +00:00
|
|
|
queryset = super(ResourceInlineFormSet, self).get_queryset()
|
2015-04-16 13:15:21 +00:00
|
|
|
return queryset.filter(resource__is_active=True).select_related('resource')
|
2014-07-08 15:19:15 +00:00
|
|
|
|
|
|
|
@cached_property
|
2014-07-22 21:47:01 +00:00
|
|
|
def forms(self, resources=resources):
|
2014-07-08 15:19:15 +00:00
|
|
|
forms = []
|
2014-07-22 21:47:01 +00:00
|
|
|
resources_copy = list(resources)
|
2015-03-20 15:13:08 +00:00
|
|
|
# Remove queryset disabled objects
|
2015-03-23 15:36:51 +00:00
|
|
|
queryset = [data for data in self.get_queryset() if data.resource in resources]
|
2014-10-27 13:29:02 +00:00
|
|
|
if self.instance.pk:
|
|
|
|
# Create missing resource data
|
|
|
|
queryset_resources = [data.resource for data in queryset]
|
|
|
|
for resource in resources:
|
|
|
|
if resource not in queryset_resources:
|
2015-03-20 15:13:08 +00:00
|
|
|
kwargs = {
|
|
|
|
'content_object': self.instance,
|
|
|
|
}
|
|
|
|
if resource.default_allocation:
|
|
|
|
kwargs['allocated'] = resource.default_allocation
|
|
|
|
data = resource.dataset.create(**kwargs)
|
2014-10-27 13:29:02 +00:00
|
|
|
queryset.append(data)
|
|
|
|
# Existing dataset
|
|
|
|
for i, data in enumerate(queryset):
|
2014-07-22 21:47:01 +00:00
|
|
|
forms.append(self._construct_form(i, resource=data.resource))
|
2015-03-20 15:13:08 +00:00
|
|
|
try:
|
|
|
|
resources_copy.remove(data.resource)
|
|
|
|
except ValueError:
|
|
|
|
pass
|
2014-10-27 13:29:02 +00:00
|
|
|
# Missing dataset
|
|
|
|
for i, resource in enumerate(resources_copy, len(queryset)):
|
2014-07-08 15:19:15 +00:00
|
|
|
forms.append(self._construct_form(i, resource=resource))
|
|
|
|
return forms
|
|
|
|
|
2015-05-01 18:18:13 +00:00
|
|
|
class ResourceInline(contenttypes.admin.GenericTabularInline):
|
2014-07-09 16:17:43 +00:00
|
|
|
model = ResourceData
|
2014-07-08 15:19:15 +00:00
|
|
|
verbose_name_plural = _("resources")
|
|
|
|
form = ResourceForm
|
|
|
|
formset = ResourceInlineFormSet
|
2014-07-10 17:34:23 +00:00
|
|
|
can_delete = False
|
2014-07-16 15:20:16 +00:00
|
|
|
fields = (
|
2014-10-27 13:29:02 +00:00
|
|
|
'verbose_name', 'display_used', 'display_updated', 'allocated', 'unit',
|
2014-07-16 15:20:16 +00:00
|
|
|
)
|
2014-10-27 13:29:02 +00:00
|
|
|
readonly_fields = ('display_used', 'display_updated')
|
2014-07-08 15:19:15 +00:00
|
|
|
|
|
|
|
class Media:
|
|
|
|
css = {
|
|
|
|
'all': ('orchestra/css/hide-inline-id.css',)
|
|
|
|
}
|
|
|
|
|
2014-09-26 15:05:20 +00:00
|
|
|
display_updated = admin_date('updated_at', default=_("Never"))
|
2014-07-22 21:47:01 +00:00
|
|
|
|
2014-10-27 13:29:02 +00:00
|
|
|
def display_used(self, data):
|
|
|
|
update_link = ''
|
|
|
|
if data.pk:
|
|
|
|
url = reverse('admin:resources_resourcedata_monitor', args=(data.pk,))
|
|
|
|
update_link = '<a href="%s"><strong>%s</strong></a>' % (url, ugettext("Update"))
|
|
|
|
if data.used is not None:
|
|
|
|
return '%s %s %s' % (data.used, data.resource.unit, update_link)
|
|
|
|
return _("Unknonw %s") % update_link
|
|
|
|
display_used.short_description = _("Used")
|
2015-04-01 15:49:21 +00:00
|
|
|
display_used.allow_tags = True
|
2014-10-27 13:29:02 +00:00
|
|
|
|
2014-07-08 15:19:15 +00:00
|
|
|
def has_add_permission(self, *args, **kwargs):
|
|
|
|
""" Hidde add another """
|
|
|
|
return False
|
2014-10-27 13:29:02 +00:00
|
|
|
|
2014-07-08 15:19:15 +00:00
|
|
|
return ResourceInline
|
|
|
|
|
2014-10-04 14:19:29 +00:00
|
|
|
|
|
|
|
def insert_resource_inlines():
|
2014-10-07 13:08:59 +00:00
|
|
|
# Clean previous state
|
|
|
|
for related in Resource._related:
|
|
|
|
modeladmin = get_modeladmin(related)
|
|
|
|
modeladmin_class = type(modeladmin)
|
|
|
|
for inline in getattr(modeladmin_class, 'inlines', []):
|
|
|
|
if inline.__name__ == 'ResourceInline':
|
|
|
|
modeladmin_class.inlines.remove(inline)
|
2015-03-20 15:13:08 +00:00
|
|
|
resources = Resource.objects.filter(is_active=True)
|
2015-04-02 16:14:55 +00:00
|
|
|
for ct, resources in resources.group_by('content_type').items():
|
2014-07-08 15:19:15 +00:00
|
|
|
inline = resource_inline_factory(resources)
|
2014-07-25 13:27:31 +00:00
|
|
|
model = ct.model_class()
|
2014-10-07 13:08:59 +00:00
|
|
|
insertattr(model, 'inlines', inline)
|
2014-10-09 17:04:12 +00:00
|
|
|
|
2014-10-07 13:08:59 +00:00
|
|
|
|
|
|
|
if database_ready():
|
|
|
|
insert_resource_inlines()
|