recommended way to configure a centos-7 network interface with static settings via ansible

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.


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