|
18 | 18 | */ |
19 | 19 | package com.cloud.hypervisor.kvm.storage; |
20 | 20 |
|
21 | | -import static com.cloud.utils.NumbersUtil.toHumanReadableSize; |
22 | | -import static com.cloud.utils.storage.S3.S3Utils.putFile; |
23 | | - |
24 | | -import java.io.File; |
25 | | -import java.io.FileNotFoundException; |
26 | | -import java.io.FileOutputStream; |
27 | | -import java.io.IOException; |
28 | | -import java.nio.file.Files; |
29 | | -import java.nio.file.Paths; |
30 | | -import java.text.DateFormat; |
31 | | -import java.text.SimpleDateFormat; |
32 | | -import java.util.Arrays; |
33 | | -import java.util.Date; |
34 | | -import java.util.HashMap; |
35 | | -import java.util.HashSet; |
36 | | -import java.util.List; |
37 | | -import java.util.Map; |
38 | | -import java.util.Set; |
39 | | -import java.util.UUID; |
40 | | -import java.util.stream.Collectors; |
41 | | - |
42 | | -import javax.naming.ConfigurationException; |
43 | | - |
44 | | -import org.apache.cloudstack.agent.directdownload.DirectDownloadAnswer; |
45 | | -import org.apache.cloudstack.agent.directdownload.DirectDownloadCommand; |
46 | | -import org.apache.cloudstack.direct.download.DirectDownloadHelper; |
47 | | -import org.apache.cloudstack.direct.download.DirectTemplateDownloader; |
48 | | -import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo; |
49 | | -import org.apache.cloudstack.storage.command.AttachAnswer; |
50 | | -import org.apache.cloudstack.storage.command.AttachCommand; |
51 | | -import org.apache.cloudstack.storage.command.CheckDataStoreStoragePolicyComplainceCommand; |
52 | | -import org.apache.cloudstack.storage.command.CopyCmdAnswer; |
53 | | -import org.apache.cloudstack.storage.command.CopyCommand; |
54 | | -import org.apache.cloudstack.storage.command.CreateObjectAnswer; |
55 | | -import org.apache.cloudstack.storage.command.CreateObjectCommand; |
56 | | -import org.apache.cloudstack.storage.command.DeleteCommand; |
57 | | -import org.apache.cloudstack.storage.command.DettachAnswer; |
58 | | -import org.apache.cloudstack.storage.command.DettachCommand; |
59 | | -import org.apache.cloudstack.storage.command.ForgetObjectCmd; |
60 | | -import org.apache.cloudstack.storage.command.IntroduceObjectCmd; |
61 | | -import org.apache.cloudstack.storage.command.ResignatureAnswer; |
62 | | -import org.apache.cloudstack.storage.command.ResignatureCommand; |
63 | | -import org.apache.cloudstack.storage.command.SnapshotAndCopyAnswer; |
64 | | -import org.apache.cloudstack.storage.command.SnapshotAndCopyCommand; |
65 | | -import org.apache.cloudstack.storage.command.SyncVolumePathCommand; |
66 | | -import org.apache.cloudstack.storage.to.PrimaryDataStoreTO; |
67 | | -import org.apache.cloudstack.storage.to.SnapshotObjectTO; |
68 | | -import org.apache.cloudstack.storage.to.TemplateObjectTO; |
69 | | -import org.apache.cloudstack.storage.to.VolumeObjectTO; |
70 | | -import org.apache.cloudstack.utils.qemu.QemuImg; |
71 | | -import org.apache.cloudstack.utils.qemu.QemuImg.PhysicalDiskFormat; |
72 | | -import org.apache.cloudstack.utils.qemu.QemuImgException; |
73 | | -import org.apache.cloudstack.utils.qemu.QemuImgFile; |
74 | | -import org.apache.cloudstack.utils.qemu.QemuObject; |
75 | | -import org.apache.commons.collections.MapUtils; |
76 | | -import org.apache.commons.io.FileUtils; |
77 | | -import org.apache.commons.lang3.BooleanUtils; |
78 | | -import org.apache.commons.lang3.StringUtils; |
79 | | -import org.apache.commons.lang3.builder.ToStringBuilder; |
80 | | -import org.apache.commons.lang3.builder.ToStringStyle; |
81 | | -import org.apache.log4j.Logger; |
82 | | -import org.libvirt.Connect; |
83 | | -import org.libvirt.Domain; |
84 | | -import org.libvirt.DomainInfo; |
85 | | -import org.libvirt.DomainSnapshot; |
86 | | -import org.libvirt.LibvirtException; |
87 | | - |
88 | 21 | import com.ceph.rados.IoCTX; |
89 | 22 | import com.ceph.rados.Rados; |
90 | 23 | import com.ceph.rados.exceptions.ErrorCode; |
|
133 | 66 | import com.cloud.utils.script.Script; |
134 | 67 | import com.cloud.utils.storage.S3.S3Utils; |
135 | 68 | import com.cloud.vm.VmDetailConstants; |
| 69 | +import org.apache.cloudstack.agent.directdownload.DirectDownloadAnswer; |
| 70 | +import org.apache.cloudstack.agent.directdownload.DirectDownloadCommand; |
| 71 | +import org.apache.cloudstack.direct.download.DirectDownloadHelper; |
| 72 | +import org.apache.cloudstack.direct.download.DirectTemplateDownloader; |
| 73 | +import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo; |
| 74 | +import org.apache.cloudstack.storage.command.AttachAnswer; |
| 75 | +import org.apache.cloudstack.storage.command.AttachCommand; |
| 76 | +import org.apache.cloudstack.storage.command.CheckDataStoreStoragePolicyComplainceCommand; |
| 77 | +import org.apache.cloudstack.storage.command.CopyCmdAnswer; |
| 78 | +import org.apache.cloudstack.storage.command.CopyCommand; |
| 79 | +import org.apache.cloudstack.storage.command.CreateObjectAnswer; |
| 80 | +import org.apache.cloudstack.storage.command.CreateObjectCommand; |
| 81 | +import org.apache.cloudstack.storage.command.DeleteCommand; |
| 82 | +import org.apache.cloudstack.storage.command.DettachAnswer; |
| 83 | +import org.apache.cloudstack.storage.command.DettachCommand; |
| 84 | +import org.apache.cloudstack.storage.command.ForgetObjectCmd; |
| 85 | +import org.apache.cloudstack.storage.command.IntroduceObjectCmd; |
| 86 | +import org.apache.cloudstack.storage.command.ResignatureAnswer; |
| 87 | +import org.apache.cloudstack.storage.command.ResignatureCommand; |
| 88 | +import org.apache.cloudstack.storage.command.SnapshotAndCopyAnswer; |
| 89 | +import org.apache.cloudstack.storage.command.SnapshotAndCopyCommand; |
| 90 | +import org.apache.cloudstack.storage.command.SyncVolumePathCommand; |
| 91 | +import org.apache.cloudstack.storage.to.PrimaryDataStoreTO; |
| 92 | +import org.apache.cloudstack.storage.to.SnapshotObjectTO; |
| 93 | +import org.apache.cloudstack.storage.to.TemplateObjectTO; |
| 94 | +import org.apache.cloudstack.storage.to.VolumeObjectTO; |
| 95 | +import org.apache.cloudstack.utils.cryptsetup.KeyFile; |
| 96 | +import org.apache.cloudstack.utils.qemu.QemuImageOptions; |
| 97 | +import org.apache.cloudstack.utils.qemu.QemuImg; |
| 98 | +import org.apache.cloudstack.utils.qemu.QemuImg.PhysicalDiskFormat; |
| 99 | +import org.apache.cloudstack.utils.qemu.QemuImgException; |
| 100 | +import org.apache.cloudstack.utils.qemu.QemuImgFile; |
| 101 | +import org.apache.cloudstack.utils.qemu.QemuObject; |
| 102 | +import org.apache.cloudstack.utils.qemu.QemuObject.EncryptFormat; |
| 103 | +import org.apache.commons.collections.MapUtils; |
| 104 | +import org.apache.commons.io.FileUtils; |
| 105 | +import org.apache.commons.lang3.BooleanUtils; |
| 106 | +import org.apache.commons.lang3.StringUtils; |
| 107 | +import org.apache.commons.lang3.builder.ToStringBuilder; |
| 108 | +import org.apache.commons.lang3.builder.ToStringStyle; |
| 109 | +import org.apache.log4j.Logger; |
| 110 | +import org.libvirt.Connect; |
| 111 | +import org.libvirt.Domain; |
| 112 | +import org.libvirt.DomainInfo; |
| 113 | +import org.libvirt.DomainSnapshot; |
| 114 | +import org.libvirt.LibvirtException; |
| 115 | + |
| 116 | +import javax.naming.ConfigurationException; |
| 117 | +import java.io.File; |
| 118 | +import java.io.FileNotFoundException; |
| 119 | +import java.io.FileOutputStream; |
| 120 | +import java.io.IOException; |
| 121 | +import java.nio.file.Files; |
| 122 | +import java.nio.file.Paths; |
| 123 | +import java.text.DateFormat; |
| 124 | +import java.text.SimpleDateFormat; |
| 125 | +import java.util.ArrayList; |
| 126 | +import java.util.Arrays; |
| 127 | +import java.util.Date; |
| 128 | +import java.util.HashMap; |
| 129 | +import java.util.HashSet; |
| 130 | +import java.util.List; |
| 131 | +import java.util.Map; |
| 132 | +import java.util.Set; |
| 133 | +import java.util.UUID; |
| 134 | +import java.util.stream.Collectors; |
| 135 | + |
| 136 | +import static com.cloud.utils.NumbersUtil.toHumanReadableSize; |
| 137 | +import static com.cloud.utils.storage.S3.S3Utils.putFile; |
136 | 138 |
|
137 | 139 | public class KVMStorageProcessor implements StorageProcessor { |
138 | 140 | private static final Logger s_logger = Logger.getLogger(KVMStorageProcessor.class); |
@@ -1744,7 +1746,7 @@ public Answer createSnapshot(final CreateObjectCommand cmd) { |
1744 | 1746 | snapshotPath = getSnapshotPathInPrimaryStorage(primaryPool.getLocalPath(), snapshotName); |
1745 | 1747 |
|
1746 | 1748 | String diskLabel = takeVolumeSnapshot(resource.getDisks(conn, vmName), snapshotName, diskPath, vm); |
1747 | | - String convertResult = convertBaseFileToSnapshotFileInPrimaryStorageDir(primaryPool, diskPath, snapshotPath, volume, cmd.getWait()); |
| 1749 | + String convertResult = convertBaseFileToSnapshotFileInPrimaryStorageDir(primaryPool, disk, snapshotPath, volume, cmd.getWait()); |
1748 | 1750 |
|
1749 | 1751 | mergeSnapshotIntoBaseFile(vm, diskLabel, diskPath, snapshotName, volume, conn); |
1750 | 1752 |
|
@@ -1813,7 +1815,7 @@ public Answer createSnapshot(final CreateObjectCommand cmd) { |
1813 | 1815 | } |
1814 | 1816 | } else { |
1815 | 1817 | snapshotPath = getSnapshotPathInPrimaryStorage(primaryPool.getLocalPath(), snapshotName); |
1816 | | - String convertResult = convertBaseFileToSnapshotFileInPrimaryStorageDir(primaryPool, diskPath, snapshotPath, volume, cmd.getWait()); |
| 1818 | + String convertResult = convertBaseFileToSnapshotFileInPrimaryStorageDir(primaryPool, disk, snapshotPath, volume, cmd.getWait()); |
1817 | 1819 | validateConvertResult(convertResult, snapshotPath); |
1818 | 1820 | } |
1819 | 1821 | } |
@@ -1936,26 +1938,43 @@ protected void manuallyDeleteUnusedSnapshotFile(boolean isLibvirtSupportingFlagD |
1936 | 1938 | * @param snapshotPath Path to convert the base file; |
1937 | 1939 | * @return null if the conversion occurs successfully or an error message that must be handled. |
1938 | 1940 | */ |
1939 | | - protected String convertBaseFileToSnapshotFileInPrimaryStorageDir(KVMStoragePool primaryPool, String baseFile, String snapshotPath, VolumeObjectTO volume, int wait) { |
1940 | | - try { |
1941 | | - s_logger.debug(String.format("Trying to convert volume [%s] (%s) to snapshot [%s].", volume, baseFile, snapshotPath)); |
| 1941 | + protected String convertBaseFileToSnapshotFileInPrimaryStorageDir(KVMStoragePool primaryPool, |
| 1942 | + KVMPhysicalDisk baseFile, String snapshotPath, VolumeObjectTO volume, int wait) { |
| 1943 | + try (KeyFile srcKey = new KeyFile(volume.getPassphrase())) { |
| 1944 | + s_logger.debug( |
| 1945 | + String.format("Trying to convert volume [%s] (%s) to snapshot [%s].", volume, baseFile, snapshotPath)); |
1942 | 1946 |
|
1943 | 1947 | primaryPool.createFolder(TemplateConstants.DEFAULT_SNAPSHOT_ROOT_DIR); |
| 1948 | + convertTheBaseFileToSnapshot(baseFile, snapshotPath, wait, srcKey); |
| 1949 | + } catch (QemuImgException | LibvirtException | IOException ex) { |
| 1950 | + return String.format("Failed to convert %s snapshot of volume [%s] to [%s] due to [%s].", volume, baseFile, |
| 1951 | + snapshotPath, ex.getMessage()); |
| 1952 | + } |
1944 | 1953 |
|
1945 | | - QemuImgFile srcFile = new QemuImgFile(baseFile); |
1946 | | - srcFile.setFormat(PhysicalDiskFormat.QCOW2); |
| 1954 | + s_logger.debug(String.format("Converted volume [%s] (from path \"%s\") to snapshot [%s].", volume, baseFile, |
| 1955 | + snapshotPath)); |
| 1956 | + return null; |
| 1957 | + } |
1947 | 1958 |
|
1948 | | - QemuImgFile destFile = new QemuImgFile(snapshotPath); |
1949 | | - destFile.setFormat(PhysicalDiskFormat.QCOW2); |
| 1959 | + private void convertTheBaseFileToSnapshot(KVMPhysicalDisk baseFile, String snapshotPath, int wait, KeyFile srcKey) |
| 1960 | + throws LibvirtException, QemuImgException { |
| 1961 | + List<QemuObject> qemuObjects = new ArrayList<>(); |
| 1962 | + Map<String, String> options = new HashMap<>(); |
| 1963 | + QemuImageOptions qemuImageOpts = new QemuImageOptions(baseFile.getPath()); |
| 1964 | + if (srcKey.isSet()) { |
| 1965 | + String srcKeyName = "sec0"; |
| 1966 | + qemuObjects.add(QemuObject.prepareSecretForQemuImg(baseFile.getFormat(), EncryptFormat.LUKS, |
| 1967 | + srcKey.toString(), srcKeyName, options)); |
| 1968 | + qemuImageOpts = new QemuImageOptions(baseFile.getFormat(), baseFile.getPath(), srcKeyName); |
| 1969 | + } |
| 1970 | + QemuImgFile srcFile = new QemuImgFile(baseFile.getPath()); |
| 1971 | + srcFile.setFormat(PhysicalDiskFormat.QCOW2); |
1950 | 1972 |
|
1951 | | - QemuImg q = new QemuImg(wait); |
1952 | | - q.convert(srcFile, destFile); |
| 1973 | + QemuImgFile destFile = new QemuImgFile(snapshotPath); |
| 1974 | + destFile.setFormat(PhysicalDiskFormat.QCOW2); |
1953 | 1975 |
|
1954 | | - s_logger.debug(String.format("Converted volume [%s] (from path \"%s\") to snapshot [%s].", volume, baseFile, snapshotPath)); |
1955 | | - return null; |
1956 | | - } catch (QemuImgException | LibvirtException ex) { |
1957 | | - return String.format("Failed to convert %s snapshot of volume [%s] to [%s] due to [%s].", volume, baseFile, snapshotPath, ex.getMessage()); |
1958 | | - } |
| 1976 | + QemuImg q = new QemuImg(wait); |
| 1977 | + q.convert(srcFile, destFile, options, qemuObjects, qemuImageOpts, null, true); |
1959 | 1978 | } |
1960 | 1979 |
|
1961 | 1980 | /** |
|
0 commit comments