diff --git a/network/src/main/java/org/zstack/network/l2/L2NetworkApiInterceptor.java b/network/src/main/java/org/zstack/network/l2/L2NetworkApiInterceptor.java index fdb12a36f6b..cf16ae5fb71 100755 --- a/network/src/main/java/org/zstack/network/l2/L2NetworkApiInterceptor.java +++ b/network/src/main/java/org/zstack/network/l2/L2NetworkApiInterceptor.java @@ -146,9 +146,25 @@ private void validate(APIChangeL2NetworkVlanIdMsg msg) { throw new ApiMessageInterceptionException(argerr(ORG_ZSTACK_NETWORK_L2_10015, "cannot change vlan for l2Network[uuid:%s]" + " because this l2Network is isolated", l2.getUuid())); } + String targetType = StringUtils.trimToNull(msg.getType()); + msg.setType(targetType); + // When type is not specified (or blank), default to the current network type. + if (targetType == null) { + targetType = l2.getType(); + msg.setType(targetType); + } + + boolean targetIsVlan = L2NetworkConstant.L2_VLAN_NETWORK_TYPE.equals(targetType); + boolean targetIsNoVlan = L2NetworkConstant.L2_NO_VLAN_NETWORK_TYPE.equals(targetType); + boolean targetIsGeneve = L2NetworkConstant.L2_GENEVE_NETWORK_TYPE.equals(targetType); + if (!targetIsVlan && !targetIsNoVlan && !targetIsGeneve) { + throw new ApiMessageInterceptionException(argerr(ORG_ZSTACK_NETWORK_L2_10011, + "unsupported l2Network type[%s] for ChangeL2NetworkVlanId", targetType)); + } + String sdnControllerUuid = L2NetworkSystemTags.L2_NETWORK_SDN_CONTROLLER_UUID .getTokenByResourceUuid(msg.getL2NetworkUuid(), L2NetworkSystemTags.L2_NETWORK_SDN_CONTROLLER_UUID_TOKEN); - if (msg.getType().equals(L2NetworkConstant.L2_VLAN_NETWORK_TYPE)) { + if (targetIsVlan) { if (msg.getVlan() == null) { throw new ApiMessageInterceptionException(argerr(ORG_ZSTACK_NETWORK_L2_10016, "vlan is required for " + "ChangeL2NetworkVlanId with type[%s]", msg.getType())); @@ -159,7 +175,9 @@ private void validate(APIChangeL2NetworkVlanIdMsg msg) { List attachedClusters = l2.getAttachedClusterRefs().stream() .map(L2NetworkClusterRefVO::getClusterUuid).collect(Collectors.toList()); List l2s; - if (sdnControllerUuid == null) { + if (attachedClusters.isEmpty()) { + l2s = java.util.Collections.emptyList(); + } else if (sdnControllerUuid == null) { l2s = SQL.New("select l2" + " from L2NetworkVO l2, L2NetworkClusterRefVO ref" + " where l2.uuid = ref.l2NetworkUuid" + @@ -192,7 +210,7 @@ private void validate(APIChangeL2NetworkVlanIdMsg msg) { throw new ApiMessageInterceptionException(argerr(ORG_ZSTACK_NETWORK_L2_10018, "There has been a l2Network attached to cluster with virtual network id[%s] and physical interface[%s]. Failed to change L2 network[uuid:%s]", msg.getVlan(), l2.getPhysicalInterface(), l2.getUuid())); } - } else if (msg.getType().equals(L2NetworkConstant.L2_NO_VLAN_NETWORK_TYPE)) { + } else if (targetIsNoVlan) { if (msg.getVlan() != null) { throw new ApiMessageInterceptionException(argerr(ORG_ZSTACK_NETWORK_L2_10019, "vlan is not allowed for " + "ChangeL2NetworkVlanId with type[%s]", msg.getType())); @@ -200,7 +218,9 @@ private void validate(APIChangeL2NetworkVlanIdMsg msg) { List attachedClusters = l2.getAttachedClusterRefs().stream() .map(L2NetworkClusterRefVO::getClusterUuid).collect(Collectors.toList()); List l2s; - if (sdnControllerUuid != null) { + if (attachedClusters.isEmpty()) { + l2s = java.util.Collections.emptyList(); + } else if (sdnControllerUuid != null) { l2s = SQL.New("select l2" + " from L2NetworkVO l2, L2NetworkClusterRefVO ref, SystemTagVO tag" + " where l2.uuid = ref.l2NetworkUuid" + diff --git a/network/src/main/java/org/zstack/network/l2/L2NetworkExtensionPointEmitter.java b/network/src/main/java/org/zstack/network/l2/L2NetworkExtensionPointEmitter.java index fa864bafaf2..b1eecae4d5e 100755 --- a/network/src/main/java/org/zstack/network/l2/L2NetworkExtensionPointEmitter.java +++ b/network/src/main/java/org/zstack/network/l2/L2NetworkExtensionPointEmitter.java @@ -53,6 +53,20 @@ public void run(L2NetworkDeleteExtensionPoint arg) { }); } + public void beforeUpdate(final L2NetworkInventory inv) { + for (L2NetworkUpdateExtensionPoint ext : updateExtensions) { + try { + ext.beforeChangeL2NetworkVlanId(inv); + } catch (RuntimeException e) { + // propagate validation failures and other runtime exceptions immediately + throw e; + } catch (Exception e) { + logger.warn(String.format("unhandled exception in L2NetworkUpdateExtensionPoint.beforeChangeL2NetworkVlanId of %s", + ext.getClass().getCanonicalName()), e); + } + } + } + public void afterUpdate(final L2NetworkInventory inv) { CollectionUtils.safeForEach(updateExtensions, arg -> arg.afterChangeL2NetworkVlanId(inv)); } diff --git a/network/src/main/java/org/zstack/network/l2/L2NetworkHostHelper.java b/network/src/main/java/org/zstack/network/l2/L2NetworkHostHelper.java index a612b3847c5..0136649f4bf 100644 --- a/network/src/main/java/org/zstack/network/l2/L2NetworkHostHelper.java +++ b/network/src/main/java/org/zstack/network/l2/L2NetworkHostHelper.java @@ -15,7 +15,6 @@ import java.util.HashSet; import java.util.List; import java.util.Set; -import java.util.stream.Collectors; import static java.util.Arrays.asList; @@ -87,6 +86,10 @@ public L2NetworkHostRefInventory getL2NetworkHostRef(String l2NetworkUuid, Strin } public static Set getHostsByL2NetworkAttachedCluster(L2NetworkInventory l2NetworkInventory) { + if (l2NetworkInventory.getAttachedClusterUuids() == null || l2NetworkInventory.getAttachedClusterUuids().isEmpty()) { + return new HashSet<>(); + } + return new HashSet<>(Q.New(HostVO.class) .in(HostVO_.clusterUuid, l2NetworkInventory.getAttachedClusterUuids()) .notIn(HostVO_.state,asList(HostState.PreMaintenance, HostState.Maintenance)) diff --git a/plugin/vxlan/src/main/java/org/zstack/network/l2/vxlan/vxlanNetworkPool/VxlanNetworkCheckerImpl.java b/plugin/vxlan/src/main/java/org/zstack/network/l2/vxlan/vxlanNetworkPool/VxlanNetworkCheckerImpl.java index d3a46ed8d78..9f9e9848714 100644 --- a/plugin/vxlan/src/main/java/org/zstack/network/l2/vxlan/vxlanNetworkPool/VxlanNetworkCheckerImpl.java +++ b/plugin/vxlan/src/main/java/org/zstack/network/l2/vxlan/vxlanNetworkPool/VxlanNetworkCheckerImpl.java @@ -38,7 +38,7 @@ public APIMessage intercept(APIMessage msg) throws ApiMessageInterceptionExcepti } private void validate(APIChangeL2NetworkVlanIdMsg msg) { - if (!msg.getType().equals(VxlanNetworkConstant.VXLAN_NETWORK_TYPE)){ + if (!VxlanNetworkConstant.VXLAN_NETWORK_TYPE.equals(msg.getType())){ return; } if (!NetworkUtils.isValidVni(msg.getVlan())) { 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 733c53d6688..a13b90c7d48 100644 --- a/utils/src/main/java/org/zstack/utils/clouderrorcode/CloudOperationsErrorCode.java +++ b/utils/src/main/java/org/zstack/utils/clouderrorcode/CloudOperationsErrorCode.java @@ -11950,6 +11950,15 @@ public class CloudOperationsErrorCode { public static final String ORG_ZSTACK_NETWORK_ZNS_10009 = "ORG_ZSTACK_NETWORK_ZNS_10009"; + // ZNS error-code semantic mapping: + // 10010 unsupported API for ZNS controller + // 10011 ZNS L2 only supports L3BasicNetwork + // 10012 duplicate ZNS L2NoVlan creation under same controller + // 10013 invalid ZNS L2 target type in change-vlan flow + // 10014 Geneve type can only change VNI, not L2 type + // 10015 cannot switch to Geneve / cannot move NIC across ZNS controllers + // 10016 duplicate Geneve VNI under same controller + // 10017 non-ZNS L2 cannot change to Geneve type public static final String ORG_ZSTACK_NETWORK_ZNS_10010 = "ORG_ZSTACK_NETWORK_ZNS_10010"; public static final String ORG_ZSTACK_NETWORK_ZNS_10011 = "ORG_ZSTACK_NETWORK_ZNS_10011"; @@ -11962,6 +11971,10 @@ public class CloudOperationsErrorCode { public static final String ORG_ZSTACK_NETWORK_ZNS_10015 = "ORG_ZSTACK_NETWORK_ZNS_10015"; + public static final String ORG_ZSTACK_NETWORK_ZNS_10016 = "ORG_ZSTACK_NETWORK_ZNS_10016"; + + public static final String ORG_ZSTACK_NETWORK_ZNS_10017 = "ORG_ZSTACK_NETWORK_ZNS_10017"; + public static final String ORG_ZSTACK_PREMIUM_EXTERNALSERVICE_MARKETPLACE_10000 = "ORG_ZSTACK_PREMIUM_EXTERNALSERVICE_MARKETPLACE_10000"; public static final String ORG_ZSTACK_ALIYUN_NAS_STORAGE_PRIMARY_IMAGESTORE_10000 = "ORG_ZSTACK_ALIYUN_NAS_STORAGE_PRIMARY_IMAGESTORE_10000";