diff --git a/engine/storage/image/src/main/java/org/apache/cloudstack/storage/image/SecondaryStorageServiceImpl.java b/engine/storage/image/src/main/java/org/apache/cloudstack/storage/image/SecondaryStorageServiceImpl.java index b73dc87df28..523c240c0ee 100644 --- a/engine/storage/image/src/main/java/org/apache/cloudstack/storage/image/SecondaryStorageServiceImpl.java +++ b/engine/storage/image/src/main/java/org/apache/cloudstack/storage/image/SecondaryStorageServiceImpl.java @@ -37,7 +37,6 @@ import org.apache.cloudstack.framework.async.AsyncCallFuture; import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher; import org.apache.cloudstack.framework.async.AsyncCompletionCallback; import org.apache.cloudstack.framework.async.AsyncRpcContext; -import org.apache.cloudstack.storage.command.CopyCmdAnswer; import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao; import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO; import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao; @@ -47,6 +46,7 @@ import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreDao; import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreVO; import org.apache.log4j.Logger; +import com.cloud.agent.api.Answer; import com.cloud.secstorage.CommandExecLogDao; import com.cloud.storage.DataStoreRole; import com.cloud.utils.Pair; @@ -91,6 +91,7 @@ public class SecondaryStorageServiceImpl implements SecondaryStorageService { if (srcDataObject instanceof SnapshotInfo && snapshotChain != null && snapshotChain.containsKey(srcDataObject)) { List parentSnapshotPaths = new ArrayList<>(); for (SnapshotInfo snapshotInfo : snapshotChain.get(srcDataObject).first()) { + destDataObject = null; if (!parentSnapshotPaths.isEmpty() && parentSnapshotPaths.contains(snapshotInfo.getPath())) { parentSnapshotPaths.add(snapshotInfo.getPath()); SnapshotDataStoreVO snapshotStore = snapshotStoreDao.findByStoreSnapshot(DataStoreRole.Image, srcDatastore.getId(), snapshotInfo.getSnapshotId()); @@ -135,6 +136,7 @@ public class SecondaryStorageServiceImpl implements SecondaryStorageService { } catch (Exception e) { s_logger.debug("Failed to copy Data", e); if (destDataObject != null) { + s_logger.info("Deleting data on destination store: " + destDataObject.getDataStore().getName()); destDataObject.getDataStore().delete(destDataObject); } if (!(srcDataObject instanceof VolumeInfo)) { @@ -164,7 +166,7 @@ public class SecondaryStorageServiceImpl implements SecondaryStorageService { CopyCommandResult result = callback.getResult(); AsyncCallFuture future = context.future; DataObjectResult res = new DataObjectResult(srcData); - CopyCmdAnswer answer = (CopyCmdAnswer) result.getAnswer(); + Answer answer = result.getAnswer(); try { if (!answer.getResult()) { s_logger.warn("Migration failed for "+srcData.getUuid()); diff --git a/engine/storage/src/main/java/org/apache/cloudstack/storage/image/BaseImageStoreDriverImpl.java b/engine/storage/src/main/java/org/apache/cloudstack/storage/image/BaseImageStoreDriverImpl.java index 37a7985ce6f..8eab4b24f69 100644 --- a/engine/storage/src/main/java/org/apache/cloudstack/storage/image/BaseImageStoreDriverImpl.java +++ b/engine/storage/src/main/java/org/apache/cloudstack/storage/image/BaseImageStoreDriverImpl.java @@ -32,6 +32,8 @@ import java.util.stream.Collectors; import javax.inject.Inject; +import com.cloud.agent.api.to.NfsTO; +import com.cloud.storage.DataStoreRole; import com.cloud.storage.Upload; import org.apache.cloudstack.storage.image.deployasis.DeployAsIsHelper; import org.apache.log4j.Logger; @@ -396,6 +398,15 @@ public abstract class BaseImageStoreDriverImpl implements ImageStoreDriver { @Override public boolean canCopy(DataObject srcData, DataObject destData) { + DataStore srcStore = srcData.getDataStore(); + DataStore destStore = destData.getDataStore(); + if ((srcData.getDataStore().getTO() instanceof NfsTO && destData.getDataStore().getTO() instanceof NfsTO) && + (srcStore.getRole() == DataStoreRole.Image && destStore.getRole() == DataStoreRole.Image) && + ((srcData.getType() == DataObjectType.TEMPLATE && destData.getType() == DataObjectType.TEMPLATE) || + (srcData.getType() == DataObjectType.SNAPSHOT && destData.getType() == DataObjectType.SNAPSHOT) || + (srcData.getType() == DataObjectType.VOLUME && destData.getType() == DataObjectType.VOLUME))) { + return true; + } return false; } diff --git a/engine/storage/volume/src/main/java/org/apache/cloudstack/storage/volume/VolumeObject.java b/engine/storage/volume/src/main/java/org/apache/cloudstack/storage/volume/VolumeObject.java index da759f84a7c..9750fb1b84f 100644 --- a/engine/storage/volume/src/main/java/org/apache/cloudstack/storage/volume/VolumeObject.java +++ b/engine/storage/volume/src/main/java/org/apache/cloudstack/storage/volume/VolumeObject.java @@ -416,6 +416,8 @@ public class VolumeObject implements VolumeInfo { volEvent = Volume.Event.UploadRequested; } else if (event == ObjectInDataStoreStateMachine.Event.MigrationRequested) { volEvent = Volume.Event.CopyRequested; + } else if (event == ObjectInDataStoreStateMachine.Event.MigrateDataRequested) { + return; } } else { if (event == ObjectInDataStoreStateMachine.Event.CreateRequested || event == ObjectInDataStoreStateMachine.Event.CreateOnlyRequested) { diff --git a/services/secondary-storage/server/src/main/java/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java b/services/secondary-storage/server/src/main/java/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java index 03eba4a6b84..6f67de50122 100644 --- a/services/secondary-storage/server/src/main/java/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java +++ b/services/secondary-storage/server/src/main/java/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java @@ -46,6 +46,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -1313,6 +1314,8 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S srcDir = new File(srcFile.getParent()); } else if (!srcFile.isDirectory()) { srcDir = new File(srcFile.getParent()); + } else if (srcFile.isDirectory() && Arrays.stream(srcData.getPath().split(File.separator)).count() == 4) { + destFile = new File(destFile.getPath(), srcFile.getName()); } File destDir = null; if (destFile.isFile()) {