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 ;
4849import com .linbit .linstor .api .model .Resource ;
4950import com .linbit .linstor .api .model .ResourceConnectionModify ;
5051import com .linbit .linstor .api .model .ResourceDefinition ;
52+ import com .linbit .linstor .api .model .ResourceDefinitionModify ;
5153import com .linbit .linstor .api .model .ResourceGroupSpawn ;
5254import com .linbit .linstor .api .model .ResourceMakeAvailable ;
5355import com .linbit .linstor .api .model .ResourceWithVolumes ;
@@ -235,6 +237,34 @@ public KVMPhysicalDisk createPhysicalDisk(String name, KVMStoragePool pool, Qemu
235237 }
236238 }
237239
240+ private void setAllowTwoPrimariesOnRD (DevelopersApi api , String rscName ) throws ApiException {
241+ ResourceDefinitionModify rdm = new ResourceDefinitionModify ();
242+ Properties props = new Properties ();
243+ props .put ("DrbdOptions/Net/allow-two-primaries" , "yes" );
244+ props .put ("DrbdOptions/Net/protocol" , "C" );
245+ rdm .setOverrideProps (props );
246+ ApiCallRcList answers = api .resourceDefinitionModify (rscName , rdm );
247+ if (answers .hasError ()) {
248+ logger .error (String .format ("Unable to set protocol C and 'allow-two-primaries' on %s" , rscName ));
249+ // do not fail here as adding allow-two-primaries property is only a problem while live migrating
250+ }
251+ }
252+
253+ private void setAllowTwoPrimariesOnRc (DevelopersApi api , String rscName , String inUseNode ) throws ApiException {
254+ ResourceConnectionModify rcm = new ResourceConnectionModify ();
255+ Properties props = new Properties ();
256+ props .put ("DrbdOptions/Net/allow-two-primaries" , "yes" );
257+ props .put ("DrbdOptions/Net/protocol" , "C" );
258+ rcm .setOverrideProps (props );
259+ ApiCallRcList answers = api .resourceConnectionModify (rscName , inUseNode , localNodeName , rcm );
260+ if (answers .hasError ()) {
261+ logger .error (String .format (
262+ "Unable to set protocol C and 'allow-two-primaries' on %s/%s/%s" ,
263+ inUseNode , localNodeName , rscName ));
264+ // do not fail here as adding allow-two-primaries property is only a problem while live migrating
265+ }
266+ }
267+
238268 /**
239269 * Checks if the given resource is in use by drbd on any host and
240270 * if so set the drbd option allow-two-primaries
@@ -246,16 +276,13 @@ private void allow2PrimariesIfInUse(DevelopersApi api, String rscName) throws Ap
246276 String inUseNode = LinstorUtil .isResourceInUse (api , rscName );
247277 if (inUseNode != null && !inUseNode .equalsIgnoreCase (localNodeName )) {
248278 // allow 2 primaries for live migration, should be removed by disconnect on the other end
249- ResourceConnectionModify rcm = new ResourceConnectionModify ();
250- Properties props = new Properties ();
251- props .put ("DrbdOptions/Net/allow-two-primaries" , "yes" );
252- props .put ("DrbdOptions/Net/protocol" , "C" );
253- rcm .setOverrideProps (props );
254- ApiCallRcList answers = api .resourceConnectionModify (rscName , inUseNode , localNodeName , rcm );
255- if (answers .hasError ()) {
256- logger .error ("Unable to set protocol C and 'allow-two-primaries' on {}/{}/{}" ,
257- inUseNode , localNodeName , rscName );
258- // do not fail here as adding allow-two-primaries property is only a problem while live migrating
279+
280+ // if non hyperconverged setup, we have to set allow-two-primaries on the resource-definition
281+ // as there is no resource connection between diskless nodes.
282+ if (LinstorUtil .areResourcesDiskless (api , rscName , Arrays .asList (inUseNode , localNodeName ))) {
283+ setAllowTwoPrimariesOnRD (api , rscName );
284+ } else {
285+ setAllowTwoPrimariesOnRc (api , rscName , inUseNode );
259286 }
260287 }
261288 }
@@ -294,11 +321,22 @@ public boolean connectPhysicalDisk(String volumePath, KVMStoragePool pool, Map<S
294321 return true ;
295322 }
296323
297- private void removeTwoPrimariesRcProps (DevelopersApi api , String inUseNode , String rscName ) throws ApiException {
324+ private void removeTwoPrimariesRDProps (DevelopersApi api , String rscName , List <String > deleteProps )
325+ throws ApiException {
326+ ResourceDefinitionModify rdm = new ResourceDefinitionModify ();
327+ rdm .deleteProps (deleteProps );
328+ ApiCallRcList answers = api .resourceDefinitionModify (rscName , rdm );
329+ if (answers .hasError ()) {
330+ logger .error (
331+ String .format ("Failed to remove 'protocol' and 'allow-two-primaries' on %s: %s" ,
332+ rscName , LinstorUtil .getBestErrorMessage (answers )));
333+ // do not fail here as removing allow-two-primaries property isn't fatal
334+ }
335+ }
336+
337+ private void removeTwoPrimariesRcProps (DevelopersApi api , String rscName , String inUseNode , List <String > deleteProps )
338+ throws ApiException {
298339 ResourceConnectionModify rcm = new ResourceConnectionModify ();
299- List <String > deleteProps = new ArrayList <>();
300- deleteProps .add ("DrbdOptions/Net/allow-two-primaries" );
301- deleteProps .add ("DrbdOptions/Net/protocol" );
302340 rcm .deleteProps (deleteProps );
303341 ApiCallRcList answers = api .resourceConnectionModify (rscName , localNodeName , inUseNode , rcm );
304342 if (answers .hasError ()) {
@@ -310,6 +348,15 @@ private void removeTwoPrimariesRcProps(DevelopersApi api, String inUseNode, Stri
310348 }
311349 }
312350
351+ private void removeTwoPrimariesProps (DevelopersApi api , String inUseNode , String rscName ) throws ApiException {
352+ List <String > deleteProps = new ArrayList <>();
353+ deleteProps .add ("DrbdOptions/Net/allow-two-primaries" );
354+ deleteProps .add ("DrbdOptions/Net/protocol" );
355+
356+ removeTwoPrimariesRDProps (api , rscName , deleteProps );
357+ removeTwoPrimariesRcProps (api , rscName , inUseNode , deleteProps );
358+ }
359+
313360 private boolean tryDisconnectLinstor (String volumePath , KVMStoragePool pool )
314361 {
315362 if (volumePath == null ) {
@@ -343,7 +390,7 @@ private boolean tryDisconnectLinstor(String volumePath, KVMStoragePool pool)
343390 try {
344391 String inUseNode = LinstorUtil .isResourceInUse (api , rsc .getName ());
345392 if (inUseNode != null && !inUseNode .equalsIgnoreCase (localNodeName )) {
346- removeTwoPrimariesRcProps (api , inUseNode , rsc .getName ());
393+ removeTwoPrimariesProps (api , inUseNode , rsc .getName ());
347394 }
348395 } catch (ApiException apiEx ) {
349396 logger .error (apiEx .getBestMessage ());
0 commit comments