1717package com .cloud .hypervisor .kvm .storage ;
1818
1919import java .util .ArrayList ;
20+ import java .util .Arrays ;
2021import java .util .Collections ;
2122import java .util .HashMap ;
2223import java .util .List ;
4748import com .linbit .linstor .api .model .Resource ;
4849import com .linbit .linstor .api .model .ResourceConnectionModify ;
4950import com .linbit .linstor .api .model .ResourceDefinition ;
51+ import com .linbit .linstor .api .model .ResourceDefinitionModify ;
5052import com .linbit .linstor .api .model .ResourceGroupSpawn ;
5153import com .linbit .linstor .api .model .ResourceMakeAvailable ;
5254import 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 ());
0 commit comments