diff --git a/plugin/sdnController/src/main/java/org/zstack/sdnController/SdnControllerApiInterceptor.java b/plugin/sdnController/src/main/java/org/zstack/sdnController/SdnControllerApiInterceptor.java index 97840150a1e..fa0f9c1932d 100644 --- a/plugin/sdnController/src/main/java/org/zstack/sdnController/SdnControllerApiInterceptor.java +++ b/plugin/sdnController/src/main/java/org/zstack/sdnController/SdnControllerApiInterceptor.java @@ -87,6 +87,8 @@ public APIMessage intercept(APIMessage msg) throws ApiMessageInterceptionExcepti validate((APIPullSdnControllerTenantMsg) msg); } else if (msg instanceof APIChangeSdnControllerMsg) { validate((APIChangeSdnControllerMsg) msg); + } else if (msg instanceof APIRemoveSdnControllerMsg) { + validate((APIRemoveSdnControllerMsg) msg); } setServiceId(msg); @@ -311,6 +313,17 @@ private boolean isOverlappedVlanRange(int start, int end, Integer startVlan, Int (start <= startVlan && end >= endVlan); } + private void validate(APIRemoveSdnControllerMsg msg) { + long poolCount = Q.New(HardwareL2VxlanNetworkPoolVO.class) + .eq(HardwareL2VxlanNetworkPoolVO_.sdnControllerUuid, msg.getUuid()) + .count(); + if (poolCount > 0) { + throw new ApiMessageInterceptionException(argerr(ORG_ZSTACK_SDNCONTROLLER_10031, + "could not remove sdn controller[uuid:%s] because it still has %d L2 vxlan network pool(s) attached. Please detach them first", + msg.getUuid(), poolCount)); + } + } + private void validate(APIChangeSdnControllerMsg msg) { if (msg.getVlanRanges() != null && !msg.getVlanRanges().isEmpty()) { validateVlanRanges(msg.getVlanRanges()); diff --git a/test/src/test/groovy/org/zstack/test/integration/network/sdnController/HardwareVxlanCase.groovy b/test/src/test/groovy/org/zstack/test/integration/network/sdnController/HardwareVxlanCase.groovy index d5f0c01eb14..1cebbf68020 100644 --- a/test/src/test/groovy/org/zstack/test/integration/network/sdnController/HardwareVxlanCase.groovy +++ b/test/src/test/groovy/org/zstack/test/integration/network/sdnController/HardwareVxlanCase.groovy @@ -41,6 +41,11 @@ class HardwareVxlanCase extends SubCase { @Override void clean() { + // ZSTAC-80186: delete pools created in createEnv() before env.delete() + // removes the SDN controller (which now validates no attached pools) + queryL2VxlanNetworkPool {}.each { pool -> + deleteL2Network { uuid = pool.uuid } + } env.delete() } diff --git a/utils/src/main/java/org/zstack/utils/clouderrorcode/CloudOperationsErrorCode.java b/utils/src/main/java/org/zstack/utils/clouderrorcode/CloudOperationsErrorCode.java index a0f09d4f1e9..f3a60d4978a 100644 --- a/utils/src/main/java/org/zstack/utils/clouderrorcode/CloudOperationsErrorCode.java +++ b/utils/src/main/java/org/zstack/utils/clouderrorcode/CloudOperationsErrorCode.java @@ -15264,6 +15264,8 @@ public class CloudOperationsErrorCode { public static final String ORG_ZSTACK_SDNCONTROLLER_10030 = "ORG_ZSTACK_SDNCONTROLLER_10030"; + public static final String ORG_ZSTACK_SDNCONTROLLER_10031 = "ORG_ZSTACK_SDNCONTROLLER_10031"; + public static final String ORG_ZSTACK_TEST_INTEGRATION_PREMIUM_ZSV_SNAPSHOT_10000 = "ORG_ZSTACK_TEST_INTEGRATION_PREMIUM_ZSV_SNAPSHOT_10000"; public static final String ORG_ZSTACK_TEST_INTEGRATION_PREMIUM_ZSV_SNAPSHOT_10001 = "ORG_ZSTACK_TEST_INTEGRATION_PREMIUM_ZSV_SNAPSHOT_10001";