100100import org .apache .cloudstack .storage .datastore .db .StoragePoolVO ;
101101import org .apache .cloudstack .storage .datastore .util .LinstorConfigurationManager ;
102102import org .apache .cloudstack .storage .datastore .util .LinstorUtil ;
103+ import org .apache .cloudstack .storage .snapshot .SnapshotObject ;
103104import org .apache .cloudstack .storage .to .SnapshotObjectTO ;
104105import org .apache .cloudstack .storage .to .VolumeObjectTO ;
105106import org .apache .cloudstack .storage .volume .VolumeObject ;
@@ -230,7 +231,7 @@ private void deleteSnapshot(@Nonnull DataStore dataStore, @Nonnull String rscDef
230231
231232 try
232233 {
233- ApiCallRcList answers = linstorApi .resourceSnapshotDelete (rscDefName , snapshotName );
234+ ApiCallRcList answers = linstorApi .resourceSnapshotDelete (rscDefName , snapshotName , Collections . emptyList () );
234235 if (answers .hasError ())
235236 {
236237 for (ApiCallRc answer : answers )
@@ -1004,25 +1005,29 @@ private Answer copyVolume(DataObject srcData, DataObject dstData) {
10041005 * @param api Linstor Developer api object
10051006 * @param pool StoragePool this resource resides on
10061007 * @param rscName rscName of the snapshotted resource
1007- * @param snapshotInfo snapshot info of the snapshot
1008+ * @param snapshotName Name of the snapshot to copy from
1009+ * @param snapshotObject snapshot object of the origCmd, so the path can be modified
10081010 * @param origCmd original LinstorBackupSnapshotCommand that needs to have a patched path
10091011 * @return answer from agent operation
10101012 * @throws ApiException if any Linstor api operation fails
10111013 */
10121014 private Answer copyFromTemporaryResource (
1013- DevelopersApi api , StoragePoolVO pool , String rscName , SnapshotInfo snapshotInfo , CopyCommand origCmd )
1015+ DevelopersApi api ,
1016+ StoragePoolVO pool ,
1017+ String rscName ,
1018+ String snapshotName ,
1019+ SnapshotObject snapshotObject ,
1020+ CopyCommand origCmd )
10141021 throws ApiException {
10151022 Answer answer ;
10161023 String restoreName = rscName + "-rst" ;
1017- String snapshotName = LinstorUtil .RSC_PREFIX + snapshotInfo .getUuid ();
10181024 String devName = restoreResourceFromSnapshot (api , pool , rscName , snapshotName , restoreName );
10191025
10201026 Optional <RemoteHostEndPoint > optEPAny = getLinstorEP (api , restoreName );
10211027 if (optEPAny .isPresent ()) {
10221028 // patch the src device path to the temporary linstor resource
1023- SnapshotObjectTO soTO = (SnapshotObjectTO )snapshotInfo .getTO ();
1024- soTO .setPath (devName );
1025- origCmd .setSrcTO (soTO );
1029+ snapshotObject .setPath (devName );
1030+ origCmd .setSrcTO (snapshotObject .getTO ());
10261031 answer = optEPAny .get ().sendMessage (origCmd );
10271032 } else {
10281033 answer = new Answer (origCmd , false , "Unable to get matching Linstor endpoint." );
@@ -1032,13 +1037,36 @@ private Answer copyFromTemporaryResource(
10321037 return answer ;
10331038 }
10341039
1040+ /**
1041+ * vmsnapshots don't have our typical snapshot path set
1042+ * instead the path is the internal snapshot name e.g.: {vm}_VS_{datestr}
1043+ * we have to find out and modify the path here before
1044+ * @return the original snapshotObject.getPath()
1045+ */
1046+ private String setCorrectSnapshotPath (DevelopersApi api , String rscName , SnapshotObject snapshotObject )
1047+ throws ApiException {
1048+ String originalPath = LinstorUtil .RSC_PREFIX + snapshotObject .getUuid ();
1049+ if (!(snapshotObject .getPath ().startsWith ("/dev/mapper/" ) ||
1050+ snapshotObject .getPath ().startsWith ("zfs://" ))) {
1051+ originalPath = snapshotObject .getPath ();
1052+ com .linbit .linstor .api .model .StoragePool linStoragePool =
1053+ LinstorUtil .getDiskfulStoragePool (api , rscName );
1054+ if (linStoragePool == null ) {
1055+ throw new CloudRuntimeException ("Linstor: Unable to find storage pool for resource " + rscName );
1056+ }
1057+ final String path = LinstorUtil .getSnapshotPath (linStoragePool , rscName , snapshotObject .getPath ());
1058+ snapshotObject .setPath (path );
1059+ }
1060+ return originalPath ;
1061+ }
1062+
10351063 protected Answer copySnapshot (DataObject srcData , DataObject destData ) {
10361064 String value = _configDao .getValue (Config .BackupSnapshotWait .toString ());
10371065 int _backupsnapshotwait = NumbersUtil .parseInt (
10381066 value , Integer .parseInt (Config .BackupSnapshotWait .getDefaultValue ()));
10391067
1040- SnapshotInfo snapshotInfo = (SnapshotInfo )srcData ;
1041- Boolean snapshotFullBackup = snapshotInfo .getFullBackup ();
1068+ SnapshotObject snapshotObject = (SnapshotObject )srcData ;
1069+ Boolean snapshotFullBackup = snapshotObject .getFullBackup ();
10421070 final StoragePoolVO pool = _storagePoolDao .findById (srcData .getDataStore ().getId ());
10431071 final DevelopersApi api = LinstorUtil .getLinstorAPI (pool .getHostAddress ());
10441072 boolean fullSnapshot = true ;
@@ -1049,29 +1077,31 @@ protected Answer copySnapshot(DataObject srcData, DataObject destData) {
10491077 options .put ("fullSnapshot" , fullSnapshot + "" );
10501078 options .put (SnapshotInfo .BackupSnapshotAfterTakingSnapshot .key (),
10511079 String .valueOf (SnapshotInfo .BackupSnapshotAfterTakingSnapshot .value ()));
1052- options .put ("volumeSize" , snapshotInfo .getBaseVolume ().getSize () + "" );
1080+ options .put ("volumeSize" , snapshotObject .getBaseVolume ().getSize () + "" );
10531081
10541082 try {
1083+ final String rscName = LinstorUtil .RSC_PREFIX + snapshotObject .getBaseVolume ().getUuid ();
1084+ String snapshotName = setCorrectSnapshotPath (api , rscName , snapshotObject );
1085+
10551086 CopyCommand cmd = new LinstorBackupSnapshotCommand (
1056- srcData .getTO (),
1087+ snapshotObject .getTO (),
10571088 destData .getTO (),
10581089 _backupsnapshotwait ,
10591090 VirtualMachineManager .ExecuteInSequence .value ());
10601091 cmd .setOptions (options );
10611092
1062- String rscName = LinstorUtil .RSC_PREFIX + snapshotInfo .getBaseVolume ().getUuid ();
10631093 Optional <RemoteHostEndPoint > optEP = getDiskfullEP (api , rscName );
10641094 Answer answer ;
10651095 if (optEP .isPresent ()) {
10661096 answer = optEP .get ().sendMessage (cmd );
10671097 } else {
10681098 s_logger .debug ("No diskfull endpoint found to copy image, creating diskless endpoint" );
1069- answer = copyFromTemporaryResource (api , pool , rscName , snapshotInfo , cmd );
1099+ answer = copyFromTemporaryResource (api , pool , rscName , snapshotName , snapshotObject , cmd );
10701100 }
10711101 return answer ;
10721102 } catch (Exception e ) {
10731103 s_logger .debug ("copy snapshot failed: " , e );
1074- throw new CloudRuntimeException (e . toString () );
1104+ throw new CloudRuntimeException ("Copy snapshot failed, please cleanup snapshot manually: " + e );
10751105 }
10761106
10771107 }
0 commit comments