Skip to content

Commit 5b7c86a

Browse files
Merge remote-tracking branch 'origin/4.18' into 4.19
Signed-off-by: Rohit Yadav <[email protected]>
2 parents 22c6f08 + 896b8bf commit 5b7c86a

File tree

3 files changed

+87
-17
lines changed

3 files changed

+87
-17
lines changed

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

Lines changed: 62 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package com.cloud.hypervisor.kvm.storage;
1818

1919
import java.util.ArrayList;
20+
import java.util.Arrays;
2021
import java.util.Collections;
2122
import java.util.HashMap;
2223
import java.util.List;
@@ -47,6 +48,7 @@
4748
import com.linbit.linstor.api.model.Resource;
4849
import com.linbit.linstor.api.model.ResourceConnectionModify;
4950
import com.linbit.linstor.api.model.ResourceDefinition;
51+
import com.linbit.linstor.api.model.ResourceDefinitionModify;
5052
import com.linbit.linstor.api.model.ResourceGroupSpawn;
5153
import com.linbit.linstor.api.model.ResourceMakeAvailable;
5254
import com.linbit.linstor.api.model.ResourceWithVolumes;
@@ -231,6 +233,34 @@ public KVMPhysicalDisk createPhysicalDisk(String name, KVMStoragePool pool, Qemu
231233
}
232234
}
233235

