Copilot commented on code in PR #12811:
URL: https://github.com/apache/cloudstack/pull/12811#discussion_r2929970072


##########
ui/src/views/infra/zone/BgpPeersTab.vue:
##########
@@ -18,15 +18,15 @@
 <template>
   <a-spin :spinning="componentLoading">
     <a-alert
-      v-if="this.resource.ip4routing"
+      v-if="this.resource.ip4routing || this.resource.ip6routing"
       type="info">
       <template #message>
         <div v-html="$t('message.bgp.peers.null')" />
       </template>
     </a-alert>
     <br>
     <a-button
-      v-if="!this.resource.ip4routing"
+      v-if="!(this.resource.ip4routing || this.resource.ip6routing)"

Review Comment:
   The condition (this.resource.ip4routing || this.resource.ip6routing) is 
repeated in multiple v-if expressions in this component. Consider introducing a 
computed/property (e.g., hasRoutingConfigured) to centralize the logic and 
reduce the chance of inconsistent updates in the future.
   



##########
server/src/main/java/com/cloud/api/ApiResponseHelper.java:
##########
@@ -3578,12 +3582,24 @@ public VpcResponse createVpcResponse(ResponseView view, 
Vpc vpc) {
                     response.addIpv4Route(route);
                 }
             }
-            if (view == ResponseView.Full) {
-                List<BgpPeerVO> bgpPeerVOS = 
bgpPeerDao.listNonRevokeByVpcId(vpc.getId());
-                for (BgpPeerVO bgpPeerVO : bgpPeerVOS) {
-                    BgpPeerResponse bgpPeerResponse = 
routedIpv4Manager.createBgpPeerResponse(bgpPeerVO);
-                    response.addBgpPeer(bgpPeerResponse);
-                }
+        }
+
+        // add IPv6 routes
+        ipv6Service.updateIpv6RoutesForVpcResponse(vpc, response);
+        if (CollectionUtils.isNotEmpty(response.getIpv6Routes())) {
+            if (Objects.nonNull(asNumberVO)) {
+                response.setIpv6Routing(Network.Routing.Dynamic.name());
+            } else {
+                response.setIpv6Routing(Network.Routing.Static.name());
+            }

Review Comment:
   ipv6Routing is only set when ipv6Routes is non-empty. This can leave 
ipv6Routing unset for VPCs that support IPv6 but currently have no routes 
populated, which is problematic for clients/UI that rely on ipv6Routing 
presence/value (e.g., to determine whether to show BGP-related UI/actions). 
Consider setting ipv6Routing deterministically (Dynamic/Static) independent of 
whether ipv6Routes is empty.
   



##########
api/src/main/java/org/apache/cloudstack/api/response/VpcResponse.java:
##########
@@ -165,6 +165,10 @@ public class VpcResponse extends 
BaseResponseWithAnnotations implements Controll
     @Param(description = "The IPv4 routing mode of VPC", since = "4.20.0")
     private String ipv4Routing;
 
+    @SerializedName(ApiConstants.IPV6_ROUTING)
+    @Param(description = "The Ipv6 routing type of VPC", since = "4.22.1")

Review Comment:
   In the `@Param` description, 'Ipv6' should be capitalized as 'IPv6' to match 
standard terminology used elsewhere in the API.
   



##########
ui/src/views/infra/zone/BgpPeersTab.vue:
##########
@@ -18,15 +18,15 @@
 <template>
   <a-spin :spinning="componentLoading">
     <a-alert
-      v-if="this.resource.ip4routing"
+      v-if="this.resource.ip4routing || this.resource.ip6routing"

Review Comment:
   The condition (this.resource.ip4routing || this.resource.ip6routing) is 
repeated in multiple v-if expressions in this component. Consider introducing a 
computed/property (e.g., hasRoutingConfigured) to centralize the logic and 
reduce the chance of inconsistent updates in the future.



##########
server/src/main/java/com/cloud/network/router/CommandSetupHelper.java:
##########
@@ -1470,11 +1470,21 @@ public void createBgpPeersCommands(final List<? extends 
BgpPeer> bgpPeers, final
         for (BgpPeer bgpPeer: bgpPeers) {
             Map<BgpPeer.Detail, String> bgpPeerDetails = 
bgpPeerDetailsDao.getBgpPeerDetails(bgpPeer.getId());
             for (Network guestNetwork : guestNetworks) {
-                bgpPeerTOs.add(new BgpPeerTO(bgpPeer.getId(), 
bgpPeer.getIp4Address(), bgpPeer.getIp6Address(), bgpPeer.getAsNumber(), 
bgpPeer.getPassword(),
-                        guestNetwork.getId(), asNumberVO.getAsNumber(), 
guestNetwork.getCidr(), guestNetwork.getIp6Cidr(), bgpPeerDetails));
+                final NetworkOfferingVO offering = 
_networkOfferingDao.findByIdIncludingRemoved(guestNetwork.getNetworkOfferingId());
+                if 
(NetworkOffering.NetworkMode.ROUTED.equals(offering.getNetworkMode())) {
+                    bgpPeerTOs.add(new BgpPeerTO(bgpPeer.getId(), 
bgpPeer.getIp4Address(), bgpPeer.getIp6Address(), bgpPeer.getAsNumber(), 
bgpPeer.getPassword(),
+                            guestNetwork.getId(), asNumberVO.getAsNumber(), 
guestNetwork.getCidr(), guestNetwork.getIp6Cidr(), bgpPeerDetails));
+                } else if (guestNetwork.getIp6Cidr() != null && 
bgpPeer.getIp6Address() != null) {
+                    bgpPeerTOs.add(new BgpPeerTO(bgpPeer.getId(), null, 
bgpPeer.getIp6Address(), bgpPeer.getAsNumber(), bgpPeer.getPassword(),
+                            guestNetwork.getId(), asNumberVO.getAsNumber(), 
guestNetwork.getCidr(), guestNetwork.getIp6Cidr(), bgpPeerDetails));

Review Comment:
   In the IPv6-only path (non-ROUTED offerings), the BgpPeerTO is constructed 
with a null IPv4 peer address but still passes guestNetwork.getCidr() (IPv4 
CIDR). If the agent/VR side assumes IPv4 CIDR is present whenever provided, 
this can lead to incorrect IPv4 route/BGP config attempts. Consider passing 
null for the IPv4 CIDR (or adjusting the TO/agent handling) when creating an 
IPv6-only BGP peer entry.
   



##########
server/src/main/java/com/cloud/network/router/CommandSetupHelper.java:
##########
@@ -1470,11 +1470,21 @@ public void createBgpPeersCommands(final List<? extends 
BgpPeer> bgpPeers, final
         for (BgpPeer bgpPeer: bgpPeers) {
             Map<BgpPeer.Detail, String> bgpPeerDetails = 
bgpPeerDetailsDao.getBgpPeerDetails(bgpPeer.getId());
             for (Network guestNetwork : guestNetworks) {
-                bgpPeerTOs.add(new BgpPeerTO(bgpPeer.getId(), 
bgpPeer.getIp4Address(), bgpPeer.getIp6Address(), bgpPeer.getAsNumber(), 
bgpPeer.getPassword(),
-                        guestNetwork.getId(), asNumberVO.getAsNumber(), 
guestNetwork.getCidr(), guestNetwork.getIp6Cidr(), bgpPeerDetails));
+                final NetworkOfferingVO offering = 
_networkOfferingDao.findByIdIncludingRemoved(guestNetwork.getNetworkOfferingId());
+                if 
(NetworkOffering.NetworkMode.ROUTED.equals(offering.getNetworkMode())) {

Review Comment:
   The network offering lookup is inside the nested (peers × guestNetworks) 
loops, leading to repeated DAO calls for the same guestNetwork offering. 
Consider precomputing offering/network-mode per guestNetwork (or per 
networkOfferingId) before iterating bgpPeers, so each offering is fetched once 
per network rather than once per peer.



##########
server/src/main/java/com/cloud/bgp/BGPServiceImpl.java:
##########
@@ -396,9 +397,12 @@ public boolean applyBgpPeers(Network network, boolean 
continueOnError) throws Re
         if (!routedIpv4Manager.isDynamicRoutedNetwork(network)) {
             return true;
         }
-        final String gatewayProviderStr = 
ntwkSrvcDao.getProviderForServiceInNetwork(network.getId(), 
Network.Service.Gateway);
-        if (gatewayProviderStr != null) {
-            NetworkElement provider = 
networkModel.getElementImplementingProvider(gatewayProviderStr);
+        NetworkOffering networkOffering = 
networkOfferingDao.findById(network.getNetworkOfferingId());
+        final String bgpServiceProvider = 
NetworkOffering.NetworkMode.ROUTED.equals(networkOffering.getNetworkMode()) ?
+                ntwkSrvcDao.getProviderForServiceInNetwork(network.getId(), 
Network.Service.Gateway):
+                ntwkSrvcDao.getProviderForServiceInNetwork(network.getId(), 
Network.Service.SourceNat);

Review Comment:
   networkOfferingDao.findById(...) (and similarly 
vpcOfferingDao.findById(...)) can return null (e.g., removed/invalid offering), 
which will NPE on getNetworkMode(). Add a null guard and decide on a safe 
behavior (e.g., log and return true / skip applying peers, or throw a 
ResourceUnavailableException) to avoid a hard failure.



##########
server/src/main/java/com/cloud/api/ApiResponseHelper.java:
##########
@@ -2843,6 +2839,15 @@ public NetworkResponse 
createNetworkResponse(ResponseView view, Network network)
             }
         }
 
+        // Add BGP peer information for full view
+        if (view == ResponseView.Full) {
+            List<BgpPeerVO> bgpPeerVOS = 
bgpPeerDao.listNonRevokeByNetworkId(network.getId());
+            for (BgpPeerVO bgpPeerVO : bgpPeerVOS) {
+                BgpPeerResponse bgpPeerResponse = 
routedIpv4Manager.createBgpPeerResponse(bgpPeerVO);
+                response.addBgpPeer(bgpPeerResponse);
+            }
+        }

Review Comment:
   This now performs a BGP peer DAO lookup for every NetworkResponse in Full 
view, even when the network isn't eligible for dynamic routing/BGP (likely 
yielding empty results). Consider gating this block behind the same eligibility 
condition used for applying peers (e.g., 
routedIpv4Manager.isDynamicRoutedNetwork(network)), to avoid unnecessary 
database queries in admin-heavy listing scenarios.



##########
server/src/test/java/com/cloud/network/router/CommandSetupHelperTest.java:
##########
@@ -226,6 +227,10 @@ public void testCreateBgpPeersCommandsForNetwork() {
         when(dcDao.findById(zoneId)).thenReturn(dc);
         when(dc.getNetworkType()).thenReturn(DataCenter.NetworkType.Advanced);
 
+        NetworkOfferingVO offering = Mockito.mock(NetworkOfferingVO.class);
+        
when(networkOfferingDao.findByIdIncludingRemoved(anyLong())).thenReturn(offering);
+        
when(offering.getNetworkMode()).thenReturn(NetworkOffering.NetworkMode.ROUTED);

Review Comment:
   Current tests only cover the ROUTED network-mode path. The new logic adds an 
IPv6-only path for non-ROUTED offerings (and early-return when bgpPeerTOs is 
empty). Add unit tests that (1) verify BgpPeerTO creation for non-ROUTED + IPv6 
CIDR (with IPv4 peer/IP fields absent as expected), and (2) verify no command 
is added when no eligible peers/networks produce any BgpPeerTOs.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to