6262import com .cloud .api .storage .LinstorRevertBackupSnapshotCommand ;
6363import com .cloud .configuration .Config ;
6464import com .cloud .host .Host ;
65+ import com .cloud .host .HostVO ;
66+ import com .cloud .host .Status ;
6567import com .cloud .host .dao .HostDao ;
6668import com .cloud .resource .ResourceState ;
6769import com .cloud .storage .DataStoreRole ;
@@ -918,9 +920,10 @@ private String revertSnapshotFromImageStore(
918920 _backupsnapshotwait ,
919921 VirtualMachineManager .ExecuteInSequence .value ());
920922
921- Optional <RemoteHostEndPoint > optEP = getDiskfullEP (linstorApi , rscName );
923+ final StoragePool pool = (StoragePool ) volumeInfo .getDataStore ();
924+ Optional <RemoteHostEndPoint > optEP = getDiskfullEP (linstorApi , pool , rscName );
922925 if (optEP .isEmpty ()) {
923- optEP = getLinstorEP (linstorApi , rscName );
926+ optEP = getLinstorEP (linstorApi , pool , rscName );
924927 }
925928
926929 if (optEP .isPresent ()) {
@@ -1060,13 +1063,29 @@ public void copyAsync(DataObject srcData, DataObject dstData, AsyncCompletionCal
10601063 Answer answer = copyVolume (srcData , dstData );
10611064 res = new CopyCommandResult (null , answer );
10621065 } else {
1063- Answer answer = new Answer (null , false , "noimpl" );
1064- res = new CopyCommandResult (null , answer );
1065- res .setResult ("Not implemented yet" );
1066+ throw new CloudRuntimeException ("Not implemented for Linstor primary storage." );
10661067 }
10671068 callback .complete (res );
10681069 }
10691070
1071+ private Host getEnabledClusterHost (StoragePool storagePool , List <String > linstorNodeNames ) {
1072+ List <HostVO > csHosts ;
1073+ if (storagePool .getClusterId () != null ) {
1074+ csHosts = _hostDao .findByClusterId (storagePool .getClusterId ());
1075+ } else {
1076+ csHosts = _hostDao .findByDataCenterId (storagePool .getDataCenterId ());
1077+ }
1078+ Collections .shuffle (csHosts ); // so we do not always pick the same host for operations
1079+ for (HostVO host : csHosts ) {
1080+ if (host .getResourceState () == ResourceState .Enabled &&
1081+ host .getStatus () == Status .Up &&
1082+ linstorNodeNames .contains (host .getName ())) {
1083+ return host ;
1084+ }
1085+ }
1086+ return null ;
1087+ }
1088+
10701089 /**
10711090 * Tries to get a Linstor cloudstack end point, that is at least diskless.
10721091 *
@@ -1075,47 +1094,37 @@ public void copyAsync(DataObject srcData, DataObject dstData, AsyncCompletionCal
10751094 * @return Optional RemoteHostEndPoint if one could get found.
10761095 * @throws ApiException
10771096 */
1078- private Optional <RemoteHostEndPoint > getLinstorEP (DevelopersApi api , String rscName ) throws ApiException {
1097+ private Optional <RemoteHostEndPoint > getLinstorEP (DevelopersApi api , StoragePool storagePool , String rscName )
1098+ throws ApiException {
10791099 List <String > linstorNodeNames = LinstorUtil .getLinstorNodeNames (api );
1080- Collections .shuffle (linstorNodeNames ); // do not always pick the first linstor node
1081-
1082- Host host = null ;
1083- for (String nodeName : linstorNodeNames ) {
1084- host = _hostDao .findByName (nodeName );
1085- if (host != null && host .getResourceState () == ResourceState .Enabled ) {
1086- s_logger .info (String .format ("Linstor: Make resource %s available on node %s ..." , rscName , nodeName ));
1087- ApiCallRcList answers = api .resourceMakeAvailableOnNode (rscName , nodeName , new ResourceMakeAvailable ());
1088- if (!answers .hasError ()) {
1089- break ; // found working host
1090- } else {
1091- s_logger .error (
1092- String .format ("Linstor: Unable to make resource %s on node %s available: %s" ,
1093- rscName ,
1094- nodeName ,
1095- LinstorUtil .getBestErrorMessage (answers )));
1096- }
1100+ Host host = getEnabledClusterHost (storagePool , linstorNodeNames );
1101+ if (host != null ) {
1102+ s_logger .info (String .format ("Linstor: Make resource %s available on node %s ..." , rscName , host .getName ()));
1103+ ApiCallRcList answers = api .resourceMakeAvailableOnNode (
1104+ rscName , host .getName (), new ResourceMakeAvailable ());
1105+ if (answers .hasError ()) {
1106+ s_logger .error (String .format ("Linstor: Unable to make resource %s on node %s available: %s" ,
1107+ rscName , host .getName (), LinstorUtil .getBestErrorMessage (answers )));
1108+ return Optional .empty ();
1109+ } else {
1110+ return Optional .of (RemoteHostEndPoint .getHypervisorHostEndPoint (host ));
10971111 }
10981112 }
10991113
1100- if (host == null )
1101- {
1102- s_logger .error ("Linstor: Couldn't create a resource on any cloudstack host." );
1103- return Optional .empty ();
1104- }
1105- else
1106- {
1107- return Optional .of (RemoteHostEndPoint .getHypervisorHostEndPoint (host ));
1108- }
1114+ s_logger .error ("Linstor: Couldn't create a resource on any cloudstack host." );
1115+ return Optional .empty ();
11091116 }
11101117
1111- private Optional <RemoteHostEndPoint > getDiskfullEP (DevelopersApi api , String rscName ) throws ApiException {
1118+ private Optional <RemoteHostEndPoint > getDiskfullEP (DevelopersApi api , StoragePool storagePool , String rscName )
1119+ throws ApiException {
11121120 List <com .linbit .linstor .api .model .StoragePool > linSPs = LinstorUtil .getDiskfulStoragePools (api , rscName );
11131121 if (linSPs != null ) {
1114- for (com .linbit .linstor .api .model .StoragePool sp : linSPs ) {
1115- Host host = _hostDao .findByName (sp .getNodeName ());
1116- if (host != null && host .getResourceState () == ResourceState .Enabled ) {
1117- return Optional .of (RemoteHostEndPoint .getHypervisorHostEndPoint (host ));
1118- }
1122+ List <String > linstorNodeNames = linSPs .stream ()
1123+ .map (com .linbit .linstor .api .model .StoragePool ::getNodeName )
1124+ .collect (Collectors .toList ());
1125+ Host host = getEnabledClusterHost (storagePool , linstorNodeNames );
1126+ if (host != null ) {
1127+ return Optional .of (RemoteHostEndPoint .getHypervisorHostEndPoint (host ));
11191128 }
11201129 }
11211130 s_logger .error ("Linstor: No diskfull host found." );
@@ -1196,12 +1205,12 @@ private Answer copyTemplate(DataObject srcData, DataObject dstData) {
11961205 VirtualMachineManager .ExecuteInSequence .value ());
11971206
11981207 try {
1199- Optional <RemoteHostEndPoint > optEP = getLinstorEP (api , rscName );
1208+ Optional <RemoteHostEndPoint > optEP = getLinstorEP (api , pool , rscName );
12001209 if (optEP .isPresent ()) {
12011210 answer = optEP .get ().sendMessage (cmd );
12021211 } else {
1203- answer = new Answer (cmd , false , "Unable to get matching Linstor endpoint." );
12041212 deleteResourceDefinition (pool , rscName );
1213+ throw new CloudRuntimeException ("Unable to get matching Linstor endpoint." );
12051214 }
12061215 } catch (ApiException exc ) {
12071216 s_logger .error ("copy template failed: " , exc );
@@ -1238,12 +1247,12 @@ private Answer copyVolume(DataObject srcData, DataObject dstData) {
12381247 Answer answer ;
12391248
12401249 try {
1241- Optional <RemoteHostEndPoint > optEP = getLinstorEP (api , rscName );
1250+ Optional <RemoteHostEndPoint > optEP = getLinstorEP (api , pool , rscName );
12421251 if (optEP .isPresent ()) {
12431252 answer = optEP .get ().sendMessage (cmd );
12441253 }
12451254 else {
1246- answer = new Answer ( cmd , false , "Unable to get matching Linstor endpoint." );
1255+ throw new CloudRuntimeException ( "Unable to get matching Linstor endpoint." );
12471256 }
12481257 } catch (ApiException exc ) {
12491258 s_logger .error ("copy volume failed: " , exc );
@@ -1276,14 +1285,14 @@ private Answer copyFromTemporaryResource(
12761285 try {
12771286 String devName = restoreResourceFromSnapshot (api , pool , rscName , snapshotName , restoreName );
12781287
1279- Optional <RemoteHostEndPoint > optEPAny = getLinstorEP (api , restoreName );
1288+ Optional <RemoteHostEndPoint > optEPAny = getLinstorEP (api , pool , restoreName );
12801289 if (optEPAny .isPresent ()) {
12811290 // patch the src device path to the temporary linstor resource
12821291 snapshotObject .setPath (devName );
12831292 origCmd .setSrcTO (snapshotObject .getTO ());
12841293 answer = optEPAny .get ().sendMessage (origCmd );
1285- } else {
1286- answer = new Answer ( origCmd , false , "Unable to get matching Linstor endpoint." );
1294+ } else {
1295+ throw new CloudRuntimeException ( "Unable to get matching Linstor endpoint." );
12871296 }
12881297 } finally {
12891298 // delete the temporary resource, noop if already gone
@@ -1345,7 +1354,7 @@ protected Answer copySnapshot(DataObject srcData, DataObject destData) {
13451354 VirtualMachineManager .ExecuteInSequence .value ());
13461355 cmd .setOptions (options );
13471356
1348- Optional <RemoteHostEndPoint > optEP = getDiskfullEP (api , rscName );
1357+ Optional <RemoteHostEndPoint > optEP = getDiskfullEP (api , pool , rscName );
13491358 Answer answer ;
13501359 if (optEP .isPresent ()) {
13511360 answer = optEP .get ().sendMessage (cmd );
0 commit comments