add some checks to prevent networkmode change when provider is nsx/netris from the source networkmode

This commit is contained in:
Pearl Dsilva 2026-02-02 13:16:02 -05:00
parent 09cdd31cb4
commit 6ea054cb01
3 changed files with 163 additions and 40 deletions

View File

@ -8298,44 +8298,61 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
logger.info("Cloning network offering {} (id: {}) to new offering with name: {}",
sourceOffering.getName(), sourceOfferingId, name);
String detectedProvider = cmd.getProvider();
if (detectedProvider == null || detectedProvider.isEmpty()) {
Map<Network.Service, Set<Network.Provider>> sourceServiceProviderMap =
Map<Network.Service, Set<Network.Provider>> sourceServiceProviderMap =
_networkModel.getNetworkOfferingServiceProvidersMap(sourceOfferingId);
if (sourceServiceProviderMap.containsKey(Network.Service.NetworkACL)) {
Set<Network.Provider> networkAclProviders = sourceServiceProviderMap.get(Network.Service.NetworkACL);
if (networkAclProviders != null && !networkAclProviders.isEmpty()) {
Network.Provider provider = networkAclProviders.iterator().next();
if (provider == Network.Provider.Nsx) {
detectedProvider = "NSX";
} else if (provider == Network.Provider.Netris) {
detectedProvider = "Netris";
}
}
}
}
validateProvider(sourceOffering, sourceServiceProviderMap, cmd.getProvider(), cmd.getNetworkMode());
// If this is an NSX/Netris offering, prevent network mode changes
if (detectedProvider != null && (detectedProvider.equals("NSX") || detectedProvider.equals("Netris"))) {
String cmdNetworkMode = cmd.getNetworkMode();
if (cmdNetworkMode != null && sourceOffering.getNetworkMode() != null) {
if (!cmdNetworkMode.equalsIgnoreCase(sourceOffering.getNetworkMode().toString())) {
throw new InvalidParameterValueException(
String.format("Cannot change network mode when cloning %s provider network offerings. " +
"Source offering has network mode '%s', but '%s' was specified. " +
"The network mode is determined by the provider configuration and cannot be modified.",
detectedProvider, sourceOffering.getNetworkMode(), cmdNetworkMode));
}
}
}
applySourceOfferingValuesToCloneCmd(cmd, sourceOffering);
applySourceOfferingValuesToCloneCmd(cmd, sourceServiceProviderMap, sourceOffering);
return createNetworkOffering(cmd);
}
private void validateProvider(NetworkOfferingVO sourceOffering,
Map<Network.Service, Set<Network.Provider>> sourceServiceProviderMap,
String detectedProvider, String networkMode) {
detectedProvider = getExternalNetworkProvider(detectedProvider, sourceServiceProviderMap);
// If this is an NSX/Netris offering, prevent network mode changes
if (detectedProvider != null && (detectedProvider.equals("NSX") || detectedProvider.equals("Netris"))) {
if (networkMode != null && sourceOffering.getNetworkMode() != null) {
if (!networkMode.equalsIgnoreCase(sourceOffering.getNetworkMode().toString())) {
throw new InvalidParameterValueException(
String.format("Cannot change network mode when cloning %s provider network offerings. " +
"Source offering has network mode '%s', but '%s' was specified. ",
detectedProvider, sourceOffering.getNetworkMode(), networkMode));
}
}
}
}
public static String getExternalNetworkProvider(String detectedProvider,
Map<Network.Service, Set<Network.Provider>> sourceServiceProviderMap) {
if (StringUtils.isNotEmpty(detectedProvider)) {
return detectedProvider;
}
if (sourceServiceProviderMap == null || sourceServiceProviderMap.isEmpty()) {
return null;
}
for (Set<Provider> providers : sourceServiceProviderMap.values()) {
if (CollectionUtils.isEmpty(providers)) {
continue;
}
for (Provider provider : providers) {
if (provider == Provider.Nsx) {
return "NSX";
}
if (provider == Provider.Netris) {
return "Netris";
}
}
}
return null;
}
/**
* Converts service provider map from internal format to API parameter format.
*
@ -8364,12 +8381,11 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
return apiFormatMap;
}
private void applySourceOfferingValuesToCloneCmd(CloneNetworkOfferingCmd cmd, NetworkOfferingVO sourceOffering) {
private void applySourceOfferingValuesToCloneCmd(CloneNetworkOfferingCmd cmd,
Map<Network.Service, Set<Network.Provider>> sourceServiceProviderMap,
NetworkOfferingVO sourceOffering) {
Long sourceOfferingId = sourceOffering.getId();
Map<Network.Service, Set<Network.Provider>> sourceServiceProviderMap =
_networkModel.getNetworkOfferingServiceProvidersMap(sourceOfferingId);
// Build final services list with add/drop support
List<String> finalServices = resolveFinalServicesList(cmd, sourceServiceProviderMap);

View File

@ -835,21 +835,39 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
VpcOfferingVO vpcOfferingVO = _vpcOffDao.findByUniqueName(name);
if (vpcOfferingVO != null) {
throw new InvalidParameterValueException(String.format("A VPC offering with name %s already exists", name));
}
logger.info("Cloning VPC offering {} (id: {}) to new offering with name: {}",
sourceVpcOffering.getName(), sourceVpcOfferingId, name);
applySourceOfferingValuesToCloneCmd(cmd, sourceVpcOffering);
Map<Network.Service, Set<Network.Provider>> sourceServiceProviderMap = getVpcOffSvcProvidersMap(sourceVpcOfferingId);
validateProvider(sourceVpcOffering, sourceServiceProviderMap, cmd.getProvider(), cmd.getNetworkMode());
applySourceOfferingValuesToCloneCmd(cmd, sourceServiceProviderMap, sourceVpcOffering);
return createVpcOffering(cmd);
}
private void applySourceOfferingValuesToCloneCmd(CloneVPCOfferingCmd cmd, VpcOffering sourceVpcOffering) {
Long sourceOfferingId = sourceVpcOffering.getId();
private void validateProvider(VpcOffering sourceVpcOffering,
Map<Network.Service, Set<Network.Provider>> sourceServiceProviderMap,
String provider, String networkMode) {
provider = ConfigurationManagerImpl.getExternalNetworkProvider(provider, sourceServiceProviderMap);
if (provider != null && (provider.equals("NSX") || provider.equals("Netris"))) {
if (networkMode != null && sourceVpcOffering.getNetworkMode() != null) {
if (!networkMode.equalsIgnoreCase(sourceVpcOffering.getNetworkMode().toString())) {
throw new InvalidParameterValueException(
String.format("Cannot change network mode when cloning %s provider VPC offerings. " +
"Source offering has network mode '%s', but '%s' was specified. ",
provider, sourceVpcOffering.getNetworkMode(), networkMode));
}
}
}
}
Map<Network.Service, Set<Network.Provider>> sourceServiceProviderMap = getVpcOffSvcProvidersMap(sourceOfferingId);
private void applySourceOfferingValuesToCloneCmd(CloneVPCOfferingCmd cmd,
Map<Network.Service, Set<Network.Provider>> sourceServiceProviderMap,
VpcOffering sourceVpcOffering) {
Long sourceOfferingId = sourceVpcOffering.getId();
List<String> finalServices = resolveFinalServicesList(cmd, sourceServiceProviderMap);

View File

@ -90,11 +90,15 @@ import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.test.util.ReflectionTestUtils;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
@ -1292,4 +1296,89 @@ public class ConfigurationManagerImplTest {
Assert.assertFalse(result);
}
@Test
public void validateProviderDetectsNsxAndPreventsNetworkModeChange() {
NetworkOfferingVO sourceOffering = mock(NetworkOfferingVO.class);
when(sourceOffering.getNetworkMode()).thenReturn(NetworkOffering.NetworkMode.NATTED);
Map<Network.Service, Set<Network.Provider>> serviceProviderMap = new HashMap<>();
Set<Network.Provider> providers = new HashSet<>();
providers.add(Network.Provider.Nsx);
serviceProviderMap.put(Network.Service.Firewall, providers);
try {
Method method = null;
try {
method = configurationManagerImplSpy.getClass().getDeclaredMethod("validateProvider", NetworkOfferingVO.class, Map.class, String.class, String.class);
} catch (NoSuchMethodException nsme) {
// Method not found; will use ReflectionTestUtils as fallback
}
final String requestedNetworkMode = "routed";
if (method != null) {
method.setAccessible(true);
try {
method.invoke(configurationManagerImplSpy, sourceOffering, serviceProviderMap, null, requestedNetworkMode);
Assert.fail("Expected InvalidParameterValueException to be thrown");
} catch (InvocationTargetException ite) {
Throwable cause = ite.getCause();
if (cause instanceof InvalidParameterValueException) {
return;
}
cause.printStackTrace(System.out);
Assert.fail("Unexpected exception type: " + cause);
}
}
} catch (Exception e) {
e.printStackTrace(System.out);
Assert.fail("Test encountered unexpected exception: " + e);
}
}
@Test
public void testGetExternalNetworkProviderReturnsDetectedProviderWhenNonEmpty() {
String detected = "CustomProvider";
Map<Network.Service, Set<Network.Provider>> serviceProviderMap = new HashMap<>();
String result = ConfigurationManagerImpl.getExternalNetworkProvider(detected, serviceProviderMap);
Assert.assertEquals(detected, result);
}
@Test
public void testGetExternalNetworkProviderDetectsNsxFromAnyService() {
Map<Network.Service, Set<Network.Provider>> serviceProviderMap = new HashMap<>();
Set<Network.Provider> providers = new HashSet<>();
providers.add(Network.Provider.Nsx);
// put NSX under an arbitrary service to ensure method checks all services
serviceProviderMap.put(Network.Service.Dhcp, providers);
String result = ConfigurationManagerImpl.getExternalNetworkProvider(null, serviceProviderMap);
Assert.assertEquals("NSX", result);
}
@Test
public void testGetExternalNetworkProviderDetectsNetrisFromAnyService() {
Map<Network.Service, Set<Network.Provider>> serviceProviderMap = new HashMap<>();
Set<Network.Provider> providers = new HashSet<>();
providers.add(Network.Provider.Netris);
serviceProviderMap.put(Network.Service.StaticNat, providers);
String result = ConfigurationManagerImpl.getExternalNetworkProvider(null, serviceProviderMap);
Assert.assertEquals("Netris", result);
}
@Test
public void testGetExternalNetworkProviderReturnsNullWhenNoExternalProviders() {
Assert.assertNull(ConfigurationManagerImpl.getExternalNetworkProvider(null, null));
Map<Network.Service, Set<Network.Provider>> emptyMap = new HashMap<>();
Assert.assertNull(ConfigurationManagerImpl.getExternalNetworkProvider(null, emptyMap));
Map<Network.Service, Set<Network.Provider>> mapWithEmptySet = new HashMap<>();
mapWithEmptySet.put(Network.Service.Firewall, Collections.emptySet());
Assert.assertNull(ConfigurationManagerImpl.getExternalNetworkProvider(null, mapWithEmptySet));
}
}