236+
private void setAllowTwoPrimariesOnRD(DevelopersApi api, String rscName) throws ApiException {
237+
ResourceDefinitionModify rdm = new ResourceDefinitionModify();
238+
Properties props = new Properties();
239+
props.put("DrbdOptions/Net/allow-two-primaries", "yes");
240+
props.put("DrbdOptions/Net/protocol", "C");
241+
rdm.setOverrideProps(props);
242+
ApiCallRcList answers = api.resourceDefinitionModify(rscName, rdm);
243+
if (answers.hasError()) {
244+
s_logger.error(String.format("Unable to set protocol C and 'allow-two-primaries' on %s", rscName));
245+
// do not fail here as adding allow-two-primaries property is only a problem while live migrating
246+
}
247+
}
248+
249+
private void setAllowTwoPrimariesOnRc(DevelopersApi api, String rscName, String inUseNode) throws ApiException {
250+
ResourceConnectionModify rcm = new ResourceConnectionModify();
251+
Properties props = new Properties();
252+
props.put("DrbdOptions/Net/allow-two-primaries", "yes");
253+
props.put("DrbdOptions/Net/protocol", "C");
254+
rcm.setOverrideProps(props);
255+
ApiCallRcList answers = api.resourceConnectionModify(rscName, inUseNode, localNodeName, rcm);
256+
if (answers.hasError()) {
257+
s_logger.error(String.format(
258+
"Unable to set protocol C and 'allow-two-primaries' on %s/%s/%s",
259+
inUseNode, localNodeName, rscName));
260+
// do not fail here as adding allow-two-primaries property is only a problem while live migrating
261+
}
262+
}
263+
234264
/**
235265
* Checks if the given resource is in use by drbd on any host and
236266
* if so set the drbd option allow-two-primaries
@@ -242,17 +272,13 @@ private void allow2PrimariesIfInUse(DevelopersApi api, String rscName) throws Ap
242272
String inUseNode = LinstorUtil.isResourceInUse(api, rscName);
243273
if (inUseNode != null && !inUseNode.equalsIgnoreCase(localNodeName)) {
244274
// allow 2 primaries for live migration, should be removed by disconnect on the other end
245-
ResourceConnectionModify rcm = new ResourceConnectionModify();
246-
Properties props = new Properties();
247-
props.put("DrbdOptions/Net/allow-two-primaries", "yes");
248-
props.put("DrbdOptions/Net/protocol", "C");
249-
rcm.setOverrideProps(props);
250-
ApiCallRcList answers = api.resourceConnectionModify(rscName, inUseNode, localNodeName, rcm);
251-
if (answers.hasError()) {
252-
s_logger.error(String.format(
253-
"Unable to set protocol C and 'allow-two-primaries' on %s/%s/%s",
254-
inUseNode, localNodeName, rscName));
255-
// do not fail here as adding allow-two-primaries property is only a problem while live migrating
275+
276+
// if non hyperconverged setup, we have to set allow-two-primaries on the resource-definition
277+
// as there is no resource connection between diskless nodes.
278+
if (LinstorUtil.areResourcesDiskless(api, rscName, Arrays.asList(inUseNode, localNodeName))) {
279+
setAllowTwoPrimariesOnRD(api, rscName);
280+
} else {
281+
setAllowTwoPrimariesOnRc(api, rscName, inUseNode);
256282
}
257283
}
258284
}
@@ -291,11 +317,22 @@ public boolean connectPhysicalDisk(String volumePath, KVMStoragePool pool, Map<S
291317
return true;
292318
}
293319

294-
private void removeTwoPrimariesRcProps(DevelopersApi api, String inUseNode, String rscName) throws ApiException {
320+
private void removeTwoPrimariesRDProps(DevelopersApi api, String rscName, List<String> deleteProps)
321+
throws ApiException {
322+
ResourceDefinitionModify rdm = new ResourceDefinitionModify();
323+
rdm.deleteProps(deleteProps);
324+
ApiCallRcList answers = api.resourceDefinitionModify(rscName, rdm);
325+
if (answers.hasError()) {
326+
s_logger.error(
327+
String.format("Failed to remove 'protocol' and 'allow-two-primaries' on %s: %s",
328+
rscName, LinstorUtil.getBestErrorMessage(answers)));
329+
// do not fail here as removing allow-two-primaries property isn't fatal
330+
}
331+
}
332+
333+
private void removeTwoPrimariesRcProps(DevelopersApi api, String rscName, String inUseNode, List<String> deleteProps)
334+
throws ApiException {
295335
ResourceConnectionModify rcm = new ResourceConnectionModify();
296-
List<String> deleteProps = new ArrayList<>();
297-
deleteProps.add("DrbdOptions/Net/allow-two-primaries");
298-
deleteProps.add("DrbdOptions/Net/protocol");
299336
rcm.deleteProps(deleteProps);
300337
ApiCallRcList answers = api.resourceConnectionModify(rscName, localNodeName, inUseNode, rcm);
301338
if (answers.hasError()) {
@@ -308,6 +345,15 @@ private void removeTwoPrimariesRcProps(DevelopersApi api, String inUseNode, Stri
308345
}
309346
}
310347

348+
private void removeTwoPrimariesProps(DevelopersApi api, String inUseNode, String rscName) throws ApiException {
349+
List<String> deleteProps = new ArrayList<>();
350+
deleteProps.add("DrbdOptions/Net/allow-two-primaries");
351+
deleteProps.add("DrbdOptions/Net/protocol");
352+
353+
removeTwoPrimariesRDProps(api, rscName, deleteProps);
354+
removeTwoPrimariesRcProps(api, rscName, inUseNode, deleteProps);
355+
}
356+
311357
private boolean tryDisconnectLinstor(String volumePath, KVMStoragePool pool)
312358
{
313359
if (volumePath == null) {
@@ -341,7 +387,7 @@ private boolean tryDisconnectLinstor(String volumePath, KVMStoragePool pool)
341387
try {
342388
String inUseNode = LinstorUtil.isResourceInUse(api, rsc.getName());
343389
if (inUseNode != null && !inUseNode.equalsIgnoreCase(localNodeName)) {
344-
removeTwoPrimariesRcProps(api, inUseNode, rsc.getName());
390+
removeTwoPrimariesProps(api, inUseNode, rsc.getName());
345391
}
346392
} catch (ApiException apiEx) {
347393
s_logger.error(apiEx.getBestMessage());

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.apache.cloudstack.storage.datastore.util;
1818

1919
import com.linbit.linstor.api.ApiClient;
20+
import com.linbit.linstor.api.ApiConsts;
2021
import com.linbit.linstor.api.ApiException;
2122
import com.linbit.linstor.api.DevelopersApi;
2223
import com.linbit.linstor.api.model.ApiCallRc;
@@ -33,6 +34,7 @@
3334

3435
import javax.annotation.Nonnull;
3536

37+
import java.util.Collection;
3638
import java.util.Collections;
3739
import java.util.List;
3840
import java.util.stream.Collectors;
@@ -209,6 +211,28 @@ public static String isResourceInUse(DevelopersApi api, String rscName) throws A
209211
return null;
210212
}
211213

214+
/**
215+
* Check if the given resources are diskless.
216+
*
217+
* @param api developer api object to use
218+
* @param rscName resource name to check in use state.
219+
* @return NodeName where the resource is inUse, if not in use `null`
220+
* @throws ApiException forwards api errors
221+
*/
222+
public static boolean areResourcesDiskless(DevelopersApi api, String rscName, Collection<String> nodeNames)
223+
throws ApiException {
224+
List<Resource> rscs = api.resourceList(rscName, null, null);
225+
if (rscs != null) {
226+
Collection<String> disklessNodes = rscs.stream()
227+
.filter(rsc -> rsc.getFlags() != null && (rsc.getFlags().contains(ApiConsts.FLAG_DISKLESS) ||
228+
rsc.getFlags().contains(ApiConsts.FLAG_DRBD_DISKLESS)))
229+
.map(rsc -> rsc.getNodeName().toLowerCase())
230+
.collect(Collectors.toList());
231+
return disklessNodes.containsAll(nodeNames.stream().map(String::toLowerCase).collect(Collectors.toList()));
232+
}
233+
return false;
234+
}
235+
212236
/**
213237
* Try to get the device path for the given resource name.
214238
* This could be made a bit more direct after java-linstor api is fixed for layer data subtypes.

systemvm/debian/opt/cloud/bin/cs/CsFile.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,6 @@ def deleteLine(self, search):
174174
self.new_config = list(temp_config)
175175

176176
def compare(self, o):
177-
result = (isinstance(o, self.__class__) and set(self.config) == set(o.config))
177+
result = (isinstance(o, self.__class__) and self.config == o.config)
178178
logging.debug("Comparison of CsFiles content is ==> %s" % result)
179179
return result

0 commit comments

Comments
 (0)