Skip to content

Commit a851ee3

Browse files
committed
Merge remote-tracking branch 'origin/4.18' into 4.19
Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>
2 parents 601e9b6 + 537c0a1 commit a851ee3

File tree

3 files changed

+59
-23
lines changed

3 files changed

+59
-23
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Changelog
2+
3+
All notable changes to Linstor CloudStack plugin will be documented in this file.
4+
5+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7+
8+
## [2024-08-27]
9+
10+
### Changed
11+
12+
- Allow two primaries(+protocol c) is now set on resource-connection level instead of rd

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

Lines changed: 39 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
// under the License.
1717
package com.cloud.hypervisor.kvm.storage;
1818

19+
import java.util.ArrayList;
1920
import java.util.Collections;
2021
import java.util.HashMap;
2122
import java.util.List;
@@ -26,6 +27,7 @@
2627

2728
import com.cloud.storage.Storage;
2829
import com.cloud.utils.exception.CloudRuntimeException;
30+
2931
import org.apache.cloudstack.storage.datastore.util.LinstorUtil;
3032
import org.apache.cloudstack.utils.qemu.QemuImg;
3133
import org.apache.cloudstack.utils.qemu.QemuImgException;
@@ -43,8 +45,8 @@
4345
import com.linbit.linstor.api.model.Properties;
4446
import com.linbit.linstor.api.model.ProviderKind;
4547
import com.linbit.linstor.api.model.Resource;
48+
import com.linbit.linstor.api.model.ResourceConnectionModify;
4649
import com.linbit.linstor.api.model.ResourceDefinition;
47-
import com.linbit.linstor.api.model.ResourceDefinitionModify;
4850
import com.linbit.linstor.api.model.ResourceGroupSpawn;
4951
import com.linbit.linstor.api.model.ResourceMakeAvailable;
5052
import com.linbit.linstor.api.model.ResourceWithVolumes;
@@ -237,15 +239,19 @@ public KVMPhysicalDisk createPhysicalDisk(String name, KVMStoragePool pool, Qemu
237239
* @throws ApiException if any problem connecting to the Linstor controller
238240
*/
239241
private void allow2PrimariesIfInUse(DevelopersApi api, String rscName) throws ApiException {
240-
if (LinstorUtil.isResourceInUse(api, rscName)) {
242+
String inUseNode = LinstorUtil.isResourceInUse(api, rscName);
243+
if (inUseNode != null && !inUseNode.equalsIgnoreCase(localNodeName)) {
241244
// allow 2 primaries for live migration, should be removed by disconnect on the other end
242-
ResourceDefinitionModify rdm = new ResourceDefinitionModify();
245+
ResourceConnectionModify rcm = new ResourceConnectionModify();
243246
Properties props = new Properties();
244247
props.put("DrbdOptions/Net/allow-two-primaries", "yes");
245-
rdm.setOverrideProps(props);
246-
ApiCallRcList answers = api.resourceDefinitionModify(rscName, rdm);
248+
props.put("DrbdOptions/Net/protocol", "C");
249+
rcm.setOverrideProps(props);
250+
ApiCallRcList answers = api.resourceConnectionModify(rscName, inUseNode, localNodeName, rcm);
247251
if (answers.hasError()) {
248-
s_logger.error("Unable to set 'allow-two-primaries' on " + rscName);
252+
s_logger.error(String.format(
253+
"Unable to set protocol C and 'allow-two-primaries' on %s/%s/%s",
254+
inUseNode, localNodeName, rscName));
249255
// do not fail here as adding allow-two-primaries property is only a problem while live migrating
250256
}
251257
}
@@ -285,6 +291,23 @@ public boolean connectPhysicalDisk(String volumePath, KVMStoragePool pool, Map<S
285291
return true;
286292
}
287293

294+
private void removeTwoPrimariesRcProps(DevelopersApi api, String inUseNode, String rscName) throws ApiException {
295+
ResourceConnectionModify rcm = new ResourceConnectionModify();
296+
List<String> deleteProps = new ArrayList<>();
297+
deleteProps.add("DrbdOptions/Net/allow-two-primaries");
298+
deleteProps.add("DrbdOptions/Net/protocol");
299+
rcm.deleteProps(deleteProps);
300+
ApiCallRcList answers = api.resourceConnectionModify(rscName, localNodeName, inUseNode, rcm);
301+
if (answers.hasError()) {
302+
s_logger.error(
303+
String.format("Failed to remove 'protocol' and 'allow-two-primaries' on %s/%s/%s: %s",
304+
localNodeName,
305+
inUseNode,
306+
rscName, LinstorUtil.getBestErrorMessage(answers)));
307+
// do not fail here as removing allow-two-primaries property isn't fatal
308+
}
309+
}
310+
288311
private boolean tryDisconnectLinstor(String volumePath, KVMStoragePool pool)
289312
{
290313
if (volumePath == null) {
@@ -314,27 +337,25 @@ private boolean tryDisconnectLinstor(String volumePath, KVMStoragePool pool)
314337

315338

316339
if (optRsc.isPresent()) {
340+
Resource rsc = optRsc.get();
317341
try {
318-
Resource rsc = optRsc.get();
342+
String inUseNode = LinstorUtil.isResourceInUse(api, rsc.getName());
343+
if (inUseNode != null && !inUseNode.equalsIgnoreCase(localNodeName)) {
344+
removeTwoPrimariesRcProps(api, inUseNode, rsc.getName());
345+
}
346+
} catch (ApiException apiEx) {
347+
s_logger.error(apiEx.getBestMessage());
348+
// do not fail here as removing allow-two-primaries property or deleting diskless isn't fatal
349+
}
319350

351+
try {
320352
// if diskless resource remove it, in the worst case it will be transformed to a tiebreaker
321353
if (rsc.getFlags() != null &&
322354
rsc.getFlags().contains(ApiConsts.FLAG_DRBD_DISKLESS) &&
323355
!rsc.getFlags().contains(ApiConsts.FLAG_TIE_BREAKER)) {
324356
ApiCallRcList delAnswers = api.resourceDelete(rsc.getName(), localNodeName);
325357
logLinstorAnswers(delAnswers);
326358
}
327-
328-
// remove allow-two-primaries
329-
ResourceDefinitionModify rdm = new ResourceDefinitionModify();
330-
rdm.deleteProps(Collections.singletonList("DrbdOptions/Net/allow-two-primaries"));
331-
ApiCallRcList answers = api.resourceDefinitionModify(rsc.getName(), rdm);
332-
if (answers.hasError()) {
333-
s_logger.error(
334-
String.format("Failed to remove 'allow-two-primaries' on %s: %s",
335-
rsc.getName(), LinstorUtil.getBestErrorMessage(answers)));
336-
// do not fail here as removing allow-two-primaries property isn't fatal
337-
}
338359
} catch (ApiException apiEx) {
339360
s_logger.error(apiEx.getBestMessage());
340361
// do not fail here as removing allow-two-primaries property or deleting diskless isn't fatal

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

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -191,17 +191,20 @@ public static long getCapacityBytes(String linstorUrl, String rscGroupName) {
191191
*
192192
* @param api developer api object to use
193193
* @param rscName resource name to check in use state.
194-
* @return True if a resource found that is in use(primary) state, else false.
194+
* @return NodeName where the resource is inUse, if not in use `null`
195195
* @throws ApiException forwards api errors
196196
*/
197-
public static boolean isResourceInUse(DevelopersApi api, String rscName) throws ApiException {
197+
public static String isResourceInUse(DevelopersApi api, String rscName) throws ApiException {
198198
List<Resource> rscs = api.resourceList(rscName, null, null);
199199
if (rscs != null) {
200200
return rscs.stream()
201-
.anyMatch(rsc -> rsc.getState() != null && Boolean.TRUE.equals(rsc.getState().isInUse()));
202-
}
201+
.filter(rsc -> rsc.getState() != null && Boolean.TRUE.equals(rsc.getState().isInUse()))
202+
.map(Resource::getNodeName)
203+
.findFirst()
204+
.orElse(null);
205+
}
203206
s_logger.error("isResourceInUse: null returned from resourceList");
204-
return false;
207+
return null;
205208
}
206209

207210
/**

0 commit comments

Comments
 (0)