Skip to content

[RFC] [podman] Collect podman Data for All Users#4290

Open
sahithiRavindranath wants to merge 1 commit into
sosreport:mainfrom
sahithiRavindranath:main
Open

[RFC] [podman] Collect podman Data for All Users#4290
sahithiRavindranath wants to merge 1 commit into
sosreport:mainfrom
sahithiRavindranath:main

Conversation

@sahithiRavindranath
Copy link
Copy Markdown

Issue Description:
The current sos report only gathers podman data for the root user. It is unable to collect container data belonging to non‑root users because sos report runs with elevated (sudo) privileges.

Solution:
Added a new plugin option, allusers, to the podman plugin. When enabled, this option collects podman container data for all non‑root users which has container running on the system in addition to the root user.


Please place an 'X' inside each '[]' to confirm you adhere to our Contributor Guidelines

  • Is the commit message split over multiple lines and hard-wrapped at 72 characters?
  • Is the subject and message clear and concise?
  • Does the subject start with [plugin_name] if submitting a plugin patch or a [section_name] if part of the core sosreport code?
  • Does the commit contain a Signed-off-by: First Lastname email@example.com?
  • Are any related Issues or existing PRs properly referenced via a Closes (Issue) or Resolved (PR) line?
  • Are all passwords or private data gathered by this PR obfuscated?

Comment thread sos/report/plugins/podman.py Outdated
if user == 'root':
command = ""
else:
# Check if user has any containers before collecting data
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Worth to move command = "sudo -u "+ user from line 88 here.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I've removed all embedded sudo calls and now use the runas parameter instead, as requested by @TurboTurtle.

Comment thread sos/report/plugins/podman.py Outdated
if self.get_option('allusers'):
non_root_users = self.exec_cmd("lslogins -u -o USER --noheadings")
if non_root_users['status'] == 0:
for user in non_root_users['output'].splitlines()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Missing trailing :

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed

Comment thread sos/report/plugins/podman.py Outdated

