diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/ha/ConfigureHAForHostCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/ha/ConfigureHAForHostCmd.java index d7707e197d64..04fe128eb9c2 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/ha/ConfigureHAForHostCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/ha/ConfigureHAForHostCmd.java @@ -38,6 +38,9 @@ import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.ha.HAConfigManager; import org.apache.cloudstack.ha.HAResource; +import org.apache.cloudstack.outofbandmanagement.OutOfBandManagementService; +import com.cloud.hypervisor.Hypervisor.HypervisorType; + import javax.inject.Inject; @@ -50,6 +53,9 @@ public final class ConfigureHAForHostCmd extends BaseAsyncCmd { @Inject private HAConfigManager haConfigManager; + @Inject + private OutOfBandManagementService outOfBandManagementService; + ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// ///////////////////////////////////////////////////// @@ -98,6 +104,12 @@ public void execute() throws ResourceUnavailableException, InsufficientCapacityE throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Unable to find host by ID: " + getHostId()); } + if (host.getHypervisorType() == HypervisorType.KVM) { + if (!outOfBandManagementService.isOutOfBandManagementEnabled(host)) { + throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Cannot configure HA on KVM host because Out-of-Band Management (OOBM) is not enabled."); + } + } + final boolean result = haConfigManager.configureHA(host.getId(), HAResource.ResourceType.Host, getHaProvider()); if (!result) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to configure HA provider for the host"); diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/ha/EnableHAForHostCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/ha/EnableHAForHostCmd.java index f54767225432..82a9f6554012 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/ha/EnableHAForHostCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/ha/EnableHAForHostCmd.java @@ -37,7 +37,8 @@ import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.ha.HAConfigManager; import org.apache.cloudstack.ha.HAResource; - +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import org.apache.cloudstack.outofbandmanagement.OutOfBandManagementService; import javax.inject.Inject; @APICommand(name = "enableHAForHost", description = "Enables HA for a host", @@ -49,6 +50,10 @@ public final class EnableHAForHostCmd extends BaseAsyncCmd { @Inject private HAConfigManager haConfigManager; + @Inject + private OutOfBandManagementService outOfBandManagementService; + + ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// ///////////////////////////////////////////////////// @@ -89,6 +94,15 @@ public void execute() throws ResourceUnavailableException, InsufficientCapacityE if (host == null) { throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Unable to find host by ID: " + getHostId()); } + + // --- YOUR NEW GUARDRAIL --- + if (host.getHypervisorType() == HypervisorType.KVM) { + if (!outOfBandManagementService.isOutOfBandManagementEnabled(host)) { + throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Cannot enable HA on KVM host because Out-of-Band Management (OOBM) is not enabled."); + } + } + // -------------------------- + final boolean result = haConfigManager.enableHA(host.getId(), HAResource.ResourceType.Host); CallContext.current().setEventDetails("Host Id:" + host.getId() + " HA enabled: true"); diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/outofbandmanagement/DisableOutOfBandManagementForHostCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/outofbandmanagement/DisableOutOfBandManagementForHostCmd.java index 6c9b48ef28f7..6ae61b11de8b 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/outofbandmanagement/DisableOutOfBandManagementForHostCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/outofbandmanagement/DisableOutOfBandManagementForHostCmd.java @@ -38,6 +38,9 @@ import org.apache.cloudstack.api.response.OutOfBandManagementResponse; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.outofbandmanagement.OutOfBandManagementService; +import org.apache.cloudstack.ha.HAConfigManager; +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import org.apache.cloudstack.ha.HAResource; import javax.inject.Inject; @@ -46,6 +49,9 @@ since = "4.9.0", authorized = {RoleType.Admin}) public class DisableOutOfBandManagementForHostCmd extends BaseAsyncCmd { + @Inject + private HAConfigManager haConfigManager; + @Inject private OutOfBandManagementService outOfBandManagementService; @@ -61,13 +67,22 @@ public class DisableOutOfBandManagementForHostCmd extends BaseAsyncCmd { /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// - @Override - final public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException { + @Override + public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException { final Host host = _resourceService.getHost(getHostId()); if (host == null) { throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Unable to find host by ID: " + getHostId()); } + if (host.getHypervisorType() == HypervisorType.KVM) { + java.util.List haConfigs = haConfigManager.listHAResources(host.getId(), HAResource.ResourceType.Host); + if (haConfigs != null && !haConfigs.isEmpty()) { + if (haConfigs.get(0).isEnabled()) { + throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Cannot disable Out-of-Band Management (OOBM) because HA is currently enabled on this KVM host. Please disable HA first."); + } + } + } + OutOfBandManagementResponse response = outOfBandManagementService.disableOutOfBandManagement(host); CallContext.current().setEventDetails("Host Id:" + host.getId() + " out-of-band management enabled: false"); diff --git a/test/integration/smoke/test_hostha_kvm.py b/test/integration/smoke/test_hostha_kvm.py index 9b131558dc24..e43040cd018d 100644 --- a/test/integration/smoke/test_hostha_kvm.py +++ b/test/integration/smoke/test_hostha_kvm.py @@ -88,6 +88,7 @@ def setUp(self): self.configureAndDisableHostHa() self.cleanup = [self.service_offering] + self.configureAndEnableOobm() def updateConfiguration(self, name, value): cmd = updateConfiguration.updateConfigurationCmd() @@ -229,6 +230,7 @@ def test_disable_oobm_ha_state_ineligible(self): self.logger.debug("Starting test_disable_oobm_ha_state_ineligible") # Enable ha for host + self.configureAndEnableOobm() self.configureAndEnableHostHa() # Disable OOBM @@ -252,6 +254,7 @@ def test_hostha_configure_default_driver(self): """ self.logger.debug("Starting test_hostha_configure_default_driver") + self.configureAndEnableOobm() cmd = self.getHostHaConfigCmd() response = self.apiclient.configureHAForHost(cmd) self.assertEqual(response.hostid, cmd.hostid) @@ -343,6 +346,7 @@ def test_remove_ha_provider_not_possible(self): # Enable HA + self.configureAndEnableOobm() self.apiclient.configureHAForHost(self.getHostHaConfigCmd()) cmd = self.getHostHaEnableCmd() cmd.hostid = self.host.id @@ -403,6 +407,7 @@ def test_hostha_kvm_host_recovering(self): self.skipIfMSIsUnsupported() self.configureAndStartIpmiServer() self.assertIssueCommandState('ON', 'On') + self.configureAndEnableOobm() self.configureAndEnableHostHa() self.deployVM() @@ -443,6 +448,7 @@ def test_hostha_kvm_host_fencing(self): self.skipIfMSIsUnsupported() self.configureAndStartIpmiServer() self.assertIssueCommandState('ON', 'On') + self.configureAndEnableOobm() self.configureAndEnableHostHa() self.deployVM() diff --git a/ui/src/config/section/infra/hosts.js b/ui/src/config/section/infra/hosts.js index f81d19b136df..dc189d2e25e7 100644 --- a/ui/src/config/section/infra/hosts.js +++ b/ui/src/config/section/infra/hosts.js @@ -195,6 +195,9 @@ export default { docHelp: 'adminguide/hosts.html#out-of-band-management', dataView: true, show: (record) => { + if (record.hypervisor === 'KVM' && record?.hostha?.haenable === true) { + return false + } return record?.outofbandmanagement?.enabled === true }, args: ['hostid'],