Skip to content

Conversation

@EnigmaXV
Copy link
Contributor

@EnigmaXV EnigmaXV commented Dec 9, 2025

  • Implemented both backend and frontend parts of the bulk power state feature
  • Added backend unit tests
  • Implemented new endpoint for changing the power state
  • Synced power state updates with the power status icon

@github-actions github-actions bot added the UI label Dec 9, 2025
@EnigmaXV EnigmaXV force-pushed the 38948-add-power-state-bulk-actions branch from 4a1e36d to 10df08a Compare December 9, 2025 23:13
@sbernhard sbernhard requested a review from jeremylenz December 19, 2025 12:50
sbernhard
sbernhard previously approved these changes Dec 19, 2025
Copy link
Contributor

@sbernhard sbernhard left a comment

Choose a reason for hiding this comment

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

Thanks Omar. Very cool addition.

@nadjaheitmann
Copy link
Contributor

It looks great @EnigmaXV !

@jeremylenz
Copy link
Contributor

@chris1984 is going to give this a quick test, stand by :)

@lfu
Copy link
Contributor

lfu commented Dec 19, 2025

The tests looked good to me. Power state was updated correctly on the host index page.
power on

Sometimes I noticed each host was called for power state twice. And sometimes only some hosts got called for power state twice.
And I think each host should be called only once for power state after the power change.
Not sure what is exactly going on here. Maybe it is expected.

12:31:12 rails.1   | 2025-12-19T12:31:12 [I|app|25b30605] Started PUT "/api/v2/hosts/bulk/change_power_state" for xxx at 2025-12-19 12:31:12 -0500
12:31:12 rails.1   | 2025-12-19T12:31:12 [I|app|25b30605] Processing by Api::V2::HostsBulkActionsController#change_power_state as JSON
12:31:12 rails.1   | 2025-12-19T12:31:12 [I|app|25b30605]   Parameters: {"included"=>{"search"=>"id ^ (12)"}, "power"=>"start", "apiv"=>"v2", "hosts_bulk_action"=>{"included"=>{"search"=>"id ^ (12)"}, "power"=>"start"}}
12:31:13 rails.1   | 2025-12-19T12:31:13 [D|app|25b30605] Body: {"message":"The power state of the selected hosts will be set to start"}
12:31:13 rails.1   | 2025-12-19T12:31:13 [I|app|25b30605] Completed 200 OK in 861ms (Views: 0.2ms | ActiveRecord: 2.7ms | Allocations: 36098)
12:31:13 rails.1   |  25b30605 | 
12:31:13 rails.1   |  25b30605 | 
12:31:13 rails.1   | 2025-12-19T12:31:13 [I|app|4a7f8dd9] Started GET _"/api/v2/hosts/xxxx-67-29.x.com/power"_ for xxx at 2025-12-19 12:31:13 -0500
12:31:13 rails.1   | 2025-12-19T12:31:13 [I|app|b803c564] Started GET "/api/hosts" for xxx at 2025-12-19 12:31:13 -0500
12:31:13 rails.1   | 2025-12-19T12:31:13 [I|app|2752c148] Started GET "/api/v2/hosts/xxxx-85.lx.com/power" for xxx at 2025-12-19 12:31:13 -0500
12:31:13 rails.1   | 2025-12-19T12:31:13 [I|app|f1ee1942] Started GET "/api/v2/hosts/xxxx-249.x.com-1/power" for xxx at 2025-12-19 12:31:13 -0500
12:31:13 rails.1   | 2025-12-19T12:31:13 [I|app|9e2c0602] Started GET "/api/v2/hosts/xxxx-175.x.com/power" for xxx at 2025-12-19 12:31:13 -0500
12:31:13 rails.1   | 2025-12-19T12:31:13 [I|app|4a7f8dd9] Processing by Api::V2::HostsController#power_status as JSON
12:31:13 rails.1   | 2025-12-19T12:31:13 [I|app|4a7f8dd9]   Parameters: {"apiv"=>"v2", "id"=>"xxxx-67-29.x.com"}
...
12:31:13 rails.1   | 2025-12-19T12:31:13 [I|app|16def301] Started GET _"/api/v2/hosts/xxxx-67-29.x.com/power"_ for xxx at 2025-12-19 12:31:13 -0500
...
12:31:13 rails.1   | 2025-12-19T12:31:13 [I|app|16def301] Processing by Api::V2::HostsController#power_status as JSON
12:31:13 rails.1   | 2025-12-19T12:31:13 [I|app|16def301]   Parameters: {"apiv"=>"v2", "id"=>"xxxx-67-29.x.com"}
12:31:13 rails.1   | 2025-12-19T12:31:13 [D|app|16def301] Body: {"id":1,"state":"na","title":"N/A","statusText":"Power operations are not enabled on this host."}
12:31:13 rails.1   | 2025-12-19T12:31:13 [I|app|16def301] Completed 200 OK in 22ms (Views: 0.2ms | ActiveRecord: 8.7ms | Allocations: 8018)
12:31:13 rails.1   |  16def301 | 
12:31:13 rails.1   |  16def301 | 

