@@ -1026,6 +1026,82 @@ protected Answer backupSnapshotForObjectStore(final CopyCommand cmd) {
10261026 return copyToObjectStore (newCpyCmd );
10271027 }
10281028
1029+ /**
1030+ * Backs up a snapshot from managed storage (e.g., ONTAP iSCSI) to secondary storage.
1031+ * Connects to the iSCSI LUN using the IQN/path from the CopyCommand options, copies
1032+ * the raw disk data to the NFS secondary storage.
1033+ *
1034+ * This mirrors the approach used by {@link #createTemplateFromVolumeOrSnapshot(CopyCommand)}.
1035+ */
1036+ private Answer backupSnapshotFromManagedStorage (final CopyCommand cmd ) {
1037+ final DataTO srcData = cmd .getSrcTO ();
1038+ final DataTO destData = cmd .getDestTO ();
1039+ final SnapshotObjectTO snapshot = (SnapshotObjectTO ) srcData ;
1040+ final PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO ) snapshot .getDataStore ();
1041+ final SnapshotObjectTO destSnapshot = (SnapshotObjectTO ) destData ;
1042+ final DataStoreTO imageStore = destData .getDataStore ();
1043+
1044+ if (!(imageStore instanceof NfsTO )) {
1045+ return new CopyCmdAnswer ("backupSnapshotFromManagedStorage: unsupported secondary storage protocol" );
1046+ }
1047+
1048+ final NfsTO nfsImageStore = (NfsTO ) imageStore ;
1049+ KVMStoragePool secondaryStorage = null ;
1050+ String path = null ;
1051+
1052+ try {
1053+ final Map <String , String > details = cmd .getOptions ();
1054+ path = details != null ? details .get (DiskTO .PATH ) : null ;
1055+ if (path == null ) {
1056+ path = details != null ? details .get (DiskTO .IQN ) : null ;
1057+ if (path == null ) {
1058+ return new CopyCmdAnswer ("backupSnapshotFromManagedStorage: IQN or PATH is required in options" );
1059+ }
1060+ }
1061+
1062+ logger .info ("backupSnapshotFromManagedStorage: Connecting to managed storage, poolType={}, poolUuid={}, path={}" ,
1063+ primaryStore .getPoolType (), primaryStore .getUuid (), path );
1064+
1065+ storagePoolMgr .connectPhysicalDisk (primaryStore .getPoolType (), primaryStore .getUuid (), path , details );
1066+
1067+ final KVMPhysicalDisk srcDisk = storagePoolMgr .getPhysicalDisk (primaryStore .getPoolType (), primaryStore .getUuid (), path );
1068+
1069+ secondaryStorage = storagePoolMgr .getStoragePoolByURI (nfsImageStore .getUrl ());
1070+
1071+ final String snapshotRelPath = destSnapshot .getPath ();
1072+ final String snapshotDestPath = secondaryStorage .getLocalPath () + File .separator + snapshotRelPath ;
1073+
1074+ storageLayer .mkdirs (snapshotDestPath );
1075+
1076+ final String snapshotName = UUID .randomUUID ().toString ();
1077+ final String destName = snapshotRelPath + "/" + snapshotName ;
1078+
1079+ logger .info ("backupSnapshotFromManagedStorage: Copying {} disk {} to {}" ,
1080+ srcDisk .getFormat (), srcDisk .getPath (), destName );
1081+
1082+ storagePoolMgr .copyPhysicalDisk (srcDisk , destName , secondaryStorage , cmd .getWaitInMillSeconds ());
1083+
1084+ final File snapFile = new File (snapshotDestPath + "/" + snapshotName );
1085+ final long size = snapFile .exists () ? snapFile .length () : 0 ;
1086+
1087+ final SnapshotObjectTO newSnapshot = new SnapshotObjectTO ();
1088+ newSnapshot .setPath (snapshotRelPath + File .separator + snapshotName );
1089+ newSnapshot .setPhysicalSize (size );
1090+
1091+ return new CopyCmdAnswer (newSnapshot );
1092+ } catch (final Exception ex ) {
1093+ logger .error ("backupSnapshotFromManagedStorage: Failed to backup snapshot" , ex );
1094+ return new CopyCmdAnswer ("backupSnapshotFromManagedStorage: " + ex .getMessage ());
1095+ } finally {
1096+ if (path != null ) {
1097+ storagePoolMgr .disconnectPhysicalDisk (primaryStore .getPoolType (), primaryStore .getUuid (), path );
1098+ }
1099+ if (secondaryStorage != null ) {
1100+ secondaryStorage .delete ();
1101+ }
1102+ }
1103+ }
1104+
10291105 @ Override
10301106 public Answer backupSnapshot (final CopyCommand cmd ) {
10311107 final DataTO srcData = cmd .getSrcTO ();
@@ -1035,6 +1111,16 @@ public Answer backupSnapshot(final CopyCommand cmd) {
10351111 final SnapshotObjectTO destSnapshot = (SnapshotObjectTO )destData ;
10361112 final DataStoreTO imageStore = destData .getDataStore ();
10371113
1114+ // For managed storage (e.g., ONTAP iSCSI), the IQN/path is passed in options
1115+ // by grantAccessForSnapshot(). Route to the managed-storage handler which connects
1116+ // to the iSCSI device and copies the raw data to secondary storage.
1117+ final Map <String , String > srcDetails = cmd .getOptions ();
1118+ logger .info ("backupSnapshot: Received request to backup snapshot with srcDetails: {}" , srcDetails );
1119+ if (srcDetails != null && (srcDetails .get (DiskTO .IQN ) != null || srcDetails .get (DiskTO .PATH ) != null )) {
1120+ logger .info ("backupSnapshot: backupSnapshotFromManagedStorage: {}" , cmd .toString ());
1121+ return backupSnapshotFromManagedStorage (cmd );
1122+ }
1123+
10381124 if (!(imageStore instanceof NfsTO )) {
10391125 return backupSnapshotForObjectStore (cmd );
10401126 }
0 commit comments