Handle multiple active entries for same hostname in k8s setup

This commit is contained in:
mprokopchuk 2026-02-16 22:24:30 +01:00 committed by Pearl Dsilva
parent 855f611bfa
commit c64d1feb79
4 changed files with 18 additions and 32 deletions

View File

@ -1050,8 +1050,8 @@ public class ClusterManagerImpl extends ManagerBase implements ClusterManager, C
// Look for duplicate hostname in the case of kubernetes setup where ip/mac changes but hostname is constant.
if (mshost == null && StringUtils.isNotBlank(currentHostname)) {
ManagementServerHostVO activeEntry = _mshostDao.findByName(currentHostname);
if (activeEntry != null) {
List<ManagementServerHostVO> activeEntries = _mshostDao.findAllByName(currentHostname);
for (ManagementServerHostVO activeEntry : activeEntries) {
// Found an active entry with this hostname but different MSID
// This happens when a pod restarts with a new MAC address (new MSID)
if (activeEntry.getMsid() != _msId) {

View File

@ -31,7 +31,7 @@ public interface ManagementServerHostDao extends GenericDao<ManagementServerHost
ManagementServerHostVO findByMsid(long msid);
ManagementServerHostVO findByName(String name);
List<ManagementServerHostVO> findAllByName(String name);
int increaseAlertCount(long id);

View File

@ -26,6 +26,7 @@ import java.util.TimeZone;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import com.cloud.cluster.ClusterInvalidSessionException;
import org.apache.cloudstack.management.ManagementServerHost;
@ -77,29 +78,13 @@ public class ManagementServerHostDaoImpl extends GenericDaoBase<ManagementServer
}
@Override
public ManagementServerHostVO findByName(String name) {
if (name == null || name.trim().isEmpty()) {
return null;
public List<ManagementServerHostVO> findAllByName(String name) {
if (StringUtils.isBlank(name)) {
return List.of();
}
SearchCriteria<ManagementServerHostVO> sc = NameSearch.create();
sc.setParameters("name", name);
// Only search for active (non-removed) entries to avoid non-deterministic results
// when multiple removed entries exist for the same hostname
sc.addAnd("removed", SearchCriteria.Op.NULL);
List<ManagementServerHostVO> l = listBy(sc);
if (l != null && l.size() > 0) {
if (l.size() > 1) {
s_logger.error(String.format(
"Data corruption detected: Found %d active entries for hostname '%s'. " +
"This should never happen and indicates duplicate mshost records.",
l.size(), name));
}
return l.get(0);
}
return null;
return listBy(sc);
}
@Override

View File

@ -22,7 +22,8 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
import static org.junit.Assert.assertNull;
import java.util.List;
import static org.junit.Assert.assertEquals;
/**
* Unit tests for ManagementServerHostDaoImpl focusing on the new findByName method added in PR #641.
@ -39,26 +40,26 @@ public class ManagementServerHostDaoImplTest {
@Test
public void testFindByName_ReturnsNullForNullHostname() {
ManagementServerHostVO result = dao.findByName(null);
assertNull("Result should be null for null hostname", result);
List<ManagementServerHostVO> result = dao.findAllByName(null);
assertEquals(0, result.size());
}
@Test
public void testFindByName_ReturnsNullForEmptyHostname() {
ManagementServerHostVO result = dao.findByName("");
assertNull("Result should be null for empty hostname", result);
List<ManagementServerHostVO> result = dao.findAllByName("");
assertEquals(0, result.size());
}
@Test
public void testFindByName_ReturnsNullForWhitespaceHostname() {
ManagementServerHostVO result = dao.findByName(" ");
assertNull("Result should be null for whitespace-only hostname", result);
List<ManagementServerHostVO> result = dao.findAllByName(" ");
assertEquals(0, result.size());
}
@Test
public void testFindByName_ReturnsNullForTabAndSpaceHostname() {
ManagementServerHostVO result = dao.findByName(" \t ");
assertNull("Result should be null for tab/space-only hostname", result);
List<ManagementServerHostVO> result = dao.findAllByName(" \t ");
assertEquals(0, result.size());
}
/**