Skip to content

Bind-mount RH Cloud inventory reports into Foreman and Dynflow - #825

Open
nofaralfasi wants to merge 1 commit into
theforeman:masterfrom
nofaralfasi:rh-cloud-inventory-exports
Open

Bind-mount RH Cloud inventory reports into Foreman and Dynflow#825
nofaralfasi wants to merge 1 commit into
theforeman:masterfrom
nofaralfasi:rh-cloud-inventory-exports

Conversation

@nofaralfasi

@nofaralfasi nofaralfasi commented Sep 10, 2026

Copy link
Copy Markdown

Why are you introducing these changes? (Problem description, related links)

foreman-rake rh_cloud_inventory:report:generate writes reports under /var/lib/foreman/red_hat_inventory. In a containerized deploy that directory is not bind-mounted, so the file is not available on the host, and Foreman and Dynflow do not share the same tree.

/var/lib/foreman already exists for IoP manual override files (root:root, not mounted into Foreman/Dynflow). This PR bind-mounts that directory so inventory reports (and anything else written there) are on the host and shared. See #647 and #755.

Fixes: https://redhat.atlassian.net/browse/SAT-48305

What are the changes introduced in this pull request?

  • Create /var/lib/foreman (root:root, 0755)
  • Bind-mount /var/lib/foreman into the Foreman and Dynflow containers (rw,z,U)
  • Allow rh_cloud_inventory:report:generate in the foreman-rake wrapper
  • Add tests for the directory, mounts, write access from Foreman and Dynflow, and the rake allowlist

How to test this pull request

Steps to reproduce:

  • Deploy, then ./foremanctl deploy --add-feature rh-cloud (or --add-feature iop)
  • Confirm /var/lib/foreman exists on the host
  • Confirm the bind mount (/var/lib/foreman -> /var/lib/foreman):
    podman inspect foreman --format '{{json .Mounts}}'
    podman inspect dynflow-sidekiq-worker --format '{{json .Mounts}}'
  • Confirm both containers can write, and a Dynflow-created file is visible in Foreman and on the host
  • Run foreman-rake rh_cloud_inventory:report:generate and check /var/lib/foreman/red_hat_inventory/generated_reports/
  • From the machine that SSHes into the VM (not on the VM itself):
    ./forge test --pytest-args 'tests/feature/foreman/inventory_storage_test.py tests/feature/foreman/foreman_rake_test.py -vv'

@coderabbitai

coderabbitai Bot commented Sep 10, 2026

Copy link
Copy Markdown

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Advanced

Run ID: 00dca4fc-d475-4d9a-9c47-49b77d622ef6

📥 Commits

Reviewing files that changed from the base of the PR and between 1f14946 and 4bb9eab.

📒 Files selected for processing (2)
  • src/roles/foreman/tasks/main.yaml
  • tests/feature/foreman/inventory_storage_test.py

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

The change provisions /var/lib/foreman, mounts it into Foreman and Dynflow, permits the inventory report rake action, and adds tests for storage sharing, write access, and action validation.

Changes

Foreman inventory integration

Layer / File(s) Summary
Shared inventory storage and mounts
src/roles/foreman/tasks/main.yaml, tests/feature/foreman/inventory_storage_test.py
Creates /var/lib/foreman with root ownership and mode 0755. Mounts the path into Foreman and Dynflow. Tests mounts, write access, shared visibility, and inventory export access.
Inventory report rake action
src/roles/foreman/templates/foreman-rake.j2, tests/feature/foreman/foreman_rake_test.py
Allows rh_cloud_inventory:report:generate and verifies that the wrapper contains the action.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Suggested reviewers: ehelms

Merge Risk: ⚪ Minimal · up to 4bb9e

