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 ;
@@ -103,6 +104,10 @@ private void logLinstorAnswer(@Nonnull ApiCallRc answer) {
103104 }
104105 }
105106
107+ private void logLinstorAnswers (@ Nonnull ApiCallRcList answers ) {
108+ answers .forEach (this ::logLinstorAnswer );
109+ }
110+
106111 private void checkLinstorAnswersThrow (@ Nonnull ApiCallRcList answers ) {
107112 answers .forEach (this ::logLinstorAnswer );
108113 if (answers .hasError ())
@@ -316,23 +321,90 @@ public boolean connectPhysicalDisk(String volumePath, KVMStoragePool pool, Map<S
316321 return true ;
317322 }
318323
324+ private boolean tryDisconnectLinstor (String volumePath , KVMStoragePool pool )
325+ {
326+ if (volumePath == null ) {
327+ return false ;
328+ }
329+
330+ s_logger .debug ("Linstor: Using storage pool: " + pool .getUuid ());
331+ final DevelopersApi api = getLinstorAPI (pool );
332+
333+ Optional <ResourceWithVolumes > optRsc ;
334+ try
335+ {
336+ List <ResourceWithVolumes > resources = api .viewResources (
337+ Collections .singletonList (localNodeName ),
338+ null ,
339+ null ,
340+ null ,
341+ null ,
342+ null );
343+
344+ optRsc = getResourceByPath (resources , volumePath );
345+ } catch (ApiException apiEx ) {
346+ // couldn't query linstor controller
347+ s_logger .error (apiEx .getBestMessage ());
348+ return false ;
349+ }
350+
351+
352+ if (optRsc .isPresent ()) {
353+ try {
354+ Resource rsc = optRsc .get ();
355+
356+ // if diskless resource remove it, in the worst case it will be transformed to a tiebreaker
357+ if (rsc .getFlags () != null &&
358+ rsc .getFlags ().contains (ApiConsts .FLAG_DRBD_DISKLESS ) &&
359+ !rsc .getFlags ().contains (ApiConsts .FLAG_TIE_BREAKER )) {
360+ ApiCallRcList delAnswers = api .resourceDelete (rsc .getName (), localNodeName );
361+ logLinstorAnswers (delAnswers );
362+ }
363+
364+ // remove allow-two-primaries
365+ ResourceDefinitionModify rdm = new ResourceDefinitionModify ();
366+ rdm .deleteProps (Collections .singletonList ("DrbdOptions/Net/allow-two-primaries" ));
367+ ApiCallRcList answers = api .resourceDefinitionModify (rsc .getName (), rdm );
368+ if (answers .hasError ()) {
369+ s_logger .error (
370+ String .format ("Failed to remove 'allow-two-primaries' on %s: %s" ,
371+ rsc .getName (), LinstorUtil .getBestErrorMessage (answers )));
372+ // do not fail here as removing allow-two-primaries property isn't fatal
373+ }
374+ } catch (ApiException apiEx ) {
375+ s_logger .error (apiEx .getBestMessage ());
376+ // do not fail here as removing allow-two-primaries property or deleting diskless isn't fatal
377+ }
378+
379+ return true ;
380+ }
381+
382+ s_logger .warn ("Linstor: Couldn't find resource for this path: " + volumePath );
383+ return false ;
384+ }
385+
319386 @ Override
320387 public boolean disconnectPhysicalDisk (String volumePath , KVMStoragePool pool )
321388 {
322389 s_logger .debug ("Linstor: disconnectPhysicalDisk " + pool .getUuid () + ":" + volumePath );
390+ if (MapStorageUuidToStoragePool .containsValue (pool )) {
391+ return tryDisconnectLinstor (volumePath , pool );
392+ }
323393 return false ;
324394 }
325395
326396 @ Override
327397 public boolean disconnectPhysicalDisk (Map <String , String > volumeToDisconnect )
328398 {
399+ // as of now this is only relevant for iscsi targets
400+ s_logger .info ("Linstor: disconnectPhysicalDisk(Map<String, String> volumeToDisconnect) called?" );
329401 return false ;
330402 }
331403
332404 private Optional <ResourceWithVolumes > getResourceByPath (final List <ResourceWithVolumes > resources , String path ) {
333405 return resources .stream ()
334406 .filter (rsc -> rsc .getVolumes ().stream ()
335- .anyMatch (v -> v .getDevicePath (). equals ( path )))
407+ .anyMatch (v -> path . equals ( v .getDevicePath ())))
336408 .findFirst ();
337409 }
338410
@@ -353,46 +425,8 @@ public boolean disconnectPhysicalDiskByPath(String localPath)
353425 s_logger .debug ("Linstor: disconnectPhysicalDiskByPath " + localPath );
354426 final KVMStoragePool pool = optFirstPool .get ();
355427
356- s_logger .debug ("Linstor: Using storpool: " + pool .getUuid ());
357- final DevelopersApi api = getLinstorAPI (pool );
358-
359- Optional <ResourceWithVolumes > optRsc ;
360- try {
361- List <ResourceWithVolumes > resources = api .viewResources (
362- Collections .singletonList (localNodeName ),
363- null ,
364- null ,
365- null ,
366- null ,
367- null );
368-
369- optRsc = getResourceByPath (resources , localPath );
370- } catch (ApiException apiEx ) {
371- // couldn't query linstor controller
372- s_logger .error (apiEx .getBestMessage ());
373- return false ;
374- }
375-
376- if (optRsc .isPresent ()) {
377- try {
378- Resource rsc = optRsc .get ();
379- ResourceDefinitionModify rdm = new ResourceDefinitionModify ();
380- rdm .deleteProps (Collections .singletonList ("DrbdOptions/Net/allow-two-primaries" ));
381- ApiCallRcList answers = api .resourceDefinitionModify (rsc .getName (), rdm );
382- if (answers .hasError ()) {
383- s_logger .error (
384- String .format ("Failed to remove 'allow-two-primaries' on %s: %s" ,
385- rsc .getName (), LinstorUtil .getBestErrorMessage (answers )));
386- // do not fail here as removing allow-two-primaries property isn't fatal
387- }
388- } catch (ApiException apiEx ){
389- s_logger .error (apiEx .getBestMessage ());
390- // do not fail here as removing allow-two-primaries property isn't fatal
391- }
392- return true ;
393- }
428+ return tryDisconnectLinstor (localPath , pool );
394429 }
395- s_logger .info ("Linstor: Couldn't find resource for this path: " + localPath );
396430 return false ;
397431 }
398432
0 commit comments