Skip to content

Commit 83b33a8

Browse files
committed
Merge remote-tracking branch 'origin/linear2'
* origin/linear2: [linear2] fix another test relying on Connection.parent [linear2] more merge fallout, fix Connection._mitogen_reset(mode=) [linear2] update mitogen_get_stack for new _build_stack() return value [linear2] fix mitogen_shutdown_all service context access docs: changelog concision / additions add 363 to changelog docs: update Changelog docs: note fd usage has halved docs: more stream-refactor work docs: update Changelog for stream-refactor. docs: Add lineinfile bug to changelog. [linear2] fix MuxProcess test fixture and some merge fallout service: avoid taking another lock in the usual case service: don't acquire lock when pool already initialized profiler: marginal improvements core: ensure 'exit' signal fires even on Broker crash. core: wake Waker outside of lock. core: wake Latch outside of lock. core: remove old blocking call guard, it's in the wrong place Make setting affinity optional. ansible: abstract worker process model. [stream-refactor] parent: fix crash on graceful shutdown parent: tidy up create_socketpair() core: more concise Side.repr.
2 parents a5619a6 + 1151455 commit 83b33a8

File tree

17 files changed

+852
-382
lines changed

17 files changed

+852
-382
lines changed

ansible_mitogen/connection.py

Lines changed: 36 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import time
3939

4040
import jinja2.runtime
41+
from ansible.module_utils import six
4142
import ansible.constants as C
4243
import ansible.errors
4344
import ansible.plugins.connection
@@ -459,15 +460,10 @@ def call(self, func, *args, **kwargs):
459460

460461

461462
class Connection(ansible.plugins.connection.ConnectionBase):
462-
#: mitogen.master.Broker for this worker.
463-
broker = None
464-
465-
#: mitogen.master.Router for this worker.
466-
router = None
467-
468-
#: mitogen.parent.Context representing the parent Context, which is
469-
#: presently always the connection multiplexer process.
470-
parent = None
463+
#: The :class:`ansible_mitogen.process.Binding` representing the connection
464+
#: multiplexer this connection's target is assigned to. :data:`None` when
465+
#: disconnected.
466+
binding = None
471467

472468
#: mitogen.parent.Context for the target account on the target, possibly
473469
#: reached via become.
@@ -518,13 +514,6 @@ class Connection(ansible.plugins.connection.ConnectionBase):
518514
#: matching vanilla Ansible behaviour.
519515
loader_basedir = None
520516

521-
def __init__(self, play_context, new_stdin, **kwargs):
522-
assert ansible_mitogen.process.MuxProcess.unix_listener_path, (
523-
'Mitogen connection types may only be instantiated '
524-
'while the "mitogen" strategy is active.'
525-
)
526-
super(Connection, self).__init__(play_context, new_stdin)
527-
528517
def __del__(self):
529518
"""
530519
Ansible cannot be trusted to always call close() e.g. the synchronize
@@ -585,6 +574,15 @@ def homedir(self):
585574
self._connect()
586575
return self.init_child_result['home_dir']
587576

577+
def get_binding(self):
578+
"""
579+
Return the :class:`ansible_mitogen.process.Binding` representing the
580+
process that hosts the physical connection and services (context
581+
establishment, file transfer, ..) for our desired target.
582+
"""
583+
assert self.binding is not None
584+
return self.binding
585+
588586
@property
589587
def connected(self):
590588
return self.context is not None
@@ -672,33 +670,21 @@ def _stack_from_spec(self, spec, stack=(), seen_names=()):
672670

673671
return stack
674672

675-
def _connect_broker(self):
676-
"""
677-
Establish a reference to the Broker, Router and parent context used for
678-
connections.
679-
"""
680-
if not self.broker:
681-
self.broker = mitogen.master.Broker()
682-
self.router, self.parent = mitogen.unix.connect(
683-
path=ansible_mitogen.process.MuxProcess.unix_listener_path,
684-
broker=self.broker,
685-
)
686-
687673
def _build_stack(self):
688674
"""
689675
Construct a list of dictionaries representing the connection
690676
configuration between the controller and the target. This is
691677
additionally used by the integration tests "mitogen_get_stack" action
692678
to fetch the would-be connection configuration.
693679
"""
694-
return self._stack_from_spec(
695-
ansible_mitogen.transport_config.PlayContextSpec(
696-
connection=self,
697-
play_context=self._play_context,
698-
transport=self.transport,
699-
inventory_name=self.inventory_hostname,
700-
)
680+
spec = ansible_mitogen.transport_config.PlayContextSpec(
681+
connection=self,
682+
play_context=self._play_context,
683+
transport=self.transport,
684+
inventory_name=self.inventory_hostname,
701685
)
686+
stack = self._stack_from_spec(spec)
687+
return spec.inventory_name(), stack
702688

703689
def _connect_stack(self, stack):
704690
"""
@@ -711,7 +697,8 @@ def _connect_stack(self, stack):
711697
description of the returned dictionary.
712698
"""
713699
try:
714-
dct = self.parent.call_service(
700+
dct = mitogen.service.call(
701+
call_context=self.binding.get_service_context(),
715702
service_name='ansible_mitogen.services.ContextService',
716703
method_name='get',
717704
stack=mitogen.utils.cast(list(stack)),
@@ -758,8 +745,9 @@ def _connect(self):
758745
if self.connected:
759746
return
760747

761-
self._connect_broker()
762-
stack = self._build_stack()
748+
inventory_name, stack = self._build_stack()
749+
worker_model = ansible_mitogen.process.get_worker_model()
750+
self.binding = worker_model.get_binding(inventory_name)
763751
self._connect_stack(stack)
764752

765753
def _mitogen_reset(self, mode):
@@ -776,7 +764,8 @@ def _mitogen_reset(self, mode):
776764
return
777765

778766
self.chain.reset()
779-
self.parent.call_service(
767+
mitogen.service.call(
768+
call_context=self.binding.get_service_context(),
780769
service_name='ansible_mitogen.services.ContextService',
781770
method_name=mode,
782771
context=self.context
@@ -787,35 +776,16 @@ def _mitogen_reset(self, mode):
787776
self.init_child_result = None
788777
self.chain = None
789778

790-
def _shutdown_broker(self):
791-
"""
792-
Shutdown the broker thread during :meth:`close` or :meth:`reset`.
793-
"""
794-
if self.broker:
795-
self.broker.shutdown()
796-
self.broker.join()
797-
self.broker = None
798-
self.router = None
799-
800-
# #420: Ansible executes "meta" actions in the top-level process,
801-
# meaning "reset_connection" will cause :class:`mitogen.core.Latch`
802-
# FDs to be cached and erroneously shared by children on subsequent
803-
# WorkerProcess forks. To handle that, call on_fork() to ensure any
804-
# shared state is discarded.
805-
# #490: only attempt to clean up when it's known that some
806-
# resources exist to cleanup, otherwise later __del__ double-call
807-
# to close() due to GC at random moment may obliterate an unrelated
808-
# Connection's resources.
809-
mitogen.fork.on_fork()
810-
811779
def close(self):
812780
"""
813781
Arrange for the mitogen.master.Router running in the worker to
814782
gracefully shut down, and wait for shutdown to complete. Safe to call
815783
multiple times.
816784
"""
817785
self._mitogen_reset(mode='put')
818-
self._shutdown_broker()
786+
if self.binding:
787+
self.binding.close()
788+
self.binding = None
819789

820790
def _reset_find_task_vars(self):
821791
"""
@@ -853,7 +823,8 @@ def reset(self):
853823

