// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

package com.cloud.resource;

import com.cloud.agent.AgentManager;
import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.GetVncPortAnswer;
import com.cloud.agent.api.GetVncPortCommand;
import com.cloud.capacity.dao.CapacityDao;
import com.cloud.dc.ClusterVO;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.HostPodVO;
import com.cloud.dc.dao.ClusterDao;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.HostPodDao;
import com.cloud.event.ActionEventUtils;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.ha.HighAvailabilityManager;
import com.cloud.host.Host;
import com.cloud.host.HostVO;
import com.cloud.host.Status;
import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor;
import com.cloud.storage.ScopeType;
import com.cloud.storage.StorageManager;
import com.cloud.storage.StoragePoolHostVO;
import com.cloud.storage.Volume;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.dao.StoragePoolAndAccessGroupMapDao;
import com.cloud.storage.dao.StoragePoolHostDao;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.utils.Ternary;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.fsm.NoTransitionException;
import com.cloud.utils.ssh.SSHCmdHelper;
import com.cloud.utils.ssh.SshException;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.dao.VMInstanceDetailsDao;
import com.cloud.vm.dao.VMInstanceDao;
import com.trilead.ssh2.Connection;
import org.apache.cloudstack.api.command.admin.host.CancelHostAsDegradedCmd;
import org.apache.cloudstack.api.command.admin.host.DeclareHostAsDegradedCmd;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreInfo;
import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.BDDMockito;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockedConstruction;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
import org.mockito.junit.MockitoJUnitRunner;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.UUID;

import static com.cloud.resource.ResourceState.Event.ErrorsCorrected;
import static com.cloud.resource.ResourceState.Event.InternalEnterMaintenance;
import static com.cloud.resource.ResourceState.Event.UnableToMaintain;
import static com.cloud.resource.ResourceState.Event.UnableToMigrate;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@RunWith(MockitoJUnitRunner.class)
public class ResourceManagerImplTest {

    @Mock
    private CapacityDao capacityDao;
    @Mock
    private StorageManager storageManager;
    @Mock
    private HighAvailabilityManager haManager;
    @Mock
    private VMInstanceDetailsDao vmInstanceDetailsDao;
    @Mock
    private AgentManager agentManager;
    @Mock
    private HostDao hostDao;
    @Mock
    private ClusterDao clusterDao;
    @Mock
    private HostPodDao podDao;
    @Mock
    private DataCenterDao dcDao;
    @Mock
    private VMInstanceDao vmInstanceDao;
    @Mock
    private ConfigurationDao configurationDao;
    @Mock
    private VolumeDao volumeDao;
    @Mock
    private PrimaryDataStoreDao storagePoolDao;
    @Mock
    private StoragePoolHostDao storagePoolHostDao;

    @Spy
    @InjectMocks
    private ResourceManagerImpl resourceManager = new ResourceManagerImpl();

    @Mock
    private HostVO host;
    @Mock
    private VMInstanceVO vm1;
    @Mock
    private VMInstanceVO vm2;

    @Mock
    private GetVncPortAnswer getVncPortAnswerVm1;
    @Mock
    private GetVncPortAnswer getVncPortAnswerVm2;
    @Mock
    private VolumeVO rootDisk1;
    @Mock
    private VolumeVO rootDisk2;
    @Mock
    private VolumeVO dataDisk;

    @Mock
    private Connection sshConnection;

    @Mock
    private StoragePoolAndAccessGroupMapDao storagePoolAccessGroupMapDao;

    private static long hostId = 1L;
    private static final String hostUsername = "user";
    private static final String hostPassword = "password";
    private static final String hostPrivateKey = "privatekey";
    private static final String hostPrivateIp = "192.168.1.10";

    private static long vm1Id = 1L;
    private static String vm1InstanceName = "i-1-VM";
    private static long vm2Id = 2L;
    private static String vm2InstanceName = "i-2-VM";

    private static String vm1VncAddress = "10.2.2.2";
    private static int vm1VncPort = 5900;
    private static String vm2VncAddress = "10.2.2.2";
    private static int vm2VncPort = 5901;

    private static long poolId = 1L;
    private List<VolumeVO> rootDisks;
    private List<VolumeVO> dataDisks;
    private MockedStatic<SSHCmdHelper> sshHelperMocked;
    private MockedStatic<ActionEventUtils> actionEventUtilsMocked;
    private MockedConstruction<GetVncPortCommand> getVncPortCommandMockedConstruction;
    private AutoCloseable closeable;

    private void overrideDefaultConfigValue(final ConfigKey configKey, final String name, final Object o) throws IllegalAccessException, NoSuchFieldException {
        Field f = ConfigKey.class.getDeclaredField(name);
        f.setAccessible(true);
        f.set(configKey, o);
    }

    @Before
    public void setup() throws Exception {
        closeable = MockitoAnnotations.openMocks(this);
        when(host.getType()).thenReturn(Host.Type.Routing);
        when(host.getId()).thenReturn(hostId);
        when(host.getResourceState()).thenReturn(ResourceState.Enabled);
        when(host.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM);
        when(hostDao.findById(hostId)).thenReturn(host);
        when(host.getDetail("username")).thenReturn(hostUsername);
        when(host.getDetail("password")).thenReturn(hostPassword);
        when(configurationDao.getValue("ssh.privatekey")).thenReturn(hostPrivateKey);
        when(host.getStatus()).thenReturn(Status.Up);
        when(host.getPrivateIpAddress()).thenReturn(hostPrivateIp);
        when(vm1.getId()).thenReturn(vm1Id);
        when(vm2.getId()).thenReturn(vm2Id);
        when(vm1.getInstanceName()).thenReturn(vm1InstanceName);
        when(vm2.getInstanceName()).thenReturn(vm2InstanceName);
        when(vmInstanceDao.listByHostId(hostId)).thenReturn(new ArrayList<>());
        when(vmInstanceDao.listVmsMigratingFromHost(hostId)).thenReturn(new ArrayList<>());
        when(vmInstanceDao.listNonMigratingVmsByHostEqualsLastHost(hostId)).thenReturn(new ArrayList<>());
        actionEventUtilsMocked = Mockito.mockStatic(ActionEventUtils.class);
        BDDMockito.given(ActionEventUtils.onCompletedActionEvent(anyLong(), anyLong(), anyString(), anyString(), anyString(), anyLong(), anyString(), anyLong()))
                .willReturn(1L);
        when(getVncPortAnswerVm1.getAddress()).thenReturn(vm1VncAddress);
        when(getVncPortAnswerVm1.getPort()).thenReturn(vm1VncPort);
        when(getVncPortAnswerVm2.getAddress()).thenReturn(vm2VncAddress);
        when(getVncPortAnswerVm2.getPort()).thenReturn(vm2VncPort);
        getVncPortCommandMockedConstruction = Mockito.mockConstruction(GetVncPortCommand.class, (mock,context) -> {
            if (context.arguments().get(0).equals(vm1Id) && context.arguments().get(1) == vm1InstanceName) {
                when(agentManager.easySend(eq(hostId), eq(mock))).thenReturn(getVncPortAnswerVm1);
            } else if (context.arguments().get(0).equals(vm2Id) && context.arguments().get(1) == vm2InstanceName) {
                when(agentManager.easySend(eq(hostId), eq(mock))).thenReturn(getVncPortAnswerVm2);
            }
        });

        sshHelperMocked = Mockito.mockStatic(SSHCmdHelper.class);
        BDDMockito.given(SSHCmdHelper.acquireAuthorizedConnection(eq(hostPrivateIp), eq(22),
                eq(hostUsername), eq(hostPassword), eq(hostPrivateKey))).willReturn(sshConnection);
        BDDMockito.given(SSHCmdHelper.sshExecuteCmdOneShot(eq(sshConnection),
                eq("service cloudstack-agent restart"))).
                willReturn(new SSHCmdHelper.SSHCmdResult(0,"",""));

        overrideDefaultConfigValue(ResourceManager.KvmSshToAgentEnabled, "_defaultValue", "true");

        rootDisks = Arrays.asList(rootDisk1, rootDisk2);
        dataDisks = Collections.singletonList(dataDisk);
        when(volumeDao.findNonDestroyedVolumesByPoolId(poolId)).thenReturn(rootDisks);
        when(volumeDao.findNonDestroyedVolumesByPoolId(poolId, Volume.Type.DATADISK)).thenReturn(dataDisks);
    }

    @After
    public void tearDown() throws Exception {
        sshHelperMocked.close();
        actionEventUtilsMocked.close();
        getVncPortCommandMockedConstruction.close();
        closeable.close();
    }

    @Test(expected = InvalidParameterValueException.class)
    public void testCheckForDuplicateHostThrowsWhenIpAlreadyExists() {
        when(hostDao.findByIp("10.0.0.10")).thenReturn(host);
        resourceManager.checkForDuplicateHost("http://10.0.0.10");
    }

    @Test
    public void testCheckForDuplicateHostAllowsUniqueHost() {
        when(hostDao.findByIp("10.0.0.30")).thenReturn(null);
        resourceManager.checkForDuplicateHost("http://10.0.0.30");
        verify(hostDao, times(1)).findByIp("10.0.0.30");
    }

