|
|
|
@ -34,7 +34,10 @@ from ansible.release import __version__, __author__
|
|
|
|
|
from ansible import constants as C
|
|
|
|
|
from ansible.errors import AnsibleError
|
|
|
|
|
from ansible.utils.unicode import to_bytes, to_unicode
|
|
|
|
|
from ansible.plugins.strategy import action_write_locks
|
|
|
|
|
# Must import strategy and use write_locks from there
|
|
|
|
|
# If we import write_locks directly then we end up binding a
|
|
|
|
|
# variable to the object and then it never gets updated.
|
|
|
|
|
from ansible.plugins import strategy
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
from __main__ import display
|
|
|
|
@ -552,14 +555,29 @@ def _find_snippet_imports(module_name, module_data, module_path, module_args, ta
|
|
|
|
|
zipdata = None
|
|
|
|
|
# Optimization -- don't lock if the module has already been cached
|
|
|
|
|
if os.path.exists(cached_module_filename):
|
|
|
|
|
display.debug('ZIPLOADER: using cached module: %s' % cached_module_filename)
|
|
|
|
|
zipdata = open(cached_module_filename, 'rb').read()
|
|
|
|
|
# Fool the check later... I think we should just remove the check
|
|
|
|
|
py_module_names.add(('basic',))
|
|
|
|
|
else:
|
|
|
|
|
with action_write_locks[module_name]:
|
|
|
|
|
if module_name in strategy.action_write_locks:
|
|
|
|
|
display.debug('ZIPLOADER: Using lock for %s' % module_name)
|
|
|
|
|
lock = strategy.action_write_locks[module_name]
|
|
|
|
|
else:
|
|
|
|
|
# If the action plugin directly invokes the module (instead of
|
|
|
|
|
# going through a strategy) then we don't have a cross-process
|
|
|
|
|
# Lock specifically for this module. Use the "unexpected
|
|
|
|
|
# module" lock instead
|
|
|
|
|
display.debug('ZIPLOADER: Using generic lock for %s' % module_name)
|
|
|
|
|
lock = strategy.action_write_locks[None]
|
|
|
|
|
|
|
|
|
|
display.debug('ZIPLOADER: Acquiring lock')
|
|
|
|
|
with lock:
|
|
|
|
|
display.debug('ZIPLOADER: Lock acquired: %s' % id(lock))
|
|
|
|
|
# Check that no other process has created this while we were
|
|
|
|
|
# waiting for the lock
|
|
|
|
|
if not os.path.exists(cached_module_filename):
|
|
|
|
|
display.debug('ZIPLOADER: Creating module')
|
|
|
|
|
# Create the module zip data
|
|
|
|
|
zipoutput = BytesIO()
|
|
|
|
|
zf = zipfile.ZipFile(zipoutput, mode='w', compression=compression_method)
|
|
|
|
@ -580,15 +598,19 @@ def _find_snippet_imports(module_name, module_data, module_path, module_args, ta
|
|
|
|
|
# Note -- if we have a global function to setup, that would
|
|
|
|
|
# be a better place to run this
|
|
|
|
|
os.mkdir(lookup_path)
|
|
|
|
|
display.debug('ZIPLOADER: Writing module')
|
|
|
|
|
with open(cached_module_filename + '-part', 'w') as f:
|
|
|
|
|
f.write(zipdata)
|
|
|
|
|
|
|
|
|
|
# Rename the file into its final position in the cache so
|
|
|
|
|
# future users of this module can read it off the
|
|
|
|
|
# filesystem instead of constructing from scratch.
|
|
|
|
|
display.debug('ZIPLOADER: Renaming module')
|
|
|
|
|
os.rename(cached_module_filename + '-part', cached_module_filename)
|
|
|
|
|
display.debug('ZIPLOADER: Done creating module')
|
|
|
|
|
|
|
|
|
|
if zipdata is None:
|
|
|
|
|
display.debug('ZIPLOADER: Reading module after lock')
|
|
|
|
|
# Another process wrote the file while we were waiting for
|
|
|
|
|
# the write lock. Go ahead and read the data from disk
|
|
|
|
|
# instead of re-creating it.
|
|
|
|
|