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

fix(runpath): On *BSD, create /run is not ephemeral #4677

Merged
merged 3 commits into from
Jan 5, 2024

Conversation

igalic
Copy link
Collaborator

@igalic igalic commented Dec 8, 2023

Proposed Commit Message

fix(runpath): On *BSD, /run is not ephemeral

On *BSD, `/run` is not ephemeral, but the way cloud-init behaves, it
expects it to be. To fix this, we ds-identify's RUN_* initialization after
figuring out which OS we run on.
For the Python we set the config to the expected directories.

Add and fix tests to ensure this behavior is correct and consistent.

Sponsored by: The FreeBSD Foundation
Fixes GH-4180
Fixes GH-4231

Additional Context

Test Steps

Checklist

Merge type

  • Squash merge using "Proposed Commit Message"
  • Rebase and merge unique commits. Requires commit messages per-commit each referencing the pull request number (#<PR_NUM>)

igalic added a commit to igalic/cloud-init that referenced this pull request Dec 8, 2023
On *BSD, `/run` is not ephemeral, but the way cloud-init behaves, it
expects it to be.
This is hack is partial fix for canonicalGH-4180 / canonicalGH-4231.
But to be good Unix citizens, we should still make /run relocatable in
the code and in the installer.

Sponsored by: The FreeBSD Foundation
Fixes canonicalGH-4180
Fixes canonicalGH-4231
igalic added a commit to igalic/cloud-init that referenced this pull request Dec 8, 2023
let's just use an `if`!

Sponsored by: The FreeBSD Foundation
@holmanb holmanb self-assigned this Dec 11, 2023
sysvinit/netbsd/cloudfinal.tmpl Show resolved Hide resolved
sysvinit/freebsd/cloudinitlocal.tmpl Show resolved Hide resolved
sysvinit/freebsd/dsidentify.tmpl Outdated Show resolved Hide resolved
sysvinit/freebsd/dsidentify.tmpl Outdated Show resolved Hide resolved
igalic added a commit to igalic/cloud-init that referenced this pull request Dec 13, 2023
let's just use an `if`!

Sponsored by: The FreeBSD Foundation
@igalic igalic marked this pull request as draft December 13, 2023 16:00
@igalic igalic changed the title hack(sysvinit): On *BSD, create /run as symlink fix(runpath): On *BSD, create /run is not ephemeral Dec 13, 2023
igalic added a commit to igalic/cloud-init that referenced this pull request Dec 13, 2023
let's just use an `if`!

Sponsored by: The FreeBSD Foundation
@igalic igalic marked this pull request as ready for review December 14, 2023 12:35
Copy link
Collaborator Author

@igalic igalic left a comment

Choose a reason for hiding this comment

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

this is some of the best (harmless) shell code I've written yet

igalic added a commit to igalic/cloud-init that referenced this pull request Dec 15, 2023
let's just use an `if`!

Sponsored by: The FreeBSD Foundation
igalic added a commit to igalic/cloud-init that referenced this pull request Dec 15, 2023
shuffle code-paths around such that we initialize RUN_PATH, and all the
things that depend on it after figuring out which OS we're on, while
still alowing these global variables to be overwritten from the outside.
On BSD /run is not ephemeral, so here we set RUN_PATH to /var/run.
Ensure everything is initialized for 'print_info', not just for 'main'.

For the tests, we equally ensure that for not-Linux systems the data is
written into `rootd + var/run` instead of `rootd + run`.

Sponsored by: The FreeBSD Foundation
igalic added a commit to igalic/cloud-init that referenced this pull request Dec 15, 2023
on BSD, /run is not ephemeral.
relocate BSDs config to /var/run

Sponsored by: The FreeBSD Foundation
Fixes canonicalGH-4180
Fixes canonicalGH-4231
Co-authored-by: Brett Holman <brett.holman@canonical.com>
@@ -1579,6 +1581,10 @@ collect_info() {
}

print_info() {
DI_LOG=stderr
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

my understanding is that this is correct
although it didn't seem to be necessary before

Copy link
Member

@holmanb holmanb Jan 3, 2024

Choose a reason for hiding this comment

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

Why do we need the DI_LOG=stderr and ensure_sane_path calls? I don't think that those ones are required.

I think that I see why read_uname_info and set_run_path might be required - this function is the other "main" entry point of this function, thus will require the PATH_RUN* variables to be properly set, as they were before this function.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

here's what happens without DI_LOG=stderr:

tools/ds-identify: 185: 3: Bad file descriptor
tools/ds-identify: 185: 3: Bad file descriptor

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

but set_run_path is not, so i removed that.

Copy link
Member

@holmanb holmanb Jan 4, 2024

Choose a reason for hiding this comment

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

I meant the other way around:

diff --git a/tools/ds-identify b/tools/ds-identify
index 6e923a550..154668a00 100755
--- a/tools/ds-identify
+++ b/tools/ds-identify
@@ -1584,8 +1584,7 @@ collect_info() {
 }
 
 print_info() {
-    DI_LOG=stderr
-    ensure_sane_path
+    set_run_path
     read_uname_info
     collect_info
     _print_info

set_run_path sets DI_LOG, so I don't think hardcoding it here is necessary. We shouldn't unconditionally log to stderr, in case of DI_MAIN=print_info DI_LOG=/some/file tools/ds-identify or similar.

The above didn't have the bad descriptor issue you mentioned.

Also ensure_sane_path wasn't called in print_info before - I see no reason to add it.

igalic added a commit to igalic/cloud-init that referenced this pull request Dec 19, 2023
let's just use an `if`!

Sponsored by: The FreeBSD Foundation
igalic added a commit to igalic/cloud-init that referenced this pull request Dec 19, 2023
shuffle code-paths around such that we initialize RUN_PATH, and all the
things that depend on it after figuring out which OS we're on, while
still alowing these global variables to be overwritten from the outside.
On BSD /run is not ephemeral, so here we set RUN_PATH to /var/run.
Ensure everything is initialized for 'print_info', not just for 'main'.

For the tests, we equally ensure that for not-Linux systems the data is
written into `rootd + var/run` instead of `rootd + run`.

Sponsored by: The FreeBSD Foundation
igalic added a commit to igalic/cloud-init that referenced this pull request Dec 19, 2023
on BSD, /run is not ephemeral.
relocate BSDs config to /var/run

Sponsored by: The FreeBSD Foundation
Fixes canonicalGH-4180
Fixes canonicalGH-4231
Co-authored-by: Brett Holman <brett.holman@canonical.com>
@igalic igalic mentioned this pull request Dec 21, 2023
Copy link
Member

@holmanb holmanb left a comment

Choose a reason for hiding this comment

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

Great work here @igalic, I like the way this one is coming together. I have a couple smallish requests / questions, once resolved I'll merge.

@@ -1579,6 +1581,10 @@ collect_info() {
}

print_info() {
DI_LOG=stderr
Copy link
Member

@holmanb holmanb Jan 3, 2024

Choose a reason for hiding this comment

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

Why do we need the DI_LOG=stderr and ensure_sane_path calls? I don't think that those ones are required.

I think that I see why read_uname_info and set_run_path might be required - this function is the other "main" entry point of this function, thus will require the PATH_RUN* variables to be properly set, as they were before this function.


DI_LOG="${DI_LOG:-${PATH_RUN_CI}/ds-identify.log}"
# Declare global here, we'll set it properly in main()
Copy link
Member

Choose a reason for hiding this comment

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

Lets add a comment explaining that the default values for these variables are system-specific, therefore must be assigned after collecting some information from the system.

tests/unittests/test_ds_identify.py Show resolved Hide resolved
igalic added a commit to igalic/cloud-init that referenced this pull request Jan 4, 2024
let's just use an `if`!

Sponsored by: The FreeBSD Foundation
igalic added a commit to igalic/cloud-init that referenced this pull request Jan 4, 2024
shuffle code-paths around such that we initialize RUN_PATH, and all the
things that depend on it after figuring out which OS we're on, while
still alowing these global variables to be overwritten from the outside.
On BSD /run is not ephemeral, so here we set RUN_PATH to /var/run.
Ensure everything is initialized for 'print_info', not just for 'main'.

For the tests, we equally ensure that for not-Linux systems the data is
written into `rootd + var/run` instead of `rootd + run`.

Sponsored by: The FreeBSD Foundation
igalic added a commit to igalic/cloud-init that referenced this pull request Jan 4, 2024
on BSD, /run is not ephemeral.
relocate BSDs config to /var/run

Sponsored by: The FreeBSD Foundation
Fixes canonicalGH-4180
Fixes canonicalGH-4231
let's just use an `if`!

Sponsored by: The FreeBSD Foundation
igalic added a commit to igalic/cloud-init that referenced this pull request Jan 4, 2024
shuffle code-paths around such that we initialize RUN_PATH, and all the
things that depend on it after figuring out which OS we're on, while
still alowing these global variables to be overwritten from the outside.
On BSD /run is not ephemeral, so here we set RUN_PATH to /var/run.
Ensure everything is initialized for 'print_info', not just for 'main'.

For the tests, we equally ensure that for not-Linux systems the data is
written into `rootd + var/run` instead of `rootd + run`.

Sponsored by: The FreeBSD Foundation
igalic added a commit to igalic/cloud-init that referenced this pull request Jan 4, 2024
on BSD, /run is not ephemeral.
relocate BSDs config to /var/run

Sponsored by: The FreeBSD Foundation
Fixes canonicalGH-4180
Fixes canonicalGH-4231
@igalic igalic force-pushed the hack/ephemeral-run branch 2 times, most recently from 2bbde27 to 13281ca Compare January 4, 2024 22:52
igalic added a commit to igalic/cloud-init that referenced this pull request Jan 4, 2024
shuffle code-paths around such that we initialize RUN_PATH, and all the
things that depend on it after figuring out which OS we're on, while
still alowing these global variables to be overwritten from the outside.
On BSD /run is not ephemeral, so here we set RUN_PATH to /var/run.
Ensure everything is initialized for 'print_info', not just for 'main'.

For the tests, we equally ensure that for not-Linux systems the data is
written into `rootd + var/run` instead of `rootd + run`.

Sponsored by: The FreeBSD Foundation
igalic added a commit to igalic/cloud-init that referenced this pull request Jan 4, 2024
on BSD, /run is not ephemeral.
relocate BSDs config to /var/run

Sponsored by: The FreeBSD Foundation
Fixes canonicalGH-4180
Fixes canonicalGH-4231
shuffle code-paths around such that we initialize RUN_PATH, and all the
things that depend on it after figuring out which OS we're on, while
still alowing these global variables to be overwritten from the outside.
On BSD /run is not ephemeral, so here we set RUN_PATH to /var/run.
Ensure everything is initialized for 'print_info', not just for 'main'.

For the tests, we equally ensure that for not-Linux systems the data is
written into `rootd + var/run` instead of `rootd + run`.

Sponsored by: The FreeBSD Foundation
on BSD, /run is not ephemeral.
relocate BSDs config to /var/run

Sponsored by: The FreeBSD Foundation
Fixes canonicalGH-4180
Fixes canonicalGH-4231
Copy link
Collaborator Author

@igalic igalic left a comment

Choose a reason for hiding this comment

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

i think this is done now…

@@ -1835,12 +1843,25 @@ read_uptime() {
return
}

set_run_path() {
if [ "$DI_UNAME_KERNEL_NAME" != "Linux" ]; then
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

make sure this function works on Linux… even if someone forgot to call read_uname_info()

@@ -154,6 +159,8 @@ debug() {
shift
[ "$lvl" -gt "${DI_DEBUG_LEVEL}" ] && return

[ "$DI_LOG" = "" ] && DI_LOG="stderr"
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

make sure the debug() function works, even if someone forgot to set_run_path(), or DI_LOG.

Copy link
Member

Choose a reason for hiding this comment

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

Mentally walking through this:

  1. call to debug before set_run_path causes DI_LOG set to stderr, _DI_LOGGED set to stderr, file descriptor 3 redirects to file descriptor 2
  2. set_run_path redefines DI_LOG to whatever/cloud-init.log
  3. subsequent call to debug sees that "$_DI_LOGGED" != "$DI_LOG", re-opens fd 3 pointing to whatever/cloud-init.log, reassigns _DI_LOGGED to $DI_LOG
  4. subsequent calls to debug use fd 3 which points to the right file

Looks good to me!

Copy link
Member

@holmanb holmanb left a comment

Choose a reason for hiding this comment

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

Great work @igalic. This looks good to me.

@@ -154,6 +159,8 @@ debug() {
shift
[ "$lvl" -gt "${DI_DEBUG_LEVEL}" ] && return

[ "$DI_LOG" = "" ] && DI_LOG="stderr"
Copy link
Member

Choose a reason for hiding this comment

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

Mentally walking through this:

  1. call to debug before set_run_path causes DI_LOG set to stderr, _DI_LOGGED set to stderr, file descriptor 3 redirects to file descriptor 2
  2. set_run_path redefines DI_LOG to whatever/cloud-init.log
  3. subsequent call to debug sees that "$_DI_LOGGED" != "$DI_LOG", re-opens fd 3 pointing to whatever/cloud-init.log, reassigns _DI_LOGGED to $DI_LOG
  4. subsequent calls to debug use fd 3 which points to the right file

Looks good to me!

@holmanb holmanb merged commit 8937b5e into canonical:main Jan 5, 2024
29 checks passed
holmanb pushed a commit that referenced this pull request Jan 5, 2024
let's just use an `if`!

Sponsored by: The FreeBSD Foundation
holmanb pushed a commit that referenced this pull request Jan 5, 2024
shuffle code-paths around such that we initialize RUN_PATH, and all the
things that depend on it after figuring out which OS we're on, while
still alowing these global variables to be overwritten from the outside.
On BSD /run is not ephemeral, so here we set RUN_PATH to /var/run.
Ensure everything is initialized for 'print_info', not just for 'main'.

For the tests, we equally ensure that for not-Linux systems the data is
written into `rootd + var/run` instead of `rootd + run`.

Sponsored by: The FreeBSD Foundation
netgate-git-updates pushed a commit to pfsense/FreeBSD-ports that referenced this pull request Jan 10, 2024
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