self.add_cmd_tags({
f'{command} podman images': 'podman_list_images',
f'{command} podman ps': 'podman_list_containers'
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Do we (and should we) support adding one tag for multiple command outputs, @TurboTurtle ? This is being tagged for each and every user, incl. root.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We do, and I believe we should. I'm not immediately opposed to adding the same tag that root gets to non-root users, but I'd suggest checking with at least the Insights team to see if this would throw off anything for them.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Current implementation uses the same tag for all users. Should I switch to unique tags per user (e.g., podman_list_images_root, podman_list_images_user1) or keep the shared tag approach?"

Comment thread sos/report/plugins/podman.py Outdated
command = ""
else:
# Check if user has any containers before collecting data
cmd = self.exec_cmd(f"{command} podman ps -aq")
Copy link
Copy Markdown
Contributor

@pmoravec pmoravec Apr 13, 2026

Choose a reason for hiding this comment

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

This fails if the user does not have permissions to access ${PWD} where the root is. E.g. trying this on a containerised AAP deployment where podman containers run under my aap user:

# who am I
root     pts/0        2026-04-13 12:03 (10.44.32.126)
# pwd
/root/sos-main-pr4290
# sudo -u aap podman ps -aq
cannot chdir to /root/sos-main-pr4290: Permission denied
# su - aap -c "podman ps -aq"
8a634b8461cb
.. list of podman container ids ..
#

(but I dont know if the su - {user} -c .. is the best approach here)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed! Using the runas parameter instead of embedded sudo solves this - the sos framework handles working directory permissions properly. I've also added exception handling to gracefully skip users that can't be accessed

@packit-as-a-service
Copy link
Copy Markdown

Congratulations! One of the builds has completed. 🍾

You can install the built RPMs by following these steps:

  • sudo dnf install -y 'dnf*-command(copr)'
  • dnf copr enable packit/sosreport-sos-4290
  • And now you can install the packages.

Please note that the RPMs should be used only in a testing environment.

Comment thread sos/report/plugins/podman.py Outdated
Comment on lines +90 to +91
else:
command = "sudo -u "+ user
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nack.

We do not permit embedded sudo calls in plugins. For any collection that needs to be done as a non-root user, you need to use the runas parameter to add_cmd_output(). I believe we have a single exception to this today in pulp, but it is something we have worked to eliminate over the last few years.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed! All embedded sudo calls removed. Now using runas parameter throughout.

Comment thread sos/report/plugins/podman.py Outdated
Comment on lines +85 to +89
for user in users:
if not user:
continue
if user == 'root':
command = ""
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Rather than nesting everything under a potentially large item loop like this, it'd be cleaner to instead break the collection into another method (or several, even) and call that method from the loop, with the user as an optional argument. The default here would be to run as root, and always be fired, with non-root iterations only firing if the users list above is populated at all (i.e. root should not be included).

This would be a cleaner approach and would also allow for easier future modification and any per-user validations we may want to do.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

broke the loop into several helper functions and calling the those function for root user always regardless if non-root_list is populated at all.

@TurboTurtle TurboTurtle added Kind/Enhancement Status/Needs Review This issue still needs a review from project members Kind/Collection New or updated command or file collection labels Apr 13, 2026
@sahithiRavindranath sahithiRavindranath force-pushed the main branch 2 times, most recently from d22a871 to d4f5786 Compare April 17, 2026 08:34
@sahithiRavindranath
Copy link
Copy Markdown
Author

I can see there are 1 test case failing on Debian and 2 on Ubuntu:

Debian 13
Link: https://github.com/sosreport/sos/pull/4290/checks?check_run_id=71792161692

Error: ModuleNotFoundError: No module named 'pkg_resources'

This is nothing to do with my changes I think. The module is needed for package build.

Ubuntu 25.10 DEB
Link: https://github.com/sosreport/sos/pull/4290/checks?check_run_id=71792157716

Results: PASS 254 | ERROR 0 | FAIL 1 | SKIP 26 | WARN 0 | INTERRUPT 0 | CANCEL 0

Job Time: 990.12 s

Failed Test: 152-tests/report_tests/encryption_tests.py:EncryptedCleanedReportTest.test_archive_gpg_encrypted

This is something to do with Encryption, which I think is not related to my patch.

Ubuntu 25.10 Snap
✅ 00:04 clone
❌ 29:55 setup
It is a setup failure.

@pmoravec @TurboTurtle It seems the above test case failures are unrelated to the changes introduced by this pull request. Please confirm if that is not the case.

@arif-ali
Copy link
Copy Markdown
Member

@sahithiRavindranath if you rebase to main, the pkg_resources will go away. I have just restarted the 2 ubuntu jobs, as one timed out, and the other may have other issues.

Copy link
Copy Markdown
Member

@TurboTurtle TurboTurtle left a comment

Choose a reason for hiding this comment

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

Looking very solid, just a few minor touch points below.

Comment thread sos/report/plugins/podman.py Outdated
Comment on lines +118 to +122
try:
cmd = self.exec_cmd("podman ps -aq", runas=user)
return cmd['status'] == 0 and cmd['output'].strip()
except subprocess.SubprocessError:
return False
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We shouldn't ever be throwing a subprocess exception here via exec_cmd(), or at least we don't intend to be doing so. Did you run into one? I'd rather fix that within Plugin (separately to this PR), than capture that here. The intent behind exec_cmd(), like anything else that culminates in a call to sos_get_command_output(), is that any exception results in a non-zero status value rather than trickling back up to the call.

Copy link
Copy Markdown
Author

@sahithiRavindranath sahithiRavindranath May 6, 2026

Choose a reason for hiding this comment

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

Yes, encountered this during testing when switching to certain users:

subprocess.SubprocessError: Exception occurred in preexec_fn.
File "/usr/lib64/python3.9/subprocess.py", line 1838, in _execute_child
raise child_exception_type(err_msg)

The exception occurs at utilities.py line 346 during Popen() initialization when preexec_fn fails during user switching (permission issues).

I've removed the try-except from the plugin. Can the exception handling be added in sos_get_command_output() as below?

diff --git a/sos/utilities.py b/sos/utilities.py
index 2646ab22..4910acbe 100644
--- a/sos/utilities.py
+++ b/sos/utilities.py
@@ -10,7 +10,7 @@ import os
 import pwd
 import re
 import inspect
-from subprocess import Popen, PIPE, STDOUT
+from subprocess import Popen, PIPE, STDOUT, SubprocessError
 import logging
 import fnmatch
 import errno
@@ -407,6 +407,11 @@ def sos_get_command_output(command, timeout=TIMEOUT_DEFAULT, stderr=False,
         if e.errno == errno.ENOENT:
             return {'status': 127, 'output': "", 'truncated': ''}
         raise e
+    except SubprocessError:
+        # Handle exceptions in preexec_fn (e.g., user switching failures)
+        # Return 126 (command cannot execute)
+        return {'status': 126, 'output': "", 'truncated': ''}
     finally:
         if hasattr(_output, 'close'):
             _output.close()

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

@TurboTurtle Following up on the diff above. The SubprocessError handling would prevent preexec_fn exceptions by returning status 126 instead. Thoughts on this approach?

Comment thread sos/utilities.py
Comment on lines +302 to +304
# XDG_RUNTIME_DIR is required for rootless podman to access
# user-specific runtime files and sockets
'XDG_RUNTIME_DIR': f"/run/user/{pwd_user.pw_uid}"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

ack for this usecase, but I wonder if there are situation where we don't want to be passing this by default? @pmoravec @arif-ali any concerns here?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

No concerns.

Comment thread sos/report/plugins/podman.py Outdated
#
# See the LICENSE file in the source distribution for further information.

import shlex
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We haven't seen the need to shlex.quote the entities this is being added to previously, or at least none has been reported.

I'm curious what causes the need here? Not saying doing this is a problem or anything, just wondering.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Added as defensive coding for edge cases with special characters in container/image/volume names. However, since it hasn't been needed historically, I've removed it per your feedback. All shlex.quote() calls and the import have been removed.

@sahithiRavindranath sahithiRavindranath force-pushed the main branch 2 times, most recently from 0e80347 to 4035372 Compare May 8, 2026 04:58

def _user_has_containers(self, user):
"""Check if user has any containers before collecting data"""
cmd = self.exec_cmd("podman ps -aq", runas=user)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This does not scale well when there are tens or hundreds of users (I hope lslogins -u -o USER --noheadings does not list AD / LDAP users..?). I think it is fine for now, but we might need to improve it in future.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Ack. I'll optimize it in future iterations.

Copy link
Copy Markdown
Member

@TurboTurtle TurboTurtle left a comment

Choose a reason for hiding this comment

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

Minor change I'd like to see, should have caught it earlier, my apologies for the review delay.

Comment thread sos/report/plugins/podman.py Outdated
non_root_users = self._get_non_root_users()
for user in non_root_users:
if self._user_has_containers(user):
self._collect_for_user(user, f'{user}/', subcmds)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

One last change request here. Instead of putting user dirs in the top-level plugin directory, let's nest them, perhaps under a users dir or somesuch. Just to keep things a little more tidy.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed. User directories are now nested under users/

Issue Description:
The current sos report only gathers podman data for the root user.
It is unable to collect container data belonging to non‑root users
because sos report runs with elevated (sudo) privileges.

Solution:
Added a new plugin option, allusers, to the podman plugin. When
enabled, this option collects podman container data for all non‑root
users which has container running on the system in addition to the
root user.

Signed-off-by: Sahithi Ravindranath <sahithi.Ravindranath@ibm.com>
@sahithiRavindranath
Copy link
Copy Markdown
Author

rebased to main

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Kind/Collection New or updated command or file collection Kind/Enhancement Status/Needs Review This issue still needs a review from project members

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants