server: optimize listSupportedNetworkServiceProviders

This commit is contained in:
Wei Zhou 2026-04-30 17:29:29 +02:00
parent b6500ca7e3
commit 429105e7b1
2 changed files with 43 additions and 26 deletions

View File

@ -99,6 +99,7 @@ import com.cloud.network.element.IpDeployingRequester;
import com.cloud.network.element.NetworkElement;
import com.cloud.network.element.UserDataServiceProvider;
import com.cloud.network.router.VirtualRouter;
import org.apache.cloudstack.extension.Extension;
import org.apache.cloudstack.extension.ExtensionHelper;
import org.apache.cloudstack.framework.extensions.network.NetworkExtensionElement;
import com.cloud.network.rules.FirewallRule.Purpose;
@ -1310,34 +1311,46 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel, Confi
}
}
// Also include extension-backed NetworkExtension providers registered in
// physical_network_service_providers whose provider name matches a registered
// NetworkOrchestrator extension (detected via extensionHelper.isNetworkExtensionProvider).
//
// We use _pNSPDao.listBy(physNetId) to enumerate all NSP entries, then check
// each provider name against the extension registry. This avoids a separate
// pass over all physical-network/extension combinations.
// Also include extension-backed NetworkExtension providers.
// resolveProvider() creates a transient Provider (not added to the static list)
// for extension names that are not in the built-in registry.
try {
List<PhysicalNetworkVO> physNets = _physicalNetworkDao.listAll();
if (physNets != null) {
// Use a set to avoid adding the same provider name twice (multiple phys-nets)
Set<String> addedExtProviders = new HashSet<>();
for (PhysicalNetworkVO physNet : physNets) {
List<PhysicalNetworkServiceProviderVO> nsps = _pNSPDao.listBy(physNet.getId());
if (nsps == null) continue;
List<PhysicalNetworkServiceProviderVO> nsps = _pNSPDao.listAll();
if (CollectionUtils.isNotEmpty(nsps)) {
Set<String> extensionProviderNames = new HashSet<>();
List<Extension> extensions = extensionHelper.listExtensionsByType(Extension.Type.NetworkOrchestrator);
if (extensions != null) {
for (Extension extension : extensions) {
if (extension == null || StringUtils.isBlank(extension.getName())) {
continue;
}
extensionProviderNames.add(extension.getName().toLowerCase());
}
}
if (!extensionProviderNames.isEmpty()) {
// Avoid duplicate provider names across multiple physical networks.
Set<String> addedExtProviders = new HashSet<>();
for (PhysicalNetworkServiceProviderVO nsp : nsps) {
String provName = nsp.getProviderName();
if (provName == null || addedExtProviders.contains(provName)) continue;
if (!extensionHelper.isNetworkExtensionProvider(provName)) continue;
if (StringUtils.isBlank(provName)) {
continue;
}
// Filter by service if requested: check the NSP's service flags
if (service != null && !isServiceProvidedByNsp(nsp, service)) continue;
if (addedExtProviders.contains(provName) || !extensionProviderNames.contains(provName)) {
continue;
}
// Filter by service if requested: check the NSP's service flags.
if (service != null && !isServiceProvidedByNsp(nsp, service)) {
continue;
}
// Resolve or create a transient Provider for the extension name.
Provider extProvider = resolveProvider(provName);
if (extProvider == null) continue;
if (extProvider == null) {
continue;
}
supportedProviders.add(extProvider);
addedExtProviders.add(provName);
}
@ -1355,7 +1368,7 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel, Confi
* has its service flag set for {@code service}.
*
* <p>This is used by {@link #listSupportedNetworkServiceProviders} to filter extension-backed
* providers (looked up via {@link com.cloud.network.dao.PhysicalNetworkServiceProviderDao#listBy})
* providers (looked up via {@link com.cloud.network.dao.PhysicalNetworkServiceProviderDao#listAll})
* without having to query each extension's capability JSON.</p>
*/
private boolean isServiceProvidedByNsp(

View File

@ -60,7 +60,6 @@ import com.cloud.network.dao.NetworkVO;
import com.cloud.network.dao.PhysicalNetworkDao;
import com.cloud.network.dao.PhysicalNetworkServiceProviderDao;
import com.cloud.network.dao.PhysicalNetworkServiceProviderVO;
import com.cloud.network.dao.PhysicalNetworkVO;
import com.cloud.network.element.NetworkElement;
import com.cloud.network.element.VpcVirtualRouterElement;
import com.cloud.network.vpc.VpcVO;
@ -73,6 +72,7 @@ import com.cloud.utils.net.Ip;
import com.cloud.vm.Nic;
import com.cloud.vm.NicProfile;
import com.cloud.vm.VirtualMachine;
import org.apache.cloudstack.extension.Extension;
import org.apache.cloudstack.extension.ExtensionHelper;
import org.apache.cloudstack.framework.extensions.network.NetworkExtensionElement;
@ -392,13 +392,14 @@ public class NetworkModelImplTest {
@Test
public void listSupportedNetworkServiceProvidersIncludesExtensionBackedProviders() {
PhysicalNetworkVO physNet = mock(PhysicalNetworkVO.class);
when(physNet.getId()).thenReturn(1L);
when(physicalNetworkDao.listAll()).thenReturn(List.of(physNet));
PhysicalNetworkServiceProviderVO nsp = mock(PhysicalNetworkServiceProviderVO.class);
when(nsp.getProviderName()).thenReturn("my-ext");
when(physicalNetworkServiceProviderDao.listBy(1L)).thenReturn(List.of(nsp));
when(physicalNetworkServiceProviderDao.listAll()).thenReturn(List.of(nsp));
Extension extension = mock(Extension.class);
when(extension.getName()).thenReturn("my-ext");
when(extensionHelper.listExtensionsByType(Extension.Type.NetworkOrchestrator)).thenReturn(List.of(extension));
when(extensionHelper.isNetworkExtensionProvider("my-ext")).thenReturn(true);
// networkElements is empty so no standard providers found
@ -409,5 +410,8 @@ public class NetworkModelImplTest {
boolean found = result.stream().anyMatch(p -> "my-ext".equalsIgnoreCase(p.getName()));
assertTrue("Extension-backed provider should be included", found);
Mockito.verify(physicalNetworkServiceProviderDao, Mockito.times(1)).listAll();
Mockito.verify(physicalNetworkServiceProviderDao, Mockito.never()).listBy(Mockito.anyLong());
}
}