@chris1984
Copy link
Member

Tested and working good as far as turning on and off the hosts. I did notice what @lfu mentioned as well with it being called twice.

@EnigmaXV
Copy link
Contributor Author

EnigmaXV commented Jan 9, 2026

Thx @chris1984 and @lfu for your feedback

I tried a few things to rule out unintended re-renders (memoizing inputs, guarding bumpRefresh with refs, removing the hosts list refetch to avoid extra renders, and checking Redux DevTools + Network to confirm there’s no polling or interval involved).

From what I can tell, the behavior comes from the current design: each row renders a HostPowerStatus component that fetches its state on mount, and after a successful bulk power change we trigger a refresh so the icons update. That results in one request per host initially, and one additional request per host after the change.

It’s also worth mentioning that the second request is returned as 304 Not Modified, so it’s served from cache and doesn’t re-hit the backend. Because of that, I don’t think this is a major performance issue right now.

Happy to hear if I missed something or if there’s a preferred approach here.

@lfu
Copy link
Contributor

lfu commented Jan 9, 2026

Thanks @EnigmaXV for taking time looking into the issue.

From what I can tell, the behavior comes from the current design: each row renders a HostPowerStatus component that fetches its state on mount, and after a successful bulk power change we trigger a refresh so the icons update. That results in one request per host initially, and one additional request per host after the change.

That is the behavior I would expect. But I noticed multiple 'power' requests per host after power state change.

If no experts with power related functions object here, the current change is fine with me.

@EnigmaXV EnigmaXV force-pushed the 38948-add-power-state-bulk-actions branch from 10df08a to 47d1648 Compare January 14, 2026 15:17
@sbernhard
Copy link
Contributor

@chris1984 / @jeremylenz Should we then finish / merge this PR after the explanation from @EnigmaXV ?

@ekohl
Copy link
Member

ekohl commented Jan 19, 2026

We are about to enter Foreman 3.18 stabilization: https://community.theforeman.org/t/foreman-3-18-branching-process/45265 Not making any judgement if it should or should not be merged but reminding you the merge window for features closes at the end of the month. The sooner a decision is made, the better

@jeremylenz
Copy link
Contributor

I'm going to see if anyone can show me these multiple requests so I can take a look, but I really would like to merge this before stabilization. If it works otherwise we can improve it later.

@ekohl
Copy link
Member

ekohl commented Jan 19, 2026

Note we have https://github.com/theforeman/smart-proxy/blob/develop/docs/bmc.md which can help you to set up the power management features without the physical hardware.

Copy link
Contributor

@jeremylenz jeremylenz left a comment

Choose a reason for hiding this comment

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

I do see 2 requests per host to GET api/v2/hosts/:id/power. (They all return 200 OK.) It should be at most 1 request. However, since this PR is well tested and works as expected otherwise, I am going to open a followup issue for that. https://projects.theforeman.org/issues/39009

@jeremylenz jeremylenz merged commit 16e9ca9 into theforeman:develop Jan 19, 2026
26 checks passed
@maximiliankolb maximiliankolb deleted the 38948-add-power-state-bulk-actions branch January 21, 2026 12:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants