Repository navigation
Description
ISSUE TYPE
- Bug Report
COMPONENT NAME
file module
ANSIBLE VERSION
currently i am using ansible 2.2 ,python 2.7, but i think it exists in the latest version, because file module fails when shutil.rmtree throws an exception
ansible/lib/ansible/modules/files/file.py
Lines 267 to 282 in 571f878
| if state == 'absent': | |
| if state_change: | |
| if not module.check_mode: | |
| if prev_state == 'directory': | |
| try: | |
| shutil.rmtree(b_path, ignore_errors=False) | |
| except Exception as e: | |
| module.fail_json(msg="rmtree failed: %s" % to_native(e)) | |
| else: | |
| try: | |
| os.unlink(b_path) | |
| except Exception as e: | |
| module.fail_json(path=path, msg="unlinking failed: %s " % to_native(e)) | |
| module.exit_json(path=path, changed=True, diff=diff) | |
| else: | |
| module.exit_json(path=path, changed=False) |
OS / ENVIRONMENT
N/A
SUMMARY
when i use file module ( state=absent )to delete a non-empty directory, ansible throws :
failed:
[20.20.20.22] (item=/usr/libexec/kubernetes) => {"failed": true, "item": "/usr/libexec/kubernetes", "msg": >"rmtree failed: [Errno 39] Directory not empty: '/usr/libexec/kubernetes/kubelet-plugins/volume'"}
related reports:
https://groups.google.com/forum/#!topic/ansible-project/XrKPpnOxD0I
STEPS TO REPRODUCE
this is randomly reproducible, our codes works well for over a year, now we meet one failure.
it seems to be a bug in shutil.rmtree, easybuild workaround this bug by retry invoking shutil.rmtree
https://github.com/easybuilders/easybuild-framework/blob/master/easybuild/tools/filetools.py#L1185
hashdist also workarounds this bug by retry invoking shutil.rmtree
https://github.com/hashdist/hashdist/blob/master/hashdist/core/fileutils.py#L69-L89
Activity
ansibot commentedon Jan 2, 2018
Files identified in the description:
If these files are inaccurate, please update the
component namesection of the description or use the!componentbot command.click here for bot help
yuji-k64613 commentedon Feb 4, 2018
I could not reproduce this OSError.
It works well as follows.
bruceauyeung commentedon Feb 5, 2018
i think this bug can be reproduced with these steps:
orenwolf commentedon Jun 19, 2018
Can confirm this happens if the directory is active and updated by multiple processes, likely leading to a race condition where files are written in after rmtree stats the files to delete but actually deletes them.
dagwieers commentedon Jul 4, 2018
Yup, I don't think you can really fix this, unless you rename the directory prior to recursively removing.
And even then, if a process has the directory entry open, changes can still occur in the directory you're trying to recursively remove.
If you would retry removing files/directories, you might be fighting indefinitely with other processes.
Maybe a clarification in the file module documentation is in order ?
DownRangeDevOps commentedon Sep 8, 2018
This seems very counter intuitive, maybe I'm interpreting this answer wrong or
shutil.rmtreehas changed since 2014?ansible/lib/ansible/modules/files/file.py
Line 421 in 1891827
Seems like the SO answer is saying this should be:
dagwieers commentedon Sep 9, 2018
@techfishio Which would end up not removing the whole tree. Which is not what the user intended. If the user asks operation A to be performed, and operation A did not succeed, we do not want to silently ignore this and continue. So
ignore_error=Trueis pretending everything worked fine.litaozijin commentedon Jul 28, 2019
ansibot commentedon May 16, 2020
Files identified in the description:
lib/ansible/modules/file.pyIf these files are incorrect, please update the
component namesection of the description or use the!componentbot command.click here for bot help
bcoca commentedon Apr 23, 2021
I do not consider this a bug but a race condition, if your left and right hand are doing opposite actions, you expect to get this kind of error. Using retry/until are a good way to deal with this at the task level and should be the playbook author's call and not built into the module as such event should really require a decision from a human closer to the context in which it is run.
So I'm closing this issue.