diff --git a/header/src/main/java/org/zstack/header/storage/primary/ConvertVolumeEncryptionOnPrimaryStorageMsg.java b/header/src/main/java/org/zstack/header/storage/primary/ConvertVolumeEncryptionOnPrimaryStorageMsg.java index 2c36e56e9eb..6554cf85d9d 100644 --- a/header/src/main/java/org/zstack/header/storage/primary/ConvertVolumeEncryptionOnPrimaryStorageMsg.java +++ b/header/src/main/java/org/zstack/header/storage/primary/ConvertVolumeEncryptionOnPrimaryStorageMsg.java @@ -54,7 +54,6 @@ public static class VolumeEncryptionConversionItem implements Serializable { private String resourceUuid; private String resourceType; private String sourceInstallPath; - private String sourceTrashInstallPath; private String targetInstallPath; private String targetBackingInstallPath; @@ -82,14 +81,6 @@ public void setSourceInstallPath(String sourceInstallPath) { this.sourceInstallPath = sourceInstallPath; } - public String getSourceTrashInstallPath() { - return sourceTrashInstallPath; - } - - public void setSourceTrashInstallPath(String sourceTrashInstallPath) { - this.sourceTrashInstallPath = sourceTrashInstallPath; - } - public String getTargetInstallPath() { return targetInstallPath; } diff --git a/plugin/ceph/src/main/java/org/zstack/storage/ceph/primary/CephPrimaryStorageBase.java b/plugin/ceph/src/main/java/org/zstack/storage/ceph/primary/CephPrimaryStorageBase.java index e6eb650e1a4..08a6a0a9a59 100755 --- a/plugin/ceph/src/main/java/org/zstack/storage/ceph/primary/CephPrimaryStorageBase.java +++ b/plugin/ceph/src/main/java/org/zstack/storage/ceph/primary/CephPrimaryStorageBase.java @@ -459,7 +459,6 @@ public static class KVMHostLuksConvertCmd implements Serializable { public String encryptedDek; public String installPath; public String targetInstallPath; - public String sourceTrashInstallPath; public boolean targetEncrypted; public Long virtualSize; } @@ -490,19 +489,6 @@ public static class KVMHostLuksRsp extends KVMAgentCommands.AgentResponse { public Long actualSize; } - public static class ReplaceLuksRbdCmd extends AgentCommand { - public String installPath; - public String targetInstallPath; - public String temporaryInstallPath; - public String sourceTrashInstallPath; - public boolean deleteSourceTrash; - } - - public static class ReplaceLuksRbdRsp extends AgentResponse { - public Long size; - public Long actualSize; - } - public static class SwapInPlaceLuksRbdCmd extends AgentCommand { public String installPath; public String temporaryInstallPath; @@ -1454,7 +1440,6 @@ public int compareTo(SnapInfo snapInfo) { public static final String KVM_HOST_LUKS_ENCRYPT_IN_PLACE_PATH = "/ceph/primarystorage/kvmhost/encryptinplace"; public static final String KVM_HOST_LUKS_RESIZE_PATH = "/ceph/primarystorage/kvmhost/luksresize"; public static final String KVM_HOST_LUKS_CONVERT_PATH = "/ceph/primarystorage/kvmhost/luksconvert"; - public static final String LUKS_REPLACE_VOLUME_PATH = "/ceph/primarystorage/volume/luksreplace"; public static final String LUKS_SWAP_IN_PLACE_PATH = "/ceph/primarystorage/volume/luksswapinplace"; public static final String KVM_HOST_IMAGESTORE_ENCRYPTED_DOWNLOAD_PATH = "/ceph/primarystorage/kvmhost/imagestore/encrypteddownload"; public static final String FLATTEN_PATH = "/ceph/primarystorage/volume/flatten"; @@ -3629,12 +3614,38 @@ protected void handle(ConvertVolumeEncryptionOnPrimaryStorageMsg msg) { KVMHostLuksConvertCmd kcmd = new KVMHostLuksConvertCmd(); kcmd.psUuid = self.getUuid(); kcmd.installPath = item.getSourceInstallPath(); - kcmd.targetInstallPath = makeTemporaryLuksRbdInstallPath(item.getTargetInstallPath(), "converting"); - kcmd.sourceTrashInstallPath = item.getSourceTrashInstallPath(); + kcmd.targetInstallPath = item.getTargetInstallPath(); kcmd.targetEncrypted = msg.isTargetEncrypted(); kcmd.virtualSize = msg.getVolume().getSize(); kcmd.encryptedDek = volumeEncryptedSecretHelper.materializeAndSealVolumeDekForHost(hostUuid, msg.getVolume().getUuid()); + CheckIsBitsExistingCmd checkTargetCmd = new CheckIsBitsExistingCmd(); + checkTargetCmd.setInstallPath(item.getTargetInstallPath()); + httpCall(CHECK_BITS_PATH, checkTargetCmd, CheckIsBitsExistingRsp.class, + new ReturnValueCompletion(msg) { + @Override + public void success(CheckIsBitsExistingRsp returnValue) { + if (returnValue.isExisting()) { + reply.setError(operr("RBD LUKS conversion target already exists: %s", item.getTargetInstallPath())); + bus.reply(msg, reply); + return; + } + convertVolumeEncryptionOnKvmHost(msg, reply, kcmd, hostUuid); + } + + @Override + public void fail(ErrorCode errorCode) { + reply.setError(errorCode); + bus.reply(msg, reply); + } + }); + } + + private void convertVolumeEncryptionOnKvmHost(ConvertVolumeEncryptionOnPrimaryStorageMsg msg, + ConvertVolumeEncryptionOnPrimaryStorageReply reply, + KVMHostLuksConvertCmd kcmd, + String hostUuid) { + ConvertVolumeEncryptionOnPrimaryStorageMsg.VolumeEncryptionConversionItem item = msg.getItems().get(0); httpCallToKvmHost(hostUuid, KVM_HOST_LUKS_CONVERT_PATH, kcmd, KVMHostLuksRsp.class, new ReturnValueCompletion(msg) { @Override @@ -3646,16 +3657,16 @@ public void fail(ErrorCode err) { @Override public void success(KVMHostLuksRsp ret) { - ReplaceLuksRbdCmd rcmd = new ReplaceLuksRbdCmd(); - rcmd.installPath = item.getSourceInstallPath(); - rcmd.targetInstallPath = item.getTargetInstallPath(); - rcmd.temporaryInstallPath = kcmd.targetInstallPath; - rcmd.sourceTrashInstallPath = item.getSourceTrashInstallPath(); - rcmd.deleteSourceTrash = false; - httpCall(LUKS_REPLACE_VOLUME_PATH, rcmd, ReplaceLuksRbdRsp.class, - new ReturnValueCompletion(msg) { + if (ret.actualSize != null) { + reply.setActualSizes(Collections.singletonMap(msg.getVolume().getUuid(), ret.actualSize)); + bus.reply(msg, reply); + return; + } + + syncVolumeSize(msg.getVolume().getUuid(), item.getTargetInstallPath(), + new ReturnValueCompletion(msg) { @Override - public void success(ReplaceLuksRbdRsp rsp) { + public void success(GetVolumeSizeRsp rsp) { if (rsp.actualSize != null) { reply.setActualSizes(Collections.singletonMap(msg.getVolume().getUuid(), rsp.actualSize)); } @@ -3664,8 +3675,8 @@ public void success(ReplaceLuksRbdRsp rsp) { @Override public void fail(ErrorCode errorCode) { - deleteRbdBitsBestEffort(kcmd.targetInstallPath); - reply.setError(errorCode); + logger.warn(String.format("failed to sync converted RBD volume[uuid:%s, installPath:%s] size: %s", + msg.getVolume().getUuid(), item.getTargetInstallPath(), errorCode.getReadableDetails())); bus.reply(msg, reply); } }); diff --git a/storage/src/main/java/org/zstack/storage/volume/VolumeBase.java b/storage/src/main/java/org/zstack/storage/volume/VolumeBase.java index c364e790fe9..738bcbe80d8 100755 --- a/storage/src/main/java/org/zstack/storage/volume/VolumeBase.java +++ b/storage/src/main/java/org/zstack/storage/volume/VolumeBase.java @@ -3308,7 +3308,6 @@ public String getName() { private static class VolumeEncryptionConversionContext { List snapshots; Map oldAndNewInstallPaths; - Map oldAndTrashInstallPaths; VolumeInventory oldVolumeInventory; List oldSnapshotInventories; List items; @@ -3365,7 +3364,7 @@ public void rollback(FlowRollback trigger, Map data) { @Override public void run(FlowTrigger trigger, Map data) { - conversionContext.set(buildVolumeEncryptionConversionContext()); + conversionContext.set(buildVolumeEncryptionConversionContext(targetEncrypted)); trigger.next(); } }); @@ -3409,7 +3408,12 @@ public void run(FlowTrigger trigger, Map data) { VolumeEncryptionConversionContext ctx = conversionContext.get(); updateVolumeEncryptionConversionInDb(targetEncrypted, ctx.snapshots, ctx.oldAndNewInstallPaths, (Map) data.get("actualSizes")); - refreshVO(); + try { + refreshVO(); + } catch (RuntimeException e) { + logger.warn(String.format("failed to refresh volume[uuid:%s] after encryption conversion DB update: %s", + self.getUuid(), e.getMessage()), e); + } trigger.next(); } @@ -3434,8 +3438,14 @@ public void run(FlowTrigger trigger, Map data) { return; } - volumeEncryptedSecretHelper.deleteSecretOnHostBestEffort( - sourceSecretHostUuid, sourceSecretVmUuid, self.getUuid(), sourceKeyVersion); + try { + volumeEncryptedSecretHelper.deleteSecretOnHostBestEffort( + sourceSecretHostUuid, sourceSecretVmUuid, self.getUuid(), sourceKeyVersion); + VolumeSystemTags.VOLUME_LIBVIRT_SECRET_HOST.delete(self.getUuid(), VolumeVO.class); + } catch (RuntimeException e) { + logger.warn(String.format("failed to cleanup old libvirt secret for volume[uuid:%s] after encryption conversion: %s", + self.getUuid(), e.getMessage()), e); + } trigger.next(); } }); @@ -3450,9 +3460,14 @@ public void run(FlowTrigger trigger, Map data) { return; } - volumeEncryptedResourceKeyBackend.detachKeyProviderFromVolume(self.getUuid()); - for (VolumeSnapshotVO snapshot : conversionContext.get().snapshots) { - volumeEncryptedResourceKeyBackend.detachKeyProviderFromSnapshot(snapshot.getUuid()); + try { + volumeEncryptedResourceKeyBackend.detachKeyProviderFromVolume(self.getUuid()); + for (VolumeSnapshotVO snapshot : conversionContext.get().snapshots) { + volumeEncryptedResourceKeyBackend.detachKeyProviderFromSnapshot(snapshot.getUuid()); + } + } catch (RuntimeException e) { + logger.warn(String.format("failed to cleanup plain resource key refs for volume[uuid:%s] after encryption conversion: %s", + self.getUuid(), e.getMessage()), e); } trigger.next(); } @@ -3463,10 +3478,15 @@ public void run(FlowTrigger trigger, Map data) { @Override public void run(FlowTrigger trigger, Map data) { - VolumeEncryptionConversionContext ctx = conversionContext.get(); - trash.createTrash(TrashType.ConvertVolumeEncryption, false, ctx.oldVolumeInventory); - for (VolumeSnapshotInventory snapshot : ctx.oldSnapshotInventories) { - trash.createTrash(TrashType.ConvertVolumeSnapshotEncryption, false, snapshot); + try { + VolumeEncryptionConversionContext ctx = conversionContext.get(); + trash.createTrash(TrashType.ConvertVolumeEncryption, false, ctx.oldVolumeInventory); + for (VolumeSnapshotInventory snapshot : ctx.oldSnapshotInventories) { + trash.createTrash(TrashType.ConvertVolumeSnapshotEncryption, false, snapshot); + } + } catch (RuntimeException e) { + logger.warn(String.format("failed to record old volume bits in trash for volume[uuid:%s] after encryption conversion: %s", + self.getUuid(), e.getMessage()), e); } trigger.next(); } @@ -3485,7 +3505,7 @@ public void handle(ErrorCode errCode, Map data) { }).start(); } - private VolumeEncryptionConversionContext buildVolumeEncryptionConversionContext() { + private VolumeEncryptionConversionContext buildVolumeEncryptionConversionContext(boolean targetEncrypted) { VolumeEncryptionConversionContext ctx = new VolumeEncryptionConversionContext(); ctx.snapshots = Q.New(VolumeSnapshotVO.class) .eq(VolumeSnapshotVO_.volumeUuid, self.getUuid()) @@ -3494,20 +3514,13 @@ private VolumeEncryptionConversionContext buildVolumeEncryptionConversionContext .comparingInt(VolumeSnapshotVO::getDistance) .thenComparing(VolumeSnapshotVO::getUuid)); - ctx.oldAndNewInstallPaths = buildEncryptionConversionInstallPaths(ctx.snapshots); - ctx.oldAndTrashInstallPaths = buildEncryptionConversionSourceTrashInstallPaths(ctx.snapshots); + ctx.oldAndNewInstallPaths = buildEncryptionConversionInstallPaths(ctx.snapshots, targetEncrypted, Platform.getUuid()); ctx.oldVolumeInventory = VolumeInventory.valueOf(self); - ctx.oldVolumeInventory.setInstallPath(ctx.oldAndTrashInstallPaths.get(self.getInstallPath())); ctx.oldSnapshotInventories = ctx.snapshots.stream() .filter(snapshot -> StringUtils.isNotBlank(snapshot.getPrimaryStorageInstallPath())) - .filter(snapshot -> StringUtils.isNotBlank(ctx.oldAndTrashInstallPaths.get(snapshot.getPrimaryStorageInstallPath()))) - .map(snapshot -> { - VolumeSnapshotInventory inv = VolumeSnapshotInventory.valueOf(snapshot); - inv.setPrimaryStorageInstallPath(ctx.oldAndTrashInstallPaths.get(snapshot.getPrimaryStorageInstallPath())); - return inv; - }) + .map(VolumeSnapshotInventory::valueOf) .collect(Collectors.toList()); - ctx.items = buildEncryptionConversionItems(ctx.snapshots, ctx.oldAndNewInstallPaths, ctx.oldAndTrashInstallPaths); + ctx.items = buildEncryptionConversionItems(ctx.snapshots, ctx.oldAndNewInstallPaths); return ctx; } @@ -3573,37 +3586,25 @@ private boolean ensureVolumeKeyBindingIfNeeded(boolean targetEncrypted) { return true; } - private Map buildEncryptionConversionInstallPaths(List snapshots) { + private Map buildEncryptionConversionInstallPaths(List snapshots, + boolean targetEncrypted, + String conversionUuid) { Map paths = new LinkedHashMap<>(); for (VolumeSnapshotVO snapshot : snapshots) { if (StringUtils.isNotBlank(snapshot.getPrimaryStorageInstallPath())) { paths.put(snapshot.getPrimaryStorageInstallPath(), - makeConvertedSnapshotInstallPath(snapshot.getPrimaryStorageInstallPath(), snapshot.getUuid())); - } - } - paths.put(self.getInstallPath(), makeConvertedVolumeInstallPath(self.getInstallPath(), self.getUuid())); - return paths; - } - - private Map buildEncryptionConversionSourceTrashInstallPaths(List snapshots) { - Map paths = new LinkedHashMap<>(); - Set trashPaths = new HashSet<>(); - for (VolumeSnapshotVO snapshot : snapshots) { - if (StringUtils.isNotBlank(snapshot.getPrimaryStorageInstallPath())) { - String sourceTrashPath = makeSourceSnapshotTrashInstallPath(snapshot.getPrimaryStorageInstallPath(), snapshot.getUuid(), - snapshot.isEncrypted(), trashPaths); - if (StringUtils.isNotBlank(sourceTrashPath)) { - paths.put(snapshot.getPrimaryStorageInstallPath(), sourceTrashPath); - } + makeConvertedSnapshotInstallPath(snapshot.getPrimaryStorageInstallPath(), snapshot.getUuid(), + targetEncrypted, conversionUuid)); } } - paths.put(self.getInstallPath(), makeSourceTrashInstallPath(self.getInstallPath(), self.getUuid(), self.isEncrypted(), trashPaths)); + paths.put(self.getInstallPath(), makeConvertedVolumeInstallPath(self.getInstallPath(), self.getUuid(), + targetEncrypted, conversionUuid)); + validateEncryptionConversionTargetPaths(paths); return paths; } private List buildEncryptionConversionItems( - List snapshots, Map oldAndNewInstallPaths, - Map oldAndTrashInstallPaths) { + List snapshots, Map oldAndNewInstallPaths) { Map snapshotMap = snapshots.stream() .collect(Collectors.toMap(VolumeSnapshotVO::getUuid, it -> it)); List items = new ArrayList<>(); @@ -3618,7 +3619,7 @@ private List oldAndNewInstallPaths) { + Set targets = new HashSet<>(); + for (Map.Entry entry : oldAndNewInstallPaths.entrySet()) { + if (StringUtils.isBlank(entry.getValue())) { + throw new OperationFailureException(operr("failed to build converted install path for source path[%s]", + entry.getKey())); + } + if (entry.getKey().equals(entry.getValue())) { + throw new OperationFailureException(operr("converted install path must differ from source path[%s]", + entry.getKey())); + } + if (!targets.add(entry.getValue())) { + throw new OperationFailureException(operr("duplicate converted install path[%s]", entry.getValue())); + } } - return makeSiblingInstallPath(installPath, String.format("%s.qcow2", resourceUuid)); } private String makeSiblingInstallPath(String installPath, String fileName) { @@ -3701,27 +3719,6 @@ private String makeCephVolumeInstallPath(String installPath, String resourceUuid return String.format("%s%s/%s", prefix, path.substring(0, poolEnd), resourceUuid); } - private String makeSourceSnapshotTrashInstallPath(String installPath, String resourceUuid, boolean sourceEncrypted, Set trashPaths) { - if (isCephInstallPath(installPath)) { - return null; - } - return makeSourceTrashInstallPath(installPath, resourceUuid, sourceEncrypted, trashPaths); - } - - private String makeSourceTrashInstallPath(String installPath, String resourceUuid, boolean sourceEncrypted, Set trashPaths) { - String trashPath; - do { - String fileName = String.format("%s.trash.%s.%s.qcow2", - resourceUuid, sourceEncrypted ? "encrypted" : "plain", Platform.getUuid().substring(0, 6)); - if (isCephInstallPath(installPath)) { - trashPath = makeCephVolumeInstallPath(installPath, fileName); - } else { - trashPath = makeSiblingInstallPath(installPath, fileName); - } - } while (!trashPaths.add(trashPath)); - return trashPath; - } - private boolean isCephInstallPath(String installPath) { return installPath != null && installPath.startsWith("ceph://"); } @@ -3749,34 +3746,38 @@ private void deleteConvertedVolumeEncryptionBits(List snapshots, Map oldAndNewInstallPaths, Map actualSizes) { - VolumeSnapshotReferenceUtils.handleVolumeInstallUrlChange(self.getUuid(), oldAndNewInstallPaths); - - UpdateQuery q = SQL.New(VolumeVO.class) - .eq(VolumeVO_.uuid, self.getUuid()) - .set(VolumeVO_.installPath, oldAndNewInstallPaths.get(self.getInstallPath())) - .set(VolumeVO_.encrypted, targetEncrypted); - if (actualSizes != null && actualSizes.get(self.getUuid()) != null) { - q.set(VolumeVO_.actualSize, actualSizes.get(self.getUuid())); - } - q.update(); + new SQLBatch() { + @Override + protected void scripts() { + VolumeSnapshotReferenceUtils.handleVolumeInstallUrlChange(self.getUuid(), oldAndNewInstallPaths); + + UpdateQuery q = SQL.New(VolumeVO.class) + .eq(VolumeVO_.uuid, self.getUuid()) + .set(VolumeVO_.installPath, oldAndNewInstallPaths.get(self.getInstallPath())) + .set(VolumeVO_.encrypted, targetEncrypted); + if (actualSizes != null && actualSizes.get(self.getUuid()) != null) { + q.set(VolumeVO_.actualSize, actualSizes.get(self.getUuid())); + } + q.update(); - Map convertedSnapshotInstallPaths = new LinkedHashMap<>(); - for (VolumeSnapshotVO snapshot : snapshots) { - String newPath = oldAndNewInstallPaths.get(snapshot.getPrimaryStorageInstallPath()); - if (StringUtils.isBlank(newPath)) { - continue; - } - convertedSnapshotInstallPaths.put(snapshot.getUuid(), newPath); - } + Map convertedSnapshotInstallPaths = new LinkedHashMap<>(); + for (VolumeSnapshotVO snapshot : snapshots) { + String newPath = oldAndNewInstallPaths.get(snapshot.getPrimaryStorageInstallPath()); + if (StringUtils.isBlank(newPath)) { + continue; + } + convertedSnapshotInstallPaths.put(snapshot.getUuid(), newPath); + } - updateConvertedSnapshotPaths(convertedSnapshotInstallPaths, targetEncrypted); - if (targetEncrypted && !convertedSnapshotInstallPaths.isEmpty()) { - volumeEncryptedResourceKeyBackend.copyVolumeKeyRefToSnapshots(self.getUuid(), convertedSnapshotInstallPaths.keySet()); - } + updateConvertedSnapshotPaths(convertedSnapshotInstallPaths, targetEncrypted); + if (targetEncrypted && !convertedSnapshotInstallPaths.isEmpty()) { + volumeEncryptedResourceKeyBackend.copyVolumeKeyRefToSnapshots(self.getUuid(), convertedSnapshotInstallPaths.keySet()); + } + } + }.execute(); } private void updateConvertedSnapshotPaths(Map snapshotInstallPaths, boolean targetEncrypted) { diff --git a/testlib/src/main/java/org/zstack/testlib/CephPrimaryStorageSpec.groovy b/testlib/src/main/java/org/zstack/testlib/CephPrimaryStorageSpec.groovy index 5e711d6819d..bc3ec418f24 100755 --- a/testlib/src/main/java/org/zstack/testlib/CephPrimaryStorageSpec.groovy +++ b/testlib/src/main/java/org/zstack/testlib/CephPrimaryStorageSpec.groovy @@ -262,47 +262,6 @@ class CephPrimaryStorageSpec extends PrimaryStorageSpec { return rsp } - simulator(CephPrimaryStorageBase.LUKS_REPLACE_VOLUME_PATH) { HttpEntity e, EnvSpec spec -> - return new CephPrimaryStorageBase.ReplaceLuksRbdRsp() - } - - VFS.vfsHook(CephPrimaryStorageBase.LUKS_REPLACE_VOLUME_PATH, espec) { CephPrimaryStorageBase.ReplaceLuksRbdRsp rsp, HttpEntity e, EnvSpec spec -> - def cmd = JSONObjectUtil.toObject(e.body, CephPrimaryStorageBase.ReplaceLuksRbdCmd.class) - VFS vfs = vfs(cmd, spec) - String srcPath = cephPathToVFSPath(cmd.installPath) - String tmpPath = cephPathToVFSPath(cmd.temporaryInstallPath) - String targetPath = cephPathToVFSPath(cmd.targetInstallPath ?: cmd.installPath) - boolean deleteSourceTrash = cmd.deleteSourceTrash || !cmd.sourceTrashInstallPath - String trashPath = cephPathToVFSPath(cmd.sourceTrashInstallPath ?: "${srcPath}-trash-${Platform.uuid.substring(0, 8)}") - - [srcPath, tmpPath, targetPath, trashPath].each { - vfs.Assert(!it.contains("@"), "RBD LUKS replacement only supports active image paths[${it}]") - } - vfs.Assert(vfs.isFile(srcPath), "cannot find the source file[${cmd.installPath}]") - CephRaw src = vfs.getFile(srcPath, true) - if (!vfs.exists(tmpPath)) { - CephRaw tmp = vfs.createCephRaw(tmpPath, src.virtualSize) - tmp.actualSize = src.actualSize - tmp.update() - } - vfs.Assert(vfs.isFile(tmpPath), "cannot find the temporary file[${cmd.temporaryInstallPath}]") - vfs.Assert(!vfs.exists(trashPath), "trash file[${trashPath}] already exists") - if (targetPath != srcPath) { - vfs.Assert(!vfs.exists(targetPath), "target file[${targetPath}] already exists") - } - - src.move(trashPath) - CephRaw tmp = vfs.getFile(tmpPath, true) - CephRaw target = tmp.move(targetPath) - if (deleteSourceTrash && vfs.exists(trashPath)) { - vfs.delete(trashPath) - } - - rsp.size = target.virtualSize - rsp.actualSize = target.actualSize - return rsp - } - simulator(CephPrimaryStorageBase.LUKS_SWAP_IN_PLACE_PATH) { HttpEntity e, EnvSpec spec -> return new CephPrimaryStorageBase.AgentResponse() } @@ -672,7 +631,11 @@ class CephPrimaryStorageSpec extends PrimaryStorageSpec { VFS.vfsHook(CephPrimaryStorageBase.CHECK_BITS_PATH, espec) { rsp, HttpEntity e, EnvSpec spec -> def cmd = JSONObjectUtil.toObject(e.body, CephPrimaryStorageBase.CheckIsBitsExistingCmd.class) VFS vfs = vfs(cmd, spec) - vfs.Assert(vfs.isFile(cephPathToVFSPath(cmd.installPath)), "cannot find ${cmd.installPath}") + if (cmd.installPath ==~ /.*[0-9a-f]{32}\.(encrypted|plain)\.[0-9a-f]{32}$/) { + rsp.existing = vfs.exists(cephPathToVFSPath(cmd.installPath)) + } else { + vfs.Assert(vfs.isFile(cephPathToVFSPath(cmd.installPath)), "cannot find ${cmd.installPath}") + } return rsp } diff --git a/testlib/src/main/java/org/zstack/testlib/LocalStorageSpec.groovy b/testlib/src/main/java/org/zstack/testlib/LocalStorageSpec.groovy index 3530492f9bb..a0accf71676 100755 --- a/testlib/src/main/java/org/zstack/testlib/LocalStorageSpec.groovy +++ b/testlib/src/main/java/org/zstack/testlib/LocalStorageSpec.groovy @@ -303,6 +303,20 @@ class LocalStorageSpec extends PrimaryStorageSpec { return new LocalStorageKvmBackend.ConvertVolumeEncryptionRsp() } + VFS.vfsHook(LocalStorageKvmBackend.CONVERT_VOLUME_ENCRYPTION_PATH, espec) { rsp, HttpEntity e, EnvSpec spec -> + def cmd = JSONObjectUtil.toObject(e.body, LocalStorageKvmBackend.ConvertVolumeEncryptionCmd.class) + VFS vfs = vfs(e, cmd, spec) + rsp.actualSizes = [:] + cmd.items.each { item -> + Qcow2 source = vfs.getFile(item.sourceInstallPath) + assert source != null : "cannot find source file[${item.sourceInstallPath}]" + Qcow2 target = vfs.createQcow2(item.targetInstallPath, source.actualSize, + source.virtualSize, item.targetBackingInstallPath) + rsp.actualSizes[item.resourceUuid] = target.actualSize + } + return rsp + } + VFS.vfsHook(LocalStorageKvmBackend.CREATE_VOLUME_WITH_BACKING_PATH, espec) { rsp, HttpEntity e, EnvSpec spec -> def cmd = JSONObjectUtil.toObject(e.body, LocalStorageKvmBackend.CreateVolumeWithBackingCmd.class) VFS vfs = vfs(e, cmd, spec) diff --git a/testlib/src/main/java/org/zstack/testlib/NfsPrimaryStorageSpec.groovy b/testlib/src/main/java/org/zstack/testlib/NfsPrimaryStorageSpec.groovy index 32ea00411d1..6fbca40156c 100755 --- a/testlib/src/main/java/org/zstack/testlib/NfsPrimaryStorageSpec.groovy +++ b/testlib/src/main/java/org/zstack/testlib/NfsPrimaryStorageSpec.groovy @@ -161,6 +161,20 @@ class NfsPrimaryStorageSpec extends PrimaryStorageSpec { return new NfsPrimaryStorageKVMBackendCommands.ConvertVolumeEncryptionRsp() } + VFS.vfsHook(NfsPrimaryStorageKVMBackend.CONVERT_VOLUME_ENCRYPTION_PATH, xspec) { rsp, HttpEntity e, EnvSpec spec -> + def cmd = JSONObjectUtil.toObject(e.body, NfsPrimaryStorageKVMBackendCommands.ConvertVolumeEncryptionCmd.class) + VFS vfs = vfs(cmd, spec) + rsp.actualSizes = [:] + cmd.items.each { item -> + Qcow2 source = vfs.getFile(item.sourceInstallPath) + assert source != null : "cannot find source file[${item.sourceInstallPath}]" + Qcow2 target = vfs.createQcow2(item.targetInstallPath, source.actualSize, + source.virtualSize, item.targetBackingInstallPath) + rsp.actualSizes[item.resourceUuid] = target.actualSize + } + return rsp + } + VFS.vfsHook(NfsPrimaryStorageKVMBackend.CREATE_EMPTY_VOLUME_PATH, xspec) { rsp, HttpEntity e, EnvSpec spec -> def cmd = JSONObjectUtil.toObject(e.body, NfsPrimaryStorageKVMBackendCommands.CreateEmptyVolumeCmd.class) VFS vfs = vfs(cmd, spec)