Skip to content

Commit 4c49ea2

Browse files
committed
Add support for erasure code pools
1 parent f10d9fe commit 4c49ea2

File tree

21 files changed

+267
-107
lines changed

21 files changed

+267
-107
lines changed

api/src/main/java/org/apache/cloudstack/api/response/StoragePoolResponse.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,10 @@ public class StoragePoolResponse extends BaseResponseWithAnnotations {
145145
@Param(description = "whether this pool is managed or not")
146146
private Boolean managed;
147147

148+
@SerializedName(ApiConstants.DETAILS)
149+
@Param(description = "the storage pool details")
150+
private Map<String, String> details;
151+
148152
public Map<String, String> getCaps() {
149153
return caps;
150154
}
@@ -395,4 +399,12 @@ public Boolean getManaged() {
395399
public void setManaged(Boolean managed) {
396400
this.managed = managed;
397401
}
402+
403+
public Map<String, String> getDetails() {
404+
return details;
405+
}
406+
407+
public void setDetails(Map<String, String> details) {
408+
this.details = details;
409+
}
398410
}

engine/storage/volume/src/main/java/org/apache/cloudstack/storage/datastore/provider/DefaultHostListener.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@
4242
import com.cloud.storage.StoragePoolHostVO;
4343
import com.cloud.storage.StorageService;
4444
import com.cloud.storage.dao.StoragePoolHostDao;
45-
import com.cloud.utils.Pair;
4645
import com.cloud.utils.exception.CloudRuntimeException;
4746

4847
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
@@ -130,10 +129,12 @@ private NicTO createNicTOFromNetworkAndOffering(NetworkVO networkVO, NetworkOffe
130129
@Override
131130
public boolean hostConnect(long hostId, long poolId) throws StorageConflictException {
132131
StoragePool pool = (StoragePool) this.dataStoreMgr.getDataStore(poolId, DataStoreRole.Primary);
133-
Pair<Map<String, String>, Boolean> nfsMountOpts = storageManager.getStoragePoolNFSMountOpts(pool, null);
132+
Map<String, String> detailsMap = storagePoolDetailsDao.listDetailsKeyPairs(poolId);
133+
detailsMap.putAll(storageManager.getStoragePoolNFSMountOpts(pool, null).first());
134134

135-
ModifyStoragePoolCommand cmd = new ModifyStoragePoolCommand(true, pool, nfsMountOpts.first());
135+
ModifyStoragePoolCommand cmd = new ModifyStoragePoolCommand(true, pool, detailsMap);
136136
cmd.setWait(modifyStoragePoolCommandWait);
137+
137138
logger.debug(String.format("Sending modify storage pool command to agent: %d for storage pool: %d with timeout %d seconds",
138139
hostId, poolId, cmd.getWait()));
139140
final Answer answer = agentMgr.easySend(hostId, cmd);

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtCreatePrivateTemplateFromVolumeCommandWrapper.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,7 @@ public Answer execute(final CreatePrivateTemplateFromVolumeCommand command, fina
108108
} else {
109109
logger.debug("Converting RBD disk " + disk.getPath() + " into template " + command.getUniqueName());
110110

111-
final QemuImgFile srcFile =
112-
new QemuImgFile(KVMPhysicalDisk.RBDStringBuilder(primary.getSourceHost(), primary.getSourcePort(), primary.getAuthUserName(),
113-
primary.getAuthSecret(), disk.getPath()));
111+
final QemuImgFile srcFile = new QemuImgFile(KVMPhysicalDisk.RBDStringBuilder(primary, disk.getPath()));
114112
srcFile.setFormat(PhysicalDiskFormat.RAW);
115113

116114
final QemuImgFile destFile = new QemuImgFile(tmpltPath + "/" + command.getUniqueName() + ".qcow2");

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtGetVolumesOnStorageCommandWrapper.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -161,11 +161,7 @@ private Map<String, String> getDiskFileInfo(KVMStoragePool pool, KVMPhysicalDisk
161161
QemuImg qemu = new QemuImg(0);
162162
QemuImgFile qemuFile = new QemuImgFile(disk.getPath(), disk.getFormat());
163163
if (StoragePoolType.RBD.equals(pool.getType())) {
164-
String rbdDestFile = KVMPhysicalDisk.RBDStringBuilder(pool.getSourceHost(),
165-
pool.getSourcePort(),
166-
pool.getAuthUserName(),
167-
pool.getAuthSecret(),
168-
disk.getPath());
164+
String rbdDestFile = KVMPhysicalDisk.RBDStringBuilder(pool, disk.getPath());
169165
qemuFile = new QemuImgFile(rbdDestFile, disk.getFormat());
170166
}
171167
return qemu.info(qemuFile, secure);

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/IscsiAdmStorageAdaptor.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -410,9 +410,7 @@ public KVMPhysicalDisk copyPhysicalDisk(KVMPhysicalDisk srcDisk, String destVolu
410410
KVMStoragePool srcPool = srcDisk.getPool();
411411

412412
if (srcPool.getType() == StoragePoolType.RBD) {
413-
srcFile = new QemuImgFile(KVMPhysicalDisk.RBDStringBuilder(srcPool.getSourceHost(), srcPool.getSourcePort(),
414-
srcPool.getAuthUserName(), srcPool.getAuthSecret(),
415-
srcDisk.getPath()),srcDisk.getFormat());
413+
srcFile = new QemuImgFile(KVMPhysicalDisk.RBDStringBuilder(srcPool, srcDisk.getPath()), srcDisk.getFormat());
416414
} else {
417415
srcFile = new QemuImgFile(srcDisk.getPath(), srcDisk.getFormat());
418416
}

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMPhysicalDisk.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
import java.util.ArrayList;
2525
import java.util.List;
26+
import java.util.Map;
2627

2728
public class KVMPhysicalDisk {
2829
private String path;
@@ -32,10 +33,15 @@ public class KVMPhysicalDisk {
3233
private String vmName;
3334
private boolean useAsTemplate;
3435

35-
public static String RBDStringBuilder(String monHost, int monPort, String authUserName, String authSecret, String image) {
36-
String rbdOpts;
36+
public static String RBDStringBuilder(KVMStoragePool storagePool, String image) {
37+
String monHost = storagePool.getSourceHost();
38+
int monPort = storagePool.getSourcePort();
39+
String authUserName = storagePool.getAuthUserName();
40+
String authSecret = storagePool.getAuthSecret();
41+
Map<String, String> details = storagePool.getDetails();
42+
String dataPool = (details == null) ? null : details.get("rbd_default_data_pool");
3743

38-
rbdOpts = "rbd:" + image;
44+
String rbdOpts = "rbd:" + image;
3945
rbdOpts += ":mon_host=" + composeOptionForMonHosts(monHost, monPort);
4046

4147
if (authUserName == null) {
@@ -46,6 +52,10 @@ public static String RBDStringBuilder(String monHost, int monPort, String authUs
4652
rbdOpts += ":key=" + authSecret;
4753
}
4854

55+
if (dataPool != null) {
56+
rbdOpts += String.format(":rbd_default_data_pool=%s", dataPool);
57+
}
58+
4959
rbdOpts += ":rbd_default_format=2";
5060
rbdOpts += ":client_mount_timeout=30";
5161

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java

Lines changed: 20 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -53,28 +53,6 @@
5353
public class KVMStoragePoolManager {
5454
protected Logger logger = LogManager.getLogger(getClass());
5555

56-
private class StoragePoolInformation {
57-
String name;
58-
String host;
59-
int port;
60-
String path;
61-
String userInfo;
62-
boolean type;
63-
StoragePoolType poolType;
64-
Map<String, String> details;
65-
66-
public StoragePoolInformation(String name, String host, int port, String path, String userInfo, StoragePoolType poolType, Map<String, String> details, boolean type) {
67-
this.name = name;
68-
this.host = host;
69-
this.port = port;
70-
this.path = path;
71-
this.userInfo = userInfo;
72-
this.type = type;
73-
this.poolType = poolType;
74-
this.details = details;
75-
}
76-
}
77-
7856
private KVMHAMonitor _haMonitor;
7957
private final Map<String, StoragePoolInformation> _storagePools = new ConcurrentHashMap<String, StoragePoolInformation>();
8058
private final Map<String, StorageAdaptor> _storageMapper = new HashMap<String, StorageAdaptor>();
@@ -303,14 +281,33 @@ public KVMStoragePool getStoragePool(StoragePoolType type, String uuid, boolean
303281
} catch (Exception e) {
304282
StoragePoolInformation info = _storagePools.get(uuid);
305283
if (info != null) {
306-
pool = createStoragePool(info.name, info.host, info.port, info.path, info.userInfo, info.poolType, info.details, info.type);
284+
pool = createStoragePool(info.getName(), info.getHost(), info.getPort(), info.getPath(), info.getUserInfo(), info.getPoolType(), info.getDetails(), info.isType());
307285
} else {
308286
throw new CloudRuntimeException("Could not fetch storage pool " + uuid + " from libvirt due to " + e.getMessage());
309287
}
310288
}
289+
290+
if (pool instanceof LibvirtStoragePool) {
291+
addPoolDetails(uuid, (LibvirtStoragePool) pool);
292+
}
293+
311294
return pool;
312295
}
313296

297+
/**
298+
* As the class {@link LibvirtStoragePool} is constrained to the {@link org.libvirt.StoragePool} class, there is no way of saving a generic parameter such as the details, hence,
299+
* this method was created to always make available the details of libvirt primary storages for when they are needed.
300+
*/
301+
private void addPoolDetails(String uuid, LibvirtStoragePool pool) {
302+
StoragePoolInformation storagePoolInformation = _storagePools.get(uuid);
303+
Map<String, String> details = storagePoolInformation.getDetails();
304+
305+
if (MapUtils.isNotEmpty(details)) {
306+
logger.trace("Adding the details {} to the pool with UUID {}.", details, uuid);
307+
pool.setDetails(details);
308+
}
309+
}
310+
314311
public KVMStoragePool getStoragePoolByURI(String uri) {
315312
URI storageUri = null;
316313

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -655,9 +655,7 @@ public Answer createTemplateFromVolume(final CopyCommand cmd) {
655655
} else {
656656
logger.debug("Converting RBD disk " + disk.getPath() + " into template " + templateName);
657657

658-
final QemuImgFile srcFile =
659-
new QemuImgFile(KVMPhysicalDisk.RBDStringBuilder(primary.getSourceHost(), primary.getSourcePort(), primary.getAuthUserName(),
660-
primary.getAuthSecret(), disk.getPath()));
658+
final QemuImgFile srcFile = new QemuImgFile(KVMPhysicalDisk.RBDStringBuilder(primary, disk.getPath()));
661659
srcFile.setFormat(PhysicalDiskFormat.RAW);
662660

663661
final QemuImgFile destFile = new QemuImgFile(tmpltPath + "/" + templateName + ".qcow2");
@@ -1004,9 +1002,7 @@ public Answer backupSnapshot(final CopyCommand cmd) {
10041002
logger.debug("Attempting to create " + snapDir.getAbsolutePath() + " recursively for snapshot storage");
10051003
FileUtils.forceMkdir(snapDir);
10061004

1007-
final QemuImgFile srcFile =
1008-
new QemuImgFile(KVMPhysicalDisk.RBDStringBuilder(primaryPool.getSourceHost(), primaryPool.getSourcePort(), primaryPool.getAuthUserName(),
1009-
primaryPool.getAuthSecret(), rbdSnapshot));
1005+
final QemuImgFile srcFile = new QemuImgFile(KVMPhysicalDisk.RBDStringBuilder(primaryPool, rbdSnapshot));
10101006
srcFile.setFormat(snapshotDisk.getFormat());
10111007

10121008
final QemuImgFile destFile = new QemuImgFile(snapshotFile);

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -868,7 +868,7 @@ public KVMPhysicalDisk createPhysicalDisk(String name, KVMStoragePool pool,
868868

869869
StoragePoolType poolType = pool.getType();
870870
if (poolType.equals(StoragePoolType.RBD)) {
871-
return createPhysicalDiskByLibVirt(name, pool, PhysicalDiskFormat.RAW, provisioningType, size);
871+
return createPhysicalDiskByQemuImg(name, pool, PhysicalDiskFormat.RAW, provisioningType, size, passphrase);
872872
} else if (poolType.equals(StoragePoolType.NetworkFilesystem) || poolType.equals(StoragePoolType.Filesystem)) {
873873
switch (format) {
874874
case QCOW2:
@@ -917,18 +917,25 @@ private KVMPhysicalDisk createPhysicalDiskByLibVirt(String name, KVMStoragePool
917917
}
918918

919919

920-
private KVMPhysicalDisk createPhysicalDiskByQemuImg(String name, KVMStoragePool pool,
921-
PhysicalDiskFormat format, Storage.ProvisioningType provisioningType, long size, byte[] passphrase) {
922-
String volPath = pool.getLocalPath() + "/" + name;
920+
private KVMPhysicalDisk createPhysicalDiskByQemuImg(String name, KVMStoragePool pool, PhysicalDiskFormat format, Storage.ProvisioningType provisioningType, long size,
921+
byte[] passphrase) {
922+
String volPath;
923923
String volName = name;
924924
long virtualSize = 0;
925925
long actualSize = 0;
926926
QemuObject.EncryptFormat encryptFormat = null;
927927
List<QemuObject> passphraseObjects = new ArrayList<>();
928-
929928
final int timeout = 0;
929+
QemuImgFile destFile;
930+
931+
if (StoragePoolType.RBD.equals(pool.getType())) {
932+
volPath = pool.getSourceDir() + "/" + name;
933+
destFile = new QemuImgFile(KVMPhysicalDisk.RBDStringBuilder(pool, volPath));
934+
} else {
935+
volPath = pool.getLocalPath();
936+
destFile = new QemuImgFile(volPath);
937+
}
930938

931-
QemuImgFile destFile = new QemuImgFile(volPath);
932939
destFile.setFormat(format);
933940
destFile.setSize(size);
934941
Map<String, String> options = new HashMap<String, String>();
@@ -1211,11 +1218,7 @@ private KVMPhysicalDisk createDiskFromTemplateOnRBD(KVMPhysicalDisk template,
12111218

12121219

12131220
QemuImgFile srcFile;
1214-
QemuImgFile destFile = new QemuImgFile(KVMPhysicalDisk.RBDStringBuilder(destPool.getSourceHost(),
1215-
destPool.getSourcePort(),
1216-
destPool.getAuthUserName(),
1217-
destPool.getAuthSecret(),
1218-
disk.getPath()));
1221+
QemuImgFile destFile = new QemuImgFile(KVMPhysicalDisk.RBDStringBuilder(destPool, disk.getPath()));
12191222
destFile.setFormat(format);
12201223

12211224
if (srcPool.getType() != StoragePoolType.RBD) {
@@ -1490,11 +1493,7 @@ to support snapshots(backuped) as qcow2 files. */
14901493
try {
14911494
srcFile = new QemuImgFile(sourcePath, sourceFormat);
14921495
String rbdDestPath = destPool.getSourceDir() + "/" + name;
1493-
String rbdDestFile = KVMPhysicalDisk.RBDStringBuilder(destPool.getSourceHost(),
1494-
destPool.getSourcePort(),
1495-
destPool.getAuthUserName(),
1496-
destPool.getAuthSecret(),
1497-
rbdDestPath);
1496+
String rbdDestFile = KVMPhysicalDisk.RBDStringBuilder(destPool, rbdDestPath);
14981497
destFile = new QemuImgFile(rbdDestFile, destFormat);
14991498

15001499
logger.debug("Starting copy from source image " + srcFile.getFileName() + " to RBD image " + rbdDestPath);
@@ -1537,9 +1536,7 @@ to support snapshots(backuped) as qcow2 files. */
15371536
We let Qemu-Img do the work here. Although we could work with librbd and have that do the cloning
15381537
it doesn't benefit us. It's better to keep the current code in place which works
15391538
*/
1540-
srcFile =
1541-
new QemuImgFile(KVMPhysicalDisk.RBDStringBuilder(srcPool.getSourceHost(), srcPool.getSourcePort(), srcPool.getAuthUserName(), srcPool.getAuthSecret(),
1542-
sourcePath));
1539+
srcFile = new QemuImgFile(KVMPhysicalDisk.RBDStringBuilder(srcPool, sourcePath));
15431540
srcFile.setFormat(sourceFormat);
15441541
destFile = new QemuImgFile(destPath);
15451542
destFile.setFormat(destFormat);

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/LibvirtStoragePool.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ public class LibvirtStoragePool implements KVMStoragePool {
5555
protected String authSecret;
5656
protected String sourceHost;
5757
protected int sourcePort;
58-
5958
protected String sourceDir;
59+
protected Map<String, String> details;
6060

6161
public LibvirtStoragePool(String uuid, String name, StoragePoolType type, StorageAdaptor adaptor, StoragePool pool) {
6262
this.uuid = uuid;
@@ -292,7 +292,11 @@ public boolean supportsConfigDriveIso() {
292292

293293
@Override
294294
public Map<String, String> getDetails() {
295-
return null;
295+
return this.details;
296+
}
297+
298+
public void setDetails(Map<String, String> details) {
299+
this.details = details;
296300
}
297301

298302
@Override

0 commit comments

Comments
 (0)