From cce93819d1a718a73a75295e6170859b4cd85882 Mon Sep 17 00:00:00 2001 From: Jiao Pengju Date: Thu, 23 Nov 2017 15:07:55 +0800 Subject: [PATCH] Fix trigger creation failed Currently, karbor use 'calendar' format as the default time format, but karbor-dashboard use 'crontab', this makes the trigger creation failed. This patch convert the time format of the dashboard to canlendar to make it work. Change-Id: I7a89365005af3256bdf02478dd60428a118a8bbe Closes-Bug: #1613587 --- .../locale/en_GB/LC_MESSAGES/django.po | 6 + .../templates/triggers/_detail.html | 12 ++ karbor_dashboard/triggers/forms.py | 6 +- karbor_dashboard/triggers/utils.py | 145 ++++++++++++++++-- karbor_dashboard/triggers/views.py | 15 +- 5 files changed, 159 insertions(+), 25 deletions(-) diff --git a/karbor_dashboard/locale/en_GB/LC_MESSAGES/django.po b/karbor_dashboard/locale/en_GB/LC_MESSAGES/django.po index 71d047d..7f72fc2 100644 --- a/karbor_dashboard/locale/en_GB/LC_MESSAGES/django.po +++ b/karbor_dashboard/locale/en_GB/LC_MESSAGES/django.po @@ -112,6 +112,12 @@ msgstr "Error Deleting" msgid "Event Trigger" msgstr "Event Trigger" +msgid "Every Minute" +msgstr "Every Minute" + +msgid "Every Hour" +msgstr "Every Hour" + msgid "Every Day" msgstr "Every Day" diff --git a/karbor_dashboard/templates/triggers/_detail.html b/karbor_dashboard/templates/triggers/_detail.html index dd6998d..5654a4d 100644 --- a/karbor_dashboard/templates/triggers/_detail.html +++ b/karbor_dashboard/templates/triggers/_detail.html @@ -22,5 +22,17 @@
{% trans "Execution Time (HH:MM)" %}
{{ trigger.time }}
{% endif %} + {% if trigger.hour %} +
{% trans "Hour" %}
+
{{ trigger.hour }}
+ {% endif %} + {% if trigger.minute %} +
{% trans "Minute" %}
+
{{ trigger.minute }}
+ {% endif %} + {% if trigger.interval %} +
{% trans "Execution Interval" %}
+
{{ trigger.interval }}
+ {% endif %} diff --git a/karbor_dashboard/triggers/forms.py b/karbor_dashboard/triggers/forms.py index 2229b0d..7412175 100644 --- a/karbor_dashboard/triggers/forms.py +++ b/karbor_dashboard/triggers/forms.py @@ -34,7 +34,7 @@ class CreateTriggerForm(horizon_forms.SelfHandlingForm): })) frequence = forms.ChoiceField( label=_('Frequence'), - choices=utils.FREQUENCE_CHOICES, + choices=utils.CRONTAB_FREQUENCE_CHOICES, widget=forms.Select(attrs={ 'class': 'switchable switched', 'data-slug': 'frequence'})) @@ -60,12 +60,12 @@ class CreateTriggerForm(horizon_forms.SelfHandlingForm): def __init__(self, request, *args, **kwargs): super(CreateTriggerForm, self).__init__(request, *args, **kwargs) - self.fields['day'].choices = utils.DAY_CHOICES + self.fields['day'].choices = utils.CRONTAB_DAY_CHOICES self.fields['date'].choices = [(e, e) for e in range(1, 31 + 1)] def handle(self, request, data): try: - data_properties = utils.CrontabUtil.convert_to_crontab(data) + data_properties = utils.CalendarUtil.convert_to_calendar(data) new_trigger = karborclient.trigger_create(request, data["name"], data["type"], diff --git a/karbor_dashboard/triggers/utils.py b/karbor_dashboard/triggers/utils.py index 9fcfcf5..955a7ad 100644 --- a/karbor_dashboard/triggers/utils.py +++ b/karbor_dashboard/triggers/utils.py @@ -14,29 +14,32 @@ import collections from django.utils.translation import ugettext_lazy as _ +from icalendar.cal import Component +from icalendar import Event +from oslo_serialization import jsonutils TRIGGERTYPE_CHOICES = [('time', _('Time Trigger')), ('event', _('Event Trigger'))] CRONTAB = 'crontab' -DAY_CHOICES = [('1', _('Monday')), - ('2', _('Tuesday')), - ('3', _('Wednesday')), - ('4', _('Thursday')), - ('5', _('Friday')), - ('6', _('Saturday')), - ('0', _('Sunday'))] -DAY_DICT = collections.OrderedDict(DAY_CHOICES) +CRONTAB_DAY_CHOICES = [('1', _('Monday')), + ('2', _('Tuesday')), + ('3', _('Wednesday')), + ('4', _('Thursday')), + ('5', _('Friday')), + ('6', _('Saturday')), + ('0', _('Sunday'))] +CRONTAB_DAY_DICT = collections.OrderedDict(CRONTAB_DAY_CHOICES) EVERYDAY = 'everyday' EVERYWEEK = 'everyweek' EVERYMONTH = 'everymonth' -FREQUENCE_CHOICES = [(EVERYDAY, _('Every Day')), - (EVERYWEEK, _('Every Week')), - (EVERYMONTH, _('Every Month'))] -FREQUENCE_DICT = collections.OrderedDict(FREQUENCE_CHOICES) +CRONTAB_FREQUENCE_CHOICES = [(EVERYDAY, _('Every Day')), + (EVERYWEEK, _('Every Week')), + (EVERYMONTH, _('Every Month'))] +CRONTAB_FREQUENCE_DICT = collections.OrderedDict(CRONTAB_FREQUENCE_CHOICES) class CrontabUtil(object): @@ -78,7 +81,9 @@ class CrontabUtil(object): @staticmethod def convert_from_crontab(dict_crontab): - data = {} + data = { + 'format': dict_crontab['format'] + } if dict_crontab["format"] == CRONTAB: pattern = dict_crontab["pattern"] patterns = pattern.split(" ") @@ -86,18 +91,124 @@ class CrontabUtil(object): if patterns[2] == "*" \ and patterns[3] == "*" \ and patterns[4] == "*": - data["frequence"] = FREQUENCE_DICT[EVERYDAY] + data["frequence"] = CRONTAB_FREQUENCE_DICT[EVERYDAY] elif patterns[2] == "*" \ and patterns[3] == "*" \ and patterns[4] != "*": - data["frequence"] = FREQUENCE_DICT[EVERYWEEK] - data["day"] = DAY_DICT[patterns[4]] + data["frequence"] = CRONTAB_FREQUENCE_DICT[EVERYWEEK] + data["day"] = CRONTAB_DAY_DICT[patterns[4]] elif patterns[2] != "*" \ and patterns[3] == "*" \ and patterns[4] == "*": - data["frequence"] = FREQUENCE_DICT[EVERYMONTH] + data["frequence"] = CRONTAB_FREQUENCE_DICT[EVERYMONTH] data["date"] = patterns[2] data["time"] = '%s:%s' % (patterns[1].zfill(2), patterns[0].zfill(2)) return data + +CALENDAR = 'calendar' +CALENDAR_DAY_CHOICES = [('1', _('MO')), + ('2', _('TU')), + ('3', _('WE')), + ('4', _('TH')), + ('5', _('FR')), + ('6', _('SA')), + ('0', _('SU'))] +CALENDAR_DAY_DICT = collections.OrderedDict(CALENDAR_DAY_CHOICES) +CALENDAR_DAY_MAPPING = [('MO', _('Monday')), + ('TU', _('Tuesday')), + ('WE', _('Wednesday')), + ('TH', _('Thursday')), + ('FR', _('Friday')), + ('SA', _('Saturday')), + ('SU', _('Sunday'))] +CALENDAR_DAY_MAPPING_DICT = collections.OrderedDict(CALENDAR_DAY_MAPPING) +MINUTELY = 'MINUTELY' +HOURLY = 'HOURLY' +DAILY = 'DAILY' +WEEKLY = 'WEEKLY' +MONTHLY = 'MONTHLY' + + +class CalendarUtil(object): + """Convert to or from calendar format.""" + @staticmethod + def convert_to_calendar(data): + dict_calendar = { + "format": CALENDAR, + } + + pattern_frequence = '' + if data['frequence'] == EVERYMONTH: + pattern_frequence = MONTHLY + elif data['frequence'] == EVERYWEEK: + pattern_frequence = WEEKLY + elif data['frequence'] == EVERYDAY: + pattern_frequence = DAILY + calendar_event = Event() + rule_pattern = { + 'freq': pattern_frequence, + 'byhour': data["time"].hour, + 'byminute': data["time"].minute, + } + + if pattern_frequence == MONTHLY: + rule_pattern['bymonthday'] = data["date"] + elif pattern_frequence == WEEKLY: + rule_pattern['byday'] = CALENDAR_DAY_DICT[data["day"]] + + calendar_event.add('rrule', rule_pattern) + dict_calendar['pattern'] = calendar_event.to_ical() + return dict_calendar + + @staticmethod + def decode_calendar_pattern(pattern): + try: + pattern.index('\\') + pattern_dict = jsonutils.loads('{"pattern": "%s"}' % pattern) + return pattern_dict["pattern"] + except Exception: + return pattern + + @staticmethod + def convert_from_calendar(dict_calendar): + data = { + 'format': dict_calendar['format'] + } + if dict_calendar["format"] == CALENDAR: + pattern = dict_calendar["pattern"] + calendar_event = Component.from_ical( + CalendarUtil.decode_calendar_pattern(pattern) + ) + if isinstance(calendar_event, Event): + calendar_event_rule = calendar_event['RRULE'] + data['frequence'] = calendar_event_rule['FREQ'][0] + + if data['frequence'] == MONTHLY and not ( + 'INTERVAL' in calendar_event['RRULE']): + data['date'] = ' '.join( + str(date) + for date in calendar_event_rule['BYMONTHDAY']) + + if data['frequence'] == WEEKLY and not ( + 'INTERVAL' in calendar_event['RRULE']): + data['day'] = ' '.join( + str(CALENDAR_DAY_MAPPING_DICT[day]) + for day in calendar_event_rule['BYDAY']) + + if 'BYHOUR' in calendar_event['RRULE']: + data['hour'] = ' '.join( + str(hour) for hour in calendar_event_rule['BYHOUR']) + + if 'BYMINUTE' in calendar_event['RRULE']: + data['minute'] = ' '.join( + str(minute) + for minute in calendar_event_rule['BYMINUTE']) + + if 'INTERVAL' in calendar_event['RRULE']: + data['interval'] = ' '.join( + str(interval) + for interval in calendar_event_rule['INTERVAL']) + + return data diff --git a/karbor_dashboard/triggers/views.py b/karbor_dashboard/triggers/views.py index fefdc92..4d53319 100644 --- a/karbor_dashboard/triggers/views.py +++ b/karbor_dashboard/triggers/views.py @@ -89,11 +89,16 @@ class DetailView(horizon_views.HorizonTemplateView): if trigger is not None and trigger.properties is not None: if trigger.properties["format"] == utils.CRONTAB: - data = utils.CrontabUtil\ - .convert_from_crontab(trigger.properties) - if data: - for key, value in data.items(): - setattr(trigger, key, value) + data = utils.CrontabUtil.convert_from_crontab( + trigger.properties + ) + else: + data = utils.CalendarUtil.convert_from_calendar( + trigger.properties + ) + if data: + for key, value in data.items(): + setattr(trigger, key, value) context["trigger"] = trigger context["url"] = reverse("horizon:karbor:triggers:index")