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 ()) {
@@ -1063,13 +1066,29 @@ public void copyAsync(DataObject srcData, DataObject dstData, AsyncCompletionCal
10631066 Answer answer = copyVolume (srcData , dstData );
10641067 res = new CopyCommandResult (null , answer );
10651068 } else {
1066- Answer answer = new Answer (null , false , "noimpl" );
1067- res = new CopyCommandResult (null , answer );
1068- res .setResult ("Not implemented yet" );
1069+ throw new CloudRuntimeException ("Not implemented for Linstor primary storage." );
10691070 }
10701071 callback .complete (res );
10711072 }
10721073
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+
10731092 /**
10741093 * Tries to get a Linstor cloudstack end point, that is at least diskless.
10751094 *
@@ -1078,47 +1097,37 @@ public void copyAsync(DataObject srcData, DataObject dstData, AsyncCompletionCal
10781097 * @return Optional RemoteHostEndPoint if one could get found.
10791098 * @throws ApiException
10801099 */
1081- private Optional <RemoteHostEndPoint > getLinstorEP (DevelopersApi api , String rscName ) throws ApiException {
1100+ private Optional <RemoteHostEndPoint > getLinstorEP (DevelopersApi api , StoragePool storagePool , String rscName )
1101+ throws ApiException {
10821102 List <String > linstorNodeNames = LinstorUtil .getLinstorNodeNames (api );
1083- Collections .shuffle (linstorNodeNames ); // do not always pick the first linstor node
1084-
1085- Host host = null ;
1086- for (String nodeName : linstorNodeNames ) {
1087- host = _hostDao .findByName (nodeName );
1088- if (host != null && host .getResourceState () == ResourceState .Enabled ) {
1089- logger .info (String .format ("Linstor: Make resource %s available on node %s ..." , rscName , nodeName ));
1090- ApiCallRcList answers = api .resourceMakeAvailableOnNode (rscName , nodeName , new ResourceMakeAvailable ());
1091- if (!answers .hasError ()) {
1092- break ; // found working host
1093- } else {
1094- logger .error (
1095- String .format ("Linstor: Unable to make resource %s on node %s available: %s" ,
1096- rscName ,
1097- nodeName ,
1098- LinstorUtil .getBestErrorMessage (answers )));
1099- }
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 ));
11001114 }
11011115 }
11021116
1103- if (host == null )
1104- {
1105- logger .error ("Linstor: Couldn't create a resource on any cloudstack host." );
1106- return Optional .empty ();
1107- }
1108- else
1109- {
1110- return Optional .of (RemoteHostEndPoint .getHypervisorHostEndPoint (host ));
1111- }
1117+ logger .error ("Linstor: Couldn't create a resource on any cloudstack host." );
1118+ return Optional .empty ();
11121119 }
11131120
1114- private Optional <RemoteHostEndPoint > getDiskfullEP (DevelopersApi api , String rscName ) throws ApiException {
1121+ private Optional <RemoteHostEndPoint > getDiskfullEP (DevelopersApi api , StoragePool storagePool , String rscName )
1122+ throws ApiException {
11151123 List <com .linbit .linstor .api .model .StoragePool > linSPs = LinstorUtil .getDiskfulStoragePools (api , rscName );
11161124 if (linSPs != null ) {
1117- for (com .linbit .linstor .api .model .StoragePool sp : linSPs ) {
1118- Host host = _hostDao .findByName (sp .getNodeName ());
1119- if (host != null && host .getResourceState () == ResourceState .Enabled ) {
1120- return Optional .of (RemoteHostEndPoint .getHypervisorHostEndPoint (host ));
1121- }
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 ));
11221131 }
11231132 }
11241133 logger .error ("Linstor: No diskfull host found." );
@@ -1199,12 +1208,12 @@ private Answer copyTemplate(DataObject srcData, DataObject dstData) {
11991208 VirtualMachineManager .ExecuteInSequence .value ());
12001209
12011210 try {
1202- Optional <RemoteHostEndPoint > optEP = getLinstorEP (api , rscName );
1211+ Optional <RemoteHostEndPoint > optEP = getLinstorEP (api , pool , rscName );
12031212 if (optEP .isPresent ()) {
12041213 answer = optEP .get ().sendMessage (cmd );
12051214 } else {
1206- answer = new Answer (cmd , false , "Unable to get matching Linstor endpoint." );
12071215 deleteResourceDefinition (pool , rscName );
1216+ throw new CloudRuntimeException ("Unable to get matching Linstor endpoint." );
12081217 }
12091218 } catch (ApiException exc ) {
12101219 logger .error ("copy template failed: " , exc );
@@ -1241,12 +1250,12 @@ private Answer copyVolume(DataObject srcData, DataObject dstData) {
12411250 Answer answer ;
12421251
12431252 try {
1244- Optional <RemoteHostEndPoint > optEP = getLinstorEP (api , rscName );
1253+ Optional <RemoteHostEndPoint > optEP = getLinstorEP (api , pool , rscName );
12451254 if (optEP .isPresent ()) {
12461255 answer = optEP .get ().sendMessage (cmd );
12471256 }
12481257 else {
1249- answer = new Answer ( cmd , false , "Unable to get matching Linstor endpoint." );
1258+ throw new CloudRuntimeException ( "Unable to get matching Linstor endpoint." );
12501259 }
12511260 } catch (ApiException exc ) {
12521261 logger .error ("copy volume failed: " , exc );
@@ -1279,14 +1288,14 @@ private Answer copyFromTemporaryResource(
12791288 try {
12801289 String devName = restoreResourceFromSnapshot (api , pool , rscName , snapshotName , restoreName );
12811290
1282- Optional <RemoteHostEndPoint > optEPAny = getLinstorEP (api , restoreName );
1291+ Optional <RemoteHostEndPoint > optEPAny = getLinstorEP (api , pool , restoreName );
12831292 if (optEPAny .isPresent ()) {
12841293 // patch the src device path to the temporary linstor resource
12851294 snapshotObject .setPath (devName );
12861295 origCmd .setSrcTO (snapshotObject .getTO ());
12871296 answer = optEPAny .get ().sendMessage (origCmd );
1288- } else {
1289- answer = new Answer ( origCmd , false , "Unable to get matching Linstor endpoint." );
1297+ } else {
1298+ throw new CloudRuntimeException ( "Unable to get matching Linstor endpoint." );
12901299 }
12911300 } finally {
12921301 // delete the temporary resource, noop if already gone
@@ -1348,7 +1357,7 @@ protected Answer copySnapshot(DataObject srcData, DataObject destData) {
13481357 VirtualMachineManager .ExecuteInSequence .value ());
13491358 cmd .setOptions (options );
13501359
1351- Optional <RemoteHostEndPoint > optEP = getDiskfullEP (api , rscName );
1360+ Optional <RemoteHostEndPoint > optEP = getDiskfullEP (api , pool , rscName );
13521361 Answer answer ;
13531362 if (optEP .isPresent ()) {
13541363 answer = optEP .get ().sendMessage (cmd );
0 commit comments