8

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 ...

Ben
  • 391
  • 1
  • 3
  • 11
  • 1
    I think you are wrong in thinking this is a pretty common need. `ansible` needs to logon from the control computer to the managed computers; this means that the managed computers already have their networking setup, so `ansible` would normally not be used for setting up networking. Since you are new to `ansible`, I would recommend, if possible, to postpone investigating this issue and come back to it when you will have some more experience with `ansible`. – Antonis Christofides Feb 11 '15 at 10:08
  • Thanks for this -- I think its a good answer and I started to come to that conclusion as well when I realized I wouldn't have a way to direct ansible to apply a particular role to a host with some random ip address. I should've probably included what I was trying to accomplish in my question -- I want to bootstrap all the elements needed for a small network environment -- so I thought I'd start with configuring the dns/dhcp server ... I think I will manually configure the network interfaces on the dhcp/dns server as you suggest for now... – Ben Feb 11 '15 at 18:13
  • I think it would be nice to extract the 'network interface configuration' process into some kind of ad-hoc deployable ansible-playbook though -- something I could run to bootstrap a newly installed host so that its network settings match a specific host within my inventory ... Thanks! – Ben Feb 11 '15 at 18:14

2 Answers2

6

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.

Ben
  • 391
  • 1
  • 3
  • 11
  • Can you share your "bounce interface" and "wait for new network settings" handlers? – sheldonh Nov 12 '15 at 06:39
  • - name: reload network interface shell: nmcli con reload (sometimes you might need this as well/instead of the above bounce interface method ...) - name: restart NetworkManager service: name=NetworkManager state=restarted - name: wait for networking to come back up sudo: false local_action: module: wait_for host={{ ansible_ssh_host | default(inventory_hostname) }} port=22 delay=10 timeout=300 – Ben Nov 24 '15 at 03:53
  • Added sample handlers to above answer – Ben Nov 25 '15 at 23:59
2

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

lzap
  • 2,704
  • 2
  • 22
  • 22
  • 3
    Whilst this may theoretically answer the question, [it would be preferable](http://meta.stackoverflow.com/q/8259) to include the essential parts of the answer here, and provide the link for reference. – Gerald Schneider Dec 02 '19 at 14:57
  • Worth noting that nmcli will edit network-scripts to match configuration. You do need to manually run `nmcli connection up` though. – DustWolf Jan 27 '21 at 12:52