Skip to content

Commit 3935ddf

Browse files
authored
CSI Volume Group Snapshots ONTAP-SAN NVMe
This commit extends the CSI Volume Group Snapshot feature to the ONTAP-SAN NVMe storage driver.
1 parent 78cd9b5 commit 3935ddf

File tree

2 files changed

+161
-0
lines changed

2 files changed

+161
-0
lines changed

storage_drivers/ontap/ontap_san_nvme.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1125,6 +1125,60 @@ func (d *NVMeStorageDriver) DeleteSnapshot(
11251125
return nil
11261126
}
11271127

1128+
// GetGroupSnapshotTarget returns a set of information about the target of a group snapshot.
1129+
// This information is used to gather information in a consistent way across storage drivers.
1130+
func (d *NVMeStorageDriver) GetGroupSnapshotTarget(
1131+
ctx context.Context, volConfigs []*storage.VolumeConfig,
1132+
) (*storage.GroupSnapshotTargetInfo, error) {
1133+
fields := LogFields{
1134+
"Method": "GetGroupSnapshotTarget",
1135+
"Type": "NVMeStorageDriver",
1136+
}
1137+
Logd(ctx, d.Name(), d.Config.DebugTraceFlags["method"]).WithFields(fields).Trace(">>>> GetGroupSnapshotTarget")
1138+
defer Logd(ctx, d.Name(), d.Config.DebugTraceFlags["method"]).WithFields(fields).Trace("<<<< GetGroupSnapshotTarget")
1139+
1140+
return GetGroupSnapshotTarget(ctx, volConfigs, &d.Config, d.API)
1141+
}
1142+
1143+
func (d *NVMeStorageDriver) CreateGroupSnapshot(
1144+
ctx context.Context, config *storage.GroupSnapshotConfig, target *storage.GroupSnapshotTargetInfo,
1145+
) error {
1146+
fields := LogFields{
1147+
"Method": "CreateGroupSnapshot",
1148+
"Type": "NVMeStorageDriver",
1149+
}
1150+
Logd(ctx, d.Name(), d.Config.DebugTraceFlags["method"]).WithFields(fields).Trace(">>>> CreateGroupSnapshot")
1151+
defer Logd(ctx, d.Name(), d.Config.DebugTraceFlags["method"]).WithFields(fields).Trace("<<<< CreateGroupSnapshot")
1152+
1153+
return CreateGroupSnapshot(ctx, config, target, &d.Config, d.API)
1154+
}
1155+
1156+
func (d *NVMeStorageDriver) ProcessGroupSnapshot(
1157+
ctx context.Context, config *storage.GroupSnapshotConfig, volConfigs []*storage.VolumeConfig,
1158+
) ([]*storage.Snapshot, error) {
1159+
fields := LogFields{
1160+
"Method": "ProcessGroupSnapshot",
1161+
"Type": "NVMeStorageDriver",
1162+
}
1163+
Logd(ctx, d.Name(), d.Config.DebugTraceFlags["method"]).WithFields(fields).Trace(">>>> ProcessGroupSnapshot")
1164+
defer Logd(ctx, d.Name(), d.Config.DebugTraceFlags["method"]).WithFields(fields).Trace("<<<< ProcessGroupSnapshot")
1165+
1166+
return ProcessGroupSnapshot(ctx, config, volConfigs, &d.Config, d.API, d.namespaceSize)
1167+
}
1168+
1169+
func (d *NVMeStorageDriver) ConstructGroupSnapshot(
1170+
ctx context.Context, config *storage.GroupSnapshotConfig, snapshots []*storage.Snapshot,
1171+
) (*storage.GroupSnapshot, error) {
1172+
fields := LogFields{
1173+
"Method": "ConstructGroupSnapshot",
1174+
"Type": "NVMeStorageDriver",
1175+
}
1176+
Logd(ctx, d.Name(), d.Config.DebugTraceFlags["method"]).WithFields(fields).Trace(">>>> ConstructGroupSnapshot")
1177+
defer Logd(ctx, d.Name(), d.Config.DebugTraceFlags["method"]).WithFields(fields).Trace("<<<< ConstructGroupSnapshot")
1178+
1179+
return ConstructGroupSnapshot(ctx, config, snapshots, &d.Config)
1180+
}
1181+
11281182
// Get tests for the existence of a volume.
11291183
func (d *NVMeStorageDriver) Get(ctx context.Context, name string) error {
11301184
fields := LogFields{

storage_drivers/ontap/ontap_san_nvme_test.go

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2908,6 +2908,113 @@ func TestNVMeDeleteSnapshot_Error(t *testing.T) {
29082908
assert.Error(t, err)
29092909
}
29102910

2911+
func TestNVMeCreateVolumeGroupSnapshot(t *testing.T) {
2912+
ctx := context.Background()
2913+
2914+
driver, mockAPI := newNVMeDriverAndMockApi(t)
2915+
mockAPI.EXPECT().SVMName().AnyTimes().Return("SVM1")
2916+
mockAPI.EXPECT().IsDisaggregated().AnyTimes().Return(false)
2917+
2918+
groupSnapshotConfig := &storage.GroupSnapshotConfig{
2919+
Name: "groupsnapshot-1234",
2920+
InternalName: "groupsnapshot-1234",
2921+
VolumeNames: []string{"vol1", "vol2"},
2922+
}
2923+
storageVols := storage.GroupSnapshotTargetVolumes{
2924+
"trident_vol1": {
2925+
"vol1": &storage.VolumeConfig{Name: "vol1"},
2926+
},
2927+
"trident_vol2": {
2928+
"vol2": &storage.VolumeConfig{Name: "vol2"},
2929+
},
2930+
}
2931+
targetInfo := &storage.GroupSnapshotTargetInfo{
2932+
StorageType: "unified",
2933+
StorageUUID: "12345",
2934+
StorageVolumes: storageVols,
2935+
}
2936+
storageVolNames := []string{"trident_vol1", "trident_vol2"}
2937+
snapName, _ := storage.ConvertGroupSnapshotID(groupSnapshotConfig.Name)
2938+
2939+
mockAPI.EXPECT().ConsistencyGroupSnapshot(ctx, snapName, gomock.InAnyOrder(storageVolNames)).Return(nil).Times(1)
2940+
2941+
err := driver.CreateGroupSnapshot(ctx, groupSnapshotConfig, targetInfo)
2942+
assert.NoError(t, err, "Group snapshot creation failed")
2943+
}
2944+
2945+
func TestNVMeProcessVolumeGroupSnapshot(t *testing.T) {
2946+
ctx := context.Background()
2947+
2948+
driver, mockAPI := newNVMeDriverAndMockApi(t)
2949+
mockAPI.EXPECT().SVMName().AnyTimes().Return("SVM1")
2950+
mockAPI.EXPECT().IsDisaggregated().AnyTimes().Return(false)
2951+
2952+
groupSnapshotConfig := &storage.GroupSnapshotConfig{
2953+
Name: "groupsnapshot-1234",
2954+
InternalName: "groupsnapshot-1234",
2955+
VolumeNames: []string{"vol1", "vol2"},
2956+
}
2957+
storageVols := []*storage.VolumeConfig{
2958+
{Name: "vol1"},
2959+
{Name: "vol2"},
2960+
}
2961+
snapName, _ := storage.ConvertGroupSnapshotID(groupSnapshotConfig.Name)
2962+
snapInfoResult := api.Snapshot{CreateTime: "1"}
2963+
size := 1073741824
2964+
2965+
mockAPI.EXPECT().VolumeSnapshotInfo(ctx, snapName, gomock.Any()).Return(snapInfoResult, nil).Times(2)
2966+
mockAPI.EXPECT().NVMeNamespaceGetSize(ctx, gomock.Any()).Return(1073741824, nil).Times(2)
2967+
2968+
snaps, err := driver.ProcessGroupSnapshot(ctx, groupSnapshotConfig, storageVols)
2969+
assert.NoError(t, err, "Group snapshot processing failed")
2970+
assert.NotNil(t, snaps, "Grouped snapshot extraction failed")
2971+
for _, snap := range snaps {
2972+
assert.Equal(t, snapName, snap.Config.Name)
2973+
assert.Equal(t, int64(size), snap.SizeBytes)
2974+
}
2975+
}
2976+
2977+
func TestNVMeGetGroupSnapshotTarget(t *testing.T) {
2978+
ctx := context.Background()
2979+
2980+
driver, mockAPI := newNVMeDriverAndMockApi(t)
2981+
mockAPI.EXPECT().SVMName().AnyTimes().Return("SVM1")
2982+
mockAPI.EXPECT().IsDisaggregated().AnyTimes().Return(false)
2983+
2984+
volumeConfigs := []*storage.VolumeConfig{
2985+
{
2986+
Name: "vol1",
2987+
InternalName: "trident_vol1",
2988+
},
2989+
{
2990+
Name: "vol2",
2991+
InternalName: "trident_vol2",
2992+
},
2993+
}
2994+
2995+
storageVols := storage.GroupSnapshotTargetVolumes{
2996+
"trident_vol1": {
2997+
"vol1": &storage.VolumeConfig{Name: "vol1", InternalName: "trident_vol1"},
2998+
},
2999+
"trident_vol2": {
3000+
"vol2": &storage.VolumeConfig{Name: "vol2", InternalName: "trident_vol2"},
3001+
},
3002+
}
3003+
expectedTargetInfo := &storage.GroupSnapshotTargetInfo{
3004+
StorageType: "Unified",
3005+
StorageUUID: "12345",
3006+
StorageVolumes: storageVols,
3007+
}
3008+
3009+
mockAPI.EXPECT().GetSVMUUID().Return("12345").Times(1)
3010+
mockAPI.EXPECT().VolumeExists(ctx, gomock.Any()).Return(true, nil).Times(2)
3011+
3012+
targetInfo, err := driver.GetGroupSnapshotTarget(ctx, volumeConfigs)
3013+
3014+
assert.Equal(t, targetInfo, expectedTargetInfo)
3015+
assert.NoError(t, err, "Volume group target failed")
3016+
}
3017+
29113018
// Phase 3: Volume Management Tests
29123019
func TestNVMeGet_Success(t *testing.T) {
29133020
d, mAPI := newNVMeDriverAndMockApi(t)

0 commit comments

Comments
 (0)