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 ;
@@ -922,9 +924,10 @@ private String revertSnapshotFromImageStore(
922924 _backupsnapshotwait ,
923925 VirtualMachineManager .ExecuteInSequence .value ());
924926
925- Optional <RemoteHostEndPoint > optEP = getDiskfullEP (linstorApi , rscName );
927+ final StoragePool pool = (StoragePool ) volumeInfo .getDataStore ();
928+ Optional <RemoteHostEndPoint > optEP = getDiskfullEP (linstorApi , pool , rscName );
926929 if (optEP .isEmpty ()) {
927- optEP = getLinstorEP (linstorApi , rscName );
930+ optEP = getLinstorEP (linstorApi , pool , rscName );
928931 }
929932
930933 if (optEP .isPresent ()) {
@@ -1064,13 +1067,29 @@ public void copyAsync(DataObject srcData, DataObject dstData, AsyncCompletionCal
10641067 Answer answer = copyVolume (srcData , dstData );
10651068 res = new CopyCommandResult (null , answer );
10661069 } else {
1067- Answer answer = new Answer (null , false , "noimpl" );
1068- res = new CopyCommandResult (null , answer );
1069- res .setResult ("Not implemented yet" );
1070+ throw new CloudRuntimeException ("Not implemented for Linstor primary storage." );
10701071 }
10711072 callback .complete (res );
10721073 }
10731074
1075+ private Host getEnabledClusterHost (StoragePool storagePool , List <String > linstorNodeNames ) {
1076+ List <HostVO > csHosts ;
1077+ if (storagePool .getClusterId () != null ) {
1078+ csHosts = _hostDao .findByClusterId (storagePool .getClusterId ());
1079+ } else {
1080+ csHosts = _hostDao .findByDataCenterId (storagePool .getDataCenterId ());
1081+ }
1082+ Collections .shuffle (csHosts ); // so we do not always pick the same host for operations
1083+ for (HostVO host : csHosts ) {
1084+ if (host .getResourceState () == ResourceState .Enabled &&
1085+ host .getStatus () == Status .Up &&
1086+ linstorNodeNames .contains (host .getName ())) {
1087+ return host ;
1088+ }
1089+ }
1090+ return null ;
1091+ }
1092+
10741093 /**
10751094 * Tries to get a Linstor cloudstack end point, that is at least diskless.
10761095 *
@@ -1079,47 +1098,37 @@ public void copyAsync(DataObject srcData, DataObject dstData, AsyncCompletionCal
10791098 * @return Optional RemoteHostEndPoint if one could get found.
10801099 * @throws ApiException
10811100 */
1082- private Optional <RemoteHostEndPoint > getLinstorEP (DevelopersApi api , String rscName ) throws ApiException {
1101+ private Optional <RemoteHostEndPoint > getLinstorEP (DevelopersApi api , StoragePool storagePool , String rscName )
1102+ throws ApiException {
10831103 List <String > linstorNodeNames = LinstorUtil .getLinstorNodeNames (api );
1084- Collections .shuffle (linstorNodeNames ); // do not always pick the first linstor node
1085-
1086- Host host = null ;
1087- for (String nodeName : linstorNodeNames ) {
1088- host = _hostDao .findByName (nodeName );
1089- if (host != null && host .getResourceState () == ResourceState .Enabled ) {
1090- logger .info (String .format ("Linstor: Make resource %s available on node %s ..." , rscName , nodeName ));
1091- ApiCallRcList answers = api .resourceMakeAvailableOnNode (rscName , nodeName , new ResourceMakeAvailable ());
1092- if (!answers .hasError ()) {
1093- break ; // found working host
1094- } else {
1095- logger .error (
1096- String .format ("Linstor: Unable to make resource %s on node %s available: %s" ,
1097- rscName ,
1098- nodeName ,
1099- LinstorUtil .getBestErrorMessage (answers )));
1100- }
1104+ Host host = getEnabledClusterHost (storagePool , linstorNodeNames );
1105+ if (host != null ) {
1106+ logger .info ("Linstor: Make resource {} available on node {} ..." , rscName , host .getName ());
1107+ ApiCallRcList answers = api .resourceMakeAvailableOnNode (
1108+ rscName , host .getName (), new ResourceMakeAvailable ());
1109+ if (answers .hasError ()) {
1110+ logger .error ("Linstor: Unable to make resource {} on node {} available: {}" ,
1111+ rscName , host .getName (), LinstorUtil .getBestErrorMessage (answers ));
1112+ return Optional .empty ();
1113+ } else {
1114+ return Optional .of (RemoteHostEndPoint .getHypervisorHostEndPoint (host ));
11011115 }
11021116 }
11031117
1104- if (host == null )
1105- {
1106- logger .error ("Linstor: Couldn't create a resource on any cloudstack host." );
1107- return Optional .empty ();
1108- }
1109- else
1110- {
1111- return Optional .of (RemoteHostEndPoint .getHypervisorHostEndPoint (host ));
1112- }
1118+ logger .error ("Linstor: Couldn't create a resource on any cloudstack host." );
1119+ return Optional .empty ();
11131120 }
11141121
1115- private Optional <RemoteHostEndPoint > getDiskfullEP (DevelopersApi api , String rscName ) throws ApiException {
1122+ private Optional <RemoteHostEndPoint > getDiskfullEP (DevelopersApi api , StoragePool storagePool , String rscName )
1123+ throws ApiException {
11161124 List <com .linbit .linstor .api .model .StoragePool > linSPs = LinstorUtil .getDiskfulStoragePools (api , rscName );
11171125 if (linSPs != null ) {
1118- for (com .linbit .linstor .api .model .StoragePool sp : linSPs ) {
1119- Host host = _hostDao .findByName (sp .getNodeName ());
1120- if (host != null && host .getResourceState () == ResourceState .Enabled ) {
1121- return Optional .of (RemoteHostEndPoint .getHypervisorHostEndPoint (host ));
1122- }
1126+ List <String > linstorNodeNames = linSPs .stream ()
1127+ .map (com .linbit .linstor .api .model .StoragePool ::getNodeName )
1128+ .collect (Collectors .toList ());
1129+ Host host = getEnabledClusterHost (storagePool , linstorNodeNames );
1130+ if (host != null ) {
1131+ return Optional .of (RemoteHostEndPoint .getHypervisorHostEndPoint (host ));
11231132 }
11241133 }
11251134 logger .error ("Linstor: No diskfull host found." );
@@ -1200,12 +1209,12 @@ private Answer copyTemplate(DataObject srcData, DataObject dstData) {
12001209 VirtualMachineManager .ExecuteInSequence .value ());
12011210
12021211 try {
1203- Optional <RemoteHostEndPoint > optEP = getLinstorEP (api , rscName );
1212+ Optional <RemoteHostEndPoint > optEP = getLinstorEP (api , pool , rscName );
12041213 if (optEP .isPresent ()) {
12051214 answer = optEP .get ().sendMessage (cmd );
12061215 } else {
1207- answer = new Answer (cmd , false , "Unable to get matching Linstor endpoint." );
12081216 deleteResourceDefinition (pool , rscName );
1217+ throw new CloudRuntimeException ("Unable to get matching Linstor endpoint." );
12091218 }
12101219 } catch (ApiException exc ) {
12111220 logger .error ("copy template failed: " , exc );
@@ -1242,12 +1251,12 @@ private Answer copyVolume(DataObject srcData, DataObject dstData) {
12421251 Answer answer ;
12431252
12441253 try {
1245- Optional <RemoteHostEndPoint > optEP = getLinstorEP (api , rscName );
1254+ Optional <RemoteHostEndPoint > optEP = getLinstorEP (api , pool , rscName );
12461255 if (optEP .isPresent ()) {
12471256 answer = optEP .get ().sendMessage (cmd );
12481257 }
12491258 else {
1250- answer = new Answer ( cmd , false , "Unable to get matching Linstor endpoint." );
1259+ throw new CloudRuntimeException ( "Unable to get matching Linstor endpoint." );
12511260 }
12521261 } catch (ApiException exc ) {
12531262 logger .error ("copy volume failed: " , exc );
@@ -1280,14 +1289,14 @@ private Answer copyFromTemporaryResource(
12801289 try {
12811290 String devName = restoreResourceFromSnapshot (api , pool , rscName , snapshotName , restoreName );
12821291
1283- Optional <RemoteHostEndPoint > optEPAny = getLinstorEP (api , restoreName );
1292+ Optional <RemoteHostEndPoint > optEPAny = getLinstorEP (api , pool , restoreName );
12841293 if (optEPAny .isPresent ()) {
12851294 // patch the src device path to the temporary linstor resource
12861295 snapshotObject .setPath (devName );
12871296 origCmd .setSrcTO (snapshotObject .getTO ());
12881297 answer = optEPAny .get ().sendMessage (origCmd );
1289- } else {
1290- answer = new Answer ( origCmd , false , "Unable to get matching Linstor endpoint." );
1298+ } else {
1299+ throw new CloudRuntimeException ( "Unable to get matching Linstor endpoint." );
12911300 }
12921301 } finally {
12931302 // delete the temporary resource, noop if already gone
@@ -1349,7 +1358,7 @@ protected Answer copySnapshot(DataObject srcData, DataObject destData) {
13491358 VirtualMachineManager .ExecuteInSequence .value ());
13501359 cmd .setOptions (options );
13511360
1352- Optional <RemoteHostEndPoint > optEP = getDiskfullEP (api , rscName );
1361+ Optional <RemoteHostEndPoint > optEP = getDiskfullEP (api , pool , rscName );
13531362 Answer answer ;
13541363 if (optEP .isPresent ()) {
13551364 answer = optEP .get ().sendMessage (cmd );
0 commit comments