mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
Merge remote-tracking branch 'origin/4.18' into 4.19
Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>
This commit is contained in:
commit
a851ee375c
12
plugins/storage/volume/linstor/CHANGELOG.md
Normal file
12
plugins/storage/volume/linstor/CHANGELOG.md
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
All notable changes to Linstor CloudStack plugin will be documented in this file.
|
||||||
|
|
||||||
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [2024-08-27]
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Allow two primaries(+protocol c) is now set on resource-connection level instead of rd
|
||||||
@ -16,6 +16,7 @@
|
|||||||
// under the License.
|
// under the License.
|
||||||
package com.cloud.hypervisor.kvm.storage;
|
package com.cloud.hypervisor.kvm.storage;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -26,6 +27,7 @@ import javax.annotation.Nonnull;
|
|||||||
|
|
||||||
import com.cloud.storage.Storage;
|
import com.cloud.storage.Storage;
|
||||||
import com.cloud.utils.exception.CloudRuntimeException;
|
import com.cloud.utils.exception.CloudRuntimeException;
|
||||||
|
|
||||||
import org.apache.cloudstack.storage.datastore.util.LinstorUtil;
|
import org.apache.cloudstack.storage.datastore.util.LinstorUtil;
|
||||||
import org.apache.cloudstack.utils.qemu.QemuImg;
|
import org.apache.cloudstack.utils.qemu.QemuImg;
|
||||||
import org.apache.cloudstack.utils.qemu.QemuImgException;
|
import org.apache.cloudstack.utils.qemu.QemuImgException;
|
||||||
@ -43,8 +45,8 @@ import com.linbit.linstor.api.model.ApiCallRcList;
|
|||||||
import com.linbit.linstor.api.model.Properties;
|
import com.linbit.linstor.api.model.Properties;
|
||||||
import com.linbit.linstor.api.model.ProviderKind;
|
import com.linbit.linstor.api.model.ProviderKind;
|
||||||
import com.linbit.linstor.api.model.Resource;
|
import com.linbit.linstor.api.model.Resource;
|
||||||
|
import com.linbit.linstor.api.model.ResourceConnectionModify;
|
||||||
import com.linbit.linstor.api.model.ResourceDefinition;
|
import com.linbit.linstor.api.model.ResourceDefinition;
|
||||||
import com.linbit.linstor.api.model.ResourceDefinitionModify;
|
|
||||||
import com.linbit.linstor.api.model.ResourceGroupSpawn;
|
import com.linbit.linstor.api.model.ResourceGroupSpawn;
|
||||||
import com.linbit.linstor.api.model.ResourceMakeAvailable;
|
import com.linbit.linstor.api.model.ResourceMakeAvailable;
|
||||||
import com.linbit.linstor.api.model.ResourceWithVolumes;
|
import com.linbit.linstor.api.model.ResourceWithVolumes;
|
||||||
@ -237,15 +239,19 @@ public class LinstorStorageAdaptor implements StorageAdaptor {
|
|||||||
* @throws ApiException if any problem connecting to the Linstor controller
|
* @throws ApiException if any problem connecting to the Linstor controller
|
||||||
*/
|
*/
|
||||||
private void allow2PrimariesIfInUse(DevelopersApi api, String rscName) throws ApiException {
|
private void allow2PrimariesIfInUse(DevelopersApi api, String rscName) throws ApiException {
|
||||||
if (LinstorUtil.isResourceInUse(api, rscName)) {
|
String inUseNode = LinstorUtil.isResourceInUse(api, rscName);
|
||||||
|
if (inUseNode != null && !inUseNode.equalsIgnoreCase(localNodeName)) {
|
||||||
// allow 2 primaries for live migration, should be removed by disconnect on the other end
|
// allow 2 primaries for live migration, should be removed by disconnect on the other end
|
||||||
ResourceDefinitionModify rdm = new ResourceDefinitionModify();
|
ResourceConnectionModify rcm = new ResourceConnectionModify();
|
||||||
Properties props = new Properties();
|
Properties props = new Properties();
|
||||||
props.put("DrbdOptions/Net/allow-two-primaries", "yes");
|
props.put("DrbdOptions/Net/allow-two-primaries", "yes");
|
||||||
rdm.setOverrideProps(props);
|
props.put("DrbdOptions/Net/protocol", "C");
|
||||||
ApiCallRcList answers = api.resourceDefinitionModify(rscName, rdm);
|
rcm.setOverrideProps(props);
|
||||||
|
ApiCallRcList answers = api.resourceConnectionModify(rscName, inUseNode, localNodeName, rcm);
|
||||||
if (answers.hasError()) {
|
if (answers.hasError()) {
|
||||||
s_logger.error("Unable to set 'allow-two-primaries' on " + rscName);
|
s_logger.error(String.format(
|
||||||
|
"Unable to set protocol C and 'allow-two-primaries' on %s/%s/%s",
|
||||||
|
inUseNode, localNodeName, rscName));
|
||||||
// do not fail here as adding allow-two-primaries property is only a problem while live migrating
|
// do not fail here as adding allow-two-primaries property is only a problem while live migrating
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -285,6 +291,23 @@ public class LinstorStorageAdaptor implements StorageAdaptor {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void removeTwoPrimariesRcProps(DevelopersApi api, String inUseNode, String rscName) throws ApiException {
|
||||||
|
ResourceConnectionModify rcm = new ResourceConnectionModify();
|
||||||
|
List<String> deleteProps = new ArrayList<>();
|
||||||
|
deleteProps.add("DrbdOptions/Net/allow-two-primaries");
|
||||||
|
deleteProps.add("DrbdOptions/Net/protocol");
|
||||||
|
rcm.deleteProps(deleteProps);
|
||||||
|
ApiCallRcList answers = api.resourceConnectionModify(rscName, localNodeName, inUseNode, rcm);
|
||||||
|
if (answers.hasError()) {
|
||||||
|
s_logger.error(
|
||||||
|
String.format("Failed to remove 'protocol' and 'allow-two-primaries' on %s/%s/%s: %s",
|
||||||
|
localNodeName,
|
||||||
|
inUseNode,
|
||||||
|
rscName, LinstorUtil.getBestErrorMessage(answers)));
|
||||||
|
// do not fail here as removing allow-two-primaries property isn't fatal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private boolean tryDisconnectLinstor(String volumePath, KVMStoragePool pool)
|
private boolean tryDisconnectLinstor(String volumePath, KVMStoragePool pool)
|
||||||
{
|
{
|
||||||
if (volumePath == null) {
|
if (volumePath == null) {
|
||||||
@ -314,9 +337,18 @@ public class LinstorStorageAdaptor implements StorageAdaptor {
|
|||||||
|
|
||||||
|
|
||||||
if (optRsc.isPresent()) {
|
if (optRsc.isPresent()) {
|
||||||
|
Resource rsc = optRsc.get();
|
||||||
try {
|
try {
|
||||||
Resource rsc = optRsc.get();
|
String inUseNode = LinstorUtil.isResourceInUse(api, rsc.getName());
|
||||||
|
if (inUseNode != null && !inUseNode.equalsIgnoreCase(localNodeName)) {
|
||||||
|
removeTwoPrimariesRcProps(api, inUseNode, rsc.getName());
|
||||||
|
}
|
||||||
|
} catch (ApiException apiEx) {
|
||||||
|
s_logger.error(apiEx.getBestMessage());
|
||||||
|
// do not fail here as removing allow-two-primaries property or deleting diskless isn't fatal
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
// if diskless resource remove it, in the worst case it will be transformed to a tiebreaker
|
// if diskless resource remove it, in the worst case it will be transformed to a tiebreaker
|
||||||
if (rsc.getFlags() != null &&
|
if (rsc.getFlags() != null &&
|
||||||
rsc.getFlags().contains(ApiConsts.FLAG_DRBD_DISKLESS) &&
|
rsc.getFlags().contains(ApiConsts.FLAG_DRBD_DISKLESS) &&
|
||||||
@ -324,17 +356,6 @@ public class LinstorStorageAdaptor implements StorageAdaptor {
|
|||||||
ApiCallRcList delAnswers = api.resourceDelete(rsc.getName(), localNodeName);
|
ApiCallRcList delAnswers = api.resourceDelete(rsc.getName(), localNodeName);
|
||||||
logLinstorAnswers(delAnswers);
|
logLinstorAnswers(delAnswers);
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove allow-two-primaries
|
|
||||||
ResourceDefinitionModify rdm = new ResourceDefinitionModify();
|
|
||||||
rdm.deleteProps(Collections.singletonList("DrbdOptions/Net/allow-two-primaries"));
|
|
||||||
ApiCallRcList answers = api.resourceDefinitionModify(rsc.getName(), rdm);
|
|
||||||
if (answers.hasError()) {
|
|
||||||
s_logger.error(
|
|
||||||
String.format("Failed to remove 'allow-two-primaries' on %s: %s",
|
|
||||||
rsc.getName(), LinstorUtil.getBestErrorMessage(answers)));
|
|
||||||
// do not fail here as removing allow-two-primaries property isn't fatal
|
|
||||||
}
|
|
||||||
} catch (ApiException apiEx) {
|
} catch (ApiException apiEx) {
|
||||||
s_logger.error(apiEx.getBestMessage());
|
s_logger.error(apiEx.getBestMessage());
|
||||||
// do not fail here as removing allow-two-primaries property or deleting diskless isn't fatal
|
// do not fail here as removing allow-two-primaries property or deleting diskless isn't fatal
|
||||||
|
|||||||
@ -191,17 +191,20 @@ public class LinstorUtil {
|
|||||||
*
|
*
|
||||||
* @param api developer api object to use
|
* @param api developer api object to use
|
||||||
* @param rscName resource name to check in use state.
|
* @param rscName resource name to check in use state.
|
||||||
* @return True if a resource found that is in use(primary) state, else false.
|
* @return NodeName where the resource is inUse, if not in use `null`
|
||||||
* @throws ApiException forwards api errors
|
* @throws ApiException forwards api errors
|
||||||
*/
|
*/
|
||||||
public static boolean isResourceInUse(DevelopersApi api, String rscName) throws ApiException {
|
public static String isResourceInUse(DevelopersApi api, String rscName) throws ApiException {
|
||||||
List<Resource> rscs = api.resourceList(rscName, null, null);
|
List<Resource> rscs = api.resourceList(rscName, null, null);
|
||||||
if (rscs != null) {
|
if (rscs != null) {
|
||||||
return rscs.stream()
|
return rscs.stream()
|
||||||
.anyMatch(rsc -> rsc.getState() != null && Boolean.TRUE.equals(rsc.getState().isInUse()));
|
.filter(rsc -> rsc.getState() != null && Boolean.TRUE.equals(rsc.getState().isInUse()))
|
||||||
}
|
.map(Resource::getNodeName)
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
s_logger.error("isResourceInUse: null returned from resourceList");
|
s_logger.error("isResourceInUse: null returned from resourceList");
|
||||||
return false;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user