Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,10 @@
import com.cloud.network.dao.PhysicalNetworkDao;
import com.cloud.network.dao.PhysicalNetworkVO;
import com.cloud.network.vpc.Vpc;
import com.cloud.network.vpc.dao.VpcOfferingDao;
import com.cloud.network.vpc.dao.VpcOfferingServiceMapDao;
import com.cloud.network.vpc.dao.VpcServiceMapDao;
import com.cloud.offerings.dao.NetworkOfferingDao;
import com.cloud.offerings.dao.NetworkOfferingServiceMapDao;
import com.cloud.org.Cluster;
import com.cloud.serializer.GsonHelper;
Expand Down Expand Up @@ -248,6 +250,12 @@
@Inject
VpcOfferingServiceMapDao vpcOfferingServiceMapDao;

@Inject

Check warning on line 253 in framework/extensions/src/main/java/org/apache/cloudstack/framework/extensions/manager/ExtensionsManagerImpl.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this field injection and use constructor injection instead.

See more on https://sonarcloud.io/project/issues?id=apache_cloudstack&issues=AaEckB1LAL6E-fKsC3-i&open=AaEckB1LAL6E-fKsC3-i&pullRequest=14370
NetworkOfferingDao networkOfferingDao;

@Inject

Check warning on line 256 in framework/extensions/src/main/java/org/apache/cloudstack/framework/extensions/manager/ExtensionsManagerImpl.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this field injection and use constructor injection instead.

See more on https://sonarcloud.io/project/issues?id=apache_cloudstack&issues=AaEckB1LAL6E-fKsC3-j&open=AaEckB1LAL6E-fKsC3-j&pullRequest=14370
VpcOfferingDao vpcOfferingDao;

@Inject
NetworkModel networkModel;

