mirror of https://github.com/apache/cloudstack.git
Bug : 15133
only delete snapshot which is not referenced by any snapshots in DB for a volume
This commit is contained in:
parent
c53c0ce906
commit
3286e6edba
|
|
@ -19,11 +19,14 @@ package com.cloud.agent.api;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
|
||||
public class CleanupSnapshotBackupCommand extends Command {
|
||||
private String secondaryStoragePoolURL;
|
||||
private Long dcId;
|
||||
private Long accountId;
|
||||
private Long volumeId;
|
||||
private HypervisorType type;
|
||||
private List<String> validBackupUUIDs;
|
||||
|
||||
protected CleanupSnapshotBackupCommand() {
|
||||
|
|
@ -40,12 +43,14 @@ public class CleanupSnapshotBackupCommand extends Command {
|
|||
Long dcId,
|
||||
Long accountId,
|
||||
Long volumeId,
|
||||
HypervisorType type,
|
||||
List<String> validBackupUUIDs)
|
||||
{
|
||||
this.secondaryStoragePoolURL = secondaryStoragePoolURL;
|
||||
this.dcId = dcId;
|
||||
this.accountId = accountId;
|
||||
this.volumeId = volumeId;
|
||||
this.type = type;
|
||||
this.validBackupUUIDs = validBackupUUIDs;
|
||||
}
|
||||
|
||||
|
|
@ -57,6 +62,10 @@ public class CleanupSnapshotBackupCommand extends Command {
|
|||
return dcId;
|
||||
}
|
||||
|
||||
public HypervisorType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public Long getAccountId() {
|
||||
return accountId;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
*/
|
||||
package com.cloud.storage.resource;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
|
|
@ -30,6 +31,7 @@ import java.security.NoSuchAlgorithmException;
|
|||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
|
@ -70,6 +72,7 @@ import com.cloud.agent.api.storage.DownloadProgressCommand;
|
|||
import com.cloud.agent.api.storage.UploadCommand;
|
||||
import com.cloud.host.Host;
|
||||
import com.cloud.host.Host.Type;
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.resource.ServerResourceBase;
|
||||
import com.cloud.storage.StorageLayer;
|
||||
import com.cloud.storage.template.DownloadManager;
|
||||
|
|
@ -83,6 +86,7 @@ import com.cloud.utils.component.ComponentLocator;
|
|||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.utils.net.NetUtils;
|
||||
import com.cloud.utils.net.NfsUtils;
|
||||
import com.cloud.utils.script.OutputInterpreter;
|
||||
import com.cloud.utils.script.Script;
|
||||
import com.cloud.vm.SecondaryStorageVm;
|
||||
|
||||
|
|
@ -405,6 +409,44 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
|
|||
return new Answer(cmd, true, null);
|
||||
}
|
||||
|
||||
public static class VhdChainParser extends OutputInterpreter {
|
||||
private List<List<String>> vhdchains = new ArrayList<List<String>>();
|
||||
|
||||
|
||||
public VhdChainParser() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String interpret(BufferedReader reader) throws IOException {
|
||||
String line = null;
|
||||
List<String> vhdchain = new ArrayList<String>();
|
||||
while ((line = reader.readLine()) != null) {
|
||||
s_logger.trace("VHD " + line);
|
||||
if(line.startsWith("vhd=") && !vhdchain.isEmpty()) {
|
||||
vhdchains.add(vhdchain);
|
||||
s_logger.trace("VHD CHAINS " + vhdchains);
|
||||
vhdchain = new ArrayList<String>();
|
||||
}
|
||||
vhdchain.add(line.trim().substring(4, 40));
|
||||
s_logger.trace("VHD CHAIN " + vhdchain);
|
||||
}
|
||||
if (!vhdchain.isEmpty()) {
|
||||
vhdchains.add(vhdchain);
|
||||
}
|
||||
s_logger.trace("VHD CHAINS " + vhdchains);
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<List<String>> getVhdChains() {
|
||||
return vhdchains;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean drain() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Answer execute(CleanupSnapshotBackupCommand cmd) {
|
||||
String parent = getRootDir(cmd.getSecondaryStoragePoolURL());
|
||||
if (!parent.endsWith(File.separator)) {
|
||||
|
|
@ -413,22 +455,64 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
|
|||
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);
|
||||
}
|
||||
}
|
||||
if (cmd.getType() == HypervisorType.XenServer ) {
|
||||
Script command = new Script("/bin/bash", s_logger);
|
||||
command.add("-c");
|
||||
command.add("/bin/vhd-util scan -p " + absoluteSnapsthotDir + "/*.vhd");
|
||||
VhdChainParser vhdChainParser = new VhdChainParser();
|
||||
String result = command.execute(vhdChainParser);
|
||||
if (result != null) {
|
||||
s_logger.warn("Can not parser VHD chain for snapshots of volume " + cmd.getVolumeId() );
|
||||
} else {
|
||||
List<List<String>> vhdChains = vhdChainParser.getVhdChains();
|
||||
s_logger.trace("VHD CHAINS " + vhdChains);
|
||||
for (String uuid : cmd.getValidBackupUUIDs()) {
|
||||
Iterator<List<String>> it = vhdChains.iterator();
|
||||
while (it.hasNext()) {
|
||||
List<String> vhdchain = it.next();
|
||||
s_logger.trace("VHD CHAIN " + vhdchain);
|
||||
if (vhdchain == null || vhdchain.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
if (vhdchain.contains(uuid)) {
|
||||
s_logger.trace("VHD keep vhd chain " + vhdchain);
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
s_logger.trace("VHD CHAINS " + vhdChains);
|
||||
for (List<String> vhdchain : vhdChains) {
|
||||
if (vhdchain == null || vhdchain.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
for (String uuid : vhdchain) {
|
||||
File file = new File(absoluteSnapsthotDir + "/"
|
||||
+ uuid + ".vhd");
|
||||
file.delete();
|
||||
String msg = "snapshot " + file.getName() + " is removed";
|
||||
s_logger.warn(msg);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1063,9 +1063,7 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag
|
|||
@Override
|
||||
public boolean start() {
|
||||
if (_storageCleanupEnabled) {
|
||||
Random generator = new Random();
|
||||
int initialDelay = generator.nextInt(_storageCleanupInterval);
|
||||
_executor.scheduleWithFixedDelay(new StorageGarbageCollector(), initialDelay, _storageCleanupInterval, TimeUnit.SECONDS);
|
||||
_executor.scheduleWithFixedDelay(new StorageGarbageCollector(), _storageCleanupInterval, _storageCleanupInterval, TimeUnit.SECONDS);
|
||||
} else {
|
||||
s_logger.debug("Storage cleanup is not enabled, so the storage cleanup thread is not being scheduled.");
|
||||
}
|
||||
|
|
@ -2130,8 +2128,11 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag
|
|||
if (snapshots == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
HypervisorType type = _clusterDao.findById(_storagePoolDao.findById(volume.getPoolId()).getClusterId()).getHypervisorType();
|
||||
|
||||
CleanupSnapshotBackupCommand cmd = new CleanupSnapshotBackupCommand(secondaryStorageHost.getStorageUrl(), secondaryStorageHost.getDataCenterId(), volume.getAccountId(),
|
||||
volumeId, snapshots);
|
||||
volumeId, type, snapshots);
|
||||
|
||||
Answer answer = _agentMgr.sendToSecStorage(secondaryStorageHost, cmd);
|
||||
if ((answer == null) || !answer.getResult()) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue