Scenario / Questions

I’m new to ansible and a little googling hasn’t lead me quickly towards the right solution to my question.

What’s the ‘with the grain’ way to assign static network settings to a centos-7 host with ansible. I feel like this must be a pretty common need — and there must be a lot of people with questions about the right approach to take after all the changes to the network configuration system in the transition from rhel-6 to rhel-7 (namely, network-manager by default, consistent device naming by default from the kernel, systemd).

Prior to ansible I had been uninstalling network-manager and manually configuring hosts via /etc/init.d/network-scripts/ifcfg-* files — I think I could do the same thing with ansible using the ansible_default_ipv4 fact:

    "ansible_default_ipv4": {
        "address": <snip>,
        "alias": "enp3s0",
        "gateway": <snip>,
        "interface": "enp3s0",
        "macaddress": <snip>,
        "mtu": 1500,
        "netmask": "255.255.255.128",
        "network": <snip>,
        "type": "ether"
    }

Ansible far is so great and for this I want to make sure I’m not going unnecessarily against the ansible grain. I’m willing to not uninstall network-manager if there are good ways to manage the network-manager mediated interface configuration through ansible …

Find below all possible solutions or suggestions for the above questions..

Suggestion: 1

I went back to this after becoming a bit more familiar with ansible — thought I’d share my solution.

First something to be aware of: NetworkManager has the concept of Configuration plugins — which are used to adapt external sources of information into NetworkManager configuration. Redhat distributes a plugin called ifcfg-rh which attempts to adapt /etc/sysconfig/network-scripts/ifcfg* style configuration files into NetworkManager configuration, however there are quite a few gotchas with this approach … and the network-scripts/ifcfg* configuration format was never particularly straightforward … Its also quite confusing as to what the semantics of changes to the network-scripts files are — and when exactly new settings will get applied. Additionally, ifcfg-* type files don’t support all the network configurations that are supported by NetworkManager.

I found it much easier and more straightforward to abandon the ifcfg-rh plugin and use the keyfile plugin instead.

Within the tasks/main.yml:

---

- name: ensure NetworkManager is configured to use keyfile plugin
  copy: src=NetworkManager.conf dest=/etc/NetworkManager/NetworkManager.conf mode=0600
  notify:
   - restart NetworkManager
   - wait for new network settings

- name: ensure NetworkManager settings are initialized from appropriate keyfile configuration
  copy: src={{ myorg_network_profile }}.conf dest=/etc/NetworkManager/system-connections/ansible_generated.conf mode=0600
  notify:
    - restart NetworkManager
    - reload network interface
    - wait for new network settings

Handlers look something like this:


 - name: reload network interface
   shell: nmcli con reload 
 - name: restart NetworkManager 
   service: name=NetworkManager state=restarted 
 - name: wait for new network settings
   sudo: false 
   local_action: 
      module: wait_for host={{ ansible_ssh_host | default(inventory_hostname) }} port=22 delay=10 timeout=300

with a NetworkManager.conf that looks like this:

[main]
plugin=keyfile

I then create keyfile config files suitable for the various kinds of networking configurations I want to deploy:

example: files/dhcp.conf

[connection]
id=dhcp
uuid=50263651-4f14-46bc-8dd8-818bf0fe3367
type=ethernet
autoconnect=true

[ipv6]
method=auto

[ipv4]
method=auto

or for a host with static network settings and an ip on two subnets:

[connection]
id=custom-connection-profile
uuid=50263651-4f14-46bc-8dd8-818bf0fe3362
type=ethernet
autoconnect=true

[ipv6]
method=auto

[ipv4]
method=manual
dns=192.168.0.1;192.168.0.x;
dns-search=foo.com;
address1=192.168.0.4/24,192.168.0.1
address2=172.19.0.12/25,172.19.12.1

To turn a newly installed system at a random ip into a host with a statically assigned address:

ansible-playbook site.yml -i hosts.ini --extra_vars "ansible_ssh_host=<ip_address_of_newly_installed_host>" --limit <ansible_hostname_from_inventory>

I think this is a good approach but happy for any feeback.

Suggestion: 2

These days (fall 2019) native Ansible nmcli module would be the answer: https://docs.ansible.com/ansible/latest/modules/nmcli_module.html