Skip to content

Commit ff2b0a4

Browse files
mprokopchuksureshanaparti
authored andcommitted
Remove IP address dependency for management server communication
Allows the management.server.address config to be a list of hostnames instead of static IPs. Rebalancing, cluster propagation, alerts, and stats collection all detect the format at runtime via ManagementServerAddressUtil and use the matching lookup (listNonUpStateMsHostnames vs listNonUpStateMsIPs) when computing the "avoid" list sent to agents. Hostnames survive MS restarts and IP reassignments where static IPs do not, which is required in deployment environments where management server instances can be rescheduled or replaced.
1 parent 936e03e commit ff2b0a4

15 files changed

Lines changed: 810 additions & 88 deletions

File tree

api/src/main/java/org/apache/cloudstack/management/ManagementServerHost.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
// under the License.
1717
package org.apache.cloudstack.management;
1818

19+
import com.cloud.utils.StringUtils;
1920
import org.apache.cloudstack.acl.ControlledEntity;
2021
import org.apache.cloudstack.api.Identity;
2122
import org.apache.cloudstack.api.InternalIdentity;
@@ -34,4 +35,15 @@ enum State {
3435
String getVersion();
3536

3637
String getServiceIP();
38+
39+
/**
40+
* Returns the node's hostname when set, otherwise falls back to the service IP, so log and
41+
* alert messages always carry a usable identifier even though the name column is nullable.
42+
*
43+
* @return the hostname if not blank, else the service IP
44+
*/
45+
default String getHostIdentifier() {
46+
String name = getName();
47+
return StringUtils.isNotBlank(name) ? name : getServiceIP();
48+
}
3749
}

engine/components-api/src/main/java/com/cloud/agent/AgentManager.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
// under the License.
1717
package com.cloud.agent;
1818

19+
import java.util.List;
1920
import java.util.Map;
2021

2122
import org.apache.cloudstack.framework.config.ConfigKey;
@@ -178,4 +179,6 @@ enum TapAgentsAction {
178179
boolean transferDirectAgentsFromMS(String fromMsUuid, long fromMsId, long timeoutDurationInMs, boolean excludeHostsInMaintenance);
179180

180181
int getHostSshPort(HostVO host);
182+
183+
List<String> getAvoidMsList();
181184
}

engine/orchestration/src/main/java/com/cloud/agent/manager/AgentManagerImpl.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949

5050
import com.cloud.agent.api.AgentConnectStatusAnswer;
5151
import com.cloud.agent.api.AgentConnectStatusCommand;
52+
import com.cloud.cluster.ManagementServerAddressUtil;
5253
import com.cloud.event.EventTypes;
5354
import com.cloud.utils.DateUtil;
5455
import com.cloud.utils.Profiler;
@@ -1859,10 +1860,16 @@ private void updateReadyCommandWithMSList(HostVO host, ReadyCommand ready, Start
18591860
}
18601861
}
18611862

