Skip to content

Commit fd0f2c5

Browse files
rp-dhslove
authored andcommitted
Linstor fix migration while node offline (apache#8610)
* linstor: Add util method getBestErrorMessage from main * linstor: failed remove of allow-two-primaries is no fatal error * linstor: Fix failure if a Linstor node is down while migrating If a Linstor node is down while migrating resource, allow-two-primaries setting will fail because we can't reach the downed node. But it will still set the property on the other nodes and migration should work. We now just report an error instead of completely failing.
1 parent 7e8c6c9 commit fd0f2c5

2 files changed

Lines changed: 36 additions & 21 deletions

File tree

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

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -276,27 +276,35 @@ public boolean connectPhysicalDisk(String volumePath, KVMStoragePool pool, Map<S
276276
}
277277

278278
final DevelopersApi api = getLinstorAPI(pool);
279+
String rscName;
279280
try
280281
{
281-
final String rscName = getLinstorRscName(volumePath);
282+
rscName = getLinstorRscName(volumePath);
282283

283284
ResourceMakeAvailable rma = new ResourceMakeAvailable();
284285
ApiCallRcList answers = api.resourceMakeAvailableOnNode(rscName, localNodeName, rma);
285286
checkLinstorAnswersThrow(answers);
286287

288+
} catch (ApiException apiEx) {
289+
logger.error(apiEx);
290+
throw new CloudRuntimeException(apiEx.getBestMessage(), apiEx);
291+
}
292+
293+
try
294+
{
287295
// allow 2 primaries for live migration, should be removed by disconnect on the other end
288296
ResourceDefinitionModify rdm = new ResourceDefinitionModify();
289297
Properties props = new Properties();
290298
props.put("DrbdOptions/Net/allow-two-primaries", "yes");
291299
rdm.setOverrideProps(props);
292-
answers = api.resourceDefinitionModify(rscName, rdm);
300+
ApiCallRcList answers = api.resourceDefinitionModify(rscName, rdm);
293301
if (answers.hasError()) {
294302
logger.error("Unable to set 'allow-two-primaries' on " + rscName);
295-
throw new CloudRuntimeException(answers.get(0).getMessage());
303+
// do not fail here as adding allow-two-primaries property is only a problem while live migrating
296304
}
297305
} catch (ApiException apiEx) {
298306
logger.error(apiEx);
299-
throw new CloudRuntimeException(apiEx.getBestMessage(), apiEx);
307+
// do not fail here as adding allow-two-primaries property is only a problem while live migrating
300308
}
301309
return true;
302310
}
@@ -360,19 +368,21 @@ public boolean disconnectPhysicalDiskByPath(String localPath)
360368
ApiCallRcList answers = api.resourceDefinitionModify(rsc.get().getName(), rdm);
361369
if (answers.hasError())
362370
{
363-
logger.error("Failed to remove 'allow-two-primaries' on " + rsc.get().getName());
364-
throw new CloudRuntimeException(answers.get(0).getMessage());
371+
logger.error(
372+
String.format("Failed to remove 'allow-two-primaries' on %s: %s",
373+
rsc.get().getName(), LinstorUtil.getBestErrorMessage(answers)));
374+
// do not fail here as removing allow-two-primaries property isn't fatal
365375
}
366376

367377
return true;
368378
}
369379
logger.warn("Linstor: Couldn't find resource for this path: " + localPath);
370380
} catch (ApiException apiEx) {
371-
logger.error(apiEx);
372-
throw new CloudRuntimeException(apiEx.getBestMessage(), apiEx);
381+
logger.error(apiEx.getBestMessage());
382+
// do not fail here as removing allow-two-primaries property isn't fatal
373383
}
374384
}
375-
return false;
385+
return true;
376386
}
377387

378388
@Override

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

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -137,28 +137,33 @@ public static String getSnapshotPath(com.linbit.linstor.api.model.StoragePool sp
137137
return path;
138138
}
139139

140-
public static long getCapacityBytes(String linstorUrl, String rscGroupName) {
141-
DevelopersApi linstorApi = getLinstorAPI(linstorUrl);
142-
try {
143-
List<ResourceGroup> rscGrps = linstorApi.resourceGroupList(
140+
public static List<StoragePool> getRscGroupStoragePools(DevelopersApi api, String rscGroupName)
141+
throws ApiException {
142+
List<ResourceGroup> rscGrps = api.resourceGroupList(
144143
Collections.singletonList(rscGroupName),
145144
null,
146145
null,
147146
null);
148147

149-
if (rscGrps.isEmpty()) {
150-
final String errMsg = String.format("Linstor: Resource group '%s' not found", rscGroupName);
151-
LOGGER.error(errMsg);
152-
throw new CloudRuntimeException(errMsg);
153-
}
148+
if (rscGrps.isEmpty()) {
149+
final String errMsg = String.format("Linstor: Resource group '%s' not found", rscGroupName);
150+
LOGGER.error(errMsg);
151+
throw new CloudRuntimeException(errMsg);
152+
}
154153

155-
List<StoragePool> storagePools = linstorApi.viewStoragePools(
154+
return api.viewStoragePools(
156155
Collections.emptyList(),
157156
rscGrps.get(0).getSelectFilter().getStoragePoolList(),
158157
null,
159158
null,
160159
null
161-
);
160+
);
161+
}
162+
163+
public static long getCapacityBytes(String linstorUrl, String rscGroupName) {
164+
DevelopersApi linstorApi = getLinstorAPI(linstorUrl);
165+
try {
166+
List<StoragePool> storagePools = getRscGroupStoragePools(linstorApi, rscGroupName);
162167

163168
return storagePools.stream()
164169
.filter(sp -> sp.getProviderKind() != ProviderKind.DISKLESS)
@@ -169,4 +174,4 @@ public static long getCapacityBytes(String linstorUrl, String rscGroupName) {
169174
throw new CloudRuntimeException(apiEx);
170175
}
171176
}
172-
}
177+
}

0 commit comments

Comments
 (0)