Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

import javax.inject.Inject;

import com.cloud.storage.dao.SnapshotDetailsVO;
import org.apache.cloudstack.engine.subsystem.api.storage.ChapInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult;
Expand Down Expand Up @@ -110,7 +111,6 @@
import com.cloud.storage.VolumeVO;
import com.cloud.storage.dao.SnapshotDao;
import com.cloud.storage.dao.SnapshotDetailsDao;
import com.cloud.storage.dao.SnapshotDetailsVO;
import com.cloud.storage.dao.StoragePoolHostDao;
import com.cloud.storage.dao.VMTemplateDetailsDao;
import com.cloud.storage.dao.VolumeDao;
Expand Down Expand Up @@ -640,57 +640,16 @@ public void copyAsync(DataObject srcData, DataObject dstData, AsyncCompletionCal
SnapshotDataStoreVO snap = getSnapshotImageStoreRef(sinfo.getId(), vinfo.getDataCenterId());
SnapshotDetailsVO snapshotDetail = snapshotDetailsDao.findDetail(sinfo.getId(), StorPoolUtil.SP_DELAY_DELETE);
if (snapshotDetail != null) {
err = String.format("Could not create volume from snapshot due to: %s", resp.getError());
err = String.format("Could not create volume from snapshot due to: %s. The snapshot was created with the delayDelete option.", resp.getError());
} else if (snap != null && StorPoolStorageAdaptor.getVolumeNameFromPath(snap.getInstallPath(), false) == null) {
resp = StorPoolUtil.volumeCreate(srcData.getUuid(), null, size, null, "no", "snapshot", sinfo.getBaseVolume().getMaxIops(), conn);
if (resp.getError() == null) {
VolumeObjectTO dstTO = (VolumeObjectTO) dstData.getTO();
dstTO.setSize(size);
dstTO.setPath(StorPoolUtil.devPath(StorPoolUtil.getNameFromResponse(resp, false)));
cmd = new StorPoolDownloadTemplateCommand(srcData.getTO(), dstTO, StorPoolHelper.getTimeout(StorPoolHelper.PrimaryStorageDownloadWait, configDao), VirtualMachineManager.ExecuteInSequence.value(), "volume");

EndPoint ep = selector.select(srcData, dstData);
if (ep == null) {
err = "No remote endpoint to send command, check if host or ssvm is down?";
} else {
answer = ep.sendMessage(cmd);
}

if (answer != null && answer.getResult()) {
SpApiResponse resp2 = StorPoolUtil.volumeFreeze(StorPoolUtil.getNameFromResponse(resp, true), conn);
if (resp2.getError() != null) {
err = String.format("Could not freeze Storpool volume %s. Error: %s", srcData.getUuid(), resp2.getError());
} else {
String name = StorPoolUtil.getNameFromResponse(resp, false);
SnapshotDetailsVO snapshotDetails = snapshotDetailsDao.findDetail(sinfo.getId(), sinfo.getUuid());
if (snapshotDetails != null) {
StorPoolHelper.updateSnapshotDetailsValue(snapshotDetails.getId(), StorPoolUtil.devPath(name), "snapshot");
}else {
StorPoolHelper.addSnapshotDetails(sinfo.getId(), sinfo.getUuid(), StorPoolUtil.devPath(name), snapshotDetailsDao);
}
resp = StorPoolUtil.volumeCreate(volumeName, StorPoolUtil.getNameFromResponse(resp, true), size, null, null, "volume", sinfo.getBaseVolume().getMaxIops(), conn);
if (resp.getError() == null) {
updateStoragePool(dstData.getDataStore().getId(), size);

VolumeObjectTO to = (VolumeObjectTO) dstData.getTO();
to.setPath(StorPoolUtil.devPath(StorPoolUtil.getNameFromResponse(resp, false)));
to.setSize(size);
// successfully downloaded snapshot to primary storage
answer = new CopyCmdAnswer(to);
StorPoolUtil.spLog("Created volume=%s with uuid=%s from snapshot=%s with uuid=%s", name, to.getUuid(), snapshotName, sinfo.getUuid());

} else {
err = String.format("Could not create Storpool volume %s from snapshot %s. Error: %s", volumeName, snapshotName, resp.getError());
}
}
} else {
err = answer != null ? answer.getDetails() : "Unknown error while downloading template. Null answer returned.";
}
SpApiResponse emptyVolumeCreateResp = StorPoolUtil.volumeCreate(volumeName, null, size, null, null, "volume", null, conn);
if (emptyVolumeCreateResp.getError() == null) {
answer = createVolumeFromSnapshot(srcData, dstData, size, emptyVolumeCreateResp);
} else {
err = String.format("Could not create Storpool volume %s from snapshot %s. Error: %s", volumeName, snapshotName, resp.getError());
answer = new Answer(cmd, false, String.format("Could not create Storpool volume %s from snapshot %s. Error: %s", volumeName, snapshotName, emptyVolumeCreateResp.getError()));
}
} else {
err = String.format("The snapshot %s does not exists neither on primary, neither on secondary storage. Cannot create volume from snapshot", snapshotName);
answer = new Answer(cmd, false, String.format("The snapshot %s does not exists neither on primary, neither on secondary storage. Cannot create volume from snapshot", snapshotName));
}
} else {
err = String.format("Could not create Storpool volume %s from snapshot %s. Error: %s", volumeName, snapshotName, resp.getError());
Expand Down Expand Up @@ -791,22 +750,17 @@ public void copyAsync(DataObject srcData, DataObject dstData, AsyncCompletionCal
err = String.format("Could not create Storpool volume for CS template %s. Error: %s", name, resp.getError());
} else {
String volumeNameToSnapshot = StorPoolUtil.getNameFromResponse(resp, true);
SpApiResponse resp2 = StorPoolUtil.volumeFreeze(volumeNameToSnapshot, conn);
if (resp2.getError() != null) {
err = String.format("Could not freeze Storpool volume %s. Error: %s", name, resp2.getError());
} else {
StorPoolUtil.spLog("Storpool snapshot [%s] for a template exists. Creating template on Storpool with name [%s]", tinfo.getUuid(), name);
TemplateObjectTO dstTO = (TemplateObjectTO) dstData.getTO();
dstTO.setPath(StorPoolUtil.devPath(StorPoolUtil.getNameFromResponse(resp, false)));
dstTO.setSize(size);
answer = new CopyCmdAnswer(dstTO);
}
TemplateObjectTO dstTO = (TemplateObjectTO) dstData.getTO();

answer = createVolumeSnapshot(cmd, size, conn, volumeNameToSnapshot, dstTO);
StorPoolUtil.volumeDelete(volumeNameToSnapshot, conn);
}
} else {
resp = StorPoolUtil.volumeCreate(name, null, size, null, "no", "template", null, conn);
if (resp.getError() != null) {
err = String.format("Could not create Storpool volume for CS template %s. Error: %s", name, resp.getError());
} else {
String volName = StorPoolUtil.getNameFromResponse(resp, true);
TemplateObjectTO dstTO = (TemplateObjectTO)dstData.getTO();
dstTO.setPath(StorPoolUtil.devPath(StorPoolUtil.getNameFromResponse(resp, false)));
dstTO.setSize(size);
Expand All @@ -822,19 +776,12 @@ public void copyAsync(DataObject srcData, DataObject dstData, AsyncCompletionCal

if (answer != null && answer.getResult()) {
// successfully downloaded template to primary storage
SpApiResponse resp2 = StorPoolUtil.volumeFreeze(StorPoolUtil.getNameFromResponse(resp, true), conn);
if (resp2.getError() != null) {
err = String.format("Could not freeze Storpool volume %s. Error: %s", name, resp2.getError());
}
answer = createVolumeSnapshot(cmd, size, conn, volName, dstTO);
} else {
err = answer != null ? answer.getDetails() : "Unknown error while downloading template. Null answer returned.";
}
}
}
if (err != null) {
resp = StorPoolUtil.volumeDelete(StorPoolUtil.getNameFromResponse(resp, true), conn);
if (resp.getError() != null) {
logger.warn(String.format("Could not clean-up Storpool volume %s. Error: %s", name, resp.getError()));

StorPoolUtil.volumeDelete(volName, conn);
}
}
} else if (srcType == DataObjectType.TEMPLATE && dstType == DataObjectType.VOLUME) {
Expand Down Expand Up @@ -1027,6 +974,42 @@ public void copyAsync(DataObject srcData, DataObject dstData, AsyncCompletionCal
callback.complete(res);
}

private Answer createVolumeSnapshot(StorageSubSystemCommand cmd, Long size, SpConnectionDesc conn,
String volName, TemplateObjectTO dstTO) {
Answer answer;
SpApiResponse resp = StorPoolUtil.volumeSnapshot(volName, dstTO.getUuid(), null, "template", null, conn);
if (resp.getError() != null) {
answer = new Answer(cmd, false, String.format("Could not snapshot volume. Error: %s", resp.getError()));
} else {
dstTO.setPath(StorPoolUtil.devPath(
StorPoolUtil.getSnapshotNameFromResponse(resp, false, StorPoolUtil.GLOBAL_ID)));
dstTO.setSize(size);
answer = new CopyCmdAnswer(dstTO);
}
return answer;
}

private Answer createVolumeFromSnapshot(DataObject srcData, DataObject dstData, final Long size,
SpApiResponse emptyVolumeCreateResp) {
Answer answer;
String name = StorPoolUtil.getNameFromResponse(emptyVolumeCreateResp, false);
VolumeObjectTO dstTO = (VolumeObjectTO) dstData.getTO();
dstTO.setSize(size);
dstTO.setPath(StorPoolUtil.devPath(name));
StorageSubSystemCommand cmd = new StorPoolDownloadTemplateCommand(srcData.getTO(), dstTO, StorPoolHelper.getTimeout(StorPoolHelper.PrimaryStorageDownloadWait, configDao), VirtualMachineManager.ExecuteInSequence.value(), "volume");

EndPoint ep = selector.select(srcData, dstData);
if (ep == null) {
answer = new Answer(cmd, false, "\"No remote endpoint to send command, check if host or ssvm is down?\"");
} else {
answer = ep.sendMessage(cmd);
}
if (answer == null || !answer.getResult()) {
answer = new Answer(cmd, false, answer != null ? answer.getDetails() : "Unknown error while downloading template. Null answer returned.");
}
return answer;
}

private void updateVolumePoolType(VolumeInfo vinfo) {
VolumeVO volumeVO = volumeDao.findById(vinfo.getId());
volumeVO.setPoolType(StoragePoolType.StorPool);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,12 @@ public static SpApiResponse volumeRevert(final String name, final String snapsho
return POST("MultiCluster/VolumeRevert/" + name, json, conn);
}

/**
* @deprecated Use volumeSnapshot instead
* @param volumeName
* @param conn
* @return
*/
public static SpApiResponse volumeFreeze(final String volumeName, SpConnectionDesc conn) {
return POST("MultiCluster/VolumeFreeze/" + volumeName, null, conn);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,24 +219,23 @@ public void copyAsync(DataObject srcData, DataObject destData, Host destHost,
} else {
answer = (CopyCmdAnswer) ep2.sendMessage(backupSnapshot);
if (answer != null && answer.getResult()) {
SpApiResponse resSnapshot = StorPoolUtil.volumeFreeze(volumeName, conn);
SpApiResponse resSnapshot = StorPoolUtil.volumeSnapshot(volumeName, template.getUuid(), null, "template", null, conn);
if (resSnapshot.getError() != null) {
logger.debug("Could not snapshot volume [id: {}, name: {}]", snapshot.getId(), snapshot.getName());
StorPoolUtil.spLog("Volume freeze failed with error=%s", resSnapshot.getError().getDescr());
logger.debug(String.format("Could not snapshot volume with ID={}", snapshot.getId()));
StorPoolUtil.spLog("VolumeSnapshot failed with error=%s", resSnapshot.getError().getDescr());
err = resSnapshot.getError().getDescr();
StorPoolUtil.volumeDelete(volumeName, conn);
} else {
String templPath = StorPoolUtil.devPath(
StorPoolUtil.getSnapshotNameFromResponse(resSnapshot, false, StorPoolUtil.GLOBAL_ID));
StorPoolHelper.updateVmStoreTemplate(template.getId(), template.getDataStore().getRole(),
StorPoolUtil.devPath(StorPoolUtil.getNameFromResponse(res, false)), _templStoreDao);
templPath, _templStoreDao);
}
} else {
err = "Could not copy template to secondary " + answer.getResult();
StorPoolUtil.volumeDelete(StorPoolUtil.getNameFromResponse(res, true), conn);
}
}
} catch (CloudRuntimeException e) {
err = e.getMessage();
}
StorPoolUtil.volumeDelete(volumeName, conn);
}
_vmTemplateDetailsDao.persist(new VMTemplateDetailVO(template.getId(), StorPoolUtil.SP_STORAGE_POOL_ID,
String.valueOf(vInfo.getDataStore().getId()), false));
Expand Down