17
17
package com .cloud .hypervisor .kvm .storage ;
18
18
19
19
import java .util .ArrayList ;
20
+ import java .util .Arrays ;
20
21
import java .util .Collections ;
21
22
import java .util .HashMap ;
22
23
import java .util .List ;
48
49
import com .linbit .linstor .api .model .Resource ;
49
50
import com .linbit .linstor .api .model .ResourceConnectionModify ;
50
51
import com .linbit .linstor .api .model .ResourceDefinition ;
52
+ import com .linbit .linstor .api .model .ResourceDefinitionModify ;
51
53
import com .linbit .linstor .api .model .ResourceGroupSpawn ;
52
54
import com .linbit .linstor .api .model .ResourceMakeAvailable ;
53
55
import com .linbit .linstor .api .model .ResourceWithVolumes ;
@@ -235,6 +237,34 @@ public KVMPhysicalDisk createPhysicalDisk(String name, KVMStoragePool pool, Qemu
235
237
}
236
238
}
237
239
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
+
238
268
/**
239
269
* Checks if the given resource is in use by drbd on any host and
240
270
* if so set the drbd option allow-two-primaries
@@ -246,16 +276,13 @@ private void allow2PrimariesIfInUse(DevelopersApi api, String rscName) throws Ap
246
276
String inUseNode = LinstorUtil .isResourceInUse (api , rscName );
247
277
if (inUseNode != null && !inUseNode .equalsIgnoreCase (localNodeName )) {
248
278
// 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 );
259
286
}
260
287
}
261
288
}
@@ -294,11 +321,22 @@ public boolean connectPhysicalDisk(String volumePath, KVMStoragePool pool, Map<S
294
321
return true ;
295
322
}
296
323
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 {
298
339
ResourceConnectionModify rcm = new ResourceConnectionModify ();
299
- List <String > deleteProps = new ArrayList <>();
300
- deleteProps .add ("DrbdOptions/Net/allow-two-primaries" );
301
- deleteProps .add ("DrbdOptions/Net/protocol" );
302
340
rcm .deleteProps (deleteProps );
303
341
ApiCallRcList answers = api .resourceConnectionModify (rscName , localNodeName , inUseNode , rcm );
304
342
if (answers .hasError ()) {
@@ -310,6 +348,15 @@ private void removeTwoPrimariesRcProps(DevelopersApi api, String inUseNode, Stri
310
348
}
311
349
}
312
350
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
+
313
360
private boolean tryDisconnectLinstor (String volumePath , KVMStoragePool pool )
314
361
{
315
362
if (volumePath == null ) {
@@ -343,7 +390,7 @@ private boolean tryDisconnectLinstor(String volumePath, KVMStoragePool pool)
343
390
try {
344
391
String inUseNode = LinstorUtil .isResourceInUse (api , rsc .getName ());
345
392
if (inUseNode != null && !inUseNode .equalsIgnoreCase (localNodeName )) {
346
- removeTwoPrimariesRcProps (api , inUseNode , rsc .getName ());
393
+ removeTwoPrimariesProps (api , inUseNode , rsc .getName ());
347
394
}
348
395
} catch (ApiException apiEx ) {
349
396
logger .error (apiEx .getBestMessage ());
0 commit comments