From 0b4b38abe7ea4012d7f89d738fb5b743b608a4a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adolfo=20G=C3=B3mez=20Garc=C3=ADa?= Date: Fri, 1 Apr 2016 07:18:42 +0200 Subject: [PATCH] Fixed model of Calandars && finished Scheduled calendar actions --- .../REST/methods/services_pool_calendars.py | 20 +++---- .../src/uds/core/workers/ScheduledAction.py | 60 +++++++++++++++++++ ...330_0938.py => 0021_auto_20160401_0652.py} | 14 ++--- server/src/uds/models/CalendarAccess.py | 4 +- server/src/uds/models/CalendarAction.py | 38 +++++++----- 5 files changed, 102 insertions(+), 34 deletions(-) create mode 100644 server/src/uds/core/workers/ScheduledAction.py rename server/src/uds/migrations/{0021_auto_20160330_0938.py => 0021_auto_20160401_0652.py} (85%) diff --git a/server/src/uds/REST/methods/services_pool_calendars.py b/server/src/uds/REST/methods/services_pool_calendars.py index 43e7f66e7..890372101 100644 --- a/server/src/uds/REST/methods/services_pool_calendars.py +++ b/server/src/uds/REST/methods/services_pool_calendars.py @@ -102,12 +102,12 @@ class AccessCalendars(DetailHandler): if uuid is not None: calAccess = CalendarAccess.objects.get(uuid=uuid) calAccess.calendar = calendar - calAccess.servicePool = parent + calAccess.service_pool = parent calAccess.access = access calAccess.priority = priority calAccess.save() else: - CalendarAccess.objects.create(calendar=calendar, servicePool=parent, access=access, priority=priority) + CalendarAccess.objects.create(calendar=calendar, service_pool=parent, access=access, priority=priority) return self.success() @@ -130,11 +130,11 @@ class ActionsCalendars(DetailHandler): 'calendar': item.calendar.name, 'action': item.action, 'actionDescription': CALENDAR_ACTION_DICT[item.action]['description'], - 'atStart': item.atStart, - 'eventsOffset': item.eventsOffset, + 'atStart': item.at_start, + 'eventsOffset': item.events_offset, 'params': json.loads(item.params), - 'nextExecution': item.nextExecution, - 'lastExecution': item.lastExecution + 'nextExecution': item.next_execution, + 'lastExecution': item.last_execution } def getItems(self, parent, item): @@ -177,14 +177,14 @@ class ActionsCalendars(DetailHandler): if uuid is not None: calAction = CalendarAction.objects.get(uuid=uuid) calAction.calendar = calendar - calAction.servicePool = parent + calAction.service_pool = parent calAction.action = action - calAction.atStart = atStart - calAction.eventsOffset = eventsOffset + calAction.at_start = atStart + calAction.events_offset = eventsOffset calAction.params = params calAction.save() else: - CalendarAction.objects.create(calendar=calendar, servicePool=parent, action=action, atStart=atStart, eventsOffset=eventsOffset, params=params) + CalendarAction.objects.create(calendar=calendar, service_pool=parent, action=action, at_start=atStart, events_offset=eventsOffset, params=params) return self.success() diff --git a/server/src/uds/core/workers/ScheduledAction.py b/server/src/uds/core/workers/ScheduledAction.py new file mode 100644 index 000000000..922d5d8a4 --- /dev/null +++ b/server/src/uds/core/workers/ScheduledAction.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- + +# +# Copyright (c) 2012 Virtual Cable S.L. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * Neither the name of Virtual Cable S.L. nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +''' +@author: Adolfo Gómez, dkmaster at dkmon dot com +''' +from __future__ import unicode_literals + +from django.db import transaction + +from uds.core.util.Config import GlobalConfig +from uds.models import CalendarAction, getSqlDatetime +from uds.core.util.State import State +from uds.core.jobs.Job import Job +from datetime import timedelta +import logging + +logger = logging.getLogger(__name__) + + +class ScheduledAction(Job): + frecuency = 29 # Frecuncy for this job + friendly_name = 'Scheduled action runner' + + def __init__(self, environment): + super(ScheduledAction, self).__init__(environment) + + def run(self): + for ca in CalendarAction.objects.filter(service_pool__service__provider__maintenance_mode=False, next_execution__lt=getSqlDatetime()).order_by('next_execution'): + logger.debug('Executing calendar action {}.{}'.format(ca.service_pool.name, ca.calendar.name)) + try: + ca.execute() + except Exception as e: + logger.exception('Got an exception executing calendar access action: {}'.format(e)) diff --git a/server/src/uds/migrations/0021_auto_20160330_0938.py b/server/src/uds/migrations/0021_auto_20160401_0652.py similarity index 85% rename from server/src/uds/migrations/0021_auto_20160330_0938.py rename to server/src/uds/migrations/0021_auto_20160401_0652.py index 082e05c8a..18429a2e4 100644 --- a/server/src/uds/migrations/0021_auto_20160330_0938.py +++ b/server/src/uds/migrations/0021_auto_20160401_0652.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Generated by Django 1.9.2 on 2016-03-30 09:38 +# Generated by Django 1.9.2 on 2016-04-01 06:52 from __future__ import unicode_literals from django.db import migrations, models @@ -33,11 +33,11 @@ class Migration(migrations.Migration): ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('uuid', models.CharField(default=None, max_length=50, null=True, unique=True)), ('action', models.CharField(default='', max_length=64)), - ('atStart', models.BooleanField(default=False)), - ('eventsOffset', models.IntegerField(default=0)), + ('at_start', models.BooleanField(default=False)), + ('events_offset', models.IntegerField(default=0)), ('params', models.CharField(default='', max_length=1024)), - ('lastExecution', models.DateTimeField(blank=True, db_index=True, default=None, null=True)), - ('nextExecution', models.DateTimeField(blank=True, db_index=True, default=None, null=True)), + ('last_execution', models.DateTimeField(blank=True, db_index=True, default=None, null=True)), + ('next_execution', models.DateTimeField(blank=True, db_index=True, default=None, null=True)), ('calendar', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='uds.Calendar')), ], options={ @@ -51,12 +51,12 @@ class Migration(migrations.Migration): ), migrations.AddField( model_name='calendaraction', - name='servicePool', + name='service_pool', field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='uds.DeployedService'), ), migrations.AddField( model_name='calendaraccess', - name='servicePool', + name='service_pool', field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='uds.DeployedService'), ), migrations.AddField( diff --git a/server/src/uds/models/CalendarAccess.py b/server/src/uds/models/CalendarAccess.py index d083ca0c8..8137c06ac 100644 --- a/server/src/uds/models/CalendarAccess.py +++ b/server/src/uds/models/CalendarAccess.py @@ -34,7 +34,7 @@ from __future__ import unicode_literals -__updated__ = '2016-02-19' +__updated__ = '2016-04-01' from django.db import models from uds.core.util import states @@ -49,7 +49,7 @@ logger = logging.getLogger(__name__) class CalendarAccess(UUIDModel): calendar = models.ForeignKey(Calendar, on_delete=models.CASCADE) - servicePool = models.ForeignKey(ServicePool, on_delete=models.CASCADE) + service_pool = models.ForeignKey(ServicePool, on_delete=models.CASCADE) access = models.CharField(max_length=8, default=states.action.DENY) priority = models.IntegerField(default=0, db_index=True) diff --git a/server/src/uds/models/CalendarAction.py b/server/src/uds/models/CalendarAction.py index 4f618c901..ccd68f612 100644 --- a/server/src/uds/models/CalendarAction.py +++ b/server/src/uds/models/CalendarAction.py @@ -34,7 +34,7 @@ from __future__ import unicode_literals -__updated__ = '2016-03-30' +__updated__ = '2016-04-01' from django.utils.translation import ugettext_lazy as _ from django.db import models @@ -63,16 +63,18 @@ CALENDAR_ACTION_MAX = { 'id': 'MAX', 'description': _('Change maximum number of CALENDAR_ACTION_DICT = dict(list((c['id'], c) for c in (CALENDAR_ACTION_PUBLISH, CALENDAR_ACTION_CACHE_L1, CALENDAR_ACTION_CACHE_L2, CALENDAR_ACTION_INITIAL, CALENDAR_ACTION_MAX))) + +@python_2_unicode_compatible class CalendarAction(UUIDModel): calendar = models.ForeignKey(Calendar, on_delete=models.CASCADE) - servicePool = models.ForeignKey(ServicePool, on_delete=models.CASCADE) + service_pool = models.ForeignKey(ServicePool, on_delete=models.CASCADE) action = models.CharField(max_length=64, default='') - atStart = models.BooleanField(default=False) # If false, action is done at end of event - eventsOffset = models.IntegerField(default=0) # In minutes + at_start = models.BooleanField(default=False) # If false, action is done at end of event + events_offset = models.IntegerField(default=0) # In minutes params = models.CharField(max_length=1024, default='') # Not to be edited, just to be used as indicators for executions - lastExecution = models.DateTimeField(default=None, db_index=True, null=True, blank=True) - nextExecution = models.DateTimeField(default=None, db_index=True, null=True, blank=True) + last_execution = models.DateTimeField(default=None, db_index=True, null=True, blank=True) + next_execution = models.DateTimeField(default=None, db_index=True, null=True, blank=True) class Meta: ''' @@ -83,25 +85,25 @@ class CalendarAction(UUIDModel): @property def offset(self): - return datetime.timedelta(minutes=self.eventsOffset) + return datetime.timedelta(minutes=self.events_offset) def execute(self, save=True): logger.debug('Executing action') - self.lastExecution = getSqlDatetime() + self.last_execution = getSqlDatetime() params = json.loads(self.params) saveServicePool = save if CALENDAR_ACTION_CACHE_L1['id'] == self.action: - self.servicePool.cache_l1_srvs = int(params['size']) + self.service_pool.cache_l1_srvs = int(params['size']) elif CALENDAR_ACTION_CACHE_L2['id'] == self.action: - self.servicePool.cache_l1_srvs = int(params['size']) + self.service_pool.cache_l1_srvs = int(params['size']) elif CALENDAR_ACTION_INITIAL['id'] == self.action: - self.servicePool.initial_srvs = int(params['size']) + self.service_pool.initial_srvs = int(params['size']) elif CALENDAR_ACTION_MAX['id'] == self.action: - self.servicePool.max_srvs = int(params['size']) + self.service_pool.max_srvs = int(params['size']) elif CALENDAR_ACTION_PUBLISH['id'] == self.action: - self.servicePool.publish(changeLog='Scheduled publication action') + self.service_pool.publish(changeLog='Scheduled publication action') saveServicePool = False # On save, will regenerate nextExecution @@ -109,10 +111,16 @@ class CalendarAction(UUIDModel): self.save() if saveServicePool: - self.servicePool.save() + self.service_pool.save() def save(self, *args, **kwargs): - self.nextExecution = calendar.CalendarChecker(self.calendar).nextEvent(checkFrom=self.lastExecution, startEvent=self.atStart, offset=self.offset) + self.next_execution = calendar.CalendarChecker(self.calendar).nextEvent(checkFrom=self.last_execution, startEvent=self.at_start, offset=self.offset) return UUIDModel.save(self, *args, **kwargs) + + + def __str__(self): + return 'Calendar of {}, last_execution = {}, next execution = {}, action = {}, params = {}'.format( + self.service_pool.name, self.last_execution, self.next_execution, self.action, self.params + ) \ No newline at end of file