Deleted resource backend support

This commit is contained in:
Marc Aymerich 2015-05-13 14:27:24 +00:00
parent cc4ecee4dd
commit ab6d027f01
11 changed files with 46 additions and 80 deletions

View file

@ -362,3 +362,8 @@ resorce monitoring more efficient, less mem an better queries for calc current d
# autoresponses on mailboxes, not addresses or remove them # autoresponses on mailboxes, not addresses or remove them
# Async particular actions? # Async particular actions?
apt-get install cython3
export CYTHON='cython3'
pip3 install https://github.com/fantix/gevent/archive/master.zip

View file

@ -5,12 +5,13 @@ from django.db import models
from django.utils import timezone from django.utils import timezone
from django.utils.functional import cached_property from django.utils.functional import cached_property
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from djcelery.models import PeriodicTask
from orchestra.core import validators from orchestra.core import validators
from orchestra.models import queryset, fields from orchestra.models import queryset, fields
from orchestra.models.utils import get_model_field_path from orchestra.models.utils import get_model_field_path
from . import tasks, settings from . import tasks
from .backends import ServiceMonitor from .backends import ServiceMonitor
from .aggregations import Aggregation from .aggregations import Aggregation
from .validators import validate_scale from .validators import validate_scale
@ -37,9 +38,9 @@ class Resource(models.Model):
_related = set() # keeps track of related models for resource cleanup _related = set() # keeps track of related models for resource cleanup
name = models.CharField(_("name"), max_length=32, name = models.CharField(_("name"), max_length=32,
help_text=_("Required. 32 characters or fewer. Lowercase letters, " help_text=_("Required. 32 characters or fewer. Lowercase letters, "
"digits and hyphen only."), "digits and hyphen only."),
validators=[validators.validate_name]) validators=[validators.validate_name])
verbose_name = models.CharField(_("verbose name"), max_length=256) verbose_name = models.CharField(_("verbose name"), max_length=256)
content_type = models.ForeignKey(ContentType, content_type = models.ForeignKey(ContentType,
help_text=_("Model where this resource will be hooked.")) help_text=_("Model where this resource will be hooked."))
@ -118,18 +119,32 @@ class Resource(models.Model):
created = not self.pk created = not self.pk
super(Resource, self).save(*args, **kwargs) super(Resource, self).save(*args, **kwargs)
self.sync_periodic_task() self.sync_periodic_task()
# This only work on tests (multiprocessing used on real deployments) # This only works on tests (multiprocessing used on real deployments)
apps.get_app_config('resources').reload_relations() apps.get_app_config('resources').reload_relations()
def delete(self, *args, **kwargs): def delete(self, *args, **kwargs):
super(Resource, self).delete(*args, **kwargs) super(Resource, self).delete(*args, **kwargs)
name = 'monitor.%s' % str(self)
self.sync_periodic_task() self.sync_periodic_task()
def sync_periodic_task(self): def sync_periodic_task(self):
name = 'monitor.%s' % str(self) name = 'monitor.%s' % str(self)
sync = import_class(settings.RESOURCES_TASK_BACKEND) if resource.pk and resource.crontab:
return sync(self, name) try:
task = PeriodicTask.objects.get(name=name)
except PeriodicTask.DoesNotExist:
if resource.is_active:
PeriodicTask.objects.create(
name=name,
task='resources.Monitor',
args=[resource.pk],
crontab=resource.crontab
)
else:
if task.crontab != resource.crontab:
task.crontab = resource.crontab
task.save(update_fields=['crontab'])
else:
PeriodicTask.objects.filter(name=name).delete()
def get_model_path(self, monitor): def get_model_path(self, monitor):
""" returns a model path between self.content_type and monitor.model """ """ returns a model path between self.content_type and monitor.model """

View file

@ -1,6 +0,0 @@
from orchestra.contrib.settings import Setting
RESOURCES_TASK_BACKEND = Setting('RESOURCES_TASK_BACKEND',
'orchestra.contrib.resources.utils.cron_sync'
)

