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

API: update netplan_delete_connection() to avoid spawning another process #322

Merged
merged 4 commits into from
Feb 8, 2023

Conversation

slyon
Copy link
Collaborator

@slyon slyon commented Feb 1, 2023

Description

This function has been calling into the python 'netplan set' command for historical reasons. We can now stay internal to libnetplan and execute the corresponding libnetplan functions directly.

Basically, we're now implementing inside this function in util.c what has previously been executed via netplan/cli/commands/set.py

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.

Copy link
Collaborator

@sil2100 sil2100 left a comment

Choose a reason for hiding this comment

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

Looks good from my POV, but then again I don't really know the exact logic for netplan set anymore so I'm not leaving any Approval/Disapproval. Is the intent to move away from calling netplan set from inside the compiled netplan for various cases? Since I see dbus.c also uses netplan set.

I took a look on how netplan set is written and the workflow here at least makes sense.

if (!np_state->netdefs) {
rewind(patch);
if ( !netplan_parser_load_nullable_fields(output_parser, patch_fd, &error)
|| !netplan_parser_load_yaml_hierarchy(output_parser, rootdir, &error)) {
// LCOV_EXCL_START
Copy link
Collaborator

Choose a reason for hiding this comment

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

Just out of curiosity: why are we excluding those multiple error cases from coverage? Are they being tested in integration testing?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Those are things which are really hard to test. They are not being tested in integration testing either. It's basically file system errors or errors in the emitter and/or parser of libyaml, which we cannot easily influence.

I guess I could mock some of the netplan_ functions, when adding new unit tests as part of our new C based cmoka tests in tests/ctest/.. Maybe I should do this to test more of the error reporting cases.

@slyon
Copy link
Collaborator Author

slyon commented Feb 1, 2023

Is the intent to move away from calling netplan set from inside the compiled netplan for various cases? Since I see dbus.c also uses netplan set.

Yes, indeed. We want to avoid spawning new processes from inside compiled (lib-)netplan. In the past all of netplan set including it's YAML parser was implemented in Python, so we just called into that python code from the libnetplan API. Now the parser is actually implemented in netplan itself, so a call of this library function would call into the python code, which would in turn call back into libnetplan. We want to avoid this libnetplan -> python -> libnetplan back and forth.

dbus.c is a mess and should be refactored eventually consuming all of the new API. But it's also a stand-alone binary, so not that much of a problem as calling back and forth into the library.

src/util.c Outdated Show resolved Hide resolved
src/util.c Outdated Show resolved Hide resolved
Copy link
Contributor

@schopin-pro schopin-pro 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 approving because of the small tmpfile issue, but overall I really like the patch.

In an ideal world we'd have a netplan_state_delete_netdef function that wouldn't require us to craft a YAML payload, but that's a bit further away ;)

src/util.c Outdated Show resolved Hide resolved
@slyon slyon force-pushed the api_delete_connection branch 4 times, most recently from ec9b848 to eefb892 Compare February 6, 2023 14:57
This enables us to create anonymous files in memory (memfd_* functions).
_GNU_SOURCE includes _DEFAULT_SOURCE, which includes __USE_MISC (used for the
GLOB_BRACE flag in glob.h), so we should avoid setting it manually/explicitly.
Copy link
Collaborator

@daniloegea daniloegea left a comment

Choose a reason for hiding this comment

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

It looks good. Only requesting a minor change to avoid a leak when stdin is closed.

src/util.c Outdated Show resolved Hide resolved
This function has been calling into the python 'netplan set' command
for historical reasons. We can now stay internal to libnetplan and
execute the corresponding libnetplan functions directly.
The find_yaml_glob() function is Netplan internal and only used from
netplan-dbus, which has a hard dependency on libnetplan of the same version.

ABI LOG:

Run abidiff abi-compat/jammy_0.105.xml _build/src/libnetplan.so.0.0 --headers-dir2 include/ --header-file2 src/abi.h --suppressions abi-compat/suppressions.abignore --no-added-syms
Functions changes summary: 0 Removed, 1 Changed (46 filtered out), 0 Added (18 filtered out) functions
Variables changes summary: 0 Removed, 0 Changed (1 filtered out), 0 Added variable

1 function with some indirect sub-type change:

  [C] 'function int find_yaml_glob(const char*, glob_t*)' at util.c:116:1 has some indirect sub-type changes:
    parameter 2 of type 'glob_t*' has sub-type changes:
      in pointed to type 'typedef glob_t' at glob.h:105:1:
        underlying type 'struct glob_t' at glob.h:82:1 changed:
          type size hasn't changed
          3 data member changes:
            type of 'void* (void*)* gl_readdir' changed:
              in pointed to type 'function type void* (void*)':
                return type changed:
                  in pointed to type 'void' at dirent.h:22:1:
                    entity changed from 'void' to 'struct dirent' at dirent.h:22:1
                    type size changed from 0 to 2240 (in bits)
            type of 'int (const char* restrict, void* restrict)* gl_lstat' changed:
              in pointed to type 'function type int (const char* restrict, void* restrict)':
                parameter 2 of type 'void* restrict' changed:
                  'void* restrict' changed to 'stat* restrict'
            'int (const char* restrict, void* restrict)* gl_stat' has *some* difference - please report as a bug
Copy link
Collaborator

@daniloegea daniloegea left a comment

Choose a reason for hiding this comment

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

Looks good. Just the change to _GNU_SOURCE could use another pair of eyes.

Regarding the ABI breakage, I tested Network Manager built with an old version of libnetplan and it still works after this change (without rebuilding it I mean)

Copy link
Contributor

@schopin-pro schopin-pro left a comment

Choose a reason for hiding this comment

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

LGTM.

Regarding the ABI changes, since we have a tight dependency I'm OK with it. However, to be clear: this kind of ABI break wouldn't result in the binary refusing to start, and instead would lead to fun things like stack corruption ;).

I'm guessing last time I bumped the XOPEN_SOURCE value it was an ABI break too, huh? Live & learn...

@slyon
Copy link
Collaborator Author

slyon commented Feb 8, 2023

Thank you for the feedback @daniloegea and @schopin-pro! Let's get this merged.

@slyon slyon merged commit c658bf0 into canonical:main Feb 8, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
5 participants