Skip to content

Commit 2339412

Browse files
authored
linstor: make getDevicePath more robust (#9143)
1 parent c791c13 commit 2339412

File tree

3 files changed

+43
-42
lines changed

3 files changed

+43
-42
lines changed

plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -157,24 +157,12 @@ public KVMPhysicalDisk getPhysicalDisk(String name, KVMStoragePool pool)
157157
List<VolumeDefinition> volumeDefs = api.volumeDefinitionList(rscName, null, null);
158158
final long size = volumeDefs.isEmpty() ? 0 : volumeDefs.get(0).getSizeKib() * 1024;
159159

160-
List<ResourceWithVolumes> resources = api.viewResources(
161-
Collections.emptyList(),
162-
Collections.singletonList(rscName),
163-
Collections.emptyList(),
164-
null,
165-
null,
166-
null);
167-
if (!resources.isEmpty() && !resources.get(0).getVolumes().isEmpty()) {
168-
final String devPath = resources.get(0).getVolumes().get(0).getDevicePath();
169-
final KVMPhysicalDisk kvmDisk = new KVMPhysicalDisk(devPath, name, pool);
170-
kvmDisk.setFormat(QemuImg.PhysicalDiskFormat.RAW);
171-
kvmDisk.setSize(size);
172-
kvmDisk.setVirtualSize(size);
173-
return kvmDisk;
174-
} else {
175-
s_logger.error("Linstor: viewResources didn't return resources or volumes for " + rscName);
176-
throw new CloudRuntimeException("Linstor: viewResources didn't return resources or volumes.");
177-
}
160+
final String devicePath = LinstorUtil.getDevicePath(api, rscName);
161+
final KVMPhysicalDisk kvmDisk = new KVMPhysicalDisk(devicePath, name, pool);
162+
kvmDisk.setFormat(QemuImg.PhysicalDiskFormat.RAW);
163+
kvmDisk.setSize(size);
164+
kvmDisk.setVirtualSize(size);
165+
return kvmDisk;
178166
} catch (ApiException apiEx) {
179167
s_logger.error(apiEx);
180168
throw new CloudRuntimeException(apiEx.getBestMessage(), apiEx);

plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/driver/LinstorPrimaryDataStoreDriverImpl.java

Lines changed: 3 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
import com.linbit.linstor.api.model.ResourceDefinitionCreate;
2929
import com.linbit.linstor.api.model.ResourceDefinitionModify;
3030
import com.linbit.linstor.api.model.ResourceGroupSpawn;
31-
import com.linbit.linstor.api.model.ResourceWithVolumes;
3231
import com.linbit.linstor.api.model.Snapshot;
3332
import com.linbit.linstor.api.model.SnapshotRestore;
3433
import com.linbit.linstor.api.model.VolumeDefinition;
@@ -38,7 +37,6 @@
3837
import javax.inject.Inject;
3938

4039
import java.util.Arrays;
41-
import java.util.Collections;
4240
import java.util.HashMap;
4341
import java.util.List;
4442
import java.util.Map;
@@ -315,25 +313,6 @@ private String checkLinstorAnswers(@Nonnull ApiCallRcList answers) {
315313
return answers.stream().filter(ApiCallRc::isError).findFirst().map(ApiCallRc::getMessage).orElse(null);
316314
}
317315

318-
private String getDeviceName(DevelopersApi linstorApi, String rscName) throws ApiException {
319-
List<ResourceWithVolumes> resources = linstorApi.viewResources(
320-
Collections.emptyList(),
321-
Collections.singletonList(rscName),
322-
Collections.emptyList(),
323-
null,
324-
null,
325-
null);
326-
if (!resources.isEmpty() && !resources.get(0).getVolumes().isEmpty())
327-
{
328-
s_logger.info("Linstor: Created drbd device: " + resources.get(0).getVolumes().get(0).getDevicePath());
329-
return resources.get(0).getVolumes().get(0).getDevicePath();
330-
} else
331-
{
332-
s_logger.error("Linstor: viewResources didn't return resources or volumes.");
333-
throw new CloudRuntimeException("Linstor: viewResources didn't return resources or volumes.");
334-
}
335-
}
336-
337316
private void applyQoSSettings(StoragePoolVO storagePool, DevelopersApi api, String rscName, Long maxIops)
338317
throws ApiException
339318
{
@@ -420,7 +399,7 @@ private String createResource(VolumeInfo vol, StoragePoolVO storagePoolVO)
420399
applyAuxProps(linstorApi, rscName, vol.getName(), vol.getAttachedVmName());
421400
applyQoSSettings(storagePoolVO, linstorApi, rscName, vol.getMaxIops());
422401

423-
return getDeviceName(linstorApi, rscName);
402+
return LinstorUtil.getDevicePath(linstorApi, rscName);
424403
} catch (ApiException apiEx)
425404
{
426405
s_logger.error("Linstor: ApiEx - " + apiEx.getMessage());
@@ -473,7 +452,7 @@ private String cloneResource(long csCloneId, VolumeInfo volumeInfo, StoragePoolV
473452
applyAuxProps(linstorApi, rscName, volumeInfo.getName(), volumeInfo.getAttachedVmName());
474453
applyQoSSettings(storagePoolVO, linstorApi, rscName, volumeInfo.getMaxIops());
475454

476-
return getDeviceName(linstorApi, rscName);
455+
return LinstorUtil.getDevicePath(linstorApi, rscName);
477456
} catch (ApiException apiEx) {
478457
s_logger.error("Linstor: ApiEx - " + apiEx.getMessage());
479458
throw new CloudRuntimeException(apiEx.getBestMessage(), apiEx);
@@ -520,7 +499,7 @@ private String createResourceFromSnapshot(long csSnapshotId, String rscName, Sto
520499
applyAuxProps(linstorApi, rscName, volumeVO.getName(), null);
521500
applyQoSSettings(storagePoolVO, linstorApi, rscName, volumeVO.getMaxIops());
522501

523-
return getDeviceName(linstorApi, rscName);
502+
return LinstorUtil.getDevicePath(linstorApi, rscName);
524503
} catch (ApiException apiEx) {
525504
s_logger.error("Linstor: ApiEx - " + apiEx.getMessage());
526505
throw new CloudRuntimeException(apiEx.getBestMessage(), apiEx);

plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/util/LinstorUtil.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import com.linbit.linstor.api.model.ProviderKind;
2626
import com.linbit.linstor.api.model.Resource;
2727
import com.linbit.linstor.api.model.ResourceGroup;
28+
import com.linbit.linstor.api.model.ResourceWithVolumes;
2829
import com.linbit.linstor.api.model.StoragePool;
2930

3031
import java.util.Collections;
@@ -109,4 +110,37 @@ public static boolean isResourceInUse(DevelopersApi api, String rscName) throws
109110
s_logger.error("isResourceInUse: null returned from resourceList");
110111
return false;
111112
}
113+
114+
/**
115+
* Try to get the device path for the given resource name.
116+
* This could be made a bit more direct after java-linstor api is fixed for layer data subtypes.
117+
* @param api developer api object to use
118+
* @param rscName resource name to get the device path
119+
* @return The device path of the resource.
120+
* @throws ApiException if Linstor API call failed.
121+
* @throws CloudRuntimeException if no device path could be found.
122+
*/
123+
public static String getDevicePath(DevelopersApi api, String rscName) throws ApiException, CloudRuntimeException {
124+
List<ResourceWithVolumes> resources = api.viewResources(
125+
Collections.emptyList(),
126+
Collections.singletonList(rscName),
127+
Collections.emptyList(),
128+
null,
129+
null,
130+
null);
131+
for (ResourceWithVolumes rsc : resources) {
132+
if (!rsc.getVolumes().isEmpty()) {
133+
// CloudStack resource always only have 1 volume
134+
String devicePath = rsc.getVolumes().get(0).getDevicePath();
135+
if (devicePath != null && !devicePath.isEmpty()) {
136+
s_logger.debug(String.format("getDevicePath: %s -> %s", rscName, devicePath));
137+
return devicePath;
138+
}
139+
}
140+
}
141+
142+
final String errMsg = "viewResources didn't return resources or volumes for " + rscName;
143+
s_logger.error(errMsg);
144+
throw new CloudRuntimeException("Linstor: " + errMsg);
145+
}
112146
}

0 commit comments

Comments
 (0)