|
81 | 81 | import static org.mockito.ArgumentMatchers.anyLong; |
82 | 82 | import static org.mockito.ArgumentMatchers.anyMap; |
83 | 83 | import static org.mockito.ArgumentMatchers.anyString; |
| 84 | +import static org.mockito.ArgumentMatchers.eq; |
84 | 85 | import static org.mockito.ArgumentMatchers.isNull; |
85 | 86 | import static org.mockito.Mockito.mock; |
86 | 87 | import static org.mockito.Mockito.mockStatic; |
| 88 | +import static org.mockito.Mockito.times; |
| 89 | +import static org.mockito.Mockito.verify; |
87 | 90 | import static org.mockito.Mockito.when; |
88 | 91 |
|
89 | 92 | @RunWith(MockitoJUnitRunner.class) |
@@ -230,7 +233,7 @@ private SharedFS prepareDeploySharedFS() throws ResourceUnavailableException, In |
230 | 233 |
|
231 | 234 | DataCenterVO zone = mock(DataCenterVO.class); |
232 | 235 | when(dataCenterDao.findById(s_zoneId)).thenReturn(zone); |
233 | | - when(resourceMgr.getSupportedHypervisorTypes(s_zoneId, false, null)).thenReturn(List.of(Hypervisor.HypervisorType.KVM)); |
| 236 | + when(resourceMgr.getSupportedHypervisorTypes(s_zoneId, true, null)).thenReturn(List.of(Hypervisor.HypervisorType.KVM)); |
234 | 237 |
|
235 | 238 | ServiceOfferingVO serviceOffering = mock(ServiceOfferingVO.class); |
236 | 239 | when(serviceOfferingDao.findById(s_serviceOfferingId)).thenReturn(serviceOffering); |
@@ -274,46 +277,6 @@ public void testDeploySharedFS() throws ResourceUnavailableException, Insufficie |
274 | 277 | Assert.assertEquals(Optional.ofNullable(result.second()), Optional.ofNullable(s_vmId)); |
275 | 278 | } |
276 | 279 |
|
277 | | - @Test |
278 | | - public void testDeploySharedFSContinuesWhenTemplateIsMissingForNonLastHypervisor() throws ResourceUnavailableException, InsufficientCapacityException, ResourceAllocationException, IOException, OperationTimedoutException { |
279 | | - SharedFS sharedFS = prepareDeploySharedFS(); |
280 | | - when(resourceMgr.getSupportedHypervisorTypes(s_zoneId, false, null)).thenReturn(new ArrayList<>(List.of(Hypervisor.HypervisorType.External, Hypervisor.HypervisorType.KVM)) { |
281 | | - @Override |
282 | | - public Hypervisor.HypervisorType set(int index, Hypervisor.HypervisorType element) { |
283 | | - // Keep the test order stable while exercising the production shuffle call. |
284 | | - return get(index); |
285 | | - } |
286 | | - }); |
287 | | - when(templateDao.findSystemVMReadyTemplate(s_zoneId, Hypervisor.HypervisorType.External, ResourceManager.SystemVmPreferredArchitecture.defaultValue())).thenReturn(null); |
288 | | - |
289 | | - Account owner = mock(Account.class); |
290 | | - when(owner.getId()).thenReturn(s_ownerId); |
291 | | - when(accountMgr.getActiveAccountById(s_ownerId)).thenReturn(owner); |
292 | | - |
293 | | - UserVm vm = mock(UserVm.class); |
294 | | - when(vm.getId()).thenReturn(s_vmId); |
295 | | - when(userVmService.createAdvancedVirtualMachine( |
296 | | - any(DataCenter.class), any(ServiceOffering.class), any(VirtualMachineTemplate.class), anyList(), any(Account.class), anyString(), |
297 | | - anyString(), anyLong(), anyLong(), any(), isNull(), any(Hypervisor.HypervisorType.class), any(BaseCmd.HTTPMethod.class), anyString(), |
298 | | - isNull(), isNull(), anyList(), isNull(), any(Network.IpAddresses.class), isNull(), isNull(), isNull(), |
299 | | - anyMap(), isNull(), isNull(), isNull(), isNull(), |
300 | | - anyBoolean(), anyString(), isNull(), isNull(), isNull())).thenReturn(vm); |
301 | | - |
302 | | - VolumeVO rootVol = mock(VolumeVO.class); |
303 | | - when(rootVol.getVolumeType()).thenReturn(Volume.Type.ROOT); |
304 | | - when(rootVol.getName()).thenReturn("ROOT-1"); |
305 | | - VolumeVO dataVol = mock(VolumeVO.class); |
306 | | - when(dataVol.getId()).thenReturn(s_volumeId); |
307 | | - when(dataVol.getName()).thenReturn("DATA-1"); |
308 | | - when(dataVol.getVolumeType()).thenReturn(Volume.Type.DATADISK); |
309 | | - when(volumeDao.findByInstance(s_vmId)).thenReturn(List.of(rootVol, dataVol)); |
310 | | - |
311 | | - Pair<Long, Long> result = lifeCycle.deploySharedFS(sharedFS, s_networkId, s_diskOfferingId, s_size, s_minIops, s_maxIops); |
312 | | - |
313 | | - Assert.assertEquals(Optional.ofNullable(result.first()), Optional.ofNullable(s_volumeId)); |
314 | | - Assert.assertEquals(Optional.ofNullable(result.second()), Optional.ofNullable(s_vmId)); |
315 | | - } |
316 | | - |
317 | 280 | @Test(expected = CloudRuntimeException.class) |
318 | 281 | public void testDeploySharedFSHypervisorNotFound() throws ResourceUnavailableException, InsufficientCapacityException, ResourceAllocationException, IOException, OperationTimedoutException { |
319 | 282 | SharedFS sharedFS = mock(SharedFS.class); |
@@ -341,11 +304,65 @@ public void testDeploySharedFSTemplateNotFound() throws ResourceUnavailableExcep |
341 | 304 | when(accountMgr.getActiveAccountById(s_ownerId)).thenReturn(null); |
342 | 305 | DataCenterVO zone = mock(DataCenterVO.class); |
343 | 306 | when(dataCenterDao.findById(s_zoneId)).thenReturn(zone); |
344 | | - when(resourceMgr.getSupportedHypervisorTypes(s_zoneId, false, null)).thenReturn(List.of(Hypervisor.HypervisorType.KVM)); |
| 307 | + when(resourceMgr.getSupportedHypervisorTypes(s_zoneId, true, null)).thenReturn(List.of(Hypervisor.HypervisorType.KVM)); |
345 | 308 |
|
346 | 309 | lifeCycle.deploySharedFS(sharedFS, s_networkId, s_diskOfferingId, s_size, s_minIops, s_maxIops); |
347 | 310 | } |
348 | 311 |
|
| 312 | + @Test |
| 313 | + public void testDeploySharedFSSkipsHypervisorWithoutTemplate() throws ResourceUnavailableException, InsufficientCapacityException, ResourceAllocationException, IOException, OperationTimedoutException { |
| 314 | + // Verifies that when the systemvm template is missing for one of the supported hypervisors, |
| 315 | + // deploySharedFSVM() skips it and tries the next one instead of failing with an NPE. |
| 316 | + SharedFS sharedFS = mock(SharedFS.class); |
| 317 | + when(sharedFS.getDataCenterId()).thenReturn(s_zoneId); |
| 318 | + when(sharedFS.getName()).thenReturn(s_name); |
| 319 | + when(sharedFS.getServiceOfferingId()).thenReturn(s_serviceOfferingId); |
| 320 | + when(sharedFS.getFsType()).thenReturn(SharedFS.FileSystemType.valueOf(s_fsFormat)); |
| 321 | + when(sharedFS.getAccountId()).thenReturn(s_ownerId); |
| 322 | + |
| 323 | + Account owner = mock(Account.class); |
| 324 | + when(owner.getId()).thenReturn(s_ownerId); |
| 325 | + when(accountMgr.getActiveAccountById(s_ownerId)).thenReturn(owner); |
| 326 | + |
| 327 | + DataCenterVO zone = mock(DataCenterVO.class); |
| 328 | + when(dataCenterDao.findById(s_zoneId)).thenReturn(zone); |
| 329 | + |
| 330 | + List<Hypervisor.HypervisorType> hypervisors = new ArrayList<>(List.of(Hypervisor.HypervisorType.XenServer, Hypervisor.HypervisorType.KVM)); |
| 331 | + when(resourceMgr.getSupportedHypervisorTypes(s_zoneId, true, null)).thenReturn(hypervisors); |
| 332 | + |
| 333 | + ServiceOfferingVO serviceOffering = mock(ServiceOfferingVO.class); |
| 334 | + when(serviceOfferingDao.findById(s_serviceOfferingId)).thenReturn(serviceOffering); |
| 335 | + |
| 336 | + // The hypervisor list is shuffled before iteration, so instead of pinning which hypervisor is |
| 337 | + // tried first, the first lookup (whichever hypervisor that is) returns no template and the |
| 338 | + // second lookup returns a valid one, exercising the "skip and try the next hypervisor" fix. |
| 339 | + VMTemplateVO template = mock(VMTemplateVO.class); |
| 340 | + when(template.getId()).thenReturn(s_templateId); |
| 341 | + when(templateDao.findSystemVMReadyTemplate(eq(s_zoneId), any(Hypervisor.HypervisorType.class), eq(ResourceManager.SystemVmPreferredArchitecture.defaultValue()))) |
| 342 | + .thenReturn(null, template); |
| 343 | + |
| 344 | + UserVm vm = mock(UserVm.class); |
| 345 | + when(vm.getId()).thenReturn(s_vmId); |
| 346 | + when(userVmService.createAdvancedVirtualMachine( |
| 347 | + any(DataCenter.class), any(ServiceOffering.class), any(VirtualMachineTemplate.class), anyList(), any(Account.class), anyString(), |
| 348 | + anyString(), anyLong(), anyLong(), any(), isNull(), any(Hypervisor.HypervisorType.class), any(BaseCmd.HTTPMethod.class), anyString(), |
| 349 | + isNull(), isNull(), anyList(), isNull(), any(Network.IpAddresses.class), isNull(), isNull(), isNull(), |
| 350 | + anyMap(), isNull(), isNull(), isNull(), isNull(), |
| 351 | + anyBoolean(), anyString(), isNull(), isNull(), isNull())).thenReturn(vm); |
| 352 | + |
| 353 | + VolumeVO dataVol = mock(VolumeVO.class); |
| 354 | + when(dataVol.getId()).thenReturn(s_volumeId); |
| 355 | + when(dataVol.getName()).thenReturn("DATA-1"); |
| 356 | + when(dataVol.getVolumeType()).thenReturn(Volume.Type.DATADISK); |
| 357 | + when(volumeDao.findByInstance(s_vmId)).thenReturn(List.of(dataVol)); |
| 358 | + |
| 359 | + Pair<Long, Long> result = lifeCycle.deploySharedFS(sharedFS, s_networkId, s_diskOfferingId, s_size, s_minIops, s_maxIops); |
| 360 | + Assert.assertEquals(Optional.of(s_volumeId), Optional.ofNullable(result.first())); |
| 361 | + Assert.assertEquals(Optional.of(s_vmId), Optional.ofNullable(result.second())); |
| 362 | + |
| 363 | + verify(templateDao, times(2)).findSystemVMReadyTemplate(eq(s_zoneId), any(Hypervisor.HypervisorType.class), eq(ResourceManager.SystemVmPreferredArchitecture.defaultValue())); |
| 364 | + } |
| 365 | + |
349 | 366 | @Test |
350 | 367 | public void testDeleteSharedFS() throws ResourceUnavailableException { |
351 | 368 | SharedFS sharedFS = mock(SharedFS.class); |
|
0 commit comments