We don't care whether a 'ip' or 'bond' setting is
entirely omitted or whether some fields are set by
the user.
Omitting a setting should make use of some default
values, but that's it. No need to track whether the
setting is actually specified by the user.
As it is, a slave profile MUST reference an existing "master"
profile. Hence, the "slave_type" is implicitly known and not
required.
However, don't drop the "slave_type" option entirely. It allows a user
to explicitly set it, and network_connections.py will reject mismatching
configurations.
Also, check that the 'master' profile is actually of a valid master
type for the slave.
- the maximum allowed vlan_id is 4094, not 4095.
- for ifcfg, we must convert the value to str()
- for nm, we don't need to convert the value, it's
already int().
Implement what nmcli does when activating/deactivating
a connection: waits until the device is fully activated
or deactivate.
The 'wait' option is basically like nmcli's --wait option.
If omitted, wait a default duration of time. If the action
does not complete within the specified timeout, it fails.
Note that a failure may be suppressed by setting 'ignore_errors',
either globaly or per-state.
Set 'wait=0' not to wait. This was the previous behavior before
this commit.
- extend the maxiumum wait time to 3600 seconds
- disallow -1 values for 'wait'. It was used to mark
the default value, but that marker should not be
a valid value for user configuration. Instead, internally
mark the missing value with None.
- don't coerce a missing 'wait' parameter to 90 in _validate_post().
Instead, track it as None so we can later decide between an explicitly
set paramter and a default value. Also, the default for the states
'up', 'down', and 'wait' differ.
This also allows us to slience the warning about 'wait' not
being implemented -- in case the user didn't configure it.
- However, still allow zero.
For
- state: wait
wait: 0
allow it for convinience, so a user can disable the statement by
setting the wait value to zero.
For
- name: MyProfile
state: up
wait: 0
'wait' zero makes sense. It is what we currently do -- not wait
at all. Later, when we implement waiting for complete activation, the
default of wait will change (to 90 in this case).
The role already supported a default variable ("network_provider") and
host variables ("network_provider_default", "network_service_name",
"network_packages").
Don't use nested variables under "network" like
network:
provider:
ignore_error:
connections:
instead promote them all to top-level variables like:
network_provider:
network_ignore_error:
network_connections:
This seems more consistent (as we already have multiple top-level
variables), it seems to follow ansible style, and it makes it easier
to overload individual variables via conditional include files.
The library fetches interface info by reading sysfs. However, "/sys/class/net/"
may contain certain files that are not interface names, like "bonding_master"
Skip over these files. Otherwise, the code fails with
File "/tmp/ansible_HkmKOM/ansible_module_network_connections.py", line 347,
in link_infos b = SysUtil._link_infos_fetch()
File "/tmp/ansible_HkmKOM/ansible_module_network_connections.py", line 323,
in _link_infos_fetch ifindex = SysUtil._link_read_ifindex(ifname)
File "/tmp/ansible_HkmKOM/ansible_module_network_connections.py", line 302,
in _link_read_ifindex c = SysUtil._sysctl_read('/sys/class/net/' + ifname + '/ifindex')
File "/tmp/ansible_HkmKOM/ansible_module_network_connections.py", line 293,
in _sysctl_read with open(filename, 'r') as f: IOError: [Errno 20] Not a directory: '/sys/class/net/bonding_masters/ifindex'
This requires to make "library/network_connections.py" more
independent from ansible modules
In the end, the Python code runs on the target machines,
with the python installed there. So, it makes sense to also
run the unit tests as part of the CI tests.
The unit tests should run without requiring the
ansible module.
At least, all currently existing tests can now run.
In the future, we might have tests that optionally
only run when the ansible libraries are available.
As the module runs, it constructs debugging information
in run_result array. That is, because we can only pass
on the debugging messages at the end during json_exit()
or json_fail().
During early stage of run_prepare() we must also ensure
no to loose messages.
We should not set "dhcp4_send_hostname" unless it is explicitly
present in the configuration. That is because initscripts don't
support this parameter and issue a warning.
It's more idiomatic for ansible then "on_error".
'ignore_errors' can be specified as a module argument.
But it can also be specified on a per-profile level,
with the intuitive behavior that the per-profile setting
overwrites the per-module setting.
We use libnm for the async operations. We would expect that
an async operation always returns, but there might be a bug
in libnm so that it doesn't
Add our own timeout around the libnm calls to avoid hanging.
Instead, of having the tasks call the "network_connections.py"
library for each connection profile individually (using with_items),
pass all profiles at once.
The advantage is:
- the module can validate the input arguments better as it has
access to all profiles. For example, when a slave connection
refers to another master profile from the same play. Previously,
each invocation of the module only sees the current profile and
cannot verify whether the reference is valid.
- while configuring the network, the play might need to shortly
disconnect the control connection. In the previous way, after
tearing down the network the target host becomes unreachable for
ansible and the following steps cannot be executed anymore.
Now, all steps are done as a whole on the target host, via
one connection. If the host becomes unreachable for a short
time, that is not a problem as long as the connectivty is
restored at the end.
Ansible also supports to switch the host IP (or SSH port). With
this new way, the ansible play can apply a bunch of profiles
autonomously and the ansible play can potentially handle a changing
IP configuration.