package org.zstack.test.virtualrouter; import org.junit.Before; import org.junit.Test; import org.zstack.core.CoreGlobalProperty; import org.zstack.core.cloudbus.CloudBus; import org.zstack.core.componentloader.ComponentLoader; import org.zstack.core.db.DatabaseFacade; import org.zstack.core.thread.SyncTask; import org.zstack.core.thread.SyncThread; import org.zstack.core.thread.ThreadFacade; import org.zstack.core.workflow.SimpleFlowChain; import org.zstack.core.workflow.WorkFlowStatistic; import org.zstack.header.configuration.InstanceOfferingInventory; import org.zstack.header.identity.SessionInventory; import org.zstack.header.image.ImageInventory; import org.zstack.header.image.ImageVO; import org.zstack.header.network.l3.L3NetworkInventory; import org.zstack.header.rest.HttpCallStatistic; import org.zstack.header.rest.RESTFacade; import org.zstack.header.vm.VmInstanceInventory; import org.zstack.network.service.portforwarding.PortForwardingProtocolType; import org.zstack.network.service.portforwarding.PortForwardingRuleInventory; import org.zstack.network.service.vip.VipInventory; import org.zstack.simulator.SimulatorGlobalProperty; import org.zstack.simulator.kvm.KVMSimulatorConfig; import org.zstack.simulator.virtualrouter.VirtualRouterSimulatorConfig; import org.zstack.test.*; import org.zstack.test.deployer.Deployer; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import static org.zstack.utils.StringDSL.ln; public class TestVirtualRouterPortForwarding1000Vm { Deployer deployer; Api api; ComponentLoader loader; CloudBus bus; DatabaseFacade dbf; SessionInventory session; VirtualRouterSimulatorConfig vconfig; KVMSimulatorConfig kconfig; ThreadFacade thdf; RESTFacade restf; int total = 1000; int syncLevel = 150; int timeout = 600; int ruleNum = 5000; CountDownLatch ruleLatch = new CountDownLatch(ruleNum); List<Long> timeCost = new ArrayList<Long>(ruleNum); List<Long> vipCost = new ArrayList<Long>(ruleNum); List<Long> createCost = new ArrayList<Long>(ruleNum); final List<String> vmNicUuids = new ArrayList<String>(total); @Before public void setUp() throws Exception { DBUtil.reDeployDB(); WebBeanConstructor con = new WebBeanConstructor(); deployer = new Deployer("deployerXml/virtualRouter/TestPortForwarding1000Vm.xml", con); deployer.addSpringConfig("VirtualRouter.xml"); deployer.addSpringConfig("VirtualRouterSimulator.xml"); deployer.addSpringConfig("KVMRelated.xml"); deployer.addSpringConfig("PortForwarding.xml"); deployer.addSpringConfig("vip.xml"); deployer.build(); api = deployer.getApi(); loader = deployer.getComponentLoader(); vconfig = loader.getComponent(VirtualRouterSimulatorConfig.class); kconfig = loader.getComponent(KVMSimulatorConfig.class); bus = loader.getComponent(CloudBus.class); dbf = loader.getComponent(DatabaseFacade.class); thdf = loader.getComponent(ThreadFacade.class); restf = loader.getComponent(RESTFacade.class); session = api.loginAsAdmin(); SimulatorGlobalProperty.NOT_CACHE_AGENT_COMMAND = true; } @SyncThread(level = 1000) private void createRule(L3NetworkInventory pub, L3NetworkInventory guest, String vmNicUuid, int port) throws ApiSenderException { try { api.setTimeout(600); long s = System.currentTimeMillis(); VipInventory vip = api.acquireIp(pub.getUuid()); long s1 = System.currentTimeMillis(); vipCost.add(s1 - s); PortForwardingRuleInventory rule = new PortForwardingRuleInventory(); rule.setVipUuid(vip.getUuid()); rule.setName("pf"); rule.setVipPortStart(port); rule.setVipPortEnd(port); rule.setPrivatePortStart(port); rule.setPrivatePortEnd(port); rule.setProtocolType(PortForwardingProtocolType.TCP.toString()); rule = api.createPortForwardingRuleByFullConfig(rule); long s2 = System.currentTimeMillis(); createCost.add(s2 - s1); api.attachPortForwardingRule(rule.getUuid(), vmNicUuid); timeCost.add(System.currentTimeMillis() - s2); } finally { ruleLatch.countDown(); } } @Test public void test() throws ApiSenderException, InterruptedException { CoreGlobalProperty.VM_TRACER_ON = false; final L3NetworkInventory guestL3 = deployer.l3Networks.get("TestL3Network1"); L3NetworkInventory pubL3 = deployer.l3Networks.get("MgmtNetwork"); final ImageInventory img = deployer.images.get("TestImage"); ImageVO imgvo = dbf.findByUuid(img.getUuid(), ImageVO.class); imgvo.setSize(1); dbf.update(imgvo); final InstanceOfferingInventory ioinv = deployer.instanceOfferings.get("TestInstanceOffering"); final CountDownLatch latch = new CountDownLatch(total); for (int i = 0; i < total; i++) { final int finalI = i; thdf.syncSubmit(new SyncTask<Object>() { @Override public String getSyncSignature() { return "creating-vm"; } @Override public int getSyncLevel() { return syncLevel; } @Override public String getName() { return getSyncSignature(); } @Override public Object call() throws Exception { try { VmCreator creator = new VmCreator(api); creator.addL3Network(guestL3.getUuid()); creator.instanceOfferingUuid = ioinv.getUuid(); creator.imageUuid = img.getUuid(); creator.name = "vm-" + finalI; creator.timeout = (int) TimeUnit.MINUTES.toSeconds(10); VmInstanceInventory vm = creator.create(); synchronized (vmNicUuids) { vmNicUuids.add(vm.getVmNics().get(0).getUuid()); } } finally { latch.countDown(); } return null; } }); } latch.await(timeout, TimeUnit.MINUTES); CoreGlobalProperty.PROFILER_WORKFLOW = true; CoreGlobalProperty.PROFILER_HTTP_CALL = true; SimulatorGlobalProperty.NOT_CACHE_AGENT_COMMAND = true; long start = System.currentTimeMillis(); long rulePerVm = ruleNum / total; System.out.println(String.format("start creating port forwarding rule, total: %s, rule per vm: %s", ruleNum, rulePerVm)); for (int j = 0; j < total; j++) { String nicUuid = vmNicUuids.get(j); for (int i = 0; i < rulePerVm; i++) { createRule(pubL3, guestL3, nicUuid, i); } } ruleLatch.await(timeout, TimeUnit.MINUTES); long end = System.currentTimeMillis(); long min = 0; long max = 0; long avg = 0; long total = 0; for (long t : vipCost) { min = Math.min(t, min); max = Math.max(t, max); total += t; } avg = total / vipCost.size(); System.out.println(ln( "create vip cost:", "total time: {0}", "max: {1}", "min: {2}", "avg: {3}" ).format( TimeUnit.MILLISECONDS.toSeconds(end - start), TimeUnit.MILLISECONDS.toSeconds(max), TimeUnit.MILLISECONDS.toSeconds(min), TimeUnit.MILLISECONDS.toSeconds(avg) )); min = 0; max = 0; avg = 0; total = 0; for (long t : createCost) { min = Math.min(t, min); max = Math.max(t, max); total += t; } avg = total / createCost.size(); System.out.println(ln( "create pf cost:", "total time: {0}", "max: {1}", "min: {2}", "avg: {3}" ).format( TimeUnit.MILLISECONDS.toSeconds(end - start), TimeUnit.MILLISECONDS.toSeconds(max), TimeUnit.MILLISECONDS.toSeconds(min), TimeUnit.MILLISECONDS.toSeconds(avg) )); min = 0; max = 0; avg = 0; total = 0; for (long t : timeCost) { min = Math.min(t, min); max = Math.max(t, max); total += t; } avg = total / timeCost.size(); System.out.println(ln( "attach pf cost:", "total time: {0}", "max: {1}", "min: {2}", "avg: {3}" ).format( TimeUnit.MILLISECONDS.toSeconds(end - start), TimeUnit.MILLISECONDS.toSeconds(max), TimeUnit.MILLISECONDS.toSeconds(min), TimeUnit.MILLISECONDS.toSeconds(avg) )); List<WorkFlowStatistic> stats = new ArrayList<WorkFlowStatistic>(); stats.addAll(SimpleFlowChain.getStatistics().values()); Collections.sort(stats, new Comparator<WorkFlowStatistic>() { @Override public int compare(WorkFlowStatistic o1, WorkFlowStatistic o2) { return (int) (o2.getTotalTime() - o1.getTotalTime()); } }); for (WorkFlowStatistic stat : stats) { System.out.println(stat.toString()); } System.out.println(); List<HttpCallStatistic> hstats = new ArrayList<HttpCallStatistic>(); hstats.addAll(restf.getStatistics().values()); Collections.sort(hstats, new Comparator<HttpCallStatistic>() { @Override public int compare(HttpCallStatistic o1, HttpCallStatistic o2) { return (int) (o2.getTotalTime() - o1.getTotalTime()); } }); for (HttpCallStatistic stat : hstats) { System.out.println(stat.toString()); } } }