CLOUDSTACK-9180: Optimize concurrent VM deployment operation on same network

Check if VR needs to be allocated for a given network and only acquire lock if required
This commit is contained in:
Koushik Das 2015-12-16 17:53:03 +05:30
parent 94a14485f7
commit de8942644d
2 changed files with 65 additions and 18 deletions

View File

@ -193,28 +193,45 @@ public class RouterDeploymentDefinition {
}
public List<DomainRouterVO> deployVirtualRouter() throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException {
findOrDeployVirtualRouter();
return nwHelper.startRouters(this);
}
private boolean isRouterDeployed() throws ResourceUnavailableException {
boolean isDeployed = true;
checkPreconditions();
final List<DeployDestination> destinations = findDestinations();
for (final DeployDestination destination : destinations) {
dest = destination;
generateDeploymentPlan();
planDeploymentRouters();
if (getNumberOfRoutersToDeploy() > 0 && prepareDeployment()) {
isDeployed = false;
break;
}
}
return isDeployed;
}
@DB
protected void findOrDeployVirtualRouter() throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException {
try {
lock();
checkPreconditions();
if (!isRouterDeployed()) {
try {
lock();
// reset router list that got populated during isRouterDeployed()
routers.clear();
checkPreconditions();
// dest has pod=null, for Basic Zone findOrDeployVRs for all Pods
final List<DeployDestination> destinations = findDestinations();
for (final DeployDestination destination : destinations) {
dest = destination;
generateDeploymentPlan();
executeDeployment();
// dest has pod=null, for Basic Zone findOrDeployVRs for all Pods
final List<DeployDestination> destinations = findDestinations();
for (final DeployDestination destination : destinations) {
dest = destination;
generateDeploymentPlan();
executeDeployment();
}
} finally {
unlock();
}
} finally {
unlock();
}
}
@ -378,7 +395,7 @@ public class RouterDeploymentDefinition {
final PhysicalNetworkServiceProvider provider = physicalProviderDao.findByServiceProvider(physicalNetworkId, type.toString());
if (provider == null) {
throw new CloudRuntimeException(String.format("Cannot find service provider %s in physical network %s", type.toString(), physicalNetworkId));
throw new CloudRuntimeException(String.format("Cannot find service provider %s in physical network %s", type.toString(), physicalNetworkId));
}
vrProvider = vrProviderDao.findByNspIdAndType(provider.getId(), type);

View File

@ -513,9 +513,9 @@ public class RouterDeploymentDefinitionTest extends RouterDeploymentDefinitionTe
} finally {
// Assert
verify(deploymentUT, times(1)).lock();
verify(deploymentUT, times(1)).checkPreconditions();
verify(deploymentUT, times(1)).findDestinations();
verify(deploymentUT, times(2)).generateDeploymentPlan();
verify(deploymentUT, times(2)).checkPreconditions();
verify(deploymentUT, times(2)).findDestinations();
verify(deploymentUT, times(3)).generateDeploymentPlan();
verify(deploymentUT, times(2)).executeDeployment();
//verify(deploymentUT, times(2)).planDeploymentRouters();
verify(deploymentUT, times(1)).unlock();
@ -524,6 +524,36 @@ public class RouterDeploymentDefinitionTest extends RouterDeploymentDefinitionTe
fail();
}
@Test
public void testDeployVirtualRouterSkip() throws ConcurrentOperationException,
InsufficientCapacityException, ResourceUnavailableException {
// Prepare
final List<DeployDestination> mockDestinations = new ArrayList<>();
mockDestinations.add(mock(DeployDestination.class));
mockDestinations.add(mock(DeployDestination.class));
final RouterDeploymentDefinition deploymentUT = spy(deployment);
doNothing().when(deploymentUT).checkPreconditions();
doReturn(mockDestinations).when(deploymentUT).findDestinations();
doNothing().when(deploymentUT).planDeploymentRouters();
doNothing().when(deploymentUT).generateDeploymentPlan();
doReturn(0).when(deploymentUT).getNumberOfRoutersToDeploy();
// Execute
try {
deploymentUT.findOrDeployVirtualRouter();
} finally {
// Assert
verify(deploymentUT, times(0)).lock(); // lock shouldn't be acquired when VR already present
verify(deploymentUT, times(1)).checkPreconditions();
verify(deploymentUT, times(1)).findDestinations();
verify(deploymentUT, times(2)).generateDeploymentPlan();
verify(deploymentUT, times(0)).executeDeployment(); // no need to deploy VR as already present
verify(deploymentUT, times(0)).unlock(); // same as lock
}
}
@Test
public void testGetNumberOfRoutersToDeploy() {
// Prepare