This is an automated email from the ASF dual-hosted git repository.

Pearl1594 pushed a commit to branch netris-improvements
in repository https://gitbox.apache.org/repos/asf/cloudstack.git

commit b66eb66623ee9bfe84e57a1163c1ffa296511e66
Author: Pearl Dsilva <[email protected]>
AuthorDate: Mon Jul 6 09:16:41 2026 -0400

    Add check for vnet name length and cleanup vpc and vnet resources on 
failure of creation of allocation
    
    * Netris - Support NAT, PF for Secondary IP
    
    * Allow PF rules to be correctly created on secondary IP of a VM on netris
    
    * unique static nat names on netris by adding public IP - handle backward 
compatibility
    
    ---------
    
    Co-authored-by: Pearl Dsilva <[email protected]>
    
    * Netris - Support for L2 networks
    
    * Add support for L2 networks in Netris
    
    * remove the need to add connectivity to identify netris provider, remove 
changes to ui and create net offering
    
    * create vpc network and use it for l2 networks
    
    * dont fail if deletion on netris doesnt succeed
    
    * remove connectivity capability
    
    * update vpc name when l2 name is updated
    
    ---------
    
    Co-authored-by: Pearl Dsilva <[email protected]>
    
    * Netris - CKS support
    
    Co-authored-by: Pearl Dsilva <[email protected]>
    
    * Netris - Enable Global Routing Flag for NATTED Dual-Stack VPCs
    
    * Set globalRouting = true, when network offering is NATTED, dual-stack
    
    * update global routing based on routing mode and ip protocol type
    
    ---------
    
    Co-authored-by: Pearl Dsilva <[email protected]>
    Co-authored-by: nvazquez <[email protected]>
    
    * Netris - Fix allocate vnets with the correct account ID so that release 
succeeds on network deletion
    
    * Fix allocate vnets with the correct account ID so that release succeeds 
on network deletion
    
    * add fix for vpc tiers as well
    
    * move entire vnet cleanup logic to trash from shutdown, so that it works 
for all network types for netris
    
    * cleanup vnets when reservation id is null
    
    ---------
    
    Co-authored-by: Pearl Dsilva <[email protected]>
    
    * Netris - Add support to include VPN service for NATTED Netris offerings
    
    * Add support to include VPN service for NATTED Netris offerings
    
    * missing changes of global routing
    
    * Remove extra space
    
    ---------
    
    Co-authored-by: Pearl Dsilva <[email protected]>
    Co-authored-by: nvazquez <[email protected]>
    
    * Netris - Support Redundant Virtual Routers for Netris VPC networks
    
    * Add support for redundant routers for Netris VPC networks
    
    * address comment
    
    * default null network mode to natted for netris
    
    * preventing vpc and ipam creation if already exists
    
    ---------
    
    Co-authored-by: Pearl Dsilva <[email protected]>
    
    * Netris - Enable autoscaling groups for Netris network offerings
    
    * Enable autoscaling groups for Netris network offerings
    
    * Fix UI loading for services when network mode changes for external 
providers and show vm autoscaling always set to true / non-editable for netris 
when LB is selected i.e, natted mode
    
    * Revert removed comment
    
    ---------
    
    Co-authored-by: Pearl Dsilva <[email protected]>
    Co-authored-by: nvazquez <[email protected]>
    
    * merge conflict
    
    * systemvm: fix VPC VPN issue when network id is bigger than 1000 on Netris
    
    * show networks for vnf nic mappings
    
    * Add a check to prevent re-adding existing ACLs
    
    * Add a check to prevent re-adding existing ACLs
    
    * change message compare statement
    
    * Add check for vnet name length and cleanup vpc and vnet resources on 
failure of creation of allocation
    
    * add name length validation to update path
    
    ---------
    
    Co-authored-by: Pearl Dsilva <[email protected]>
    Co-authored-by: nvazquez <[email protected]>
    Co-authored-by: Wei Zhou <[email protected]>
---
 .../resource/NetrisResourceObjectUtils.java        | 12 ++++
 .../cloudstack/service/NetrisApiClientImpl.java    | 66 +++++++++++++++++++---
 2 files changed, 69 insertions(+), 9 deletions(-)

diff --git 
a/plugins/network-elements/netris/src/main/java/org/apache/cloudstack/resource/NetrisResourceObjectUtils.java
 
b/plugins/network-elements/netris/src/main/java/org/apache/cloudstack/resource/NetrisResourceObjectUtils.java
index d67054398f6..5b7b9d8973d 100644
--- 
a/plugins/network-elements/netris/src/main/java/org/apache/cloudstack/resource/NetrisResourceObjectUtils.java
+++ 
b/plugins/network-elements/netris/src/main/java/org/apache/cloudstack/resource/NetrisResourceObjectUtils.java
@@ -16,6 +16,7 @@
 // under the License.
 package org.apache.cloudstack.resource;
 
+import com.cloud.exception.InvalidParameterValueException;
 import com.cloud.offering.NetworkOffering;
 import org.apache.cloudstack.agent.api.NetrisCommand;
 import org.apache.commons.lang3.ArrayUtils;
@@ -24,6 +25,8 @@ import java.util.Objects;
 
 public class NetrisResourceObjectUtils {
 
+    public static final int NETRIS_VNET_NAME_MAX_LENGTH = 50;
+
     public enum NetrisObjectType {
         VPC, IPAM_ALLOCATION, IPAM_SUBNET, VNET, SNAT, STATICNAT, DNAT, 
STATICROUTE, ACL, LB
     }
@@ -102,6 +105,15 @@ public class NetrisResourceObjectUtils {
         return stringBuilder.toString();
     }
 
+    public static void validateNetrisVnetNameLength(String netrisVnetName, 
String networkName) {
+        if (netrisVnetName.length() > NETRIS_VNET_NAME_MAX_LENGTH) {
+            throw new InvalidParameterValueException(
+                    String.format("The resulting Netris vNet name '%s' exceeds 
the maximum allowed length of %d characters (actual: %d). " +
+                            "Please use a shorter network name (current: 
'%s')",
+                            netrisVnetName, NETRIS_VNET_NAME_MAX_LENGTH, 
netrisVnetName.length(), networkName));
+        }
+    }
+
     public static NetworkOffering.NetworkMode 
getNetworkMode(NetworkOffering.NetworkMode mode) {
         return Objects.isNull(mode) ? NetworkOffering.NetworkMode.NATTED : 
mode;
     }
diff --git 
a/plugins/network-elements/netris/src/main/java/org/apache/cloudstack/service/NetrisApiClientImpl.java
 