    @Test
    public void testCheckForDuplicateHostIgnoresNonRoutingHost() {
        when(host.getType()).thenReturn(Host.Type.SecondaryStorage);
        when(hostDao.findByIp("10.0.0.20")).thenReturn(host);
        resourceManager.checkForDuplicateHost("nfs://10.0.0.20/export/secondary");
        verify(hostDao, times(1)).findByIp("10.0.0.20");
    }

    @Test
    public void testCheckAndMaintainEnterMaintenanceModeNoVms() throws NoTransitionException {
        // Test entering into maintenance with no VMs running on host.
        boolean enterMaintenanceMode = resourceManager.checkAndMaintain(hostId);
        verify(resourceManager).attemptMaintain(host);
        verify(resourceManager).setHostIntoMaintenance(host);
        verify(resourceManager, never()).setHostIntoErrorInPrepareForMaintenance(any(), any());
        verify(resourceManager, never()).setHostIntoErrorInMaintenance(any(), any());
        verify(resourceManager, never()).setHostIntoPrepareForMaintenanceAfterErrorsFixed(any());
        verify(resourceManager).resourceStateTransitTo(eq(host), eq(InternalEnterMaintenance), anyLong());

        Assert.assertTrue(enterMaintenanceMode);
    }

    @Test
    public void testCheckAndMaintainProceedsWithPrepareForMaintenanceRunningVms() throws NoTransitionException {
        // Test proceeding through with no events if pending migrating works / retries left.
        setupRunningVMs();
        setupPendingMigrationRetries();
        verifyNoChangeInMaintenance();
    }

    @Test
    public void testCheckAndMaintainErrorInMaintenanceRunningVms() throws NoTransitionException {
        // Test entering into ErrorInMaintenance when no pending migrations etc, and due to - Running VMs
        setupRunningVMs();
        setupNoPendingMigrationRetries();
        verifyErrorInMaintenanceCalls();
    }

    @Test
    public void testCheckAndMaintainErrorInMaintenanceWithErrorVms() throws NoTransitionException {
        // Test entering into ErrorInMaintenance when no pending migrations etc, and due to - no migrating but error VMs
        setupErrorVms();
        setupNoPendingMigrationRetries();
        verifyErrorInMaintenanceCalls();
    }

    @Test
    public void testCheckAndMaintainErrorInPrepareForMaintenanceFailedMigrationsPendingRetries() throws NoTransitionException {
        // Test entering into ErrorInPrepareForMaintenance when pending migrations retries and due to - Failed Migrations
        setupFailedMigrations();
        setupPendingMigrationRetries();
        when(vmInstanceDao.findByHostInStates(hostId, VirtualMachine.State.Running)).thenReturn(Arrays.asList(vm2));
        verifyErrorInPrepareForMaintenanceCalls();
    }

    @Test
    public void testCheckAndMaintainErrorInPrepareForMaintenanceWithErrorVmsPendingRetries() throws NoTransitionException {
        // Test entering into ErrorInMaintenance when pending migrations retries due to - no migrating but error VMs
        setupErrorVms();
        setupPendingMigrationRetries();
        when(vmInstanceDao.listVmsMigratingFromHost(hostId)).thenReturn(Arrays.asList(vm2));
        verifyErrorInPrepareForMaintenanceCalls();
    }

    @Test
    public void testCheckAndMaintainErrorInPrepareForMaintenanceFailedMigrationsAndMigratingVms() throws NoTransitionException {
        // Test entering into ErrorInPrepareForMaintenance when no pending migrations retries
        // but executing migration and due to - Failed Migrations
        setupFailedMigrations();
        setupNoPendingMigrationRetries();
        when(vmInstanceDao.listVmsMigratingFromHost(hostId)).thenReturn(Arrays.asList(vm2));
        verifyErrorInPrepareForMaintenanceCalls();
    }

    @Test
    public void testCheckAndMaintainErrorInPrepareForMaintenanceWithErrorVmsAndMigratingVms() throws NoTransitionException {
        // Test entering into ErrorInPrepareForMaintenance when no pending migrations retries
        // but executing migration and due to - Error Vms
        setupErrorVms();
        setupNoPendingMigrationRetries();
        when(vmInstanceDao.listVmsMigratingFromHost(hostId)).thenReturn(Arrays.asList(vm2));
        verifyErrorInPrepareForMaintenanceCalls();
    }

    @Test
    public void testCheckAndMaintainErrorInPrepareForMaintenanceFailedMigrationsAndStoppingVms() throws NoTransitionException {
        // Test entering into ErrorInPrepareForMaintenance when no pending migrations retries
        // but stopping VMs and due to - Failed Migrations
        setupFailedMigrations();
        setupNoPendingMigrationRetries();
        when(vmInstanceDao.findByHostInStates(hostId, VirtualMachine.State.Stopping)).thenReturn(Arrays.asList(vm2));
        verifyErrorInPrepareForMaintenanceCalls();
    }

    @Test
    public void testCheckAndMaintainReturnsToPrepareForMaintenanceRunningVms() throws NoTransitionException {
        // Test switching back to PrepareForMaintenance
        when(host.getResourceState()).thenReturn(ResourceState.ErrorInPrepareForMaintenance);
        setupRunningVMs();
        setupPendingMigrationRetries();
        verifyReturnToPrepareForMaintenanceCalls();
    }

    @Test
    public void testConfigureVncAccessForKVMHostFailedMigrations() {
        when(host.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM);
        List<VMInstanceVO> vms = Arrays.asList(vm1, vm2);
        resourceManager.configureVncAccessForKVMHostFailedMigrations(host, vms);
        verify(agentManager).pullAgentOutMaintenance(hostId);
        verify(resourceManager).setKVMVncAccess(hostId, vms);
        verify(agentManager, times(vms.size())).easySend(eq(hostId), any(GetVncPortCommand.class));
        verify(agentManager).pullAgentToMaintenance(hostId);
        verify(vmInstanceDetailsDao).addDetail(eq(vm1Id), eq("kvm.vnc.address"), eq(vm1VncAddress), anyBoolean());
        verify(vmInstanceDetailsDao).addDetail(eq(vm1Id), eq("kvm.vnc.port"), eq(String.valueOf(vm1VncPort)), anyBoolean());
        verify(vmInstanceDetailsDao).addDetail(eq(vm2Id), eq("kvm.vnc.address"), eq(vm2VncAddress), anyBoolean());
        verify(vmInstanceDetailsDao).addDetail(eq(vm2Id), eq("kvm.vnc.port"), eq(String.valueOf(vm2VncPort)), anyBoolean());
    }

    @Test(expected = CloudRuntimeException.class)
    public void testGetHostCredentialsMissingParameter() {
        when(host.getDetail("password")).thenReturn(null);
        when(configurationDao.getValue("ssh.privatekey")).thenReturn(null);
        resourceManager.getHostCredentials(host);
    }

    private HostVO mockExistingRoutingHost(long dcId, Long podId, Long clusterId) {
        HostVO existing = Mockito.mock(HostVO.class);
        when(existing.getType()).thenReturn(Host.Type.Routing);
        when(existing.getDataCenterId()).thenReturn(dcId);
        when(existing.getPodId()).thenReturn(podId);
        when(existing.getClusterId()).thenReturn(clusterId);
        when(existing.getUuid()).thenReturn("host-uuid");
        return existing;
    }

    @Test(expected = InvalidParameterValueException.class)
    public void testValidateExistingHostLocationImmutableRejectsZoneChange() {
        HostVO existing = mockExistingRoutingHost(1L, 10L, 100L);
        StartupCommand startup = Mockito.mock(StartupCommand.class);
        when(startup.getPrivateIpAddress()).thenReturn("10.10.10.10");
        resourceManager.validateExistingHostLocationImmutable(existing, false, 2L, 10L, 100L, startup);
    }

    @Test(expected = InvalidParameterValueException.class)
    public void testValidateExistingHostLocationImmutableRejectsPodChange() {
        HostVO existing = mockExistingRoutingHost(1L, 10L, 100L);
        StartupCommand startup = Mockito.mock(StartupCommand.class);
        when(startup.getPrivateIpAddress()).thenReturn("10.10.10.10");
        resourceManager.validateExistingHostLocationImmutable(existing, false, 1L, 11L, 100L, startup);
    }

    @Test(expected = InvalidParameterValueException.class)
    public void testValidateExistingHostLocationImmutableRejectsClusterChange() {
        HostVO existing = mockExistingRoutingHost(1L, 10L, 100L);
        StartupCommand startup = Mockito.mock(StartupCommand.class);
        when(startup.getPrivateIpAddress()).thenReturn("10.10.10.10");
        resourceManager.validateExistingHostLocationImmutable(existing, false, 1L, 10L, 101L, startup);
    }

    @Test
    public void testValidateExistingHostLocationImmutableAllowsSameTupleReconnect() {
        HostVO existing = mockExistingRoutingHost(1L, 10L, 100L);
        resourceManager.validateExistingHostLocationImmutable(existing, false, 1L, 10L, 100L, null);
    }

    @Test
    public void testValidateExistingHostLocationImmutableAllowsNewHost() {
        HostVO existing = mockExistingRoutingHost(2L, 20L, 200L);
        resourceManager.validateExistingHostLocationImmutable(existing, true, 1L, 10L, 100L, null);
    }

    @Test
    public void testValidateExistingHostLocationImmutableSkipsNonRoutingHost() {
        HostVO existing = Mockito.mock(HostVO.class);
        when(existing.getType()).thenReturn(Host.Type.SecondaryStorageVM);
        resourceManager.validateExistingHostLocationImmutable(existing, false, 1L, 10L, 100L, null);
    }

