Refactores plugins, fixes on mailing contacts and improved resource validation
This commit is contained in:
parent
e962e5d7b2
commit
4732925f63
10
TODO.md
10
TODO.md
|
@ -149,20 +149,16 @@
|
|||
|
||||
* Resource used_list_display=True, allocated_list_displat=True, allow resources to show up on list_display
|
||||
|
||||
* Move plugins back from apps to orchestra main app
|
||||
|
||||
* BackendLog.updated_at (tasks that run over several minutes when finished they do not appear first on the changelist) (like celery tasks.when)
|
||||
|
||||
* Validate a model path exists between resource.content_type and backend.model
|
||||
|
||||
* Periodic task for cleaning old monitoring data
|
||||
|
||||
* Generate reports of Account contracted services
|
||||
|
||||
* Create an admin service_view with icons (like SaaS app)
|
||||
|
||||
* Fix ftp traffic
|
||||
|
||||
* Resource graph for each related object
|
||||
|
||||
* contacts filter by email_usage fix exact for contains
|
||||
* Rename apache logs ending on .log in order to logrotate easily
|
||||
|
||||
* SaaS wordpress multiple blogs per user? separate users from sites?
|
||||
|
|
|
@ -3,8 +3,9 @@ from django.core.mail import send_mass_mail
|
|||
from django.shortcuts import render
|
||||
from django.utils.translation import ungettext, ugettext_lazy as _
|
||||
|
||||
from orchestra.admin.utils import change_url
|
||||
from .. import settings
|
||||
|
||||
from .utils import change_url
|
||||
from .forms import SendEmailForm
|
||||
|
||||
|
||||
|
@ -13,18 +14,19 @@ class SendEmail(object):
|
|||
short_description = _("Send email")
|
||||
form = SendEmailForm
|
||||
template = 'admin/orchestra/generic_confirmation.html'
|
||||
default_from = settings.ORCHESTRA_DEFAULT_SUPPORT_FROM_EMAIL
|
||||
__name__ = 'semd_email'
|
||||
|
||||
def __call__(self, modeladmin, request, queryset):
|
||||
""" make this monster behave like a function """
|
||||
self.modeladmin = modeladmin
|
||||
self.queryset = queryset
|
||||
opts = modeladmin.model._meta
|
||||
app_label = opts.app_label
|
||||
self.opts = modeladmin.model._meta
|
||||
app_label = self.opts.app_label
|
||||
self.context = {
|
||||
'action_name': _("Send email"),
|
||||
'action_value': self.__name__,
|
||||
'opts': opts,
|
||||
'opts': self.opts,
|
||||
'app_label': app_label,
|
||||
'queryset': queryset,
|
||||
'action_checkbox_name': admin.helpers.ACTION_CHECKBOX_NAME,
|
||||
|
@ -34,14 +36,17 @@ class SendEmail(object):
|
|||
def write_email(self, request):
|
||||
if not request.user.is_superuser:
|
||||
raise PermissionDenied
|
||||
form = self.form()
|
||||
initial={
|
||||
'email_from': self.default_from,
|
||||
'to': ' '.join(self.queryset.values_list('email', flat=True))
|
||||
}
|
||||
form = self.form(initial=initial)
|
||||
if request.POST.get('post'):
|
||||
form = self.form(request.POST)
|
||||
form = self.form(request.POST, initial=initial)
|
||||
if form.is_valid():
|
||||
options = {
|
||||
'email_from': form.cleaned_data['email_from'],
|
||||
'cc': form.cleaned_data['cc'],
|
||||
'bcc': form.cleaned_data['bcc'],
|
||||
'extra_to': form.cleaned_data['extra_to'],
|
||||
'subject': form.cleaned_data['subject'],
|
||||
'message': form.cleaned_data['message'],
|
||||
|
||||
|
@ -50,7 +55,7 @@ class SendEmail(object):
|
|||
opts = self.modeladmin.model._meta
|
||||
app_label = opts.app_label
|
||||
self.context.update({
|
||||
'title': _("Send e-mail to contacts"),
|
||||
'title': _("Send e-mail to %s") % self.opts.verbose_name_plural,
|
||||
'content_title': "",
|
||||
'form': form,
|
||||
'submit_value': _("Continue"),
|
||||
|
@ -61,31 +66,36 @@ class SendEmail(object):
|
|||
def confirm_email(self, request, **options):
|
||||
num = len(self.queryset)
|
||||
email_from = options['email_from']
|
||||
bcc = options['bcc']
|
||||
to = options['cc']
|
||||
extra_to = options['extra_to']
|
||||
subject = options['subject']
|
||||
message = options['message']
|
||||
# The user has already confirmed
|
||||
if request.POST.get('post') == 'email_confirmation':
|
||||
emails = []
|
||||
for contact in self.queryset.all():
|
||||
to.append(contact.email)
|
||||
send_mass_mail(subject, message, email_from, to, bcc)
|
||||
emails.append((subject, message, email_from, [contact.email]))
|
||||
if extra_to:
|
||||
emails.append((subject, message, email_from, extra_to))
|
||||
send_mass_mail(emails)
|
||||
msg = ungettext(
|
||||
_("Message has been sent to %s.") % str(contact),
|
||||
_("Message has been sent to %i contacts.") % num,
|
||||
_("Message has been sent to %i %s.") % (num, self.opts.verbose_name_plural),
|
||||
num
|
||||
)
|
||||
self.modeladmin.message_user(request, msg)
|
||||
return None
|
||||
|
||||
form = self.form(initial={
|
||||
'email_from': email_from,
|
||||
'extra_to': ', '.join(extra_to),
|
||||
'subject': subject,
|
||||
'message': message
|
||||
})
|
||||
self.context.update({
|
||||
'title': _("Are you sure?"),
|
||||
'content_message': _(
|
||||
"Are you sure you want to send the following message to the following contacts?"),
|
||||
"Are you sure you want to send the following message to the following %s?"
|
||||
) % self.opts.verbose_name_plural,
|
||||
'display_objects': ["%s (%s)" % (contact, contact.email) for contact in self.queryset],
|
||||
'form': form,
|
||||
'subject': subject,
|
|
@ -2,10 +2,13 @@ from functools import partial
|
|||
|
||||
from django import forms
|
||||
from django.contrib.admin import helpers
|
||||
from django.core import validators
|
||||
from django.forms.models import modelformset_factory, BaseModelFormSet
|
||||
from django.template import Template, Context
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from orchestra.forms.widgets import ShowTextWidget, ReadOnlyWidget
|
||||
|
||||
from ..core.validators import validate_password
|
||||
|
||||
|
||||
|
@ -129,3 +132,39 @@ class AdminPasswordChangeForm(forms.Form):
|
|||
return ['password']
|
||||
changed_data = property(_get_changed_data)
|
||||
|
||||
|
||||
class SendEmailForm(forms.Form):
|
||||
email_from = forms.EmailField(label=_("From"),
|
||||
widget=forms.TextInput(attrs={'size':'118'}))
|
||||
to = forms.CharField(label="To", required=False,
|
||||
widget=ShowTextWidget())
|
||||
extra_to = forms.CharField(label="To (extra)", required=False,
|
||||
widget=forms.TextInput(attrs={'size':'118'}))
|
||||
subject = forms.CharField(label=_("Subject"),
|
||||
widget=forms.TextInput(attrs={'size':'118'}))
|
||||
message = forms.CharField(label=_("Message"),
|
||||
widget=forms.Textarea(attrs={'cols': 118, 'rows': 15}))
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(SendEmailForm, self).__init__(*args, **kwargs)
|
||||
initial = kwargs.get('initial')
|
||||
if 'to' in initial:
|
||||
self.fields['to'].widget = ReadOnlyWidget(initial['to'])
|
||||
else:
|
||||
self.fields.pop('to')
|
||||
|
||||
def clean_comma_separated_emails(self, value):
|
||||
clean_value = []
|
||||
for email in value.split(','):
|
||||
email = email.strip()
|
||||
if email:
|
||||
try:
|
||||
validators.validate_email(email)
|
||||
except validators.ValidationError:
|
||||
raise validators.ValidationError("Comma separated email addresses.")
|
||||
clean_value.append(email)
|
||||
return clean_value
|
||||
|
||||
def clean_extra_to(self):
|
||||
extra_to = self.cleaned_data['extra_to']
|
||||
return self.clean_comma_separated_emails(extra_to)
|
||||
|
|
|
@ -39,13 +39,22 @@ list_contacts.verbose_name = _("List contacts")
|
|||
|
||||
def service_report(modeladmin, request, queryset):
|
||||
accounts = []
|
||||
for account in queryset:
|
||||
fields = []
|
||||
# First we get related manager names to fire a prefetch related
|
||||
for name, field in queryset.model._meta._name_map.iteritems():
|
||||
model = field[0].model
|
||||
if model in services.get() and model != queryset.model:
|
||||
fields.append((model, name))
|
||||
sorted(fields, key=lambda i: i[0]._meta.verbose_name_plural.lower())
|
||||
fields = [field for model, field in fields]
|
||||
|
||||
for account in queryset.prefetch_related(*fields):
|
||||
items = []
|
||||
for service in services.get():
|
||||
if service != type(account):
|
||||
items.append((service._meta, service.objects.filter(account=account)))
|
||||
sorted(items, key=lambda i: i[0].verbose_name_plural.lower())
|
||||
for field in fields:
|
||||
related_manager = getattr(account, field)
|
||||
items.append((related_manager.model._meta, related_manager.all()))
|
||||
accounts.append((account, items))
|
||||
|
||||
context = {
|
||||
'accounts': accounts,
|
||||
'date': timezone.now().today()
|
||||
|
|
|
@ -13,6 +13,7 @@ from django.utils.six.moves.urllib.parse import parse_qsl
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from orchestra.admin import ExtendedModelAdmin, ChangePasswordAdminMixin
|
||||
from orchestra.admin.actions import SendEmail
|
||||
from orchestra.admin.utils import wrap_admin_view, admin_link, set_url_query, change_url
|
||||
from orchestra.core import services, accounts
|
||||
from orchestra.forms import UserChangeForm
|
||||
|
@ -61,7 +62,7 @@ class AccountAdmin(ChangePasswordAdminMixin, auth.UserAdmin, ExtendedModelAdmin)
|
|||
filter_horizontal = ()
|
||||
change_readonly_fields = ('username', 'main_systemuser_link')
|
||||
change_form_template = 'admin/accounts/account/change_form.html'
|
||||
actions = [disable, list_contacts, service_report]
|
||||
actions = [disable, list_contacts, service_report, SendEmail()]
|
||||
change_view_actions = [disable, service_report]
|
||||
list_select_related = ('billcontact',)
|
||||
ordering = ()
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{% load utils %}
|
||||
{% load utils i18n %}
|
||||
<html>
|
||||
<head>
|
||||
<title>{% block title %}Service Report{% endblock %}</title>
|
||||
<title>{% block title %}Account service report{% endblock %}</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||
{% block head %}{% endblock %}
|
||||
<style type="text/css">
|
||||
|
@ -11,11 +11,11 @@
|
|||
float: none !important;
|
||||
font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif;
|
||||
font-size: 12px;
|
||||
color: #2E2E2E;
|
||||
color: #444;
|
||||
}
|
||||
#date {
|
||||
float: right;
|
||||
color: #666;
|
||||
color: rgb(102, 102, 102);
|
||||
}
|
||||
.account-content {
|
||||
margin: 0px 0px 40px 20px;
|
||||
|
@ -23,27 +23,38 @@
|
|||
.item-title {
|
||||
list-style-type: none;
|
||||
font-weight: bold;
|
||||
color: #666;
|
||||
}
|
||||
.items-ul {
|
||||
padding: 0px;
|
||||
margin: 5px 0px 10px 20px;
|
||||
}
|
||||
.related {
|
||||
list-style: disc;
|
||||
}
|
||||
hr {
|
||||
margin-top: -9px;
|
||||
}
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: rgb(91, 128, 178);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="date">Service report generated on {{ date | date }}</div>
|
||||
<div id="date">{% trans "Service report generated on" %} {{ date | date }}</div>
|
||||
{% for account, items in accounts %}
|
||||
<h3>{{ account.get_full_name }} ({{ account.username }})</h3>
|
||||
<h3>{{ account.get_full_name }} - <a href="{{ account|admin_url }}">{{ account.username }}</a></h3>
|
||||
<hr>
|
||||
<div class="account-content">
|
||||
{{ account.get_type_display }} account registered on {{ account.date_joined | date }}<br>
|
||||
{{ account.get_type_display }} {% trans "account registered on" %} {{ account.date_joined | date }}<br>
|
||||
<ul class="items-ul">
|
||||
{% for opts, related in items %}
|
||||
<li class="item-title">{{ opts.verbose_name_plural|capfirst }}</li>
|
||||
<ul>
|
||||
{% for obj in related %}
|
||||
<li>{{ obj }}{% if not obj|isactive %} (disabled){% endif %}</li>
|
||||
<li class="related"><a href="{{ obj|admin_url }}">{{ obj }}</a>{% if not obj|isactive %} ({% trans "disabled" %}){% endif %}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endfor %}
|
||||
|
|
|
@ -3,11 +3,12 @@ from django.contrib import admin
|
|||
from django.utils.translation import ugettext, ugettext_lazy as _
|
||||
|
||||
from orchestra.admin import AtLeastOneRequiredInlineFormSet, ExtendedModelAdmin
|
||||
from orchestra.admin.actions import SendEmail
|
||||
from orchestra.admin.utils import insertattr, admin_link, change_url
|
||||
from orchestra.apps.accounts.admin import AccountAdmin, AccountAdminMixin
|
||||
from orchestra.forms.widgets import paddingCheckboxSelectMultiple
|
||||
|
||||
from .actions import SendEmail
|
||||
from .filters import EmailUsageListFilter
|
||||
from .models import Contact
|
||||
|
||||
|
||||
|
@ -16,7 +17,7 @@ class ContactAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
|||
'dispaly_name', 'email', 'phone', 'phone2', 'country', 'account_link'
|
||||
)
|
||||
# TODO email usage custom filter contains
|
||||
list_filter = ('email_usage',)
|
||||
list_filter = (EmailUsageListFilter,)
|
||||
search_fields = (
|
||||
'account__username', 'account__full_name', 'short_name', 'full_name', 'phone', 'phone2',
|
||||
'email'
|
||||
|
|
16
orchestra/apps/contacts/filters.py
Normal file
16
orchestra/apps/contacts/filters.py
Normal file
|
@ -0,0 +1,16 @@
|
|||
from django.contrib.admin import SimpleListFilter
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from .models import Contact
|
||||
|
||||
|
||||
class EmailUsageListFilter(SimpleListFilter):
|
||||
title = _("email usages")
|
||||
parameter_name = 'email_usages'
|
||||
|
||||
def lookups(self, request, model_admin):
|
||||
return Contact.email_usage.field.choices
|
||||
|
||||
def queryset(self, request, queryset):
|
||||
value = self.value().split(',')
|
||||
return queryset.filter(email_usages=value)
|
|
@ -1,36 +0,0 @@
|
|||
from django import forms
|
||||
from django.core import validators
|
||||
from django.utils.translation import ungettext, ugettext_lazy as _
|
||||
|
||||
from orchestra.forms.widgets import ShowTextWidget
|
||||
|
||||
from . import settings
|
||||
|
||||
|
||||
class SendEmailForm(forms.Form):
|
||||
email_from = forms.EmailField(label=_("From"),
|
||||
initial=settings.CONTACTS_DEFAULT_FROM_EMAIL,
|
||||
widget=forms.TextInput(attrs={'size':'118'}))
|
||||
cc = forms.CharField(label="CC", required=False,
|
||||
widget=forms.TextInput(attrs={'size':'118'}))
|
||||
bcc = forms.CharField(label="BCC", required=False,
|
||||
widget=forms.TextInput(attrs={'size':'118'}))
|
||||
subject = forms.CharField(label=_("Subject"),
|
||||
widget=forms.TextInput(attrs={'size':'118'}))
|
||||
message = forms.CharField(label=_("Message"),
|
||||
widget=forms.Textarea(attrs={'cols': 118, 'rows': 15}))
|
||||
|
||||
def clean_space_separated_emails(self, value):
|
||||
value = value.split()
|
||||
for email in value:
|
||||
try:
|
||||
validators.validate_email(email)
|
||||
except validators.ValidationError:
|
||||
raise validators.ValidationError("Space separated emails.")
|
||||
return value
|
||||
|
||||
def clean_cc(self):
|
||||
return self.clean_space_separated_emails(self.cleaned_data['cc'])
|
||||
|
||||
def clean_bcc(self):
|
||||
return self.clean_space_separated_emails(self.cleaned_data['bcc'])
|
|
@ -2,18 +2,22 @@ from django.conf import settings
|
|||
from django_countries import data
|
||||
|
||||
|
||||
CONTACTS_DEFAULT_EMAIL_USAGES = getattr(settings, 'CONTACTS_DEFAULT_EMAIL_USAGES',
|
||||
('SUPPORT', 'ADMIN', 'BILLING', 'TECH', 'ADDS', 'EMERGENCY')
|
||||
)
|
||||
CONTACTS_DEFAULT_EMAIL_USAGES = getattr(settings, 'CONTACTS_DEFAULT_EMAIL_USAGES', (
|
||||
'SUPPORT',
|
||||
'ADMIN',
|
||||
'BILLING',
|
||||
'TECH',
|
||||
'ADDS',
|
||||
'EMERGENCY'
|
||||
))
|
||||
|
||||
|
||||
CONTACTS_DEFAULT_CITY = getattr(settings, 'CONTACTS_DEFAULT_CITY', 'Barcelona')
|
||||
|
||||
|
||||
CONTACTS_COUNTRIES = getattr(settings, 'CONTACTS_COUNTRIES', ((k,v) for k,v in data.COUNTRIES.iteritems()))
|
||||
CONTACTS_COUNTRIES = getattr(settings, 'CONTACTS_COUNTRIES', (
|
||||
(k,v) for k,v in data.COUNTRIES.iteritems()
|
||||
))
|
||||
|
||||
|
||||
CONTACTS_DEFAULT_COUNTRY = getattr(settings, 'CONTACTS_DEFAULT_COUNTRY', 'ES')
|
||||
|
||||
|
||||
CONTACTS_DEFAULT_FROM_EMAIL = getattr(settings, 'CONTACTS_DEFAULT_FROM_EMAIL', 'support@orchestra.lan')
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
from django.contrib.admin import SimpleListFilter
|
||||
from django.utils.encoding import force_text
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
|
||||
class TopDomainListFilter(SimpleListFilter):
|
||||
""" Filter Nodes by group according to request.user """
|
||||
title = _("Top domains")
|
||||
title = _("top domains")
|
||||
parameter_name = 'top_domain'
|
||||
|
||||
def lookups(self, request, model_admin):
|
||||
|
|
|
@ -8,8 +8,8 @@ from django.utils.translation import ugettext_lazy as _
|
|||
from orchestra.admin import ExtendedModelAdmin
|
||||
from orchestra.admin.utils import admin_link
|
||||
from orchestra.apps.accounts.admin import AccountAdminMixin
|
||||
from orchestra.apps.plugins import PluginModelAdapter
|
||||
from orchestra.apps.plugins.admin import SelectPluginAdminMixin
|
||||
from orchestra.plugins import PluginModelAdapter
|
||||
from orchestra.plugins.admin import SelectPluginAdminMixin
|
||||
|
||||
from . import settings
|
||||
from .models import MiscService, Miscellaneous
|
||||
|
@ -26,7 +26,9 @@ class MiscServiceAdmin(ExtendedModelAdmin):
|
|||
)
|
||||
list_editable = ('is_active',)
|
||||
list_filter = ('has_identifier', 'has_amount', 'is_active')
|
||||
fields = ('verbose_name', 'name', 'description', 'has_identifier', 'has_amount', 'is_active')
|
||||
fields = (
|
||||
'verbose_name', 'name', 'description', 'has_identifier', 'has_amount', 'is_active'
|
||||
)
|
||||
prepopulated_fields = {'name': ('verbose_name',)}
|
||||
change_readonly_fields = ('name',)
|
||||
|
||||
|
@ -51,9 +53,12 @@ class MiscServiceAdmin(ExtendedModelAdmin):
|
|||
|
||||
|
||||
class MiscellaneousAdmin(AccountAdminMixin, SelectPluginAdminMixin, admin.ModelAdmin):
|
||||
list_display = ('__unicode__', 'service_link', 'amount', 'dispaly_active', 'account_link')
|
||||
list_display = (
|
||||
'__unicode__', 'service_link', 'amount', 'dispaly_active', 'account_link'
|
||||
)
|
||||
list_filter = ('service__name', 'is_active')
|
||||
list_select_related = ('service', 'account')
|
||||
search_fields = ('identifier', 'description')
|
||||
plugin_field = 'service'
|
||||
plugin = MiscServicePlugin
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ from django.utils import timezone
|
|||
from django.utils.functional import cached_property
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from orchestra.apps import plugins
|
||||
from orchestra import plugins
|
||||
|
||||
from . import methods
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ from django.utils.translation import ugettext_lazy as _
|
|||
from orchestra.admin import ChangeViewActionsMixin, ExtendedModelAdmin
|
||||
from orchestra.admin.utils import admin_colored, admin_link
|
||||
from orchestra.apps.accounts.admin import AccountAdminMixin, SelectAccountAdminMixin
|
||||
from orchestra.apps.plugins.admin import SelectPluginAdminMixin
|
||||
from orchestra.plugins.admin import SelectPluginAdminMixin
|
||||
|
||||
from . import actions
|
||||
from .methods import PaymentMethod
|
||||
|
|
|
@ -2,7 +2,7 @@ from django import forms
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
from rest_framework import serializers
|
||||
|
||||
from orchestra.apps.plugins.forms import PluginDataForm
|
||||
from orchestra.plugins.forms import PluginDataForm
|
||||
|
||||
from .options import PaymentMethod
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ from dateutil import relativedelta
|
|||
from django import forms
|
||||
from django.core.exceptions import ValidationError
|
||||
|
||||
from orchestra.apps import plugins
|
||||
from orchestra import plugins
|
||||
from orchestra.utils.functional import cached
|
||||
from orchestra.utils.python import import_class
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ from django_iban.forms import IBANFormField
|
|||
from django_iban.validators import IBANValidator, IBAN_COUNTRY_CODE_LENGTH
|
||||
from rest_framework import serializers
|
||||
|
||||
from orchestra.apps.plugins.forms import PluginDataForm
|
||||
from orchestra.plugins.forms import PluginDataForm
|
||||
|
||||
from .. import settings
|
||||
from .options import PaymentMethod
|
||||
|
|
|
@ -86,6 +86,21 @@ class Resource(models.Model):
|
|||
|
||||
def clean(self):
|
||||
self.verbose_name = self.verbose_name.strip()
|
||||
# Validate that model path exists between ct and each monitor.model
|
||||
monitor_errors = []
|
||||
for monitor in self.monitors:
|
||||
try:
|
||||
self.get_model_path(monitor)
|
||||
except (RuntimeError, LookupError):
|
||||
monitor_errors.append(monitor)
|
||||
if monitor_errors:
|
||||
raise validators.ValidationError({
|
||||
'monitors': [
|
||||
_("Path does not exists between '%s' and '%s'") % (
|
||||
get_model(ServiceMonitor.get_backend(monitor).model)._meta.model_name,
|
||||
self.content_type.model_class()._meta.model_name,
|
||||
) for error in monitor_errors
|
||||
]})
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
created = not self.pk
|
||||
|
@ -99,6 +114,13 @@ class Resource(models.Model):
|
|||
super(Resource, self).delete(*args, **kwargs)
|
||||
name = 'monitor.%s' % str(self)
|
||||
|
||||
def get_model_path(self, monitor):
|
||||
""" returns a model path between self.content_type and monitor.model """
|
||||
resource_model = self.content_type.model_class()
|
||||
model_path = ServiceMonitor.get_backend(monitor).model
|
||||
monitor_model = get_model(model_path)
|
||||
return get_model_field_path(monitor_model, resource_model)
|
||||
|
||||
def sync_periodic_task(self):
|
||||
name = 'monitor.%s' % str(self)
|
||||
if self.pk and self.crontab:
|
||||
|
@ -190,17 +212,14 @@ class ResourceData(models.Model):
|
|||
today = timezone.now()
|
||||
datasets = []
|
||||
for monitor in resource.monitors:
|
||||
resource_model = self.content_type.model_class()
|
||||
model_path = ServiceMonitor.get_backend(monitor).model
|
||||
monitor_model = get_model(model_path)
|
||||
if resource_model == monitor_model:
|
||||
path = self.resource.get_model_path(monitor)
|
||||
if path == []:
|
||||
dataset = MonitorData.objects.filter(
|
||||
monitor=monitor,
|
||||
content_type=self.content_type_id,
|
||||
object_id=self.object_id
|
||||
)
|
||||
else:
|
||||
path = get_model_field_path(monitor_model, resource_model)
|
||||
fields = '__'.join(path)
|
||||
objects = monitor_model.objects.filter(**{fields: self.object_id})
|
||||
pks = objects.values_list('id', flat=True)
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
from django.core.validators import ValidationError
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
|
||||
def validate_scale(value):
|
||||
try:
|
||||
int(eval(value))
|
||||
except ValueError:
|
||||
raise ValidationError(_("%s value is not a valid scale expression"))
|
||||
except Exception, e:
|
||||
raise ValidationError(
|
||||
_("'%s' is not a valid scale expression. (%s)") % (value, str(e))
|
||||
)
|
||||
|
|
|
@ -2,7 +2,7 @@ from django.contrib import admin
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from orchestra.apps.accounts.admin import AccountAdminMixin
|
||||
from orchestra.apps.plugins.admin import SelectPluginAdminMixin
|
||||
from orchestra.plugins.admin import SelectPluginAdminMixin
|
||||
|
||||
from .models import SaaS
|
||||
from .services import SoftwareService
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from django import forms
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from orchestra.apps.plugins.forms import PluginDataForm
|
||||
from orchestra.plugins.forms import PluginDataForm
|
||||
|
||||
from .options import SoftwareService
|
||||
|
||||
|
|
|
@ -3,8 +3,8 @@ from django.core.exceptions import ValidationError
|
|||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from orchestra.apps import plugins
|
||||
from orchestra.apps.plugins.forms import PluginDataForm
|
||||
from orchestra import plugins
|
||||
from orchestra.plugins.forms import PluginDataForm
|
||||
from orchestra.core import validators
|
||||
from orchestra.forms import widgets
|
||||
from orchestra.utils.functional import cached
|
||||
|
@ -72,6 +72,7 @@ class SoftwareServiceForm(PluginDataForm):
|
|||
obj.set_password(self.cleaned_data["password1"])
|
||||
return obj
|
||||
|
||||
|
||||
class SoftwareService(plugins.Plugin):
|
||||
form = SoftwareServiceForm
|
||||
serializer = None
|
||||
|
|
|
@ -7,7 +7,7 @@ from django.contrib.contenttypes.models import ContentType
|
|||
from django.utils import timezone
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from orchestra.apps import plugins
|
||||
from orchestra import plugins
|
||||
from orchestra.utils.humanize import text2int
|
||||
from orchestra.utils.python import AttrDict
|
||||
|
||||
|
|
|
@ -86,7 +86,6 @@ INSTALLED_APPS = (
|
|||
'orchestra.apps.miscellaneous',
|
||||
'orchestra.apps.bills',
|
||||
'orchestra.apps.payments',
|
||||
'orchestra.apps.plugins',
|
||||
|
||||
# Third-party apps
|
||||
'django_extensions',
|
||||
|
|
|
@ -47,3 +47,4 @@ def get_model_field_path(origin, target):
|
|||
new_path = list(path)
|
||||
new_path.append(field.name)
|
||||
queue.append((new_model, new_path))
|
||||
raise LookupError("Path does not exists between '%s' and '%s' models" % (origin, target))
|
||||
|
|
|
@ -31,3 +31,8 @@ API_ROOT_VIEW = getattr(settings, 'API_ROOT_VIEW', 'orchestra.api.root.APIRoot')
|
|||
|
||||
|
||||
ORCHESTRA_MIGRATION_MODE = getattr(settings, 'ORCHESTRA_MIGRATION_MODE', False)
|
||||
|
||||
|
||||
ORCHESTRA_DEFAULT_SUPPORT_FROM_EMAIL = getattr(settings, 'ORCHESTRA_DEFAULT_SUPPORT_FROM_EMAIL',
|
||||
'support@orchestra.lan'
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue