package org.zstack.compute.host;
import org.springframework.beans.factory.annotation.Autowired;
import org.zstack.core.cloudbus.CloudBus;
import org.zstack.core.db.DatabaseFacade;
import org.zstack.core.db.Q;
import org.zstack.core.db.SimpleQuery;
import org.zstack.core.db.SimpleQuery.Op;
import org.zstack.core.errorcode.ErrorFacade;
import org.zstack.header.apimediator.StopRoutingException;
import org.zstack.header.errorcode.SysErrors;
import org.zstack.header.apimediator.ApiMessageInterceptionException;
import org.zstack.header.apimediator.ApiMessageInterceptor;
import org.zstack.header.host.*;
import org.zstack.header.message.APIMessage;
import org.zstack.utils.network.NetworkUtils;
import static org.zstack.core.Platform.argerr;
import static org.zstack.core.Platform.operr;
/**
* Created with IntelliJ IDEA.
* User: frank
* Time: 3:48 PM
* To change this template use File | Settings | File Templates.
*/
public class HostApiInterceptor implements ApiMessageInterceptor {
@Autowired
private CloudBus bus;
@Autowired
private ErrorFacade errf;
@Autowired
private DatabaseFacade dbf;
private void setServiceId(APIMessage msg) {
if (msg instanceof HostMessage) {
HostMessage hmsg = (HostMessage)msg;
bus.makeTargetServiceIdByResourceUuid(msg, HostConstant.SERVICE_ID, hmsg.getHostUuid());
}
}
@Override
public APIMessage intercept(APIMessage msg) throws ApiMessageInterceptionException {
setServiceId(msg);
if (msg instanceof APIAddHostMsg) {
validate((APIAddHostMsg) msg);
} else if (msg instanceof APIUpdateHostMsg) {
validate((APIUpdateHostMsg) msg);
} else if (msg instanceof APIDeleteHostMsg) {
validate((APIDeleteHostMsg) msg);
} else if (msg instanceof APIChangeHostStateMsg){
validate((APIChangeHostStateMsg) msg);
} else if (msg instanceof APIReconnectHostMsg){
validate((APIReconnectHostMsg) msg);
}
return msg;
}
private void validate(APIDeleteHostMsg msg) {
if (!dbf.isExist(msg.getUuid(), HostVO.class)) {
APIDeleteHostEvent evt = new APIDeleteHostEvent(msg.getId());
bus.publish(evt);
throw new StopRoutingException();
}
}
private void validate(APIUpdateHostMsg msg) {
if (msg.getManagementIp() != null) {
SimpleQuery<HostVO> q = dbf.createQuery(HostVO.class);
q.add(HostVO_.managementIp, Op.EQ, msg.getManagementIp());
if (q.isExists()) {
throw new ApiMessageInterceptionException(argerr("there has been a host having managementIp[%s]", msg.getManagementIp()));
}
}
HostStatus hostStatus = Q.New(HostVO.class)
.select(HostVO_.status)
.eq(HostVO_.uuid,msg.getHostUuid())
.findValue();
if (hostStatus == HostStatus.Connecting){
throw new ApiMessageInterceptionException(
operr("can not update host[uuid:%s]which is connecting or creating, please wait.", msg.getHostUuid()));
}
}
private void validate(APIReconnectHostMsg msg) {
HostStatus hostStatus = Q.New(HostVO.class)
.select(HostVO_.status)
.eq(HostVO_.uuid,msg.getHostUuid())
.findValue();
if (hostStatus == HostStatus.Connecting){
throw new ApiMessageInterceptionException(
operr("can not reconnect host[uuid:%s]which is connecting or creating, please wait", msg.getHostUuid()));
}
}
private void validate(APIAddHostMsg msg) {
if (!NetworkUtils.isIpv4Address(msg.getManagementIp()) && !NetworkUtils.isHostname(msg.getManagementIp())) {
throw new ApiMessageInterceptionException(argerr("managementIp[%s] is neither an IPv4 address nor a valid hostname", msg.getManagementIp()));
}
SimpleQuery<HostVO> q = dbf.createQuery(HostVO.class);
q.add(HostVO_.managementIp, Op.EQ, msg.getManagementIp());
if (q.isExists()) {
throw new ApiMessageInterceptionException(argerr("there has been a host having managementIp[%s]", msg.getManagementIp()));
}
}
private void validate(APIChangeHostStateMsg msg){
HostStatus hostStatus = Q.New(HostVO.class)
.select(HostVO_.status)
.eq(HostVO_.uuid,msg.getHostUuid())
.findValue();
if (hostStatus == HostStatus.Connecting && msg.getStateEvent().equals(HostStateEvent.maintain.toString())){
throw new ApiMessageInterceptionException(operr("can not maintain host[uuid:%s]which is connecting", msg.getHostUuid()));
}
}
}