6464import com .cloud .api .storage .LinstorRevertBackupSnapshotCommand ;
6565import com .cloud .configuration .Config ;
6666import com .cloud .host .Host ;
67+ import com .cloud .host .HostVO ;
68+ import com .cloud .host .Status ;
6769import com .cloud .host .dao .HostDao ;
6870import com .cloud .resource .ResourceState ;
6971import com .cloud .storage .DataStoreRole ;
@@ -923,9 +925,10 @@ private String revertSnapshotFromImageStore(
923925 _backupsnapshotwait ,
924926 VirtualMachineManager .ExecuteInSequence .value ());
925927
926- Optional <RemoteHostEndPoint > optEP = getDiskfullEP (linstorApi , rscName );
928+ final StoragePool pool = (StoragePool ) volumeInfo .getDataStore ();
929+ Optional <RemoteHostEndPoint > optEP = getDiskfullEP (linstorApi , pool , rscName );
927930 if (optEP .isEmpty ()) {
928- optEP = getLinstorEP (linstorApi , rscName );
931+ optEP = getLinstorEP (linstorApi , pool , rscName );
929932 }
930933
931934 if (optEP .isPresent ()) {
@@ -1065,13 +1068,29 @@ public void copyAsync(DataObject srcData, DataObject dstData, AsyncCompletionCal
10651068 Answer answer = copyVolume (srcData , dstData );
10661069 res = new CopyCommandResult (null , answer );
10671070 } else {
1068- Answer answer = new Answer (null , false , "noimpl" );
1069- res = new CopyCommandResult (null , answer );
1070- res .setResult ("Not implemented yet" );
1071+ throw new CloudRuntimeException ("Not implemented for Linstor primary storage." );
10711072 }
10721073 callback .complete (res );
10731074 }
10741075
1076+ private Host getEnabledClusterHost (StoragePool storagePool , List <String > linstorNodeNames ) {
1077+ List <HostVO > csHosts ;
1078+ if (storagePool .getClusterId () != null ) {
1079+ csHosts = _hostDao .findByClusterId (storagePool .getClusterId ());
1080+ } else {
1081+ csHosts = _hostDao .findByDataCenterId (storagePool .getDataCenterId ());
1082+ }
1083+ Collections .shuffle (csHosts ); // so we do not always pick the same host for operations
1084+ for (HostVO host : csHosts ) {
1085+ if (host .getResourceState () == ResourceState .Enabled &&
1086+ host .getStatus () == Status .Up &&
1087+ linstorNodeNames .contains (host .getName ())) {
1088+ return host ;
1089+ }
1090+ }
1091+ return null ;
1092+ }
1093+
10751094 /**
10761095 * Tries to get a Linstor cloudstack end point, that is at least diskless.
10771096 *
@@ -1080,47 +1099,37 @@ public void copyAsync(DataObject srcData, DataObject dstData, AsyncCompletionCal
10801099 * @return Optional RemoteHostEndPoint if one could get found.
10811100 * @throws ApiException
10821101 */
1083- private Optional <RemoteHostEndPoint > getLinstorEP (DevelopersApi api , String rscName ) throws ApiException {
1102+ private Optional <RemoteHostEndPoint > getLinstorEP (DevelopersApi api , StoragePool storagePool , String rscName )
1103+ throws ApiException {
10841104 List <String > linstorNodeNames = LinstorUtil .getLinstorNodeNames (api );
1085- Collections .shuffle (linstorNodeNames ); // do not always pick the first linstor node
1086-
1087- Host host = null ;
1088- for (String nodeName : linstorNodeNames ) {
1089- host = _hostDao .findByName (nodeName );
1090- if (host != null && host .getResourceState () == ResourceState .Enabled ) {
1091- logger .info (String .format ("Linstor: Make resource %s available on node %s ..." , rscName , nodeName ));
1092- ApiCallRcList answers = api .resourceMakeAvailableOnNode (rscName , nodeName , new ResourceMakeAvailable ());
1093- if (!answers .hasError ()) {
1094- break ; // found working host
1095- } else {
1096- logger .error (
1097- String .format ("Linstor: Unable to make resource %s on node %s available: %s" ,
1098- rscName ,
1099- nodeName ,
1100- LinstorUtil .getBestErrorMessage (answers )));
1101- }
1105+ Host host = getEnabledClusterHost (storagePool , linstorNodeNames );
1106+ if (host != null ) {
1107+ logger .info ("Linstor: Make resource {} available on node {} ..." , rscName , host .getName ());
1108+ ApiCallRcList answers = api .resourceMakeAvailableOnNode (
1109+ rscName , host .getName (), new ResourceMakeAvailable ());
1110+ if (answers .hasError ()) {
1111+ logger .error ("Linstor: Unable to make resource {} on node {} available: {}" ,
1112+ rscName , host .getName (), LinstorUtil .getBestErrorMessage (answers ));
1113+ return Optional .empty ();
1114+ } else {
1115+ return Optional .of (RemoteHostEndPoint .getHypervisorHostEndPoint (host ));
11021116 }
11031117 }
11041118
1105- if (host == null )
1106- {
1107- logger .error ("Linstor: Couldn't create a resource on any cloudstack host." );
1108- return Optional .empty ();
1109- }
1110- else
1111- {
1112- return Optional .of (RemoteHostEndPoint .getHypervisorHostEndPoint (host ));
1113- }
1119+ logger .error ("Linstor: Couldn't create a resource on any cloudstack host." );
1120+ return Optional .empty ();
11141121 }
11151122
1116- private Optional <RemoteHostEndPoint > getDiskfullEP (DevelopersApi api , String rscName ) throws ApiException {
1123+ private Optional <RemoteHostEndPoint > getDiskfullEP (DevelopersApi api , StoragePool storagePool , String rscName )
1124+ throws ApiException {
11171125 List <com .linbit .linstor .api .model .StoragePool > linSPs = LinstorUtil .getDiskfulStoragePools (api , rscName );
11181126 if (linSPs != null ) {
1119- for (com .linbit .linstor .api .model .StoragePool sp : linSPs ) {
1120- Host host = _hostDao .findByName (sp .getNodeName ());
1121- if (host != null && host .getResourceState () == ResourceState .Enabled ) {
1122- return Optional .of (RemoteHostEndPoint .getHypervisorHostEndPoint (host ));
1123- }
1127+ List <String > linstorNodeNames = linSPs .stream ()
1128+ .map (com .linbit .linstor .api .model .StoragePool ::getNodeName )
1129+ .collect (Collectors .toList ());
1130+ Host host = getEnabledClusterHost (storagePool , linstorNodeNames );
1131+ if (host != null ) {
1132+ return Optional .of (RemoteHostEndPoint .getHypervisorHostEndPoint (host ));
11241133 }
11251134 }
11261135 logger .error ("Linstor: No diskfull host found." );
@@ -1201,12 +1210,12 @@ private Answer copyTemplate(DataObject srcData, DataObject dstData) {
12011210 VirtualMachineManager .ExecuteInSequence .value ());
12021211
12031212 try {
1204- Optional <RemoteHostEndPoint > optEP = getLinstorEP (api , rscName );
1213+ Optional <RemoteHostEndPoint > optEP = getLinstorEP (api , pool , rscName );
12051214 if (optEP .isPresent ()) {
12061215 answer = optEP .get ().sendMessage (cmd );
12071216 } else {
1208- answer = new Answer (cmd , false , "Unable to get matching Linstor endpoint." );
12091217 deleteResourceDefinition (pool , rscName );
1218+ throw new CloudRuntimeException ("Unable to get matching Linstor endpoint." );
12101219 }
12111220 } catch (ApiException exc ) {
12121221 logger .error ("copy template failed: " , exc );
@@ -1243,12 +1252,12 @@ private Answer copyVolume(DataObject srcData, DataObject dstData) {
12431252 Answer answer ;
12441253
12451254 try {
1246- Optional <RemoteHostEndPoint > optEP = getLinstorEP (api , rscName );
1255+ Optional <RemoteHostEndPoint > optEP = getLinstorEP (api , pool , rscName );
12471256 if (optEP .isPresent ()) {
12481257 answer = optEP .get ().sendMessage (cmd );
12491258 }
12501259 else {
1251- answer = new Answer ( cmd , false , "Unable to get matching Linstor endpoint." );
1260+ throw new CloudRuntimeException ( "Unable to get matching Linstor endpoint." );
12521261 }
12531262 } catch (ApiException exc ) {
12541263 logger .error ("copy volume failed: " , exc );
@@ -1281,14 +1290,14 @@ private Answer copyFromTemporaryResource(
12811290 try {
12821291 String devName = restoreResourceFromSnapshot (api , pool , rscName , snapshotName , restoreName );
12831292
1284- Optional <RemoteHostEndPoint > optEPAny = getLinstorEP (api , restoreName );
1293+ Optional <RemoteHostEndPoint > optEPAny = getLinstorEP (api , pool , restoreName );
12851294 if (optEPAny .isPresent ()) {
12861295 // patch the src device path to the temporary linstor resource
12871296 snapshotObject .setPath (devName );
12881297 origCmd .setSrcTO (snapshotObject .getTO ());
12891298 answer = optEPAny .get ().sendMessage (origCmd );
1290- } else {
1291- answer = new Answer ( origCmd , false , "Unable to get matching Linstor endpoint." );
1299+ } else {
1300+ throw new CloudRuntimeException ( "Unable to get matching Linstor endpoint." );
12921301 }
12931302 } finally {
12941303 // delete the temporary resource, noop if already gone
@@ -1350,7 +1359,7 @@ protected Answer copySnapshot(DataObject srcData, DataObject destData) {
13501359 VirtualMachineManager .ExecuteInSequence .value ());
13511360 cmd .setOptions (options );
13521361
1353- Optional <RemoteHostEndPoint > optEP = getDiskfullEP (api , rscName );
1362+ Optional <RemoteHostEndPoint > optEP = getDiskfullEP (api , pool , rscName );
13541363 Answer answer ;
13551364 if (optEP .isPresent ()) {
13561365 answer = optEP .get ().sendMessage (cmd );
0 commit comments