mirror of
https://github.com/apache/cloudstack.git
synced 2025-11-03 04:12:31 +01:00
cleanup snapshot in secondary storage in background
Conflicts: core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java server/src/com/cloud/storage/StorageManager.java server/src/com/cloud/storage/StorageManagerImpl.java
This commit is contained in:
parent
fa2a308d56
commit
86aef08865
@ -39,6 +39,7 @@ import org.apache.log4j.Logger;
|
||||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.CheckHealthAnswer;
|
||||
import com.cloud.agent.api.CheckHealthCommand;
|
||||
import com.cloud.agent.api.CleanupSnapshotBackupCommand;
|
||||
import com.cloud.agent.api.Command;
|
||||
import com.cloud.agent.api.ComputeChecksumCommand;
|
||||
import com.cloud.agent.api.DeleteObjectFromSwiftCommand;
|
||||
@ -165,6 +166,8 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
|
||||
return execute((uploadTemplateToSwiftFromSecondaryStorageCommand) cmd);
|
||||
} else if (cmd instanceof DeleteObjectFromSwiftCommand) {
|
||||
return execute((DeleteObjectFromSwiftCommand) cmd);
|
||||
} else if (cmd instanceof CleanupSnapshotBackupCommand){
|
||||
return execute((CleanupSnapshotBackupCommand)cmd);
|
||||
} else {
|
||||
return Answer.createUnsupportedCommandAnswer(cmd);
|
||||
}
|
||||
@ -837,6 +840,35 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
|
||||
return new Answer(cmd, true, null);
|
||||
}
|
||||
|
||||
Answer execute(CleanupSnapshotBackupCommand cmd) {
|
||||
String parent = getRootDir(cmd.getSecondaryStoragePoolURL());
|
||||
if (!parent.endsWith(File.separator)) {
|
||||
parent += File.separator;
|
||||
}
|
||||
String absoluteSnapsthotDir = parent + File.separator + "snapshots" + File.separator + cmd.getAccountId() + File.separator + cmd.getVolumeId();
|
||||
File ssParent = new File(absoluteSnapsthotDir);
|
||||
if (ssParent.exists() && ssParent.isDirectory()) {
|
||||
File[] files = ssParent.listFiles();
|
||||
for (File file : files) {
|
||||
boolean found = false;
|
||||
String filename = file.getName();
|
||||
for (String uuid : cmd.getValidBackupUUIDs()) {
|
||||
if (filename.startsWith(uuid)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
file.delete();
|
||||
String msg = "snapshot " + filename + " is not recorded in DB, remove it";
|
||||
s_logger.warn(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
return new Answer(cmd, true, null);
|
||||
}
|
||||
|
||||
|
||||
synchronized public String getRootDir(String secUrl) {
|
||||
try {
|
||||
URI uri = new URI(secUrl);
|
||||
|
||||
@ -224,4 +224,5 @@ public interface StorageManager extends Manager {
|
||||
|
||||
List<Long> getUpHostsInPool(long poolId);
|
||||
|
||||
void cleanupSecondaryStorage(boolean recurring);
|
||||
}
|
||||
|
||||
@ -20,6 +20,8 @@ package com.cloud.storage;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
@ -45,6 +47,7 @@ import org.apache.log4j.Logger;
|
||||
import com.cloud.agent.AgentManager;
|
||||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.BackupSnapshotCommand;
|
||||
import com.cloud.agent.api.CleanupSnapshotBackupCommand;
|
||||
import com.cloud.agent.api.Command;
|
||||
import com.cloud.agent.api.CreateStoragePoolCommand;
|
||||
import com.cloud.agent.api.CreateVolumeFromSnapshotAnswer;
|
||||
@ -1102,7 +1105,9 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag
|
||||
@Override
|
||||
public boolean start() {
|
||||
if (_storageCleanupEnabled) {
|
||||
_executor.scheduleWithFixedDelay(new StorageGarbageCollector(), _storageCleanupInterval, _storageCleanupInterval, TimeUnit.SECONDS);
|
||||
Random generator = new Random();
|
||||
int initialDelay = generator.nextInt(_storageCleanupInterval);
|
||||
_executor.scheduleWithFixedDelay(new StorageGarbageCollector(), initialDelay, _storageCleanupInterval, TimeUnit.SECONDS);
|
||||
} else {
|
||||
s_logger.debug("Storage cleanup is not enabled, so the storage cleanup thread is not being scheduled.");
|
||||
}
|
||||
@ -1978,46 +1983,8 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup secondary storage hosts
|
||||
List<HostVO> secondaryStorageHosts = _ssvmMgr.listSecondaryStorageHostsInAllZones();
|
||||
for (HostVO secondaryStorageHost : secondaryStorageHosts) {
|
||||
try {
|
||||
long hostId = secondaryStorageHost.getId();
|
||||
List<VMTemplateHostVO> destroyedTemplateHostVOs = _vmTemplateHostDao.listDestroyed(hostId);
|
||||
s_logger.debug("Secondary storage garbage collector found " + destroyedTemplateHostVOs.size() + " templates to cleanup on secondary storage host: "
|
||||
+ secondaryStorageHost.getName());
|
||||
for (VMTemplateHostVO destroyedTemplateHostVO : destroyedTemplateHostVOs) {
|
||||
if (!_tmpltMgr.templateIsDeleteable(destroyedTemplateHostVO)) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Not deleting template at: " + destroyedTemplateHostVO);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Deleting template host: " + destroyedTemplateHostVO);
|
||||
}
|
||||
|
||||
String installPath = destroyedTemplateHostVO.getInstallPath();
|
||||
|
||||
if (installPath != null) {
|
||||
Answer answer = _agentMgr.sendToSecStorage(secondaryStorageHost, new DeleteTemplateCommand(secondaryStorageHost.getStorageUrl(),destroyedTemplateHostVO.getInstallPath()));
|
||||
|
||||
if (answer == null || !answer.getResult()) {
|
||||
s_logger.debug("Failed to delete " + destroyedTemplateHostVO + " due to " + ((answer == null) ? "answer is null" : answer.getDetails()));
|
||||
} else {
|
||||
_vmTemplateHostDao.remove(destroyedTemplateHostVO.getId());
|
||||
s_logger.debug("Deleted template at: " + destroyedTemplateHostVO.getInstallPath());
|
||||
}
|
||||
} else {
|
||||
_vmTemplateHostDao.remove(destroyedTemplateHostVO.getId());
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
s_logger.warn("problem cleaning up secondary storage " + secondaryStorageHost, e);
|
||||
}
|
||||
}
|
||||
|
||||
cleanupSecondaryStorage(recurring);
|
||||
|
||||
List<VolumeVO> vols = _volsDao.listVolumesToBeDestroyed();
|
||||
for (VolumeVO vol : vols) {
|
||||
@ -2035,6 +2002,142 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag
|
||||
scanLock.releaseRef();
|
||||
}
|
||||
}
|
||||
|
||||
@DB
|
||||
List<Long> findAllVolumeIdInSnapshotTable(Long hostId) {
|
||||
String sql = "SELECT volume_id from snapshots WHERE sechost_id=? GROUP BY volume_id";
|
||||
List<Long> list = new ArrayList<Long>();
|
||||
try {
|
||||
Transaction txn = Transaction.currentTxn();
|
||||
ResultSet rs = null;
|
||||
PreparedStatement pstmt = null;
|
||||
pstmt = txn.prepareAutoCloseStatement(sql);
|
||||
pstmt.setLong(1, hostId);
|
||||
rs = pstmt.executeQuery();
|
||||
while (rs.next()) {
|
||||
list.add(rs.getLong(1));
|
||||
}
|
||||
return list;
|
||||
} catch (Exception e) {
|
||||
s_logger.debug("failed to get all volumes who has snapshots in secondary storage " + hostId + " due to " + e.getMessage());
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
List<String> findAllSnapshotForVolume(Long volumeId) {
|
||||
String sql = "SELECT backup_snap_id FROM snapshots WHERE volume_id=? and backup_snap_id is not NULL";
|
||||
try {
|
||||
Transaction txn = Transaction.currentTxn();
|
||||
ResultSet rs = null;
|
||||
PreparedStatement pstmt = null;
|
||||
pstmt = txn.prepareAutoCloseStatement(sql);
|
||||
pstmt.setLong(1, volumeId);
|
||||
rs = pstmt.executeQuery();
|
||||
List<String> list = new ArrayList<String>();
|
||||
while (rs.next()) {
|
||||
list.add(rs.getString(1));
|
||||
}
|
||||
return list;
|
||||
} catch (Exception e) {
|
||||
s_logger.debug("failed to get all snapshots for a volume " + volumeId + " due to " + e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@DB
|
||||
public void cleanupSecondaryStorage(boolean recurring) {
|
||||
try {
|
||||
// Cleanup templates in secondary storage hosts
|
||||
List<HostVO> secondaryStorageHosts = _hostDao.listSecondaryStorageHosts();
|
||||
for (HostVO secondaryStorageHost : secondaryStorageHosts) {
|
||||
try {
|
||||
long hostId = secondaryStorageHost.getId();
|
||||
List<VMTemplateHostVO> destroyedTemplateHostVOs = _vmTemplateHostDao.listDestroyed(hostId);
|
||||
s_logger.debug("Secondary storage garbage collector found " + destroyedTemplateHostVOs.size() + " templates to cleanup on secondary storage host: "
|
||||
+ secondaryStorageHost.getName());
|
||||
for (VMTemplateHostVO destroyedTemplateHostVO : destroyedTemplateHostVOs) {
|
||||
if (!_tmpltMgr.templateIsDeleteable(destroyedTemplateHostVO)) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Not deleting template at: " + destroyedTemplateHostVO);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Deleting template host: " + destroyedTemplateHostVO);
|
||||
}
|
||||
|
||||
String installPath = destroyedTemplateHostVO.getInstallPath();
|
||||
|
||||
if (installPath != null) {
|
||||
Answer answer = _agentMgr.sendToSecStorage(secondaryStorageHost, new DeleteTemplateCommand(secondaryStorageHost.getStorageUrl(), destroyedTemplateHostVO.getInstallPath()));
|
||||
|
||||
if (answer == null || !answer.getResult()) {
|
||||
s_logger.debug("Failed to delete " + destroyedTemplateHostVO + " due to " + ((answer == null) ? "answer is null" : answer.getDetails()));
|
||||
} else {
|
||||
_vmTemplateHostDao.remove(destroyedTemplateHostVO.getId());
|
||||
s_logger.debug("Deleted template at: " + destroyedTemplateHostVO.getInstallPath());
|
||||
}
|
||||
} else {
|
||||
_vmTemplateHostDao.remove(destroyedTemplateHostVO.getId());
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
s_logger.warn("problem cleaning up templates in secondary storage " + secondaryStorageHost, e);
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup snapshot in secondary storage hosts
|
||||
for (HostVO secondaryStorageHost : secondaryStorageHosts) {
|
||||
try {
|
||||
long hostId = secondaryStorageHost.getId();
|
||||
List<Long> vIDs = findAllVolumeIdInSnapshotTable(hostId);
|
||||
if (vIDs == null) {
|
||||
continue;
|
||||
}
|
||||
for (Long volumeId : vIDs) {
|
||||
boolean lock = false;
|
||||
try {
|
||||
VolumeVO volume = _volsDao.findByIdIncludingRemoved(volumeId);
|
||||
if (volume.getRemoved() == null) {
|
||||
volume = _volsDao.acquireInLockTable(volumeId, 10);
|
||||
if (volume == null) {
|
||||
continue;
|
||||
}
|
||||
lock = true;
|
||||
}
|
||||
List<String> snapshots = findAllSnapshotForVolume(volumeId);
|
||||
if (snapshots == null) {
|
||||
continue;
|
||||
}
|
||||
CleanupSnapshotBackupCommand cmd = new CleanupSnapshotBackupCommand(secondaryStorageHost.getStorageUrl(), secondaryStorageHost.getDataCenterId(), volume.getAccountId(),
|
||||
volumeId, snapshots);
|
||||
|
||||
Answer answer = _agentMgr.sendToSecStorage(secondaryStorageHost, cmd);
|
||||
if ((answer == null) || !answer.getResult()) {
|
||||
String details = "Failed to cleanup snapshots for volume " + volumeId + " due to " + (answer == null ? "null" : answer.getDetails());
|
||||
s_logger.warn(details);
|
||||
}
|
||||
} catch (Exception e1) {
|
||||
s_logger.warn("problem cleaning up snapshots in secondary storage " + secondaryStorageHost, e1);
|
||||
} finally {
|
||||
if (lock) {
|
||||
_volsDao.releaseFromLockTable(volumeId);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e2) {
|
||||
s_logger.warn("problem cleaning up snapshots in secondary storage " + secondaryStorageHost, e2);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception e3) {
|
||||
s_logger.warn("problem cleaning up secondary storage ", e3);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPrimaryStorageNameLabel(VolumeVO volume) {
|
||||
@ -3087,6 +3190,7 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onManagementNodeJoined(List<ManagementServerHostVO> nodeList, long selfNodeId) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user