Skip to content

Commit 66c39c1

Browse files
authored
storage: Linstor volume plugin (#4994)
This adds a volume(primary) storage plugin for the Linstor SDS. Currently it can create/delete/migrate volumes, snapshots should be possible, but currently don't work for RAW volume types in cloudstack. * plugin-storage-volume-linstor: notify libvirt guests about the resize
1 parent 1bf6862 commit 66c39c1

File tree

31 files changed

+3585
-48
lines changed

31 files changed

+3585
-48
lines changed

api/src/main/java/com/cloud/storage/Storage.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ public static enum StoragePoolType {
147147
Gluster(true, false),
148148
PowerFlex(true, true), // Dell EMC PowerFlex/ScaleIO (formerly VxFlexOS)
149149
ManagedNFS(true, false),
150+
Linstor(true, true),
150151
DatastoreCluster(true, true); // for VMware, to abstract pool of clusters
151152

152153
private final boolean shared;

api/src/test/java/com/cloud/storage/StorageTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ public void isSharedStoragePool() {
4848
Assert.assertTrue(StoragePoolType.Gluster.isShared());
4949
Assert.assertTrue(StoragePoolType.ManagedNFS.isShared());
5050
Assert.assertTrue(StoragePoolType.DatastoreCluster.isShared());
51+
Assert.assertTrue(StoragePoolType.Linstor.isShared());
5152
}
5253

5354
@Test
@@ -71,5 +72,6 @@ public void supportsOverprovisioningStoragePool() {
7172
Assert.assertFalse(StoragePoolType.Gluster.supportsOverProvisioning());
7273
Assert.assertFalse(StoragePoolType.ManagedNFS.supportsOverProvisioning());
7374
Assert.assertTrue(StoragePoolType.DatastoreCluster.supportsOverProvisioning());
75+
Assert.assertTrue(StoragePoolType.Linstor.supportsOverProvisioning());
7476
}
7577
}

client/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,11 @@
9292
<artifactId>cloud-plugin-storage-volume-scaleio</artifactId>
9393
<version>${project.version}</version>
9494
</dependency>
95+
<dependency>
96+
<groupId>org.apache.cloudstack</groupId>
97+
<artifactId>cloud-plugin-storage-volume-linstor</artifactId>
98+
<version>${project.version}</version>
99+
</dependency>
95100
<dependency>
96101
<groupId>org.apache.cloudstack</groupId>
97102
<artifactId>cloud-server</artifactId>

engine/storage/integration-test/pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,12 @@
9999
<version>${project.version}</version>
100100
<scope>test</scope>
101101
</dependency>
102+
<dependency>
103+
<groupId>org.apache.cloudstack</groupId>
104+
<artifactId>cloud-plugin-storage-volume-linstor</artifactId>
105+
<version>${project.version}</version>
106+
<scope>test</scope>
107+
</dependency>
102108
<dependency>
103109
<groupId>org.apache.cloudstack</groupId>
104110
<artifactId>cloud-secondary-storage</artifactId>

plugins/hypervisors/kvm/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,11 @@
6262
<artifactId>rados</artifactId>
6363
<version>${cs.rados-java.version}</version>
6464
</dependency>
65+
<dependency>
66+
<groupId>com.linbit.linstor.api</groupId>
67+
<artifactId>java-linstor</artifactId>
68+
<version>${cs.java-linstor.version}</version>
69+
</dependency>
6570
<dependency>
6671
<groupId>net.java.dev.jna</groupId>
6772
<artifactId>jna</artifactId>

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,8 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
279279
*/
280280
private static final String AARCH64 = "aarch64";
281281

282+
public static final String RESIZE_NOTIFY_ONLY = "NOTIFYONLY";
283+
282284
private String _modifyVlanPath;
283285
private String _versionstringpath;
284286
private String _patchScriptPath;
@@ -1910,6 +1912,8 @@ public String getResizeScriptType(final KVMStoragePool pool, final KVMPhysicalDi
19101912
|| poolType == StoragePoolType.Gluster)
19111913
&& volFormat == PhysicalDiskFormat.QCOW2 ) {
19121914
return "QCOW2";
1915+
} else if (poolType == StoragePoolType.Linstor) {
1916+
return RESIZE_NOTIFY_ONLY;
19131917
}
19141918
throw new CloudRuntimeException("Cannot determine resize type from pool type " + pool.getType());
19151919
}

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public Answer execute(final ResizeVolumeCommand command, final LibvirtComputingR
5757
final String vmInstanceName = command.getInstanceName();
5858
final boolean shrinkOk = command.getShrinkOk();
5959
final StorageFilerTO spool = command.getPool();
60-
final String notifyOnlyType = "NOTIFYONLY";
60+
final String notifyOnlyType = LibvirtComputingResource.RESIZE_NOTIFY_ONLY;
6161

6262
if ( currentSize == newSize) {
6363
// nothing to do
@@ -73,19 +73,20 @@ public Answer execute(final ResizeVolumeCommand command, final LibvirtComputingR
7373
final String path = vol.getPath();
7474
String type = notifyOnlyType;
7575

76-
if (pool.getType() != StoragePoolType.RBD) {
76+
if (pool.getType() != StoragePoolType.RBD && pool.getType() != StoragePoolType.Linstor) {
7777
type = libvirtComputingResource.getResizeScriptType(pool, vol);
7878
if (type.equals("QCOW2") && shrinkOk) {
7979
return new ResizeVolumeAnswer(command, false, "Unable to shrink volumes of type " + type);
8080
}
8181
} else {
82-
s_logger.debug("Volume " + path + " is on a RBD storage pool. No need to query for additional information.");
82+
s_logger.debug("Volume " + path + " is on a RBD/Linstor storage pool. No need to query for additional information.");
8383
}
8484

8585
s_logger.debug("Resizing volume: " + path + ", from: " + toHumanReadableSize(currentSize) + ", to: " + toHumanReadableSize(newSize) + ", type: " + type + ", name: " + vmInstanceName + ", shrinkOk: " + shrinkOk);
8686

8787
/* libvirt doesn't support resizing (C)LVM devices, and corrupts QCOW2 in some scenarios, so we have to do these via Bash script */
88-
if (pool.getType() != StoragePoolType.CLVM && vol.getFormat() != PhysicalDiskFormat.QCOW2) {
88+
if (pool.getType() != StoragePoolType.CLVM && pool.getType() != StoragePoolType.Linstor &&
89+
vol.getFormat() != PhysicalDiskFormat.QCOW2) {
8990
s_logger.debug("Volume " + path + " can be resized by libvirt. Asking libvirt to resize the volume.");
9091
try {
9192
final LibvirtUtilitiesHelper libvirtUtilitiesHelper = libvirtComputingResource.getLibvirtUtilitiesHelper();

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ public KVMPhysicalDisk createDiskFromTemplate(KVMPhysicalDisk template, String n
378378
return adaptor.createDiskFromTemplate(template, name,
379379
PhysicalDiskFormat.DIR, provisioningType,
380380
size, destPool, timeout);
381-
} else if (destPool.getType() == StoragePoolType.PowerFlex) {
381+
} else if (destPool.getType() == StoragePoolType.PowerFlex || destPool.getType() == StoragePoolType.Linstor) {
382382
return adaptor.createDiskFromTemplate(template, name,
383383
PhysicalDiskFormat.RAW, provisioningType,
384384
size, destPool, timeout);

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,9 @@ public Answer copyTemplateToPrimaryStorage(final CopyCommand cmd) {
282282
final TemplateObjectTO newTemplate = new TemplateObjectTO();
283283
newTemplate.setPath(primaryVol.getName());
284284
newTemplate.setSize(primaryVol.getSize());
285-
if (primaryPool.getType() == StoragePoolType.RBD || primaryPool.getType() == StoragePoolType.PowerFlex) {
285+
if (primaryPool.getType() == StoragePoolType.RBD ||
286+
primaryPool.getType() == StoragePoolType.PowerFlex ||
287+
primaryPool.getType() == StoragePoolType.Linstor) {
286288
newTemplate.setFormat(ImageFormat.RAW);
287289
} else {
288290
newTemplate.setFormat(ImageFormat.QCOW2);

0 commit comments

Comments
 (0)