Skip to content

Commit bbc65d0

Browse files
committed
server: add duplicate host check
Fixes #13080 Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
1 parent a7c2a05 commit bbc65d0

2 files changed

Lines changed: 73 additions & 39 deletions

File tree

server/src/main/java/com/cloud/resource/ResourceManagerImpl.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -798,6 +798,8 @@ private List<HostVO> discoverHostsFull(final Long dcId, final Long podId, Long c
798798
throw new InvalidParameterValueException(url + " is not a valid uri");
799799
}
800800

801+
checkForDuplicateHost(url);
802+
801803
final List<HostVO> hosts = new ArrayList<>();
802804
logger.info("Trying to add a new host at {} in data center {}", url, zone);
803805
boolean isHypervisorTypeSupported = false;
@@ -2585,6 +2587,24 @@ private Host createHostAndAgent(final ServerResource resource, final Map<String,
25852587
return host;
25862588
}
25872589

2590+
void checkForDuplicateHost(final String url) {
2591+
String hostIpOrName = null;
2592+
try {
2593+
hostIpOrName = new URI(UriUtils.encodeURIComponent(url)).getHost();
2594+
} catch (final URISyntaxException ignore) {
2595+
// unparseable URL - discoverer will reject it shortly anyway
2596+
}
2597+
if (StringUtils.isBlank(hostIpOrName)) {
2598+
return;
2599+
}
2600+
final HostVO existingByIp = _hostDao.findByIp(hostIpOrName);
2601+
if (existingByIp != null) {
2602+
throw new InvalidParameterValueException(String.format(
2603+
"A host with IP address / hostname '%s' already exists (id: %s). Remove it before adding again.",
2604+
hostIpOrName, existingByIp.getUuid()));
2605+
}
2606+
}
2607+
25882608
private Host createHostAndAgentDeferred(final ServerResource resource, final Map<String, String> details, final boolean old, final List<String> hostTags, final boolean forRebalance) {
25892609
HostVO host = null;
25902610
StartupCommand[] cmds = null;

server/src/test/java/com/cloud/resource/ResourceManagerImplTest.java

Lines changed: 53 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,46 @@
1717

1818
package com.cloud.resource;
1919

20+
import static com.cloud.resource.ResourceState.Event.ErrorsCorrected;
21+
import static com.cloud.resource.ResourceState.Event.InternalEnterMaintenance;
22+
import static com.cloud.resource.ResourceState.Event.UnableToMaintain;
23+
import static com.cloud.resource.ResourceState.Event.UnableToMigrate;
24+
import static org.mockito.ArgumentMatchers.any;
25+
import static org.mockito.ArgumentMatchers.anyBoolean;
26+
import static org.mockito.ArgumentMatchers.anyLong;
27+
import static org.mockito.ArgumentMatchers.anyString;
28+
import static org.mockito.ArgumentMatchers.eq;
29+
import static org.mockito.Mockito.never;
30+
import static org.mockito.Mockito.times;
31+
import static org.mockito.Mockito.verify;
32+
import static org.mockito.Mockito.when;
33+
34+
import java.lang.reflect.Field;
35+
import java.util.ArrayList;
36+
import java.util.Arrays;
37+
import java.util.Collections;
38+
import java.util.List;
39+
import java.util.UUID;
40+
41+
import org.apache.cloudstack.api.command.admin.host.CancelHostAsDegradedCmd;
42+
import org.apache.cloudstack.api.command.admin.host.DeclareHostAsDegradedCmd;
43+
import org.apache.cloudstack.framework.config.ConfigKey;
44+
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
45+
import org.junit.After;
46+
import org.junit.Assert;
47+
import org.junit.Before;
48+
import org.junit.Test;
49+
import org.junit.runner.RunWith;
50+
import org.mockito.BDDMockito;
51+
import org.mockito.InjectMocks;
52+
import org.mockito.Mock;
53+
import org.mockito.MockedConstruction;
54+
import org.mockito.MockedStatic;
55+
import org.mockito.Mockito;
56+
import org.mockito.MockitoAnnotations;
57+
import org.mockito.Spy;
58+
import org.mockito.junit.MockitoJUnitRunner;
59+
2060
import com.cloud.agent.AgentManager;
2161
import com.cloud.agent.api.GetVncPortAnswer;
2262
import com.cloud.agent.api.GetVncPortCommand;
@@ -43,45 +83,6 @@
4383
import com.cloud.vm.dao.UserVmDetailsDao;
4484
import com.cloud.vm.dao.VMInstanceDao;
4585
import com.trilead.ssh2.Connection;
46-
import org.apache.cloudstack.api.command.admin.host.CancelHostAsDegradedCmd;
47-
import org.apache.cloudstack.api.command.admin.host.DeclareHostAsDegradedCmd;
48-
import org.apache.cloudstack.framework.config.ConfigKey;
49-
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
50-
import org.junit.After;
51-
import org.junit.Assert;
52-
import org.junit.Before;
53-
import org.junit.Test;
54-
import org.junit.runner.RunWith;
55-
import org.mockito.BDDMockito;
56-
import org.mockito.InjectMocks;
57-
import org.mockito.Mock;
58-
import org.mockito.MockedConstruction;
59-
import org.mockito.MockedStatic;
60-
import org.mockito.Mockito;
61-
import org.mockito.MockitoAnnotations;
62-
import org.mockito.Spy;
63-
import org.mockito.junit.MockitoJUnitRunner;
64-
65-
import java.lang.reflect.Field;
66-
import java.util.ArrayList;
67-
import java.util.Arrays;
68-
import java.util.Collections;
69-
import java.util.List;
70-
import java.util.UUID;
71-
72-
import static com.cloud.resource.ResourceState.Event.ErrorsCorrected;
73-
import static com.cloud.resource.ResourceState.Event.InternalEnterMaintenance;
74-
import static com.cloud.resource.ResourceState.Event.UnableToMaintain;
75-
import static com.cloud.resource.ResourceState.Event.UnableToMigrate;
76-
import static org.mockito.ArgumentMatchers.any;
77-
import static org.mockito.ArgumentMatchers.anyBoolean;
78-
import static org.mockito.ArgumentMatchers.anyLong;
79-
import static org.mockito.ArgumentMatchers.anyString;
80-
import static org.mockito.ArgumentMatchers.eq;
81-
import static org.mockito.Mockito.never;
82-
import static org.mockito.Mockito.times;
83-
import static org.mockito.Mockito.verify;
84-
import static org.mockito.Mockito.when;
8586

8687
@RunWith(MockitoJUnitRunner.class)
8788
public class ResourceManagerImplTest {
@@ -218,6 +219,19 @@ public void tearDown() throws Exception {
218219
closeable.close();
219220
}
220221

222+
@Test(expected = InvalidParameterValueException.class)
223+
public void testCheckForDuplicateHostThrowsWhenIpAlreadyExists() {
224+
when(hostDao.findByIp("10.0.0.10")).thenReturn(host);
225+
resourceManager.checkForDuplicateHost("http://10.0.0.10");
226+
}
227+
228+
@Test
229+
public void testCheckForDuplicateHostAllowsUniqueHost() {
230+
when(hostDao.findByIp("10.0.0.30")).thenReturn(null);
231+
resourceManager.checkForDuplicateHost("http://10.0.0.30");
232+
verify(hostDao, times(1)).findByIp("10.0.0.30");
233+
}
234+
221235
@Test
222236
public void testCheckAndMaintainEnterMaintenanceModeNoVms() throws NoTransitionException {
223237
// Test entering into maintenance with no VMs running on host.

0 commit comments

Comments
 (0)