Merge branch '4.22'

This commit is contained in:
Suresh Kumar Anaparti 2026-01-19 19:50:51 +05:30
commit 04b58acdd6
No known key found for this signature in database
GPG Key ID: D7CEAE3A9E71D0AA
22 changed files with 162 additions and 104 deletions

View File

@ -30,6 +30,8 @@ public interface SnapshotDataFactory {
SnapshotInfo getSnapshot(long snapshotId, long storeId, DataStoreRole role); SnapshotInfo getSnapshot(long snapshotId, long storeId, DataStoreRole role);
SnapshotInfo getSnapshotIncludingRemoved(long snapshotId, long storeId, DataStoreRole role);
SnapshotInfo getSnapshotWithRoleAndZone(long snapshotId, DataStoreRole role, long zoneId); SnapshotInfo getSnapshotWithRoleAndZone(long snapshotId, DataStoreRole role, long zoneId);
SnapshotInfo getSnapshotOnPrimaryStore(long snapshotId); SnapshotInfo getSnapshotOnPrimaryStore(long snapshotId);

View File

@ -47,6 +47,8 @@ public interface SnapshotDao extends GenericDao<SnapshotVO, Long>, StateDao<Snap
List<SnapshotVO> listAllByStatus(Snapshot.State... status); List<SnapshotVO> listAllByStatus(Snapshot.State... status);
List<SnapshotVO> listAllByStatusIncludingRemoved(Snapshot.State... status);
void updateVolumeIds(long oldVolId, long newVolId); void updateVolumeIds(long oldVolId, long newVolId);
List<SnapshotVO> listByStatusNotIn(long volumeId, Snapshot.State... status); List<SnapshotVO> listByStatusNotIn(long volumeId, Snapshot.State... status);

View File

@ -265,6 +265,13 @@ public class SnapshotDaoImpl extends GenericDaoBase<SnapshotVO, Long> implements
return listBy(sc, null); return listBy(sc, null);
} }
@Override
public List<SnapshotVO> listAllByStatusIncludingRemoved(Snapshot.State... status) {
SearchCriteria<SnapshotVO> sc = StatusSearch.create();
sc.setParameters("status", (Object[])status);
return listIncludingRemovedBy(sc, null);
}
@Override @Override
public List<SnapshotVO> listByIds(Object... ids) { public List<SnapshotVO> listByIds(Object... ids) {
SearchCriteria<SnapshotVO> sc = snapshotIdsSearch.create(); SearchCriteria<SnapshotVO> sc = snapshotIdsSearch.create();

View File

@ -52,7 +52,7 @@ public class UsageDaoImpl extends GenericDaoBase<UsageVO, Long> implements Usage
private static final String DELETE_ALL = "DELETE FROM cloud_usage"; private static final String DELETE_ALL = "DELETE FROM cloud_usage";
private static final String DELETE_ALL_BY_ACCOUNTID = "DELETE FROM cloud_usage WHERE account_id = ?"; private static final String DELETE_ALL_BY_ACCOUNTID = "DELETE FROM cloud_usage WHERE account_id = ?";
private static final String DELETE_ALL_BY_INTERVAL = "DELETE FROM cloud_usage WHERE end_date < DATE_SUB(CURRENT_DATE(), INTERVAL ? DAY)"; private static final String DELETE_ALL_BY_INTERVAL = "DELETE FROM cloud_usage WHERE end_date < DATE_SUB(CURRENT_DATE(), INTERVAL ? DAY)";
private static final String INSERT_ACCOUNT = "INSERT INTO cloud_usage.account (id, account_name, type, role_id, domain_id, removed, cleanup_needed) VALUES (?,?,?,?,?,?,?)"; private static final String INSERT_ACCOUNT = "INSERT INTO cloud_usage.account (id, account_name, uuid, type, role_id, domain_id, removed, cleanup_needed) VALUES (?,?,?,?,?,?,?,?)";
private static final String INSERT_USER_STATS = "INSERT INTO cloud_usage.user_statistics (id, data_center_id, account_id, public_ip_address, device_id, device_type, network_id, net_bytes_received," private static final String INSERT_USER_STATS = "INSERT INTO cloud_usage.user_statistics (id, data_center_id, account_id, public_ip_address, device_id, device_type, network_id, net_bytes_received,"
+ " net_bytes_sent, current_bytes_received, current_bytes_sent, agg_bytes_received, agg_bytes_sent) VALUES (?,?,?,?,?,?,?,?,?,?, ?, ?, ?)"; + " net_bytes_sent, current_bytes_received, current_bytes_sent, agg_bytes_received, agg_bytes_sent) VALUES (?,?,?,?,?,?,?,?,?,?, ?, ?, ?)";
@ -129,25 +129,26 @@ public class UsageDaoImpl extends GenericDaoBase<UsageVO, Long> implements Usage
for (AccountVO acct : accounts) { for (AccountVO acct : accounts) {
pstmt.setLong(1, acct.getId()); pstmt.setLong(1, acct.getId());
pstmt.setString(2, acct.getAccountName()); pstmt.setString(2, acct.getAccountName());
pstmt.setInt(3, acct.getType().ordinal()); pstmt.setString(3, acct.getUuid());
pstmt.setInt(4, acct.getType().ordinal());
//prevent autoboxing NPE by defaulting to User role //prevent autoboxing NPE by defaulting to User role
if(acct.getRoleId() == null){ if(acct.getRoleId() == null){
pstmt.setLong(4, RoleType.User.getId()); pstmt.setLong(5, RoleType.User.getId());
}else{ }else{
pstmt.setLong(4, acct.getRoleId()); pstmt.setLong(5, acct.getRoleId());
} }
pstmt.setLong(5, acct.getDomainId()); pstmt.setLong(6, acct.getDomainId());
Date removed = acct.getRemoved(); Date removed = acct.getRemoved();
if (removed == null) { if (removed == null) {
pstmt.setString(6, null); pstmt.setString(7, null);
} else { } else {
pstmt.setString(6, DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), acct.getRemoved())); pstmt.setString(7, DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), acct.getRemoved()));
} }
pstmt.setBoolean(7, acct.getNeedsCleanup()); pstmt.setBoolean(8, acct.getNeedsCleanup());
pstmt.addBatch(); pstmt.addBatch();
} }

