Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

netplan status --diff fixes and improvements #466

Merged
merged 10 commits into from
Jun 26, 2024

Conversation

daniloegea
Copy link
Collaborator

@daniloegea daniloegea commented May 3, 2024

This PR contains a bunch of small improvements to netplan status --diff and some additions to the libnetplan API:

  • Add getters for the gateway4 and gateway6 properties. This is required during the analysis of routes.
  • Routes from gateway4 and gateway6 are added to the list of routes being analyzed.
  • Make use of the property dynamic from addr_info to help determining if the address was received dynamically.
  • Make use of the ra flag from routes to help finding IPs that were received via RA.
  • Add getter for the accept-ra property.
  • Improve the analysis of RA and LL addresses.
  • Fix a rendering issue in the --diff mode when python3-rich is not present.
  • Use the ConfigSource property from networkd to reduce the guessing and be more precise when analyzing dynamic configuration.

I recommend testing it inside a LXD VM where IPV6 addresses are assigned dynamically. The currently netplan.io will show the IPv6 address and DNS as diffs. The heuristics added to the analysis help to reduce this noise.

Description

Checklist

  • Runs make check successfully.
  • Retains 100% code coverage (make check-coverage).
  • New/changed keys in YAML format are documented.
  • (Optional) Adds example YAML for new feature.
  • (Optional) Closes an open bug in Launchpad.

@daniloegea daniloegea force-pushed the status_diff_fixes branch 3 times, most recently from 2f63fca to d1210f2 Compare May 31, 2024 15:05
@daniloegea daniloegea marked this pull request as ready for review May 31, 2024 17:03
@daniloegea daniloegea requested a review from slyon May 31, 2024 17:03
Copy link
Collaborator

@slyon slyon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you very much for those enhancements and quality of life improvements!

Looks mostly good to me. Please consider using named constants for the ip-address family instead of plain numbers.

Also, we should avoid introducing new public API for deprecated symbols (gateay4/6), still handling them as you did via internal/private API is fine!

include/netdef.h Outdated Show resolved Hide resolved
python-cffi/netplan/netdef.py Outdated Show resolved Hide resolved
python-cffi/netplan/netdef.py Outdated Show resolved Hide resolved
python-cffi/netplan/_build_cffi.py Outdated Show resolved Hide resolved
netplan_cli/cli/state.py Outdated Show resolved Hide resolved
netplan_cli/cli/state_diff.py Outdated Show resolved Hide resolved
netplan_cli/cli/state_diff.py Show resolved Hide resolved
netplan_cli/cli/state_diff.py Show resolved Hide resolved
netplan_cli/cli/state_diff.py Outdated Show resolved Hide resolved
tests/cli/test_state_diff.py Show resolved Hide resolved
The (deprecated but still available) properties gateway4 and gateway6
were not being taken into account when comparing routes. Because of
that, the diff report will show the default route as missing in netplan.

There is a complication when considering gateway4 and gateway6 though:
both networkd and NM will set a metric for them. As these properties
cannot set metrics, these routes would still be shown in the diff
report.

To avoid this noise, when gateway4 and/or gateway6 are used AND the
system contains one, and only one, default route per protocol family, we
adopt the same metric and route table from the existing routes. By doing
this, the comparison will see that both routes, from the system and from
netplan, are the same and not show them as a diff.
When available, use the flag "dynamic" from addr_info to check if the IP
addresses was dynamically assigned.

The flag will be displayed in the status output along other flags:

 Addresses: 10.86.126.222/24 (dynamic, dhcp)
There are cases where IPv6 addresses received via RA are not set as
'dynamic'. In these cases, use the information about routes to find
these IPs and add the tag 'ra' to them.

It's done by iterating through IPv6 addresses and checking if there is
any addresses in the same network as routes received via RA.
Add the Python binding and unit test.

NOTE

accept_ra is not perfectly mapped from the netdef structure to the
YAML setting and back to the renderer. It's a boolean value in the YAML
but it maps to three different values inside libnetplan: kernel, enabled
and disabled.

Not setting it in the YAML means it will not be set in
networkd. Although, networkd will disable it unconditionally in
the kernel and will itself handle RAs, meaning that when unset, it's
enabled by default (with a few exceptions, see systemd.network(5)).

Because of that, the low level C API will return the actual internal
value of the property and not only TRUE or FALSE. The Python code will
return True, False or None (when it's unset). This will help the
consumers to differentiate the case where it's disabled or unset.
When IPv6 link-local and RA (which depends on link-local) are enabled,
the system will receive IP addresses, nameservers and routes dynamically
via RA. These addresses are not obviously identified as dynamic in the
system. networkd probably does have this information but it's not fully
exposed apparently.

Here I try to improve the comparison of these addresses by checking if
they are 1) a link-local address and 2) part of the same network as the
route received via RA.

Without this, status --diff will show the RA IP addresses and link-local
DNS nameserver as a diff.
The logic to remove tags from the output wasn't working for the
interface header in diff mode.
When networkd is used, the ConfigSource property can identify the source
of the configuration so let's use it to be more precise and reduce the
guessing.

We consume the same information when Network Manager is the renderer but
in this case networkd will not know the sources so this property can't
be relied on.

For now, we collect the sources for IP addresses and DNS. Routes can be
included in the future. We also should create abstractions for each
configuration so we don't need to keep information such as the data
source in separate tables.

Network Manager seems to expose the source through its DBus API. This
also could be considered in the future.
@daniloegea daniloegea requested a review from slyon June 19, 2024 07:58
@daniloegea
Copy link
Collaborator Author

Thank you, Lukas. I addressed your comments and tried to improve a little the analysis of dynamic configuration with networkd.

include/netdef.h Outdated Show resolved Hide resolved
tests/cli/test_state_diff.py Show resolved Hide resolved
Copy link
Collaborator

@slyon slyon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot for addressing my remarks! I like the idea of using networkd's ConfigSource. Handling similar cases through NetworkManager's DBus API in the future is a good approach!

I pushed a tiny commit to clean up some unnecessary newlines/whitespace in include/netdef.h. Otherwise, LGTM. Let's get this merged!

@slyon slyon merged commit 17812f9 into canonical:main Jun 26, 2024
15 of 16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants