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

sureshanaparti pushed a commit to branch 4.22
in repository https://gitbox.apache.org/repos/asf/cloudstack.git


The following commit(s) were added to refs/heads/4.22 by this push:
     new 05c59630e0a fix: LB Creation avoid 404 API errors due to non-needed 
patches (#12835)
05c59630e0a is described below

commit 05c59630e0ae0fb3e7df8b15ff00af0ae005197a
Author: Daniil Zhyliaiev <[email protected]>
AuthorDate: Thu Apr 16 11:28:20 2026 +0300

    fix: LB Creation avoid 404 API errors due to non-needed patches (#12835)
---
 .../apache/cloudstack/service/NsxApiClient.java    |  65 ++++-
 .../cloudstack/service/NsxApiClientTest.java       | 311 +++++++++++++++++++++
 2 files changed, 370 insertions(+), 6 deletions(-)

diff --git 
a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxApiClient.java
 
b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxApiClient.java
index 7ad27c4a635..868417f1d60 100644
--- 
a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxApiClient.java
+++ 
b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxApiClient.java
@@ -83,6 +83,7 @@ import com.vmware.vapi.internal.protocol.RestProtocol;
 import 
com.vmware.vapi.internal.protocol.client.rest.authn.BasicAuthenticationAppender;
 import com.vmware.vapi.protocol.HttpConfiguration;
 import com.vmware.vapi.std.errors.Error;
+import com.vmware.vapi.std.errors.NotFound;
 import org.apache.cloudstack.resource.NsxLoadBalancerMember;
 import org.apache.cloudstack.resource.NsxNetworkRule;
 import org.apache.cloudstack.utils.NsxControllerUtils;
@@ -96,9 +97,11 @@ import java.util.List;
 import java.util.Locale;
 import java.util.Objects;
 import java.util.Optional;
+import java.util.Set;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 
+import static java.util.stream.Collectors.toSet;
 import static 
org.apache.cloudstack.utils.NsxControllerUtils.getServerPoolMemberName;
 import static org.apache.cloudstack.utils.NsxControllerUtils.getServerPoolName;
 import static org.apache.cloudstack.utils.NsxControllerUtils.getServiceName;
@@ -656,9 +659,20 @@ public class NsxApiClient {
     public void createNsxLbServerPool(List<NsxLoadBalancerMember> memberList, 
String tier1GatewayName, String lbServerPoolName,
                                       String algorithm, String privatePort, 
String protocol) {
         try {
-            String activeMonitorPath = 
getLbActiveMonitorPath(lbServerPoolName, privatePort, protocol);
             List<LBPoolMember> members = getLbPoolMembers(memberList, 
tier1GatewayName);
             LbPools lbPools = (LbPools) nsxService.apply(LbPools.class);
+            Optional<LBPool> nsxLbServerPool = getNsxLbServerPool(lbPools, 
lbServerPoolName);
+            // Skip if pool exists and members unchanged
+            if (nsxLbServerPool.isPresent()) {
+                List<LBPoolMember> existingMembers = nsxLbServerPool
+                        .map(LBPool::getMembers)
+                        .orElseGet(List::of);
+                if (hasSamePoolMembers(existingMembers, members)) {
+                    logger.debug("Skipping patch for LB pool {} on Tier-1 {}: 
members unchanged", lbServerPoolName, tier1GatewayName);
+                    return;
+                }
+            }
+            String activeMonitorPath = 
getLbActiveMonitorPath(lbServerPoolName, privatePort, protocol);
             LBPool lbPool = new LBPool.Builder()
                     .setId(lbServerPoolName)
                     .setDisplayName(lbServerPoolName)
@@ -676,9 +690,52 @@ public class NsxApiClient {
         }
     }
 
+    private Optional<LBPool> getNsxLbServerPool(LbPools lbPools, String 
lbServerPoolName) {
+        try {
+            return Optional.ofNullable(lbPools.get(lbServerPoolName));
+        } catch (NotFound e) {
+            logger.warn("Server Pool not found: {}", lbServerPoolName);
+            return Optional.empty();
+        }
+    }
+
+    private boolean hasSamePoolMembers(List<LBPoolMember> existingMembers, 
List<LBPoolMember> membersUpdate) {
+        Set<String> existingMembersSet = existingMembers.stream()
+                .map(this::buildPoolMemberKey)
+                .collect(toSet());
+        Set<String> updateMembersSet = membersUpdate.stream()
+                .map(this::buildPoolMemberKey)
+                .collect(toSet());
+
+        return existingMembersSet.size() == updateMembersSet.size()
+               && existingMembersSet.containsAll(updateMembersSet);
+    }
+
+    private String buildPoolMemberKey(LBPoolMember member) {
+        return member.getIpAddress() + ':' + member.getPort() + ':' + 
member.getDisplayName();
+    }
+
     private String getLbActiveMonitorPath(String lbServerPoolName, String 
port, String protocol) {
         LbMonitorProfiles lbActiveMonitor = (LbMonitorProfiles) 
nsxService.apply(LbMonitorProfiles.class);
         String lbMonitorProfileId = 
getActiveMonitorProfileName(lbServerPoolName, port, protocol);
+        Optional<Structure> monitorProfile = 
getMonitorProfile(lbActiveMonitor, lbMonitorProfileId);
+        if (monitorProfile.isEmpty()) {
+            patchMonitoringProfile(port, protocol, lbMonitorProfileId, 
lbActiveMonitor);
+            monitorProfile = getMonitorProfile(lbActiveMonitor, 
lbMonitorProfileId);
+        }
+        return monitorProfile.map(structure -> 
structure._getDataValue().getField("path").toString()).orElse(null);
+    }
+
+    private Optional<Structure> getMonitorProfile(LbMonitorProfiles 
lbActiveMonitor, String lbMonitorProfileId) {
+        try {
+            return 
Optional.ofNullable(lbActiveMonitor.get(lbMonitorProfileId));
+        } catch (NotFound e) {
+            logger.warn("LB Monitor Profile not found: {}", 
lbMonitorProfileId);
+            return Optional.empty();
+        }
+    }
+
+    private void patchMonitoringProfile(String port, String protocol, String 
lbMonitorProfileId, LbMonitorProfiles lbActiveMonitor) {
         if ("TCP".equals(protocol.toUpperCase(Locale.ROOT))) {
             LBTcpMonitorProfile lbTcpMonitorProfile = new 
LBTcpMonitorProfile.Builder(TCP_MONITOR_PROFILE)
                     .setDisplayName(lbMonitorProfileId)
@@ -691,10 +748,6 @@ public class NsxApiClient {
                     .build();
             lbActiveMonitor.patch(lbMonitorProfileId, icmpMonitorProfile);
         }
-
-        LBMonitorProfileListResult listResult = 
listLBActiveMonitors(lbActiveMonitor);
-        Optional<Structure> monitorProfile = 
listResult.getResults().stream().filter(profile -> 
profile._getDataValue().getField("id").toString().equals(lbMonitorProfileId)).findFirst();
-        return monitorProfile.map(structure -> 
structure._getDataValue().getField("path").toString()).orElse(null);
     }
 
     LBMonitorProfileListResult listLBActiveMonitors(LbMonitorProfiles 
lbActiveMonitor) {
@@ -735,7 +788,7 @@ public class NsxApiClient {
             String lbVirtualServerName = 
getVirtualServerName(tier1GatewayName, lbId);
             String lbServiceName = getLoadBalancerName(tier1GatewayName);
             LbVirtualServers lbVirtualServers = (LbVirtualServers) 
nsxService.apply(LbVirtualServers.class);
-            if (Objects.nonNull(getLbVirtualServerService(lbVirtualServers, 
lbServiceName))) {
+            if (Objects.nonNull(getLbVirtualServerService(lbVirtualServers, 
lbVirtualServerName))) {
                 return;
             }
             LBVirtualServer lbVirtualServer = new LBVirtualServer.Builder()
diff --git 
a/plugins/network-elements/nsx/src/test/java/org/apache/cloudstack/service/NsxApiClientTest.java
 
b/plugins/network-elements/nsx/src/test/java/org/apache/cloudstack/service/NsxApiClientTest.java
index f9ee8daea4b..5f8d771f75d 100644
--- 
a/plugins/network-elements/nsx/src/test/java/org/apache/cloudstack/service/NsxApiClientTest.java
+++ 
b/plugins/network-elements/nsx/src/test/java/org/apache/cloudstack/service/NsxApiClientTest.java
@@ -18,13 +18,32 @@ package org.apache.cloudstack.service;
 
 import com.cloud.network.Network;
 import com.cloud.network.SDNProviderNetworkRule;
+import com.cloud.utils.exception.CloudRuntimeException;
 import com.vmware.nsx.cluster.Status;
 import com.vmware.nsx.model.ClusterStatus;
 import com.vmware.nsx.model.ControllerClusterStatus;
+import com.vmware.nsx_policy.infra.LbAppProfiles;
+import com.vmware.nsx_policy.infra.LbMonitorProfiles;
+import com.vmware.nsx_policy.infra.LbPools;
+import com.vmware.nsx_policy.infra.LbServices;
+import com.vmware.nsx_policy.infra.LbVirtualServers;
 import com.vmware.nsx_policy.infra.domains.Groups;
+import com.vmware.nsx_policy.model.ApiError;
 import com.vmware.nsx_policy.model.Group;
+import com.vmware.nsx_policy.model.LBAppProfileListResult;
+import com.vmware.nsx_policy.model.LBIcmpMonitorProfile;
+import com.vmware.nsx_policy.model.LBService;
+import com.vmware.nsx_policy.model.LBTcpMonitorProfile;
+import com.vmware.nsx_policy.model.LBPool;
+import com.vmware.nsx_policy.model.LBPoolMember;
+import com.vmware.nsx_policy.model.LBVirtualServer;
 import com.vmware.nsx_policy.model.PathExpression;
 import com.vmware.vapi.bindings.Service;
+import com.vmware.vapi.bindings.Structure;
+import com.vmware.vapi.std.errors.Error;
+import com.vmware.vapi.std.errors.NotFound;
+import org.apache.cloudstack.resource.NsxLoadBalancerMember;
+import org.apache.cloudstack.utils.NsxControllerUtils;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
@@ -36,8 +55,20 @@ import org.mockito.MockitoAnnotations;
 import java.util.List;
 import java.util.function.Function;
 
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
 public class NsxApiClientTest {
 
+    private static final String TIER_1_GATEWAY_NAME = "t1";
+
     @Mock
     private Function<Class<? extends Service>, Service> nsxService;
     @Mock
@@ -108,4 +139,284 @@ public class NsxApiClientTest {
         
Mockito.when(clusterStatus.getControlClusterStatus()).thenReturn(status);
         Assert.assertTrue(client.isNsxControllerActive());
     }
+
+    @Test
+    public void 
testCreateNsxLbServerPoolExistingMonitorProfileSkipsMonitorPatch() {
+        String lbServerPoolName = 
NsxControllerUtils.getServerPoolName(TIER_1_GATEWAY_NAME, 1L);
+        List<NsxLoadBalancerMember> memberList = List.of(new 
NsxLoadBalancerMember(1L, "10.0.0.1", 80));
+
+        LbPools lbPools = Mockito.mock(LbPools.class);
+        LbMonitorProfiles lbMonitorProfiles = mockLbMonitorProfiles();
+
+        Mockito.when(nsxService.apply(LbPools.class)).thenReturn(lbPools);
+        Mockito.when(lbPools.get(lbServerPoolName)).thenThrow(new 
NotFound(null, null));
+
+        client.createNsxLbServerPool(memberList, TIER_1_GATEWAY_NAME, 
lbServerPoolName, "roundrobin", "80", "TCP");
+
+        verify(lbMonitorProfiles, never()).patch(anyString(), 
any(LBTcpMonitorProfile.class));
+        verify(lbPools).patch(eq(lbServerPoolName), any(LBPool.class));
+    }
+
+    @Test
+    public void 
testCreateNsxLbServerPoolMissingMonitorTCPProfilePerformsPatch() {
+        String lbServerPoolName = 
NsxControllerUtils.getServerPoolName(TIER_1_GATEWAY_NAME, 1L);
+        List<NsxLoadBalancerMember> memberList = List.of(new 
NsxLoadBalancerMember(1L, "10.0.0.1", 80));
+
+        LbPools lbPools = Mockito.mock(LbPools.class);
+        LbMonitorProfiles lbMonitorProfiles = 
Mockito.mock(LbMonitorProfiles.class);
+        Structure monitorStructure = Mockito.mock(Structure.class, 
Mockito.RETURNS_DEEP_STUBS);
+
+        Mockito.when(nsxService.apply(LbPools.class)).thenReturn(lbPools);
+        
Mockito.when(nsxService.apply(LbMonitorProfiles.class)).thenReturn(lbMonitorProfiles);
+        Mockito.when(lbMonitorProfiles.get(anyString())).thenThrow(new 
NotFound(null, null)).thenReturn(monitorStructure);
+        
Mockito.when(monitorStructure._getDataValue().getField("path").toString()).thenReturn("/infra/lb-monitor-profiles/test");
+        Mockito.when(lbPools.get(lbServerPoolName)).thenThrow(new 
NotFound(null, null));
+
+        client.createNsxLbServerPool(memberList, TIER_1_GATEWAY_NAME, 
lbServerPoolName, "roundrobin", "80", "TCP");
+
+        verify(lbMonitorProfiles).patch(anyString(), 
any(LBTcpMonitorProfile.class));
+        verify(lbPools).patch(eq(lbServerPoolName), any(LBPool.class));
+    }
+
+    @Test
+    public void 
testCreateNsxLbServerPoolMissingMonitorUDPProfilePerformsPatch() {
+        String lbServerPoolName = 
NsxControllerUtils.getServerPoolName(TIER_1_GATEWAY_NAME, 1L);
+        List<NsxLoadBalancerMember> memberList = List.of(new 
NsxLoadBalancerMember(1L, "10.0.0.1", 80));
+
+        LbPools lbPools = Mockito.mock(LbPools.class);
+        LbMonitorProfiles lbMonitorProfiles = 
Mockito.mock(LbMonitorProfiles.class);
+        Structure monitorStructure = Mockito.mock(Structure.class, 
Mockito.RETURNS_DEEP_STUBS);
+
+        Mockito.when(nsxService.apply(LbPools.class)).thenReturn(lbPools);
+        
Mockito.when(nsxService.apply(LbMonitorProfiles.class)).thenReturn(lbMonitorProfiles);
+        Mockito.when(lbMonitorProfiles.get(anyString())).thenThrow(new 
NotFound(null, null)).thenReturn(monitorStructure);
+        
Mockito.when(monitorStructure._getDataValue().getField("path").toString()).thenReturn("/infra/lb-monitor-profiles/test");
+        Mockito.when(lbPools.get(lbServerPoolName)).thenThrow(new 
NotFound(null, null));
+
+        client.createNsxLbServerPool(memberList, TIER_1_GATEWAY_NAME, 
lbServerPoolName, "roundrobin", "80", "UDP");
+
+        verify(lbMonitorProfiles).patch(anyString(), 
any(LBIcmpMonitorProfile.class));
+        verify(lbPools).patch(eq(lbServerPoolName), any(LBPool.class));
+    }
+
+    @Test
+    public void testCreateNsxLbServerPoolPoolExistsWithSameMembersSkipsPatch() 
{
+        long lbId = 1L;
+        String lbServerPoolName = 
NsxControllerUtils.getServerPoolName(TIER_1_GATEWAY_NAME, lbId);
+        List<NsxLoadBalancerMember> memberList = List.of(
+                new NsxLoadBalancerMember(1L, "10.0.0.1", 80),
+                new NsxLoadBalancerMember(2L, "10.0.0.2", 80)
+        );
+        List<LBPoolMember> sameMembers = List.of(
+                createPoolMember(2L, "10.0.0.2", 80),
+                createPoolMember(1L, "10.0.0.1", 80)
+        );
+
+        LbPools lbPools = Mockito.mock(LbPools.class);
+        LBPool existingPool = Mockito.mock(LBPool.class);
+
+        Mockito.when(nsxService.apply(LbPools.class)).thenReturn(lbPools);
+        Mockito.when(lbPools.get(lbServerPoolName)).thenReturn(existingPool);
+        Mockito.when(existingPool.getMembers()).thenReturn(sameMembers);
+
+        client.createNsxLbServerPool(memberList, TIER_1_GATEWAY_NAME, 
lbServerPoolName, "roundrobin", "80", "TCP");
+
+        verify(nsxService, never()).apply(LbMonitorProfiles.class);
+        verify(lbPools, never()).patch(anyString(), any(LBPool.class));
+    }
+
+    @Test
+    public void 
testCreateNsxLbServerPoolPoolExistsWithoutMembersAndEmptyUpdateSkipsPatch() {
+        String lbServerPoolName = 
NsxControllerUtils.getServerPoolName(TIER_1_GATEWAY_NAME, 1L);
+
+        LbPools lbPools = Mockito.mock(LbPools.class);
+        LBPool existingPool = Mockito.mock(LBPool.class);
+
+        Mockito.when(nsxService.apply(LbPools.class)).thenReturn(lbPools);
+        Mockito.when(lbPools.get(lbServerPoolName)).thenReturn(existingPool);
+        Mockito.when(existingPool.getMembers()).thenReturn(null);
+
+        client.createNsxLbServerPool(List.of(), TIER_1_GATEWAY_NAME, 
lbServerPoolName, "roundrobin", "80", "TCP");
+
+        verify(nsxService, never()).apply(LbMonitorProfiles.class);
+        verify(lbPools, never()).patch(anyString(), any(LBPool.class));
+    }
+
+    @Test
+    public void 
testCreateNsxLbServerPoolPoolExistsWithDuplicateMembersSkipsPatch() {
+        long lbId = 1L;
+        String lbServerPoolName = 
NsxControllerUtils.getServerPoolName(TIER_1_GATEWAY_NAME, lbId);
+        List<NsxLoadBalancerMember> memberList = List.of(
+                new NsxLoadBalancerMember(1L, "10.0.0.1", 80),
+                new NsxLoadBalancerMember(2L, "10.0.0.2", 80)
+        );
+
+        LbPools lbPools = Mockito.mock(LbPools.class);
+        LBPool existingPool = Mockito.mock(LBPool.class);
+
+        Mockito.when(nsxService.apply(LbPools.class)).thenReturn(lbPools);
+        Mockito.when(lbPools.get(lbServerPoolName)).thenReturn(existingPool);
+        Mockito.when(existingPool.getMembers()).thenReturn(List.of(
+                createPoolMember(1L, "10.0.0.1", 80),
+                createPoolMember(1L, "10.0.0.1", 80),
+                createPoolMember(2L, "10.0.0.2", 80)
+        ));
+
+        client.createNsxLbServerPool(memberList, TIER_1_GATEWAY_NAME, 
lbServerPoolName, "roundrobin", "80", "TCP");
+
+        verify(nsxService, never()).apply(LbMonitorProfiles.class);
+        verify(lbPools, never()).patch(anyString(), any(LBPool.class));
+    }
+
+    @Test
+    public void 
testCreateNsxLbServerPoolPoolExistsWithDifferentMembersPerformsPatch() {
+        long lbId = 1L;
+        String lbServerPoolName = 
NsxControllerUtils.getServerPoolName(TIER_1_GATEWAY_NAME, lbId);
+        List<NsxLoadBalancerMember> memberList = List.of(
+                new NsxLoadBalancerMember(1L, "10.0.0.1", 80),
+                new NsxLoadBalancerMember(2L, "10.0.0.2", 80)
+        );
+
+        LbPools lbPools = Mockito.mock(LbPools.class);
+        LBPool existingPool = Mockito.mock(LBPool.class);
+
+        mockLbMonitorProfiles();
+        Mockito.when(nsxService.apply(LbPools.class)).thenReturn(lbPools);
+        Mockito.when(lbPools.get(lbServerPoolName)).thenReturn(existingPool);
+        Mockito.when(existingPool.getMembers()).thenReturn(List.of(
+                createPoolMember(1L, "10.0.0.10", 80)
+        ));
+
+        client.createNsxLbServerPool(memberList, TIER_1_GATEWAY_NAME, 
lbServerPoolName, "roundrobin", "80", "TCP");
+
+        verify(lbPools).patch(eq(lbServerPoolName), any(LBPool.class));
+    }
+
+    @Test
+    public void testCreateNsxLbServerPoolPoolDoesNotExistPerformsPatch() {
+        String lbServerPoolName = 
NsxControllerUtils.getServerPoolName(TIER_1_GATEWAY_NAME, 1L);
+        List<NsxLoadBalancerMember> memberList = List.of(new 
NsxLoadBalancerMember(1L, "10.0.0.1", 80));
+
+        LbPools lbPools = Mockito.mock(LbPools.class);
+
+        mockLbMonitorProfiles();
+        Mockito.when(nsxService.apply(LbPools.class)).thenReturn(lbPools);
+        Mockito.when(lbPools.get(lbServerPoolName)).thenThrow(new 
NotFound(null, null));
+
+        client.createNsxLbServerPool(memberList, TIER_1_GATEWAY_NAME, 
lbServerPoolName, "roundrobin", "80", "TCP");
+
+        verify(lbPools).patch(eq(lbServerPoolName), any(LBPool.class));
+    }
+
+    @Test
+    public void 
testCreateAndAddNsxLbVirtualServerVirtualServerAlreadyExistsSkipsPatch() {
+        long lbId = 1L;
+        String lbVirtualServerName = 
NsxControllerUtils.getVirtualServerName(TIER_1_GATEWAY_NAME, lbId);
+        String lbServiceName = 
NsxControllerUtils.getLoadBalancerName(TIER_1_GATEWAY_NAME);
+        List<NsxLoadBalancerMember> memberList = List.of(new 
NsxLoadBalancerMember(1L, "10.0.0.1", 80));
+
+        LbPools lbPools = Mockito.mock(LbPools.class);
+        LbServices lbServices = Mockito.mock(LbServices.class);
+        LbVirtualServers lbVirtualServers = 
Mockito.mock(LbVirtualServers.class);
+        LBVirtualServer existingVs = Mockito.mock(LBVirtualServer.class);
+
+        mockLbMonitorProfiles();
+        Mockito.when(nsxService.apply(LbPools.class)).thenReturn(lbPools);
+        
Mockito.when(nsxService.apply(LbServices.class)).thenReturn(lbServices);
+        
Mockito.when(nsxService.apply(LbVirtualServers.class)).thenReturn(lbVirtualServers);
+        Mockito.when(lbPools.get(anyString())).thenThrow(new NotFound(null, 
null));
+        Mockito.when(lbServices.get(anyString())).thenReturn(null);
+        
Mockito.when(lbVirtualServers.get(lbVirtualServerName)).thenReturn(existingVs);
+
+        client.createAndAddNsxLbVirtualServer(TIER_1_GATEWAY_NAME, lbId, 
"192.168.1.1", "443",
+                memberList, "roundrobin", "TCP", "80");
+
+        verify(lbVirtualServers).get(lbVirtualServerName);
+        verify(lbVirtualServers, never()).get(lbServiceName);
+        verify(lbVirtualServers, never()).patch(anyString(), 
any(LBVirtualServer.class));
+    }
+
+    @Test
+    public void 
testCreateAndAddNsxLbVirtualServerVirtualServerNotFoundPerformsPatch() {
+        long lbId = 1L;
+        String lbServerPoolName = 
NsxControllerUtils.getServerPoolName(TIER_1_GATEWAY_NAME, lbId);
+        String lbVirtualServerName = 
NsxControllerUtils.getVirtualServerName(TIER_1_GATEWAY_NAME, lbId);
+        String lbServiceName = 
NsxControllerUtils.getLoadBalancerName(TIER_1_GATEWAY_NAME);
+        List<NsxLoadBalancerMember> memberList = List.of(new 
NsxLoadBalancerMember(1L, "10.0.0.1", 80));
+
+        LbPools lbPools = Mockito.mock(LbPools.class);
+        LBPool lbPool = Mockito.mock(LBPool.class);
+        LbServices lbServices = Mockito.mock(LbServices.class);
+        LBService lbService = Mockito.mock(LBService.class);
+        LbVirtualServers lbVirtualServers = 
Mockito.mock(LbVirtualServers.class);
+
+        mockLbMonitorProfiles();
+        mockLbAppProfiles();
+        Mockito.when(nsxService.apply(LbPools.class)).thenReturn(lbPools);
+        
Mockito.when(nsxService.apply(LbServices.class)).thenReturn(lbServices);
+        
Mockito.when(nsxService.apply(LbVirtualServers.class)).thenReturn(lbVirtualServers);
+        Mockito.when(lbPools.get(lbServerPoolName)).thenThrow(new 
NotFound(null, null)).thenReturn(lbPool);
+        Mockito.when(lbPool.getPath()).thenReturn("/infra/lb-pools/" + 
lbServerPoolName);
+        Mockito.when(lbServices.get(lbServiceName)).thenReturn(lbService);
+        Mockito.when(lbService.getPath()).thenReturn("/infra/lb-services/" + 
lbServiceName);
+        Mockito.when(lbVirtualServers.get(lbVirtualServerName)).thenThrow(new 
NotFound(null, null));
+
+        client.createAndAddNsxLbVirtualServer(TIER_1_GATEWAY_NAME, lbId, 
"192.168.1.1", "443",
+                memberList, "roundrobin", "TCP", "80");
+
+        verify(lbVirtualServers).get(lbVirtualServerName);
+        verify(lbVirtualServers, never()).get(lbServiceName);
+        verify(lbVirtualServers).patch(eq(lbVirtualServerName), 
any(LBVirtualServer.class));
+    }
+
+    @Test
+    public void testCreateNsxLbServerPoolThrowsExceptionOnPatchError() {
+        String lbServerPoolName = 
NsxControllerUtils.getServerPoolName(TIER_1_GATEWAY_NAME, 1L);
+        List<NsxLoadBalancerMember> memberList = List.of(new 
NsxLoadBalancerMember(1L, "10.0.0.1", 80));
+
+        LbPools lbPools = Mockito.mock(LbPools.class);
+        Structure errorData = Mockito.mock(Structure.class);
+        ApiError apiError = new ApiError();
+        apiError.setErrorData(errorData);
+
+        mockLbMonitorProfiles();
+        Mockito.when(nsxService.apply(LbPools.class)).thenReturn(lbPools);
+        Mockito.when(lbPools.get(lbServerPoolName)).thenThrow(new 
NotFound(null, null));
+        when(errorData._convertTo(ApiError.class)).thenReturn(apiError);
+        doThrow(new Error(List.of(), 
errorData)).when(lbPools).patch(eq(lbServerPoolName), any(LBPool.class));
+
+        CloudRuntimeException thrownException = 
assertThrows(CloudRuntimeException.class, () -> {
+            client.createNsxLbServerPool(memberList, TIER_1_GATEWAY_NAME, 
lbServerPoolName, "roundrobin", "80", "TCP");
+        });
+        assertTrue(thrownException.getMessage().startsWith("Failed to create 
NSX LB server pool, due to"));
+    }
+
+    private LbMonitorProfiles mockLbMonitorProfiles() {
+        LbMonitorProfiles lbMonitorProfiles = 
Mockito.mock(LbMonitorProfiles.class);
+        Structure monitorStructure = Mockito.mock(Structure.class, 
Mockito.RETURNS_DEEP_STUBS);
+
+        
Mockito.when(nsxService.apply(LbMonitorProfiles.class)).thenReturn(lbMonitorProfiles);
+        
Mockito.when(lbMonitorProfiles.get(anyString())).thenReturn(monitorStructure);
+        
Mockito.when(monitorStructure._getDataValue().getField("path").toString()).thenReturn("/infra/lb-monitor-profiles/test");
+        return lbMonitorProfiles;
+    }
+
+    private void mockLbAppProfiles() {
+        LbAppProfiles lbAppProfiles = Mockito.mock(LbAppProfiles.class);
+        LBAppProfileListResult appProfileListResult = 
Mockito.mock(LBAppProfileListResult.class);
+        Structure appProfile = Mockito.mock(Structure.class, 
Mockito.RETURNS_DEEP_STUBS);
+
+        
Mockito.when(nsxService.apply(LbAppProfiles.class)).thenReturn(lbAppProfiles);
+        Mockito.when(lbAppProfiles.list(null, null, null, null, null, 
null)).thenReturn(appProfileListResult);
+        
Mockito.when(appProfileListResult.getResults()).thenReturn(List.of(appProfile));
+        
Mockito.when(appProfile._getDataValue().getField("path").toString()).thenReturn("/infra/lb-app-profiles/default-tcp-profile");
+    }
+
+    private LBPoolMember createPoolMember(long vmId, String ipAddress, int 
port) {
+        return new LBPoolMember.Builder()
+                
.setDisplayName(NsxControllerUtils.getServerPoolMemberName(TIER_1_GATEWAY_NAME, 
vmId))
+                .setIpAddress(ipAddress)
+                .setPort(String.valueOf(port))
+                .build();
+    }
 }

Reply via email to