安装oVirt 4.5.4超融合集群时遇'str object'无'vgname'属性错误
oVirt 4.5.4超融合集群部署Ansible任务报错:'str object' has no attribute 'vgname'
环境信息
- 部署目标:3节点oVirt 4.5.4超融合集群,每节点配备1块SSD(用于安装oVirt节点)+1块HDD
- 本地环境:Python 3.11.2、Ansible 2.14.2
- 使用角色:gluster.infra/roles/backend_setup(与官方仓库内容一致)
问题描述
执行自定义Playbook时,在gluster.infra/roles/backend_setup/tasks/get_vg_groupings.yml的分组任务阶段触发致命错误,所有节点均提示'str object' has no attribute 'vgname',多次尝试无法解决。
Playbook配置
hc_nodes: hosts: node210.com: gluster_infra_volume_groups: - vgname: gluster_vg_sda pvname: /dev/sda gluster_infra_mount_devices: - path: /gluster_bricks/engine lvname: gluster_lv_engine vgname: gluster_vg_sda - path: /gluster_bricks/data lvname: gluster_lv_data vgname: gluster_vg_sda - path: /gluster_bricks/vmstore lvname: gluster_lv_vmstore vgname: gluster_vg_sda blacklist_mpath_devices: - sda gluster_infra_thick_lvs: - vgname: gluster_vg_sda lvname: gluster_lv_engine size: 100G gluster_infra_thinpools: - vgname: gluster_vg_sda thinpoolname: gluster_thinpool_gluster_vg_sda poolmetadatasize: 1G gluster_infra_lv_logicalvols: - vgname: gluster_vg_sda thinpool: gluster_thinpool_gluster_vg_sda lvname: gluster_lv_data lvsize: 150G - vgname: gluster_vg_sda thinpool: gluster_thinpool_gluster_vg_sda lvname: gluster_lv_vmstore lvsize: 150G node211.com: gluster_infra_volume_groups: - vgname: gluster_vg_sda pvname: /dev/sda gluster_infra_mount_devices: - path: /gluster_bricks/engine lvname: gluster_lv_engine vgname: gluster_vg_sda - path: /gluster_bricks/data lvname: gluster_lv_data vgname: gluster_vg_sda - path: /gluster_bricks/vmstore lvname: gluster_lv_vmstore vgname: gluster_vg_sda blacklist_mpath_devices: - sda gluster_infra_thick_lvs: - vgname: gluster_vg_sda lvname: gluster_lv_engine size: 100G gluster_infra_thinpools: - vgname: gluster_vg_sda thinpoolname: gluster_thinpool_gluster_vg_sda poolmetadatasize: 1G gluster_infra_lv_logicalvols: - vgname: gluster_vg_sda thinpool: gluster_thinpool_gluster_vg_sda lvname: gluster_lv_data lvsize: 150G - vgname: gluster_vg_sda thinpool: gluster_thinpool_gluster_vg_sda lvname: gluster_lv_vmstore lvsize: 150G node212.com: gluster_infra_volume_groups: - vgname: gluster_vg_sda pvname: /dev/sda gluster_infra_mount_devices: - path: /gluster_bricks/engine lvname: gluster_lv_engine vgname: gluster_vg_sda - path: /gluster_bricks/data lvname: gluster_lv_data vgname: gluster_vg_sda - path: /gluster_bricks/vmstore lvname: gluster_lv_vmstore vgname: gluster_vg_sda blacklist_mpath_devices: - sda gluster_infra_thick_lvs: - vgname: gluster_vg_sda lvname: gluster_lv_engine size: 100G gluster_infra_thinpools: - vgname: gluster_vg_sda thinpoolname: gluster_thinpool_gluster_vg_sda poolmetadatasize: 1G gluster_infra_lv_logicalvols: - vgname: gluster_vg_sda thinpool: gluster_thinpool_gluster_vg_sda lvname: gluster_lv_data lvsize: 150G - vgname: gluster_vg_sda thinpool: gluster_thinpool_gluster_vg_sda lvname: gluster_lv_vmstore lvsize: 150G vars: gluster_infra_disktype: JBOD gluster_set_selinux_labels: true gluster_infra_fw_ports: - 2049/tcp - 54321/tcp - 5900/tcp - 5900-6923/tcp - 5666/tcp - 16514/tcp gluster_infra_fw_permanent: true gluster_infra_fw_state: enabled gluster_infra_fw_zone: public gluster_infra_fw_services: - glusterfs gluster_features_force_varlogsizecheck: false cluster_nodes: - node210.com - node211.com - node212.com gluster_features_hci_cluster: '{{ cluster_nodes }}' gluster_features_hci_volumes: - volname: engine brick: /gluster_bricks/engine/engine arbiter: 0 - volname: data brick: /gluster_bricks/data/data arbiter: 0 - volname: vmstore brick: /gluster_bricks/vmstore/vmstore arbiter: 0
错误日志
TASK [gluster.infra/roles/backend_setup : Group devices by volume group name, including existing devices] *** task path: /etc/ansible/roles/gluster.infra/roles/backend_setup/tasks/get_vg_groupings.yml:3 fatal: [node210.com]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'str object' has no attribute 'vgname'. 'str object' has no attribute 'vgname'\n\nThe error appears to be in '/etc/ansible/roles/gluster.infra/roles/backend_setup/tasks/get_vg_groupings.yml': line 3, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n- name: Group devices by volume group name, including existing devices\n ^ here\n"} fatal: [node211.com]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'str object' has no attribute 'vgname'. 'str object' has no attribute 'vgname'\n\nThe error appears to be in '/etc/ansible/roles/gluster.infra/roles/backend_setup/tasks/get_vg_groupings.yml': line 3, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n- name: Group devices by volume group name, including existing devices\n ^ here\n"} fatal: [node212.com]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'str object' has no attribute 'vgname'. 'str object' has no attribute 'vgname'\n\nThe error appears to be in '/etc/ansible/roles/gluster.infra/roles/backend_setup/tasks/get_vg_groupings.yml': line 3, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n- name: Group devices by volume group name, including existing devices\n ^ here\n"}
get_vg_groupings.yml任务文件内容
--- - name: Group devices by volume group name, including existing devices set_fact: gluster_volumes_by_groupname_pre: >- {%- set output={} -%} {%- for grouper, devicesConf in volume_groups | groupby('vgname') -%} {%- set confs=[] -%} {%- for deviceConf in devicesConf -%} {%- if deviceConf.pvname is defined -%} {%- for device in deviceConf.pvname.split(',') -%} {%- set deviceConfCln=dict(devicesConf | first) -%} {{- deviceConfCln.__setitem__('pvname',device | trim) -}} {{- confs.append(deviceConfCln) -}} {%- endfor -%} {%- endif -%} {%- endfor -%} {{- output.__setitem__(grouper, confs) -}} {%- endfor -%} {%- if hostvars[inventory_hostname].ansible_lvm is defined and hostvars[inventory_hostname].ansible_lvm.pvs is defined -%} {%- for device, pvs in hostvars[inventory_hostname].ansible_lvm.pvs.items() -%} {%- if pvs.vg in output and output[pvs.vg] | selectattr('pvname','equalto',device) | list | count == 0 -%} {{- output[pvs.vg].append({'pvname':device, 'vgname':pvs.vg }) -}} {%- endif -%} {%- endfor -%} {%- endif -%} {{- output | to_json -}} - name: Check if vg block device exists shell: > {% for pvsname in item.value | ovirt.ovirt.json_query('[].pvname') %} test -b {{ pvsname }} && echo "1" || echo "0"; {% endfor %} register: vg_device_exists loop: "{{gluster_volumes_by_groupname_pre | dict2items}}" - name: Filter none-existing devices set_fact: gluster_volumes_by_groupname: >- {%- set output={} -%} {%- for vgname, devicesConf in gluster_volumes_by_groupname_pre.items() -%} {%- for item in vg_device_exists.results | ovirt.ovirt.json_query('[?item.key==`' ~ vgname ~ '`]') -%} {%- set confs=[] -%} {%- for vgConfig in item.item.value -%} {%- if item.stdout_lines is defined and item.stdout_lines[loop.index0] == "1" -%} {%- set vgConfigCln=dict(item.item.value | first) -%} {{- vgConfigCln.__setitem__('pvname',vgConfig.pvname) -}} {{- confs.append(vgConfigCln) -}} {%- endif -%} {%- endfor -%} {{- output.__setitem__(vgname, confs) -}} {%- endfor -%} {%- endfor -%} {{- output | to_json -}}
问题分析与解决建议
报错核心原因是任务中使用的volume_groups变量被解析为字符串而非预期的字典列表,导致groupby('vgname')无法访问对象属性。
排查与修复方向:
- 变量传递验证:检查角色逻辑是否将
gluster_infra_volume_groups正确赋值给volume_groups,若缺失需手动添加:# 在Playbook的vars或任务中添加 volume_groups: "{{ gluster_infra_volume_groups }}" - 变量冲突排查:确认是否存在同名
volume_groups变量被定义为字符串,覆盖了预期的字典列表。可执行以下命令查看变量实际值:ansible -m debug -a "var=volume_groups" node210.com - 版本兼容性调整:当前Ansible 2.14.2与gluster-ansible-infra角色可能存在兼容性问题,尝试降级Ansible到2.12.x或2.13.x版本。
- 设备路径校验:确认
/dev/sda为正确的物理卷设备,避免因设备不存在或路径错误导致变量解析异常。
内容的提问来源于stack exchange,提问作者charnet1019
相关产品推荐
相关产品推荐

