package org.zstack.network.service.virtualrouter.portforwarding;
import org.springframework.beans.factory.annotation.Autowire;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.beans.factory.annotation.Qualifier;
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.workflow.Flow;
import org.zstack.header.core.workflow.FlowRollback;
import org.zstack.header.core.workflow.FlowTrigger;
import org.zstack.header.errorcode.ErrorCode;
import org.zstack.header.message.MessageReply;
import org.zstack.header.vm.VmInstanceConstant;
import org.zstack.network.service.virtualrouter.*;
import org.zstack.network.service.virtualrouter.VirtualRouterCommands.CreatePortForwardingRuleRsp;
import org.zstack.network.service.virtualrouter.VirtualRouterCommands.RevokePortForwardingRuleRsp;
import org.zstack.utils.Utils;
import org.zstack.utils.gson.JSONObjectUtil;
import org.zstack.utils.logging.CLogger;
import static org.zstack.core.Platform.operr;
import java.util.Arrays;
import java.util.Map;
@Configurable(preConstruction = true, autowire = Autowire.BY_TYPE)
public class ApplyPortforwardingRuleOnVirtualRouterVmFlow implements Flow {
private static final CLogger logger = Utils.getLogger(ApplyPortforwardingRuleOnVirtualRouterVmFlow.class);
@Autowired
protected VirtualRouterManager vrMgr;
@Autowired
@Qualifier("VirtualRouterPortForwardingBackend")
protected VirtualRouterPortForwardingBackend backend;
@Autowired
private CloudBus bus;
@Autowired
private ErrorFacade errf;
@Autowired
private ApiTimeoutManager apiTimeoutManager;
private final static String VR_APPLY_PORT_FORWARDING_RULE_SUCCESS = "ApplyPortForwardingRuleSuccess";
@Override
public void run(final FlowTrigger chain, final Map data) {
final PortForwardingRuleTO to = (PortForwardingRuleTO) data.get(VirtualRouterConstant.VR_PORT_FORWARDING_RULE);
final VirtualRouterVmInventory vr = (VirtualRouterVmInventory) data.get(VirtualRouterConstant.VR_RESULT_VM);
VirtualRouterCommands.CreatePortForwardingRuleCmd cmd = new VirtualRouterCommands.CreatePortForwardingRuleCmd();
cmd.setRules(Arrays.asList(to));
VirtualRouterAsyncHttpCallMsg msg = new VirtualRouterAsyncHttpCallMsg();
msg.setVmInstanceUuid(vr.getUuid());
msg.setCommand(cmd);
msg.setCommandTimeout(apiTimeoutManager.getTimeout(cmd.getClass(), "30m"));
msg.setPath(VirtualRouterConstant.VR_CREATE_PORT_FORWARDING);
msg.setCheckStatus(true);
bus.makeTargetServiceIdByResourceUuid(msg, VmInstanceConstant.SERVICE_ID, vr.getUuid());
bus.send(msg, new CloudBusCallBack(chain) {
@Override
public void run(MessageReply reply) {
if (!reply.isSuccess()) {
chain.fail(reply.getError());
return;
}
VirtualRouterAsyncHttpCallReply re = reply.castReply();
CreatePortForwardingRuleRsp ret = re.toResponse(CreatePortForwardingRuleRsp.class);
if (ret.isSuccess()) {
String info = String
.format("successfully create port forwarding rule[vip ip: %s, private ip: %s, vip start port: %s, vip end port: %s, private start port: %s, private end port: %s]",
to.getVipIp(), to.getPrivateIp(), to.getVipPortStart(), to.getVipPortEnd(),
to.getPrivatePortStart(), to.getPrivatePortEnd());
logger.debug(info);
data.put(VR_APPLY_PORT_FORWARDING_RULE_SUCCESS, Boolean.TRUE);
chain.next();
} else {
ErrorCode err = operr("failed to create port forwarding rule[vip ip: %s, private ip: %s, vip start port: %s, vip end port: %s, private start port: %s, private end port: %s], because %s",
to.getVipIp(), to.getPrivateIp(), to.getVipPortStart(), to.getVipPortEnd(),
to.getPrivatePortStart(), to.getPrivatePortEnd(), ret.getError());
chain.fail(err);
}
}
});
}
@Override
public void rollback(final FlowRollback chain, Map data) {
if (data.get(VR_APPLY_PORT_FORWARDING_RULE_SUCCESS) != null) {
final PortForwardingRuleTO to = (PortForwardingRuleTO) data.get(VirtualRouterConstant.VR_PORT_FORWARDING_RULE);
final VirtualRouterVmInventory vr = (VirtualRouterVmInventory) data.get(VirtualRouterConstant.VR_RESULT_VM);
VirtualRouterCommands.RevokePortForwardingRuleCmd cmd = new VirtualRouterCommands.RevokePortForwardingRuleCmd();
cmd.setRules(Arrays.asList(to));
VirtualRouterAsyncHttpCallMsg msg = new VirtualRouterAsyncHttpCallMsg();
msg.setCheckStatus(true);
msg.setPath(VirtualRouterConstant.VR_REVOKE_PORT_FORWARDING);
msg.setCommand(cmd);
msg.setCommandTimeout(apiTimeoutManager.getTimeout(cmd.getClass(), "30m"));
msg.setVmInstanceUuid(vr.getUuid());
bus.makeTargetServiceIdByResourceUuid(msg, VmInstanceConstant.SERVICE_ID, vr.getUuid());
bus.send(msg, new CloudBusCallBack(chain) {
@Override
public void run(MessageReply reply) {
if (!reply.isSuccess()) {
String err = String.format("failed to revoke port forwarding rules %s, because %s", JSONObjectUtil.toJsonString(to), reply.getError());
logger.warn(err);
//TODO GC
} else {
VirtualRouterAsyncHttpCallReply re = reply.castReply();
RevokePortForwardingRuleRsp ret = re.toResponse(RevokePortForwardingRuleRsp.class);
if (ret.isSuccess()) {
String info = String.format("successfully revoke port forwarding rules: %s", JSONObjectUtil.toJsonString(to));
logger.debug(info);
} else {
String err = String.format("failed to revoke port forwarding rules %, because %s", JSONObjectUtil.toJsonString(to), ret.getError());
logger.warn(err);
//TODO GC
}
}
chain.rollback();
}
});
} else {
chain.rollback();
}
}
}