Avoid CFEngine hanging on start with the ignore_interfaces.rx file

Using CFEngine on a regular basis (and training people to use it), I often have to deploy CFEngine agents on virtual machines. Trouble is that often virtual machines (especially the ones cloned a bit hastily) have broken network configurations (incorrect hosts file, stray network interfaces …).

While CFEngine is quite tolerant about network failures, it is not about interface resolution, as during the agent initialization, a name lookup is done on every interface detected on the machine.

The problem: if this lookup is not possible, the agent will hang until the time out (5-30 seconds usually), and it can get rather frustrating when multiple interfaces are present.

A simple solution is to use the ignore_interfaces.rx file in CFEngine!

What is this special file you’re telling me about?

Well, actually by default it does not even exist!

The purpose of this file is to define whether CFEngine is to ignore or not some networks interface you know that will cause trouble in some conditions.

First, let’s see a verbose CFEngine run, without this file (cf-agent -KIv):

[code lang=”shell”]
2013-08-13T17:34:26+0200 verbose: GNU autoconf class from compile time: compiled_on_linux_gnu
2013-08-13T17:34:26+0200 verbose: Address given by nameserver: 127.0.1.1
2013-08-13T17:34:26+0200 verbose: No interface exception file /var/cfengine/inputs/ignore_interfaces.rx
2013-08-13T17:34:26+0200 verbose: Interface 1: lo
2013-08-13T17:34:26+0200 verbose: Interface 2: eth0
2013-08-13T17:34:26+0200 verbose: IP address of host set to 192.168.1.254
2013-08-13T17:34:26+0200 verbose: Trying to locate my IPv6 address
2013-08-13T17:34:26+0200 verbose: Found IPv6 address fe80::dead:beef:9999:1337
[/code]

Everything goes fine, the execution is fast and I got the expected results.

Now, I’m adding some dummy interfaces to the machine:

[code lang=”shell”]
ip link add dummy0 type dummy
ip link add dummy1 type dummy
ip link add dummy2 type dummy
ifconfig dummy0 192.168.10.1/24
ifconfig dummy1 192.168.11.1/24
ifconfig dummy2 192.168.12.1/24
[/code]

When I try to run CFEngine again, I notice important delays in the execution (approximately 7 extra seconds per interface) before CFEngine starts executing anything. When launched in verbose mode, this is what happens:

[code lang=”shell”]
2013-08-13T17:37:53+0200 verbose: GNU autoconf class from compile time: compiled_on_linux_gnu
2013-08-13T17:37:53+0200 verbose: Address given by nameserver: 127.0.1.1
2013-08-13T17:37:53+0200 verbose: No interface exception file /var/cfengine/inputs/ignore_interfaces.rx
2013-08-13T17:37:53+0200 verbose: Interface 1: lo
2013-08-13T17:37:53+0200 verbose: Interface 2: eth0
2013-08-13T17:37:53+0200 verbose: IP address of host set to 192.168.90.50
2013-08-13T17:37:53+0200 verbose: Interface 3: dummy0
2013-08-13T17:37:58+0200 verbose: Interface 4: dummy1
2013-08-13T17:38:03+0200 verbose: Interface 5: dummy2
2013-08-13T17:38:03+0200 verbose: Trying to locate my IPv6 address
2013-08-13T17:38:03+0200 verbose: Found IPv6 address fe80::dead:beef:9999:1337
2013-08-13T17:38:03+0200 verbose: Found IPv6 address fe80::dead:beef:9999:1338
2013-08-13T17:38:03+0200 verbose: Found IPv6 address fe80::dead:beef:9999:1339
2013-08-13T17:38:03+0200 verbose: Found IPv6 address fe80::dead:beef:9999:1340
[/code]

Notice the delay during interface detection: now, it takes 5 seconds to timeout on every dummy interface!

Bloody hell, this sucks. What can I do to prevent this?

The reason for this is simple: CFEngine is trying to resolve these interfaces IP addresses, and as they are using private addressing and are not registered within /etc/hosts, it timeouts on each of them. Not really nice, eh?

The solution? It is easy! You just need to match the problematic interfaces in the “/var/cfengine/inputs/ignore_interfaces.rx” file and CFEngine will no more try to interact with them:

File format definition for ignore_interfaces.rx

This file is a simple plain text file, that contains entries defining the interfaces to ignore using regular expressions. It is intended to contain one regular expression per line.

For example, you can match every interface of the system (.*), a specific interface prefix (evilprefix.* which would match evilprefix1, evilprefix2, …) or a very specific interface (eth2, virbr0, bond0…).

Real life use case

[code lang=”shell”]
echo "dummy.*" > /var/cfengine/inputs/ignore_interfaces.rx
[/code]

Result?

[code lang=”shell”]
2013-08-13T17:48:25+0200 verbose: GNU autoconf class from compile time: compiled_on_linux_gnu
2013-08-13T17:48:25+0200 verbose: Address given by nameserver: 127.0.1.1
2013-08-13T17:48:25+0200 verbose: Interface 1: lo
2013-08-13T17:48:25+0200 verbose: Interface 2: eth0
2013-08-13T17:48:25+0200 verbose: IP address of host set to 192.168.90.50
2013-08-13T17:48:25+0200 verbose: Ignoring interface ‘dummy0’ because it matches ‘ignore_interfaces.rx’
2013-08-13T17:48:25+0200 verbose: Ignoring interface ‘dummy1’ because it matches ‘ignore_interfaces.rx’
2013-08-13T17:48:25+0200 verbose: Ignoring interface ‘dummy2’ because it matches ‘ignore_interfaces.rx’
2013-08-13T17:48:25+0200 verbose: Trying to locate my IPv6 address
2013-08-13T17:48:25+0200 verbose: Found IPv6 address fe80::dead:beef:9999:1337
2013-08-13T17:48:25+0200 verbose: Found IPv6 address fe80::dead:beef:9999:1338
2013-08-13T17:48:25+0200 verbose: Found IPv6 address fe80::dead:beef:9999:1339
2013-08-13T17:48:25+0200 verbose: Found IPv6 address fe80::dead:beef:9999:1340
[/code]

Notice that there is no longer any delay during the agent execution (less than 1 second) whereas the dummy interfaces are still present.

Conclusion: When you have a specific network configuration on your IT, remember that CFEngine provides features to help you ignore problematic interfaces. The main symptom is, during a verbose execution, a 5-second hang on some interfaces.