From b30393fd7fb43f4e9be7f74e5dd2f0e95d0e9c60 Mon Sep 17 00:00:00 2001 From: jakduch Date: Tue, 7 Apr 2026 13:17:31 +0200 Subject: [PATCH] Fixes #455 - skip Proxmox compute orchestration for unmanaged hosts When a host is registered via Global Registration with a hostgroup that has a Compute Resource (Proxmox), the compute orchestration methods (setComputeUpdate, delComputeUpdate, setComputeDetails) are triggered even though the host is unmanaged (managed: false). This causes errors like "protected method setCompute called" because the orchestration tries to interact with the Proxmox API for a host that was not provisioned through Foreman. This patch adds managed? guards with log messages to skip Proxmox-specific compute orchestration for unmanaged hosts, analogous to foreman core PR #10905. Unit tests verify all three methods skip orchestration and log appropriately for unmanaged hosts. Assisted-By: Claude (Anthropic) --- .../concerns/orchestration/proxmox/compute.rb | 13 ++++ .../proxmox_orchestration_compute_test.rb | 67 +++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 test/unit/foreman_fog_proxmox/proxmox_orchestration_compute_test.rb diff --git a/app/models/concerns/orchestration/proxmox/compute.rb b/app/models/concerns/orchestration/proxmox/compute.rb index 20771575d..026b4f5e5 100644 --- a/app/models/concerns/orchestration/proxmox/compute.rb +++ b/app/models/concerns/orchestration/proxmox/compute.rb @@ -26,6 +26,11 @@ def setComputeUpdate if compute_resource.class != ForemanFogProxmox::Proxmox super else + unless managed? + logger.info(format("Skipping Proxmox compute update for %s - host is not managed", name)) + return true + end + logger.info "Update Proxmox Compute instance for #{name}" final_compute_attributes = compute_attributes.merge(compute_resource.host_compute_attrs(self)) logger.debug("setComputeUpdate: final_compute_attributes=#{final_compute_attributes}") @@ -40,6 +45,11 @@ def delComputeUpdate if compute_resource.class != ForemanFogProxmox::Proxmox super else + unless managed? + logger.info(format("Skipping Proxmox compute update rollback for %s - host is not managed", name)) + return true + end + logger.info "Undo Update Proxmox Compute instance for #{name}" final_compute_attributes = old.compute_attributes.merge(compute_resource.host_compute_attrs(old)) compute_resource.save_vm uuid, final_compute_attributes @@ -97,6 +107,9 @@ def setVmDetails def setComputeDetails if compute_resource.class != ForemanFogProxmox::Proxmox super + elsif !managed? + logger.info(format("Skipping Proxmox compute details for %s - host is not managed", name)) + true elsif vm setVmDetails else diff --git a/test/unit/foreman_fog_proxmox/proxmox_orchestration_compute_test.rb b/test/unit/foreman_fog_proxmox/proxmox_orchestration_compute_test.rb new file mode 100644 index 000000000..0e5562077 --- /dev/null +++ b/test/unit/foreman_fog_proxmox/proxmox_orchestration_compute_test.rb @@ -0,0 +1,67 @@ +# frozen_string_literal: true + +# Copyright 2018 Tristan Robert + +# This file is part of ForemanFogProxmox. + +# ForemanFogProxmox is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# ForemanFogProxmox is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with ForemanFogProxmox. If not, see . + +require 'test_plugin_helper' + +module ForemanFogProxmox + class ProxmoxOrchestrationComputeTest < ActiveSupport::TestCase + describe 'unmanaged host with Proxmox compute resource' do + let(:cr) { FactoryBot.build_stubbed(:proxmox_cr) } + let(:host) do + FactoryBot.build(:host_empty, + :managed => false, + :compute_resource => cr, + :compute_attributes => { 'type' => 'qemu' }) + end + + test 'setComputeUpdate skips orchestration for unmanaged host' do + assert host.setComputeUpdate + end + + test 'setComputeUpdate logs info when skipping for unmanaged host' do + mock_logger = mock('logger') + mock_logger.expects(:info).with(format("Skipping Proxmox compute update for %s - host is not managed", host.name)) + host.stubs(:logger).returns(mock_logger) + host.setComputeUpdate + end + + test 'delComputeUpdate skips orchestration for unmanaged host' do + assert host.delComputeUpdate + end + + test 'delComputeUpdate logs info when skipping for unmanaged host' do + mock_logger = mock('logger') + mock_logger.expects(:info).with(format("Skipping Proxmox compute update rollback for %s - host is not managed", host.name)) + host.stubs(:logger).returns(mock_logger) + host.delComputeUpdate + end + + test 'setComputeDetails skips orchestration for unmanaged host' do + assert host.setComputeDetails + end + + test 'setComputeDetails logs info when skipping for unmanaged host' do + mock_logger = mock('logger') + mock_logger.expects(:info).with(format("Skipping Proxmox compute details for %s - host is not managed", host.name)) + host.stubs(:logger).returns(mock_logger) + host.setComputeDetails + end + end + end +end