    @Test
    public void testValidateExistingHostLocationImmutableSkipsPartialLocationRow() {
        HostVO existing = Mockito.mock(HostVO.class);
        when(existing.getType()).thenReturn(Host.Type.Routing);
        when(existing.getDataCenterId()).thenReturn(1L);
        when(existing.getPodId()).thenReturn(null);
        when(existing.getClusterId()).thenReturn(null);
        resourceManager.validateExistingHostLocationImmutable(existing, false, 2L, 10L, 100L, null);
    }

    @Test
    public void testValidateExistingHostLocationImmutableSkipsNullExistingHost() {
        resourceManager.validateExistingHostLocationImmutable(null, false, 2L, 10L, 100L, null);
    }

    @Test
    public void testGetHostCredentials() {
        Ternary<String, String, String> credentials = resourceManager.getHostCredentials(host);
        Assert.assertNotNull(credentials);
        Assert.assertEquals(hostUsername, credentials.first());
        Assert.assertEquals(hostPassword, credentials.second());
        Assert.assertEquals(hostPrivateKey, credentials.third());
    }

    @Test(expected = CloudRuntimeException.class)
    public void testConnectAndRestartAgentOnHostCannotConnect() {
        BDDMockito.given(SSHCmdHelper.acquireAuthorizedConnection(eq(hostPrivateIp), eq(22),
                eq(hostUsername), eq(hostPassword), eq(hostPrivateKey))).willReturn(null);
        resourceManager.connectAndRestartAgentOnHost(host, hostUsername, hostPassword, hostPrivateKey);
    }

    @Test(expected = CloudRuntimeException.class)
    public void testConnectAndRestartAgentOnHostCannotRestart() throws Exception {
        BDDMockito.given(SSHCmdHelper.sshExecuteCmdOneShot(eq(sshConnection),
                eq("service cloudstack-agent restart"))).willThrow(new SshException("exception"));
        resourceManager.connectAndRestartAgentOnHost(host, hostUsername, hostPassword, hostPrivateKey);
    }

    @Test
    public void testConnectAndRestartAgentOnHost() {
        when(agentManager.getHostSshPort(any())).thenReturn(22);
        resourceManager.connectAndRestartAgentOnHost(host, hostUsername, hostPassword, hostPrivateKey);
    }

    @Test
    public void testHandleAgentSSHEnabledNotConnectedAgent() {
        when(host.getStatus()).thenReturn(Status.Disconnected);
        when(agentManager.getHostSshPort(any())).thenReturn(22);
        resourceManager.handleAgentIfNotConnected(host, false);
        verify(resourceManager).getHostCredentials(eq(host));
        verify(resourceManager).connectAndRestartAgentOnHost(eq(host), eq(hostUsername), eq(hostPassword), eq(hostPrivateKey));
    }

    @Test
    public void testHandleAgentSSHEnabledConnectedAgent() {
        when(host.getStatus()).thenReturn(Status.Up);
        resourceManager.handleAgentIfNotConnected(host, false);
        verify(resourceManager, never()).getHostCredentials(eq(host));
        verify(resourceManager, never()).connectAndRestartAgentOnHost(eq(host), eq(hostUsername), eq(hostPassword), eq(hostPrivateKey));
    }

    @Test(expected = CloudRuntimeException.class)
    public void testHandleAgentSSHDisabledNotConnectedAgent() throws NoSuchFieldException, IllegalAccessException {
        when(host.getStatus()).thenReturn(Status.Disconnected);
        overrideDefaultConfigValue(ResourceManager.KvmSshToAgentEnabled, "_defaultValue", "false");
        resourceManager.handleAgentIfNotConnected(host, false);
    }

    @Test
    public void testHandleAgentSSHDisabledConnectedAgent() {
        when(host.getStatus()).thenReturn(Status.Up);
        resourceManager.handleAgentIfNotConnected(host, false);
        verify(resourceManager, never()).getHostCredentials(eq(host));
        verify(resourceManager, never()).connectAndRestartAgentOnHost(eq(host), eq(hostUsername), eq(hostPassword), eq(hostPrivateKey));
    }

    @Test
    public void testHandleAgentVMsMigrating() {
        resourceManager.handleAgentIfNotConnected(host, true);
        verify(resourceManager, never()).getHostCredentials(eq(host));
        verify(resourceManager, never()).connectAndRestartAgentOnHost(eq(host), eq(hostUsername), eq(hostPassword), eq(hostPrivateKey));
    }

    private void setupNoPendingMigrationRetries() {
        when(haManager.hasPendingMigrationsWork(vm1.getId())).thenReturn(false);
        when(haManager.hasPendingMigrationsWork(vm2.getId())).thenReturn(false);
    }

    private void setupRunningVMs() {
        when(vmInstanceDao.listByHostId(hostId)).thenReturn(Arrays.asList(vm1, vm2));
        when(vmInstanceDao.findByHostInStates(hostId, VirtualMachine.State.Migrating, VirtualMachine.State.Running, VirtualMachine.State.Starting, VirtualMachine.State.Stopping, VirtualMachine.State.Error, VirtualMachine.State.Unknown)).thenReturn(Arrays.asList(vm1, vm2));
        when(vmInstanceDao.findByHostInStates(hostId, VirtualMachine.State.Running)).thenReturn(Arrays.asList(vm1, vm2));
    }

    private void setupPendingMigrationRetries() {
        when(haManager.hasPendingMigrationsWork(vm1.getId())).thenReturn(true);
    }

    private void setupFailedMigrations() {
        when(vmInstanceDao.listByHostId(hostId)).thenReturn(Arrays.asList(vm1, vm2));
        when(vmInstanceDao.findByHostInStates(hostId, VirtualMachine.State.Migrating, VirtualMachine.State.Running, VirtualMachine.State.Starting, VirtualMachine.State.Stopping, VirtualMachine.State.Error, VirtualMachine.State.Unknown)).thenReturn(Arrays.asList(vm1, vm2));
        when(vmInstanceDao.listNonMigratingVmsByHostEqualsLastHost(hostId)).thenReturn(Arrays.asList(vm1));
    }

    private void setupErrorVms() {
        when(vmInstanceDao.listByHostId(hostId)).thenReturn(Arrays.asList(vm1, vm2));
        when(vmInstanceDao.findByHostInStates(hostId, VirtualMachine.State.Migrating, VirtualMachine.State.Running, VirtualMachine.State.Starting, VirtualMachine.State.Stopping, VirtualMachine.State.Error, VirtualMachine.State.Unknown)).thenReturn(Arrays.asList(vm1, vm2));
        when(vmInstanceDao.findByHostInStates(hostId, VirtualMachine.State.Unknown, VirtualMachine.State.Error)).thenReturn(Arrays.asList(vm1));
    }

    private void verifyErrorInMaintenanceCalls() throws NoTransitionException {
        boolean enterMaintenanceMode = resourceManager.checkAndMaintain(hostId);
        verify(resourceManager).attemptMaintain(host);
        verify(resourceManager).setHostIntoErrorInMaintenance(eq(host), any());
        verify(resourceManager, never()).setHostIntoMaintenance(any());
        verify(resourceManager, never()).setHostIntoErrorInPrepareForMaintenance(any(), any());
        verify(resourceManager, never()).setHostIntoPrepareForMaintenanceAfterErrorsFixed(any());
        verify(resourceManager).resourceStateTransitTo(eq(host), eq(UnableToMaintain), anyLong());
        Assert.assertFalse(enterMaintenanceMode);
    }

    private void verifyErrorInPrepareForMaintenanceCalls() throws NoTransitionException {
        boolean enterMaintenanceMode = resourceManager.checkAndMaintain(hostId);
        verify(resourceManager).attemptMaintain(host);
        verify(resourceManager).setHostIntoErrorInPrepareForMaintenance(eq(host), any());
        verify(resourceManager, never()).setHostIntoMaintenance(any());
        verify(resourceManager, never()).setHostIntoErrorInMaintenance(any(), any());
        verify(resourceManager, never()).setHostIntoPrepareForMaintenanceAfterErrorsFixed(any());
        verify(resourceManager).resourceStateTransitTo(eq(host), eq(UnableToMigrate), anyLong());
        Assert.assertFalse(enterMaintenanceMode);
    }

    private void verifyReturnToPrepareForMaintenanceCalls() throws NoTransitionException {
        boolean enterMaintenanceMode = resourceManager.checkAndMaintain(hostId);
        verify(resourceManager).attemptMaintain(host);
        verify(resourceManager).setHostIntoPrepareForMaintenanceAfterErrorsFixed(eq(host));
        verify(resourceManager).resourceStateTransitTo(eq(host), eq(ErrorsCorrected), anyLong());
        verify(resourceManager, never()).setHostIntoMaintenance(any());
        verify(resourceManager, never()).setHostIntoErrorInPrepareForMaintenance(any(), any());
        verify(resourceManager, never()).setHostIntoErrorInMaintenance(any(), any());
        Assert.assertFalse(enterMaintenanceMode);
    }