b/plugins/network-elements/netris/src/main/java/org/apache/cloudstack/service/NetrisApiClientImpl.java
index cb4ed59333b..bc6dd912be5 100644
--- 
a/plugins/network-elements/netris/src/main/java/org/apache/cloudstack/service/NetrisApiClientImpl.java
+++ 
b/plugins/network-elements/netris/src/main/java/org/apache/cloudstack/service/NetrisApiClientImpl.java
@@ -345,8 +345,19 @@ public class NetrisApiClientImpl implements 
NetrisApiClient {
 
         String netrisIpamAllocationName = 
NetrisResourceObjectUtils.retrieveNetrisResourceObjectName(cmd, 
NetrisResourceObjectUtils.NetrisObjectType.IPAM_ALLOCATION, cmd.getCidr());
         String vpcCidr = cmd.getCidr();
-        InlineResponse2004Data createdIpamAllocation = 
createIpamAllocationInternal(netrisIpamAllocationName, vpcCidr, 
createdVpc.getData());
-        return createdIpamAllocation != null;
+        VPCListing vpcListing = createdVpc.getData();
+        InlineResponse2004Data createdIpamAllocation = 
createIpamAllocationInternal(netrisIpamAllocationName, vpcCidr, vpcListing);
+        if (createdIpamAllocation == null) {
+            logger.warn("IPAM Allocation creation failed for VPC {}, rolling 
back VPC", netrisVpcName);
+            try {
+                deleteVpcInternal(vpcListing);
+            } catch (Exception e) {
+                logger.error("Failed to rollback VPC {} after IPAM Allocation 
failure - manual cleanup may be required: {}",
+                        netrisVpcName, e.getMessage());
+            }
+            return false;
+        }
+        return true;
     }
 
     @Override
@@ -1240,8 +1251,13 @@ public class NetrisApiClientImpl implements 
NetrisApiClient {
         }
         String netrisV6Cidr = cmd.getIpv6Cidr();
 
+        VPCListing associatedVpc = null;
+        String netrisSubnetName = null;
+        String netrisV6IpamAllocationName = null;
+        String netrisV6SubnetName = null;
+        boolean createdIpv6Allocation = false;
+
         try {
-            VPCListing associatedVpc;
             if (isL2) {
                 associatedVpc = getOrCreateL2Vpc(cmd);
                 if (associatedVpc == null) {
@@ -1264,19 +1280,22 @@ public class NetrisApiClientImpl implements 
NetrisApiClient {
                 vNetName = String.format("N%s-%s", networkId, networkName);
             }
             String netrisVnetName = 
NetrisResourceObjectUtils.retrieveNetrisResourceObjectName(cmd, 
NetrisResourceObjectUtils.NetrisObjectType.VNET, vNetName);
+            
NetrisResourceObjectUtils.validateNetrisVnetNameLength(netrisVnetName, 
networkName);
 
             if (!isL2) {
-                String netrisSubnetName = 
NetrisResourceObjectUtils.retrieveNetrisResourceObjectName(cmd, 
NetrisResourceObjectUtils.NetrisObjectType.IPAM_SUBNET, 
String.valueOf(cmd.getVpcId()), vnetCidr);
+                netrisSubnetName = 
NetrisResourceObjectUtils.retrieveNetrisResourceObjectName(cmd, 
NetrisResourceObjectUtils.NetrisObjectType.IPAM_SUBNET, 
String.valueOf(cmd.getVpcId()), vnetCidr);
                 createIpamSubnetInternal(netrisSubnetName, vnetCidr, 
SubnetBody.PurposeEnum.COMMON, associatedVpc, ipv4GlobalRouting);
                 if (Objects.nonNull(netrisV6Cidr)) {
-                    String netrisV6IpamAllocationName = 
NetrisResourceObjectUtils.retrieveNetrisResourceObjectName(cmd, 
NetrisResourceObjectUtils.NetrisObjectType.IPAM_ALLOCATION, netrisV6Cidr);
-                    String netrisV6SubnetName = 
NetrisResourceObjectUtils.retrieveNetrisResourceObjectName(cmd, 
NetrisResourceObjectUtils.NetrisObjectType.IPAM_SUBNET, 
String.valueOf(cmd.getVpcId()), netrisV6Cidr);
+                    netrisV6IpamAllocationName = 
NetrisResourceObjectUtils.retrieveNetrisResourceObjectName(cmd, 
NetrisResourceObjectUtils.NetrisObjectType.IPAM_ALLOCATION, netrisV6Cidr);
+                    netrisV6SubnetName = 
NetrisResourceObjectUtils.retrieveNetrisResourceObjectName(cmd, 
NetrisResourceObjectUtils.NetrisObjectType.IPAM_SUBNET, 
String.valueOf(cmd.getVpcId()), netrisV6Cidr);
                     BigDecimal ipamAllocationId = 
getIpamAllocationIdByPrefixAndVpc(netrisV6Cidr, associatedVpc);
                     if (ipamAllocationId == null) {
-                        InlineResponse2004Data createdIpamAllocation = 
createIpamAllocationInternal(netrisV6IpamAllocationName, netrisV6Cidr, 
associatedVpc);
-                        if (Objects.isNull(createdIpamAllocation)) {
+                        InlineResponse2004Data createdIpamAllocationData = 
createIpamAllocationInternal(netrisV6IpamAllocationName, netrisV6Cidr, 
associatedVpc);
+                        if (Objects.isNull(createdIpamAllocationData)) {
+                            rollbackVnetResources(associatedVpc, 
netrisSubnetName, null, null, networkName);
                             throw new 
CloudRuntimeException(String.format("Failed to create Netris IPAM Allocation %s 
for VPC %s", netrisV6IpamAllocationName, associatedVpc.getName()));
                         }
+                        createdIpv6Allocation = true;
                     }
                     createIpamSubnetInternal(netrisV6SubnetName, netrisV6Cidr, 
SubnetBody.PurposeEnum.COMMON, associatedVpc, ipv6GlobalRouting);
                 }
@@ -1287,9 +1306,17 @@ public class NetrisApiClientImpl implements 
NetrisApiClient {
             if (vnetResponse == null || !vnetResponse.isIsSuccess()) {
                 String reason = vnetResponse == null ? "Empty response" : 
"Operation failed on Netris";
                 logger.debug("The Netris vNet creation {} failed: {}", 
vNetName, reason);
+                if (!isL2) {
+                    rollbackVnetResources(associatedVpc, netrisSubnetName, 
netrisV6SubnetName,
+                            createdIpv6Allocation ? netrisV6IpamAllocationName 
: null, networkName);
+                }
                 return false;
             }
-        } catch (ApiException e) {
+        } catch (Exception e) {
+            if (!isL2 && associatedVpc != null) {
+                rollbackVnetResources(associatedVpc, netrisSubnetName, 
netrisV6SubnetName,
+                        createdIpv6Allocation ? netrisV6IpamAllocationName : 
null, networkName);
+            }
             throw new CloudRuntimeException(String.format("Failed to create 
Netris vNet %s", networkName), e);
         }
         return true;
@@ -1324,6 +1351,7 @@ public class NetrisApiClientImpl implements 
NetrisApiClient {
         String netrisVnetName = 
NetrisResourceObjectUtils.retrieveNetrisResourceObjectName(cmd, 
NetrisResourceObjectUtils.NetrisObjectType.VNET, vNetName) ;
         String prevNetrisVnetName = 
NetrisResourceObjectUtils.retrieveNetrisResourceObjectName(cmd, 
NetrisResourceObjectUtils.NetrisObjectType.VNET, prevVnetName) ;
 
+        NetrisResourceObjectUtils.validateNetrisVnetNameLength(netrisVnetName, 
networkName);
         VnetResAddBody response = updateVnetInternal(associatedVpc, 
netrisVnetName, prevNetrisVnetName);
         if (response == null || !response.isIsSuccess()) {
             String reason = response == null ? "Empty response" : "Operation 
failed on Netris";
@@ -1958,6 +1986,26 @@ public class NetrisApiClientImpl implements 
NetrisApiClient {
         }
     }
 
+    private void rollbackVnetResources(VPCListing associatedVpc, String 
ipv4SubnetName, String ipv6SubnetName,
+                                       String ipv6AllocationName, String 
networkName) {
+        logger.warn("Rolling back Netris resources created for network {}", 
networkName);
+        FilterByVpc vpcFilter = new FilterByVpc();
+        vpcFilter.add(associatedVpc.getId());
+        try {
+            if (ipv6SubnetName != null) {
+                deleteSubnetInternal(vpcFilter, null, ipv6SubnetName);
+            }
+            if (ipv6AllocationName != null) {
+                deleteVpcIpamAllocationInternal(associatedVpc, 
ipv6AllocationName);
+            }
+            if (ipv4SubnetName != null) {
+                deleteSubnetInternal(vpcFilter, null, ipv4SubnetName);
+            }
+        } catch (Exception e) {
+            logger.error("Failed to rollback Netris resources for network {} - 
manual cleanup may be required: {}", networkName, e.getMessage());
+        }
+    }
+
     private SubnetBody getIpamSubnetBody(VPCListing vpc, 
SubnetBody.PurposeEnum purpose, String subnetName, String subnetPrefix, Boolean 
isGlobalRouting) {
         SubnetBody subnetBody = new SubnetBody();
         subnetBody.setName(subnetName);

Reply via email to