2121import java .io .InputStreamReader ;
2222
2323import java .util .ArrayList ;
24+ import java .util .Arrays ;
2425import java .util .Collections ;
2526import java .util .HashMap ;
2627import java .util .List ;
5354import com .linbit .linstor .api .model .ResourceConnectionModify ;
5455import com .linbit .linstor .api .model .ResourceDefinition ;
5556import com .linbit .linstor .api .model .ResourceGroup ;
57+ import com .linbit .linstor .api .model .ResourceDefinitionModify ;
5658import com .linbit .linstor .api .model .ResourceGroupSpawn ;
5759import com .linbit .linstor .api .model .ResourceMakeAvailable ;
5860import com .linbit .linstor .api .model .ResourceWithVolumes ;
@@ -257,6 +259,34 @@ public KVMPhysicalDisk createPhysicalDisk(String name, KVMStoragePool pool, Qemu
257259 }
258260 }
259261
262+ private void setAllowTwoPrimariesOnRD (DevelopersApi api , String rscName ) throws ApiException {
263+ ResourceDefinitionModify rdm = new ResourceDefinitionModify ();
264+ Properties props = new Properties ();
265+ props .put ("DrbdOptions/Net/allow-two-primaries" , "yes" );
266+ props .put ("DrbdOptions/Net/protocol" , "C" );
267+ rdm .setOverrideProps (props );
268+ ApiCallRcList answers = api .resourceDefinitionModify (rscName , rdm );
269+ if (answers .hasError ()) {
270+ s_logger .error (String .format ("Unable to set protocol C and 'allow-two-primaries' on %s" , rscName ));
271+ // do not fail here as adding allow-two-primaries property is only a problem while live migrating
272+ }
273+ }
274+
275+ private void setAllowTwoPrimariesOnRc (DevelopersApi api , String rscName , String inUseNode ) throws ApiException {
276+ ResourceConnectionModify rcm = new ResourceConnectionModify ();
277+ Properties props = new Properties ();
278+ props .put ("DrbdOptions/Net/allow-two-primaries" , "yes" );
279+ props .put ("DrbdOptions/Net/protocol" , "C" );
280+ rcm .setOverrideProps (props );
281+ ApiCallRcList answers = api .resourceConnectionModify (rscName , inUseNode , localNodeName , rcm );
282+ if (answers .hasError ()) {
283+ s_logger .error (String .format (
284+ "Unable to set protocol C and 'allow-two-primaries' on %s/%s/%s" ,
285+ inUseNode , localNodeName , rscName ));
286+ // do not fail here as adding allow-two-primaries property is only a problem while live migrating
287+ }
288+ }
289+
260290 /**
261291 * Checks if the given resource is in use by drbd on any host and
262292 * if so set the drbd option allow-two-primaries
@@ -268,17 +298,13 @@ private void allow2PrimariesIfInUse(DevelopersApi api, String rscName) throws Ap
268298 String inUseNode = LinstorUtil .isResourceInUse (api , rscName );
269299 if (inUseNode != null && !inUseNode .equalsIgnoreCase (localNodeName )) {
270300 // allow 2 primaries for live migration, should be removed by disconnect on the other end
271- ResourceConnectionModify rcm = new ResourceConnectionModify ();
272- Properties props = new Properties ();
273- props .put ("DrbdOptions/Net/allow-two-primaries" , "yes" );
274- props .put ("DrbdOptions/Net/protocol" , "C" );
275- rcm .setOverrideProps (props );
276- ApiCallRcList answers = api .resourceConnectionModify (rscName , inUseNode , localNodeName , rcm );
277- if (answers .hasError ()) {
278- s_logger .error (String .format (
279- "Unable to set protocol C and 'allow-two-primaries' on %s/%s/%s" ,
280- inUseNode , localNodeName , rscName ));
281- // do not fail here as adding allow-two-primaries property is only a problem while live migrating
301+
302+ // if non hyperconverged setup, we have to set allow-two-primaries on the resource-definition
303+ // as there is no resource connection between diskless nodes.
304+ if (LinstorUtil .areResourcesDiskless (api , rscName , Arrays .asList (inUseNode , localNodeName ))) {
305+ setAllowTwoPrimariesOnRD (api , rscName );
306+ } else {
307+ setAllowTwoPrimariesOnRc (api , rscName , inUseNode );
282308 }
283309 }
284310 }
@@ -317,11 +343,22 @@ public boolean connectPhysicalDisk(String volumePath, KVMStoragePool pool, Map<S
317343 return true ;
318344 }
319345
320- private void removeTwoPrimariesRcProps (DevelopersApi api , String inUseNode , String rscName ) throws ApiException {
346+ private void removeTwoPrimariesRDProps (DevelopersApi api , String rscName , List <String > deleteProps )
347+ throws ApiException {
348+ ResourceDefinitionModify rdm = new ResourceDefinitionModify ();
349+ rdm .deleteProps (deleteProps );
350+ ApiCallRcList answers = api .resourceDefinitionModify (rscName , rdm );
351+ if (answers .hasError ()) {
352+ s_logger .error (
353+ String .format ("Failed to remove 'protocol' and 'allow-two-primaries' on %s: %s" ,
354+ rscName , LinstorUtil .getBestErrorMessage (answers )));
355+ // do not fail here as removing allow-two-primaries property isn't fatal
356+ }
357+ }
358+
359+ private void removeTwoPrimariesRcProps (DevelopersApi api , String rscName , String inUseNode , List <String > deleteProps )
360+ throws ApiException {
321361 ResourceConnectionModify rcm = new ResourceConnectionModify ();
322- List <String > deleteProps = new ArrayList <>();
323- deleteProps .add ("DrbdOptions/Net/allow-two-primaries" );
324- deleteProps .add ("DrbdOptions/Net/protocol" );
325362 rcm .deleteProps (deleteProps );
326363 ApiCallRcList answers = api .resourceConnectionModify (rscName , localNodeName , inUseNode , rcm );
327364 if (answers .hasError ()) {
@@ -334,6 +371,15 @@ private void removeTwoPrimariesRcProps(DevelopersApi api, String inUseNode, Stri
334371 }
335372 }
336373
374+ private void removeTwoPrimariesProps (DevelopersApi api , String inUseNode , String rscName ) throws ApiException {
375+ List <String > deleteProps = new ArrayList <>();
376+ deleteProps .add ("DrbdOptions/Net/allow-two-primaries" );
377+ deleteProps .add ("DrbdOptions/Net/protocol" );
378+
379+ removeTwoPrimariesRDProps (api , rscName , deleteProps );
380+ removeTwoPrimariesRcProps (api , rscName , inUseNode , deleteProps );
381+ }
382+
337383 private boolean tryDisconnectLinstor (String volumePath , KVMStoragePool pool )
338384 {
339385 if (volumePath == null ) {
@@ -367,7 +413,7 @@ private boolean tryDisconnectLinstor(String volumePath, KVMStoragePool pool)
367413 try {
368414 String inUseNode = LinstorUtil .isResourceInUse (api , rsc .getName ());
369415 if (inUseNode != null && !inUseNode .equalsIgnoreCase (localNodeName )) {
370- removeTwoPrimariesRcProps (api , inUseNode , rsc .getName ());
416+ removeTwoPrimariesProps (api , inUseNode , rsc .getName ());
371417 }
372418 } catch (ApiException apiEx ) {
373419 s_logger .error (apiEx .getBestMessage ());
0 commit comments