    private void verifyNoChangeInMaintenance() throws NoTransitionException {
        boolean enterMaintenanceMode = resourceManager.checkAndMaintain(hostId);
        verify(resourceManager).attemptMaintain(host);
        verify(resourceManager, never()).setHostIntoMaintenance(any());
        verify(resourceManager, never()).setHostIntoErrorInPrepareForMaintenance(any(), any());
        verify(resourceManager, never()).setHostIntoErrorInMaintenance(any(), any());
        verify(resourceManager, never()).setHostIntoPrepareForMaintenanceAfterErrorsFixed(any());
        verify(resourceManager, never()).resourceStateTransitTo(any(), any(), anyLong());
        Assert.assertFalse(enterMaintenanceMode);
    }

    @Test
    public void declareHostAsDegradedTestDisconnected() throws NoTransitionException {
        prepareAndTestDeclareHostAsDegraded(Status.Disconnected, ResourceState.Enabled, ResourceState.Degraded);
    }

    @Test
    public void declareHostAsDegradedTestAlert() throws NoTransitionException {
        prepareAndTestDeclareHostAsDegraded(Status.Alert, ResourceState.Enabled, ResourceState.Degraded);
    }

    @Test(expected = InvalidParameterValueException.class)
    public void declareHostAsDegradedExpectNoTransitionException() throws NoTransitionException {
        Status[] statusArray = Status.values();
        for (int i = 0; i < statusArray.length - 1; i++) {
            if (statusArray[i] != Status.Alert && statusArray[i] != Status.Disconnected) {
                prepareAndTestDeclareHostAsDegraded(statusArray[i], ResourceState.Enabled, ResourceState.Enabled);
            }
        }
    }

    @Test(expected = NoTransitionException.class)
    public void declareHostAsDegradedTestAlreadyDegraded() throws NoTransitionException {
        prepareAndTestDeclareHostAsDegraded(Status.Alert, ResourceState.Degraded, ResourceState.Degraded);
    }

    @Test(expected = NoTransitionException.class)
    public void declareHostAsDegradedTestOnError() throws NoTransitionException {
        prepareAndTestDeclareHostAsDegraded(Status.Alert, ResourceState.Error, ResourceState.Degraded);
    }

    @Test(expected = NoTransitionException.class)
    public void declareHostAsDegradedTestOnCreating() throws NoTransitionException {
        prepareAndTestDeclareHostAsDegraded(Status.Alert, ResourceState.Creating, ResourceState.Degraded);
    }

    @Test(expected = NoTransitionException.class)
    public void declareHostAsDegradedTestOnErrorInMaintenance() throws NoTransitionException {
        prepareAndTestDeclareHostAsDegraded(Status.Alert, ResourceState.ErrorInPrepareForMaintenance, ResourceState.Degraded);
    }

    @Test
    public void declareHostAsDegradedTestSupportedStates() throws NoTransitionException {
        ResourceState[] states = ResourceState.values();
        for (int i = 0; i < states.length - 1; i++) {
            if (states[i] == ResourceState.Enabled
                    || states[i] == ResourceState.Maintenance
                    || states[i] == ResourceState.Disabled) {
                prepareAndTestDeclareHostAsDegraded(Status.Alert, states[i], ResourceState.Degraded);
            }
        }
    }

    private void prepareAndTestDeclareHostAsDegraded(Status hostStatus, ResourceState originalState, ResourceState expectedResourceState) throws NoTransitionException {
        DeclareHostAsDegradedCmd declareHostAsDegradedCmd = Mockito.spy(new DeclareHostAsDegradedCmd());
        HostVO hostVo = createDummyHost(hostStatus);
        hostVo.setResourceState(originalState);
        when(declareHostAsDegradedCmd.getId()).thenReturn(0l);
        when(hostDao.findById(0l)).thenReturn(hostVo);

        Host result = resourceManager.declareHostAsDegraded(declareHostAsDegradedCmd);

        Assert.assertEquals(expectedResourceState, hostVo.getResourceState());
    }

    @Test
    public void cancelHostAsDegradedTest() throws NoTransitionException {
        prepareAndTestCancelHostAsDegraded(Status.Alert, ResourceState.Degraded, ResourceState.Enabled);
    }

    @Test(expected = NoTransitionException.class)
    public void cancelHostAsDegradedTestHostNotDegraded() throws NoTransitionException {
        prepareAndTestCancelHostAsDegraded(Status.Alert, ResourceState.Enabled, ResourceState.Enabled);
    }

    private void prepareAndTestCancelHostAsDegraded(Status hostStatus, ResourceState originalState, ResourceState expectedResourceState) throws NoTransitionException {
        CancelHostAsDegradedCmd cancelHostAsDegradedCmd = Mockito.spy(new CancelHostAsDegradedCmd());
        HostVO hostVo = createDummyHost(hostStatus);
        hostVo.setResourceState(originalState);
        when(cancelHostAsDegradedCmd.getId()).thenReturn(0l);
        when(hostDao.findById(0l)).thenReturn(hostVo);

        Host result = resourceManager.cancelHostAsDegraded(cancelHostAsDegradedCmd);

        Assert.assertEquals(expectedResourceState, hostVo.getResourceState());
    }

    private HostVO createDummyHost(Status hostStatus) {
        return new HostVO(1L, "host01", Host.Type.Routing, "192.168.1.1", "255.255.255.0", null, null, null, null, null, null, null, null, null, null, UUID.randomUUID().toString(),
                hostStatus, "1.0", null, null, 1L, null, 0, 0, null, 0, null);
    }

    @Test
    public void testDestroyLocalStoragePoolVolumesBothRootDisksAndDataDisks() {
        resourceManager.destroyLocalStoragePoolVolumes(poolId);
        verify(volumeDao, times(rootDisks.size() + dataDisks.size()))
                .updateAndRemoveVolume(any(VolumeVO.class));
    }

    @Test
    public void testDestroyLocalStoragePoolVolumesOnlyRootDisks() {
        when(volumeDao.findNonDestroyedVolumesByPoolId(poolId, Volume.Type.DATADISK)).thenReturn(null);
        resourceManager.destroyLocalStoragePoolVolumes(poolId);
        verify(volumeDao, times(rootDisks.size())).updateAndRemoveVolume(any(VolumeVO.class));
    }

    @Test
    public void testDestroyLocalStoragePoolVolumesOnlyDataDisks() {
        when(volumeDao.findNonDestroyedVolumesByPoolId(poolId)).thenReturn(null);
        resourceManager.destroyLocalStoragePoolVolumes(poolId);
        verify(volumeDao, times(dataDisks.size())).updateAndRemoveVolume(any(VolumeVO.class));
    }

    @Test
    public void testDestroyLocalStoragePoolVolumesNoDisks() {
        when(volumeDao.findNonDestroyedVolumesByPoolId(poolId)).thenReturn(null);
        when(volumeDao.findNonDestroyedVolumesByPoolId(poolId, Volume.Type.DATADISK)).thenReturn(null);
        resourceManager.destroyLocalStoragePoolVolumes(poolId);
        verify(volumeDao, never()).updateAndRemoveVolume(any(VolumeVO.class));
    }

    @Test
    public void testEmptyHostList() {
        List<HostVO> allHosts = new ArrayList<>();
        List<String> storageAccessGroups = Arrays.asList("group1", "group2");

        List<HostVO> hostsToConnect = resourceManager.filterHostsBasedOnStorageAccessGroups(allHosts, storageAccessGroups);

        Assert.assertTrue("No hosts should be returned when the host list is empty.", hostsToConnect.isEmpty());
    }

    @Test
    public void testEmptyStorageAccessGroups() {
        List<HostVO> allHosts = Arrays.asList(Mockito.mock(HostVO.class), Mockito.mock(HostVO.class));
        List<String> storageAccessGroups = new ArrayList<>();

        for (HostVO host : allHosts) {
            Mockito.when(host.getId()).thenReturn(1L);
            Mockito.doReturn(new String[]{"group1", "group2"})
                    .when(storageManager).getStorageAccessGroups(null, null, null, 1L);
        }

        List<HostVO> hostsToConnect = resourceManager.filterHostsBasedOnStorageAccessGroups(allHosts, storageAccessGroups);

        Assert.assertTrue("All hosts should be returned when storage access groups are empty.", hostsToConnect.containsAll(allHosts));
        Assert.assertEquals("The number of returned hosts should match the total number of hosts.", allHosts.size(), hostsToConnect.size());
    }

    @Test
    public void testHostWithMatchingStorageAccessGroups() {
        HostVO host1 = Mockito.mock(HostVO.class);
        HostVO host2 = Mockito.mock(HostVO.class);
        List<HostVO> allHosts = Arrays.asList(host1, host2);
        List<String> storageAccessGroups = Arrays.asList("group1", "group2");

        Mockito.when(host1.getId()).thenReturn(1L);
        Mockito.doReturn(new String[]{"group1"})
                .when(storageManager).getStorageAccessGroups(null, null, null, 1L);

        Mockito.when(host2.getId()).thenReturn(2L);
        Mockito.doReturn(new String[]{"group3"})
                .when(storageManager).getStorageAccessGroups(null, null, null, 2L);

        List<HostVO> hostsToConnect = resourceManager.filterHostsBasedOnStorageAccessGroups(allHosts, storageAccessGroups);

        Assert.assertTrue("Only hosts with matching storage access groups should be included.", hostsToConnect.contains(host1));
        Assert.assertFalse("Hosts without matching storage access groups should not be included.", hostsToConnect.contains(host2));
        Assert.assertEquals("Only one host should match the storage access groups.", 1, hostsToConnect.size());
    }