Expand Down Expand Up @@ -1306,10 +1314,13 @@
return;
}
for (Service removedService : removedServices) {
boolean usedByNetworkOffering = CollectionUtils.isNotEmpty(
networkOfferingServiceMapDao.listOfferingIdsByServiceAndProvider(removedService, extension.getName()));
boolean usedByVpcOffering = CollectionUtils.isNotEmpty(
vpcOfferingServiceMapDao.listOfferingIdsByServiceAndProvider(removedService, extension.getName()));
// offering service map rows are kept when an offering is deleted, so ignore removed offerings
boolean usedByNetworkOffering = networkOfferingServiceMapDao
.listOfferingIdsByServiceAndProvider(removedService, extension.getName()).stream()
.anyMatch(offeringId -> networkOfferingDao.findById(offeringId) != null);
boolean usedByVpcOffering = vpcOfferingServiceMapDao
.listOfferingIdsByServiceAndProvider(removedService, extension.getName()).stream()
Comment on lines +1318 to +1322
.anyMatch(offeringId -> vpcOfferingDao.findById(offeringId) != null);
Comment on lines +1318 to +1323
if (usedByNetworkOffering || usedByVpcOffering) {
throw new CloudRuntimeException(String.format(
"Cannot remove service %s from extension '%s' as it is used by a network/VPC offering",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import org.apache.cloudstack.acl.Role;
Expand Down Expand Up @@ -139,8 +140,12 @@
import com.cloud.network.dao.PhysicalNetworkVO;
import com.cloud.network.element.NetworkElement;
import com.cloud.network.vpc.Vpc;
import com.cloud.network.vpc.VpcOfferingVO;
import com.cloud.network.vpc.dao.VpcOfferingDao;
import com.cloud.network.vpc.dao.VpcOfferingServiceMapDao;
import com.cloud.network.vpc.dao.VpcServiceMapDao;
import com.cloud.offerings.NetworkOfferingVO;
import com.cloud.offerings.dao.NetworkOfferingDao;
import com.cloud.offerings.dao.NetworkOfferingServiceMapDao;
import org.apache.cloudstack.extension.NetworkCustomActionProvider;
import com.cloud.org.Cluster;
Expand Down Expand Up @@ -223,6 +228,12 @@
@Mock
private VpcOfferingServiceMapDao vpcOfferingServiceMapDao;

@Mock
private NetworkOfferingDao networkOfferingDao;

@Mock
private VpcOfferingDao vpcOfferingDao;

@Before
public void setUp() {
MockitoAnnotations.openMocks(this);
Expand Down Expand Up @@ -961,6 +972,7 @@

when(networkOfferingServiceMapDao.listOfferingIdsByServiceAndProvider(Network.Service.StaticNat, "MyExt"))
.thenReturn(Collections.singletonList(1L));
when(networkOfferingDao.findById(1L)).thenReturn(mock(NetworkOfferingVO.class));

Check warning on line 975 in framework/extensions/src/test/java/org/apache/cloudstack/framework/extensions/manager/ExtensionsManagerImplTest.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Extract this mock creation to a local variable.

See more on https://sonarcloud.io/project/issues?id=apache_cloudstack&issues=AaEckBw-AL6E-fKsC3-g&open=AaEckBw-AL6E-fKsC3-g&pullRequest=14370

extensionsManager.updateExtension(cmd);
}
Expand Down Expand Up @@ -992,10 +1004,42 @@
.thenReturn(Collections.emptyList());
when(vpcOfferingServiceMapDao.listOfferingIdsByServiceAndProvider(Network.Service.StaticNat, "MyExt"))
.thenReturn(Collections.singletonList(1L));
when(vpcOfferingDao.findById(1L)).thenReturn(mock(VpcOfferingVO.class));

Check warning on line 1007 in framework/extensions/src/test/java/org/apache/cloudstack/framework/extensions/manager/ExtensionsManagerImplTest.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Extract this mock creation to a local variable.

See more on https://sonarcloud.io/project/issues?id=apache_cloudstack&issues=AaEckBw-AL6E-fKsC3-h&open=AaEckBw-AL6E-fKsC3-h&pullRequest=14370

extensionsManager.updateExtension(cmd);
}

@Test
public void updateNetworkExtensionServicesOnPhysicalNetworks_IgnoresRemovedOfferings() {
ExtensionVO ext = mock(ExtensionVO.class);
when(ext.getId()).thenReturn(9L);
when(ext.getName()).thenReturn("MyExt");

// service map rows still reference offerings 1 (network) and 2 (VPC), but both offerings are removed
when(networkOfferingServiceMapDao.listOfferingIdsByServiceAndProvider(Network.Service.CustomAction, "MyExt"))
.thenReturn(Collections.singletonList(1L));
when(vpcOfferingServiceMapDao.listOfferingIdsByServiceAndProvider(Network.Service.CustomAction, "MyExt"))
.thenReturn(Collections.singletonList(2L));
when(networkOfferingDao.findById(1L)).thenReturn(null);
when(vpcOfferingDao.findById(2L)).thenReturn(null);

when(extensionResourceMapDao.listResourceIdsByExtensionIdAndType(9L, ExtensionResourceMap.ResourceType.PhysicalNetwork))
.thenReturn(Collections.singletonList(100L));
PhysicalNetworkServiceProviderVO nsp = mock(PhysicalNetworkServiceProviderVO.class);
when(nsp.getId()).thenReturn(500L);
when(nsp.getEnabledServices()).thenReturn(new ArrayList<>(Collections.singletonList(Network.Service.CustomAction)));
when(physicalNetworkServiceProviderDao.findByServiceProvider(100L, "MyExt")).thenReturn(nsp);

extensionsManager.updateNetworkExtensionServicesOnPhysicalNetworks(ext,
Set.of(Network.Service.CustomAction), Set.of(Network.Service.UserData));

ArgumentCaptor<List<Network.Service>> captor = ArgumentCaptor.forClass(List.class);
verify(nsp).setEnabledServices(captor.capture());
assertFalse(captor.getValue().contains(Network.Service.CustomAction));
assertTrue(captor.getValue().contains(Network.Service.UserData));
verify(physicalNetworkServiceProviderDao).update(500L, nsp);
}

@Test
public void testUpdateExtension_UpdatesPhysicalNetworkServicesWhenNotInUse() {
UpdateExtensionCmd cmd = mock(UpdateExtensionCmd.class);
Expand Down
Loading