mirror of
https://github.com/ansible/awx.git
synced 2026-03-24 20:35:02 -02:30
move reload functionality to its own file
This commit is contained in:
@@ -10,7 +10,6 @@ import json
|
|||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import signal
|
import signal
|
||||||
import subprocess
|
|
||||||
import pipes
|
import pipes
|
||||||
import re
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
@@ -34,7 +33,6 @@ import pexpect
|
|||||||
# Celery
|
# Celery
|
||||||
from celery import Task, task
|
from celery import Task, task
|
||||||
from celery.signals import celeryd_init, worker_process_init
|
from celery.signals import celeryd_init, worker_process_init
|
||||||
from celery import current_app
|
|
||||||
|
|
||||||
# Django
|
# Django
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
@@ -55,6 +53,7 @@ from awx.main.task_engine import TaskEnhancer
|
|||||||
from awx.main.utils import (get_ansible_version, get_ssh_version, decrypt_field, update_scm_url,
|
from awx.main.utils import (get_ansible_version, get_ssh_version, decrypt_field, update_scm_url,
|
||||||
check_proot_installed, build_proot_temp_dir, wrap_args_with_proot,
|
check_proot_installed, build_proot_temp_dir, wrap_args_with_proot,
|
||||||
get_system_task_capacity, OutputEventFilter, parse_yaml_or_json)
|
get_system_task_capacity, OutputEventFilter, parse_yaml_or_json)
|
||||||
|
from awx.main.utils.reload import restart_local_services
|
||||||
from awx.main.utils.handlers import configure_external_logger
|
from awx.main.utils.handlers import configure_external_logger
|
||||||
from awx.main.consumers import emit_channel_notification
|
from awx.main.consumers import emit_channel_notification
|
||||||
|
|
||||||
@@ -94,59 +93,6 @@ def task_set_logger_pre_run(*args, **kwargs):
|
|||||||
configure_external_logger(settings, async_flag=False, is_startup=False)
|
configure_external_logger(settings, async_flag=False, is_startup=False)
|
||||||
|
|
||||||
|
|
||||||
def _uwsgi_reload():
|
|
||||||
# http://uwsgi-docs.readthedocs.io/en/latest/MasterFIFO.html#available-commands
|
|
||||||
logger.warn('Initiating uWSGI chain reload of server')
|
|
||||||
TRIGGER_CHAIN_RELOAD = 'c'
|
|
||||||
with open(settings.uWSGI_FIFO_LOCATION, 'w') as awxfifo:
|
|
||||||
awxfifo.write(TRIGGER_CHAIN_RELOAD)
|
|
||||||
|
|
||||||
|
|
||||||
def _reset_celery_thread_pool():
|
|
||||||
# Send signal to restart thread pool
|
|
||||||
app = current_app._get_current_object()
|
|
||||||
app.control.broadcast('pool_restart', arguments={'reload': True},
|
|
||||||
destination=['celery@{}'.format(settings.CLUSTER_HOST_ID)], reply=False)
|
|
||||||
|
|
||||||
|
|
||||||
def _supervisor_service_restart(service_internal_names):
|
|
||||||
'''
|
|
||||||
Service internal name options:
|
|
||||||
- beat - celery - callback - channels - uwsgi - daphne
|
|
||||||
- fact - nginx
|
|
||||||
example use pattern of supervisorctl:
|
|
||||||
# supervisorctl restart tower-processes:receiver tower-processes:factcacher
|
|
||||||
'''
|
|
||||||
group_name = 'tower-processes'
|
|
||||||
args = ['supervisorctl']
|
|
||||||
if settings.DEBUG:
|
|
||||||
args.extend(['-c', '/supervisor.conf'])
|
|
||||||
programs = []
|
|
||||||
name_translation_dict = settings.SERVICE_NAME_DICT
|
|
||||||
for n in service_internal_names:
|
|
||||||
if n in name_translation_dict:
|
|
||||||
programs.append('{}:{}'.format(group_name, name_translation_dict[n]))
|
|
||||||
args.extend(['restart'])
|
|
||||||
args.extend(programs)
|
|
||||||
logger.debug('Issuing command to restart services, args={}'.format(args))
|
|
||||||
subprocess.Popen(args)
|
|
||||||
|
|
||||||
|
|
||||||
def restart_local_services(service_internal_names):
|
|
||||||
logger.warn('Restarting services {} on this node in response to user action'.format(service_internal_names))
|
|
||||||
if 'uwsgi' in service_internal_names:
|
|
||||||
_uwsgi_reload()
|
|
||||||
service_internal_names.pop('uwsgi')
|
|
||||||
restart_celery = False
|
|
||||||
if 'celery' in service_internal_names:
|
|
||||||
restart_celery = True
|
|
||||||
service_internal_names.pop('celery')
|
|
||||||
_supervisor_service_restart(service_internal_names)
|
|
||||||
if restart_celery:
|
|
||||||
# Celery restarted last because this probably includes current process
|
|
||||||
_reset_celery_thread_pool()
|
|
||||||
|
|
||||||
|
|
||||||
def _clear_cache_keys(set_of_keys):
|
def _clear_cache_keys(set_of_keys):
|
||||||
logger.debug('cache delete_many(%r)', set_of_keys)
|
logger.debug('cache delete_many(%r)', set_of_keys)
|
||||||
cache.delete_many(set_of_keys)
|
cache.delete_many(set_of_keys)
|
||||||
|
|||||||
@@ -1,13 +1,37 @@
|
|||||||
# from django.conf import LazySettings
|
|
||||||
import pytest
|
|
||||||
|
|
||||||
# awx.main.utils.reload
|
# awx.main.utils.reload
|
||||||
from awx.main.main.tasks import _supervisor_service_restart, subprocess
|
from awx.main.utils import reload
|
||||||
|
|
||||||
|
|
||||||
def test_produce_supervisor_command(mocker):
|
def test_produce_supervisor_command(mocker):
|
||||||
with mocker.patch.object(subprocess, 'Popen'):
|
with mocker.patch.object(reload.subprocess, 'Popen'):
|
||||||
_supervisor_service_restart(['beat', 'callback', 'fact'])
|
reload._supervisor_service_restart(['beat', 'callback', 'fact'])
|
||||||
subprocess.Popen.assert_called_once_with(
|
reload.subprocess.Popen.assert_called_once_with(
|
||||||
['supervisorctl', 'restart', 'tower-processes:receiver', 'tower-processes:factcacher'])
|
['supervisorctl', 'restart', 'tower-processes:receiver', 'tower-processes:factcacher'])
|
||||||
|
|
||||||
|
|
||||||
|
def test_routing_of_service_restarts_works(mocker):
|
||||||
|
'''
|
||||||
|
This tests that the parent restart method will call the appropriate
|
||||||
|
service restart methods, depending on which services are given in args
|
||||||
|
'''
|
||||||
|
with mocker.patch.object(reload, '_uwsgi_reload'):
|
||||||
|
with mocker.patch.object(reload, '_reset_celery_thread_pool'):
|
||||||
|
with mocker.patch.object(reload, '_supervisor_service_restart'):
|
||||||
|
reload.restart_local_services(['uwsgi', 'celery', 'flower', 'daphne'])
|
||||||
|
reload._uwsgi_reload.assert_called_once_with()
|
||||||
|
reload._reset_celery_thread_pool.assert_called_once_with()
|
||||||
|
reload._supervisor_service_restart.assert_called_once_with(['flower', 'daphne'])
|
||||||
|
|
||||||
|
|
||||||
|
def test_routing_of_service_restarts_diables(mocker):
|
||||||
|
'''
|
||||||
|
Test that methods are not called if not in the args
|
||||||
|
'''
|
||||||
|
with mocker.patch.object(reload, '_uwsgi_reload'):
|
||||||
|
with mocker.patch.object(reload, '_reset_celery_thread_pool'):
|
||||||
|
with mocker.patch.object(reload, '_supervisor_service_restart'):
|
||||||
|
reload.restart_local_services(['flower'])
|
||||||
|
reload._uwsgi_reload.assert_not_called()
|
||||||
|
reload._reset_celery_thread_pool.assert_not_called()
|
||||||
|
reload._supervisor_service_restart.assert_called_once_with(['flower'])
|
||||||
|
|
||||||
|
|||||||
68
awx/main/utils/reload.py
Normal file
68
awx/main/utils/reload.py
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
# Copyright (c) 2017 Ansible Tower by Red Hat
|
||||||
|
# All Rights Reserved.
|
||||||
|
|
||||||
|
# Python
|
||||||
|
import subprocess
|
||||||
|
import logging
|
||||||
|
|
||||||
|
# Django
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
|
# Celery
|
||||||
|
from celery import current_app
|
||||||
|
|
||||||
|
logger = logging.getLogger('awx.main.utils.reload')
|
||||||
|
|
||||||
|
|
||||||
|
def _uwsgi_reload():
|
||||||
|
# http://uwsgi-docs.readthedocs.io/en/latest/MasterFIFO.html#available-commands
|
||||||
|
logger.warn('Initiating uWSGI chain reload of server')
|
||||||
|
TRIGGER_CHAIN_RELOAD = 'c'
|
||||||
|
with open(settings.UWSGI_FIFO_LOCATION, 'w') as awxfifo:
|
||||||
|
awxfifo.write(TRIGGER_CHAIN_RELOAD)
|
||||||
|
|
||||||
|
|
||||||
|
def _reset_celery_thread_pool():
|
||||||
|
# Send signal to restart thread pool
|
||||||
|
app = current_app._get_current_object()
|
||||||
|
app.control.broadcast('pool_restart', arguments={'reload': True},
|
||||||
|
destination=['celery@{}'.format(settings.CLUSTER_HOST_ID)], reply=False)
|
||||||
|
|
||||||
|
|
||||||
|
def _supervisor_service_restart(service_internal_names):
|
||||||
|
'''
|
||||||
|
Service internal name options:
|
||||||
|
- beat - celery - callback - channels - uwsgi - daphne
|
||||||
|
- fact - nginx
|
||||||
|
example use pattern of supervisorctl:
|
||||||
|
# supervisorctl restart tower-processes:receiver tower-processes:factcacher
|
||||||
|
'''
|
||||||
|
group_name = 'tower-processes'
|
||||||
|
args = ['supervisorctl']
|
||||||
|
if settings.DEBUG:
|
||||||
|
args.extend(['-c', '/supervisor.conf'])
|
||||||
|
programs = []
|
||||||
|
name_translation_dict = settings.SERVICE_NAME_DICT
|
||||||
|
for n in service_internal_names:
|
||||||
|
if n in name_translation_dict:
|
||||||
|
programs.append('{}:{}'.format(group_name, name_translation_dict[n]))
|
||||||
|
args.extend(['restart'])
|
||||||
|
args.extend(programs)
|
||||||
|
logger.debug('Issuing command to restart services, args={}'.format(args))
|
||||||
|
subprocess.Popen(args)
|
||||||
|
|
||||||
|
|
||||||
|
def restart_local_services(service_internal_names):
|
||||||
|
logger.warn('Restarting services {} on this node in response to user action'.format(service_internal_names))
|
||||||
|
if 'uwsgi' in service_internal_names:
|
||||||
|
_uwsgi_reload()
|
||||||
|
service_internal_names.remove('uwsgi')
|
||||||
|
restart_celery = False
|
||||||
|
if 'celery' in service_internal_names:
|
||||||
|
restart_celery = True
|
||||||
|
service_internal_names.remove('celery')
|
||||||
|
_supervisor_service_restart(service_internal_names)
|
||||||
|
if restart_celery:
|
||||||
|
# Celery restarted last because this probably includes current process
|
||||||
|
_reset_celery_thread_pool()
|
||||||
|
|
||||||
@@ -122,5 +122,5 @@ SERVICE_NAME_DICT = {
|
|||||||
"fact": "factcacher",
|
"fact": "factcacher",
|
||||||
"nginx": "nginx"}
|
"nginx": "nginx"}
|
||||||
# Used for sending commands in automatic restart
|
# Used for sending commands in automatic restart
|
||||||
uWSGI_FIFO_LOCATION = '/awxfifo'
|
UWSGI_FIFO_LOCATION = '/awxfifo'
|
||||||
|
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ SERVICE_NAME_DICT = {
|
|||||||
"daphne": "awx-daphne",
|
"daphne": "awx-daphne",
|
||||||
"fact": "awx-fact-cache-receiver"}
|
"fact": "awx-fact-cache-receiver"}
|
||||||
# Used for sending commands in automatic restart
|
# Used for sending commands in automatic restart
|
||||||
uWSGI_FIFO_LOCATION = '/var/lib/awx/awxfifo'
|
UWSGI_FIFO_LOCATION = '/var/lib/awx/awxfifo'
|
||||||
|
|
||||||
# Store a snapshot of default settings at this point before loading any
|
# Store a snapshot of default settings at this point before loading any
|
||||||
# customizable config files.
|
# customizable config files.
|
||||||
|
|||||||
Reference in New Issue
Block a user