无法使用ansible和group_vars从变量创建字典

时间:2018-08-17 09:53:18

标签: python dictionary ansible

情况

最好将ansible设置为group_vars。在此上下文中,每个服务器都有两个双端口NIC(Mellanox)。网络配置是通过netplan的group_vars完成的。尽管network:bond0:interfaces就像一个魅力network:ethernets:一样没有:

## group_vars/my-server-group
Mellanox_1: enp3s0
Mellanox_2: enp5s0
bond0_interfaces:
  - "{{ Mellanox_1 }}"
  - "{{ Mellanox_1 }}d1"
  - "{{ Mellanox_2 }}"
  - "{{ Mellanox_2 }}d1"
interface_no_dhcp:
  dhcp4: no
interface_array: [ '{{ Mellanox_1 }}', '{{ Mellanox_1 }}d1', '{{ Mellanox_2 }}', '{{ Mellanox_2 }}d1' ] 
# ^^^ works, but is useless
interface_array: { '{{ Mellanox_1 }}', '{{ Mellanox_1 }}d1', '{{ Mellanox_2 }}', '{{ Mellanox_2 }}d1' } 
# ^^^ doesn't work
netplan_config_file: /etc/netplan/netplan_ansible.yaml
netplan_configuration:
  network:
    ethernets:
      "{{ interface_array }}"
    bonds:
      bond0:
        interfaces: "{{ bond0_interfaces }}"
        parameters:
          mode:                 802.3ad

结果是:

## /etc/netplan/netplan.yaml (excerpt)
netplan_configuration:
  network:
    ethernets:
      "{{ Mellanox_1 }}":       <-- instead of 'enp3s0:'
      "{{ Mellanox_1 }}d1":
      "{{ Mellanox_2 }}":
      "{{ Mellanox_2 }}d1":

以下内容也不起作用,并导致错误:recursive loop detected in template string

## group_vars/my-server-group
ethernet_interfaces: |
"{% for interface in bond0_interfaces %}"
"{{ ethernet_interfaces|combine({interface: interface_no_dhcp}) }}"
"{% endfor %}"

问题:

使用数组(例如bond0_interfaces)时,它可以按预期与字典一起工作,但会失败。 据我所知,为了遵循netplan配置指南(described here),我需要一个字典而不是一个数组。最后应该是:

目标

## /etc/netplan/netplan.yaml (excerpt)
network:
  ethernets:
    enp3s0:
      dhcp4: no
    enp3s0d1:
      dhcp4: no
    enp5s0:
      dhcp4: no
    enp5s0d1:
      dhcp4: no
  bonds:
    bond0:
      interfaces: 
      - enp3s0
      - enp3s0d1
      - enp5s0
      - enp5s0d1
      parameters:
        mode:                 802.3ad

有人可以解决吗?

this thread用户holdenweb中说:

  

“动态变量名称几乎总是一个糟糕的主意”

在这种情况下,这是绝对合理的;-)

我还检查了:

1 个答案:

答案 0 :(得分:0)

我有解决办法。我可以建议使用Ansible角色linux_postinstall吗?任务netplan完成您需要的工作。诀窍是在template

中过滤 item.conf
{{ item.conf | from_yaml | to_nice_json }}

下面是在/ scratch中创建以太网和绑定的测试方法。我尚未使用这些配置文件测试过netplan。 YMMV。 example也可以与 group_vars 一起使用。

> cat netplan.yml

- hosts: localhost
  become: yes
  become_method: sudo
  become_user: root
  vars:
    Mellanox_1: enp3s0
    Mellanox_2: enp5s0
    lp_netplan_root: "/scratch"
    lp_netplan: True
    lp_netplan_renderer: "networkd"
    lp_netplan_conf:
      - file: "91-ethernet.yaml"
        category: "ethernets"
        conf: |
          {{ Mellanox_1 }}:
            dhcp4: no
          {{ Mellanox_1 }}d1:
            dhcp4: no
          {{ Mellanox_2 }}:
            dhcp4: no
          {{ Mellanox_2 }}d1:
            dhcp4: no
      - file: "92-bonds.yaml"
        category: "bonds"
        conf: |
          bond0:
            interfaces:
            - "{{ Mellanox_1 }}"
            - "{{ Mellanox_1 }}d1"
            - "{{ Mellanox_2 }}"
            - "{{ Mellanox_2 }}d1"
            parameters:
              mode: 802.3ad
  roles:
    - vbotka.linux_postinstall

> ansible-playbook netplan.yml -t lp_netplan

>猫/scratch/91-ethernet.yaml

# Ansible managed
network:
  version: 2
  renderer: networkd
  ethernets:
    {
    "enp3s0": {
        "dhcp4": false
    }, 
    "enp3s0d1": {
        "dhcp4": false
    }, 
    "enp5s0": {
        "dhcp4": false
    }, 
    "enp5s0d1": {
        "dhcp4": false
    }
}

>猫/scratch/92-bonds.yaml

# Ansible managed
network:
  version: 2
  renderer: networkd
  bonds:
    {
    "bond0": {
        "interfaces": [
            "enp3s0", 
            "enp3s0d1", 
            "enp5s0", 
            "enp5s0d1"
        ], 
        "parameters": {
            "mode": "802.3ad"
        }
    }
}