    @Test
    public void testHostWithoutMatchingStorageAccessGroups() {
        HostVO host1 = Mockito.mock(HostVO.class);
        HostVO host2 = Mockito.mock(HostVO.class);
        List<HostVO> allHosts = Arrays.asList(host1, host2);
        List<String> storageAccessGroups = Arrays.asList("group1", "group2");

        Mockito.when(host1.getId()).thenReturn(1L);
        Mockito.doReturn(new String[]{"group3"})
                .when(storageManager).getStorageAccessGroups(null, null, null, 1L);

        Mockito.when(host2.getId()).thenReturn(2L);
        Mockito.doReturn(new String[]{"group4"})
                .when(storageManager).getStorageAccessGroups(null, null, null, 2L);

        List<HostVO> hostsToConnect = resourceManager.filterHostsBasedOnStorageAccessGroups(allHosts, storageAccessGroups);

        Assert.assertTrue("No hosts should match the storage access groups.", hostsToConnect.isEmpty());
    }

    @Test
    public void testMixedMatchingAndNonMatchingHosts() {
        HostVO host1 = Mockito.mock(HostVO.class);
        HostVO host2 = Mockito.mock(HostVO.class);
        HostVO host3 = Mockito.mock(HostVO.class);
        List<HostVO> allHosts = Arrays.asList(host1, host2, host3);
        List<String> storageAccessGroups = Arrays.asList("group1", "group2");

        Mockito.when(host1.getId()).thenReturn(1L);
        Mockito.doReturn(new String[]{"group1"})
                .when(storageManager).getStorageAccessGroups(null, null, null, 1L);

        Mockito.when(host2.getId()).thenReturn(2L);
        Mockito.doReturn(new String[]{"group3"})
                .when(storageManager).getStorageAccessGroups(null, null, null, 2L);

        Mockito.when(host3.getId()).thenReturn(3L);
        Mockito.doReturn(new String[]{"group2"})
                .when(storageManager).getStorageAccessGroups(null, null, null, 3L);

        List<HostVO> hostsToConnect = resourceManager.filterHostsBasedOnStorageAccessGroups(allHosts, storageAccessGroups);

        Assert.assertTrue("Host1 should be included as it matches 'group1'.", hostsToConnect.contains(host1));
        Assert.assertFalse("Host2 should not be included as it doesn't match any group.", hostsToConnect.contains(host2));
        Assert.assertTrue("Host3 should be included as it matches 'group2'.", hostsToConnect.contains(host3));
    }

    @Test
    public void testHostsWithEmptyStorageAccessGroups() {
        HostVO host1 = Mockito.mock(HostVO.class);
        HostVO host2 = Mockito.mock(HostVO.class);
        List<HostVO> allHosts = Arrays.asList(host1, host2);
        List<String> storageAccessGroups = Arrays.asList("group1", "group2");

        Mockito.when(host1.getId()).thenReturn(1L);
        Mockito.doReturn(new String[0])
                .when(storageManager).getStorageAccessGroups(null, null, null, 1L);

        Mockito.when(host2.getId()).thenReturn(2L);
        Mockito.doReturn(new String[0])
                .when(storageManager).getStorageAccessGroups(null, null, null, 2L);

        List<HostVO> hostsToConnect = resourceManager.filterHostsBasedOnStorageAccessGroups(allHosts, storageAccessGroups);

        Assert.assertTrue("No hosts should be included if storage access groups are empty.", hostsToConnect.isEmpty());
    }

    @Test
    public void testZoneLevelWithAllHostsUsingTags() {
        List<String> sagsToDelete = Arrays.asList("tag1", "tag2");
        Long clusterId = null;
        Long podId = null;
        Long zoneId = 3L;

        List<Long> hostIdsUsingStorageTags = Arrays.asList(1L, 2L);
        Mockito.doReturn(hostIdsUsingStorageTags).when(resourceManager).listOfHostIdsUsingTheStorageAccessGroups(sagsToDelete, clusterId, podId, zoneId);

        List<HostVO> hostsInZone = Arrays.asList(Mockito.mock(HostVO.class), Mockito.mock(HostVO.class));
        Mockito.doReturn(hostsInZone).when(hostDao).findByDataCenterId(zoneId);

        Mockito.doReturn(1L).when(hostsInZone.get(0)).getId();
        Mockito.doReturn(2L).when(hostsInZone.get(1)).getId();

        try {
            resourceManager.checkIfAllHostsInUse(sagsToDelete, clusterId, podId, zoneId);
            Assert.fail("Exception should be thrown when all hosts in the zone are using the storage access groups.");
        } catch (CloudRuntimeException e) {
            Assert.assertEquals("All hosts in the zone are using the storage access groups", e.getMessage());
        }
    }

    @Test
    public void testClusterLevelWithAllHostsUsingTags() {
        List<String> sagsToDelete = Arrays.asList("tag1", "tag2");
        Long clusterId = 1L;
        Long podId = null;
        Long zoneId = null;

        List<Long> hostIdsUsingStorageTags = Arrays.asList(1L, 2L);
        Mockito.doReturn(hostIdsUsingStorageTags).when(resourceManager).listOfHostIdsUsingTheStorageAccessGroups(sagsToDelete, clusterId, podId, zoneId);

        List<HostVO> hostsInCluster = Arrays.asList(Mockito.mock(HostVO.class), Mockito.mock(HostVO.class));
        Mockito.doReturn(hostsInCluster).when(hostDao).findByClusterId(clusterId, Host.Type.Routing);

        Mockito.doReturn(1L).when(hostsInCluster.get(0)).getId();
        Mockito.doReturn(2L).when(hostsInCluster.get(1)).getId();

        try {
            resourceManager.checkIfAllHostsInUse(sagsToDelete, clusterId, podId, zoneId);
            Assert.fail("Exception should be thrown when all hosts in the cluster are using the storage access groups.");
        } catch (CloudRuntimeException e) {
            Assert.assertEquals("All hosts in the cluster are using the storage access groups", e.getMessage());
        }
    }

    @Test
    public void testPodLevelWithAllHostsUsingTags() {
        List<String> sagsToDelete = Arrays.asList("tag1", "tag2");
        Long clusterId = null;
        Long podId = 2L;
        Long zoneId = null;

        List<Long> hostIdsUsingStorageTags = Arrays.asList(1L, 2L);
        Mockito.doReturn(hostIdsUsingStorageTags).when(resourceManager).listOfHostIdsUsingTheStorageAccessGroups(sagsToDelete, clusterId, podId, zoneId);

        List<HostVO> hostsInPod = Arrays.asList(Mockito.mock(HostVO.class), Mockito.mock(HostVO.class));
        Mockito.doReturn(hostsInPod).when(hostDao).findByPodId(podId, Host.Type.Routing);

        Mockito.doReturn(1L).when(hostsInPod.get(0)).getId();
        Mockito.doReturn(2L).when(hostsInPod.get(1)).getId();

        try {
            resourceManager.checkIfAllHostsInUse(sagsToDelete, clusterId, podId, zoneId);
            Assert.fail("Exception should be thrown when all hosts in the pod are using the storage access groups.");
        } catch (CloudRuntimeException e) {
            Assert.assertEquals("All hosts in the pod are using the storage access groups", e.getMessage());
        }
    }

    @Test
    public void testCheckIfAnyVolumesInUseWithPoolsToAdd() {
        List<String> sagsToAdd = Arrays.asList("sag1", "sag2");
        List<String> sagsToDelete = Arrays.asList("sag3", "sag4");

        HostVO host = Mockito.mock(HostVO.class);
        Mockito.when(host.getId()).thenReturn(1L);
        Mockito.when(host.getDataCenterId()).thenReturn(2L);
        Mockito.when(host.getPodId()).thenReturn(3L);
        Mockito.when(host.getClusterId()).thenReturn(4L);

        VolumeVO volume1 = Mockito.mock(VolumeVO.class);
        VolumeVO volume2 = Mockito.mock(VolumeVO.class);
        Mockito.when(volume1.getPoolId()).thenReturn(10L);
        Mockito.when(volume2.getPoolId()).thenReturn(11L);
        List<VolumeVO> volumesUsingTheStoragePoolAccessGroups = new ArrayList<>(Arrays.asList(volume1, volume2));
        Mockito.doReturn(volumesUsingTheStoragePoolAccessGroups).when(resourceManager).listOfVolumesUsingTheStorageAccessGroups(sagsToDelete, 1L, null, null, null);

        StoragePoolVO pool1 = Mockito.mock(StoragePoolVO.class);
        StoragePoolVO pool2 = Mockito.mock(StoragePoolVO.class);
        Mockito.when(pool1.getId()).thenReturn(10L);
        Mockito.when(pool2.getId()).thenReturn(12L);
        List<StoragePoolVO> poolsToAdd = Arrays.asList(pool1, pool2);

        Mockito.doReturn(poolsToAdd)
                .when(resourceManager).getStoragePoolsByAccessGroups(2L, 3L, 4L, sagsToAdd.toArray(new String[0]), true);

        try {
            resourceManager.checkIfAnyVolumesInUse(sagsToAdd, sagsToDelete, host);
            Assert.fail("Expected a CloudRuntimeException to be thrown.");
        } catch (CloudRuntimeException e) {
            Assert.assertTrue("Exception message should mention volumes in use.",
                    e.getMessage().contains("There are volumes in storage pools with the Storage Access Groups that need to be deleted"));
        }
    }