View file

@ -1,41 +0,0 @@
from orchestra.contrib.crons.utils import apply_local
from . import settings
def celery_sync(resource, name):
from djcelery.models import PeriodicTask
if resource.pk and resource.crontab:
try:
task = PeriodicTask.objects.get(name=name)
except PeriodicTask.DoesNotExist:
if resource.is_active:
PeriodicTask.objects.create(
name=name,
task='resources.Monitor',
args=[resource.pk],
crontab=resource.crontab
)
else:
if task.crontab != resource.crontab:
task.crontab = resource.crontab
task.save(update_fields=['crontab'])
else:
PeriodicTask.objects.filter(
name=name,
).delete()
def cron_sync(resource, name):
if resource.pk and resource.crontab:
context = {
'manager': os.path.join(paths.get_project_dir(), 'manage.py'),
'id': resource.pk,
}
apply_local(resource.crontab,
'python3 %(manager)s runmethod orchestra.contrib.resources.tasks.monitor %(id)s',
'orchestra', # TODO
name
)
else:
apply_local(resource.crontab, '', 'orchestra', name, action='delete')

View file

@ -2,14 +2,12 @@ from django.contrib.contenttypes.models import ContentType
from orchestra.contrib.miscellaneous.models import MiscService, Miscellaneous from orchestra.contrib.miscellaneous.models import MiscService, Miscellaneous
from orchestra.contrib.plans.models import Plan from orchestra.contrib.plans.models import Plan
from orchestra.utils.tests import random_ascii from orchestra.utils.tests import random_ascii, BaseTestCase
from ...models import Service from ...models import Service
from . import BaseBillingTest
class DomainBillingTest(BaseTestCase):
class DomainBillingTest(BaseBillingTest):
def create_domain_service(self): def create_domain_service(self):
service = Service.objects.create( service = Service.objects.create(
description="Domain .ES", description="Domain .ES",

View file

@ -6,15 +6,13 @@ from django.contrib.contenttypes.models import ContentType
from django.utils import timezone from django.utils import timezone
from orchestra.contrib.systemusers.models import SystemUser from orchestra.contrib.systemusers.models import SystemUser
from orchestra.utils.tests import random_ascii from orchestra.utils.tests import random_ascii, BaseTestCase
from ... import settings from ... import settings
from ...models import Service from ...models import Service
from . import BaseBillingTest
class FTPBillingTest(BaseTestCase):
class FTPBillingTest(BaseBillingTest):
def create_ftp_service(self): def create_ftp_service(self):
return Service.objects.create( return Service.objects.create(
description="FTP Account", description="FTP Account",

View file

@ -2,14 +2,12 @@ from django.contrib.contenttypes.models import ContentType
from orchestra.contrib.miscellaneous.models import MiscService, Miscellaneous from orchestra.contrib.miscellaneous.models import MiscService, Miscellaneous
from orchestra.contrib.plans.models import Plan from orchestra.contrib.plans.models import Plan
from orchestra.utils.tests import random_ascii from orchestra.utils.tests import random_ascii, BaseTestCase
from ...models import Service from ...models import Service
from . import BaseBillingTest
class JobBillingTest(BaseTestCase):
class JobBillingTest(BaseBillingTest):
def create_job_service(self): def create_job_service(self):
service = Service.objects.create( service = Service.objects.create(
description="Random job", description="Random job",

View file

@ -6,14 +6,12 @@ from freezegun import freeze_time
from orchestra.contrib.mailboxes.models import Mailbox from orchestra.contrib.mailboxes.models import Mailbox
from orchestra.contrib.plans.models import Plan from orchestra.contrib.plans.models import Plan
from orchestra.contrib.resources.models import Resource, ResourceData from orchestra.contrib.resources.models import Resource, ResourceData
from orchestra.utils.tests import random_ascii from orchestra.utils.tests import random_ascii, BaseTestCase
from ...models import Service from ...models import Service
from . import BaseBillingTest
class MailboxBillingTest(BaseTestCase):
class MailboxBillingTest(BaseBillingTest):
def create_mailbox_service(self): def create_mailbox_service(self):
service = Service.objects.create( service = Service.objects.create(
description="Mailbox", description="Mailbox",
@ -59,7 +57,7 @@ class MailboxBillingTest(BaseBillingTest):
self.resource = Resource.objects.create( self.resource = Resource.objects.create(
name='disk', name='disk',
content_type=ContentType.objects.get_for_model(Mailbox), content_type=ContentType.objects.get_for_model(Mailbox),
period=Resource.LAST, aggregation='last',
verbose_name='Mailbox disk', verbose_name='Mailbox disk',
unit='GB', unit='GB',
scale=10**9, scale=10**9,

View file

@ -1,13 +1,12 @@
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from orchestra.contrib.plans.models import Plan, ContractedPlan from orchestra.contrib.plans.models import Plan, ContractedPlan
from orchestra.utils.tests import BaseTestCase
from ...models import Service from ...models import Service
from . import BaseBillingTest
class PlanBillingTest(BaseTestCase):
class PlanBillingTest(BaseBillingTest):
def create_plan_service(self): def create_plan_service(self):
service = Service.objects.create( service = Service.objects.create(
description="Association membership fee", description="Association membership fee",

View file

@ -7,13 +7,12 @@ from orchestra.contrib.accounts.models import Account
from orchestra.contrib.miscellaneous.models import MiscService, Miscellaneous from orchestra.contrib.miscellaneous.models import MiscService, Miscellaneous
from orchestra.contrib.plans.models import Plan from orchestra.contrib.plans.models import Plan
from orchestra.contrib.resources.models import Resource, ResourceData, MonitorData from orchestra.contrib.resources.models import Resource, ResourceData, MonitorData
from orchestra.utils.tests import BaseTestCase
from ...models import Service from ...models import Service
from . import BaseBillingTest
class BaseTrafficBillingTest(BaseTestCase):
class BaseTrafficBillingTest(BaseBillingTest):
TRAFFIC_METRIC = 'account.resources.traffic.used' TRAFFIC_METRIC = 'account.resources.traffic.used'
def create_traffic_service(self): def create_traffic_service(self):
@ -41,7 +40,7 @@ class BaseTrafficBillingTest(BaseBillingTest):
self.resource = Resource.objects.create( self.resource = Resource.objects.create(
name='traffic', name='traffic',
content_type=ContentType.objects.get_for_model(Account), content_type=ContentType.objects.get_for_model(Account),
period=Resource.MONTHLY_SUM, aggregation='monthly-sum',
verbose_name='Account Traffic', verbose_name='Account Traffic',
unit='GB', unit='GB',
scale='10**9', scale='10**9',

View file

@ -35,11 +35,14 @@ class UNIXUserBackend(ServiceController):
usermod %(user)s --home %(home)s --password '%(password)s' --shell %(shell)s %(groups_arg)s usermod %(user)s --home %(home)s --password '%(password)s' --shell %(shell)s %(groups_arg)s
else else
useradd %(user)s --home %(home)s --password '%(password)s' --shell %(shell)s %(groups_arg)s || { useradd %(user)s --home %(home)s --password '%(password)s' --shell %(shell)s %(groups_arg)s || {
useradd_code=$?
# User is logged in, kill and retry # User is logged in, kill and retry
if [[ $? -eq 8 ]]; then if [[ $useradd_code -eq 8 ]]; then
pkill -u %(user)s; sleep 2 pkill -u %(user)s; sleep 2
pkill -9 -u %(user)s; sleep 1 pkill -9 -u %(user)s; sleep 1
useradd %(user)s --home %(home)s --password '%(password)s' --shell %(shell)s %(groups_arg)s useradd %(user)s --home %(home)s --password '%(password)s' --shell %(shell)s %(groups_arg)s
else
exit $useradd_code
fi fi
} }
fi fi