854824
self._connect()
855825
self._mitogen_reset(mode='reset')
856-
self._shutdown_broker()
826+
self.binding.close()
827+
self.binding = None
857828

858829
# Compatibility with Ansible 2.4 wait_for_connection plug-in.
859830
_reset = reset
@@ -1024,7 +995,8 @@ def put_file(self, in_path, out_path):
1024995
utimes=(st.st_atime, st.st_mtime))
1025996

1026997
self._connect()
1027-
self.parent.call_service(
998+
mitogen.service.call(
999+
call_context=self.binding.get_service_context(),
10281000
service_name='mitogen.service.FileService',
10291001
method_name='register',
10301002
path=mitogen.utils.cast(in_path)
@@ -1036,7 +1008,7 @@ def put_file(self, in_path, out_path):
10361008
# file alive, but that requires more work.
10371009
self.get_chain().call(
10381010
ansible_mitogen.target.transfer_file,
1039-
context=self.parent,
1011+
context=self.binding.get_child_service_context(),
10401012
in_path=in_path,
10411013
out_path=out_path
10421014
)

ansible_mitogen/planner.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,14 +148,16 @@ def get_kwargs(self, **kwargs):
148148
# named by `runner_name`.
149149
}
150150
"""
151+
binding = self._inv.connection.get_binding()
152+
151153
new = dict((mitogen.core.UnicodeType(k), kwargs[k])
152154
for k in kwargs)
153155
new.setdefault('good_temp_dir',
154156
self._inv.connection.get_good_temp_dir())
155157
new.setdefault('cwd', self._inv.connection.get_default_cwd())
156158
new.setdefault('extra_env', self._inv.connection.get_default_env())
157159
new.setdefault('emulate_tty', True)
158-
new.setdefault('service_context', self._inv.connection.parent)
160+
new.setdefault('service_context', binding.get_child_service_context())
159161
return new
160162

161163
def __repr__(self):
@@ -328,7 +330,9 @@ def get_search_path(self):
328330

329331
def get_module_map(self):
330332
if self._module_map is None:
331-
self._module_map = self._inv.connection.parent.call_service(
333+
binding = self._inv.connection.get_binding()
334+
self._module_map = mitogen.service.call(
335+
call_context=binding.get_service_context(),
332336
service_name='ansible_mitogen.services.ModuleDepService',
333337
method_name='scan',
334338

@@ -405,9 +409,12 @@ def get_module_data(name):
405409

406410

407411
def _propagate_deps(invocation, planner, context):
408-
invocation.connection.parent.call_service(
412+
binding = invocation.connection.get_binding()
413+
mitogen.service.call(
414+
call_context=binding.get_service_context(),
409415
service_name='mitogen.service.PushFileService',
410416
method_name='propagate_paths_and_modules',
417+
411418
context=context,
412419
paths=planner.get_push_files(),
413420
modules=planner.get_module_deps(),

ansible_mitogen/plugins/action/mitogen_get_stack.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,9 @@ def run(self, tmp=None, task_vars=None):
4747
'skipped': True,
4848
}
4949

50+
_, stack = self._connection._build_stack()
5051
return {
5152
'changed': True,
52-
'result': self._connection._build_stack(),
53+
'result': stack,
5354
'_ansible_verbose_always': True,
5455
}

ansible_mitogen/plugins/connection/mitogen_local.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,6 @@ def get_default_env(self):
8181
from WorkerProcess, we must emulate that.
8282
"""
8383
return dict_diff(
84-
old=ansible_mitogen.process.MuxProcess.original_env,
84+
old=ansible_mitogen.process.MuxProcess.cls_original_env,
8585
new=os.environ,
8686
)

0 commit comments

Comments
 (0)