    @Test
    public void testUpdateStoragePoolConnectionsOnHostsConnect1AndDisconnect2() {
        Long poolId = 1L;
        List<String> storageAccessGroups = Arrays.asList("sag1", "sag2");

        StoragePoolVO storagePool = Mockito.mock(StoragePoolVO.class);
        Mockito.when(storagePool.getId()).thenReturn(poolId);
        Mockito.when(storagePool.getScope()).thenReturn(ScopeType.CLUSTER);
        Mockito.when(storagePool.getClusterId()).thenReturn(1L);
        Mockito.when(storagePool.getPodId()).thenReturn(1L);
        Mockito.when(storagePool.getDataCenterId()).thenReturn(1L);

        Mockito.when(storagePoolDao.findById(poolId)).thenReturn(storagePool);

        HostVO host1 = Mockito.mock(HostVO.class);
        HostVO host2 = Mockito.mock(HostVO.class);
        Mockito.when(host1.getId()).thenReturn(2L);
        Mockito.when(host2.getId()).thenReturn(3L);

        List<HostVO> clusterHosts = Arrays.asList(host1, host2);
        Mockito.doReturn(clusterHosts).when(resourceManager).listAllUpHosts(Host.Type.Routing, 1L, 1L, 1L);

        StoragePoolHostVO hostPoolRecord = Mockito.mock(StoragePoolHostVO.class);
        Mockito.when(storagePoolHostDao.findByPoolHost(poolId, 2L)).thenReturn(null);
        Mockito.when(storagePoolHostDao.findByPoolHost(poolId, 3L)).thenReturn(hostPoolRecord);

        Mockito.doReturn(new String[]{"sag1", "sag2"}).when(storageManager).getStorageAccessGroups(null, null, null, 2L);
        Mockito.doReturn(new String[]{"sag3"}).when(storageManager).getStorageAccessGroups(null, null, null, 3L);

        Mockito.doReturn(new ArrayList<Long>()).when(resourceManager).listOfHostIdsUsingTheStoragePool(poolId);

        try {
            resourceManager.updateStoragePoolConnectionsOnHosts(poolId, storageAccessGroups);

            Mockito.verify(resourceManager, Mockito.times(1)).connectHostToStoragePool(host1, storagePool);
            Mockito.verify(resourceManager, Mockito.never()).connectHostToStoragePool(host2, storagePool);
            Mockito.verify(resourceManager, Mockito.times(1)).disconnectHostFromStoragePool(host2, storagePool);
            Mockito.verify(resourceManager, Mockito.never()).disconnectHostFromStoragePool(host1, storagePool);
        } catch (CloudRuntimeException e) {
            Assert.fail("No exception should be thrown.");
        }
    }

    @Test
    public void testUpdateStoragePoolConnectionsOnHosts_ZoneScope_NoAccessGroups() {
        Long poolId = 1L;
        List<String> storageAccessGroups = new ArrayList<>();

        StoragePoolVO storagePool = Mockito.mock(StoragePoolVO.class);
        Mockito.when(storagePool.getId()).thenReturn(poolId);
        Mockito.when(storagePool.getScope()).thenReturn(ScopeType.ZONE);
        Mockito.when(storagePool.getDataCenterId()).thenReturn(1L);

        Mockito.when(storagePoolDao.findById(poolId)).thenReturn(storagePool);

        HostVO host1 = Mockito.mock(HostVO.class);
        HostVO host2 = Mockito.mock(HostVO.class);
        Mockito.when(host1.getId()).thenReturn(2L);
        Mockito.when(host2.getId()).thenReturn(3L);

        List<HostVO> zoneHosts = Arrays.asList(host1, host2);
        Mockito.doReturn(zoneHosts).when(resourceManager).listAllUpHosts(Host.Type.Routing, null, null, 1L);

        Mockito.doReturn(new String[]{"sag1", "sag2"}).when(storageManager).getStorageAccessGroups(null, null, null, 2L);
        Mockito.doReturn(new String[]{""}).when(storageManager).getStorageAccessGroups(null, null, null, 3L);

        Mockito.when(storagePoolHostDao.findByPoolHost(poolId, 2L)).thenReturn(null);
        Mockito.when(storagePoolHostDao.findByPoolHost(poolId, 3L)).thenReturn(null);

        try {
            resourceManager.updateStoragePoolConnectionsOnHosts(poolId, storageAccessGroups);

            Mockito.verify(resourceManager, Mockito.times(1)).connectHostToStoragePool(host1, storagePool);
            Mockito.verify(resourceManager, Mockito.times(1)).connectHostToStoragePool(host2, storagePool);
            Mockito.verify(resourceManager, Mockito.never()).disconnectHostFromStoragePool(Mockito.any(), Mockito.eq(storagePool));
        } catch (CloudRuntimeException e) {
            Assert.fail("No exception should be thrown.");
        }
    }

    @Test
    public void testUpdateStoragePoolConnectionsOnHosts_ConflictWithHostIdsAndVolumes() {
        Long poolId = 1L;
        List<String> storageAccessGroups = Arrays.asList("sag1", "sag2");

        StoragePoolVO storagePool = Mockito.mock(StoragePoolVO.class);
        Mockito.when(storagePool.getId()).thenReturn(poolId);
        Mockito.when(storagePool.getScope()).thenReturn(ScopeType.CLUSTER);
        Mockito.when(storagePool.getClusterId()).thenReturn(1L);
        Mockito.when(storagePool.getPodId()).thenReturn(1L);
        Mockito.when(storagePool.getDataCenterId()).thenReturn(1L);

        Mockito.when(storagePoolDao.findById(poolId)).thenReturn(storagePool);

        HostVO host1 = Mockito.mock(HostVO.class);
        HostVO host2 = Mockito.mock(HostVO.class);
        Mockito.when(host1.getId()).thenReturn(2L);
        Mockito.when(host2.getId()).thenReturn(3L);

        List<HostVO> clusterHosts = Arrays.asList(host1, host2);
        Mockito.doReturn(clusterHosts).when(resourceManager).listAllUpHosts(Host.Type.Routing, 1L, 1L, 1L);

        VolumeVO volume1 = Mockito.mock(VolumeVO.class);
        VolumeVO volume2 = Mockito.mock(VolumeVO.class);

        Mockito.when(volume1.getInstanceId()).thenReturn(100L);
        Mockito.when(volume2.getInstanceId()).thenReturn(101L);

        List<VolumeVO> volumesInPool = Arrays.asList(volume1, volume2);
        Mockito.doReturn(volumesInPool).when(volumeDao).findNonDestroyedVolumesByPoolId(poolId);

        VMInstanceVO vmInstance1 = Mockito.mock(VMInstanceVO.class);
        VMInstanceVO vmInstance2 = Mockito.mock(VMInstanceVO.class);
        Mockito.when(vmInstance1.getHostId()).thenReturn(2L);
        Mockito.when(vmInstance2.getHostId()).thenReturn(3L);

        Mockito.doReturn(vmInstance1).when(vmInstanceDao).findById(100L);
        Mockito.doReturn(vmInstance2).when(vmInstanceDao).findById(101L);

        Mockito.when(storagePoolHostDao.findByPoolHost(poolId, 2L)).thenReturn(null);
        Mockito.when(storagePoolHostDao.findByPoolHost(poolId, 3L)).thenReturn(null);

        Mockito.doReturn(new String[]{"sag1"}).when(storageManager).getStorageAccessGroups(null, null, null, 2L);
        Mockito.doReturn(new String[]{"sag3"}).when(storageManager).getStorageAccessGroups(null, null, null, 3L);

        Mockito.doReturn(Arrays.asList(2L, 3L)).when(resourceManager).listOfHostIdsUsingTheStoragePool(poolId);

        try {
            resourceManager.updateStoragePoolConnectionsOnHosts(poolId, storageAccessGroups);
            Assert.fail("Expected a CloudRuntimeException to be thrown.");
        } catch (CloudRuntimeException e) {
            Assert.assertTrue(e.getMessage().contains("Storage access groups cannot be updated as they are currently in use by some hosts."));
            Mockito.verify(resourceManager, Mockito.never()).connectHostToStoragePool(Mockito.any(), Mockito.eq(storagePool));
            Mockito.verify(resourceManager, Mockito.never()).disconnectHostFromStoragePool(Mockito.any(), Mockito.eq(storagePool));
        }
    }

    @Test(expected = CloudRuntimeException.class)
    public void testNoUpHostsThrowsException() {
        PrimaryDataStoreInfo primaryStore = Mockito.mock(PrimaryDataStoreInfo.class);
        Mockito.when(primaryStore.getClusterId()).thenReturn(1L);
        Mockito.doReturn(Collections.emptyList()).when(resourceManager).listAllUpHosts(Mockito.any(), Mockito.anyLong(), Mockito.any(), Mockito.anyLong());
        resourceManager.getEligibleUpHostsInClusterForStorageConnection(primaryStore);
    }

    @Test(expected = CloudRuntimeException.class)
    public void testNoUpAndEnabledHostsThrowsException() {
        PrimaryDataStoreInfo primaryStore = Mockito.mock(PrimaryDataStoreInfo.class);
        Mockito.when(primaryStore.getClusterId()).thenReturn(1L);
        Mockito.doReturn(Collections.emptyList()).when(resourceManager).listAllUpAndEnabledHosts(Mockito.any(), Mockito.anyLong(), Mockito.any(), Mockito.anyLong());
        resourceManager.getEligibleUpAndEnabledHostsInClusterForStorageConnection(primaryStore);
    }

