diff --git a/compute/src/main/java/org/zstack/compute/host/HostBase.java b/compute/src/main/java/org/zstack/compute/host/HostBase.java index 919d92631fc..3787541a39d 100755 --- a/compute/src/main/java/org/zstack/compute/host/HostBase.java +++ b/compute/src/main/java/org/zstack/compute/host/HostBase.java @@ -955,7 +955,7 @@ private void handle(final PingHostMsg msg) { thdf.chainSubmit(new ChainTask(msg) { @Override public String getSyncSignature() { - return "do-ping-host"; + return String.format("do-ping-host-%s", msg.getHostUuid()); } @Override @@ -979,13 +979,9 @@ public void fail(ErrorCode errorCode) { @Override public String getName() { - return String.format("do-ping-host-%s", msg.getHostUuid()); + return getSyncSignature(); } - @Override - protected int getSyncLevel() { - return HostGlobalConfig.HOST_TRACK_PARALLELISM_DEGREE.value(Integer.class); - } }); } diff --git a/conf/globalConfig/host.xml b/conf/globalConfig/host.xml index ac15a50e580..c31bcbdb7e7 100755 --- a/conf/globalConfig/host.xml +++ b/conf/globalConfig/host.xml @@ -24,7 +24,7 @@ host ping.parallelismDegree - The max hosts management server sends ping command to host in parallel + The max hosts management server sends ping command to host in parallel. With per-host sync signature, this now controls per-host parallelism (one host does not block another). 100 java.lang.Integer diff --git a/test/src/test/groovy/org/zstack/test/integration/kvm/host/KVMPingCase.groovy b/test/src/test/groovy/org/zstack/test/integration/kvm/host/KVMPingCase.groovy index 1709790ab08..3fb55ec2b00 100755 --- a/test/src/test/groovy/org/zstack/test/integration/kvm/host/KVMPingCase.groovy +++ b/test/src/test/groovy/org/zstack/test/integration/kvm/host/KVMPingCase.groovy @@ -24,6 +24,7 @@ import org.zstack.testlib.SubCase import org.zstack.utils.FieldUtils import org.zstack.utils.gson.JSONObjectUtil +import java.util.concurrent.CountDownLatch import java.util.concurrent.TimeUnit class KVMPingCase extends SubCase { @@ -460,6 +461,50 @@ class KVMPingCase extends SubCase { } } + void testDifferentHostPingsNotBlocked() { + canDoReconnectFunc = { HostReconnectTask.CanDoAnswer.Ready } + + HostInventory kvm1 = env.inventoryByName("kvm1") + HostInventory kvm2 = env.inventoryByName("kvm2") + + waitHostConnected(kvm1.uuid) + waitHostConnected(kvm2.uuid) + + // Set parallelism to 1 so the test proves per-host isolation: + // old code (shared do-ping-host + level=1) → kvm2 blocked by kvm1 + // new code (per-host do-ping-host- + level=1) → kvm2 unblocked + HostGlobalConfig.HOST_TRACK_PARALLELISM_DEGREE.updateValue(1) + + CountDownLatch blockKvm1 = new CountDownLatch(1) + CountDownLatch kvm2Pinged = new CountDownLatch(1) + + env.simulator(KVMConstant.KVM_PING_PATH) { HttpEntity e, EnvSpec espec -> + KVMAgentCommands.PingCmd cmd = JSONObjectUtil.toObject(e.getBody(), KVMAgentCommands.PingCmd.class) + def rsp = new KVMAgentCommands.PingResponse() + + if (cmd.hostUuid == kvm1.uuid) { + blockKvm1.await(30, TimeUnit.SECONDS) + } + + if (cmd.hostUuid == kvm2.uuid) { + kvm2Pinged.countDown() + } + + rsp.hostUuid = cmd.hostUuid + return rsp + } + + try { + assert kvm2Pinged.await(30, TimeUnit.SECONDS) + } finally { + blockKvm1.countDown() + env.cleanSimulatorHandlers() + HostGlobalConfig.HOST_TRACK_PARALLELISM_DEGREE.updateValue(100) + recoverHostToConnected(kvm1.uuid) + recoverHostToConnected(kvm2.uuid) + } + } + @Override void test() { bus = bean(CloudBus.class) @@ -490,6 +535,7 @@ class KVMPingCase extends SubCase { testHostReconnectAfterPingFailure() testContinuePingIfHostNoReconnect() testNoPingIfHostNotReadyToReconnect() + testDifferentHostPingsNotBlocked() testManagementNodeReadyConnectAllHost() testPingConnectingHost()