1863+
public List<String> getAvoidMsList() {
1864+
// Detect config format and build avoid list using matching format
1865+
boolean isUsingHostnames = ManagementServerAddressUtil.isManagementServerAddressListUsingHostnames();
1866+
return isUsingHostnames ? _mshostDao.listNonUpStateMsHostnames() : _mshostDao.listNonUpStateMsIPs();
1867+
}
1868+
18621869
private void setReadyCommandMSList(HostVO host, ReadyCommand ready) {
18631870
List<String> newMSList = indirectAgentLB.getManagementServerList(host.getId(), host.getDataCenterId(), null);
18641871
ready.setMsHostList(newMSList);
1865-
List<String> avoidMsList = _mshostDao.listNonUpStateMsIPs();
1872+
List<String> avoidMsList = getAvoidMsList();
18661873
ready.setAvoidMsHostList(avoidMsList);
18671874
ready.setLbAlgorithm(indirectAgentLB.getLBAlgorithmName());
18681875
ready.setLbCheckInterval(indirectAgentLB.getLBPreferredHostCheckInterval(host.getClusterId()));
@@ -2381,10 +2388,6 @@ private boolean sendRequestStartupCommand(long hostId, HostVO host) {
23812388
return requestStartup;
23822389
}
23832390

2384-
private List<String> getAvoidMsList() {
2385-
return _mshostDao.listNonUpStateMsIPs();
2386-
}
2387-
23882391
protected void processResponse(final Link link, final Response response) {
23892392
final AgentAttache attache = (AgentAttache)link.attachment();
23902393
if (attache == null) {

engine/orchestration/src/main/java/com/cloud/agent/manager/ClusteredAgentManagerImpl.java

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import javax.net.ssl.SSLEngine;
4444

4545
import com.cloud.resource.ResourceState;
46+
import com.cloud.utils.StringUtils;
4647
import org.apache.cloudstack.ca.CAManager;
4748
import org.apache.cloudstack.framework.config.ConfigDepot;
4849
import org.apache.cloudstack.framework.config.ConfigKey;
@@ -541,14 +542,9 @@ public SocketChannel connectToPeer(final String peerName, final SocketChannel pr
541542
logger.info("Unable to find peer: {}", peerName);
542543
return null;
543544
}
544-
final String ip = ms.getServiceIP();
545-
InetAddress addr;
546-
int port = Port.value();
547-
try {
548-
addr = InetAddress.getByName(ip);
549-
} catch (final UnknownHostException e) {
550-
throw new CloudRuntimeException("Unable to resolve " + ip);
551-
}
545+
final String hostName = getHostIdentifier(ms);
546+
final int port = Port.value();
547+
final InetAddress addr = resolveManagementServerAddress(ms);
552548
SocketChannel ch1 = null;
553549
try {
554550
ch1 = SocketChannel.open(new InetSocketAddress(addr, port));
@@ -557,20 +553,20 @@ public SocketChannel connectToPeer(final String peerName, final SocketChannel pr
557553
ch1.socket().setSoTimeout(60 * 1000);
558554
try {
559555
SSLContext sslContext = Link.initManagementSSLContext(caService);
560-
sslEngine = sslContext.createSSLEngine(ip, port);
556+
sslEngine = sslContext.createSSLEngine(hostName, port);
561557
sslEngine.setUseClientMode(true);
562558
sslEngine.setEnabledProtocols(SSLUtils.getSupportedProtocols(sslEngine.getEnabledProtocols()));
563559
sslEngine.beginHandshake();
564560
if (!Link.doHandshake(ch1, sslEngine)) {
565561
ch1.close();
566-
throw new IOException(String.format("SSL: Handshake failed with peer management server '%s' on %s:%d ", peerName, ip, port));
562+
throw new IOException(String.format("SSL: Handshake failed with peer management server '%s' on %s:%d ", peerName, hostName, port));
567563
}
568-
logger.info("SSL: Handshake done with peer management server '{}' on {}:{} ", peerName, ip, port);
564+
logger.info("SSL: Handshake done with peer management server '{}' on {}:{} ", peerName, hostName, port);
569565
} catch (final Exception e) {
570566
ch1.close();
571567
throw new IOException("SSL: Fail to init SSL! " + e);
572568
}
573-
logger.debug("Connection to peer opened: {}, IP: {}", peerName, ip);
569+
logger.debug("Connection to peer opened: {}, host: {}", peerName, hostName);
574570
_peers.put(peerName, ch1);
575571
_sslEngines.put(peerName, sslEngine);
576572
return ch1;
@@ -582,7 +578,7 @@ public SocketChannel connectToPeer(final String peerName, final SocketChannel pr
582578
logger.error("failed to close failed peer socket: {}", ex);
583579
}
584580
}
585-
logger.warn("Unable to connect to peer management server: {}, IP {} due to {}", peerName, ip, e.getMessage(), e);
581+
logger.warn("Unable to connect to peer management server: {}, host {} due to {}", peerName, hostName, e.getMessage(), e);
586582
return null;
587583
}
588584
}
@@ -592,6 +588,38 @@ public SocketChannel connectToPeer(final String peerName, final SocketChannel pr
592588
}
593589
}
594590

591+
/**
592+
* Gets the hostname or IP address to use for connecting to a management server.
593+
* Prefers hostname (for CNAME support) but falls back to IP if hostname is null.
594+
*
595+
* @param host the management server host
596+
* @return hostname if available, otherwise service IP
597+
* @throws CloudRuntimeException if both hostname and IP are null
598+
*/
599+
private String getHostIdentifier(final ManagementServerHost host) {
600+
final String hostName = host.getName();
601+
if (StringUtils.isNotBlank(hostName)) {
602+
return hostName;
603+
}
604+
605+
final String serviceIP = host.getServiceIP();
606+
if (StringUtils.isNotBlank(serviceIP)) {
607+
return serviceIP;
608+
}
609+
610+
throw new CloudRuntimeException("Management server host has neither hostname nor IP address: " + host);
611+
}
612+
613+
private InetAddress resolveManagementServerAddress(final ManagementServerHost host) {
614+
final String addressToResolve = getHostIdentifier(host);
615+
616+
try {
617+
return InetAddress.getByName(addressToResolve);
618+
} catch (final UnknownHostException e) {
619+
throw new CloudRuntimeException("Unable to resolve " + addressToResolve, e);
620+
}
621+
}
622+
595623
public SocketChannel connectToPeer(final long hostId, final SocketChannel prevCh) {
596624
final String peerName = getPeerName(hostId);
597625
if (peerName == null) {

0 commit comments

Comments
 (0)