    @Test
    public void testEligibleHostsMatchingStorageAccessGroups() {
        PrimaryDataStoreInfo primaryStore = Mockito.mock(PrimaryDataStoreInfo.class);
        DataStore dataStore = Mockito.mock(DataStore.class);
        Mockito.when(primaryStore.getId()).thenReturn(1L);
        Mockito.when(dataStore.getId()).thenReturn(1L);
        Mockito.when(primaryStore.getClusterId()).thenReturn(1L);

        HostVO host1 = Mockito.mock(HostVO.class);
        HostVO host2 = Mockito.mock(HostVO.class);
        List<HostVO> allHosts = Arrays.asList(host1, host2);

        Mockito.when(host1.getId()).thenReturn(1L);
        Mockito.when(host2.getId()).thenReturn(2L);

        Mockito.doReturn(allHosts).when(resourceManager).listAllUpHosts(Mockito.any(), Mockito.anyLong(), Mockito.any(), Mockito.anyLong());
        Mockito.doReturn(allHosts).when(resourceManager).listAllUpAndEnabledHosts(Mockito.any(), Mockito.anyLong(), Mockito.any(), Mockito.anyLong());
        Mockito.doReturn(allHosts).when(resourceManager).listAllUpAndEnabledHostsInOneZoneByHypervisor(Mockito.any(), Mockito.anyLong());
        Mockito.doReturn(Arrays.asList("group1", "group2")).when(storagePoolAccessGroupMapDao).getStorageAccessGroups(1L);

        Mockito.doReturn(new String[]{"group1"})
                .when(storageManager).getStorageAccessGroups(null, null, null, 1L);
        Mockito.doReturn(new String[]{"group3"})
                .when(storageManager).getStorageAccessGroups(null, null, null, 2L);

        List<HostVO> hostsToConnect = resourceManager.getEligibleUpHostsInClusterForStorageConnection(primaryStore);

        Assert.assertEquals("Only one host should match the storage access groups.", 1, hostsToConnect.size());
        Assert.assertTrue("Host1 should be included as it matches the storage access group.", hostsToConnect.contains(host1));
        Assert.assertFalse("Host2 should not be included as it does not match any storage access group.", hostsToConnect.contains(host2));

        hostsToConnect = resourceManager.getEligibleUpAndEnabledHostsInClusterForStorageConnection(primaryStore);

        Assert.assertEquals("Only one host should match the storage access groups.", 1, hostsToConnect.size());
        Assert.assertTrue("Host1 should be included as it matches the storage access group.", hostsToConnect.contains(host1));
        Assert.assertFalse("Host2 should not be included as it does not match any storage access group.", hostsToConnect.contains(host2));

        hostsToConnect = resourceManager.getEligibleUpAndEnabledHostsInZoneForStorageConnection(dataStore, 1L, Hypervisor.HypervisorType.KVM);

        Assert.assertEquals("Only one host should match the storage access groups.", 1, hostsToConnect.size());
        Assert.assertTrue("Host1 should be included as it matches the storage access group.", hostsToConnect.contains(host1));
        Assert.assertFalse("Host2 should not be included as it does not match any storage access group.", hostsToConnect.contains(host2));
    }

    @Test
    public void testUpdateZoneStorageAccessGroups() {
        long zoneId = 1L;
        long podId = 2L;
        long clusterId = 3L;
        long host1Id = 1L;
        long host2Id = 2L;
        List<String> newStorageAccessGroups = Arrays.asList("group1", "group2");

        DataCenterVO zoneVO = Mockito.mock(DataCenterVO.class);
        Mockito.when(dcDao.findById(zoneId)).thenReturn(zoneVO);
        Mockito.when(zoneVO.getId()).thenReturn(zoneId);
        Mockito.when(zoneVO.getStorageAccessGroups()).thenReturn("group1,group3");

        HostVO host1 = Mockito.mock(HostVO.class);
        HostVO host2 = Mockito.mock(HostVO.class);
        Mockito.when(host1.getId()).thenReturn(host1Id);
        Mockito.when(host2.getId()).thenReturn(host2Id);

        HostPodVO pod1 = Mockito.mock(HostPodVO.class);
        ClusterVO cluster1 = Mockito.mock(ClusterVO.class);
        Mockito.when(pod1.getId()).thenReturn(podId);
        Mockito.when(cluster1.getId()).thenReturn(clusterId);
        Mockito.when(podDao.findById(podId)).thenReturn(pod1);
        Mockito.when(clusterDao.findById(clusterId)).thenReturn(cluster1);
        Mockito.when(podDao.listByDataCenterId(zoneId)).thenReturn(Collections.singletonList(pod1));
        Mockito.when(clusterDao.listByPodId(podId)).thenReturn(Collections.singletonList(cluster1));
        Mockito.when(hostDao.findHypervisorHostInPod(podId)).thenReturn(Arrays.asList(host1, host2));
        Mockito.when(hostDao.findByDataCenterId(zoneId)).thenReturn(Arrays.asList(host1, host2));
        Mockito.when(hostDao.findByClusterId(clusterId)).thenReturn(Arrays.asList(host1, host2));

        List<Long> hostIdsUsingStorageTags = Arrays.asList(host1Id);
        Mockito.doReturn(hostIdsUsingStorageTags).when(resourceManager).listOfHostIdsUsingTheStorageAccessGroups(any(), any(), any(), any());

        Mockito.doReturn(new String[]{"group1", "group3"}).when(storageManager).getStorageAccessGroups(null, null, null, host1Id);
        Mockito.doReturn(new String[]{"group2", "group4"}).when(storageManager).getStorageAccessGroups(null, null, null, host2Id);

        resourceManager.updateZoneStorageAccessGroups(zoneId, newStorageAccessGroups);

        Mockito.verify(hostDao, Mockito.times(2)).update(host1Id, host1);
        Mockito.verify(hostDao, Mockito.times(1)).update(host2Id, host2);
    }

    @Test
    public void testUpdatePodStorageAccessGroups() {
        long podId = 2L;
        long clusterId = 3L;
        long host1Id = 1L;
        long host2Id = 2L;
        List<String> newStorageAccessGroups = Arrays.asList("group1", "group2");

        HostVO host1 = Mockito.mock(HostVO.class);
        HostVO host2 = Mockito.mock(HostVO.class);
        Mockito.when(host1.getId()).thenReturn(host1Id);
        Mockito.when(host2.getId()).thenReturn(host2Id);

        HostPodVO pod1 = Mockito.mock(HostPodVO.class);
        ClusterVO cluster1 = Mockito.mock(ClusterVO.class);
        Mockito.when(pod1.getStorageAccessGroups()).thenReturn("group1,group3");
        Mockito.when(cluster1.getId()).thenReturn(clusterId);
        Mockito.when(podDao.findById(podId)).thenReturn(pod1);
        Mockito.when(clusterDao.findById(clusterId)).thenReturn(cluster1);
        Mockito.when(clusterDao.listByPodId(podId)).thenReturn(Collections.singletonList(cluster1));
        Mockito.when(hostDao.findHypervisorHostInPod(podId)).thenReturn(Arrays.asList(host1, host2));
        Mockito.when(hostDao.findByPodId(podId, Host.Type.Routing)).thenReturn(Arrays.asList(host1, host2));
        Mockito.when(hostDao.findByClusterId(clusterId)).thenReturn(Arrays.asList(host1, host2));

        List<Long> hostIdsUsingStorageTags = Arrays.asList(host1Id);
        Mockito.doReturn(hostIdsUsingStorageTags).when(resourceManager).listOfHostIdsUsingTheStorageAccessGroups(any(), any(), any(), any());

        Mockito.doReturn(new String[]{"group1", "group3"}).when(storageManager).getStorageAccessGroups(null, null, null, host1Id);
        Mockito.doReturn(new String[]{"group2", "group4"}).when(storageManager).getStorageAccessGroups(null, null, null, host2Id);

        resourceManager.updatePodStorageAccessGroups(podId, newStorageAccessGroups);

        Mockito.verify(hostDao, Mockito.times(2)).update(host1Id, host1);
        Mockito.verify(hostDao, Mockito.times(1)).update(host2Id, host2);
    }

