From 92f5025817cdfeb9f2868c7bc95c04aaa84eaeee Mon Sep 17 00:00:00 2001 From: Aaron Tan Date: Mon, 26 Jun 2017 13:21:29 -0400 Subject: [PATCH] Aggregate Tower service restart attempts. --- awx/conf/signals.py | 6 +----- awx/conf/views.py | 10 ++++++++++ awx/main/tasks.py | 25 +++++++++++++------------ 3 files changed, 24 insertions(+), 17 deletions(-) diff --git a/awx/conf/signals.py b/awx/conf/signals.py index b077cc5a18..453140241d 100644 --- a/awx/conf/signals.py +++ b/awx/conf/signals.py @@ -1,6 +1,5 @@ # Python import logging -import sys # Django from django.conf import settings @@ -14,7 +13,6 @@ import awx.main.signals from awx.conf import settings_registry from awx.conf.models import Setting from awx.conf.serializers import SettingSerializer -from awx.main.tasks import process_cache_changes logger = logging.getLogger('awx.conf.signals') @@ -30,11 +28,9 @@ def handle_setting_change(key, for_delete=False): for dependent_key in settings_registry.get_dependent_settings(key): # Note: Doesn't handle multiple levels of dependencies! setting_keys.append(dependent_key) + # NOTE: This block is probably duplicated. cache_keys = set([Setting.get_cache_key(k) for k in setting_keys]) - logger.debug('sending signals to delete cache keys(%r)', cache_keys) cache.delete_many(cache_keys) - if 'migrate_to_database_settings' not in sys.argv: - process_cache_changes.delay(list(cache_keys)) # Send setting_changed signal with new value for each setting. for setting_key in setting_keys: diff --git a/awx/conf/views.py b/awx/conf/views.py index fccb910774..2e8ac91203 100644 --- a/awx/conf/views.py +++ b/awx/conf/views.py @@ -22,6 +22,7 @@ from awx.api.permissions import IsSuperUser from awx.api.versioning import reverse from awx.main.utils import * # noqa from awx.main.utils.handlers import BaseHTTPSHandler, LoggingConnectivityException +from awx.main.tasks import handle_setting_changes from awx.conf.license import get_licensed_features from awx.conf.models import Setting from awx.conf.serializers import SettingCategorySerializer, SettingSingletonSerializer @@ -102,6 +103,7 @@ class SettingSingletonDetail(RetrieveUpdateDestroyAPIView): def perform_update(self, serializer): settings_qs = self.get_queryset() user = self.request.user if self.category_slug == 'user' else None + settings_change_list = [] for key, value in serializer.validated_data.items(): if key == 'LICENSE': continue @@ -111,9 +113,13 @@ class SettingSingletonDetail(RetrieveUpdateDestroyAPIView): setting = settings_qs.filter(key=key).order_by('pk').first() if not setting: setting = Setting.objects.create(key=key, user=user, value=value) + settings_change_list.append(key) elif setting.value != value or type(setting.value) != type(value): setting.value = value setting.save(update_fields=['value']) + settings_change_list.append(key) + if settings_change_list and 'migrate_to_database_settings' not in sys.argv: + handle_setting_changes.delay(settings_change_list) def destroy(self, request, *args, **kwargs): instance = self.get_object() @@ -121,8 +127,12 @@ class SettingSingletonDetail(RetrieveUpdateDestroyAPIView): return Response(status=status.HTTP_204_NO_CONTENT) def perform_destroy(self, instance): + settings_change_list = [] for setting in self.get_queryset().exclude(key='LICENSE'): setting.delete() + settings_change_list.append(setting.key) + if settings_change_list and 'migrate_to_database_settings' not in sys.argv: + handle_setting_changes.delay(settings_change_list) # When TOWER_URL_BASE is deleted from the API, reset it to the hostname # used to make the request as a default. diff --git a/awx/main/tasks.py b/awx/main/tasks.py index a7815eb682..5866590ba7 100644 --- a/awx/main/tasks.py +++ b/awx/main/tasks.py @@ -56,6 +56,7 @@ from awx.main.utils import (get_ansible_version, get_ssh_version, decrypt_field, from awx.main.utils.reload import restart_local_services, stop_local_services from awx.main.utils.handlers import configure_external_logger from awx.main.consumers import emit_channel_notification +from awx.conf import settings_registry __all__ = ['RunJob', 'RunSystemJob', 'RunProjectUpdate', 'RunInventoryUpdate', 'RunAdHocCommand', 'handle_work_error', 'handle_work_success', @@ -93,19 +94,19 @@ def task_set_logger_pre_run(*args, **kwargs): configure_external_logger(settings, is_startup=False) -def _clear_cache_keys(set_of_keys): - logger.debug('cache delete_many(%r)', set_of_keys) - cache.delete_many(set_of_keys) - - -@task(queue='tower_broadcast_all') -def process_cache_changes(cache_keys): +@task(queue='tower_broadcast_all', bind=True) +def handle_setting_changes(self, setting_keys): + orig_len = len(setting_keys) + for i in range(orig_len): + for dependent_key in settings_registry.get_dependent_settings(setting_keys[i]): + setting_keys.append(dependent_key) logger.warn('Processing cache changes, task args: {0.args!r} kwargs: {0.kwargs!r}'.format( - process_cache_changes.request)) - set_of_keys = set([key for key in cache_keys]) - _clear_cache_keys(set_of_keys) - for setting_key in set_of_keys: - if setting_key.startswith('LOG_AGGREGATOR_'): + self.request)) + cache_keys = set(setting_keys) + logger.debug('cache delete_many(%r)', cache_keys) + cache.delete_many(cache_keys) + for key in cache_keys: + if key.startswith('LOG_AGGREGATOR_'): restart_local_services(['uwsgi', 'celery', 'beat', 'callback', 'fact']) break