mirror of
https://github.com/ansible/awx.git
synced 2026-03-01 08:48:46 -03:30
Merge pull request #1629 from chrismeyersfsu/fix-stable_broadcast_queue_name
broadcast queues get a per-node stable queue name
This commit is contained in:
@@ -189,7 +189,7 @@ def apply_cluster_membership_policies(self):
|
|||||||
handle_ha_toplogy_changes.apply([])
|
handle_ha_toplogy_changes.apply([])
|
||||||
|
|
||||||
|
|
||||||
@shared_task(queue='tower_broadcast_all', bind=True)
|
@shared_task(exchange='tower_broadcast_all', bind=True)
|
||||||
def handle_setting_changes(self, setting_keys):
|
def handle_setting_changes(self, setting_keys):
|
||||||
orig_len = len(setting_keys)
|
orig_len = len(setting_keys)
|
||||||
for i in range(orig_len):
|
for i in range(orig_len):
|
||||||
@@ -208,7 +208,7 @@ def handle_setting_changes(self, setting_keys):
|
|||||||
restart_local_services(['uwsgi'])
|
restart_local_services(['uwsgi'])
|
||||||
|
|
||||||
|
|
||||||
@shared_task(bind=True, queue='tower_broadcast_all')
|
@shared_task(bind=True, exchange='tower_broadcast_all')
|
||||||
def handle_ha_toplogy_changes(self):
|
def handle_ha_toplogy_changes(self):
|
||||||
(changed, instance) = Instance.objects.get_or_register()
|
(changed, instance) = Instance.objects.get_or_register()
|
||||||
if changed:
|
if changed:
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
# python
|
# python
|
||||||
import pytest
|
import pytest
|
||||||
import mock
|
import mock
|
||||||
|
from contextlib import nested
|
||||||
|
|
||||||
# AWX
|
# AWX
|
||||||
from awx.main.utils.ha import (
|
from awx.main.utils.ha import (
|
||||||
@@ -47,22 +48,26 @@ class TestAddRemoveCeleryWorkerQueues():
|
|||||||
app.control.cancel_consumer = mocker.MagicMock()
|
app.control.cancel_consumer = mocker.MagicMock()
|
||||||
return app
|
return app
|
||||||
|
|
||||||
@pytest.mark.parametrize("static_queues,_worker_queues,groups,hostname,added_expected,removed_expected", [
|
@pytest.mark.parametrize("broadcast_queues,static_queues,_worker_queues,groups,hostname,added_expected,removed_expected", [
|
||||||
(['east', 'west'], ['east', 'west', 'east-1'], [], 'east-1', [], []),
|
(['tower_broadcast_all'], ['east', 'west'], ['east', 'west', 'east-1'], [], 'east-1', ['tower_broadcast_all_east-1'], []),
|
||||||
([], ['east', 'west', 'east-1'], ['east', 'west'], 'east-1', [], []),
|
([], [], ['east', 'west', 'east-1'], ['east', 'west'], 'east-1', [], []),
|
||||||
([], ['east', 'west'], ['east', 'west'], 'east-1', ['east-1'], []),
|
([], [], ['east', 'west'], ['east', 'west'], 'east-1', ['east-1'], []),
|
||||||
([], [], ['east', 'west'], 'east-1', ['east', 'west', 'east-1'], []),
|
([], [], [], ['east', 'west'], 'east-1', ['east', 'west', 'east-1'], []),
|
||||||
([], ['china', 'russia'], ['east', 'west'], 'east-1', ['east', 'west', 'east-1'], ['china', 'russia']),
|
([], [], ['china', 'russia'], ['east', 'west'], 'east-1', ['east', 'west', 'east-1'], ['china', 'russia']),
|
||||||
])
|
])
|
||||||
def test__add_remove_celery_worker_queues_noop(self, mock_app,
|
def test__add_remove_celery_worker_queues_noop(self, mock_app,
|
||||||
instance_generator,
|
instance_generator,
|
||||||
worker_queues_generator,
|
worker_queues_generator,
|
||||||
|
broadcast_queues,
|
||||||
static_queues, _worker_queues,
|
static_queues, _worker_queues,
|
||||||
groups, hostname,
|
groups, hostname,
|
||||||
added_expected, removed_expected):
|
added_expected, removed_expected):
|
||||||
instance = instance_generator(groups=groups, hostname=hostname)
|
instance = instance_generator(groups=groups, hostname=hostname)
|
||||||
worker_queues = worker_queues_generator(_worker_queues)
|
worker_queues = worker_queues_generator(_worker_queues)
|
||||||
with mock.patch('awx.main.utils.ha.settings.AWX_CELERY_QUEUES_STATIC', static_queues):
|
with nested(
|
||||||
|
mock.patch('awx.main.utils.ha.settings.AWX_CELERY_QUEUES_STATIC', static_queues),
|
||||||
|
mock.patch('awx.main.utils.ha.settings.AWX_CELERY_BCAST_QUEUES_STATIC', broadcast_queues),
|
||||||
|
mock.patch('awx.main.utils.ha.settings.CLUSTER_HOST_ID', hostname)):
|
||||||
(added_queues, removed_queues) = _add_remove_celery_worker_queues(mock_app, [instance], worker_queues, hostname)
|
(added_queues, removed_queues) = _add_remove_celery_worker_queues(mock_app, [instance], worker_queues, hostname)
|
||||||
assert set(added_queues) == set(added_expected)
|
assert set(added_queues) == set(added_expected)
|
||||||
assert set(removed_queues) == set(removed_expected)
|
assert set(removed_queues) == set(removed_expected)
|
||||||
|
|||||||
@@ -10,6 +10,10 @@ from django.conf import settings
|
|||||||
from awx.main.models import Instance
|
from awx.main.models import Instance
|
||||||
|
|
||||||
|
|
||||||
|
def construct_bcast_queue_name(common_name):
|
||||||
|
return common_name.encode('utf8') + '_' + settings.CLUSTER_HOST_ID
|
||||||
|
|
||||||
|
|
||||||
def _add_remove_celery_worker_queues(app, controlled_instances, worker_queues, worker_name):
|
def _add_remove_celery_worker_queues(app, controlled_instances, worker_queues, worker_name):
|
||||||
removed_queues = []
|
removed_queues = []
|
||||||
added_queues = []
|
added_queues = []
|
||||||
@@ -19,17 +23,14 @@ def _add_remove_celery_worker_queues(app, controlled_instances, worker_queues, w
|
|||||||
ig_names.update(instance.rampart_groups.values_list('name', flat=True))
|
ig_names.update(instance.rampart_groups.values_list('name', flat=True))
|
||||||
worker_queue_names = set([q['name'] for q in worker_queues])
|
worker_queue_names = set([q['name'] for q in worker_queues])
|
||||||
|
|
||||||
|
bcast_queue_names = set([construct_bcast_queue_name(n) for n in settings.AWX_CELERY_BCAST_QUEUES_STATIC])
|
||||||
all_queue_names = ig_names | hostnames | set(settings.AWX_CELERY_QUEUES_STATIC)
|
all_queue_names = ig_names | hostnames | set(settings.AWX_CELERY_QUEUES_STATIC)
|
||||||
|
|
||||||
# Remove queues that aren't in the instance group
|
# Remove queues that aren't in the instance group
|
||||||
for queue in worker_queues:
|
for queue_name in worker_queue_names:
|
||||||
if queue['name'] in settings.AWX_CELERY_QUEUES_STATIC or \
|
if queue_name not in all_queue_names | bcast_queue_names or not instance.enabled:
|
||||||
queue['alias'] in settings.AWX_CELERY_BCAST_QUEUES_STATIC:
|
app.control.cancel_consumer(queue_name.encode("utf8"), reply=True, destination=[worker_name])
|
||||||
continue
|
removed_queues.append(queue_name.encode("utf8"))
|
||||||
|
|
||||||
if queue['name'] not in all_queue_names or not instance.enabled:
|
|
||||||
app.control.cancel_consumer(queue['name'].encode("utf8"), reply=True, destination=[worker_name])
|
|
||||||
removed_queues.append(queue['name'].encode("utf8"))
|
|
||||||
|
|
||||||
# Add queues for instance and instance groups
|
# Add queues for instance and instance groups
|
||||||
for queue_name in all_queue_names:
|
for queue_name in all_queue_names:
|
||||||
@@ -37,6 +38,17 @@ def _add_remove_celery_worker_queues(app, controlled_instances, worker_queues, w
|
|||||||
app.control.add_consumer(queue_name.encode("utf8"), reply=True, destination=[worker_name])
|
app.control.add_consumer(queue_name.encode("utf8"), reply=True, destination=[worker_name])
|
||||||
added_queues.append(queue_name.encode("utf8"))
|
added_queues.append(queue_name.encode("utf8"))
|
||||||
|
|
||||||
|
# Add stable-named broadcast queues
|
||||||
|
for queue_name in settings.AWX_CELERY_BCAST_QUEUES_STATIC:
|
||||||
|
bcast_queue_name = construct_bcast_queue_name(queue_name)
|
||||||
|
if bcast_queue_name not in worker_queue_names:
|
||||||
|
app.control.add_consumer(bcast_queue_name,
|
||||||
|
exchange=queue_name.encode("utf8"),
|
||||||
|
exchange_type='fanout',
|
||||||
|
routing_key=queue_name.encode("utf8"),
|
||||||
|
reply=True)
|
||||||
|
added_queues.append(bcast_queue_name)
|
||||||
|
|
||||||
return (added_queues, removed_queues)
|
return (added_queues, removed_queues)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -9,8 +9,6 @@ import djcelery
|
|||||||
import six
|
import six
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
|
||||||
from kombu.common import Broadcast
|
|
||||||
|
|
||||||
# global settings
|
# global settings
|
||||||
from django.conf import global_settings
|
from django.conf import global_settings
|
||||||
# ugettext lazy
|
# ugettext lazy
|
||||||
@@ -466,9 +464,7 @@ CELERYD_POOL_RESTARTS = True
|
|||||||
CELERYD_AUTOSCALER = 'awx.main.utils.autoscale:DynamicAutoScaler'
|
CELERYD_AUTOSCALER = 'awx.main.utils.autoscale:DynamicAutoScaler'
|
||||||
CELERY_RESULT_BACKEND = 'djcelery.backends.database:DatabaseBackend'
|
CELERY_RESULT_BACKEND = 'djcelery.backends.database:DatabaseBackend'
|
||||||
CELERY_IMPORTS = ('awx.main.scheduler.tasks',)
|
CELERY_IMPORTS = ('awx.main.scheduler.tasks',)
|
||||||
CELERY_QUEUES = (
|
CELERY_QUEUES = ()
|
||||||
Broadcast('tower_broadcast_all'),
|
|
||||||
)
|
|
||||||
CELERY_ROUTES = {}
|
CELERY_ROUTES = {}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user