package org.zstack.network.service.virtualrouter;
import org.springframework.beans.factory.annotation.Autowired;
import org.zstack.core.cloudbus.CloudBusCallBack;
import org.zstack.core.cloudbus.ResourceDestinationMaker;
import org.zstack.core.config.GlobalConfig;
import org.zstack.core.config.GlobalConfigUpdateExtensionPoint;
import org.zstack.core.db.DatabaseFacade;
import org.zstack.core.db.SimpleQuery;
import org.zstack.core.tacker.PingTracker;
import org.zstack.core.thread.AsyncThread;
import org.zstack.header.managementnode.ManagementNodeChangeListener;
import org.zstack.header.managementnode.ManagementNodeReadyExtensionPoint;
import org.zstack.header.message.MessageReply;
import org.zstack.header.message.NeedReplyMessage;
import org.zstack.header.vm.VmInstanceConstant;
import org.zstack.header.vm.VmInstanceState;
import org.zstack.utils.CollectionUtils;
import org.zstack.utils.Utils;
import org.zstack.utils.function.Function;
import org.zstack.utils.logging.CLogger;
import java.util.List;
/**
* Created by frank on 6/29/2015.
*/
public class VirtualRouterPingTracker extends PingTracker implements ManagementNodeChangeListener, ManagementNodeReadyExtensionPoint {
private final static CLogger logger = Utils.getLogger(VirtualRouterPingTracker.class);
@Autowired
private DatabaseFacade dbf;
@Autowired
private ResourceDestinationMaker destinationMaker;
public String getResourceName() {
return "virtual router";
}
@Override
public NeedReplyMessage getPingMessage(String resUuid) {
PingVirtualRouterVmMsg msg = new PingVirtualRouterVmMsg();
msg.setVirtualRouterVmUuid(resUuid);
bus.makeTargetServiceIdByResourceUuid(msg, VmInstanceConstant.SERVICE_ID, resUuid);
return msg;
}
@Override
public int getPingInterval() {
return VirtualRouterGlobalConfig.PING_INTERVAL.value(Integer.class);
}
@Override
public int getParallelismDegree() {
return VirtualRouterGlobalConfig.PING_PARALLELISM_DEGREE.value(Integer.class);
}
@Override
public void handleReply(final String resourceUuid, MessageReply reply) {
if (!reply.isSuccess()) {
logger.warn(String.format("[Virtual Router VM Tracker]: unable to ping the virtual router vm[uuid: %s], %s", resourceUuid, reply.getError()));
return;
}
PingVirtualRouterVmReply pr = reply.castReply();
if (!pr.isDoReconnect() || pr.isConnected()) {
return;
}
logger.debug(String.format("[Virtual Router VM Tracker]: the virtual router vm[uuid:%s] is detected a reconnect is needed, issuing it...", resourceUuid));
ReconnectVirtualRouterVmMsg msg = new ReconnectVirtualRouterVmMsg();
msg.setVirtualRouterVmUuid(resourceUuid);
bus.makeTargetServiceIdByResourceUuid(msg, VmInstanceConstant.SERVICE_ID, resourceUuid);
bus.send(msg, new CloudBusCallBack(null) {
@Override
public void run(MessageReply reply) {
if (!reply.isSuccess()) {
logger.warn(String.format("[Virtual Router VM Tracker]: failed to reconnect the virtual router vm[uuid:%s], %s", resourceUuid, reply.getError()));
} else {
logger.debug(String.format("[Virtual Router VM Tracker]: successfully reconnect the virtual router vm[uuid:%s]", resourceUuid));
}
}
});
}
private void trackOurs() {
SimpleQuery<VirtualRouterVmVO> q = dbf.createQuery(VirtualRouterVmVO.class);
q.select(VirtualRouterVmVO_.uuid);
List<String> vrUuids = q.listValue();
List<String> toTrack = CollectionUtils.transformToList(vrUuids, new Function<String, String>() {
@Override
public String call(String arg) {
return destinationMaker.isManagedByUs(arg) ? arg : null;
}
});
untrackAll();
track(toTrack);
}
@Override
public void nodeJoin(String nodeId) {
trackOurs();
}
@Override
public void nodeLeft(String nodeId) {
trackOurs();
}
@Override
public void iAmDead(String nodeId) {
}
@Override
public void iJoin(String nodeId) {
}
@Override
protected void startHook() {
VirtualRouterGlobalConfig.PING_INTERVAL.installUpdateExtension(new GlobalConfigUpdateExtensionPoint() {
@Override
public void updateGlobalConfig(GlobalConfig oldConfig, GlobalConfig newConfig) {
pingIntervalChanged();
}
});
}
@Override
@AsyncThread
public void managementNodeReady() {
trackOurs();
}
}