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

nmcli: module refactor #1113

Merged
merged 9 commits into from Oct 23, 2020
Merged

Conversation

jbronn
Copy link
Contributor

@jbronn jbronn commented Oct 17, 2020

Refactor nmcli module for consistency and to remove duplicate and/or unused code:

  • Connection creation/modification methods:
    • connection_update: replaces all {create,modify}_connection_* methods
    • connection_options: returns consistent nmcli options for all connection types and when detecting changes.
  • Use consistent settings across connection all types:
    • IP settings: e.g., ipv4.addresses instead of ip4 or ipv4.address.
    • Connection settings: e.g., connection.autoconnect, connection.interface-nameinstead ofautoconnect, ifname`.
    • Bridges: e.g., bridge-port.hairpin-mode instead of bridge-port.hairpin.
    • Tunnels: e.g., ip-tunnel.parent instead of dev.
  • Use all settings when creating a connection so it doesn't need to be immediately modified (less nmcli commands issued).

Bugfixes:

New features:

ADDITIONAL NOTES

…modifying connections and detecting changes.

* Keep DNS list arguments as lists internally.
* Remove duplicated code where practical.
@ansibullbot
Copy link
Collaborator

Copy link
Collaborator

@felixfontein felixfontein left a comment

Choose a reason for hiding this comment

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

I'm not familiar with the module's code nor did I look through all the code-changes. I'm mainly interested in:

  1. Will this change make something stop working in certain situations that worked before? (If something specific is not installed?)
  2. Is there any (intended) behavior change which breaks existing use-cases?

changelogs/fragments/nmcli-refactor.yml Outdated Show resolved Hide resolved
changelogs/fragments/nmcli-refactor.yml Outdated Show resolved Hide resolved
if self.conn_name == con_item:
return True
def connection_exists(self):
cmd = [self.nmcli_bin, 'con', 'show', self.conn_name]
Copy link
Contributor

Choose a reason for hiding this comment

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

It is recommend to use command nmcli con show instead of nmcli con show <conn_name> for detecting if connection exists. Here're some reasons:

  1. The performance of nmcli con show <conn_name> may slower than the former one, because all details will be dumped to the standard output.
  2. Using nmcli con show could avoid most potential exceptions in parsing and displaying active connection data.
  3. Not only connection name, but also any other aliases (uuid, path, path), can be used to denote a connection in nmcli con show <conn_id>. But it's better only to match the connection name for determining the existence.

The result of connection list fetched from nmcli con show can also be cached in Nmcli object to avoid duplicated queries. If so, the cached data should be cleaned up in method remove_connection() and create_connection() as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Exactly the type of feedback I was looking for! I'll look into fixing the connection_exists implementation tonight.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in ffeae0b, but no caching.

'ipv6.dns',
'ipv6.dns-search'):
return list
return None
Copy link
Contributor

Choose a reason for hiding this comment

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

Suppose default type is str, isn't it?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 618307e.

for setting, value in options.items():
setting_type = self.settings_type(setting)
type_cast = None
if setting_type == bool:
Copy link
Contributor

Choose a reason for hiding this comment

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

The operator is is preferred for checking type objects compared to the operator ==.

For example, if setting_type is bool:.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

While it was an improvement over issubclass(setting_type, bool), I agree the identity operator is what should be used instead here; fixed in 766433e.

elif key in ['ipv4.dns', 'ipv4.dns-search', 'ipv6.dns', 'ipv6.dns-search']:
values = raw_value.split(',')
conn_info[key] = values
elif key_type == list:
Copy link
Contributor

Choose a reason for hiding this comment

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

The operator is is preferred for checking type objects compared to the operator ==.

For example, elif key_type is list:

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 766433e.

@thinkdoggie
Copy link
Contributor

thinkdoggie commented Oct 17, 2020

@jbronn thanks for your good ideas and elaborate work.

I add several comments about the implementation details for your references. I didn't test the code yet, but it looks good to work fine. :-)

jbronn and others added 3 commits October 19, 2020 09:16
Co-authored-by: Felix Fontein <felix@fontein.de>
Co-authored-by: Felix Fontein <felix@fontein.de>
@jbronn
Copy link
Contributor Author

jbronn commented Oct 19, 2020

@felixfontein

  1. Will this change make something stop working in certain situations that worked before? (If something specific is not installed?)

I don't think so. What I've done, requirements-wise with fixing #1112, is to eliminate the dependency on the Python bindings and not NetworkManager itself. The updated description in the DOCUMENTATION string should reflect the package requirements for the platforms now.

  1. Is there any (intended) behavior change which breaks existing use-cases?

As far as I know, all existing use-cases should be preserved. Other than the new "feature" of #1112, I tried to ensure I didn't introduce any other new features to muddle review on an otherwise large diff -- for example, I could've easily extended mac support beyond bridges, but didn't.

Here are some differences from the previous implementation:

  • Now that consistent options are used when creating connections, there's no need to issue a secondary nmcli con mod command to fix settings not done at creation.
  • I still bring connections up, even though I'm unsure of its necessity as nmcli defaults autoconnect=True and NetworkManager brings them up automatically after creation. The previous implementation's logic is now in the create_connection_up property.
  • There was a lot of logic (sometimes conflicting) around coming up with a default connection or interface name. These code paths are never reached because conn_name is a required parameter and won't ever be None; connection_update now handles this logic.
  • The test changes are small considering:
    • Reduced duplication in the pytest fixtures (e.g., override execute_command in mocker_set rather than individually in each test fixture).
    • A VXLAN test case was found to be using the invalid interface name as a side-effect of fixing #459 #1089 .
    • MTU settings had to be added to team-slave and ethernet connection outputs as detecting changes for it is now supported.

Please advise as to what test cases I should add if the current ones are insufficient.

@felixfontein
Copy link
Collaborator

@jbronn thanks for your reply! Sounds good to me.

About the tests: I wish there would be integration tests, but that's probably a lot harder in CI than unit tests (if possible at all). I can't say much about the unit tests, since I neither know nmcli, the module nor the unit tests enough :)

@ansibullbot ansibullbot added unit tests/unit and removed needs_triage labels Oct 19, 2020
Copy link
Contributor

@thinkdoggie thinkdoggie left a comment

Choose a reason for hiding this comment

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

+1 that looks good to me. :)

@felixfontein
Copy link
Collaborator

Changelog fragment looks good, too :)

@alcamie101 @nerzhul any comments?

If nobody complains, I'll merge in a couple of days (assuming @jbronn you don't want to change anything anymore).

@jbronn
Copy link
Contributor Author

jbronn commented Oct 20, 2020

I don't plan on adding anything more, thanks for the review y'all! In the meantime, I'll look into implementing integration tests for the other tickets I've opened.

@felixfontein felixfontein merged commit 7722800 into ansible-collections:main Oct 23, 2020
patchback bot pushed a commit that referenced this pull request Oct 23, 2020
* * Refactor `nmcli` module to use consistent parameters when creating/modifying connections and detecting changes.
* Keep DNS list arguments as lists internally.
* Remove duplicated code where practical.

* DBus and GObject dependencies are not necessary.

* Update changelog fragment.

Co-authored-by: Felix Fontein <felix@fontein.de>

* Update changelog fragment.

Co-authored-by: Felix Fontein <felix@fontein.de>

* Use identity operator instead of equality for type comparison.

* Don't start changelog notes with a capital letter.

* * Have `settings_type` return `str` by default instead of `None`.
* Improve variable naming, use `convert_func` instead of `type_cast`.

* Revert new feature of allowing ethernet types as slaves.

* Bring back `list_connection_info` to list all connections with `nmcli con show`.

Co-authored-by: Felix Fontein <felix@fontein.de>
(cherry picked from commit 7722800)
@felixfontein
Copy link
Collaborator

@jbronn thanks a lot for doing this!
@thinkdoggie thanks a lot for reviewing!

felixfontein pushed a commit that referenced this pull request Oct 23, 2020
* * Refactor `nmcli` module to use consistent parameters when creating/modifying connections and detecting changes.
* Keep DNS list arguments as lists internally.
* Remove duplicated code where practical.

* DBus and GObject dependencies are not necessary.

* Update changelog fragment.

Co-authored-by: Felix Fontein <felix@fontein.de>

* Update changelog fragment.

Co-authored-by: Felix Fontein <felix@fontein.de>

* Use identity operator instead of equality for type comparison.

* Don't start changelog notes with a capital letter.

* * Have `settings_type` return `str` by default instead of `None`.
* Improve variable naming, use `convert_func` instead of `type_cast`.

* Revert new feature of allowing ethernet types as slaves.

* Bring back `list_connection_info` to list all connections with `nmcli con show`.

Co-authored-by: Felix Fontein <felix@fontein.de>
(cherry picked from commit 7722800)

Co-authored-by: Justin Bronn <jbronn@gmail.com>
@mator
Copy link
Contributor

mator commented Oct 23, 2020

Can we look for other nmcli issues, via searching nmcli in issues? seems like there's quite a few of them, and maybe others are already fixed with this merged PR. Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
5 participants