View File

@ -76,6 +76,8 @@ StateDao<ObjectInDataStoreStateMachine.State, ObjectInDataStoreStateMachine.Even
List<SnapshotDataStoreVO> findBySnapshotId(long snapshotId); List<SnapshotDataStoreVO> findBySnapshotId(long snapshotId);
List<SnapshotDataStoreVO> findBySnapshotIdWithNonDestroyedState(long snapshotId);
void duplicateCacheRecordsOnRegionStore(long storeId); void duplicateCacheRecordsOnRegionStore(long storeId);
// delete the snapshot entry on primary data store to make sure that next snapshot will be full snapshot // delete the snapshot entry on primary data store to make sure that next snapshot will be full snapshot

View File

@ -464,6 +464,13 @@ public class SnapshotDataStoreDaoImpl extends GenericDaoBase<SnapshotDataStoreVO
@Override @Override
public List<SnapshotDataStoreVO> findBySnapshotId(long snapshotId) { public List<SnapshotDataStoreVO> findBySnapshotId(long snapshotId) {
SearchCriteria<SnapshotDataStoreVO> sc = searchFilteringStoreIdEqStateEqStoreRoleEqIdEqUpdateCountEqSnapshotIdEqVolumeIdEq.create();
sc.setParameters(SNAPSHOT_ID, snapshotId);
return listBy(sc);
}
@Override
public List<SnapshotDataStoreVO> findBySnapshotIdWithNonDestroyedState(long snapshotId) {
SearchCriteria<SnapshotDataStoreVO> sc = idStateNinSearch.create(); SearchCriteria<SnapshotDataStoreVO> sc = idStateNinSearch.create();
sc.setParameters(SNAPSHOT_ID, snapshotId); sc.setParameters(SNAPSHOT_ID, snapshotId);
sc.setParameters(STATE, State.Destroyed.name()); sc.setParameters(STATE, State.Destroyed.name());

View File

@ -303,7 +303,7 @@ public class DefaultSnapshotStrategy extends SnapshotStrategyBase {
} }
if (Snapshot.State.Error.equals(snapshotVO.getState())) { if (Snapshot.State.Error.equals(snapshotVO.getState())) {
List<SnapshotDataStoreVO> storeRefs = snapshotStoreDao.findBySnapshotId(snapshotId); List<SnapshotDataStoreVO> storeRefs = snapshotStoreDao.findBySnapshotIdWithNonDestroyedState(snapshotId);
List<Long> deletedRefs = new ArrayList<>(); List<Long> deletedRefs = new ArrayList<>();
for (SnapshotDataStoreVO ref : storeRefs) { for (SnapshotDataStoreVO ref : storeRefs) {
boolean refZoneIdMatch = false; boolean refZoneIdMatch = false;

View File

@ -94,7 +94,7 @@ public class SnapshotDataFactoryImpl implements SnapshotDataFactory {
if (snapshot == null) { //snapshot may have been removed; if (snapshot == null) { //snapshot may have been removed;
return new ArrayList<>(); return new ArrayList<>();
} }
List<SnapshotDataStoreVO> allSnapshotsAndDataStore = snapshotStoreDao.findBySnapshotId(snapshotId); List<SnapshotDataStoreVO> allSnapshotsAndDataStore = snapshotStoreDao.findBySnapshotIdWithNonDestroyedState(snapshotId);
if (CollectionUtils.isEmpty(allSnapshotsAndDataStore)) { if (CollectionUtils.isEmpty(allSnapshotsAndDataStore)) {
return new ArrayList<>(); return new ArrayList<>();
} }
@ -118,7 +118,23 @@ public class SnapshotDataFactoryImpl implements SnapshotDataFactory {
if (snapshot == null) { if (snapshot == null) {
return null; return null;
} }
SnapshotDataStoreVO snapshotStore = snapshotStoreDao.findByStoreSnapshot(role, storeId, snapshotId); return getSnapshotOnStore(snapshot, storeId, role);
}
@Override
public SnapshotInfo getSnapshotIncludingRemoved(long snapshotId, long storeId, DataStoreRole role) {
SnapshotVO snapshot = snapshotDao.findByIdIncludingRemoved(snapshotId);
if (snapshot == null) {
return null;
}
return getSnapshotOnStore(snapshot, storeId, role);
}
private SnapshotInfo getSnapshotOnStore(SnapshotVO snapshot, long storeId, DataStoreRole role) {
if (snapshot == null) {
return null;
}
SnapshotDataStoreVO snapshotStore = snapshotStoreDao.findByStoreSnapshot(role, storeId, snapshot.getId());
if (snapshotStore == null) { if (snapshotStore == null) {
return null; return null;
} }
@ -207,7 +223,7 @@ public class SnapshotDataFactoryImpl implements SnapshotDataFactory {
@Override @Override
public void updateOperationFailed(long snapshotId) throws NoTransitionException { public void updateOperationFailed(long snapshotId) throws NoTransitionException {
List<SnapshotDataStoreVO> snapshotStoreRefs = snapshotStoreDao.findBySnapshotId(snapshotId); List<SnapshotDataStoreVO> snapshotStoreRefs = snapshotStoreDao.findBySnapshotIdWithNonDestroyedState(snapshotId);
for (SnapshotDataStoreVO snapshotStoreRef : snapshotStoreRefs) { for (SnapshotDataStoreVO snapshotStoreRef : snapshotStoreRefs) {
SnapshotInfo snapshotInfo = getSnapshot(snapshotStoreRef.getSnapshotId(), snapshotStoreRef.getDataStoreId(), snapshotStoreRef.getRole()); SnapshotInfo snapshotInfo = getSnapshot(snapshotStoreRef.getSnapshotId(), snapshotStoreRef.getDataStoreId(), snapshotStoreRef.getRole());
if (snapshotInfo != null) { if (snapshotInfo != null) {

View File

@ -474,8 +474,7 @@ public class SnapshotServiceImpl implements SnapshotService {
if (res.isFailed()) { if (res.isFailed()) {
throw new CloudRuntimeException(res.getResult()); throw new CloudRuntimeException(res.getResult());
} }
SnapshotInfo destSnapshot = res.getSnapshot(); return res.getSnapshot();
return destSnapshot;
} catch (InterruptedException e) { } catch (InterruptedException e) {
logger.debug("failed copy snapshot", e); logger.debug("failed copy snapshot", e);
throw new CloudRuntimeException("Failed to copy snapshot", e); throw new CloudRuntimeException("Failed to copy snapshot", e);
@ -483,7 +482,6 @@ public class SnapshotServiceImpl implements SnapshotService {
logger.debug("Failed to copy snapshot", e); logger.debug("Failed to copy snapshot", e);
throw new CloudRuntimeException("Failed to copy snapshot", e); throw new CloudRuntimeException("Failed to copy snapshot", e);
} }
} }
protected Void copySnapshotAsyncCallback(AsyncCallbackDispatcher<SnapshotServiceImpl, CopyCommandResult> callback, CopySnapshotContext<CommandResult> context) { protected Void copySnapshotAsyncCallback(AsyncCallbackDispatcher<SnapshotServiceImpl, CopyCommandResult> callback, CopySnapshotContext<CommandResult> context) {
@ -571,7 +569,6 @@ public class SnapshotServiceImpl implements SnapshotService {
} }
protected Void deleteSnapshotCallback(AsyncCallbackDispatcher<SnapshotServiceImpl, CommandResult> callback, DeleteSnapshotContext<CommandResult> context) { protected Void deleteSnapshotCallback(AsyncCallbackDispatcher<SnapshotServiceImpl, CommandResult> callback, DeleteSnapshotContext<CommandResult> context) {
CommandResult result = callback.getResult(); CommandResult result = callback.getResult();
AsyncCallFuture<SnapshotResult> future = context.future; AsyncCallFuture<SnapshotResult> future = context.future;
SnapshotInfo snapshot = context.snapshot; SnapshotInfo snapshot = context.snapshot;
@ -729,7 +726,7 @@ public class SnapshotServiceImpl implements SnapshotService {
if (snapshot != null) { if (snapshot != null) {
if (snapshot.getState() != Snapshot.State.BackedUp) { if (snapshot.getState() != Snapshot.State.BackedUp) {
List<SnapshotDataStoreVO> snapshotDataStoreVOs = _snapshotStoreDao.findBySnapshotId(snapshotId); List<SnapshotDataStoreVO> snapshotDataStoreVOs = _snapshotStoreDao.findBySnapshotIdWithNonDestroyedState(snapshotId);
for (SnapshotDataStoreVO snapshotDataStoreVO : snapshotDataStoreVOs) { for (SnapshotDataStoreVO snapshotDataStoreVO : snapshotDataStoreVOs) {
logger.debug("Remove snapshot {}, status {} on snapshot_store_ref table with id: {}", snapshot, snapshotDataStoreVO.getState(), snapshotDataStoreVO.getId()); logger.debug("Remove snapshot {}, status {} on snapshot_store_ref table with id: {}", snapshot, snapshotDataStoreVO.getState(), snapshotDataStoreVO.getId());
@ -834,7 +831,6 @@ public class SnapshotServiceImpl implements SnapshotService {
SnapshotObject srcSnapshot = (SnapshotObject)snapshot; SnapshotObject srcSnapshot = (SnapshotObject)snapshot;
srcSnapshot.processEvent(Event.DestroyRequested); srcSnapshot.processEvent(Event.DestroyRequested);
srcSnapshot.processEvent(Event.OperationSucceeded); srcSnapshot.processEvent(Event.OperationSucceeded);
srcSnapshot.processEvent(Snapshot.Event.OperationFailed); srcSnapshot.processEvent(Snapshot.Event.OperationFailed);
_snapshotDetailsDao.removeDetail(srcSnapshot.getId(), AsyncJob.Constants.MS_ID); _snapshotDetailsDao.removeDetail(srcSnapshot.getId(), AsyncJob.Constants.MS_ID);
@ -845,7 +841,6 @@ public class SnapshotServiceImpl implements SnapshotService {
} }
} }
}); });
} }
@Override @Override

View File

@ -541,7 +541,6 @@ public class StorageSystemSnapshotStrategy extends SnapshotStrategyBase {
logger.warn("Failed to clean up snapshot '" + snapshot.getId() + "' on primary storage: " + e.getMessage()); logger.warn("Failed to clean up snapshot '" + snapshot.getId() + "' on primary storage: " + e.getMessage());
} }
} }
} }
private VMSnapshot takeHypervisorSnapshot(VolumeInfo volumeInfo) { private VMSnapshot takeHypervisorSnapshot(VolumeInfo volumeInfo) {

View File

@ -109,6 +109,9 @@ public class ObjectInDataStoreManagerImpl implements ObjectInDataStoreManager {
stateMachines.addTransition(State.Destroying, Event.DestroyRequested, State.Destroying); stateMachines.addTransition(State.Destroying, Event.DestroyRequested, State.Destroying);
stateMachines.addTransition(State.Destroying, Event.OperationSucceeded, State.Destroyed); stateMachines.addTransition(State.Destroying, Event.OperationSucceeded, State.Destroyed);
stateMachines.addTransition(State.Destroying, Event.OperationFailed, State.Destroying); stateMachines.addTransition(State.Destroying, Event.OperationFailed, State.Destroying);
stateMachines.addTransition(State.Destroyed, Event.DestroyRequested, State.Destroyed);
stateMachines.addTransition(State.Destroyed, Event.OperationSucceeded, State.Destroyed);
stateMachines.addTransition(State.Destroyed, Event.OperationFailed, State.Destroyed);
stateMachines.addTransition(State.Failed, Event.DestroyRequested, State.Destroying); stateMachines.addTransition(State.Failed, Event.DestroyRequested, State.Destroying);
// TODO: further investigate why an extra event is sent when it is // TODO: further investigate why an extra event is sent when it is
// already Ready for DownloadListener // already Ready for DownloadListener

View File

@ -105,7 +105,7 @@ public class StorPoolHelper {
if (snapshotDetails != null) { if (snapshotDetails != null) {
return StorPoolStorageAdaptor.getVolumeNameFromPath(snapshotDetails.getValue(), true); return StorPoolStorageAdaptor.getVolumeNameFromPath(snapshotDetails.getValue(), true);
} else { } else {
List<SnapshotDataStoreVO> snapshots = snapshotStoreDao.findBySnapshotId(snapshotId); List<SnapshotDataStoreVO> snapshots = snapshotStoreDao.findBySnapshotIdWithNonDestroyedState(snapshotId);
if (!CollectionUtils.isEmpty(snapshots)) { if (!CollectionUtils.isEmpty(snapshots)) {
for (SnapshotDataStoreVO snapshotDataStoreVO : snapshots) { for (SnapshotDataStoreVO snapshotDataStoreVO : snapshots) {
String name = StorPoolStorageAdaptor.getVolumeNameFromPath(snapshotDataStoreVO.getInstallPath(), true); String name = StorPoolStorageAdaptor.getVolumeNameFromPath(snapshotDataStoreVO.getInstallPath(), true);

View File

@ -300,7 +300,7 @@ public class StorPoolSnapshotStrategy implements SnapshotStrategy {
} }
protected boolean areLastSnapshotRef(long snapshotId) { protected boolean areLastSnapshotRef(long snapshotId) {
List<SnapshotDataStoreVO> snapshotStoreRefs = _snapshotStoreDao.findBySnapshotId(snapshotId); List<SnapshotDataStoreVO> snapshotStoreRefs = _snapshotStoreDao.findBySnapshotIdWithNonDestroyedState(snapshotId);
if (CollectionUtils.isEmpty(snapshotStoreRefs) || snapshotStoreRefs.size() == 1) { if (CollectionUtils.isEmpty(snapshotStoreRefs) || snapshotStoreRefs.size() == 1) {
return true; return true;
} }
@ -343,7 +343,7 @@ public class StorPoolSnapshotStrategy implements SnapshotStrategy {
} }
if (Snapshot.State.Error.equals(snapshotVO.getState())) { if (Snapshot.State.Error.equals(snapshotVO.getState())) {
List<SnapshotDataStoreVO> storeRefs = _snapshotStoreDao.findBySnapshotId(snapshotId); List<SnapshotDataStoreVO> storeRefs = _snapshotStoreDao.findBySnapshotIdWithNonDestroyedState(snapshotId);
List<Long> deletedRefs = new ArrayList<>(); List<Long> deletedRefs = new ArrayList<>();
for (SnapshotDataStoreVO ref : storeRefs) { for (SnapshotDataStoreVO ref : storeRefs) {
boolean refZoneIdMatch = false; boolean refZoneIdMatch = false;

View File

@ -2110,41 +2110,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
} }
} }
//destroy snapshots in destroying state in snapshot_store_ref cleanupSnapshotsFromStoreRefInDestroyingState();
List<SnapshotDataStoreVO> ssSnapshots = _snapshotStoreDao.listByState(ObjectInDataStoreStateMachine.State.Destroying);
for (SnapshotDataStoreVO snapshotDataStoreVO : ssSnapshots) {
String snapshotUuid = null;
SnapshotVO snapshot = null;
final String storeRole = snapshotDataStoreVO.getRole().toString().toLowerCase();
if (logger.isDebugEnabled()) {
snapshot = _snapshotDao.findById(snapshotDataStoreVO.getSnapshotId());
if (snapshot == null) {
logger.warn(String.format("Did not find snapshot [ID: %d] for which store reference is in destroying state; therefore, it cannot be destroyed.", snapshotDataStoreVO.getSnapshotId()));
continue;
}
snapshotUuid = snapshot.getUuid();
}
try {
if (logger.isDebugEnabled()) {
logger.debug(String.format("Verifying if snapshot [%s] is in destroying state in %s data store ID: %d.", snapshotUuid, storeRole, snapshotDataStoreVO.getDataStoreId()));
}
SnapshotInfo snapshotInfo = snapshotFactory.getSnapshot(snapshotDataStoreVO.getSnapshotId(), snapshotDataStoreVO.getDataStoreId(), snapshotDataStoreVO.getRole());
if (snapshotInfo != null) {
if (logger.isDebugEnabled()) {
logger.debug(String.format("Snapshot [%s] in destroying state found in %s data store [%s]; therefore, it will be destroyed.", snapshotUuid, storeRole, snapshotInfo.getDataStore().getUuid()));
}
_snapshotService.deleteSnapshot(snapshotInfo);
} else if (logger.isDebugEnabled()) {
logger.debug(String.format("Did not find snapshot [%s] in destroying state in %s data store ID: %d.", snapshotUuid, storeRole, snapshotDataStoreVO.getDataStoreId()));
}
} catch (Exception e) {
logger.error("Failed to delete snapshot [{}] from storage due to: [{}].", snapshot, e.getMessage());
if (logger.isDebugEnabled()) {
logger.debug("Failed to delete snapshot [{}] from storage.", snapshot, e);
}
}
}
cleanupSecondaryStorage(recurring); cleanupSecondaryStorage(recurring);
List<VolumeVO> vols = volumeDao.listVolumesToBeDestroyed(new Date(System.currentTimeMillis() - ((long)StorageCleanupDelay.value() << 10))); List<VolumeVO> vols = volumeDao.listVolumesToBeDestroyed(new Date(System.currentTimeMillis() - ((long)StorageCleanupDelay.value() << 10)));
@ -2184,20 +2150,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
} }
} }
// remove snapshots in Error state removeSnapshotsInErrorStatus();
List<SnapshotVO> snapshots = _snapshotDao.listAllByStatus(Snapshot.State.Error);
for (SnapshotVO snapshotVO : snapshots) {
try {
List<SnapshotDataStoreVO> storeRefs = _snapshotStoreDao.findBySnapshotId(snapshotVO.getId());
for (SnapshotDataStoreVO ref : storeRefs) {
_snapshotStoreDao.expunge(ref.getId());
}
_snapshotDao.expunge(snapshotVO.getId());
} catch (Exception e) {
logger.error("Unable to destroy snapshot [{}] due to: [{}].", snapshotVO, e.getMessage());
logger.debug("Unable to destroy snapshot [{}].", snapshotVO, e);
}
}
// destroy uploaded volumes in abandoned/error state // destroy uploaded volumes in abandoned/error state
List<VolumeDataStoreVO> volumeDataStores = _volumeDataStoreDao.listByVolumeState(Volume.State.UploadError, Volume.State.UploadAbandoned); List<VolumeDataStoreVO> volumeDataStores = _volumeDataStoreDao.listByVolumeState(Volume.State.UploadError, Volume.State.UploadAbandoned);
@ -2298,6 +2251,56 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
} }
} }
private void cleanupSnapshotsFromStoreRefInDestroyingState() {
List<SnapshotDataStoreVO> storeRefSnapshotsInDestroyingState = _snapshotStoreDao.listByState(ObjectInDataStoreStateMachine.State.Destroying);
for (SnapshotDataStoreVO snapshotDataStoreVO : storeRefSnapshotsInDestroyingState) {
SnapshotVO snapshot = _snapshotDao.findById(snapshotDataStoreVO.getSnapshotId());
if (snapshot == null) {
logger.warn("Did not find snapshot [ID: {}] for which store reference is in destroying state; therefore, it cannot be destroyed.", snapshotDataStoreVO.getSnapshotId());
continue;
}
deleteSnapshot(snapshot, snapshotDataStoreVO);
}
}
private void deleteSnapshot(SnapshotVO snapshot, SnapshotDataStoreVO snapshotDataStoreVO) {
if (snapshot == null || snapshotDataStoreVO == null) {
return;
}
try {
final String snapshotUuid = snapshot.getUuid();
final String storeRole = snapshotDataStoreVO.getRole().toString().toLowerCase();
logger.debug("Snapshot [{}] is in {} state on {} data store ID: {}.", snapshotUuid, snapshotDataStoreVO.getState(), storeRole, snapshotDataStoreVO.getDataStoreId());
SnapshotInfo snapshotInfo = snapshotFactory.getSnapshotIncludingRemoved(snapshotDataStoreVO.getSnapshotId(), snapshotDataStoreVO.getDataStoreId(), snapshotDataStoreVO.getRole());
if (snapshotInfo != null) {
logger.debug("Snapshot [{}] in {} state found on {} data store [{}], it will be deleted.", snapshotUuid, snapshotDataStoreVO.getState(), storeRole, snapshotInfo.getDataStore().getUuid());
_snapshotService.deleteSnapshot(snapshotInfo);
} else {
logger.debug("Did not find snapshot [{}] in {} state on {} data store ID: {}.", snapshotUuid, snapshotDataStoreVO.getState(), storeRole, snapshotDataStoreVO.getDataStoreId());
}
} catch (Exception e) {
logger.error("Failed to delete snapshot [{}] from storage due to: [{}].", snapshot, e.getMessage(), e);
}
}
private void removeSnapshotsInErrorStatus() {
List<SnapshotVO> snapshotsInErrorStatus = _snapshotDao.listAllByStatusIncludingRemoved(Snapshot.State.Error);
for (SnapshotVO snapshotVO : snapshotsInErrorStatus) {
try {
List<SnapshotDataStoreVO> storeRefSnapshotsInErrorStatus = _snapshotStoreDao.findBySnapshotId(snapshotVO.getId());
for (SnapshotDataStoreVO snapshotDataStoreVO : storeRefSnapshotsInErrorStatus) {
deleteSnapshot(snapshotVO, snapshotDataStoreVO);
_snapshotStoreDao.expunge(snapshotDataStoreVO.getId());
}
_snapshotDao.expunge(snapshotVO.getId());
} catch (Exception e) {
logger.error("Unable to destroy snapshot [{}] due to: [{}].", snapshotVO, e.getMessage());
logger.debug("Unable to destroy snapshot [{}].", snapshotVO, e);
}
}
}
protected boolean isVolumeSuspectedDestroyDuplicateOfVmVolume(VolumeVO gcVolume) { protected boolean isVolumeSuspectedDestroyDuplicateOfVmVolume(VolumeVO gcVolume) {
if (gcVolume.getPath() == null) { if (gcVolume.getPath() == null) {
return false; return false;

View File

@ -843,7 +843,7 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
protected Pair<List<SnapshotDataStoreVO>, List<Long>> getStoreRefsAndZonesForSnapshotDelete(long snapshotId, Long zoneId) { protected Pair<List<SnapshotDataStoreVO>, List<Long>> getStoreRefsAndZonesForSnapshotDelete(long snapshotId, Long zoneId) {
List<SnapshotDataStoreVO> snapshotStoreRefs = new ArrayList<>(); List<SnapshotDataStoreVO> snapshotStoreRefs = new ArrayList<>();
List<SnapshotDataStoreVO> allSnapshotStoreRefs = _snapshotStoreDao.findBySnapshotId(snapshotId); List<SnapshotDataStoreVO> allSnapshotStoreRefs = _snapshotStoreDao.findBySnapshotIdWithNonDestroyedState(snapshotId);
List<Long> zoneIds = new ArrayList<>(); List<Long> zoneIds = new ArrayList<>();
if (zoneId != null) { if (zoneId != null) {
DataCenterVO zone = dataCenterDao.findById(zoneId); DataCenterVO zone = dataCenterDao.findById(zoneId);
@ -1782,23 +1782,23 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
if (asyncBackup) { if (asyncBackup) {
backupSnapshotExecutor.schedule(new BackupSnapshotTask(snapshotOnPrimary, snapshotBackupRetries - 1, snapshotStrategy, zoneIds, poolIds), 0, TimeUnit.SECONDS); backupSnapshotExecutor.schedule(new BackupSnapshotTask(snapshotOnPrimary, snapshotBackupRetries - 1, snapshotStrategy, zoneIds, poolIds), 0, TimeUnit.SECONDS);
} else { } else {
SnapshotInfo backupedSnapshot = snapshotStrategy.backupSnapshot(snapshotOnPrimary); SnapshotInfo backedUpSnapshot = snapshotStrategy.backupSnapshot(snapshotOnPrimary);
if (backupedSnapshot != null) { if (backedUpSnapshot != null) {
snapshotStrategy.postSnapshotCreation(snapshotOnPrimary); snapshotStrategy.postSnapshotCreation(snapshotOnPrimary);
} }
} }
} }
protected class BackupSnapshotTask extends ManagedContextRunnable { protected class BackupSnapshotTask extends ManagedContextRunnable {
SnapshotInfo snapshot; SnapshotInfo snapshotOnPrimary;
int attempts; int attempts;
SnapshotStrategy snapshotStrategy; SnapshotStrategy snapshotStrategy;
List<Long> zoneIds; List<Long> zoneIds;
List<Long> poolIds; List<Long> poolIds;
public BackupSnapshotTask(SnapshotInfo snap, int maxRetries, SnapshotStrategy strategy, List<Long> zoneIds, List<Long> poolIds) { public BackupSnapshotTask(SnapshotInfo snapshot, int maxRetries, SnapshotStrategy strategy, List<Long> zoneIds, List<Long> poolIds) {
snapshot = snap; snapshotOnPrimary = snapshot;
attempts = maxRetries; attempts = maxRetries;
snapshotStrategy = strategy; snapshotStrategy = strategy;
this.zoneIds = zoneIds; this.zoneIds = zoneIds;
@ -1810,17 +1810,16 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
try { try {
logger.debug("Value of attempts is " + (snapshotBackupRetries - attempts)); logger.debug("Value of attempts is " + (snapshotBackupRetries - attempts));
if (Boolean.TRUE.equals(SnapshotInfo.BackupSnapshotAfterTakingSnapshot.value()) && CollectionUtils.isEmpty(poolIds)) { if (Boolean.TRUE.equals(SnapshotInfo.BackupSnapshotAfterTakingSnapshot.value()) && CollectionUtils.isEmpty(poolIds)) {
SnapshotInfo backupedSnapshot = snapshotStrategy.backupSnapshot(snapshot); SnapshotInfo backupedSnapshot = snapshotStrategy.backupSnapshot(snapshotOnPrimary);
if (backupedSnapshot != null) { if (backupedSnapshot != null) {
snapshotStrategy.postSnapshotCreation(snapshot); snapshotStrategy.postSnapshotCreation(snapshotOnPrimary);
copyNewSnapshotToZones(snapshot.getId(), snapshot.getDataCenterId(), zoneIds); copyNewSnapshotToZones(snapshotOnPrimary.getId(), snapshotOnPrimary.getDataCenterId(), zoneIds);
} }
} }
if (CollectionUtils.isNotEmpty(poolIds)) { if (CollectionUtils.isNotEmpty(poolIds)) {
for (Long poolId: poolIds) { for (Long poolId: poolIds) {
copySnapshotOnPool(snapshot, snapshotStrategy, poolId); copySnapshotOnPool(snapshotOnPrimary, snapshotStrategy, poolId);
} }
} }
} catch (final Exception e) { } catch (final Exception e) {
@ -1830,11 +1829,11 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
private void decriseBackupSnapshotAttempts() { private void decriseBackupSnapshotAttempts() {
if (attempts >= 0) { if (attempts >= 0) {
logger.debug("Backing up of snapshot failed, for snapshot {}, left with {} more attempts", snapshot, attempts); logger.debug("Backing up of snapshot failed, for snapshot {}, left with {} more attempts", snapshotOnPrimary, attempts);
backupSnapshotExecutor.schedule(new BackupSnapshotTask(snapshot, --attempts, snapshotStrategy, zoneIds, poolIds), snapshotBackupRetryInterval, TimeUnit.SECONDS); backupSnapshotExecutor.schedule(new BackupSnapshotTask(snapshotOnPrimary, --attempts, snapshotStrategy, zoneIds, poolIds), snapshotBackupRetryInterval, TimeUnit.SECONDS);
} else { } else {
logger.debug("Done with {} attempts in backing up of snapshot {}", snapshotBackupRetries, snapshot.getSnapshotVO()); logger.debug("Done with {} attempts in backing up of snapshot {}", snapshotBackupRetries, snapshotOnPrimary.getSnapshotVO());
snapshotSrv.cleanupOnSnapshotBackupFailure(snapshot); snapshotSrv.cleanupOnSnapshotBackupFailure(snapshotOnPrimary);
} }
} }
} }
@ -2058,7 +2057,7 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
public void markVolumeSnapshotsAsDestroyed(Volume volume) { public void markVolumeSnapshotsAsDestroyed(Volume volume) {
List<SnapshotVO> snapshots = _snapshotDao.listByVolumeId(volume.getId()); List<SnapshotVO> snapshots = _snapshotDao.listByVolumeId(volume.getId());
for (SnapshotVO snapshot: snapshots) { for (SnapshotVO snapshot: snapshots) {
List<SnapshotDataStoreVO> snapshotDataStoreVOs = _snapshotStoreDao.findBySnapshotId(snapshot.getId()); List<SnapshotDataStoreVO> snapshotDataStoreVOs = _snapshotStoreDao.findBySnapshotIdWithNonDestroyedState(snapshot.getId());
if (CollectionUtils.isEmpty(snapshotDataStoreVOs)) { if (CollectionUtils.isEmpty(snapshotDataStoreVOs)) {
snapshot.setState(Snapshot.State.Destroyed); snapshot.setState(Snapshot.State.Destroyed);
_snapshotDao.update(snapshot.getId(), snapshot); _snapshotDao.update(snapshot.getId(), snapshot);

View File

@ -164,7 +164,7 @@ public class SnapshotManagerImplTest {
Mockito.when(ref1.getDataStoreId()).thenReturn(2L); Mockito.when(ref1.getDataStoreId()).thenReturn(2L);
Mockito.when(ref1.getRole()).thenReturn(DataStoreRole.Image); Mockito.when(ref1.getRole()).thenReturn(DataStoreRole.Image);
List<SnapshotDataStoreVO> snapshotStoreList = List.of(ref, ref1); List<SnapshotDataStoreVO> snapshotStoreList = List.of(ref, ref1);
Mockito.when(snapshotStoreDao.findBySnapshotId(snapshotId)).thenReturn(snapshotStoreList); Mockito.when(snapshotStoreDao.findBySnapshotIdWithNonDestroyedState(snapshotId)).thenReturn(snapshotStoreList);
Mockito.when(dataStoreManager.getStoreZoneId(1L, DataStoreRole.Image)).thenReturn(100L); Mockito.when(dataStoreManager.getStoreZoneId(1L, DataStoreRole.Image)).thenReturn(100L);
Mockito.when(dataStoreManager.getStoreZoneId(2L, DataStoreRole.Image)).thenReturn(101L); Mockito.when(dataStoreManager.getStoreZoneId(2L, DataStoreRole.Image)).thenReturn(101L);
Pair<List<SnapshotDataStoreVO>, List<Long>> pair = snapshotManager.getStoreRefsAndZonesForSnapshotDelete(snapshotId, null); Pair<List<SnapshotDataStoreVO>, List<Long>> pair = snapshotManager.getStoreRefsAndZonesForSnapshotDelete(snapshotId, null);
@ -189,7 +189,7 @@ public class SnapshotManagerImplTest {
Mockito.when(ref2.getDataStoreId()).thenReturn(3L); Mockito.when(ref2.getDataStoreId()).thenReturn(3L);
Mockito.when(ref2.getRole()).thenReturn(DataStoreRole.Image); Mockito.when(ref2.getRole()).thenReturn(DataStoreRole.Image);
List<SnapshotDataStoreVO> snapshotStoreList = List.of(ref, ref1, ref2); List<SnapshotDataStoreVO> snapshotStoreList = List.of(ref, ref1, ref2);
Mockito.when(snapshotStoreDao.findBySnapshotId(snapshotId)).thenReturn(snapshotStoreList); Mockito.when(snapshotStoreDao.findBySnapshotIdWithNonDestroyedState(snapshotId)).thenReturn(snapshotStoreList);
Mockito.when(dataStoreManager.getStoreZoneId(1L, DataStoreRole.Image)).thenReturn(zoneId); Mockito.when(dataStoreManager.getStoreZoneId(1L, DataStoreRole.Image)).thenReturn(zoneId);
Mockito.when(dataStoreManager.getStoreZoneId(2L, DataStoreRole.Primary)).thenReturn(zoneId); Mockito.when(dataStoreManager.getStoreZoneId(2L, DataStoreRole.Primary)).thenReturn(zoneId);
Mockito.when(dataStoreManager.getStoreZoneId(3L, DataStoreRole.Image)).thenReturn(2L); Mockito.when(dataStoreManager.getStoreZoneId(3L, DataStoreRole.Image)).thenReturn(2L);

View File

@ -2621,7 +2621,9 @@ export default {
this.owner.domainid = null this.owner.domainid = null
this.owner.projectid = OwnerOptions.selectedProject this.owner.projectid = OwnerOptions.selectedProject
} }
if (OwnerOptions.initialized) {
this.resetData() this.resetData()
}
}, },
fetchZones (zoneId, listZoneAllow) { fetchZones (zoneId, listZoneAllow) {
this.zones = [] this.zones = []

View File

@ -19,7 +19,7 @@
<a-form layout="vertical" > <a-form layout="vertical" >
<a-form-item :label="$t('label.owner.type')"> <a-form-item :label="$t('label.owner.type')">
<a-select <a-select
@change="changeDomain" @change="changeAccountTypeOrDomain"
v-model:value="selectedAccountType" v-model:value="selectedAccountType"
defaultValue="account" defaultValue="account"
autoFocus autoFocus
@ -37,7 +37,7 @@
</a-form-item> </a-form-item>
<a-form-item :label="$t('label.domain')" required> <a-form-item :label="$t('label.domain')" required>
<a-select <a-select
@change="changeDomain" @change="changeAccountTypeOrDomain"
v-model:value="selectedDomain" v-model:value="selectedDomain"
showSearch showSearch
optionFilterProp="label" optionFilterProp="label"
@ -136,6 +136,7 @@ export default {
components: { ResourceIcon }, components: { ResourceIcon },
data () { data () {
return { return {
initialized: false,
domains: [], domains: [],
accounts: [], accounts: [],
projects: [], projects: [],
@ -143,7 +144,8 @@ export default {
selectedDomain: null, selectedDomain: null,
selectedAccount: null, selectedAccount: null,
selectedProject: null, selectedProject: null,
loading: false loading: false,
requestToken: 0
} }
}, },
props: { props: {
@ -177,7 +179,7 @@ export default {
const domainIds = this.domains?.map(domain => domain.id) const domainIds = this.domains?.map(domain => domain.id)
const ownerDomainId = this.$store.getters.project?.domainid || this.$store.getters.userInfo.domainid const ownerDomainId = this.$store.getters.project?.domainid || this.$store.getters.userInfo.domainid
this.selectedDomain = domainIds?.includes(ownerDomainId) ? ownerDomainId : this.domains?.[0]?.id this.selectedDomain = domainIds?.includes(ownerDomainId) ? ownerDomainId : this.domains?.[0]?.id
this.changeDomain() this.fetchOwnerData()
}) })
.catch((error) => { .catch((error) => {
this.$notifyError(error) this.$notifyError(error)
@ -186,8 +188,13 @@ export default {
this.loading = false this.loading = false
}) })
}, },
incrementAndGetRequestToken () {
this.requestToken += 1
return this.requestToken
},
fetchAccounts () { fetchAccounts () {
this.loading = true this.loading = true
const currentToken = this.incrementAndGetRequestToken()
getAPI('listAccounts', { getAPI('listAccounts', {
response: 'json', response: 'json',
domainId: this.selectedDomain, domainId: this.selectedDomain,
@ -196,6 +203,9 @@ export default {
isrecursive: false isrecursive: false
}) })
.then((response) => { .then((response) => {
if (currentToken !== this.requestToken) {
return
}
this.accounts = response.listaccountsresponse.account || [] this.accounts = response.listaccountsresponse.account || []
if (this.override?.accounts && this.accounts) { if (this.override?.accounts && this.accounts) {
this.accounts = this.accounts.filter(item => this.override.accounts.has(item.name)) this.accounts = this.accounts.filter(item => this.override.accounts.has(item.name))
@ -214,10 +224,12 @@ export default {
}) })
.finally(() => { .finally(() => {
this.loading = false this.loading = false
this.initialized = true
}) })
}, },
fetchProjects () { fetchProjects () {
this.loading = true this.loading = true
const currentToken = this.incrementAndGetRequestToken()
getAPI('listProjects', { getAPI('listProjects', {
response: 'json', response: 'json',
domainId: this.selectedDomain, domainId: this.selectedDomain,
@ -227,6 +239,9 @@ export default {
isrecursive: false isrecursive: false
}) })
.then((response) => { .then((response) => {
if (currentToken !== this.requestToken) {
return
}
this.projects = response.listprojectsresponse.project this.projects = response.listprojectsresponse.project
if (this.override?.projects && this.projects) { if (this.override?.projects && this.projects) {
this.projects = this.projects.filter(item => this.override.projects.has(item.id)) this.projects = this.projects.filter(item => this.override.projects.has(item.id))
@ -240,9 +255,14 @@ export default {
}) })
.finally(() => { .finally(() => {
this.loading = false this.loading = false
this.initialized = true
}) })
}, },
changeDomain () { changeAccountTypeOrDomain () {
this.initialized = true
this.fetchOwnerData()
},
fetchOwnerData () {
if (this.selectedAccountType === 'Account') { if (this.selectedAccountType === 'Account') {
this.fetchAccounts() this.fetchAccounts()
} else { } else {

View File

@ -507,7 +507,7 @@ export default {
this.owner.domainid = null this.owner.domainid = null
this.owner.projectid = OwnerOptions.selectedProject this.owner.projectid = OwnerOptions.selectedProject
} }
if (isAdminOrDomainAdmin()) { if (OwnerOptions.initialized && isAdminOrDomainAdmin()) {
this.updateVPCCheckAndFetchNetworkOfferingData() this.updateVPCCheckAndFetchNetworkOfferingData()
} }
}, },

View File

@ -309,7 +309,7 @@ export default {
this.owner.domainid = null this.owner.domainid = null
this.owner.projectid = OwnerOptions.selectedProject this.owner.projectid = OwnerOptions.selectedProject
} }
if (isAdminOrDomainAdmin()) { if (OwnerOptions.initialized && this.isAdminOrDomainAdmin()) {
this.updateVPCCheckAndFetchNetworkOfferingData() this.updateVPCCheckAndFetchNetworkOfferingData()
} }
}, },

View File

@ -272,23 +272,21 @@ export default {
}, },
fetchOwnerOptions (OwnerOptions) { fetchOwnerOptions (OwnerOptions) {
this.owner = {} this.owner = {}
console.log('fetching owner')
if (OwnerOptions.selectedAccountType === 'Account') { if (OwnerOptions.selectedAccountType === 'Account') {
if (!OwnerOptions.selectedAccount) { if (!OwnerOptions.selectedAccount) {
return return
} }
console.log('fetched account')
this.owner.account = OwnerOptions.selectedAccount this.owner.account = OwnerOptions.selectedAccount
this.owner.domainid = OwnerOptions.selectedDomain this.owner.domainid = OwnerOptions.selectedDomain
} else if (OwnerOptions.selectedAccountType === 'Project') { } else if (OwnerOptions.selectedAccountType === 'Project') {
if (!OwnerOptions.selectedProject) { if (!OwnerOptions.selectedProject) {
return return
} }
console.log('fetched project')
this.owner.projectid = OwnerOptions.selectedProject this.owner.projectid = OwnerOptions.selectedProject
} }
console.log('fetched owner') if (OwnerOptions.initialized) {
this.fetchData() this.fetchData()
}
}, },
fetchData () { fetchData () {
this.minCpu = store.getters.features.sharedfsvmmincpucount this.minCpu = store.getters.features.sharedfsvmmincpucount

View File

@ -272,7 +272,9 @@ export default {
} }
this.owner.projectid = OwnerOptions.selectedProject this.owner.projectid = OwnerOptions.selectedProject
} }
if (OwnerOptions.initialized) {
this.fetchData() this.fetchData()
}
}, },
fetchData () { fetchData () {
if (this.createVolumeFromSnapshot) { if (this.createVolumeFromSnapshot) {