package org.zstack.test.virtualrouter;
import junit.framework.Assert;
import org.springframework.beans.factory.annotation.Autowire;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;
import org.zstack.appliancevm.ApplianceVmFirewallRuleTO;
import org.zstack.core.db.DatabaseFacade;
import org.zstack.core.db.SimpleQuery;
import org.zstack.core.db.SimpleQuery.Op;
import org.zstack.header.vm.VmNicVO;
import org.zstack.header.vm.VmNicVO_;
import org.zstack.network.service.portforwarding.PortForwardingRuleInventory;
import org.zstack.network.service.vip.VipVO;
import org.zstack.network.service.virtualrouter.portforwarding.PortForwardingRuleTO;
import org.zstack.simulator.appliancevm.ApplianceVmSimulatorConfig;
import org.zstack.utils.CollectionUtils;
import org.zstack.utils.RangeSet.Range;
import org.zstack.utils.Utils;
import org.zstack.utils.function.Function;
import org.zstack.utils.gson.JSONObjectUtil;
import org.zstack.utils.logging.CLogger;
import java.util.Collection;
import java.util.List;
@Configurable(preConstruction = true, autowire = Autowire.BY_TYPE)
public class PortForwardingRuleTestValidator {
private static final CLogger logger = Utils.getLogger(PortForwardingRuleTestValidator.class);
@Autowired
private DatabaseFacade dbf;
public boolean compare(PortForwardingRuleTO to, PortForwardingRuleInventory inv) {
SimpleQuery<VmNicVO> q = dbf.createQuery(VmNicVO.class);
q.select(VmNicVO_.ip);
q.add(VmNicVO_.uuid, Op.EQ, inv.getVmNicUuid());
String privateIp = q.findValue();
boolean ret;
if (to.getAllowedCidr() == null && inv.getAllowedCidr() == null) {
ret = (to.getPrivateIp().equals(privateIp)
&& to.getPrivatePortEnd() == inv.getPrivatePortEnd() && to.getPrivatePortStart() == inv.getPrivatePortStart()
&& to.getProtocolType().equals(inv.getProtocolType())
&& to.getVipPortStart() == inv.getVipPortStart() && to.getVipPortStart() == inv.getVipPortStart());
} else {
ret = (to.getAllowedCidr().equals(inv.getAllowedCidr()) && to.getPrivateIp().equals(privateIp)
&& to.getPrivatePortEnd() == inv.getPrivatePortEnd() && to.getPrivatePortStart() == inv.getPrivatePortStart()
&& to.getProtocolType().equals(inv.getProtocolType())
&& to.getVipPortStart() == inv.getVipPortStart() && to.getVipPortStart() == inv.getVipPortStart());
}
if (!ret) {
logger.warn(String.format("port forwarding rule mismatching:\n" +
"expected: %s\n" +
"actual: %s\n", JSONObjectUtil.toJsonString(to), JSONObjectUtil.toJsonString(inv)));
}
return ret;
}
public void validate(List<PortForwardingRuleTO> actual, Collection<PortForwardingRuleInventory> expected) {
for (PortForwardingRuleInventory e : expected) {
boolean has = false;
for (PortForwardingRuleTO a : actual) {
if (compare(a, e)) {
has = true;
}
}
if (!has) {
logger.warn(String.format("can not find expected rule:\n%s, actual dump:\n%s", JSONObjectUtil.toJsonString(e), JSONObjectUtil.toJsonString(actual)));
}
Assert.assertTrue(has);
}
}
private ApplianceVmFirewallRuleTO findFirewall(final ApplianceVmSimulatorConfig config, final PortForwardingRuleInventory rule) {
final VipVO vip = dbf.findByUuid(rule.getVipUuid(), VipVO.class);
return CollectionUtils.find(config.firewallRules, new Function<ApplianceVmFirewallRuleTO, ApplianceVmFirewallRuleTO>() {
@Override
public ApplianceVmFirewallRuleTO call(ApplianceVmFirewallRuleTO arg) {
String toIdentity = String.format("%s-%s-%s-%s-%s", arg.getStartPort(), arg.getEndPort(), arg.getProtocol().toLowerCase(), arg.getAllowCidr(), arg.getDestIp());
String ruleIdentity = String.format("%s-%s-%s-%s-%s", rule.getVipPortStart(), rule.getVipPortEnd(), rule.getProtocolType().toLowerCase(), rule.getAllowedCidr(), vip == null ? null : vip.getIp());
if (!toIdentity.equals(ruleIdentity)) {
return null;
}
Range r1 = new Range(Long.valueOf(arg.getStartPort()), Long.valueOf(arg.getEndPort()));
Range r2 = new Range(Long.valueOf(rule.getVipPortStart()), Long.valueOf(rule.getVipPortEnd()));
return r1.isOverlap(r2) ? arg : null;
}
});
}
public void noFirewall(ApplianceVmSimulatorConfig config, final PortForwardingRuleInventory rule) {
ApplianceVmFirewallRuleTO to = findFirewall(config, rule);
Assert.assertNull(to);
}
public void hasFirewall(ApplianceVmSimulatorConfig config, final PortForwardingRuleInventory rule) {
ApplianceVmFirewallRuleTO to = findFirewall(config, rule);
Assert.assertNotNull(to);
}
}