mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
Improvement: management server peer states (#9885)
* Improvement: management server peer states * Update pr9885: consider new mgmt server node which has msId=managementServerNodeId * Update pr9885: update global config description * Update pr9885: update label on UI * framework: Do not update mshost_peer when mgmt server is Up as it will be updated by status update * mgmt: Update state to Up when mgmt server writes heartbeat to db * mgmt: change Service IP to Management IP --------- Co-authored-by: Boris Stoyanov - a.k.a Bobby <bss.stoyanov@gmail.com>
This commit is contained in:
parent
22a6604491
commit
34056d956c
@ -32,6 +32,8 @@ public interface ManagementServerHostStats {
|
||||
|
||||
String getManagementServerHostUuid();
|
||||
|
||||
long getManagementServerRunId();
|
||||
|
||||
long getSessions();
|
||||
|
||||
double getCpuUtilization();
|
||||
|
||||
@ -381,6 +381,14 @@ public class ApiConstants {
|
||||
public static final String PATH = "path";
|
||||
public static final String PAYLOAD = "payload";
|
||||
public static final String PAYLOAD_URL = "payloadurl";
|
||||
public static final String PEERS = "peers";
|
||||
public static final String PEER_ID = "peerid";
|
||||
public static final String PEER_NAME = "peername";
|
||||
public static final String PEER_MSID = "peermsid";
|
||||
public static final String PEER_RUNID = "peerrunid";
|
||||
public static final String PEER_SERVICE_IP = "peerserviceip";
|
||||
public static final String PEER_SERVICE_PORT = "peerserviceport";
|
||||
public static final String PEER_STATE = "peerstate";
|
||||
public static final String POD_ID = "podid";
|
||||
public static final String POD_NAME = "podname";
|
||||
public static final String POD_IDS = "podids";
|
||||
|
||||
@ -23,6 +23,7 @@ import org.apache.cloudstack.api.BaseListCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.response.ListResponse;
|
||||
import org.apache.cloudstack.api.response.ManagementServerResponse;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
|
||||
@APICommand(name = "listManagementServers", description = "Lists management servers.", responseObject = ManagementServerResponse.class,
|
||||
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
|
||||
@ -39,6 +40,11 @@ public class ListMgmtsCmd extends BaseListCmd {
|
||||
@Parameter(name = ApiConstants.NAME, type = CommandType.STRING, description = "the name of the management server")
|
||||
private String hostName;
|
||||
|
||||
@Parameter(name = ApiConstants.PEERS, type = CommandType.BOOLEAN,
|
||||
description = "Whether to return the management server peers or not. By default, the management server peers will not be returned.",
|
||||
since = "4.20.0.0")
|
||||
private Boolean peers;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
@ -51,6 +57,10 @@ public class ListMgmtsCmd extends BaseListCmd {
|
||||
return hostName;
|
||||
}
|
||||
|
||||
public Boolean getPeers() {
|
||||
return BooleanUtils.toBooleanDefaultIfNull(peers, false);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////// API Implementation///////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
@ -24,7 +24,9 @@ import org.apache.cloudstack.api.BaseResponse;
|
||||
import org.apache.cloudstack.api.EntityReference;
|
||||
import org.apache.cloudstack.management.ManagementServerHost.State;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@EntityReference(value = ManagementServerHost.class)
|
||||
public class ManagementServerResponse extends BaseResponse {
|
||||
@ -76,6 +78,10 @@ public class ManagementServerResponse extends BaseResponse {
|
||||
@Param(description = "the IP Address for this Management Server")
|
||||
private String serviceIp;
|
||||
|
||||
@SerializedName(ApiConstants.PEERS)
|
||||
@Param(description = "the Management Server Peers")
|
||||
private List<PeerManagementServerNodeResponse> peers;
|
||||
|
||||
public String getId() {
|
||||
return this.id;
|
||||
}
|
||||
@ -171,4 +177,19 @@ public class ManagementServerResponse extends BaseResponse {
|
||||
public String getKernelVersion() {
|
||||
return kernelVersion;
|
||||
}
|
||||
|
||||
public List<PeerManagementServerNodeResponse> getPeers() {
|
||||
return peers;
|
||||
}
|
||||
|
||||
public void setPeers(List<PeerManagementServerNodeResponse> peers) {
|
||||
this.peers = peers;
|
||||
}
|
||||
|
||||
public void addPeer(PeerManagementServerNodeResponse peer) {
|
||||
if (peers == null) {
|
||||
peers = new ArrayList<>();
|
||||
}
|
||||
peers.add(peer);
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,100 @@
|
||||
// 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 org.apache.cloudstack.api.response;
|
||||
|
||||
import com.cloud.serializer.Param;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.BaseResponse;
|
||||
import org.apache.cloudstack.management.ManagementServerHost.State;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public class PeerManagementServerNodeResponse extends BaseResponse {
|
||||
|
||||
@SerializedName(ApiConstants.STATE)
|
||||
@Param(description = "the state of the management server peer")
|
||||
private State state;
|
||||
|
||||
@SerializedName(ApiConstants.LAST_UPDATED)
|
||||
@Param(description = "the last updated time of the management server peer state")
|
||||
private Date lastUpdated;
|
||||
|
||||
@SerializedName(ApiConstants.PEER_ID)
|
||||
@Param(description = "the ID of the peer management server")
|
||||
private String peerId;
|
||||
|
||||
@SerializedName(ApiConstants.PEER_NAME)
|
||||
@Param(description = "the name of the peer management server")
|
||||
private String peerName;
|
||||
|
||||
@SerializedName(ApiConstants.PEER_MSID)
|
||||
@Param(description = "the management ID of the peer management server")
|
||||
private String peerMsId;
|
||||
|
||||
@SerializedName(ApiConstants.PEER_RUNID)
|
||||
@Param(description = "the run ID of the peer management server")
|
||||
private String peerRunId;
|
||||
|
||||
@SerializedName(ApiConstants.PEER_STATE)
|
||||
@Param(description = "the state of the peer management server")
|
||||
private String peerState;
|
||||
|
||||
@SerializedName(ApiConstants.PEER_SERVICE_IP)
|
||||
@Param(description = "the IP Address for the peer Management Server")
|
||||
private String peerServiceIp;
|
||||
|
||||
@SerializedName(ApiConstants.PEER_SERVICE_PORT)
|
||||
@Param(description = "the service port for the peer Management Server")
|
||||
private String peerServicePort;
|
||||
|
||||
public void setState(State state) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public void setLastUpdated(Date lastUpdated) {
|
||||
this.lastUpdated = lastUpdated;
|
||||
}
|
||||
|
||||
public void setPeerId(String peerId) {
|
||||
this.peerId = peerId;
|
||||
}
|
||||
|
||||
public void setPeerName(String peerName) {
|
||||
this.peerName = peerName;
|
||||
}
|
||||
|
||||
public void setPeerMsId(String peerMsId) {
|
||||
this.peerMsId = peerMsId;
|
||||
}
|
||||
|
||||
public void setPeerRunId(String peerRunId) {
|
||||
this.peerRunId = peerRunId;
|
||||
}
|
||||
|
||||
public void setPeerState(String peerState) {
|
||||
this.peerState = peerState;
|
||||
}
|
||||
|
||||
public void setPeerServiceIp(String peerServiceIp) {
|
||||
this.peerServiceIp = peerServiceIp;
|
||||
}
|
||||
|
||||
public void setPeerServicePort(String peerServicePort) {
|
||||
this.peerServicePort = peerServicePort;
|
||||
}
|
||||
}
|
||||
@ -117,6 +117,7 @@
|
||||
<bean id="loadBalancerCertMapDaoImpl" class="com.cloud.network.dao.LoadBalancerCertMapDaoImpl" />
|
||||
<bean id="managementServerHostDaoImpl" class="com.cloud.cluster.dao.ManagementServerHostDaoImpl" />
|
||||
<bean id="managementServerHostPeerDaoImpl" class="com.cloud.cluster.dao.ManagementServerHostPeerDaoImpl" />
|
||||
<bean id="managementServerHostPeerJoinDaoImpl" class="com.cloud.cluster.dao.ManagementServerHostPeerJoinDaoImpl" />
|
||||
<bean id="managementServerStatusDaoImpl" class="com.cloud.cluster.dao.ManagementServerStatusDaoImpl" />
|
||||
<bean id="networkAccountDaoImpl" class="com.cloud.network.dao.NetworkAccountDaoImpl" />
|
||||
<bean id="networkACLDaoImpl" class="com.cloud.network.vpc.dao.NetworkACLDaoImpl" />
|
||||
|
||||
@ -0,0 +1,28 @@
|
||||
-- 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.
|
||||
|
||||
DROP PROCEDURE IF EXISTS `cloud`.`IDEMPOTENT_ADD_FOREIGN_KEY`;
|
||||
|
||||
CREATE PROCEDURE `cloud`.`IDEMPOTENT_ADD_FOREIGN_KEY` (
|
||||
IN in_table_name VARCHAR(200)
|
||||
, IN in_key_name VARCHAR(200)
|
||||
, IN in_foreign_key VARCHAR(200)
|
||||
, IN in_references VARCHAR(1000)
|
||||
)
|
||||
BEGIN
|
||||
|
||||
DECLARE CONTINUE HANDLER FOR 1061 BEGIN END; SET @ddl = CONCAT_WS(' ', 'ALTER TABLE ', in_table_name, ' ADD CONSTRAINT ', in_key_name, ' FOREIGN KEY ', in_foreign_key, ' REFERENCES ', in_references, ' ON DELETE CASCADE'); PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt; END;
|
||||
@ -425,3 +425,10 @@ INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid, hypervisor_type, hypervi
|
||||
|
||||
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.vm_instance', 'delete_protection', 'boolean DEFAULT FALSE COMMENT "delete protection for vm" ');
|
||||
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.volumes', 'delete_protection', 'boolean DEFAULT FALSE COMMENT "delete protection for volumes" ');
|
||||
|
||||
-- Modify index for mshost_peer
|
||||
DELETE FROM `cloud`.`mshost_peer`;
|
||||
CALL `cloud`.`IDEMPOTENT_DROP_FOREIGN_KEY`('cloud.mshost_peer','fk_mshost_peer__owner_mshost');
|
||||
CALL `cloud`.`IDEMPOTENT_DROP_INDEX`('i_mshost_peer__owner_peer_runid','mshost_peer');
|
||||
CALL `cloud`.`IDEMPOTENT_ADD_UNIQUE_KEY`('cloud.mshost_peer', 'i_mshost_peer__owner_peer', '(owner_mshost, peer_mshost)');
|
||||
CALL `cloud`.`IDEMPOTENT_ADD_FOREIGN_KEY`('cloud.mshost_peer', 'fk_mshost_peer__owner_mshost', '(owner_mshost)', '`mshost`(`id`)');
|
||||
|
||||
@ -0,0 +1,44 @@
|
||||
-- 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.
|
||||
|
||||
|
||||
DROP VIEW IF EXISTS `cloud`.`mshost_peer_view`;
|
||||
|
||||
CREATE VIEW `cloud`.`mshost_peer_view` AS
|
||||
SELECT
|
||||
`mshost_peer`.`id` AS `id`,
|
||||
`mshost_peer`.`peer_state` AS `peer_state`,
|
||||
`mshost_peer`.`last_update` AS `last_update`,
|
||||
`owner_mshost`.`id` AS `owner_mshost_id`,
|
||||
`owner_mshost`.`msid` AS `owner_mshost_msid`,
|
||||
`owner_mshost`.`runid` AS `owner_mshost_runid`,
|
||||
`owner_mshost`.`name` AS `owner_mshost_name`,
|
||||
`owner_mshost`.`uuid` AS `owner_mshost_uuid`,
|
||||
`owner_mshost`.`state` AS `owner_mshost_state`,
|
||||
`owner_mshost`.`service_ip` AS `owner_mshost_service_ip`,
|
||||
`owner_mshost`.`service_port` AS `owner_mshost_service_port`,
|
||||
`peer_mshost`.`id` AS `peer_mshost_id`,
|
||||
`peer_mshost`.`msid` AS `peer_mshost_msid`,
|
||||
`peer_mshost`.`runid` AS `peer_mshost_runid`,
|
||||
`peer_mshost`.`name` AS `peer_mshost_name`,
|
||||
`peer_mshost`.`uuid` AS `peer_mshost_uuid`,
|
||||
`peer_mshost`.`state` AS `peer_mshost_state`,
|
||||
`peer_mshost`.`service_ip` AS `peer_mshost_service_ip`,
|
||||
`peer_mshost`.`service_port` AS `peer_mshost_service_port`
|
||||
FROM `cloud`.`mshost_peer`
|
||||
LEFT JOIN `cloud`.`mshost` AS owner_mshost on `mshost_peer`.`owner_mshost` = `owner_mshost`.`id`
|
||||
LEFT JOIN `cloud`.`mshost` AS peer_mshost on `mshost_peer`.`peer_mshost` = `peer_mshost`.`id`;
|
||||
@ -27,9 +27,9 @@ import com.cloud.utils.component.Manager;
|
||||
public interface ClusterManager extends Manager {
|
||||
static final String ALERT_SUBJECT = "cluster-alert";
|
||||
final ConfigKey<Integer> HeartbeatInterval = new ConfigKey<Integer>(Integer.class, "cluster.heartbeat.interval", "management-server", "1500",
|
||||
"Interval to check for the heart beat between management server nodes", false);
|
||||
"Interval (in milliseconds) to check for the heart beat between management server nodes", false);
|
||||
final ConfigKey<Integer> HeartbeatThreshold = new ConfigKey<Integer>(Integer.class, "cluster.heartbeat.threshold", "management-server", "150000",
|
||||
"Threshold before self-fence the management server", true);
|
||||
"Threshold (in milliseconds) before self-fence the management server. The threshold should be larger than management.server.stats.interval", true);
|
||||
|
||||
/**
|
||||
* Adds a new packet to the incoming queue.
|
||||
|
||||
@ -758,21 +758,16 @@ public class ClusterManagerImpl extends ManagerBase implements ClusterManager, C
|
||||
}
|
||||
|
||||
switch (msg.getMessageType()) {
|
||||
case nodeAdded: {
|
||||
final List<ManagementServerHostVO> l = msg.getNodes();
|
||||
if (l != null && l.size() > 0) {
|
||||
for (final ManagementServerHostVO mshost : l) {
|
||||
_mshostPeerDao.updatePeerInfo(_mshostId, mshost.getId(), mshost.getRunid(), ManagementServerHost.State.Up);
|
||||
}
|
||||
}
|
||||
}
|
||||
case nodeAdded:
|
||||
break;
|
||||
|
||||
case nodeRemoved: {
|
||||
final List<ManagementServerHostVO> l = msg.getNodes();
|
||||
if (l != null && l.size() > 0) {
|
||||
for (final ManagementServerHostVO mshost : l) {
|
||||
_mshostPeerDao.updatePeerInfo(_mshostId, mshost.getId(), mshost.getRunid(), ManagementServerHost.State.Down);
|
||||
if (mshost.getId() != _mshostId) {
|
||||
_mshostPeerDao.updatePeerInfo(_mshostId, mshost.getId(), mshost.getRunid(), ManagementServerHost.State.Down);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -823,8 +818,9 @@ public class ClusterManagerImpl extends ManagerBase implements ClusterManager, C
|
||||
|
||||
final List<ManagementServerHostVO> downHostList = new ArrayList<ManagementServerHostVO>();
|
||||
for (final ManagementServerHostVO host : inactiveList) {
|
||||
if (!pingManagementNode(host)) {
|
||||
logger.warn("Management node " + host.getId() + " is detected inactive by timestamp and also not pingable");
|
||||
// Check if peer state is Up in the period
|
||||
if (!_mshostPeerDao.isPeerUpState(_mshostId, host.getId(), new Date(cutTime.getTime() - HeartbeatThreshold.value()))) {
|
||||
logger.warn("Management node " + host.getId() + " is detected inactive by timestamp and did not send node status to this node");
|
||||
downHostList.add(host);
|
||||
}
|
||||
}
|
||||
@ -898,6 +894,44 @@ public class ClusterManagerImpl extends ManagerBase implements ClusterManager, C
|
||||
|
||||
final Profiler profilerInvalidatedNodeList = new Profiler();
|
||||
profilerInvalidatedNodeList.start();
|
||||
processInvalidatedNodes(invalidatedNodeList);
|
||||
profilerInvalidatedNodeList.stop();
|
||||
|
||||
final Profiler profilerRemovedList = new Profiler();
|
||||
profilerRemovedList.start();
|
||||
processRemovedNodes(cutTime, removedNodeList);
|
||||
profilerRemovedList.stop();
|
||||
|
||||
final Profiler profilerNewList = new Profiler();
|
||||
profilerNewList.start();
|
||||
processNewNodes(cutTime, currentList);
|
||||
profilerNewList.stop();
|
||||
|
||||
final Profiler profilerInactiveList = new Profiler();
|
||||
profilerInactiveList.start();
|
||||
processInactiveNodes(cutTime);
|
||||
profilerInactiveList.stop();
|
||||
|
||||
profiler.stop();
|
||||
|
||||
logger.debug(String.format("Peer scan is finished. profiler: %s , profilerQueryActiveList: %s, " +
|
||||
", profilerSyncClusterInfo: %s, profilerInvalidatedNodeList: %s, profilerRemovedList: %s," +
|
||||
", profilerNewList: %s, profilerInactiveList: %s",
|
||||
profiler, profilerQueryActiveList, profilerSyncClusterInfo, profilerInvalidatedNodeList, profilerRemovedList,
|
||||
profilerNewList, profilerInactiveList));
|
||||
|
||||
if (profiler.getDurationInMillis() >= HeartbeatInterval.value()) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(String.format("Peer scan takes too long to finish. profiler: %s , profilerQueryActiveList: %s, " +
|
||||
", profilerSyncClusterInfo: %s, profilerInvalidatedNodeList: %s, profilerRemovedList: %s," +
|
||||
", profilerNewList: %s, profilerInactiveList: %s",
|
||||
profiler, profilerQueryActiveList, profilerSyncClusterInfo, profilerInvalidatedNodeList, profilerRemovedList,
|
||||
profilerNewList, profilerInactiveList));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processInvalidatedNodes(List<ManagementServerHostVO> invalidatedNodeList) {
|
||||
// process invalidated node list
|
||||
if (invalidatedNodeList.size() > 0) {
|
||||
for (final ManagementServerHostVO mshost : invalidatedNodeList) {
|
||||
@ -911,16 +945,16 @@ public class ClusterManagerImpl extends ManagerBase implements ClusterManager, C
|
||||
|
||||
queueNotification(new ClusterManagerMessage(ClusterManagerMessage.MessageType.nodeRemoved, invalidatedNodeList));
|
||||
}
|
||||
profilerInvalidatedNodeList.stop();
|
||||
}
|
||||
|
||||
final Profiler profilerRemovedList = new Profiler();
|
||||
profilerRemovedList.start();
|
||||
private void processRemovedNodes(Date cutTime, List<ManagementServerHostVO> removedNodeList) {
|
||||
// process removed node list
|
||||
final Iterator<ManagementServerHostVO> it = removedNodeList.iterator();
|
||||
while (it.hasNext()) {
|
||||
final ManagementServerHostVO mshost = it.next();
|
||||
if (!pingManagementNode(mshost)) {
|
||||
logger.warn("Management node " + mshost.getId() + " is detected inactive by timestamp and also not pingable");
|
||||
// Check if peer state is Up in the period
|
||||
if (!_mshostPeerDao.isPeerUpState(_mshostId, mshost.getId(), new Date(cutTime.getTime() - HeartbeatThreshold.value()))) {
|
||||
logger.warn("Management node " + mshost.getId() + " is detected inactive by timestamp and did not send node status to this node");
|
||||
_activePeers.remove(mshost.getId());
|
||||
try {
|
||||
JmxUtil.unregisterMBean("ClusterManager", "Node " + mshost.getId());
|
||||
@ -928,7 +962,7 @@ public class ClusterManagerImpl extends ManagerBase implements ClusterManager, C
|
||||
logger.warn("Unable to deregiester cluster node from JMX monitoring due to exception " + e.toString());
|
||||
}
|
||||
} else {
|
||||
logger.info("Management node " + mshost.getId() + " is detected inactive by timestamp but is pingable");
|
||||
logger.info("Management node " + mshost.getId() + " is detected inactive by timestamp but sent node status to this node");
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
@ -936,8 +970,9 @@ public class ClusterManagerImpl extends ManagerBase implements ClusterManager, C
|
||||
if (removedNodeList.size() > 0) {
|
||||
queueNotification(new ClusterManagerMessage(ClusterManagerMessage.MessageType.nodeRemoved, removedNodeList));
|
||||
}
|
||||
profilerRemovedList.stop();
|
||||
}
|
||||
|
||||
private void processNewNodes(Date cutTime, List<ManagementServerHostVO> currentList) {
|
||||
final List<ManagementServerHostVO> newNodeList = new ArrayList<ManagementServerHostVO>();
|
||||
for (final ManagementServerHostVO mshost : currentList) {
|
||||
if (!_activePeers.containsKey(mshost.getId())) {
|
||||
@ -959,18 +994,31 @@ public class ClusterManagerImpl extends ManagerBase implements ClusterManager, C
|
||||
if (newNodeList.size() > 0) {
|
||||
queueNotification(new ClusterManagerMessage(ClusterManagerMessage.MessageType.nodeAdded, newNodeList));
|
||||
}
|
||||
}
|
||||
|
||||
profiler.stop();
|
||||
|
||||
if (profiler.getDurationInMillis() >= HeartbeatInterval.value()) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Peer scan takes too long to finish. profiler: " + profiler.toString() + ", profilerQueryActiveList: " +
|
||||
profilerQueryActiveList.toString() + ", profilerSyncClusterInfo: " + profilerSyncClusterInfo.toString() + ", profilerInvalidatedNodeList: " +
|
||||
profilerInvalidatedNodeList.toString() + ", profilerRemovedList: " + profilerRemovedList.toString());
|
||||
private void processInactiveNodes(Date cutTime) {
|
||||
final List<ManagementServerHostVO> inactiveList = _mshostDao.getInactiveList(new Date(cutTime.getTime() - HeartbeatThreshold.value()));
|
||||
if (inactiveList.size() > 0) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info(String.format("Found %s inactive management server node based on timestamp", inactiveList.size()));
|
||||
}
|
||||
for (final ManagementServerHostVO host : inactiveList) {
|
||||
logger.info(String.format("management server node msid: %s, name: %s, service ip: %s, version: %s",
|
||||
host.getMsid(), host.getName(), host.getServiceIP(), host.getVersion()));
|
||||
// Check if any peer state is Up in the period
|
||||
if (ManagementServerHost.State.Up.equals(host.getState()) &&
|
||||
!_mshostPeerDao.isPeerUpState(host.getId(), new Date(cutTime.getTime() - HeartbeatThreshold.value()))) {
|
||||
logger.warn("Management node " + host.getId() + " is detected inactive by timestamp and did not send node status to all other nodes");
|
||||
host.setState(ManagementServerHost.State.Down);
|
||||
_mshostDao.update(host.getId(), host);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
logger.info("No inactive management server node found");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static ManagementServerHostVO getInListById(final Long id, final List<ManagementServerHostVO> l) {
|
||||
for (final ManagementServerHostVO mshost : l) {
|
||||
if (mshost.getId() == id) {
|
||||
|
||||
@ -0,0 +1,177 @@
|
||||
// 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.cluster;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
import org.apache.cloudstack.management.ManagementServerHost;
|
||||
|
||||
@Entity
|
||||
@Table(name = "mshost_peer_view")
|
||||
public class ManagementServerHostPeerJoinVO {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "id")
|
||||
private long id;
|
||||
|
||||
@Column(name = "peer_state")
|
||||
@Enumerated(value = EnumType.STRING)
|
||||
private ManagementServerHost.State peerState;
|
||||
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
@Column(name = "last_update")
|
||||
private Date lastUpdateTime;
|
||||
|
||||
@Column(name = "owner_mshost_id")
|
||||
private long ownerMshostId;
|
||||
|
||||
@Column(name = "owner_mshost_msid")
|
||||
private long ownerMshostMsId;
|
||||
|
||||
@Column(name = "owner_mshost_runid")
|
||||
private long ownerMshostRunId;
|
||||
|
||||
@Column(name = "owner_mshost_name")
|
||||
private String ownerMshostName;
|
||||
|
||||
@Column(name = "owner_mshost_uuid")
|
||||
private String ownerMshostUuid;
|
||||
|
||||
@Column(name = "owner_mshost_state")
|
||||
private String ownerMshostState;
|
||||
|
||||
@Column(name = "owner_mshost_service_ip")
|
||||
private String ownerMshostServiceIp;
|
||||
|
||||
@Column(name = "owner_mshost_service_port")
|
||||
private Integer ownerMshostServicePort;
|
||||
|
||||
@Column(name = "peer_mshost_id")
|
||||
private long peerMshostId;
|
||||
|
||||
@Column(name = "peer_mshost_msid")
|
||||
private long peerMshostMsId;
|
||||
|
||||
@Column(name = "peer_mshost_runid")
|
||||
private long peerMshostRunId;
|
||||
|
||||
@Column(name = "peer_mshost_name")
|
||||
private String peerMshostName;
|
||||
|
||||
@Column(name = "peer_mshost_uuid")
|
||||
private String peerMshostUuid;
|
||||
|
||||
@Column(name = "peer_mshost_state")
|
||||
private String peerMshostState;
|
||||
|
||||
@Column(name = "peer_mshost_service_ip")
|
||||
private String peerMshostServiceIp;
|
||||
|
||||
@Column(name = "peer_mshost_service_port")
|
||||
private Integer peerMshostServicePort;
|
||||
|
||||
public ManagementServerHostPeerJoinVO() {
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public ManagementServerHost.State getPeerState() {
|
||||
return peerState;
|
||||
}
|
||||
|
||||
public Date getLastUpdateTime() {
|
||||
return lastUpdateTime;
|
||||
}
|
||||
|
||||
public long getOwnerMshostId() {
|
||||
return ownerMshostId;
|
||||
}
|
||||
|
||||
public long getOwnerMshostMsId() {
|
||||
return ownerMshostMsId;
|
||||
}
|
||||
|
||||
public long getOwnerMshostRunId() {
|
||||
return ownerMshostRunId;
|
||||
}
|
||||
|
||||
public String getOwnerMshostName() {
|
||||
return ownerMshostName;
|
||||
}
|
||||
|
||||
public String getOwnerMshostUuid() {
|
||||
return ownerMshostUuid;
|
||||
}
|
||||
|
||||
public String getOwnerMshostState() {
|
||||
return ownerMshostState;
|
||||
}
|
||||
|
||||
public String getOwnerMshostServiceIp() {
|
||||
return ownerMshostServiceIp;
|
||||
}
|
||||
|
||||
public Integer getOwnerMshostServicePort() {
|
||||
return ownerMshostServicePort;
|
||||
}
|
||||
|
||||
public long getPeerMshostId() {
|
||||
return peerMshostId;
|
||||
}
|
||||
|
||||
public long getPeerMshostMsId() {
|
||||
return peerMshostMsId;
|
||||
}
|
||||
|
||||
public long getPeerMshostRunId() {
|
||||
return peerMshostRunId;
|
||||
}
|
||||
|
||||
public String getPeerMshostName() {
|
||||
return peerMshostName;
|
||||
}
|
||||
|
||||
public String getPeerMshostUuid() {
|
||||
return peerMshostUuid;
|
||||
}
|
||||
|
||||
public String getPeerMshostState() {
|
||||
return peerMshostState;
|
||||
}
|
||||
|
||||
public String getPeerMshostServiceIp() {
|
||||
return peerMshostServiceIp;
|
||||
}
|
||||
|
||||
public Integer getPeerMshostServicePort() {
|
||||
return peerMshostServicePort;
|
||||
}
|
||||
}
|
||||
@ -130,7 +130,7 @@ public class ManagementServerHostDaoImpl extends GenericDaoBase<ManagementServer
|
||||
try {
|
||||
txn.start();
|
||||
|
||||
pstmt = txn.prepareAutoCloseStatement("update mshost set last_update=?, removed=null, alert_count=0 where id=? and runid=?");
|
||||
pstmt = txn.prepareAutoCloseStatement("update mshost set last_update=?, removed=null, alert_count=0, state='Up' where id=? and runid=?");
|
||||
pstmt.setString(1, DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), lastUpdate));
|
||||
pstmt.setLong(2, id);
|
||||
pstmt.setLong(3, runid);
|
||||
|
||||
@ -20,10 +20,17 @@ import org.apache.cloudstack.management.ManagementServerHost;
|
||||
import com.cloud.cluster.ManagementServerHostPeerVO;
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public interface ManagementServerHostPeerDao extends GenericDao<ManagementServerHostPeerVO, Long> {
|
||||
void clearPeerInfo(long ownerMshost);
|
||||
|
||||
void updatePeerInfo(long ownerMshost, long peerMshost, long peerRunid, ManagementServerHost.State peerState);
|
||||
|
||||
int countStateSeenInPeers(long mshost, long runid, ManagementServerHost.State state);
|
||||
int countStateSeenInPeers(long peerMshost, long runid, ManagementServerHost.State state);
|
||||
|
||||
boolean isPeerUpState(long peerMshost, Date cutTime);
|
||||
|
||||
boolean isPeerUpState(long ownerMshost, long peerMshost, Date cutTime);
|
||||
|
||||
}
|
||||
|
||||
@ -16,10 +16,10 @@
|
||||
// under the License.
|
||||
package com.cloud.cluster.dao;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
|
||||
import org.apache.cloudstack.management.ManagementServerHost;
|
||||
import com.cloud.cluster.ManagementServerHostPeerVO;
|
||||
import com.cloud.utils.db.DB;
|
||||
@ -33,10 +33,12 @@ public class ManagementServerHostPeerDaoImpl extends GenericDaoBase<ManagementSe
|
||||
private final SearchBuilder<ManagementServerHostPeerVO> ClearPeerSearch;
|
||||
private final SearchBuilder<ManagementServerHostPeerVO> FindForUpdateSearch;
|
||||
private final SearchBuilder<ManagementServerHostPeerVO> CountSearch;
|
||||
private final SearchBuilder<ManagementServerHostPeerVO> ActiveSearch;
|
||||
|
||||
public ManagementServerHostPeerDaoImpl() {
|
||||
ClearPeerSearch = createSearchBuilder();
|
||||
ClearPeerSearch.and("ownerMshost", ClearPeerSearch.entity().getOwnerMshost(), SearchCriteria.Op.EQ);
|
||||
ClearPeerSearch.or("peerMshost", ClearPeerSearch.entity().getPeerMshost(), SearchCriteria.Op.EQ);
|
||||
ClearPeerSearch.done();
|
||||
|
||||
FindForUpdateSearch = createSearchBuilder();
|
||||
@ -50,6 +52,13 @@ public class ManagementServerHostPeerDaoImpl extends GenericDaoBase<ManagementSe
|
||||
CountSearch.and("peerRunid", CountSearch.entity().getPeerRunid(), SearchCriteria.Op.EQ);
|
||||
CountSearch.and("peerState", CountSearch.entity().getPeerState(), SearchCriteria.Op.EQ);
|
||||
CountSearch.done();
|
||||
|
||||
ActiveSearch = createSearchBuilder();
|
||||
ActiveSearch.and("ownerMshost", ActiveSearch.entity().getOwnerMshost(), SearchCriteria.Op.EQ);
|
||||
ActiveSearch.and("peerMshost", ActiveSearch.entity().getPeerMshost(), SearchCriteria.Op.EQ);
|
||||
ActiveSearch.and("peerState", ActiveSearch.entity().getPeerState(), SearchCriteria.Op.EQ);
|
||||
ActiveSearch.and("lastUpdateTime", ActiveSearch.entity().getLastUpdateTime(), SearchCriteria.Op.GT);
|
||||
ActiveSearch.done();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -57,6 +66,7 @@ public class ManagementServerHostPeerDaoImpl extends GenericDaoBase<ManagementSe
|
||||
public void clearPeerInfo(long ownerMshost) {
|
||||
SearchCriteria<ManagementServerHostPeerVO> sc = ClearPeerSearch.create();
|
||||
sc.setParameters("ownerMshost", ownerMshost);
|
||||
sc.setParameters("peerMshost", ownerMshost);
|
||||
|
||||
expunge(sc);
|
||||
}
|
||||
@ -71,11 +81,12 @@ public class ManagementServerHostPeerDaoImpl extends GenericDaoBase<ManagementSe
|
||||
SearchCriteria<ManagementServerHostPeerVO> sc = FindForUpdateSearch.create();
|
||||
sc.setParameters("ownerMshost", ownerMshost);
|
||||
sc.setParameters("peerMshost", peerMshost);
|
||||
sc.setParameters("peerRunid", peerRunid);
|
||||
List<ManagementServerHostPeerVO> l = listBy(sc);
|
||||
if (l.size() == 1) {
|
||||
ManagementServerHostPeerVO peer = l.get(0);
|
||||
peer.setPeerRunid(peerRunid);
|
||||
peer.setPeerState(peerState);
|
||||
peer.setLastUpdateTime(new Date());
|
||||
update(peer.getId(), peer);
|
||||
} else {
|
||||
ManagementServerHostPeerVO peer = new ManagementServerHostPeerVO(ownerMshost, peerMshost, peerRunid, peerState);
|
||||
@ -90,13 +101,36 @@ public class ManagementServerHostPeerDaoImpl extends GenericDaoBase<ManagementSe
|
||||
|
||||
@Override
|
||||
@DB
|
||||
public int countStateSeenInPeers(long mshost, long runid, ManagementServerHost.State state) {
|
||||
public int countStateSeenInPeers(long peerMshost, long runid, ManagementServerHost.State state) {
|
||||
SearchCriteria<ManagementServerHostPeerVO> sc = CountSearch.create();
|
||||
sc.setParameters("peerMshost", mshost);
|
||||
sc.setParameters("peerMshost", peerMshost);
|
||||
sc.setParameters("peerRunid", runid);
|
||||
sc.setParameters("peerState", state);
|
||||
|
||||
List<ManagementServerHostPeerVO> l = listBy(sc);
|
||||
return l.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
@DB
|
||||
public boolean isPeerUpState(long peerMshost, Date cutTime) {
|
||||
SearchCriteria<ManagementServerHostPeerVO> sc = ActiveSearch.create();
|
||||
sc.setParameters("peerMshost", peerMshost);
|
||||
sc.setParameters("peerState", ManagementServerHost.State.Up);
|
||||
sc.setParameters("lastUpdateTime", cutTime);
|
||||
|
||||
return listBy(sc).size() > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
@DB
|
||||
public boolean isPeerUpState(long ownerMshost, long peerMshost, Date cutTime) {
|
||||
SearchCriteria<ManagementServerHostPeerVO> sc = ActiveSearch.create();
|
||||
sc.setParameters("ownerMshost", ownerMshost);
|
||||
sc.setParameters("peerMshost", peerMshost);
|
||||
sc.setParameters("peerState", ManagementServerHost.State.Up);
|
||||
sc.setParameters("lastUpdateTime", cutTime);
|
||||
|
||||
return listBy(sc).size() > 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,27 @@
|
||||
// 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.cluster.dao;
|
||||
|
||||
import com.cloud.cluster.ManagementServerHostPeerJoinVO;
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ManagementServerHostPeerJoinDao extends GenericDao<ManagementServerHostPeerJoinVO, Long> {
|
||||
|
||||
List<ManagementServerHostPeerJoinVO> listByOwnerMshostId(long ownerMshostId);
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
// 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.cluster.dao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.cloud.cluster.ManagementServerHostPeerJoinVO;
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
import com.cloud.utils.db.SearchBuilder;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
|
||||
public class ManagementServerHostPeerJoinDaoImpl extends GenericDaoBase<ManagementServerHostPeerJoinVO, Long> implements ManagementServerHostPeerJoinDao {
|
||||
|
||||
private final SearchBuilder<ManagementServerHostPeerJoinVO> AllFieldSearch;
|
||||
|
||||
public ManagementServerHostPeerJoinDaoImpl() {
|
||||
AllFieldSearch = createSearchBuilder();
|
||||
AllFieldSearch.and("ownerMshostId", AllFieldSearch.entity().getOwnerMshostId(), SearchCriteria.Op.EQ);
|
||||
AllFieldSearch.done();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ManagementServerHostPeerJoinVO> listByOwnerMshostId(long ownerMshostId) {
|
||||
SearchCriteria<ManagementServerHostPeerJoinVO> sc = AllFieldSearch.create();
|
||||
sc.setParameters("ownerMshostId", ownerMshostId);
|
||||
return listBy(sc);
|
||||
}
|
||||
}
|
||||
@ -36,7 +36,6 @@ import java.util.stream.Stream;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import com.cloud.cpu.CPU;
|
||||
import org.apache.cloudstack.acl.ControlledEntity;
|
||||
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
|
||||
import org.apache.cloudstack.acl.SecurityChecker;
|
||||
@ -114,6 +113,7 @@ import org.apache.cloudstack.api.response.IpQuarantineResponse;
|
||||
import org.apache.cloudstack.api.response.ListResponse;
|
||||
import org.apache.cloudstack.api.response.ManagementServerResponse;
|
||||
import org.apache.cloudstack.api.response.ObjectStoreResponse;
|
||||
import org.apache.cloudstack.api.response.PeerManagementServerNodeResponse;
|
||||
import org.apache.cloudstack.api.response.ProjectAccountResponse;
|
||||
import org.apache.cloudstack.api.response.ProjectInvitationResponse;
|
||||
import org.apache.cloudstack.api.response.ProjectResponse;
|
||||
@ -214,8 +214,11 @@ import com.cloud.api.query.vo.TemplateJoinVO;
|
||||
import com.cloud.api.query.vo.UserAccountJoinVO;
|
||||
import com.cloud.api.query.vo.UserVmJoinVO;
|
||||
import com.cloud.api.query.vo.VolumeJoinVO;
|
||||
import com.cloud.cluster.ManagementServerHostPeerJoinVO;
|
||||
import com.cloud.cluster.ManagementServerHostVO;
|
||||
import com.cloud.cluster.dao.ManagementServerHostDao;
|
||||
import com.cloud.cluster.dao.ManagementServerHostPeerJoinDao;
|
||||
import com.cloud.cpu.CPU;
|
||||
import com.cloud.dc.ClusterVO;
|
||||
import com.cloud.dc.DataCenter;
|
||||
import com.cloud.dc.DedicatedResourceVO;
|
||||
@ -607,6 +610,9 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
@Inject
|
||||
private ClusterDao clusterDao;
|
||||
|
||||
@Inject
|
||||
private ManagementServerHostPeerJoinDao mshostPeerJoinDao;
|
||||
|
||||
|
||||
private SearchCriteria<ServiceOfferingJoinVO> getMinimumCpuServiceOfferingJoinSearchCriteria(int cpu) {
|
||||
SearchCriteria<ServiceOfferingJoinVO> sc = _srvOfferingJoinDao.createSearchCriteria();
|
||||
@ -5342,7 +5348,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
List<ManagementServerResponse> hostResponses = new ArrayList<>();
|
||||
|
||||
for (ManagementServerJoinVO host : result.first()) {
|
||||
ManagementServerResponse hostResponse = createManagementServerResponse(host);
|
||||
ManagementServerResponse hostResponse = createManagementServerResponse(host, cmd.getPeers());
|
||||
hostResponses.add(hostResponse);
|
||||
}
|
||||
|
||||
@ -5365,7 +5371,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
return managementServerJoinDao.searchAndCount(sc, null);
|
||||
}
|
||||
|
||||
protected ManagementServerResponse createManagementServerResponse(ManagementServerJoinVO mgmt) {
|
||||
protected ManagementServerResponse createManagementServerResponse(ManagementServerJoinVO mgmt, boolean listPeers) {
|
||||
ManagementServerResponse mgmtResponse = new ManagementServerResponse();
|
||||
mgmtResponse.setId(mgmt.getUuid());
|
||||
mgmtResponse.setName(mgmt.getName());
|
||||
@ -5378,10 +5384,34 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
mgmtResponse.setLastServerStop(mgmt.getLastJvmStop());
|
||||
mgmtResponse.setLastBoot(mgmt.getLastSystemBoot());
|
||||
mgmtResponse.setServiceIp(mgmt.getServiceIP());
|
||||
if (listPeers) {
|
||||
List<ManagementServerHostPeerJoinVO> peers = mshostPeerJoinDao.listByOwnerMshostId(mgmt.getId());
|
||||
for (ManagementServerHostPeerJoinVO peer: peers) {
|
||||
mgmtResponse.addPeer(createPeerManagementServerNodeResponse(peer));
|
||||
}
|
||||
}
|
||||
mgmtResponse.setObjectName("managementserver");
|
||||
return mgmtResponse;
|
||||
}
|
||||
|
||||
private PeerManagementServerNodeResponse createPeerManagementServerNodeResponse(ManagementServerHostPeerJoinVO peer) {
|
||||
PeerManagementServerNodeResponse response = new PeerManagementServerNodeResponse();
|
||||
|
||||
response.setState(peer.getPeerState());
|
||||
response.setLastUpdated(peer.getLastUpdateTime());
|
||||
|
||||
response.setPeerId(peer.getPeerMshostUuid());
|
||||
response.setPeerName(peer.getPeerMshostName());
|
||||
response.setPeerMsId(String.valueOf(peer.getPeerMshostMsId()));
|
||||
response.setPeerRunId(String.valueOf(peer.getPeerMshostRunId()));
|
||||
response.setPeerState(peer.getPeerMshostState());
|
||||
response.setPeerServiceIp(peer.getPeerMshostServiceIp());
|
||||
response.setPeerServicePort(String.valueOf(peer.getPeerMshostServicePort()));
|
||||
|
||||
response.setObjectName("peermanagementserver");
|
||||
return response;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RouterHealthCheckResultResponse> listRouterHealthChecks(GetRouterHealthCheckResultsCmd cmd) {
|
||||
logger.info("Executing health check command " + cmd);
|
||||
|
||||
@ -24,6 +24,7 @@ public class ManagementServerHostStatsEntry implements ManagementServerHostStats
|
||||
|
||||
private long managementServerHostId;
|
||||
private String managementServerHostUuid;
|
||||
private long managementServerRunId;
|
||||
|
||||
private Date collectionTime;
|
||||
private long sessions;
|
||||
@ -94,6 +95,15 @@ public class ManagementServerHostStatsEntry implements ManagementServerHostStats
|
||||
this.managementServerHostUuid = managementServerHostUuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getManagementServerRunId() {
|
||||
return managementServerRunId;
|
||||
}
|
||||
|
||||
public void setManagementServerRunId(long managementServerRunId) {
|
||||
this.managementServerRunId = managementServerRunId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getCollectionTime(){
|
||||
return collectionTime;
|
||||
|
||||
@ -95,6 +95,7 @@ import com.cloud.cluster.ClusterServicePdu;
|
||||
import com.cloud.cluster.ManagementServerHostVO;
|
||||
import com.cloud.cluster.ManagementServerStatusVO;
|
||||
import com.cloud.cluster.dao.ManagementServerHostDao;
|
||||
import com.cloud.cluster.dao.ManagementServerHostPeerDao;
|
||||
import com.cloud.cluster.dao.ManagementServerStatusDao;
|
||||
import com.cloud.dc.Vlan.VlanType;
|
||||
import com.cloud.dc.VlanVO;
|
||||
@ -346,6 +347,8 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
|
||||
@Inject
|
||||
private ManagementServerStatusDao managementServerStatusDao;
|
||||
@Inject
|
||||
private ManagementServerHostPeerDao managementServerHostPeerDao;
|
||||
@Inject
|
||||
VirtualMachineManager virtualMachineManager;
|
||||
|
||||
private final ConcurrentHashMap<String, ManagementServerHostStats> managementServerHostStats = new ConcurrentHashMap<>();
|
||||
@ -796,6 +799,7 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
|
||||
logger.trace("Metrics collection start...");
|
||||
newEntry.setManagementServerHostId(mshost.getId());
|
||||
newEntry.setManagementServerHostUuid(mshost.getUuid());
|
||||
newEntry.setManagementServerRunId(mshost.getRunid());
|
||||
newEntry.setDbLocal(isDbLocal());
|
||||
newEntry.setUsageLocal(isUsageLocal());
|
||||
retrieveSession(newEntry);
|
||||
@ -1153,6 +1157,9 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
|
||||
try {
|
||||
hostStatsEntry = gson.fromJson(pdu.getJsonPackage(),new TypeToken<ManagementServerHostStatsEntry>(){}.getType());
|
||||
managementServerHostStats.put(hostStatsEntry.getManagementServerHostUuid(), hostStatsEntry);
|
||||
|
||||
// Update peer state to Up in mshost_peer
|
||||
updatePeerInfo(hostStatsEntry);
|
||||
} catch (JsonParseException e) {
|
||||
logger.error("Exception in decoding of other MS hosts status from : " + pdu.getSourcePeer());
|
||||
if (logger.isDebugEnabled()) {
|
||||
@ -1162,6 +1169,23 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
|
||||
return null;
|
||||
}
|
||||
|
||||
private void updatePeerInfo(ManagementServerHostStatsEntry hostStatsEntry) {
|
||||
// Update msId to id of the management server if msId is same as managementServerNodeId
|
||||
if (msId == managementServerNodeId) {
|
||||
ManagementServerHostVO mgmtServerVo = managementServerHostDao.findByMsid(managementServerNodeId);
|
||||
if (mgmtServerVo != null) {
|
||||
msId = mgmtServerVo.getId();
|
||||
} else {
|
||||
logger.warn(String.format("Cannot find management server with msid [%s]. Therefore, do not update peer info.", managementServerNodeId));
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Update peer state to Up in mshost_peer
|
||||
if (msId != hostStatsEntry.getManagementServerHostId()) {
|
||||
managementServerHostPeerDao.updatePeerInfo(msId, hostStatsEntry.getManagementServerHostId(), hostStatsEntry.getManagementServerRunId(), ManagementServerHost.State.Up);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onManagementNodeJoined(List<? extends ManagementServerHost> nodeList, long selfNodeId) {
|
||||
// do nothing, but wait for the status to come through
|
||||
|
||||
@ -1291,6 +1291,7 @@
|
||||
"label.l3gatewayserviceuuid": "L3 Gateway Service UUID",
|
||||
"label.label": "Label",
|
||||
"label.last.updated": "Last update",
|
||||
"label.lastupdated": "Last update",
|
||||
"label.lastannotated": "Last annotation date",
|
||||
"label.lastheartbeat": "Last heartbeat",
|
||||
"label.lastsuccessfuljob": "Last successful job",
|
||||
@ -1379,6 +1380,7 @@
|
||||
"label.management.ips": "Management IP addresses",
|
||||
"label.management.server": "Management server",
|
||||
"label.management.servers": "Management servers",
|
||||
"label.management.server.peers": "Peers",
|
||||
"label.managementservers": "Number of management servers",
|
||||
"label.matchall": "Match all",
|
||||
"label.max": "Max.",
|
||||
@ -1667,6 +1669,13 @@
|
||||
"label.payload": "Payload",
|
||||
"label.payloadurl": "Payload URL",
|
||||
"label.pcidevice": "GPU",
|
||||
"label.peername": "Management Server",
|
||||
"label.peermsid": "Management Server Node ID",
|
||||
"label.peerrunid": "Process Timestamp",
|
||||
"label.peerserviceip": "Management IP",
|
||||
"label.peerserviceport": "Service Port",
|
||||
"label.peerstate": "Peer State",
|
||||
"label.peerstate.lastupdated": "Peer State Updated Time",
|
||||
"label.pending.jobs": "Pending Jobs",
|
||||
"label.per.account": "Per Account",
|
||||
"label.per.zone": "Per zone",
|
||||
@ -2035,7 +2044,7 @@
|
||||
"label.service.connectivity.distributedroutercapabilitycheckbox": "Distributed router",
|
||||
"label.service.connectivity.regionlevelvpccapabilitycheckbox": "Region level VPC",
|
||||
"label.service.group": "Service group",
|
||||
"label.serviceip": "Service IP",
|
||||
"label.serviceip": "Management IP",
|
||||
"label.service.lb.elasticlbcheckbox": "Elastic LB",
|
||||
"label.service.lb.inlinemodedropdown": "Mode",
|
||||
"label.service.lb.lbisolationdropdown": "LB isolation",
|
||||
@ -2150,6 +2159,7 @@
|
||||
"label.startport": "Start port",
|
||||
"label.startquota": "Quota value",
|
||||
"label.state": "State",
|
||||
"label.state.reported": "Reported State",
|
||||
"label.staticnat": "Static NAT",
|
||||
"label.static": "Static",
|
||||
"label.static.routes": "Static routes",
|
||||
|
||||
@ -43,6 +43,10 @@ export default {
|
||||
name: 'pending.jobs',
|
||||
component: shallowRef(defineAsyncComponent(() => import('@/views/infra/AsyncJobsTab.vue')))
|
||||
},
|
||||
{
|
||||
name: 'management.server.peers',
|
||||
component: shallowRef(defineAsyncComponent(() => import('@/views/infra/ManagementServerPeerTab.vue')))
|
||||
},
|
||||
{
|
||||
name: 'comments',
|
||||
component: shallowRef(defineAsyncComponent(() => import('@/components/view/AnnotationsTab.vue')))
|
||||
|
||||
111
ui/src/views/infra/ManagementServerPeerTab.vue
Normal file
111
ui/src/views/infra/ManagementServerPeerTab.vue
Normal file
@ -0,0 +1,111 @@
|
||||
// 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.
|
||||
|
||||
<template>
|
||||
<a-table
|
||||
class="table"
|
||||
size="small"
|
||||
:columns="columns"
|
||||
:dataSource="managementservers"
|
||||
:rowKey="item => item.id"
|
||||
:pagination="false" >
|
||||
<template #peername="{ text, record }">
|
||||
<router-link :to="{ path: '/managementserver/' + record.peerid }">{{ text }}</router-link>
|
||||
</template>
|
||||
<template #peerserviceip="{ text, record }">
|
||||
<router-link :to="{ path: '/managementserver/' + record.peerid }">{{ text }}</router-link>
|
||||
</template>
|
||||
<template #lastupdated="{ text }">
|
||||
{{ $toLocaleDate(text) }}
|
||||
</template>
|
||||
</a-table>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { api } from '@/api'
|
||||
import Status from '@/components/widgets/Status'
|
||||
|
||||
export default {
|
||||
name: 'ManagementServerPeerTab',
|
||||
components: {
|
||||
Status
|
||||
},
|
||||
props: {
|
||||
resource: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
managementservers: [],
|
||||
columns: [
|
||||
{
|
||||
title: this.$t('label.peername'),
|
||||
dataIndex: 'peername',
|
||||
slots: { customRender: 'peername' }
|
||||
},
|
||||
{
|
||||
title: this.$t('label.peermsid'),
|
||||
dataIndex: 'peermsid'
|
||||
},
|
||||
{
|
||||
title: this.$t('label.peerrunid'),
|
||||
dataIndex: 'peerrunid'
|
||||
},
|
||||
{
|
||||
title: this.$t('label.peerserviceip'),
|
||||
dataIndex: 'peerserviceip',
|
||||
slots: { customRender: 'peerserviceip' }
|
||||
},
|
||||
{
|
||||
title: this.$t('label.peerserviceport'),
|
||||
dataIndex: 'peerserviceport'
|
||||
},
|
||||
{
|
||||
title: this.$t('label.state.reported'),
|
||||
dataIndex: 'state'
|
||||
},
|
||||
{
|
||||
title: this.$t('label.peerstate.lastupdated'),
|
||||
dataIndex: 'lastupdated',
|
||||
slots: { customRender: 'lastupdated' }
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.fetchData()
|
||||
},
|
||||
watch: {
|
||||
resource: function (newItem) {
|
||||
this.fetchData()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
fetchData () {
|
||||
this.managementservers = []
|
||||
api('listManagementServers', {
|
||||
peers: true,
|
||||
id: this.resource.id
|
||||
}).then(json => {
|
||||
this.managementservers = json.listmanagementserversresponse.managementserver?.[0]?.peers || []
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Loading…
x
Reference in New Issue
Block a user