package org.zstack.kvm;
import org.springframework.beans.factory.annotation.Autowired;
import org.zstack.core.cloudbus.CloudBus;
import org.zstack.core.cloudbus.CloudBusCallBack;
import org.zstack.core.errorcode.ErrorFacade;
import org.zstack.core.timeout.ApiTimeoutManager;
import org.zstack.header.core.Completion;
import org.zstack.header.core.workflow.Flow;
import org.zstack.header.core.workflow.FlowTrigger;
import org.zstack.header.core.workflow.NoRollbackFlow;
import org.zstack.header.errorcode.ErrorCode;
import org.zstack.header.host.HostConstant;
import org.zstack.header.host.HypervisorType;
import org.zstack.header.message.MessageReply;
import org.zstack.kvm.KVMAgentCommands.ApplySecurityGroupRuleCmd;
import org.zstack.kvm.KVMAgentCommands.ApplySecurityGroupRuleResponse;
import org.zstack.kvm.KVMAgentCommands.CleanupUnusedRulesOnHostResponse;
import org.zstack.kvm.KVMAgentCommands.RefreshAllRulesOnHostCmd;
import org.zstack.network.securitygroup.*;
import org.zstack.utils.Utils;
import org.zstack.utils.logging.CLogger;
import static org.zstack.core.Platform.operr;
import java.util.Map;
public class KVMSecurityGroupBackend implements SecurityGroupHypervisorBackend, KVMHostConnectExtensionPoint {
private static CLogger logger = Utils.getLogger(KVMSecurityGroupBackend.class);
public static final String SECURITY_GROUP_APPLY_RULE_PATH = "/securitygroup/applyrules";
public static final String SECURITY_GROUP_REFRESH_RULE_ON_HOST_PATH = "/securitygroup/refreshrulesonhost";
public static final String SECURITY_GROUP_CLEANUP_UNUSED_RULE_ON_HOST_PATH = "/securitygroup/cleanupunusedrules";
@Autowired
private CloudBus bus;
@Autowired
private ErrorFacade errf;
@Autowired
private ApiTimeoutManager timeoutMgr;
private void incrementallyApplyRules(final HostRuleTO hto, final Completion complete) {
ApplySecurityGroupRuleCmd cmd = new ApplySecurityGroupRuleCmd();
cmd.setRuleTOs(hto.getRules());
KVMHostAsyncHttpCallMsg msg = new KVMHostAsyncHttpCallMsg();
msg.setHostUuid(hto.getHostUuid());
msg.setPath(SECURITY_GROUP_APPLY_RULE_PATH);
msg.setCommand(cmd);
msg.setCommandTimeout(timeoutMgr.getTimeout(cmd.getClass(), "5m"));
bus.makeTargetServiceIdByResourceUuid(msg, HostConstant.SERVICE_ID, hto.getHostUuid());
bus.send(msg, new CloudBusCallBack(complete) {
@Override
public void run(MessageReply reply) {
if (!reply.isSuccess()) {
complete.fail(reply.getError());
return;
}
KVMHostAsyncHttpCallReply hreply = reply.castReply();
ApplySecurityGroupRuleResponse rsp = hreply.toResponse(ApplySecurityGroupRuleResponse.class);
if (!rsp.isSuccess()) {
ErrorCode err = operr("failed to apply rules of security group rules to kvm host[uuid:%s], because %s", hto.getHostUuid(), rsp.getError());
complete.fail(err);
return;
}
String info = String.format("successfully applied rules of security group rules to kvm host[uuid:%s]", hto.getHostUuid());
logger.debug(info);
complete.success();
}
});
}
private void reApplyAllRulesOnHost(final HostRuleTO hto, final Completion complete) {
RefreshAllRulesOnHostCmd cmd = new RefreshAllRulesOnHostCmd();
cmd.setRuleTOs(hto.getRules());
KVMHostAsyncHttpCallMsg msg = new KVMHostAsyncHttpCallMsg();
msg.setHostUuid(hto.getHostUuid());
msg.setPath(SECURITY_GROUP_REFRESH_RULE_ON_HOST_PATH);
msg.setCommand(cmd);
msg.setCommandTimeout(timeoutMgr.getTimeout(cmd.getClass(), "5m"));
msg.setNoStatusCheck(true);
bus.makeTargetServiceIdByResourceUuid(msg, HostConstant.SERVICE_ID, hto.getHostUuid());
bus.send(msg, new CloudBusCallBack(complete) {
@Override
public void run(MessageReply reply) {
if (!reply.isSuccess()) {
complete.fail(reply.getError());
return;
}
KVMHostAsyncHttpCallReply hreply = reply.castReply();
ApplySecurityGroupRuleResponse rsp = hreply.toResponse(ApplySecurityGroupRuleResponse.class);
if (!rsp.isSuccess()) {
ErrorCode err = operr("failed to apply rules of security group rules to kvm host[uuid:%s], because %s", hto.getHostUuid(), rsp.getError());
complete.fail(err);
return;
}
String info = String.format("successfully applied rules of security group rules to kvm host[uuid:%s]", hto.getHostUuid());
logger.debug(info);
complete.success();
}
});
}
@Override
public void applyRules(final HostRuleTO hto, final Completion complete) {
if (!hto.isRefreshHost()) {
incrementallyApplyRules(hto, complete);
} else {
reApplyAllRulesOnHost(hto, complete);
}
}
@Override
public void cleanUpUnusedRuleOnHost(String hostUuid, final Completion completion) {
KVMAgentCommands.CleanupUnusedRulesOnHostCmd cmd = new KVMAgentCommands.CleanupUnusedRulesOnHostCmd();
KVMHostAsyncHttpCallMsg msg = new KVMHostAsyncHttpCallMsg();
msg.setHostUuid(hostUuid);
msg.setCommand(cmd);
msg.setCommandTimeout(timeoutMgr.getTimeout(cmd.getClass(), "5m"));
msg.setPath(SECURITY_GROUP_CLEANUP_UNUSED_RULE_ON_HOST_PATH);
bus.makeTargetServiceIdByResourceUuid(msg, HostConstant.SERVICE_ID, hostUuid);
bus.send(msg, new CloudBusCallBack(completion) {
@Override
public void run(MessageReply reply) {
if (!reply.isSuccess()) {
completion.fail(reply.getError());
return;
}
KVMHostAsyncHttpCallReply hreply = reply.castReply();
CleanupUnusedRulesOnHostResponse rsp = hreply.toResponse(CleanupUnusedRulesOnHostResponse.class);
if (!rsp.isSuccess()) {
completion.fail(operr(rsp.getError()));
return;
}
completion.success();
}
});
}
@Override
public HypervisorType getSecurityGroupBackendHypervisorType() {
return HypervisorType.valueOf(KVMConstant.KVM_HYPERVISOR_TYPE);
}
@Override
public Flow createKvmHostConnectingFlow(final KVMHostConnectedContext context) {
return new NoRollbackFlow() {
String __name__ = "refresh-security-group-on-host";
@Override
public void run(FlowTrigger trigger, Map data) {
RefreshSecurityGroupRulesOnHostMsg msg = new RefreshSecurityGroupRulesOnHostMsg();
msg.setHostUuid(context.getInventory().getUuid());
bus.makeLocalServiceId(msg, SecurityGroupConstant.SERVICE_ID);
bus.send(msg);
trigger.next();
}
};
}
}