    @Test
    public void testUpdateClusterStorageAccessGroups() {
        long clusterId = 3L;
        long host1Id = 1L;
        long host2Id = 2L;
        List<String> newStorageAccessGroups = Arrays.asList("group1", "group2");

        HostVO host1 = Mockito.mock(HostVO.class);
        HostVO host2 = Mockito.mock(HostVO.class);
        Mockito.when(host1.getId()).thenReturn(host1Id);
        Mockito.when(host2.getId()).thenReturn(host2Id);

        ClusterVO cluster1 = Mockito.mock(ClusterVO.class);
        Mockito.when(cluster1.getStorageAccessGroups()).thenReturn("group1,group3");
        Mockito.when(cluster1.getId()).thenReturn(clusterId);
        Mockito.when(clusterDao.findById(clusterId)).thenReturn(cluster1);
        Mockito.when(hostDao.findHypervisorHostInCluster(clusterId)).thenReturn(Arrays.asList(host1, host2));
        Mockito.when(hostDao.findByClusterId(clusterId)).thenReturn(Arrays.asList(host1, host2));
        Mockito.when(hostDao.findByClusterId(clusterId, Host.Type.Routing)).thenReturn(Arrays.asList(host1, host2));

        List<Long> hostIdsUsingStorageTags = Arrays.asList(host1Id);
        Mockito.doReturn(hostIdsUsingStorageTags).when(resourceManager).listOfHostIdsUsingTheStorageAccessGroups(any(), any(), any(), any());

        Mockito.doReturn(new String[]{"group1", "group3"}).when(storageManager).getStorageAccessGroups(null, null, null, host1Id);
        Mockito.doReturn(new String[]{"group2", "group4"}).when(storageManager).getStorageAccessGroups(null, null, null, host2Id);

        resourceManager.updateClusterStorageAccessGroups(clusterId, newStorageAccessGroups);

        Mockito.verify(hostDao, Mockito.times(2)).update(host1Id, host1);
        Mockito.verify(hostDao, Mockito.times(1)).update(host2Id, host2);
    }

    @Test
    public void testUpdateHostStorageAccessGroups() {
        long hostId = 1L;
        long clusterId = 2L;
        List<String> newStorageAccessGroups = Arrays.asList("group1", "group2");

        HostVO host = Mockito.mock(HostVO.class);
        Mockito.when(host.getId()).thenReturn(hostId);
        Mockito.when(host.getClusterId()).thenReturn(clusterId);
        Mockito.when(host.getStorageAccessGroups()).thenReturn("group1,group3");

        Mockito.when(hostDao.findById(hostId)).thenReturn(host);
        Mockito.when(storageManager.getStorageAccessGroups(null, null, clusterId, null))
                .thenReturn(new String[]{"group3", "group4"});

        Mockito.doNothing().when(resourceManager).checkIfAnyVolumesInUse(any(), any(), any());
        Mockito.doNothing().when(resourceManager).updateConnectionsBetweenHostsAndStoragePools(any());

        resourceManager.updateHostStorageAccessGroups(hostId, newStorageAccessGroups);

        Mockito.verify(resourceManager).checkIfAnyVolumesInUse(eq(Arrays.asList("group1", "group2", "group3", "group4")),
                eq(Arrays.asList("group3")),
                eq(host));

        Mockito.verify(resourceManager).updateConnectionsBetweenHostsAndStoragePools(
                eq(Collections.singletonMap(host, Arrays.asList("group1", "group2", "group3", "group4")))
        );

        Mockito.verify(host).setStorageAccessGroups("group1,group2");
        Mockito.verify(hostDao).update(hostId, host);
    }

    @Test
    public void executeUserRequestDeleteHostPassesForcedFlags() throws Exception {
        Mockito.doReturn(true).when(resourceManager).doDeleteHost(anyLong(), anyBoolean(), anyBoolean());

        resourceManager.executeUserRequest(hostId, ResourceState.Event.DeleteHost, true, true);

        Mockito.verify(resourceManager).doDeleteHost(hostId, true, true);
    }

    @Test
    public void executeUserRequestDeleteHostPassesNonForcedFlags() throws Exception {
        Mockito.doReturn(true).when(resourceManager).doDeleteHost(anyLong(), anyBoolean(), anyBoolean());

        resourceManager.executeUserRequest(hostId, ResourceState.Event.DeleteHost, false, false);

        Mockito.verify(resourceManager).doDeleteHost(hostId, false, false);
    }

    @Test
    public void executeUserRequestDefaultOverloadPassesFalseForDeleteHost() throws Exception {
        Mockito.doReturn(true).when(resourceManager).doDeleteHost(anyLong(), anyBoolean(), anyBoolean());

        resourceManager.executeUserRequest(hostId, ResourceState.Event.DeleteHost);

        Mockito.verify(resourceManager).doDeleteHost(hostId, false, false);
    }

    @Test
    public void testUpdateClusterStorageAccessGroupsWithEmptyHostsInCluster() {
        Long clusterId = 1L;
        List<String> newStorageAccessGroups = Arrays.asList("sag1", "sag2");

        ClusterVO cluster = Mockito.mock(ClusterVO.class);
        Mockito.when(cluster.getId()).thenReturn(clusterId);
        Mockito.when(cluster.getStorageAccessGroups()).thenReturn("sag3,sag4"); // existing SAGs
        Mockito.when(resourceManager.getCluster(clusterId)).thenReturn(cluster);
        List<HostVO> emptyHostsList = new ArrayList<>();
        Mockito.when(hostDao.findHypervisorHostInCluster(clusterId)).thenReturn(emptyHostsList);
        Mockito.when(hostDao.findByClusterId(clusterId, Host.Type.Routing)).thenReturn(emptyHostsList);
        List<Long> emptyHostIdsList = new ArrayList<>();
        Mockito.doReturn(emptyHostIdsList).when(resourceManager)
                .listOfHostIdsUsingTheStorageAccessGroups(Mockito.anyList(), eq(clusterId), eq(null), eq(null));
        try {
            resourceManager.updateClusterStorageAccessGroups(clusterId, newStorageAccessGroups);
        } catch (CloudRuntimeException e) {
            Assert.fail("updateClusterStorageAccessGroups should not throw CloudRuntimeException when cluster has no hosts. Error: " + e.getMessage());
        }
        Mockito.verify(resourceManager).checkIfAllHostsInUse(Mockito.anyList(), eq(clusterId), eq(null), eq(null));
    }

    @Test
    public void testUpdateClusterStorageAccessGroupsWithEmptyHostsInZone() {
        List<String> sagsToDelete = Arrays.asList("tag1", "tag2");
        Long clusterId = null;
        Long podId = null;
        Long zoneId = 3L;

        List<Long> emptyHostIdsList = new ArrayList<>();
        Mockito.doReturn(emptyHostIdsList).when(resourceManager)
                .listOfHostIdsUsingTheStorageAccessGroups(sagsToDelete, clusterId, podId, zoneId);
        List<HostVO> emptyHostsInZone = new ArrayList<>();
        Mockito.doReturn(emptyHostsInZone).when(hostDao).findByDataCenterId(zoneId);

        try {
            resourceManager.checkIfAllHostsInUse(sagsToDelete, clusterId, podId, zoneId);
        } catch (CloudRuntimeException e) {
            Assert.fail("checkIfAllHostsInUse should not throw CloudRuntimeException when zone has no hosts. Error: " + e.getMessage());
        }
        Mockito.verify(resourceManager).checkIfAllHostsInUse(Mockito.anyList(), eq(null), eq(null), eq(zoneId));
    }

    @Test
    public void testUpdateClusterStorageAccessGroupsWithEmptyHostsInPod() {
        List<String> sagsToDelete = Arrays.asList("tag1", "tag2");
        Long clusterId = null;
        Long podId = 2L;
        Long zoneId = null;

        List<Long> emptyHostIdsList = new ArrayList<>();
        Mockito.doReturn(emptyHostIdsList).when(resourceManager)
                .listOfHostIdsUsingTheStorageAccessGroups(sagsToDelete, clusterId, podId, zoneId);
        List<HostVO> emptyHostsInPod = new ArrayList<>();
        Mockito.doReturn(emptyHostsInPod).when(hostDao).findByPodId(podId, Host.Type.Routing);

        try {
            resourceManager.checkIfAllHostsInUse(sagsToDelete, clusterId, podId, zoneId);
        } catch (CloudRuntimeException e) {
            Assert.fail("checkIfAllHostsInUse should not throw CloudRuntimeException when pod has no hosts. Error: " + e.getMessage());
        }
        Mockito.verify(resourceManager).checkIfAllHostsInUse(Mockito.anyList(), eq(null), eq(podId), eq(null));
    }

    @Test
    public void testCheckIfAllHostsInUseWithEmptyHostsInMultipleLevels() {
        List<String> sagsToDelete = Arrays.asList("tag1", "tag2");
        Long clusterId = 1L;
        Long podId = 2L;
        Long zoneId = 3L;

        List<Long> emptyHostIdsList = new ArrayList<>();
        Mockito.doReturn(emptyHostIdsList).when(resourceManager)
                .listOfHostIdsUsingTheStorageAccessGroups(sagsToDelete, clusterId, podId, zoneId);
        List<HostVO> emptyHostsInZone = new ArrayList<>();
        List<HostVO> emptyHostsInCluster = new ArrayList<>();
        List<HostVO> emptyHostsInPod = new ArrayList<>();
        Mockito.doReturn(emptyHostsInZone).when(hostDao).findByDataCenterId(zoneId);
        Mockito.doReturn(emptyHostsInCluster).when(hostDao).findByClusterId(clusterId, Host.Type.Routing);
        Mockito.doReturn(emptyHostsInPod).when(hostDao).findByPodId(podId, Host.Type.Routing);

        try {
            resourceManager.checkIfAllHostsInUse(sagsToDelete, clusterId, podId, zoneId);
        } catch (CloudRuntimeException e) {
            Assert.fail("checkIfAllHostsInUse should not throw CloudRuntimeException when all levels have no hosts. Error: " + e.getMessage());
        }
        Mockito.verify(hostDao).findByDataCenterId(zoneId);
        Mockito.verify(hostDao).findByClusterId(clusterId, Host.Type.Routing);
        Mockito.verify(hostDao).findByPodId(podId, Host.Type.Routing);
    }
}
