delete snapshot at the backend

This commit is contained in:
Edison Su 2013-05-14 21:57:07 -07:00
parent c6a5a7ee00
commit 879a954b98
15 changed files with 242 additions and 95 deletions

View File

@ -53,8 +53,8 @@ public class SnapshotCommand extends Command {
public SnapshotCommand(StoragePool pool, public SnapshotCommand(StoragePool pool,
String secondaryStorageUrl, String snapshotUuid, String secondaryStorageUrl, String snapshotUuid,
String snapshotName, Long dcId, Long accountId, Long volumeId) { String snapshotName, Long dcId, Long accountId, Long volumeId) {
this.primaryStoragePoolNameLabel = pool.getUuid(); // this.primaryStoragePoolNameLabel = pool.getUuid();
this.primaryPool = new StorageFilerTO(pool); //this.primaryPool = new StorageFilerTO(pool);
this.snapshotUuid = snapshotUuid; this.snapshotUuid = snapshotUuid;
this.secondaryStorageUrl = secondaryStorageUrl; this.secondaryStorageUrl = secondaryStorageUrl;
this.dcId = dcId; this.dcId = dcId;

View File

@ -25,8 +25,6 @@ import org.apache.cloudstack.storage.command.DeleteCommand;
import org.apache.cloudstack.storage.command.DettachCommand; import org.apache.cloudstack.storage.command.DettachCommand;
import com.cloud.agent.api.Answer; import com.cloud.agent.api.Answer;
import com.cloud.agent.api.to.DataTO;
import com.cloud.agent.api.to.DiskTO;
public interface StorageProcessor { public interface StorageProcessor {
public Answer copyTemplateToPrimaryStorage(CopyCommand cmd); public Answer copyTemplateToPrimaryStorage(CopyCommand cmd);
@ -43,4 +41,5 @@ public interface StorageProcessor {
public Answer createSnapshot(CreateObjectCommand cmd); public Answer createSnapshot(CreateObjectCommand cmd);
public Answer deleteVolume(DeleteCommand cmd); public Answer deleteVolume(DeleteCommand cmd);
public Answer createVolumeFromSnapshot(CopyCommand cmd); public Answer createVolumeFromSnapshot(CopyCommand cmd);
public Answer deleteSnapshot(DeleteCommand cmd);
} }

View File

@ -110,6 +110,8 @@ public class StorageSubsystemCommandHandlerBase implements StorageSubsystemComma
Answer answer = null; Answer answer = null;
if (data.getObjectType() == DataObjectType.VOLUME) { if (data.getObjectType() == DataObjectType.VOLUME) {
answer = processor.deleteVolume(cmd); answer = processor.deleteVolume(cmd);
} else if (data.getObjectType() == DataObjectType.SNAPSHOT) {
answer = processor.deleteSnapshot(cmd);
} else { } else {
answer = new Answer(cmd, false, "unsupported type"); answer = new Answer(cmd, false, "unsupported type");
} }

View File

@ -51,6 +51,7 @@ import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
import com.cloud.utils.S3Utils; import com.cloud.utils.S3Utils;
import com.cloud.utils.UriUtils; import com.cloud.utils.UriUtils;
import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.script.Script;
@Component @Component
public class MockLocalNfsSecondaryStorageResource extends public class MockLocalNfsSecondaryStorageResource extends
@ -67,6 +68,8 @@ public class MockLocalNfsSecondaryStorageResource extends
// TODO Auto-generated catch block // TODO Auto-generated catch block
e.printStackTrace(); e.printStackTrace();
} }
createTemplateFromSnapshotXenScript = Script.findScript(getDefaultScriptsDir(), "create_privatetemplate_from_snapshot_xen.sh");
/* /*
_storage = new JavaStorageLayer(); _storage = new JavaStorageLayer();

View File

@ -0,0 +1,20 @@
package org.apache.cloudstack.storage.test;
import org.apache.cloudstack.storage.LocalHostEndpoint;
import org.apache.cloudstack.storage.command.CopyCommand;
import org.apache.cloudstack.storage.command.DownloadCommand;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
import com.cloud.agent.api.DeleteSnapshotBackupCommand;
public class MockLocalHostEndPoint extends LocalHostEndpoint {
@Override
public Answer sendMessage(Command cmd) {
if ((cmd instanceof CopyCommand) || (cmd instanceof DownloadCommand) || (cmd instanceof DeleteSnapshotBackupCommand)) {
return resource.executeRequest(cmd);
}
// TODO Auto-generated method stub
return new Answer(cmd, false, "unsupported command:" + cmd.toString());
}
}

View File

@ -156,6 +156,7 @@ public class SnapshotTest extends CloudStackTestNGBase {
long primaryStoreId; long primaryStoreId;
VMTemplateVO image; VMTemplateVO image;
String imageStoreName = "testImageStore"; String imageStoreName = "testImageStore";
RemoteHostEndPoint remoteEp;
@Test(priority = -1) @Test(priority = -1)
public void setUp() { public void setUp() {
ComponentContext.initComponentsLifeCycle(); ComponentContext.initComponentsLifeCycle();
@ -250,6 +251,7 @@ public class SnapshotTest extends CloudStackTestNGBase {
TemplateObjectTO to = new TemplateObjectTO(); TemplateObjectTO to = new TemplateObjectTO();
to.setPath(this.getImageInstallPath()); to.setPath(this.getImageInstallPath());
to.setFormat(ImageFormat.VHD); to.setFormat(ImageFormat.VHD);
to.setSize(1000L);
CopyCmdAnswer answer = new CopyCmdAnswer(to); CopyCmdAnswer answer = new CopyCmdAnswer(to);
templateOnStore.processEvent(Event.CreateOnlyRequested); templateOnStore.processEvent(Event.CreateOnlyRequested);
templateOnStore.processEvent(Event.OperationSuccessed, answer); templateOnStore.processEvent(Event.OperationSuccessed, answer);
@ -263,10 +265,10 @@ public class SnapshotTest extends CloudStackTestNGBase {
hosts.add(this.host); hosts.add(this.host);
Mockito.when(resourceMgr.listAllUpAndEnabledHosts((Type) Mockito.any(), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong())).thenReturn(hosts); Mockito.when(resourceMgr.listAllUpAndEnabledHosts((Type) Mockito.any(), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong())).thenReturn(hosts);
RemoteHostEndPoint ep = RemoteHostEndPoint.getHypervisorHostEndPoint(this.host.getId(), this.host.getPrivateIpAddress()); remoteEp = RemoteHostEndPoint.getHypervisorHostEndPoint(this.host.getId(), this.host.getPrivateIpAddress());
Mockito.when(epSelector.select(Mockito.any(DataObject.class), Mockito.any(DataObject.class))).thenReturn(ep); Mockito.when(epSelector.select(Mockito.any(DataObject.class), Mockito.any(DataObject.class))).thenReturn(remoteEp);
Mockito.when(epSelector.select(Mockito.any(DataObject.class))).thenReturn(ep); Mockito.when(epSelector.select(Mockito.any(DataObject.class))).thenReturn(remoteEp);
Mockito.when(epSelector.select(Mockito.any(DataStore.class))).thenReturn(ep); Mockito.when(epSelector.select(Mockito.any(DataStore.class))).thenReturn(remoteEp);
Mockito.when(hyGuruMgr.getGuruProcessedCommandTargetHost(Mockito.anyLong(), Mockito.any(Command.class))).thenReturn(this.host.getId()); Mockito.when(hyGuruMgr.getGuruProcessedCommandTargetHost(Mockito.anyLong(), Mockito.any(Command.class))).thenReturn(this.host.getId());
} }
@ -360,20 +362,35 @@ public class SnapshotTest extends CloudStackTestNGBase {
return null; return null;
} }
//@Test @Test
public void createSnapshot() { public void createSnapshot() {
VolumeInfo vol = createCopyBaseImage(); VolumeInfo vol = createCopyBaseImage();
SnapshotVO snapshotVO = createSnapshotInDb(vol); SnapshotVO snapshotVO = createSnapshotInDb(vol);
SnapshotInfo snapshot = this.snapshotFactory.getSnapshot(snapshotVO.getId(), vol.getDataStore()); SnapshotInfo snapshot = this.snapshotFactory.getSnapshot(snapshotVO.getId(), vol.getDataStore());
SnapshotInfo newSnapshot = null;
for (SnapshotStrategy strategy : this.snapshotStrategies) { for (SnapshotStrategy strategy : this.snapshotStrategies) {
if (strategy.canHandle(snapshot)) { if (strategy.canHandle(snapshot)) {
strategy.takeSnapshot(snapshot); newSnapshot = strategy.takeSnapshot(snapshot);
} }
} }
AssertJUnit.assertNotNull(newSnapshot);
LocalHostEndpoint ep = new MockLocalHostEndPoint();
ep.setResource(new MockLocalNfsSecondaryStorageResource());
Mockito.when(epSelector.select(Mockito.any(DataStore.class))).thenReturn(ep);
//delete snapshot
for (SnapshotStrategy strategy : this.snapshotStrategies) {
if (strategy.canHandle(snapshot)) {
strategy.deleteSnapshot(newSnapshot.getId());
}
}
Mockito.when(epSelector.select(Mockito.any(DataStore.class))).thenReturn(remoteEp);
} }
private VMTemplateVO createTemplateInDb() { private VMTemplateVO createTemplateInDb() {
image = new VMTemplateVO(); VMTemplateVO image = new VMTemplateVO();
image.setTemplateType(TemplateType.USER); image.setTemplateType(TemplateType.USER);
image.setUniqueName(UUID.randomUUID().toString()); image.setUniqueName(UUID.randomUUID().toString());
@ -393,8 +410,50 @@ public class SnapshotTest extends CloudStackTestNGBase {
image = imageDataDao.persist(image); image = imageDataDao.persist(image);
return image; return image;
} }
@Test
public void createVolumeFromSnapshot() {
VolumeInfo vol = createCopyBaseImage();
SnapshotVO snapshotVO = createSnapshotInDb(vol);
SnapshotInfo snapshot = this.snapshotFactory.getSnapshot(snapshotVO.getId(), vol.getDataStore());
boolean result = false;
for (SnapshotStrategy strategy : this.snapshotStrategies) {
if (strategy.canHandle(snapshot)) {
snapshot = strategy.takeSnapshot(snapshot);
result = true;
}
}
//@Test AssertJUnit.assertTrue(result);
VolumeVO volVO = createVolume(vol.getTemplateId(), vol.getPoolId());
VolumeInfo newVol = this.volFactory.getVolume(volVO.getId());
this.volumeService.createVolumeFromSnapshot(newVol, newVol.getDataStore(), snapshot);
}
@Test
public void deleteSnapshot() {
VolumeInfo vol = createCopyBaseImage();
SnapshotVO snapshotVO = createSnapshotInDb(vol);
SnapshotInfo snapshot = this.snapshotFactory.getSnapshot(snapshotVO.getId(), vol.getDataStore());
SnapshotInfo newSnapshot = null;
for (SnapshotStrategy strategy : this.snapshotStrategies) {
if (strategy.canHandle(snapshot)) {
newSnapshot = strategy.takeSnapshot(snapshot);
}
}
AssertJUnit.assertNotNull(newSnapshot);
//create another snapshot
for (SnapshotStrategy strategy : this.snapshotStrategies) {
if (strategy.canHandle(snapshot)) {
strategy.deleteSnapshot(newSnapshot.getId());
}
}
}
@Test
public void createTemplateFromSnapshot() { public void createTemplateFromSnapshot() {
VolumeInfo vol = createCopyBaseImage(); VolumeInfo vol = createCopyBaseImage();
SnapshotVO snapshotVO = createSnapshotInDb(vol); SnapshotVO snapshotVO = createSnapshotInDb(vol);
@ -417,23 +476,5 @@ public class SnapshotTest extends CloudStackTestNGBase {
this.imageService.createTemplateFromSnapshotAsync(snapshot, tmpl, imageStore); this.imageService.createTemplateFromSnapshotAsync(snapshot, tmpl, imageStore);
} }
@Test
public void createVolumeFromSnapshot() {
VolumeInfo vol = createCopyBaseImage();
SnapshotVO snapshotVO = createSnapshotInDb(vol);
SnapshotInfo snapshot = this.snapshotFactory.getSnapshot(snapshotVO.getId(), vol.getDataStore());
boolean result = false;
for (SnapshotStrategy strategy : this.snapshotStrategies) {
if (strategy.canHandle(snapshot)) {
snapshot = strategy.takeSnapshot(snapshot);
result = true;
}
}
AssertJUnit.assertTrue(result);
VolumeVO volVO = createVolume(vol.getTemplateId(), vol.getPoolId());
VolumeInfo newVol = this.volFactory.getVolume(volVO.getId());
this.volumeService.createVolumeFromSnapshot(newVol, newVol.getDataStore(), snapshot);
}
} }

View File

@ -299,6 +299,9 @@ public class SnapshotServiceImpl implements SnapshotService {
try { try {
SnapshotResult res = future.get(); SnapshotResult res = future.get();
if (res.isFailed()) {
throw new CloudRuntimeException(res.getResult());
}
SnapshotInfo destSnapshot = res.getSnashot(); SnapshotInfo destSnapshot = res.getSnashot();
return destSnapshot; return destSnapshot;
} catch (InterruptedException e) { } catch (InterruptedException e) {
@ -319,6 +322,12 @@ public class SnapshotServiceImpl implements SnapshotService {
AsyncCallFuture<SnapshotResult> future = context.future; AsyncCallFuture<SnapshotResult> future = context.future;
SnapshotResult snapResult = new SnapshotResult(destSnapshot, result.getAnswer()); SnapshotResult snapResult = new SnapshotResult(destSnapshot, result.getAnswer());
if (result.isFailed()) { if (result.isFailed()) {
try {
destSnapshot.processEvent(Event.OperationFailed);
srcSnapshot.processEvent(Snapshot.Event.OperationFailed);
} catch (NoTransitionException e) {
s_logger.debug("Failed to update state: " + e.toString());
}
snapResult.setResult(result.getResult()); snapResult.setResult(result.getResult());
future.complete(snapResult); future.complete(snapResult);
return null; return null;
@ -397,7 +406,33 @@ public class SnapshotServiceImpl implements SnapshotService {
@Override @Override
public boolean deleteSnapshot(SnapshotInfo snapInfo) { public boolean deleteSnapshot(SnapshotInfo snapInfo) {
return true; snapInfo.processEvent(ObjectInDataStoreStateMachine.Event.DestroyRequested);
AsyncCallFuture<SnapshotResult> future = new AsyncCallFuture<SnapshotResult>();
DeleteSnapshotContext<CommandResult> context = new DeleteSnapshotContext<CommandResult>(null,
snapInfo, future);
AsyncCallbackDispatcher<SnapshotServiceImpl, CommandResult> caller = AsyncCallbackDispatcher
.create(this);
caller.setCallback(
caller.getTarget().deleteSnapshotCallback(null, null))
.setContext(context);
DataStore store = snapInfo.getDataStore();
store.getDriver().deleteAsync(snapInfo, caller);
SnapshotResult result = null;
try {
result = future.get();
if (result.isFailed()) {
throw new CloudRuntimeException(result.getResult());
}
return true;
} catch (InterruptedException e) {
s_logger.debug("delete snapshot is failed: " + e.toString());
} catch (ExecutionException e) {
s_logger.debug("delete snapshot is failed: " + e.toString());
}
return false;
} }

View File

@ -139,7 +139,7 @@ public class XenserverSnapshotStrategy extends SnapshotStrategyBase {
SnapshotInfo child = snapshot.getChild(); SnapshotInfo child = snapshot.getChild();
SnapshotInfo parent = snapshot.getParent(); SnapshotInfo parent = snapshot.getParent();
if (child == null) { if (child == null) {
if (!parent.getPath().equalsIgnoreCase(snapshot.getPath())) { if (parent == null || !parent.getPath().equalsIgnoreCase(snapshot.getPath())) {
this.snapshotSvr.deleteSnapshot(snapshot); this.snapshotSvr.deleteSnapshot(snapshot);
snapshot = parent; snapshot = parent;
continue; continue;
@ -178,9 +178,10 @@ public class XenserverSnapshotStrategy extends SnapshotStrategyBase {
} }
try { try {
/*
if (snapshotOnPrimary != null) { if (snapshotOnPrimary != null) {
deleteSnapshotChain(snapshotOnPrimary); deleteSnapshotChain(snapshotOnPrimary);
} }*/
SnapshotInfo snapshotOnImage = this.snapshotDataFactory.getSnapshot(snapshotId, DataStoreRole.Image); SnapshotInfo snapshotOnImage = this.snapshotDataFactory.getSnapshot(snapshotId, DataStoreRole.Image);
if (snapshotOnImage != null) { if (snapshotOnImage != null) {

View File

@ -36,7 +36,7 @@ import com.cloud.storage.download.DownloadListener;
public class LocalHostEndpoint implements EndPoint { public class LocalHostEndpoint implements EndPoint {
private ScheduledExecutorService executor; private ScheduledExecutorService executor;
ServerResource resource; protected ServerResource resource;
public LocalHostEndpoint() { public LocalHostEndpoint() {
resource = new LocalNfsSecondaryStorageResource(); resource = new LocalNfsSecondaryStorageResource();
executor = Executors.newScheduledThreadPool(10); executor = Executors.newScheduledThreadPool(10);

View File

@ -409,6 +409,8 @@ public class KVMStorageProcessor implements StorageProcessor {
TemplateObjectTO newTemplate = new TemplateObjectTO(); TemplateObjectTO newTemplate = new TemplateObjectTO();
newTemplate.setPath(templateFolder + File.separator + templateName + ".qcow2"); newTemplate.setPath(templateFolder + File.separator + templateName + ".qcow2");
newTemplate.setSize(info.virtualSize);
newTemplate.setFormat(ImageFormat.QCOW2);
return new CopyCmdAnswer(newTemplate); return new CopyCmdAnswer(newTemplate);
} catch (Exception e) { } catch (Exception e) {
s_logger.debug("Failed to create template from volume: " + e.toString()); s_logger.debug("Failed to create template from volume: " + e.toString());
@ -902,4 +904,8 @@ public class KVMStorageProcessor implements StorageProcessor {
} }
} }
@Override
public Answer deleteSnapshot(DeleteCommand cmd) {
return new Answer(cmd);
}
} }

View File

@ -69,6 +69,7 @@ import com.cloud.hypervisor.vmware.resource.VmwareResource;
import com.cloud.hypervisor.vmware.util.VmwareContext; import com.cloud.hypervisor.vmware.util.VmwareContext;
import com.cloud.hypervisor.vmware.util.VmwareHelper; import com.cloud.hypervisor.vmware.util.VmwareHelper;
import com.cloud.serializer.GsonHelper; import com.cloud.serializer.GsonHelper;
import com.cloud.storage.DataStoreRole;
import com.cloud.storage.JavaStorageLayer; import com.cloud.storage.JavaStorageLayer;
import com.cloud.storage.StorageLayer; import com.cloud.storage.StorageLayer;
import com.cloud.storage.Volume; import com.cloud.storage.Volume;
@ -579,6 +580,7 @@ public class VmwareStorageProcessor implements StorageProcessor {
TemplateObjectTO newTemplate = new TemplateObjectTO(); TemplateObjectTO newTemplate = new TemplateObjectTO();
newTemplate.setPath(template.getName()); newTemplate.setPath(template.getName());
newTemplate.setFormat(ImageFormat.OVA); newTemplate.setFormat(ImageFormat.OVA);
newTemplate.setSize(result.third());
return new CopyCmdAnswer(newTemplate); return new CopyCmdAnswer(newTemplate);
} catch (Throwable e) { } catch (Throwable e) {
@ -1272,4 +1274,15 @@ public class VmwareStorageProcessor implements StorageProcessor {
} }
return new CopyCmdAnswer(details); return new CopyCmdAnswer(details);
} }
@Override
public Answer deleteSnapshot(DeleteCommand cmd) {
SnapshotObjectTO snapshot = (SnapshotObjectTO)cmd.getData();
DataStoreTO store = snapshot.getDataStore();
if (store.getRole() == DataStoreRole.Primary) {
return new Answer(cmd);
} else {
return new Answer(cmd, false, "unsupported command");
}
}
} }

