use of org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO in project cloudstack by apache.
the class ApiResponseHelper method createTemplateResponses.
@Override
public List<TemplateResponse> createTemplateResponses(ResponseView view, long templateId, Long snapshotId, Long volumeId, boolean readyOnly) {
Long zoneId = null;
if (snapshotId != null) {
Snapshot snapshot = ApiDBUtils.findSnapshotById(snapshotId);
VolumeVO volume = findVolumeById(snapshot.getVolumeId());
// if volume comes back null, use another technique to try to discover the zone
if (volume == null) {
SnapshotDataStoreVO snapshotStore = _snapshotStoreDao.findBySnapshot(snapshot.getId(), DataStoreRole.Primary);
if (snapshotStore != null) {
long storagePoolId = snapshotStore.getDataStoreId();
StoragePoolVO storagePool = _storagePoolDao.findById(storagePoolId);
if (storagePool != null) {
zoneId = storagePool.getDataCenterId();
}
}
} else {
zoneId = volume.getDataCenterId();
}
} else {
VolumeVO volume = findVolumeById(volumeId);
zoneId = volume.getDataCenterId();
}
if (zoneId == null) {
throw new CloudRuntimeException("Unable to determine the zone ID");
}
return createTemplateResponses(view, templateId, zoneId, readyOnly);
}
use of org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO in project cloudstack by apache.
the class VolumeApiServiceImpl method allocVolume.
/*
* Just allocate a volume in the database, don't send the createvolume cmd
* to hypervisor. The volume will be finally created only when it's attached
* to a VM.
*/
@Override
@DB
@ActionEvent(eventType = EventTypes.EVENT_VOLUME_CREATE, eventDescription = "creating volume", create = true)
public VolumeVO allocVolume(CreateVolumeCmd cmd) throws ResourceAllocationException {
Account caller = CallContext.current().getCallingAccount();
long ownerId = cmd.getEntityOwnerId();
Account owner = _accountMgr.getActiveAccountById(ownerId);
Boolean displayVolume = cmd.getDisplayVolume();
// permission check
_accountMgr.checkAccess(caller, null, true, _accountMgr.getActiveAccountById(ownerId));
if (displayVolume == null) {
displayVolume = true;
} else {
if (!_accountMgr.isRootAdmin(caller.getId())) {
throw new PermissionDeniedException("Cannot update parameter displayvolume, only admin permitted ");
}
}
// Check that the resource limit for volumes won't be exceeded
_resourceLimitMgr.checkResourceLimit(owner, ResourceType.volume, displayVolume);
Long zoneId = cmd.getZoneId();
Long diskOfferingId = null;
DiskOfferingVO diskOffering = null;
Long size = null;
Long minIops = null;
Long maxIops = null;
// Volume VO used for extracting the source template id
VolumeVO parentVolume = null;
// validate input parameters before creating the volume
if (cmd.getSnapshotId() == null && cmd.getDiskOfferingId() == null) {
throw new InvalidParameterValueException("At least one of disk Offering ID or snapshot ID must be passed whilst creating volume");
}
// disallow passing disk offering ID with DATA disk volume snapshots
if (cmd.getSnapshotId() != null && cmd.getDiskOfferingId() != null) {
SnapshotVO snapshot = _snapshotDao.findById(cmd.getSnapshotId());
if (snapshot != null) {
parentVolume = _volsDao.findByIdIncludingRemoved(snapshot.getVolumeId());
if (parentVolume != null && parentVolume.getVolumeType() != Volume.Type.ROOT)
throw new InvalidParameterValueException("Disk Offering ID cannot be passed whilst creating volume from snapshot other than ROOT disk snapshots");
}
parentVolume = null;
}
Map<String, String> details = new HashMap<>();
if (cmd.getDiskOfferingId() != null) {
// create a new volume
diskOfferingId = cmd.getDiskOfferingId();
size = cmd.getSize();
Long sizeInGB = size;
if (size != null) {
if (size > 0) {
// user specify size in GB
size = size * 1024 * 1024 * 1024;
} else {
throw new InvalidParameterValueException("Disk size must be larger than 0");
}
}
// Check that the the disk offering is specified
diskOffering = _diskOfferingDao.findById(diskOfferingId);
if ((diskOffering == null) || diskOffering.getRemoved() != null || diskOffering.isComputeOnly()) {
throw new InvalidParameterValueException("Please specify a valid disk offering.");
}
if (diskOffering.isCustomized()) {
if (size == null) {
throw new InvalidParameterValueException("This disk offering requires a custom size specified");
}
Long customDiskOfferingMaxSize = VolumeOrchestrationService.CustomDiskOfferingMaxSize.value();
Long customDiskOfferingMinSize = VolumeOrchestrationService.CustomDiskOfferingMinSize.value();
if ((sizeInGB < customDiskOfferingMinSize) || (sizeInGB > customDiskOfferingMaxSize)) {
throw new InvalidParameterValueException("Volume size: " + sizeInGB + "GB is out of allowed range. Max: " + customDiskOfferingMaxSize + " Min:" + customDiskOfferingMinSize);
}
}
if (!diskOffering.isCustomized() && size != null) {
throw new InvalidParameterValueException("This disk offering does not allow custom size");
}
_configMgr.checkDiskOfferingAccess(owner, diskOffering, _dcDao.findById(zoneId));
if (diskOffering.getDiskSize() > 0) {
size = diskOffering.getDiskSize();
}
DiskOfferingDetailVO bandwidthLimitDetail = _diskOfferingDetailsDao.findDetail(diskOfferingId, Volume.BANDWIDTH_LIMIT_IN_MBPS);
if (bandwidthLimitDetail != null) {
details.put(Volume.BANDWIDTH_LIMIT_IN_MBPS, bandwidthLimitDetail.getValue());
}
DiskOfferingDetailVO iopsLimitDetail = _diskOfferingDetailsDao.findDetail(diskOfferingId, Volume.IOPS_LIMIT);
if (iopsLimitDetail != null) {
details.put(Volume.IOPS_LIMIT, iopsLimitDetail.getValue());
}
Boolean isCustomizedIops = diskOffering.isCustomizedIops();
if (isCustomizedIops != null) {
if (isCustomizedIops) {
minIops = cmd.getMinIops();
maxIops = cmd.getMaxIops();
if (minIops == null && maxIops == null) {
minIops = 0L;
maxIops = 0L;
} else {
if (minIops == null || minIops <= 0) {
throw new InvalidParameterValueException("The min IOPS must be greater than 0.");
}
if (maxIops == null) {
maxIops = 0L;
}
if (minIops > maxIops) {
throw new InvalidParameterValueException("The min IOPS must be less than or equal to the max IOPS.");
}
}
} else {
minIops = diskOffering.getMinIops();
maxIops = diskOffering.getMaxIops();
}
} else {
minIops = diskOffering.getMinIops();
maxIops = diskOffering.getMaxIops();
}
if (!validateVolumeSizeInBytes(size)) {
throw new InvalidParameterValueException(String.format("Invalid size for custom volume creation: %s, max volume size is: %s GB", NumbersUtil.toReadableSize(size), VolumeOrchestrationService.MaxVolumeSize.value()));
}
}
if (cmd.getSnapshotId() != null) {
// create volume from snapshot
Long snapshotId = cmd.getSnapshotId();
SnapshotVO snapshotCheck = _snapshotDao.findById(snapshotId);
if (snapshotCheck == null) {
throw new InvalidParameterValueException("unable to find a snapshot with id " + snapshotId);
}
if (snapshotCheck.getState() != Snapshot.State.BackedUp) {
throw new InvalidParameterValueException("Snapshot id=" + snapshotId + " is not in " + Snapshot.State.BackedUp + " state yet and can't be used for volume creation");
}
SnapshotDataStoreVO snapshotStore = _snapshotDataStoreDao.findBySnapshot(snapshotId, DataStoreRole.Primary);
if (snapshotStore != null) {
StoragePoolVO storagePoolVO = _storagePoolDao.findById(snapshotStore.getDataStoreId());
if (storagePoolVO.getPoolType() == Storage.StoragePoolType.PowerFlex) {
throw new InvalidParameterValueException("Create volume from snapshot is not supported for PowerFlex volume snapshots");
}
}
parentVolume = _volsDao.findByIdIncludingRemoved(snapshotCheck.getVolumeId());
if (zoneId == null) {
// if zoneId is not provided, we default to create volume in the same zone as the snapshot zone.
zoneId = snapshotCheck.getDataCenterId();
}
if (diskOffering == null) {
// Pure snapshot is being used to create volume.
diskOfferingId = snapshotCheck.getDiskOfferingId();
diskOffering = _diskOfferingDao.findById(diskOfferingId);
minIops = snapshotCheck.getMinIops();
maxIops = snapshotCheck.getMaxIops();
// ; disk offering is used for tags purposes
size = snapshotCheck.getSize();
} else {
if (size < snapshotCheck.getSize()) {
throw new InvalidParameterValueException(String.format("Invalid size for volume creation: %dGB, snapshot size is: %dGB", size / (1024 * 1024 * 1024), snapshotCheck.getSize() / (1024 * 1024 * 1024)));
}
}
_configMgr.checkDiskOfferingAccess(null, diskOffering, _dcDao.findById(zoneId));
// check snapshot permissions
_accountMgr.checkAccess(caller, null, true, snapshotCheck);
// one step operation - create volume in VM's cluster and attach it
// to the VM
Long vmId = cmd.getVirtualMachineId();
if (vmId != null) {
// Check that the virtual machine ID is valid and it's a user vm
UserVmVO vm = _userVmDao.findById(vmId);
if (vm == null || vm.getType() != VirtualMachine.Type.User) {
throw new InvalidParameterValueException("Please specify a valid User VM.");
}
// Check that the VM is in the correct state
if (vm.getState() != State.Running && vm.getState() != State.Stopped) {
throw new InvalidParameterValueException("Please specify a VM that is either running or stopped.");
}
// permission check
_accountMgr.checkAccess(caller, null, false, vm);
}
}
Storage.ProvisioningType provisioningType = diskOffering.getProvisioningType();
// Check that the resource limit for primary storage won't be exceeded
_resourceLimitMgr.checkResourceLimit(owner, ResourceType.primary_storage, displayVolume, new Long(size));
// Verify that zone exists
DataCenterVO zone = _dcDao.findById(zoneId);
if (zone == null) {
throw new InvalidParameterValueException("Unable to find zone by id " + zoneId);
}
// Check if zone is disabled
if (Grouping.AllocationState.Disabled == zone.getAllocationState() && !_accountMgr.isRootAdmin(caller.getId())) {
throw new PermissionDeniedException("Cannot perform this operation, Zone is currently disabled: " + zoneId);
}
// offering not allowed
if (!zone.isLocalStorageEnabled() && diskOffering.isUseLocalStorage()) {
throw new InvalidParameterValueException("Zone is not configured to use local storage but volume's disk offering " + diskOffering.getName() + " uses it");
}
String userSpecifiedName = getVolumeNameFromCommand(cmd);
return commitVolume(cmd, caller, owner, displayVolume, zoneId, diskOfferingId, provisioningType, size, minIops, maxIops, parentVolume, userSpecifiedName, _uuidMgr.generateUuid(Volume.class, cmd.getCustomId()), details);
}
use of org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO in project cloudstack by apache.
the class StorageManagerImpl method cleanupStorage.
@Override
public void cleanupStorage(boolean recurring) {
GlobalLock scanLock = GlobalLock.getInternLock("storagemgr.cleanup");
try {
if (scanLock.lock(3)) {
try {
// Cleanup primary storage pools
if (TemplateCleanupEnabled.value()) {
List<StoragePoolVO> storagePools = _storagePoolDao.listAll();
for (StoragePoolVO pool : storagePools) {
try {
List<VMTemplateStoragePoolVO> unusedTemplatesInPool = _tmpltMgr.getUnusedTemplatesInPool(pool);
s_logger.debug("Storage pool garbage collector found " + unusedTemplatesInPool.size() + " templates to clean up in storage pool: " + pool.getName());
for (VMTemplateStoragePoolVO templatePoolVO : unusedTemplatesInPool) {
if (templatePoolVO.getDownloadState() != VMTemplateStorageResourceAssoc.Status.DOWNLOADED) {
s_logger.debug("Storage pool garbage collector is skipping template with ID: " + templatePoolVO.getTemplateId() + " on pool " + templatePoolVO.getPoolId() + " because it is not completely downloaded.");
continue;
}
if (!templatePoolVO.getMarkedForGC()) {
templatePoolVO.setMarkedForGC(true);
_vmTemplatePoolDao.update(templatePoolVO.getId(), templatePoolVO);
s_logger.debug("Storage pool garbage collector has marked template with ID: " + templatePoolVO.getTemplateId() + " on pool " + templatePoolVO.getPoolId() + " for garbage collection.");
continue;
}
_tmpltMgr.evictTemplateFromStoragePool(templatePoolVO);
}
} catch (Exception e) {
s_logger.warn("Problem cleaning up primary storage pool " + pool, e);
}
}
}
// destroy snapshots in destroying state in snapshot_store_ref
List<SnapshotDataStoreVO> ssSnapshots = _snapshotStoreDao.listByState(ObjectInDataStoreStateMachine.State.Destroying);
for (SnapshotDataStoreVO ssSnapshotVO : ssSnapshots) {
try {
_snapshotService.deleteSnapshot(snapshotFactory.getSnapshot(ssSnapshotVO.getSnapshotId(), DataStoreRole.Image));
} catch (Exception e) {
s_logger.debug("Failed to delete snapshot: " + ssSnapshotVO.getId() + " from storage");
}
}
cleanupSecondaryStorage(recurring);
List<VolumeVO> vols = _volsDao.listVolumesToBeDestroyed(new Date(System.currentTimeMillis() - ((long) StorageCleanupDelay.value() << 10)));
for (VolumeVO vol : vols) {
try {
// If this fails, just log a warning. It's ideal if we clean up the host-side clustered file
// system, but not necessary.
handleManagedStorage(vol);
} catch (Exception e) {
s_logger.warn("Unable to destroy host-side clustered file system " + vol.getUuid(), e);
}
try {
VolumeInfo volumeInfo = volFactory.getVolume(vol.getId());
if (volumeInfo != null) {
volService.ensureVolumeIsExpungeReady(vol.getId());
volService.expungeVolumeAsync(volumeInfo);
} else {
s_logger.debug("Volume " + vol.getUuid() + " is already destroyed");
}
} catch (Exception e) {
s_logger.warn("Unable to destroy volume " + vol.getUuid(), e);
}
}
// remove snapshots in Error state
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) {
s_logger.warn("Unable to destroy snapshot " + snapshotVO.getUuid(), e);
}
}
// destroy uploaded volumes in abandoned/error state
List<VolumeDataStoreVO> volumeDataStores = _volumeDataStoreDao.listByVolumeState(Volume.State.UploadError, Volume.State.UploadAbandoned);
for (VolumeDataStoreVO volumeDataStore : volumeDataStores) {
VolumeVO volume = _volumeDao.findById(volumeDataStore.getVolumeId());
if (volume == null) {
s_logger.warn("Uploaded volume with id " + volumeDataStore.getVolumeId() + " not found, so cannot be destroyed");
continue;
}
try {
DataStore dataStore = _dataStoreMgr.getDataStore(volumeDataStore.getDataStoreId(), DataStoreRole.Image);
EndPoint ep = _epSelector.select(dataStore, volumeDataStore.getExtractUrl());
if (ep == null) {
s_logger.warn("There is no secondary storage VM for image store " + dataStore.getName() + ", cannot destroy uploaded volume " + volume.getUuid());
continue;
}
Host host = _hostDao.findById(ep.getId());
if (host != null && host.getManagementServerId() != null) {
if (_serverId == host.getManagementServerId().longValue()) {
volService.destroyVolume(volume.getId());
// decrement volume resource count
_resourceLimitMgr.decrementResourceCount(volume.getAccountId(), ResourceType.volume, volume.isDisplayVolume());
// expunge volume from secondary if volume is on image store
VolumeInfo volOnSecondary = volFactory.getVolume(volume.getId(), DataStoreRole.Image);
if (volOnSecondary != null) {
s_logger.info("Expunging volume " + volume.getUuid() + " uploaded using HTTP POST from secondary data store");
AsyncCallFuture<VolumeApiResult> future = volService.expungeVolumeAsync(volOnSecondary);
VolumeApiResult result = future.get();
if (!result.isSuccess()) {
s_logger.warn("Failed to expunge volume " + volume.getUuid() + " from the image store " + dataStore.getName() + " due to: " + result.getResult());
}
}
}
}
} catch (Throwable th) {
s_logger.warn("Unable to destroy uploaded volume " + volume.getUuid() + ". Error details: " + th.getMessage());
}
}
// destroy uploaded templates in abandoned/error state
List<TemplateDataStoreVO> templateDataStores = _templateStoreDao.listByTemplateState(VirtualMachineTemplate.State.UploadError, VirtualMachineTemplate.State.UploadAbandoned);
for (TemplateDataStoreVO templateDataStore : templateDataStores) {
VMTemplateVO template = _templateDao.findById(templateDataStore.getTemplateId());
if (template == null) {
s_logger.warn("Uploaded template with id " + templateDataStore.getTemplateId() + " not found, so cannot be destroyed");
continue;
}
try {
DataStore dataStore = _dataStoreMgr.getDataStore(templateDataStore.getDataStoreId(), DataStoreRole.Image);
EndPoint ep = _epSelector.select(dataStore, templateDataStore.getExtractUrl());
if (ep == null) {
s_logger.warn("There is no secondary storage VM for image store " + dataStore.getName() + ", cannot destroy uploaded template " + template.getUuid());
continue;
}
Host host = _hostDao.findById(ep.getId());
if (host != null && host.getManagementServerId() != null) {
if (_serverId == host.getManagementServerId().longValue()) {
AsyncCallFuture<TemplateApiResult> future = _imageSrv.deleteTemplateAsync(tmplFactory.getTemplate(template.getId(), dataStore));
TemplateApiResult result = future.get();
if (!result.isSuccess()) {
s_logger.warn("Failed to delete template " + template.getUuid() + " from the image store " + dataStore.getName() + " due to: " + result.getResult());
continue;
}
// remove from template_zone_ref
List<VMTemplateZoneVO> templateZones = _vmTemplateZoneDao.listByZoneTemplate(((ImageStoreEntity) dataStore).getDataCenterId(), template.getId());
if (templateZones != null) {
for (VMTemplateZoneVO templateZone : templateZones) {
_vmTemplateZoneDao.remove(templateZone.getId());
}
}
// mark all the occurrences of this template in the given store as destroyed
_templateStoreDao.removeByTemplateStore(template.getId(), dataStore.getId());
// find all eligible image stores for this template
List<DataStore> imageStores = _tmpltMgr.getImageStoreByTemplate(template.getId(), null);
if (imageStores == null || imageStores.size() == 0) {
template.setState(VirtualMachineTemplate.State.Inactive);
_templateDao.update(template.getId(), template);
// decrement template resource count
_resourceLimitMgr.decrementResourceCount(template.getAccountId(), ResourceType.template);
}
}
}
} catch (Throwable th) {
s_logger.warn("Unable to destroy uploaded template " + template.getUuid() + ". Error details: " + th.getMessage());
}
}
cleanupInactiveTemplates();
} finally {
scanLock.unlock();
}
}
} finally {
scanLock.releaseRef();
}
}
use of org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO in project cloudstack by apache.
the class SnapshotManagerImpl method deleteSnapshot.
@Override
@DB
@ActionEvent(eventType = EventTypes.EVENT_SNAPSHOT_DELETE, eventDescription = "deleting snapshot", async = true)
public boolean deleteSnapshot(long snapshotId) {
Account caller = CallContext.current().getCallingAccount();
// Verify parameters
SnapshotVO snapshotCheck = _snapshotDao.findById(snapshotId);
if (snapshotCheck == null) {
throw new InvalidParameterValueException("unable to find a snapshot with id " + snapshotId);
}
if (snapshotCheck.getState() == Snapshot.State.Destroyed) {
throw new InvalidParameterValueException("Snapshot with id: " + snapshotId + " is already destroyed");
}
_accountMgr.checkAccess(caller, null, true, snapshotCheck);
SnapshotStrategy snapshotStrategy = _storageStrategyFactory.getSnapshotStrategy(snapshotCheck, SnapshotOperation.DELETE);
if (snapshotStrategy == null) {
s_logger.error("Unable to find snaphot strategy to handle snapshot with id '" + snapshotId + "'");
return false;
}
DataStoreRole dataStoreRole = getDataStoreRole(snapshotCheck);
SnapshotDataStoreVO snapshotStoreRef = _snapshotStoreDao.findBySnapshot(snapshotId, dataStoreRole);
try {
boolean result = snapshotStrategy.deleteSnapshot(snapshotId);
if (result) {
annotationDao.removeByEntityType(AnnotationService.EntityType.SNAPSHOT.name(), snapshotCheck.getUuid());
if (snapshotCheck.getState() == Snapshot.State.BackedUp) {
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_SNAPSHOT_DELETE, snapshotCheck.getAccountId(), snapshotCheck.getDataCenterId(), snapshotId, snapshotCheck.getName(), null, null, 0L, snapshotCheck.getClass().getName(), snapshotCheck.getUuid());
}
if (snapshotCheck.getState() != Snapshot.State.Error && snapshotCheck.getState() != Snapshot.State.Destroyed) {
_resourceLimitMgr.decrementResourceCount(snapshotCheck.getAccountId(), ResourceType.snapshot);
}
if (snapshotCheck.getState() == Snapshot.State.BackedUp) {
if (snapshotStoreRef != null) {
_resourceLimitMgr.decrementResourceCount(snapshotCheck.getAccountId(), ResourceType.secondary_storage, new Long(snapshotStoreRef.getPhysicalSize()));
}
}
}
return result;
} catch (Exception e) {
s_logger.debug("Failed to delete snapshot: " + snapshotCheck.getId() + ":" + e.toString());
throw new CloudRuntimeException("Failed to delete snapshot:" + e.toString());
}
}
use of org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO in project cloudstack by apache.
the class StorageManagerImpl method deleteImageStore.
@Override
public boolean deleteImageStore(DeleteImageStoreCmd cmd) {
final long storeId = cmd.getId();
// Verify that image store exists
ImageStoreVO store = _imageStoreDao.findById(storeId);
if (store == null) {
throw new InvalidParameterValueException("Image store with id " + storeId + " doesn't exist");
}
_accountMgr.checkAccessAndSpecifyAuthority(CallContext.current().getCallingAccount(), store.getDataCenterId());
// Verify that there are no live snapshot, template, volume on the image
// store to be deleted
List<SnapshotDataStoreVO> snapshots = _snapshotStoreDao.listByStoreId(storeId, DataStoreRole.Image);
if (snapshots != null && snapshots.size() > 0) {
throw new InvalidParameterValueException("Cannot delete image store with active snapshots backup!");
}
List<VolumeDataStoreVO> volumes = _volumeStoreDao.listByStoreId(storeId);
if (volumes != null && volumes.size() > 0) {
throw new InvalidParameterValueException("Cannot delete image store with active volumes backup!");
}
// search if there are user templates stored on this image store, excluding system, builtin templates
List<TemplateJoinVO> templates = _templateViewDao.listActiveTemplates(storeId);
if (templates != null && templates.size() > 0) {
throw new InvalidParameterValueException("Cannot delete image store with active templates backup!");
}
// ready to delete
Transaction.execute(new TransactionCallbackNoReturn() {
@Override
public void doInTransactionWithoutResult(TransactionStatus status) {
// first delete from image_store_details table, we need to do that since
// we are not actually deleting record from main
// image_data_store table, so delete cascade will not work
_imageStoreDetailsDao.deleteDetails(storeId);
_snapshotStoreDao.deletePrimaryRecordsForStore(storeId, DataStoreRole.Image);
_volumeStoreDao.deletePrimaryRecordsForStore(storeId);
_templateStoreDao.deletePrimaryRecordsForStore(storeId);
annotationDao.removeByEntityType(AnnotationService.EntityType.SECONDARY_STORAGE.name(), store.getUuid());
_imageStoreDao.remove(storeId);
}
});
return true;
}
Aggregations