No actionable merge-blocking risk remains from the reviewed changes.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 7 functions across 2 files. (1 skipped: 1 … Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the primary change: bind-mounting Red Hat Cloud inventory reports into the Foreman and Dynflow containers.
Description check ✅ Passed The description directly explains the problem, implementation, testing steps, and scope of the inventory storage changes.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 7 functions across 2 files. (1 skipped: 1 unsupported.)

  • Fix all pre-merge checks with AI

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Comment thread src/roles/foreman/tasks/main.yaml Outdated
# can drop files on the host.
- name: Create RH Cloud inventory directory
ansible.builtin.file:
path: /var/lib/foreman/red_hat_inventory/exports

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.

Let's just bind mount /var/lib/foreman

@ehelms

ehelms commented Sep 10, 2026

Copy link
Copy Markdown
Member

Is there an issue tracking re-design of the report generation to not rely on an admin SSHing into their Satellite but rather being able to use the API and download the report?

@nofaralfasi

Copy link
Copy Markdown
Author

Is there an issue tracking re-design of the report generation to not rely on an admin SSHing into their Satellite but rather being able to use the API and download the report?

I haven’t found a tracker for that redesign. SAT-48305 is only this PR: make the current rake path work in containers by bind-mounting the report directory.

Generate and download via API already exist (POST/GET /api/v2/organizations/:id/rh_cloud/report). The Inventory Upload “Download report” button already uses that GET. Generation from the UI uses a different endpoint (POST /foreman_inventory_upload/:org_id/reports). Both still write or serve the archive from disk, which is why the shared mount is needed for containers.

I can file a foreman_rh_cloud issue if we want to track moving this off the local filesystem.

foreman_rh_cloud writes reports under /var/lib/foreman/red_hat_inventory.
Without a shared host bind mount those files stay inside a single
container, so rake generate cannot drop a retrievable file and Dynflow
jobs cannot share reports with Foreman.
@nofaralfasi
nofaralfasi force-pushed the rh-cloud-inventory-exports branch from 1f14946 to 4bb9eab Compare September 11, 2026 13:40
@ehelms

ehelms commented Sep 11, 2026

Copy link
Copy Markdown
Member

If the API and UI handle this for the user already, why do we need the rake task?

@lfu

lfu commented Sep 11, 2026

Copy link
Copy Markdown

I deployed this branch (4bb9eab) with foremanctl deploy on a clean RHEL 9.8 host. Foreman doesn't boot — the deploy fails at RUNNING HANDLER [foreman : Restart foreman]:

cannot load such file -- /usr/share/foreman/db/seeds.d/020-roles_list.rb (LoadError)
    from /usr/share/foreman/lib/seed_helper.rb:1:in `<top (required)>'

/var/lib/foreman isn't an empty data dir in the image — the app symlinks into it:

/usr/share/foreman/public -> /var/lib/foreman/public   # assets/ + webpack/, 168 MB
/usr/share/foreman/db     -> /var/lib/foreman/db       # migrate, seeds.rb, seeds.d

Mounting an empty host dir over it hides both. seed_helper.rb requires every file in db/seeds.d/ during the Rails finisher, so boot dies there; public/ being gone would break the UI's CSS/JS too. Same for the three dynflow-sidekiq@ instances. Only foreman-db-migrate survives, because it has no volume.

I then narrowed both Volume= lines on the deployed host to /var/lib/foreman/red_hat_inventory:/var/lib/foreman/red_hat_inventory:rw,z,U, daemon-reloaded and started the services:

  • foreman and all three dynflow-sidekiq@ instances active
  • image content intact in the container: 177 files in public/assets, 20 in db/seeds.d
  • /api/v2/ping healthy, and GET /assets/application-<digest>.css returns 200 / 444 KB
  • dynflow writes red_hat_inventory/generated_reports/report_for_1.tar.xz, foreman reads it, and it's on the host as 994:994

So the original red_hat_inventory target both fixes the boot failure and delivers the sharing this PR is after. One adjustment needed: the file task has to create /var/lib/foreman/red_hat_inventory, not just the parent.

Worth noting the mount is added unconditionally, while foreman_rh_cloud is gated behind the rh-cloud feature (FOREMAN_ENABLED_PLUGINS). On my deploy without it, foreman-rake rh_cloud_inventory:report:generate returns Don't know how to build task — so every deployment takes the boot risk for a feature only some enable. Might be worth conditioning the mount on rh-cloud.

Three smaller things:

  1. test_foreman_storage_directory can't pass live — :U chowns whatever the mount source is to the container user, so root:root doesn't survive container start; on the deployed host /var/lib/foreman came out drwxr-xr-x 2 994 994. The file task also re-chowns it every run, so it reports changed forever. (If you narrow the mount, keep that assertion on the parent — the red_hat_inventory subdir becomes 994.)

  2. exports isn't a directory foreman_rh_cloud uses (it has generated_reports/, uploads/, uploads/done/, outputs/). The test mkdir -ps it, so it passes vacuously — generated_reports is the one that matters.

  3. The rake allowlist entry alone doesn't make the report retrievable. report:generate uses base_folder = ENV['target'] || Dir.pwd; Dir.pwd is the root-owned /usr/share/foreman, so it falls back to Dir.mktmpdir. I ran it on the deployed host:

    /usr/share/foreman is not writable by the current process
    Using /tmp/d20260911-455-p46nz9 for the output
    

    That tmpdir is created in the foreman container, but the report is written by HostInventoryReportJob in a dynflow worker — which doesn't have that path (/tmp isn't shared). It ended up empty in the foreman container and absent from both the worker and the host. So the task needs target= pointing at the shared mount, e.g. /var/lib/foreman/red_hat_inventory/generated_reports. (report:generate_upload already passes generated_reports_folder, so only generate has this.)

The UI/API path does justify the shared mount either way: generation runs in a dynflow worker writing to generated_reports_folder, and download is served by the foreman container reading the same path.

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.

3 participants