View File

@ -66,6 +66,7 @@ import com.cloud.agent.api.to.StorageFilerTO;
import com.cloud.agent.api.to.SwiftTO; import com.cloud.agent.api.to.SwiftTO;
import com.cloud.exception.InternalErrorException; import com.cloud.exception.InternalErrorException;
import com.cloud.hypervisor.xen.resource.CitrixResourceBase.SRType; import com.cloud.hypervisor.xen.resource.CitrixResourceBase.SRType;
import com.cloud.storage.DataStoreRole;
import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.Storage.StoragePoolType; import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.storage.resource.StorageProcessor; import com.cloud.storage.resource.StorageProcessor;
@ -1389,6 +1390,7 @@ public class XenServerStorageProcessor implements StorageProcessor {
TemplateObjectTO newTemplate = new TemplateObjectTO(); TemplateObjectTO newTemplate = new TemplateObjectTO();
newTemplate.setPath(installPath); newTemplate.setPath(installPath);
newTemplate.setFormat(ImageFormat.VHD); newTemplate.setFormat(ImageFormat.VHD);
newTemplate.setSize(virtualSize);
CopyCmdAnswer answer = new CopyCmdAnswer(newTemplate); CopyCmdAnswer answer = new CopyCmdAnswer(newTemplate);
return answer; return answer;
} catch (Exception e) { } catch (Exception e) {
@ -1470,4 +1472,32 @@ public class XenServerStorageProcessor implements StorageProcessor {
// In all cases return something. // In all cases return something.
return new CopyCmdAnswer(details); return new CopyCmdAnswer(details);
} }
@Override
public Answer deleteSnapshot(DeleteCommand cmd) {
SnapshotObjectTO snapshot = (SnapshotObjectTO)cmd.getData();
DataStoreTO store = snapshot.getDataStore();
if (store.getRole() == DataStoreRole.Primary) {
Connection conn = this.hypervisorResource.getConnection();
VDI snapshotVdi = getVDIbyUuid(conn, snapshot.getPath());
if (snapshotVdi == null) {
return new Answer(null);
}
String errMsg = null;
try {
this.deleteVDI(conn, snapshotVdi);
} catch (BadServerResponse e) {
s_logger.debug("delete snapshot failed:" + e.toString());
errMsg = e.toString();
} catch (XenAPIException e) {
s_logger.debug("delete snapshot failed:" + e.toString());
errMsg = e.toString();
} catch (XmlRpcException e) {
s_logger.debug("delete snapshot failed:" + e.toString());
errMsg = e.toString();
}
return new Answer(cmd, false, errMsg);
}
return new Answer(cmd, false, "unsupported storage type");
}
} }

