6363import com .cloud .api .storage .LinstorRevertBackupSnapshotCommand ;
6464import com .cloud .configuration .Config ;
6565import com .cloud .host .Host ;
66+ import com .cloud .host .HostVO ;
67+ import com .cloud .host .Status ;
6668import com .cloud .host .dao .HostDao ;
6769import com .cloud .resource .ResourceState ;
6870import com .cloud .storage .DataStoreRole ;
@@ -921,9 +923,10 @@ private String revertSnapshotFromImageStore(
921923 _backupsnapshotwait ,
922924 VirtualMachineManager .ExecuteInSequence .value ());
923925
924- Optional <RemoteHostEndPoint > optEP = getDiskfullEP (linstorApi , rscName );
926+ final StoragePool pool = (StoragePool ) volumeInfo .getDataStore ();
927+ Optional <RemoteHostEndPoint > optEP = getDiskfullEP (linstorApi , pool , rscName );
925928 if (optEP .isEmpty ()) {
926- optEP = getLinstorEP (linstorApi , rscName );
929+ optEP = getLinstorEP (linstorApi , pool , rscName );
927930 }
928931
929932 if (optEP .isPresent ()) {
@@ -1068,6 +1071,24 @@ public void copyAsync(DataObject srcData, DataObject dstData, AsyncCompletionCal
10681071 callback .complete (res );
10691072 }
10701073
1074+ private Host getEnabledClusterHost (StoragePool storagePool , List <String > linstorNodeNames ) {
1075+ List <HostVO > csHosts ;
1076+ if (storagePool .getClusterId () != null ) {
1077+ csHosts = _hostDao .findByClusterId (storagePool .getClusterId ());
1078+ } else {
1079+ csHosts = _hostDao .findByDataCenterId (storagePool .getDataCenterId ());
1080+ }
1081+ Collections .shuffle (csHosts ); // so we do not always pick the same host for operations
1082+ for (HostVO host : csHosts ) {
1083+ if (host .getResourceState () == ResourceState .Enabled &&
1084+ host .getStatus () == Status .Up &&
1085+ linstorNodeNames .contains (host .getName ())) {
1086+ return host ;
1087+ }
1088+ }
1089+ return null ;
1090+ }
1091+
10711092 /**
10721093 * Tries to get a Linstor cloudstack end point, that is at least diskless.
10731094 *
@@ -1076,47 +1097,37 @@ public void copyAsync(DataObject srcData, DataObject dstData, AsyncCompletionCal
10761097 * @return Optional RemoteHostEndPoint if one could get found.
10771098 * @throws ApiException
10781099 */
1079- private Optional <RemoteHostEndPoint > getLinstorEP (DevelopersApi api , String rscName ) throws ApiException {
1100+ private Optional <RemoteHostEndPoint > getLinstorEP (DevelopersApi api , StoragePool storagePool , String rscName )
1101+ throws ApiException {
10801102 List <String > linstorNodeNames = LinstorUtil .getLinstorNodeNames (api );
1081- Collections .shuffle (linstorNodeNames ); // do not always pick the first linstor node
1082-
1083- Host host = null ;
1084- for (String nodeName : linstorNodeNames ) {
1085- host = _hostDao .findByName (nodeName );
1086- if (host != null && host .getResourceState () == ResourceState .Enabled ) {
1087- logger .info (String .format ("Linstor: Make resource %s available on node %s ..." , rscName , nodeName ));
1088- ApiCallRcList answers = api .resourceMakeAvailableOnNode (rscName , nodeName , new ResourceMakeAvailable ());
1089- if (!answers .hasError ()) {
1090- break ; // found working host
1091- } else {
1092- logger .error (
1093- String .format ("Linstor: Unable to make resource %s on node %s available: %s" ,
1094- rscName ,
1095- nodeName ,
1096- LinstorUtil .getBestErrorMessage (answers )));
1097- }
1103+ Host host = getEnabledClusterHost (storagePool , linstorNodeNames );
1104+ if (host != null ) {
1105+ logger .info ("Linstor: Make resource {} available on node {} ..." , rscName , host .getName ());
1106+ ApiCallRcList answers = api .resourceMakeAvailableOnNode (
1107+ rscName , host .getName (), new ResourceMakeAvailable ());
1108+ if (answers .hasError ()) {
1109+ logger .error ("Linstor: Unable to make resource {} on node {} available: {}" ,
1110+ rscName , host .getName (), LinstorUtil .getBestErrorMessage (answers ));
1111+ return Optional .empty ();
1112+ } else {
1113+ return Optional .of (RemoteHostEndPoint .getHypervisorHostEndPoint (host ));
10981114 }
10991115 }
11001116
1101- if (host == null )
1102- {
1103- logger .error ("Linstor: Couldn't create a resource on any cloudstack host." );
1104- return Optional .empty ();
1105- }
1106- else
1107- {
1108- return Optional .of (RemoteHostEndPoint .getHypervisorHostEndPoint (host ));
1109- }
1117+ logger .error ("Linstor: Couldn't create a resource on any cloudstack host." );
1118+ return Optional .empty ();
11101119 }
11111120
1112- private Optional <RemoteHostEndPoint > getDiskfullEP (DevelopersApi api , String rscName ) throws ApiException {
1121+ private Optional <RemoteHostEndPoint > getDiskfullEP (DevelopersApi api , StoragePool storagePool , String rscName )
1122+ throws ApiException {
11131123 List <com .linbit .linstor .api .model .StoragePool > linSPs = LinstorUtil .getDiskfulStoragePools (api , rscName );
11141124 if (linSPs != null ) {
1115- for (com .linbit .linstor .api .model .StoragePool sp : linSPs ) {
1116- Host host = _hostDao .findByName (sp .getNodeName ());
1117- if (host != null && host .getResourceState () == ResourceState .Enabled ) {
1118- return Optional .of (RemoteHostEndPoint .getHypervisorHostEndPoint (host ));
1119- }
1125+ List <String > linstorNodeNames = linSPs .stream ()
1126+ .map (com .linbit .linstor .api .model .StoragePool ::getNodeName )
1127+ .collect (Collectors .toList ());
1128+ Host host = getEnabledClusterHost (storagePool , linstorNodeNames );
1129+ if (host != null ) {
1130+ return Optional .of (RemoteHostEndPoint .getHypervisorHostEndPoint (host ));
11201131 }
11211132 }
11221133 logger .error ("Linstor: No diskfull host found." );
@@ -1197,7 +1208,7 @@ private Answer copyTemplate(DataObject srcData, DataObject dstData) {
11971208 VirtualMachineManager .ExecuteInSequence .value ());
11981209
11991210 try {
1200- Optional <RemoteHostEndPoint > optEP = getLinstorEP (api , rscName );
1211+ Optional <RemoteHostEndPoint > optEP = getLinstorEP (api , pool , rscName );
12011212 if (optEP .isPresent ()) {
12021213 answer = optEP .get ().sendMessage (cmd );
12031214 } else {
@@ -1239,7 +1250,7 @@ private Answer copyVolume(DataObject srcData, DataObject dstData) {
12391250 Answer answer ;
12401251
12411252 try {
1242- Optional <RemoteHostEndPoint > optEP = getLinstorEP (api , rscName );
1253+ Optional <RemoteHostEndPoint > optEP = getLinstorEP (api , pool , rscName );
12431254 if (optEP .isPresent ()) {
12441255 answer = optEP .get ().sendMessage (cmd );
12451256 }
@@ -1277,7 +1288,7 @@ private Answer copyFromTemporaryResource(
12771288 try {
12781289 String devName = restoreResourceFromSnapshot (api , pool , rscName , snapshotName , restoreName );
12791290
1280- Optional <RemoteHostEndPoint > optEPAny = getLinstorEP (api , restoreName );
1291+ Optional <RemoteHostEndPoint > optEPAny = getLinstorEP (api , pool , restoreName );
12811292 if (optEPAny .isPresent ()) {
12821293 // patch the src device path to the temporary linstor resource
12831294 snapshotObject .setPath (devName );
@@ -1346,7 +1357,7 @@ protected Answer copySnapshot(DataObject srcData, DataObject destData) {
13461357 VirtualMachineManager .ExecuteInSequence .value ());
13471358 cmd .setOptions (options );
13481359
1349- Optional <RemoteHostEndPoint > optEP = getDiskfullEP (api , rscName );
1360+ Optional <RemoteHostEndPoint > optEP = getDiskfullEP (api , pool , rscName );
13501361 Answer answer ;
13511362 if (optEP .isPresent ()) {
13521363 answer = optEP .get ().sendMessage (cmd );
0 commit comments