|
16 | 16 | // under the License. |
17 | 17 | package com.cloud.hypervisor.kvm.storage; |
18 | 18 |
|
| 19 | +import java.util.ArrayList; |
19 | 20 | import java.util.Collections; |
20 | 21 | import java.util.HashMap; |
21 | 22 | import java.util.List; |
|
26 | 27 |
|
27 | 28 | import com.cloud.storage.Storage; |
28 | 29 | import com.cloud.utils.exception.CloudRuntimeException; |
| 30 | + |
29 | 31 | import org.apache.cloudstack.storage.datastore.util.LinstorUtil; |
30 | 32 | import org.apache.cloudstack.utils.qemu.QemuImg; |
31 | 33 | import org.apache.cloudstack.utils.qemu.QemuImgException; |
|
43 | 45 | import com.linbit.linstor.api.model.Properties; |
44 | 46 | import com.linbit.linstor.api.model.ProviderKind; |
45 | 47 | import com.linbit.linstor.api.model.Resource; |
| 48 | +import com.linbit.linstor.api.model.ResourceConnectionModify; |
46 | 49 | import com.linbit.linstor.api.model.ResourceDefinition; |
47 | | -import com.linbit.linstor.api.model.ResourceDefinitionModify; |
48 | 50 | import com.linbit.linstor.api.model.ResourceGroupSpawn; |
49 | 51 | import com.linbit.linstor.api.model.ResourceMakeAvailable; |
50 | 52 | import com.linbit.linstor.api.model.ResourceWithVolumes; |
@@ -237,15 +239,19 @@ public KVMPhysicalDisk createPhysicalDisk(String name, KVMStoragePool pool, Qemu |
237 | 239 | * @throws ApiException if any problem connecting to the Linstor controller |
238 | 240 | */ |
239 | 241 | 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)) { |
241 | 244 | // 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(); |
243 | 246 | Properties props = new Properties(); |
244 | 247 | 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); |
247 | 251 | 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)); |
249 | 255 | // do not fail here as adding allow-two-primaries property is only a problem while live migrating |
250 | 256 | } |
251 | 257 | } |
@@ -285,6 +291,23 @@ public boolean connectPhysicalDisk(String volumePath, KVMStoragePool pool, Map<S |
285 | 291 | return true; |
286 | 292 | } |
287 | 293 |
|
| 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 | + |
288 | 311 | private boolean tryDisconnectLinstor(String volumePath, KVMStoragePool pool) |
289 | 312 | { |
290 | 313 | if (volumePath == null) { |
@@ -314,27 +337,25 @@ private boolean tryDisconnectLinstor(String volumePath, KVMStoragePool pool) |
314 | 337 |
|
315 | 338 |
|
316 | 339 | if (optRsc.isPresent()) { |
| 340 | + Resource rsc = optRsc.get(); |
317 | 341 | 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 | + } |
319 | 350 |
|
| 351 | + try { |
320 | 352 | // if diskless resource remove it, in the worst case it will be transformed to a tiebreaker |
321 | 353 | if (rsc.getFlags() != null && |
322 | 354 | rsc.getFlags().contains(ApiConsts.FLAG_DRBD_DISKLESS) && |
323 | 355 | !rsc.getFlags().contains(ApiConsts.FLAG_TIE_BREAKER)) { |
324 | 356 | ApiCallRcList delAnswers = api.resourceDelete(rsc.getName(), localNodeName); |
325 | 357 | logLinstorAnswers(delAnswers); |
326 | 358 | } |
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 | | - } |
338 | 359 | } catch (ApiException apiEx) { |
339 | 360 | s_logger.error(apiEx.getBestMessage()); |
340 | 361 | // do not fail here as removing allow-two-primaries property or deleting diskless isn't fatal |
|
0 commit comments