View File

@ -48,6 +48,7 @@ import org.apache.cloudstack.storage.snapshot.SnapshotObject;
import com.cloud.agent.AgentManager; import com.cloud.agent.AgentManager;
import com.cloud.agent.api.Answer; import com.cloud.agent.api.Answer;
import com.cloud.agent.api.DeleteSnapshotBackupCommand;
import com.cloud.agent.api.storage.DeleteTemplateCommand; import com.cloud.agent.api.storage.DeleteTemplateCommand;
import com.cloud.agent.api.storage.DeleteVolumeCommand; import com.cloud.agent.api.storage.DeleteVolumeCommand;
import com.cloud.agent.api.storage.DownloadAnswer; import com.cloud.agent.api.storage.DownloadAnswer;
@ -101,8 +102,6 @@ public class CloudStackImageStoreDriverImpl implements ImageStoreDriver {
@Inject @Inject
private S3Manager _s3Mgr; private S3Manager _s3Mgr;
@Inject AccountDao _accountDao; @Inject AccountDao _accountDao;
@Inject UserVmDao _userVmDao;
@Inject UserVmJoinDao _userVmJoinDao;
@Inject @Inject
SecondaryStorageVmManager _ssvmMgr; SecondaryStorageVmManager _ssvmMgr;
@Inject @Inject
@ -280,46 +279,37 @@ public class CloudStackImageStoreDriverImpl implements ImageStoreDriver {
UsageEventUtils.publishUsageEvent(eventType, account.getId(), sZoneId, templateId, null, null, null); UsageEventUtils.publishUsageEvent(eventType, account.getId(), sZoneId, templateId, null, null, null);
List<UserVmJoinVO> userVmUsingIso = _userVmJoinDao.listActiveByIsoId(templateId); // get installpath of this template on image store
// check if there is any VM using this ISO. TemplateDataStoreVO tmplStore = _templateStoreDao.findByStoreTemplate(storeId, templateId);
if (userVmUsingIso == null || userVmUsingIso.isEmpty()) { String installPath = tmplStore.getInstallPath();
// get installpath of this template on image store if (installPath != null) {
TemplateDataStoreVO tmplStore = _templateStoreDao.findByStoreTemplate(storeId, templateId); DeleteTemplateCommand cmd = new DeleteTemplateCommand(store.getTO(), installPath, template.getId(), template.getAccountId());
String installPath = tmplStore.getInstallPath(); EndPoint ep = _epSelector.select(templateObj);
if (installPath != null) { Answer answer = ep.sendMessage(cmd);
DeleteTemplateCommand cmd = new DeleteTemplateCommand(store.getTO(), installPath, template.getId(), template.getAccountId());
EndPoint ep = _epSelector.select(templateObj);
Answer answer = ep.sendMessage(cmd);
if (answer == null || !answer.getResult()) { if (answer == null || !answer.getResult()) {
s_logger.debug("Failed to deleted template at store: " + store.getName()); s_logger.debug("Failed to deleted template at store: " + store.getName());
CommandResult result = new CommandResult(); CommandResult result = new CommandResult();
result.setSuccess(false); result.setSuccess(false);
result.setResult("Delete template failed"); result.setResult("Delete template failed");
callback.complete(result); callback.complete(result);
} else { } else {
s_logger.debug("Deleted template at: " + installPath); s_logger.debug("Deleted template at: " + installPath);
CommandResult result = new CommandResult(); CommandResult result = new CommandResult();
result.setSuccess(true); result.setSuccess(true);
callback.complete(result); callback.complete(result);
} }
List<VMTemplateZoneVO> templateZones = templateZoneDao.listByZoneTemplate(sZoneId, templateId); List<VMTemplateZoneVO> templateZones = templateZoneDao.listByZoneTemplate(sZoneId, templateId);
if (templateZones != null) { if (templateZones != null) {
for (VMTemplateZoneVO templateZone : templateZones) { for (VMTemplateZoneVO templateZone : templateZones) {
templateZoneDao.remove(templateZone.getId()); templateZoneDao.remove(templateZone.getId());
} }
} }
}
} else{
// cannot delete iso due to some VMs are using this
s_logger.debug("Cannot delete iso since some user vms are referencing it");
CommandResult result = new CommandResult();
result.setResult("Cannot delete iso since some user vms are referencing it");
callback.complete(result);
} }
} }
private void deleteSnapshot(DataObject data, AsyncCompletionCallback<CommandResult> callback) { private void deleteSnapshot(DataObject data, AsyncCompletionCallback<CommandResult> callback) {
@ -336,29 +326,17 @@ public class CloudStackImageStoreDriverImpl implements ImageStoreDriver {
} }
try { try {
/*String secondaryStoragePoolUrl = secStore.getUri(); String secondaryStoragePoolUrl = secStore.getUri();
Long dcId = snapshot.getDataCenterId();
Long accountId = snapshot.getAccountId();
Long volumeId = snapshot.getVolumeId();
String backupOfSnapshot = snapshotObj;
if (backupOfSnapshot == null) {
callback.complete(result);
return;
}
DeleteSnapshotBackupCommand cmd = new DeleteSnapshotBackupCommand( DeleteSnapshotBackupCommand cmd = new DeleteSnapshotBackupCommand(
secStore.getTO(), secondaryStoragePoolUrl, dcId, accountId, volumeId, secStore.getTO(), secondaryStoragePoolUrl, null, null, null,
backupOfSnapshot, false); snapshotObj.getPath(), false);
EndPoint ep = _epSelector.select(secStore); EndPoint ep = _epSelector.select(secStore);
Answer answer = ep.sendMessage(cmd); Answer answer = ep.sendMessage(cmd);
if ((answer != null) && answer.getResult()) { if (answer != null && !answer.getResult()) {
snapshot.setBackupSnapshotId(null);
snapshotDao.update(snapshotObj.getId(), snapshot);
} else if (answer != null) {
result.setResult(answer.getDetails()); result.setResult(answer.getDetails());
}*/ }
} catch (Exception e) { } catch (Exception e) {
s_logger.debug("failed to delete snapshot: " + snapshotObj.getId() + ": " + e.toString()); s_logger.debug("failed to delete snapshot: " + snapshotObj.getId() + ": " + e.toString());
result.setResult(e.toString()); result.setResult(e.toString());

View File

@ -88,6 +88,8 @@ import com.cloud.agent.api.storage.DestroyCommand;
import com.cloud.agent.api.to.DataTO; import com.cloud.agent.api.to.DataTO;
import com.cloud.agent.api.to.DiskTO; import com.cloud.agent.api.to.DiskTO;
import com.cloud.api.ApiDBUtils; import com.cloud.api.ApiDBUtils;
import com.cloud.api.query.dao.UserVmJoinDao;
import com.cloud.api.query.vo.UserVmJoinVO;
import com.cloud.async.AsyncJobManager; import com.cloud.async.AsyncJobManager;
import com.cloud.async.AsyncJobVO; import com.cloud.async.AsyncJobVO;
import com.cloud.configuration.Config; import com.cloud.configuration.Config;
@ -253,6 +255,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
@Inject VolumeManager _volumeMgr; @Inject VolumeManager _volumeMgr;
@Inject ImageStoreDao _imageStoreDao; @Inject ImageStoreDao _imageStoreDao;
@Inject EndPointSelector _epSelector; @Inject EndPointSelector _epSelector;
@Inject UserVmJoinDao _userVmJoinDao;
@Inject @Inject
ConfigurationServer _configServer; ConfigurationServer _configServer;
@ -1122,6 +1125,12 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
if (template.getFormat() != ImageFormat.ISO) { if (template.getFormat() != ImageFormat.ISO) {
throw new InvalidParameterValueException("Please specify a valid iso."); throw new InvalidParameterValueException("Please specify a valid iso.");
} }
List<UserVmJoinVO> userVmUsingIso = _userVmJoinDao.listActiveByIsoId(templateId);
// check if there is any VM using this ISO.
if (!userVmUsingIso.isEmpty()) {
throw new InvalidParameterValueException("Unable to delete iso, as it's used by other vms");
}
if (zoneId != null && (this._dataStoreMgr.getImageStore(zoneId) == null)) { if (zoneId != null && (this._dataStoreMgr.getImageStore(zoneId) == null)) {
throw new InvalidParameterValueException("Failed to find a secondary storage store in the specified zone."); throw new InvalidParameterValueException("Failed to find a secondary storage store in the specified zone.");

View File

@ -45,6 +45,7 @@ import javax.naming.ConfigurationException;
import org.apache.cloudstack.storage.command.CopyCmdAnswer; import org.apache.cloudstack.storage.command.CopyCmdAnswer;
import org.apache.cloudstack.storage.command.CopyCommand; import org.apache.cloudstack.storage.command.CopyCommand;
import org.apache.cloudstack.storage.command.DeleteCommand;
import org.apache.cloudstack.storage.command.DownloadCommand; import org.apache.cloudstack.storage.command.DownloadCommand;
import org.apache.cloudstack.storage.command.DownloadProgressCommand; import org.apache.cloudstack.storage.command.DownloadProgressCommand;
import org.apache.cloudstack.storage.template.DownloadManager; import org.apache.cloudstack.storage.template.DownloadManager;
@ -161,7 +162,7 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
protected String _parent = "/mnt/SecStorage"; protected String _parent = "/mnt/SecStorage";
final private String _tmpltDir = "/var/cloudstack/template"; final private String _tmpltDir = "/var/cloudstack/template";
final private String _tmpltpp = "template.properties"; final private String _tmpltpp = "template.properties";
private String createTemplateFromSnapshotXenScript; protected String createTemplateFromSnapshotXenScript;
@Override @Override
public void disconnected() { public void disconnected() {
@ -223,7 +224,7 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
return Answer.createUnsupportedCommandAnswer(cmd); return Answer.createUnsupportedCommandAnswer(cmd);
} }
} }
protected Answer copyFromS3ToNfs(CopyCommand cmd, DataTO srcData, S3TO s3, DataTO destData, NfsTO destImageStore) { protected Answer copyFromS3ToNfs(CopyCommand cmd, DataTO srcData, S3TO s3, DataTO destData, NfsTO destImageStore) {
final String storagePath = destImageStore.getUrl(); final String storagePath = destImageStore.getUrl();
final String destPath = destData.getPath(); final String destPath = destData.getPath();
@ -353,7 +354,11 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
command.add("-s", snapshotName); command.add("-s", snapshotName);
command.add("-n", templateName); command.add("-n", templateName);
command.add("-t", destPath); command.add("-t", destPath);
command.execute(); String result = command.execute();
if (result != null && !result.equalsIgnoreCase("")) {
return new CopyCmdAnswer(result);
}
Map<String, Object> params = new HashMap<String, Object>(); Map<String, Object> params = new HashMap<String, Object>();
params.put(StorageLayer.InstanceConfigKey, _storage); params.put(StorageLayer.InstanceConfigKey, _storage);
@ -1109,9 +1114,14 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
private String deleteSnapshotBackupFromLocalFileSystem(final String secondaryStorageUrl, final Long accountId, final Long volumeId, private String deleteSnapshotBackupFromLocalFileSystem(final String secondaryStorageUrl, final Long accountId, final Long volumeId,
final String name, final Boolean deleteAllFlag) { final String name, final Boolean deleteAllFlag) {
String lPath = null;
final String lPath = determineSnapshotLocalDirectory(secondaryStorageUrl, accountId, volumeId) + File.pathSeparator int index = name.lastIndexOf(File.separator);
+ (deleteAllFlag ? "*" : "*" + name + "*"); String snapshotPath = name.substring(0, index);
if (deleteAllFlag) {
lPath = this.getRootDir(secondaryStorageUrl) + File.separator + snapshotPath + File.separator + "*";
} else {
lPath = this.getRootDir(secondaryStorageUrl) + File.separator + name + "*";
}
final String result = deleteLocalFile(lPath); final String result = deleteLocalFile(lPath);