Skip to content

Commit 74b7934

Browse files
authored
Merge pull request #710 from s1113950/issue655
Handles a `wait_for_connection` call right after a task caused a shutdown
2 parents cee088f + acde13f commit 74b7934

File tree

5 files changed

+107
-2
lines changed

5 files changed

+107
-2
lines changed

ansible_mitogen/mixins.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,13 @@ def _execute_module(self, module_name=None, module_args=None, tmp=None,
371371
self._compute_environment_string(env)
372372
self._set_temp_file_args(module_args, wrap_async)
373373

374+
# there's a case where if a task shuts down the node and then immediately calls
375+
# wait_for_connection, the `ping` test from Ansible won't pass because we lost connection
376+
# clearing out context forces a reconnect
377+
# see https://github.com/dw/mitogen/issues/655 and Ansible's `wait_for_connection` module for more info
378+
if module_name == 'ping' and type(self).__name__ == 'wait_for_connection':
379+
self._connection.context = None
380+
374381
self._connection._connect()
375382
result = ansible_mitogen.planner.invoke(
376383
ansible_mitogen.planner.Invocation(

ansible_mitogen/services.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,12 @@ def reset(self, stack):
170170
"""
171171
LOG.debug('%r.reset(%r)', self, stack)
172172

173+
# this could happen if we have a `shutdown -r` shell command
174+
# and then a `wait_for_connection` right afterwards
175+
# in this case, we have no stack to disconnect from
176+
if not stack:
177+
return False
178+
173179
l = mitogen.core.Latch()
174180
context = None
175181
with self._lock:

mitogen/service.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ def func_name(func):
7474

7575

7676
@mitogen.core.takes_router
77-
def get_or_create_pool(size=None, router=None):
77+
def get_or_create_pool(size=None, router=None, context=None):
7878
global _pool
7979
global _pool_pid
8080

@@ -84,6 +84,12 @@ def get_or_create_pool(size=None, router=None):
8484
_pool_lock.acquire()
8585
try:
8686
if _pool_pid != my_pid:
87+
if router is None:
88+
# fallback to trying to get router from context if that exists
89+
if context is not None:
90+
router = context.router
91+
else:
92+
raise ValueError("Unable to create Pool! Missing router.")
8793
_pool = Pool(
8894
router,
8995
services=[],
@@ -119,7 +125,7 @@ def call(service_name, method_name, call_context=None, **kwargs):
119125
if call_context:
120126
return call_context.call_service(service_name, method_name, **kwargs)
121127
else:
122-
pool = get_or_create_pool()
128+
pool = get_or_create_pool(context=kwargs.get('context'))
123129
invoker = pool.get_invoker(service_name, msg=None)
124130
return getattr(invoker.service, method_name)(**kwargs)
125131

tests/ansible/regression/all.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@
1212
- include: issue_590__sys_modules_crap.yml
1313
- include: issue_591__setuptools_cwd_crash.yml
1414
- include: issue_615__streaming_transfer.yml
15+
- include: issue_655__wait_for_connection_error.yml
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# https://github.com/dw/mitogen/issues/655
2+
# Spins up a Centos8 container and runs the wait_for_connection test inside of it
3+
# Doing it this way because the shutdown command causes issues in our tests
4+
# since things are ran on localhost; Azure DevOps loses connection and fails
5+
# TODO: do we want to install docker a different way to be able to do this for other tests too
6+
---
7+
# this should only run on our Mac hosts
8+
- hosts: target
9+
any_errors_fatal: True
10+
gather_facts: yes
11+
become: no
12+
tasks:
13+
- name: set up test container and run tests inside it
14+
block:
15+
- name: install deps
16+
block:
17+
- name: install docker
18+
shell: |
19+
# NOTE: for tracking purposes: https://github.com/docker/for-mac/issues/2359
20+
# using docker for mac CI workaround: https://github.com/drud/ddev/pull/1748/files#diff-19288f650af2dabdf1dcc5b354d1f245
21+
DOCKER_URL=https://download.docker.com/mac/stable/31259/Docker.dmg &&
22+
curl -O -sSL $DOCKER_URL &&
23+
open -W Docker.dmg && cp -r /Volumes/Docker/Docker.app /Applications
24+
sudo /Applications/Docker.app/Contents/MacOS/Docker --quit-after-install --unattended &&
25+
ln -s /Applications/Docker.app/Contents/Resources/bin/docker /usr/local/bin/docker &&
26+
nohup /Applications/Docker.app/Contents/MacOS/Docker --unattended &
27+
# wait 2 min for docker to come up
28+
counter=0 &&
29+
while ! /usr/local/bin/docker ps 2>/dev/null ; do
30+
if [ $counter -lt 24 ]; then
31+
let counter=counter+1
32+
else
33+
exit 1
34+
fi
35+
sleep 5
36+
done
37+
38+
# python bindings (docker_container) aren't working on this host, so gonna shell out
39+
- name: create docker container
40+
shell: /usr/local/bin/docker run --name testMitogen -d --rm centos:8 bash -c "sleep infinity & wait"
41+
42+
- name: add container to inventory
43+
add_host:
44+
name: testMitogen
45+
ansible_connection: docker
46+
ansible_user: root
47+
changed_when: false
48+
environment:
49+
PATH: /usr/local/bin/:{{ ansible_env.PATH }}
50+
51+
- name: run tests
52+
block:
53+
# to repro the issue, will create /var/run/reboot-required
54+
- name: create test file
55+
file:
56+
path: /var/run/reboot-required
57+
state: touch
58+
59+
- name: Check if reboot is required
60+
stat:
61+
path: /var/run/reboot-required
62+
register: reboot_required
63+
64+
- name: Reboot server
65+
shell: sleep 2 && shutdown -r now "Ansible updates triggered"
66+
async: 1
67+
poll: 0
68+
when: reboot_required.stat.exists == True
69+
70+
- name: Wait 300 seconds for server to become available
71+
wait_for_connection:
72+
delay: 30
73+
timeout: 300
74+
when: reboot_required.stat.exists == True
75+
76+
- name: cleanup test file
77+
file:
78+
path: /var/run/reboot-required
79+
state: absent
80+
delegate_to: testMitogen
81+
environment:
82+
PATH: /usr/local/bin/:{{ ansible_env.PATH }}
83+
84+
- name: remove test container
85+
shell: /usr/local/bin/docker stop testMitogen

0 commit comments

Comments
 (0)