3838import com .cloud .storage .Storage ;
3939import com .cloud .utils .exception .CloudRuntimeException ;
4040import com .linbit .linstor .api .ApiClient ;
41+ import com .linbit .linstor .api .ApiConsts ;
4142import com .linbit .linstor .api .ApiException ;
4243import com .linbit .linstor .api .Configuration ;
4344import com .linbit .linstor .api .DevelopersApi ;
4445import com .linbit .linstor .api .model .ApiCallRc ;
4546import com .linbit .linstor .api .model .ApiCallRcList ;
4647import com .linbit .linstor .api .model .Properties ;
4748import com .linbit .linstor .api .model .ProviderKind ;
49+ import com .linbit .linstor .api .model .Resource ;
4850import com .linbit .linstor .api .model .ResourceDefinition ;
4951import com .linbit .linstor .api .model .ResourceDefinitionModify ;
5052import com .linbit .linstor .api .model .ResourceGroup ;
@@ -102,6 +104,10 @@ private void logLinstorAnswer(@Nonnull ApiCallRc answer) {
102104 }
103105 }
104106
107+ private void logLinstorAnswers (@ Nonnull ApiCallRcList answers ) {
108+ answers .forEach (this ::logLinstorAnswer );
109+ }
110+
105111 private void checkLinstorAnswersThrow (@ Nonnull ApiCallRcList answers ) {
106112 answers .forEach (this ::logLinstorAnswer );
107113 if (answers .hasError ())
@@ -302,26 +308,89 @@ public boolean connectPhysicalDisk(String volumePath, KVMStoragePool pool, Map<S
302308 return true ;
303309 }
304310
311+ private Optional <ResourceWithVolumes > getResourceByPath (final List <ResourceWithVolumes > resources , String path ) {
312+ return resources .stream ()
313+ .filter (rsc -> rsc .getVolumes ().stream ()
314+ .anyMatch (v -> v .getDevicePath ().equals (path )))
315+ .findFirst ();
316+ }
317+
318+ private boolean tryDisconnectLinstor (String volumePath , KVMStoragePool pool )
319+ {
320+ s_logger .debug ("Linstor: Using storage pool: " + pool .getUuid ());
321+ final DevelopersApi api = getLinstorAPI (pool );
322+
323+ Optional <ResourceWithVolumes > optRsc ;
324+ try
325+ {
326+ List <ResourceWithVolumes > resources = api .viewResources (
327+ Collections .singletonList (localNodeName ),
328+ null ,
329+ null ,
330+ null ,
331+ null ,
332+ null );
333+
334+ optRsc = getResourceByPath (resources , volumePath );
335+ } catch (ApiException apiEx ) {
336+ // couldn't query linstor controller
337+ s_logger .error (apiEx .getBestMessage ());
338+ return false ;
339+ }
340+
341+
342+ if (optRsc .isPresent ()) {
343+ try {
344+ Resource rsc = optRsc .get ();
345+
346+ // if diskless resource remove it, in the worst case it will be transformed to a tiebreaker
347+ if (rsc .getFlags () != null &&
348+ rsc .getFlags ().contains (ApiConsts .FLAG_DRBD_DISKLESS ) &&
349+ !rsc .getFlags ().contains (ApiConsts .FLAG_TIE_BREAKER )) {
350+ ApiCallRcList delAnswers = api .resourceDelete (rsc .getName (), localNodeName );
351+ logLinstorAnswers (delAnswers );
352+ }
353+
354+ // remove allow-two-primaries
355+ ResourceDefinitionModify rdm = new ResourceDefinitionModify ();
356+ rdm .deleteProps (Collections .singletonList ("DrbdOptions/Net/allow-two-primaries" ));
357+ ApiCallRcList answers = api .resourceDefinitionModify (rsc .getName (), rdm );
358+ if (answers .hasError ()) {
359+ s_logger .error (
360+ String .format ("Failed to remove 'allow-two-primaries' on %s: %s" ,
361+ rsc .getName (), LinstorUtil .getBestErrorMessage (answers )));
362+ // do not fail here as removing allow-two-primaries property isn't fatal
363+ }
364+ } catch (ApiException apiEx ) {
365+ s_logger .error (apiEx .getBestMessage ());
366+ // do not fail here as removing allow-two-primaries property or deleting diskless isn't fatal
367+ }
368+
369+ return true ;
370+ }
371+
372+ s_logger .warn ("Linstor: Couldn't find resource for this path: " + volumePath );
373+ return false ;
374+ }
375+
305376 @ Override
306377 public boolean disconnectPhysicalDisk (String volumePath , KVMStoragePool pool )
307378 {
308379 s_logger .debug ("Linstor: disconnectPhysicalDisk " + pool .getUuid () + ":" + volumePath );
309- return true ;
380+ if (MapStorageUuidToStoragePool .containsValue (pool )) {
381+ return tryDisconnectLinstor (volumePath , pool );
382+ }
383+ return false ;
310384 }
311385
312386 @ Override
313387 public boolean disconnectPhysicalDisk (Map <String , String > volumeToDisconnect )
314388 {
389+ // as of now this is only relevant for iscsi targets
390+ s_logger .info ("Linstor: disconnectPhysicalDisk(Map<String, String> volumeToDisconnect) called?" );
315391 return false ;
316392 }
317393
318- private Optional <ResourceWithVolumes > getResourceByPath (final List <ResourceWithVolumes > resources , String path ) {
319- return resources .stream ()
320- .filter (rsc -> rsc .getVolumes ().stream ()
321- .anyMatch (v -> v .getDevicePath ().equals (path )))
322- .findFirst ();
323- }
324-
325394 /**
326395 * disconnectPhysicalDiskByPath is called after e.g. a live migration.
327396 * The problem is we have no idea just from the path to which linstor-controller
@@ -339,43 +408,9 @@ public boolean disconnectPhysicalDiskByPath(String localPath)
339408 s_logger .debug ("Linstor: disconnectPhysicalDiskByPath " + localPath );
340409 final KVMStoragePool pool = optFirstPool .get ();
341410
342- s_logger .debug ("Linstor: Using storpool: " + pool .getUuid ());
343- final DevelopersApi api = getLinstorAPI (pool );
344-
345- try
346- {
347- List <ResourceWithVolumes > resources = api .viewResources (
348- Collections .singletonList (localNodeName ),
349- null ,
350- null ,
351- null ,
352- null ,
353- null );
354-
355- Optional <ResourceWithVolumes > rsc = getResourceByPath (resources , localPath );
356-
357- if (rsc .isPresent ())
358- {
359- ResourceDefinitionModify rdm = new ResourceDefinitionModify ();
360- rdm .deleteProps (Collections .singletonList ("DrbdOptions/Net/allow-two-primaries" ));
361- ApiCallRcList answers = api .resourceDefinitionModify (rsc .get ().getName (), rdm );
362- if (answers .hasError ())
363- {
364- s_logger .error (
365- String .format ("Failed to remove 'allow-two-primaries' on %s: %s" ,
366- rsc .get ().getName (), LinstorUtil .getBestErrorMessage (answers )));
367- // do not fail here as removing allow-two-primaries property isn't fatal
368- }
369-
370- return true ;
371- }
372- s_logger .warn ("Linstor: Couldn't find resource for this path: " + localPath );
373- } catch (ApiException apiEx ) {
374- s_logger .error (apiEx .getBestMessage ());
375- // do not fail here as removing allow-two-primaries property isn't fatal
376- }
411+ return tryDisconnectLinstor (localPath , pool );
377412 }
378- return true ;
413+ return false ;
379414 }
380415
381416 @ Override
0 commit comments