Ansible vsphere_file单vCenter报timeout对象不支持索引错误
问题背景
- 运行环境:在VMware环境中使用Ansible执行自动化运维任务,共部署2套vCenter环境,所有任务运行在同一台Ansible控制节点上,使用相同的操作账号与权限配置。节点运行版本为Ansible 2.9.27、Python 2.7.5及对应版本VMware SDK,两套vCenter/ESXi的版本、访问权限配置完全一致。
- 异常表现:调用
community.vmware.vsphere_file模块实现本地数据存储目录创建的任务,仅在其中一套vCenter上执行失败,任务配置参考官方模块文档编写,配置内容如下:
- name: Create directories on local datastore community.vmware.vsphere_file: host: "{{ vcenter_server }}" username: "{{ provider.user }}" password: "{{ provider.password }}" validate_certs: "{{ provider.validate_certs }}" #esxi_hostname: "{{ inventory_hostname }}" datacenter: "{{ vcenter_datacenter }}" datastore: "{{ local_log_datastore_prefix }}" path: "{{ item }}" state: directory loop: "{{ esxi_local_datastore_folders }}"
报错详情
任务执行时首先触发socket.timeout: The read operation timed out读超时错误,在异常处理阶段抛出TypeError: 'timeout' object does not support indexing报错,完整执行日志如下:
<localhost> ESTABLISH LOCAL CONNECTION FOR USER: root <localhost> EXEC /bin/sh -c 'echo ~root && sleep 0' <localhost> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /root/.ansible/tmp `"&& mkdir "` echo /root/.ansible/tmp/ansible-tmp-1657748234.07-77454-176593688580855 `" && echo ansible-tmp-1657748234.07-77454-176593688580855="` echo /root/.ansible/tmp/ansible-tmp-1657748234.07-77454-176593688580855 `" ) && sleep 0' Using module file /root/.ansible/collections/ansible_collections/community/vmware/plugins/modules/vsphere_file.py <localhost> PUT /root/.ansible/tmp/ansible-local-774132iPz96/tmpUa3kiC TO /root/.ansible/tmp/ansible-tmp-1657748234.07-77454-176593688580855/AnsiballZ_vsphere_file.py <localhost> EXEC /bin/sh -c 'chmod u+x /root/.ansible/tmp/ansible-tmp-1657748234.07-77454-176593688580855/ /root/.ansible/tmp/ansible-tmp-1657748234.07-77454-176593688580855/AnsiballZ_vsphere_file.py && sleep 0' <localhost> EXEC /bin/sh -c '/usr/bin/python3 /root/.ansible/tmp/ansible-tmp-1657748234.07-77454-176593688580855/AnsiballZ_vsphere_file.py && sleep 0' <localhost> EXEC /bin/sh -c 'rm -f -r /root/.ansible/tmp/ansible-tmp-1657748234.07-77454-176593688580855/ > /dev/null 2>&1 && sleep 0' The full traceback is: Traceback (most recent call last): File "/tmp/ansible_community.vmware.vsphere_file_payload_38e7eivm/ansible_community.vmware.vsphere_file_payload.zip/ansible_collections/community/vmware/plugins/modules/vsphere_file.py", line 194, in main File "/tmp/ansible_community.vmware.vsphere_file_payload_38e7eivm/ansible_community.vmware.vsphere_file_payload.zip/ansible/module_utils/urls.py", line 1390, in open_url File "/tmp/ansible_community.vmware.vsphere_file_payload_38e7eivm/ansible_community.vmware.vsphere_file_payload.zip/ansible/module_utils/urls.py", line 1294, in open File "/usr/lib64/python3.6/urllib/request.py", line 223, in urlopen return opener.open(url, data, timeout) File "/usr/lib64/python3.6/urllib/request.py", line 526, in open response = self._open(req, data) File "/usr/lib64/python3.6/urllib/request.py", line 544, in _open '_open', req) File "/usr/lib64/python3.6/urllib/request.py", line 504, in _call_chain result = func(*args) File "/tmp/ansible_community.vmware.vsphere_file_payload_38e7eivm/ansible_community.vmware.vsphere_file_payload.zip/ansible/module_utils/urls.py", line 467, in https_open File "/usr/lib64/python3.6/urllib/request.py", line 1352, in do_open r = h.getresponse() File "/usr/lib64/python3.6/http/client.py", line 1346, in getresponse response.begin() File "/usr/lib64/python3.6/http/client.py", line 307, in begin version, status, reason = self._read_status() File "/usr/lib64/python3.6/http/client.py", line 268, in _read_status line = str(self.fp.readline(_MAXLINE + 1), "iso-8859-1") File "/usr/lib64/python3.6/socket.py", line 586, in readinto return self._sock.recv_into(b) File "/usr/lib64/python3.6/ssl.py", line 971, in recv_into return self.read(nbytes, buffer) File "/usr/lib64/python3.6/ssl.py", line 833, in read return self._sslobj.read(len, buffer) File "/usr/lib64/python3.6/ssl.py", line 590, in read v = self._sslobj.read(len, buffer) socket.timeout: The read operation timed out
异常处理阶段触发的二次报错栈如下:
Traceback (most recent call last): File "/root/.ansible/tmp/ansible-tmp-1657748244.8-77454-4966237197380/AnsiballZ_vsphere_file.py", line 102, in <module> _ansiballz_main() File "/root/.ansible/tmp/ansible-tmp-1657748244.8-77454-4966237197380/AnsiballZ_vsphere_file.py", line 94, in _ansiballz_main invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS) File "/root/.ansible/tmp/ansible-tmp-1657748244.8-77454-4966237197380/AnsiballZ_vsphere_file.py", line 40, in invoke_module runpy.run_module(mod_name='ansible_collections.community.vmware.plugins.modules.vsphere_file', init_globals=None, run_name='__main__', alter_sys=True) File "/usr/lib64/python3.6/runpy.py", line 205, in run_module return _run_module_code(code, init_globals, run_name, mod_spec) File "/usr/lib64/python3.6/runpy.py", line 96, in _run_module_code mod_name, mod_spec, pkg_name, script_name) File "/usr/lib64/python3.6/runpy.py", line 85, in _run_code exec(code, run_globals) File "/tmp/ansible_community.vmware.vsphere_file_payload_ds9zbmfy/ansible_community.vmware.vsphere_file_payload.zip/ansible_collections/community/vmware/plugins/modules/vsphere_file.py", line 349, in <module> File "/tmp/ansible_community.vmware.vsphere_file_payload_ds9zbmfy/ansible_community.vmware.vsphere_file_payload.zip/ansible_collections/community/vmware/plugins/modules/vsphere_file.py", line 198, in main TypeError: 'timeout' object does not support indexing failed: [server01.loc -> localhost] (item=.locker-server01.loc) => { "ansible_loop_var": "item", "changed": false, "item": ".locker-server01.loc", "module_stderr": "Traceback (most recent call last):\n File \"/tmp/ansible_community.vmware.vsphere_file_payload_ds9zbmfy/ansible_community.vmware.vsphere_file_payload.zip/ansible_collections/community/vmware/plugins/modules/vsphere_file.py\", line 194, in main\n File \"/tmp/ansible_community.vmware.vsphere_file_payload_ds9zbmfy/ansible_community.vmware.vsphere_file_payload.zip/ansible/module_utils/urls.py\", line 1390, in open_url\n File \"/tmp/ansible_community.vmware.vsphere_file_payload_ds9zbmfy/ansible_community.vmware.vsphere_file_payload.zip/ansible/module_utils/urls.py\", line 1294, in open\n File \"/usr/lib64/python3.6/urllib/request.py\", line 223, in urlopen\n return opener.open(url, data, timeout)\n File \"/usr/lib64/python3.6/urllib/request.py\", line 526, in open\n response = self._open(req, data)\n File \"/usr/lib64/python3.6/urllib/request.py\", line 544, in _open\n '_open', req)\n File \"/usr/lib64/python3.6/urllib/request.py\", line 504, in _call_chain\n result = func(*args)\n File \"/tmp/ansible_community.vmware.vsphere_file_payload_ds9zbmfy/ansible_community.vmware.vsphere_file_payload.zip/ansible/module_utils/urls.py\", line 467, in https_open\n File \"/usr/lib64/python3.6/urllib/request.py\", line 1352, in do_open\n r = h.getresponse()\n File \"/usr/lib64/python3.6/http/client.py\", line 1346, in getresponse\n response.begin()\n File \"/usr/lib64/python3.6/http/client.py\", line 307, in begin\n version, status, reason = self._read_status()\n File \"/usr/lib64/python3.6/http/client.py\", line 268, in _read_status\n line = str(self.fp.readline(_MAXLINE + 1), \"iso-8859-1\")\n File \"/usr/lib64/python3.6/socket.py\", line 586, in readinto\n return self._sock.recv_into(b)\n File \"/usr/lib64/python3.6/ssl.py\", line 971, in recv_into\n return self.read(nbytes, buffer)\n File \"/usr/lib64/python3.6/ssl.py\", line 833, in read\n return self._sslobj.read(len, buffer)\n File \"/usr/lib64/python3.6/ssl.py\", line 590, in read\n v = self._sslobj.read(len, buffer)\nsocket.timeout: The read operation timed out\n\nDuring handling of the above exception, another exception occurred:\n\nTraceback (most recent call last):\n File \"/root/.ansible/tmp/ansible-tmp-1657748244.8-77454-4966237197380/AnsiballZ_vsphere_file.py\", line 102, in <module>\n _ansiballz_main()\n File \"/root/.ansible/tmp/ansible-tmp-1657748244.8-77454-4966237197380/AnsiballZ_vsphere_file.py\", line 94, in _ansiballz_main\n invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\n File \"/root/.ansible/tmp/ansible-tmp-1657748244.8-77454-4966237197380/AnsiballZ_vsphere_file.py\", line 40, in invoke_module\n runpy.run_module(mod_name='ansible_collections.community.vmware.plugins.modules.vsphere_file', init_globals=None, run_name='__main__', alter_sys=True)\n File \"/usr/lib64/python3.6/runpy.py\", line 205, in run_module\n return _run_module_code(code, init_globals, run_name, mod_spec)\n File \"/usr/lib64/python3.6/runpy.py\", line 96, in _run_module_code\n mod_name, mod_spec, pkg_name, script_name)\n File \"/usr/lib64/python3.6/runpy.py\", line 85, in _run_code\n exec(code, run_globals)\n File \"/tmp/ansible_community.vmware.vsphere_file_payload_ds9zbmfy/ansible_community.vmware.vsphere_file_payload.zip/ansible_collections/community/vmware/plugins/modules/vsphere_file.py\", line 349, in <module>\n File \"/tmp/ansible_community.vmware.vsphere_file_payload_ds9zbmfy/ansible_community.vmware.vsphere_file_payload.zip/ansible_collections/community/vmware/plugins/modules/vsphere_file.py\", line 198, in main\nTypeError: 'timeout' object does not support indexing\n", "module_stdout": "", "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error", "rc": 1 }
根因分析
问题实际由两个独立原因叠加导致:
- 核心触发原因:网络连通性故障
vsphere_file模块操作本地存储时,默认不会通过vCenter API代理请求,而是从vCenter查询到目标ESXi主机的管理地址后,直接向ESXi主机的443端口发起HTTP请求创建目录。当前任务中esxi_hostname参数被注释,模块会自动匹配关联ESXi地址发起直连。
两套vCenter环境配置完全一致但仅一套失败,本质是Ansible控制节点到失败环境下目标ESXi主机的管理网443端口连通性异常,常见诱因包括路由策略拦截、防火墙规则放通不全、ESXi管理地址缺少DNS解析或本地hosts映射,导致连接建立后长时间无响应触发读超时。正常运行的那套环境,控制节点到ESXi管理网的直连网络是通的。 - 次生报错原因:模块代码Bug
你使用的旧版本community.vmware集合中,vsphere_file.py的异常捕获逻辑存在缺陷:捕获到socket.timeout超时异常后,代码错误地将timeout异常对象当作可索引的元组读取错误码,直接抛出TypeError,把原本的网络超时真实原因覆盖,加大了排查难度。
修复方案
按优先级依次操作即可解决问题:
- 解决网络连通性问题
- 取消任务配置中
esxi_hostname参数的注释,明确指定要操作的ESXi主机地址,避免模块自动解析地址错误 - 在Ansible控制节点上逐台验证到目标ESXi管理地址的443端口连通性,可使用
telnet <ESXi管理IP> 443、curl -k https://<ESXi管理IP>命令测试,打通对应的路由、防火墙规则,配置必要的DNS解析或hosts映射,确保控制节点可以正常访问ESXi的443端口 - 如果安全策略不允许控制节点直连ESXi管理网,可升级community.vmware集合到
- 取消任务配置中
相关产品推荐
相关产品推荐

