You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在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'

最终流程建议

  1. 通过oVirt/Foreman API/CLI批量获取所有目标VM的MAC地址,整理成servers_mac结构;
  2. 用递归合并的方法把servers_os_role和servers_mac合并成完整的服务器配置;
  3. 将合并后的配置传递给WDS,完成首次启动的网络配置。

内容的提问来源于stack exchange,提问作者user1174838

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 11:07:32