-
Notifications
You must be signed in to change notification settings - Fork 1.3k
CLOUDSTACK-9570: Bug in listSnapshots for snapshots with deleted data stores #1735
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -24,8 +24,6 @@ | |
| import javax.annotation.PostConstruct; | ||
| import javax.inject.Inject; | ||
|
|
||
| import org.springframework.stereotype.Component; | ||
|
|
||
| import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProvider; | ||
| import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProviderManager; | ||
| import org.apache.cloudstack.engine.subsystem.api.storage.HypervisorHostListener; | ||
|
|
@@ -35,6 +33,7 @@ | |
| import org.apache.cloudstack.storage.datastore.PrimaryDataStoreProviderManager; | ||
| import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; | ||
| import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; | ||
| import org.springframework.stereotype.Component; | ||
|
|
||
| import com.cloud.storage.StorageManager; | ||
| import com.cloud.utils.exception.CloudRuntimeException; | ||
|
|
@@ -56,7 +55,7 @@ public void config() { | |
|
|
||
| @Override | ||
| public PrimaryDataStore getPrimaryDataStore(long dataStoreId) { | ||
| StoragePoolVO dataStoreVO = dataStoreDao.findById(dataStoreId); | ||
| StoragePoolVO dataStoreVO = dataStoreDao.findByIdIncludingRemoved(dataStoreId); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is getPrimaryDataStore(long) called from many places? If so, it might be a bit risky to change this from findById to findByIdIncludingRemoved unless we are pretty sure all of the calling code is OK with that change. |
||
| if (dataStoreVO == null) { | ||
| throw new CloudRuntimeException("Unable to locate datastore with id " + dataStoreId); | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -142,6 +142,7 @@ | |
| import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; | ||
| import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreCapabilities; | ||
| import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; | ||
| import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; | ||
| import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory; | ||
| import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo; | ||
| import org.apache.cloudstack.framework.jobs.AsyncJob; | ||
|
|
@@ -493,7 +494,9 @@ public SnapshotResponse createSnapshotResponse(Snapshot snapshot) { | |
| snapshotInfo = (SnapshotInfo)snapshot; | ||
| } else { | ||
| DataStoreRole dataStoreRole = getDataStoreRole(snapshot, _snapshotStoreDao, _dataStoreMgr); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would say the default should be DataStoreRole.Image for getDataStoreRole and so getDataStoreRole should probably never return null. |
||
|
|
||
| if (dataStoreRole == null){ | ||
| return null; | ||
| } | ||
| snapshotInfo = snapshotfactory.getSnapshot(snapshot.getId(), dataStoreRole); | ||
| } | ||
|
|
||
|
|
@@ -526,16 +529,18 @@ public static DataStoreRole getDataStoreRole(Snapshot snapshot, SnapshotDataStor | |
| } | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Another possibility here is that we could simply still try to retrieve "dataStore" and then perform this check: If "dataStore" equals null, then it was removed, which should only be something that happened when unmanaged storage is being used (thus when the the snapshot resides on secondary storage). |
||
|
|
||
| long storagePoolId = snapshotStore.getDataStoreId(); | ||
| DataStore dataStore = dataStoreMgr.getDataStore(storagePoolId, DataStoreRole.Primary); | ||
| if (snapshotStore.getState() != null && ! snapshotStore.getState().equals(ObjectInDataStoreStateMachine.State.Destroyed)) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As pointed out by @mike-tutkowski store cannot be destroyed if there are snapshots. Also that enum is meant for snapshot (and entities like that) and not for snapshot store.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For managed storage, that is true. For unmanaged storage, one should be able to delete the primary storage from which a snapshot was created and the snapshot should be able to remain (since the snapshot, in this case, is on secondary storage). |
||
| DataStore dataStore = dataStoreMgr.getDataStore(storagePoolId, DataStoreRole.Primary); | ||
|
|
||
| Map<String, String> mapCapabilities = dataStore.getDriver().getCapabilities(); | ||
| Map<String, String> mapCapabilities = dataStore.getDriver().getCapabilities(); | ||
|
|
||
| if (mapCapabilities != null) { | ||
| String value = mapCapabilities.get(DataStoreCapabilities.STORAGE_SYSTEM_SNAPSHOT.toString()); | ||
| Boolean supportsStorageSystemSnapshots = new Boolean(value); | ||
| if (mapCapabilities != null) { | ||
| String value = mapCapabilities.get(DataStoreCapabilities.STORAGE_SYSTEM_SNAPSHOT.toString()); | ||
| Boolean supportsStorageSystemSnapshots = Boolean.valueOf(value); | ||
|
|
||
| if (supportsStorageSystemSnapshots) { | ||
| return DataStoreRole.Primary; | ||
| if (supportsStorageSystemSnapshots) { | ||
| return DataStoreRole.Primary; | ||
| } | ||
| } | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -517,10 +517,10 @@ public Pair<List<? extends Snapshot>, Integer> listSnapshots(ListSnapshotsCmd cm | |
| List<Long> ids = getIdsListFromCmd(cmd.getId(), cmd.getIds()); | ||
|
|
||
| Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject = new Ternary<Long, Boolean, ListProjectResourcesCriteria>(cmd.getDomainId(), cmd.isRecursive(), null); | ||
| _accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccounts, domainIdRecursiveListProject, cmd.listAll(), false); | ||
| Long domainId = domainIdRecursiveListProject.first(); | ||
| Boolean isRecursive = domainIdRecursiveListProject.second(); | ||
| ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third(); | ||
| _accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccounts, domainIdRecursiveListProject, cmd.listAll(), false); | ||
| Long domainId = domainIdRecursiveListProject.first(); | ||
| Boolean isRecursive = domainIdRecursiveListProject.second(); | ||
| ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third(); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @nvazquez What is changed here?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hi @anshul1886, at the beggining of each line there's one space added, to be consistent with indentation There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These type of changes should not be done on unrelated file as it makes following changes difficult. |
||
|
|
||
| Filter searchFilter = new Filter(SnapshotVO.class, "created", false, cmd.getStartIndex(), cmd.getPageSizeVal()); | ||
| SearchBuilder<SnapshotVO> sb = _snapshotDao.createSearchBuilder(); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is any issue observed here for which null check is added?
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This check is added as we introduced a case in
createSnapshotResponsewhere null is returned, and in that case we shouldn't add the response to the response listThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the use case for null case when that can happen?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added a few comments.
If we implement those comments, then null should not be a problem here (in other words, the code in this class could remain unchanged).