Skip to content

Commit 6a18cdd

Browse files
committed
Merge pull request apache#1825 from Accelerite/CLOUDSTACK-9660
CLOUDSTACK-9660: NPE while destroying volumes during 1000 VMs deploy and destroy tests NPE is seen as VM destroy and storage cleanup threads try to remove the same root volume. Fix is to handle only non-root volumes in storage cleanup thread, root volumes will be handled as part of VM destroy. * pr/1825: CLOUDSTACK-9660: NPE while destroying volumes during 1000 VMs deploy and destroy tests NPE is seen as VM destroy and storage cleanup threads try to remove the same root volume. Fix is to handle only non-root volumes in storage cleanup thread, root volumes will be handled as part of VM destroy. Signed-off-by: Rajani Karuturi <rajani.karuturi@accelerite.com>
2 parents 017c42b + d6b41d9 commit 6a18cdd

5 files changed

Lines changed: 21 additions & 8 deletions

File tree

engine/schema/src/com/cloud/storage/dao/VolumeDao.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ public interface VolumeDao extends GenericDao<VolumeVO, Long>, StateDao<Volume.S
8080

8181
List<VolumeVO> listVolumesToBeDestroyed();
8282

83-
List<VolumeVO> listVolumesToBeDestroyed(Date date);
83+
List<VolumeVO> listNonRootVolumesToBeDestroyed(Date date);
8484

8585
ImageFormat getImageFormat(Long volumeId);
8686

engine/schema/src/com/cloud/storage/dao/VolumeDaoImpl.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,7 @@ public VolumeDaoImpl() {
325325
AllFieldsSearch.and("deviceId", AllFieldsSearch.entity().getDeviceId(), Op.EQ);
326326
AllFieldsSearch.and("poolId", AllFieldsSearch.entity().getPoolId(), Op.EQ);
327327
AllFieldsSearch.and("vType", AllFieldsSearch.entity().getVolumeType(), Op.EQ);
328+
AllFieldsSearch.and("notVolumeType", AllFieldsSearch.entity().getVolumeType(), Op.NEQ);
328329
AllFieldsSearch.and("id", AllFieldsSearch.entity().getId(), Op.EQ);
329330
AllFieldsSearch.and("destroyed", AllFieldsSearch.entity().getState(), Op.EQ);
330331
AllFieldsSearch.and("notDestroyed", AllFieldsSearch.entity().getState(), Op.NEQ);
@@ -481,9 +482,10 @@ public List<VolumeVO> listVolumesToBeDestroyed() {
481482
}
482483

483484
@Override
484-
public List<VolumeVO> listVolumesToBeDestroyed(Date date) {
485+
public List<VolumeVO> listNonRootVolumesToBeDestroyed(Date date) {
485486
SearchCriteria<VolumeVO> sc = AllFieldsSearch.create();
486487
sc.setParameters("state", Volume.State.Destroy);
488+
sc.setParameters("notVolumeType", Volume.Type.ROOT.toString());
487489
sc.setParameters("updateTime", date);
488490

489491
return listBy(sc);

engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -174,11 +174,11 @@ public long getVolumeId() {
174174
}
175175

176176
@Override
177-
public boolean stateTransit(Volume.Event event) {
177+
public boolean stateTransit(Volume.Event event) {
178178
boolean result = false;
179179
try {
180180
volumeVO = volumeDao.findById(volumeVO.getId());
181-
if(volumeVO != null) {
181+
if (volumeVO != null) {
182182
result = _volStateMachine.transitTo(volumeVO, event, null, volumeDao);
183183
volumeVO = volumeDao.findById(volumeVO.getId());
184184
}
@@ -332,8 +332,9 @@ public void processEvent(ObjectInDataStoreStateMachine.Event event) {
332332
throw new CloudRuntimeException("Failed to update state:" + e.toString());
333333
} finally {
334334
// in case of OperationFailed, expunge the entry
335+
// state transit call reloads the volume from DB and so check for null as well
335336
if (event == ObjectInDataStoreStateMachine.Event.OperationFailed &&
336-
(volumeVO.getState() != Volume.State.Copying && volumeVO.getState() != Volume.State.Uploaded && volumeVO.getState() != Volume.State.UploadError)) {
337+
(volumeVO != null && volumeVO.getState() != Volume.State.Copying && volumeVO.getState() != Volume.State.Uploaded && volumeVO.getState() != Volume.State.UploadError)) {
337338
objectInStoreMgr.deleteIfNotReady(this);
338339
}
339340
}

engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,11 @@ public AsyncCallFuture<VolumeApiResult> expungeVolumeAsync(VolumeInfo volume) {
316316
}
317317

318318
VolumeVO vol = volDao.findById(volume.getId());
319+
if (vol == null) {
320+
s_logger.debug("Volume " + volume.getId() + " is not found");
321+
future.complete(result);
322+
return future;
323+
}
319324

320325
if (!volumeExistsOnPrimary(vol)) {
321326
// not created on primary store

server/src/com/cloud/storage/StorageManagerImpl.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1080,8 +1080,8 @@ public void cleanupStorage(boolean recurring) {
10801080

10811081
cleanupSecondaryStorage(recurring);
10821082

1083-
List<VolumeVO> vols = _volsDao.listVolumesToBeDestroyed(new Date(System.currentTimeMillis() - ((long) StorageCleanupDelay.value() << 10)));
1084-
1083+
// ROOT volumes will be destroyed as part of VM cleanup
1084+
List<VolumeVO> vols = _volsDao.listNonRootVolumesToBeDestroyed(new Date(System.currentTimeMillis() - ((long) StorageCleanupDelay.value() << 10)));
10851085
for (VolumeVO vol : vols) {
10861086
try {
10871087
// If this fails, just log a warning. It's ideal if we clean up the host-side clustered file
@@ -1092,7 +1092,12 @@ public void cleanupStorage(boolean recurring) {
10921092
}
10931093

10941094
try {
1095-
volService.expungeVolumeAsync(volFactory.getVolume(vol.getId()));
1095+
VolumeInfo volumeInfo = volFactory.getVolume(vol.getId());
1096+
if (volumeInfo != null) {
1097+
volService.expungeVolumeAsync(volumeInfo);
1098+
} else {
1099+
s_logger.debug("Volume " + vol.getUuid() + " is already destroyed");
1100+
}
10961101
} catch (Exception e) {
10971102
s_logger.warn("Unable to destroy volume " + vol.getUuid(), e);
10981103
}

0 commit comments

Comments
 (0)