在Ansible中为已有键添加值:如何合并服务器字典结构避免覆盖?
解决你的两个核心问题:合并服务器配置结构 + 获取未运行VM的MAC地址
一、正确合并两个服务器配置结构(避免覆盖)
你遇到的覆盖问题,核心是没有递归合并子字典——默认的合并操作只会替换顶层键对应的整个值,而不会深入合并子结构。下面分两种常见场景给出解决方案:
1. 如果你用Ansible(适配你的oVirt/Foreman运维场景)
Ansible的combine过滤器默认是顶层合并,加上recursive=True参数就能递归合并子字典,完美解决你的需求:
首先定义你的两个原始变量:
servers_os_role: server1: OS: Win_2016 Role: CT server2: OS: RHEL7 Role: POM servers_mac: server1: MAC: 00:01:02:03:04:05 server2: MAC: 00:01:02:03:04:06
然后用过滤器合并:
combined_servers: "{{ servers_os_role | combine(servers_mac, recursive=True) }}"
合并后的结果会是:
server1: OS: Win_2016 Role: CT MAC: 00:01:02:03:04:05 server2: OS: RHEL7 Role: POM MAC: 00:01:02:03:04:06
2. 如果你用Python做脚本处理
写一个简单的递归合并函数,手动处理子字典的合并逻辑(避免直接用dict.update()覆盖子结构):
def merge_server_configs(base, overlay): # 先复制base字典,避免修改原始数据 merged = base.copy() for server_name, server_data in overlay.items(): if server_name in merged: # 如果是子字典,递归合并;否则直接覆盖(可根据需求调整) if isinstance(merged[server_name], dict) and isinstance(server_data, dict): merged[server_name].update(server_data) else: merged[server_name] = server_data else: merged[server_name] = server_data return merged # 你的原始数据 servers_os_role = { "server1": {"OS": "Win_2016", "Role": "CT"}, "server2": {"OS": "RHEL7", "Role": "POM"} } servers_mac = { "server1": {"MAC": "00:01:02:03:04:05"}, "server2": {"MAC": "00:01:02:03:04:06"} } # 合并 combined = merge_server_configs(servers_os_role, servers_mac)
二、获取未运行VM的MAC地址(无需启动虚拟机)
既然VM已经在oVirt/Foreman中创建,即使从未运行,MAC地址已经被分配并存储在平台的数据库中,直接通过API/CLI就能获取,不需要常规事实收集:
1. 从oVirt获取(最直接,因为VM是在oVirt创建的)
用oVirt CLI工具:
# 先登录oVirt引擎(如果没有保存会话) engine-cli -u admin@internal -p your_engine_password # 获取指定VM的MAC地址 vm show --name server1 --query 'nics.mac.address'
用Ansible的oVirt模块(自动化场景首选):
- name: 登录oVirt引擎 ovirt_auth: url: https://your_ovirt_engine/ovirt-engine/api username: admin@internal password: your_password insecure: true # 如果用自签证书的话 - name: 拉取VM的网卡信息(包括MAC) ovirt_vms: auth: "{{ ovirt_auth }}" name: "{{ item }}" fetch_nested: true nested_attributes: - nics loop: - server1 - server2 register: vm_info - name: 自动合并MAC到服务器配置 set_fact: combined_servers: "{{ combined_servers | default(servers_os_role) | combine({ item.item: { 'MAC': item.ovirt_vms[0].nics[0].mac.address } }, recursive=True) }}" loop: "{{ vm_info.results }}"
2. 从Foreman获取
如果Foreman已经同步了oVirt的VM数据,也可以通过Foreman的REST API获取:
curl -u foreman_username:foreman_password https://your_foreman_host/api/hosts/server1 | jq '.interfaces[] | .mac'
最终流程建议
- 通过oVirt/Foreman API/CLI批量获取所有目标VM的MAC地址,整理成
servers_mac结构; - 用递归合并的方法把
servers_os_role和servers_mac合并成完整的服务器配置; - 将合并后的配置传递给WDS,完成首次启动的网络配置。
内容的提问来源于stack exchange,提问作者user1174838
相关产品推荐
相关产品推荐

