Skip to content

Commit e838277

Browse files
committed
Added add, get and remove methods on the pvcToSnapshotsMap
Added GetSnapshotsForPVC method on COCommonInterface interface and it's implementors Updated GetSnapshotsForPVC method of K8sOrchestrator to return the snapshots associated with the given PVC
1 parent eddf93b commit e838277

File tree

6 files changed

+159
-97
lines changed

6 files changed

+159
-97
lines changed

pkg/common/unittestcommon/utils.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,11 @@ func (c *FakeK8SOrchestrator) SetCSINodeTopologyInstances(instances []interface{
516516
c.csiNodeTopologyInstances = instances
517517
}
518518

519+
func (c *FakeK8SOrchestrator) GetSnapshotsForPVC(ctx context.Context, pvcName, namespace string) []string {
520+
//TODO implement me
521+
panic("implement me")
522+
}
523+
519524
// configFromVCSim starts a vcsim instance and returns config for use against the
520525
// vcsim instance. The vcsim instance is configured with an empty tls.Config.
521526
func configFromVCSim(vcsimParams VcsimParams, isTopologyEnv bool) (*config.Config, func()) {

pkg/csi/service/common/commonco/coagnostic.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,8 @@ type COCommonInterface interface {
128128
// GetPVCNamespacedNameByUID returns the PVC's namespaced name (namespace/name) for the given UID.
129129
// If the PVC is not found in the cache, it returns an empty string and false.
130130
GetPVCNamespacedNameByUID(uid string) (k8stypes.NamespacedName, bool)
131+
// GetSnapshotsForPVC returns the names of the snapshots for the given PVC
132+
GetSnapshotsForPVC(ctx context.Context, pvcName, namespace string) []string
131133
}
132134

133135
// GetContainerOrchestratorInterface returns orchestrator object for a given

pkg/csi/service/common/commonco/k8sorchestrator/k8sorchestrator.go

Lines changed: 138 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,71 @@ type pvcToSnapshotsMap struct {
256256
items map[namespacedName]map[namespacedName]struct{}
257257
}
258258

259+
func (m *pvcToSnapshotsMap) add(pvc, snapshot, namespace string) {
260+
m.Lock()
261+
defer m.Unlock()
262+
263+
pvcKey := namespacedName{
264+
namespace: namespace,
265+
name: pvc,
266+
}
267+
if _, ok := m.items[pvcKey]; !ok {
268+
m.items[pvcKey] = make(map[namespacedName]struct{})
269+
}
270+
snapKey := namespacedName{
271+
namespace: namespace,
272+
name: snapshot,
273+
}
274+
m.items[pvcKey][snapKey] = struct{}{}
275+
}
276+
277+
func (m *pvcToSnapshotsMap) get(pvc, namespace string) []string {
278+
m.RLock()
279+
defer m.RUnlock()
280+
281+
pvcKey := namespacedName{
282+
namespace: namespace,
283+
name: pvc,
284+
}
285+
snapMap, ok := m.items[pvcKey]
286+
if !ok {
287+
return []string{}
288+
}
289+
290+
snaps := make([]string, 0, len(snapMap))
291+
for k := range snapMap {
292+
snaps = append(snaps, k.name)
293+
}
294+
return snaps
295+
}
296+
297+
func (m *pvcToSnapshotsMap) delete(pvc, snapshot, namespace string) {
298+
m.Lock()
299+
defer m.Unlock()
300+
301+
pvcKey := namespacedName{
302+
namespace: namespace,
303+
name: pvc,
304+
}
305+
snapMap, ok := m.items[pvcKey]
306+
if !ok {
307+
return
308+
}
309+
310+
snapKey := namespacedName{
311+
namespace: namespace,
312+
name: snapshot,
313+
}
314+
delete(snapMap, snapKey)
315+
if len(snapMap) != 0 {
316+
m.items[pvcKey] = snapMap
317+
return
318+
}
319+
320+
// delete pvc entry if no snapshots are present
321+
delete(m.items, pvcKey)
322+
}
323+
259324
// K8sOrchestrator defines set of properties specific to K8s.
260325
type K8sOrchestrator struct {
261326
supervisorFSS FSSConfigMapInfo
@@ -1968,6 +2033,74 @@ func nodeRemove(obj interface{}) {
19682033
k8sOrchestratorInstance.nodeIDToNameMap.remove(nodeMoID)
19692034
}
19702035

2036+
func initPVCToSnapshotsMap(ctx context.Context, controllerClusterFlavor cnstypes.CnsClusterFlavor) error {
2037+
log := logger.GetLogger(ctx)
2038+
// TODO: check if we need to check the FSS as well
2039+
if controllerClusterFlavor != cnstypes.CnsClusterFlavorWorkload {
2040+
// PVC to VolumeSnapshot cache is only required for WCP for now.
2041+
log.Info("non WCP cluster detected. skipping initialising PVC to Snapshot cache.")
2042+
return nil
2043+
}
2044+
2045+
k8sOrchestratorInstance.pvcToSnapshotsMap = pvcToSnapshotsMap{
2046+
RWMutex: &sync.RWMutex{},
2047+
items: make(map[namespacedName]map[namespacedName]struct{}),
2048+
}
2049+
snapshotAdded := func(obj any) {
2050+
snap, ok := obj.(*snapshotv1.VolumeSnapshot)
2051+
if !ok || snap == nil {
2052+
log.Warnf("unrecognized object %+v", obj)
2053+
return
2054+
}
2055+
2056+
log.Infof("snapshotAdded: snapshot=%v", snap)
2057+
if snap.Spec.Source.PersistentVolumeClaimName == nil {
2058+
log.Warnf("snapshot is not associated with any PVC. Ignoring it...")
2059+
return
2060+
}
2061+
2062+
k8sOrchestratorInstance.pvcToSnapshotsMap.add(
2063+
*snap.Spec.Source.PersistentVolumeClaimName, snap.Name, snap.Namespace)
2064+
log.With("pvc", *snap.Spec.Source.PersistentVolumeClaimName).With("snapshot", snap.Name).
2065+
With("namespace", snap.Namespace).Debug("successfully added the snapshot to the cache")
2066+
}
2067+
snapshotDeleted := func(obj any) {
2068+
snap, ok := obj.(*snapshotv1.VolumeSnapshot)
2069+
if !ok || snap == nil {
2070+
log.Warnf("unrecognized object %+v", obj)
2071+
return
2072+
}
2073+
2074+
log.Infof("snapshotDeleted: snapshot=%v", snap)
2075+
if snap.Spec.Source.PersistentVolumeClaimName == nil {
2076+
log.Warnf("snapshot is not associated with any PVC. Ignoring it...")
2077+
return
2078+
}
2079+
2080+
k8sOrchestratorInstance.pvcToSnapshotsMap.delete(
2081+
*snap.Spec.Source.PersistentVolumeClaimName, snap.Name, snap.Namespace)
2082+
log.With("pvc", *snap.Spec.Source.PersistentVolumeClaimName).With("snapshot", snap.Name).
2083+
With("namespace", snap.Namespace).Debug("successfully removed the snapshot from the cache")
2084+
}
2085+
2086+
err := k8sOrchestratorInstance.informerManager.AddSnapshotListener(ctx,
2087+
func(obj any) {
2088+
snapshotAdded(obj)
2089+
},
2090+
func(oldObj, newObj any) {
2091+
// TODO: implement or remove as we probably don't need to take any action
2092+
log.Info("snapshotUpdated")
2093+
},
2094+
func(obj any) {
2095+
snapshotDeleted(obj)
2096+
})
2097+
if err != nil {
2098+
return logger.LogNewErrorf(log, "failed to listen on volumesnapshots. Error: %v", err)
2099+
}
2100+
2101+
return nil
2102+
}
2103+
19712104
// GetNodeIDtoNameMap returns a map containing the nodeID to node name
19722105
func (c *K8sOrchestrator) GetNodeIDtoNameMap(ctx context.Context) map[string]string {
19732106
return c.nodeIDToNameMap.items
@@ -2282,6 +2415,11 @@ func (c *K8sOrchestrator) GetPVCNamespacedNameByUID(uid string) (k8stypes.Namesp
22822415
return nsName, true
22832416
}
22842417

2418+
// GetSnapshotsForPVC returns the names of the snapshots for the given PVC
2419+
func (c *K8sOrchestrator) GetSnapshotsForPVC(ctx context.Context, pvc, namespace string) []string {
2420+
return c.pvcToSnapshotsMap.get(pvc, namespace)
2421+
}
2422+
22852423
// GetPVCDataSource Retrieves the VolumeSnapshot source when a PVC from VolumeSnapshot is being created.
22862424
func GetPVCDataSource(ctx context.Context, claim *v1.PersistentVolumeClaim) (*v1.ObjectReference, error) {
22872425
var dataSource v1.ObjectReference
@@ -2309,98 +2447,3 @@ func GetPVCDataSource(ctx context.Context, claim *v1.PersistentVolumeClaim) (*v1
23092447
}
23102448
return &dataSource, nil
23112449
}
2312-
2313-
func initPVCToSnapshotsMap(ctx context.Context, controllerClusterFlavor cnstypes.CnsClusterFlavor) error {
2314-
log := logger.GetLogger(ctx)
2315-
if controllerClusterFlavor != cnstypes.CnsClusterFlavorWorkload {
2316-
// PVC to VolumeSnapshot cache is only required for WCP for now.
2317-
log.Info("non WCP cluster detected. skipping initialising PVC to Snapshot cache.")
2318-
return nil
2319-
}
2320-
2321-
k8sOrchestratorInstance.pvcToSnapshotsMap = pvcToSnapshotsMap{
2322-
RWMutex: &sync.RWMutex{},
2323-
items: make(map[namespacedName]map[namespacedName]struct{}),
2324-
}
2325-
2326-
snapshotAdded := func(obj any) {
2327-
snap, ok := obj.(*snapshotv1.VolumeSnapshot)
2328-
if !ok || snap == nil {
2329-
log.Warnf("snapshotAdded: unrecognized object %+v", obj)
2330-
return
2331-
}
2332-
2333-
log.Infof("snapshotAdded: snapshot=%v", snap)
2334-
if snap.Spec.Source.PersistentVolumeClaimName == nil {
2335-
log.Warnf("snapshotAdded: snapshot is not associated with any PVC. Ignoring it...")
2336-
return
2337-
}
2338-
2339-
k8sOrchestratorInstance.pvcToSnapshotsMap.Lock()
2340-
defer k8sOrchestratorInstance.pvcToSnapshotsMap.Unlock()
2341-
2342-
pvcName := namespacedName{
2343-
namespace: snap.Namespace,
2344-
name: *snap.Spec.Source.PersistentVolumeClaimName,
2345-
}
2346-
if _, ok := k8sOrchestratorInstance.pvcToSnapshotsMap.items[pvcName]; !ok {
2347-
k8sOrchestratorInstance.pvcToSnapshotsMap.items[pvcName] = make(map[namespacedName]struct{})
2348-
}
2349-
snapName := namespacedName{
2350-
namespace: snap.Namespace,
2351-
name: snap.Name,
2352-
}
2353-
k8sOrchestratorInstance.pvcToSnapshotsMap.items[pvcName][snapName] = struct{}{}
2354-
log.With("pvc", pvcName).With("snapshot", snapName).Debug("successfully added the snapshot to the cache")
2355-
}
2356-
2357-
snapshotDeleted := func(obj any) {
2358-
snap, ok := obj.(*snapshotv1.VolumeSnapshot)
2359-
if !ok || snap == nil {
2360-
log.Warnf("snapshotDeleted: unrecognized object %+v", obj)
2361-
return
2362-
}
2363-
2364-
log.Infof("snapshotDeleted: snapshot=%v", snap)
2365-
if snap.Spec.Source.PersistentVolumeClaimName == nil {
2366-
log.Warnf("snapshotDeleted: snapshot is not associated with any PVC. Ignoring it...")
2367-
return
2368-
}
2369-
2370-
k8sOrchestratorInstance.pvcToSnapshotsMap.Lock()
2371-
defer k8sOrchestratorInstance.pvcToSnapshotsMap.Unlock()
2372-
2373-
pvcName := namespacedName{
2374-
namespace: snap.Namespace,
2375-
name: *snap.Spec.Source.PersistentVolumeClaimName,
2376-
}
2377-
if _, ok := k8sOrchestratorInstance.pvcToSnapshotsMap.items[pvcName]; !ok {
2378-
log.Infof("snapshotDeleted: associated PVC %s not found in the map. Ignoring the delete event...", pvcName)
2379-
return
2380-
}
2381-
2382-
snapName := namespacedName{
2383-
namespace: snap.Namespace,
2384-
name: snap.Name,
2385-
}
2386-
delete(k8sOrchestratorInstance.pvcToSnapshotsMap.items[pvcName], snapName)
2387-
log.With("pvc", pvcName).With("snapshot", snapName).Debug("successfully removed the snapshot from the cache")
2388-
}
2389-
2390-
err := k8sOrchestratorInstance.informerManager.AddSnapshotListener(ctx,
2391-
func(obj any) {
2392-
snapshotAdded(obj)
2393-
},
2394-
func(oldObj, newObj any) {
2395-
// TODO: implement
2396-
log.Info("snapshotUpdated")
2397-
},
2398-
func(obj any) {
2399-
snapshotDeleted(obj)
2400-
})
2401-
if err != nil {
2402-
return logger.LogNewErrorf(log, "failed to listen on volumesnapshots. Error: %v", err)
2403-
}
2404-
2405-
return nil
2406-
}

pkg/kubernetes/informers.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -267,8 +267,10 @@ func (im *InformerManager) AddVolumeAttachmentListener(ctx context.Context, add
267267
}
268268

269269
// AddSnapshotListener hooks up add, update, delete callbacks.
270-
func (im *InformerManager) AddSnapshotListener(ctx context.Context, add func(obj interface{}),
271-
update func(oldObj, newObj interface{}), remove func(obj interface{})) error {
270+
func (im *InformerManager) AddSnapshotListener(ctx context.Context,
271+
add func(obj interface{}),
272+
update func(oldObj, newObj interface{}),
273+
remove func(obj interface{})) error {
272274
log := logger.GetLogger(ctx)
273275
if im.snapshotInformer == nil {
274276
im.snapshotInformer = im.snapshotInformerFactory.

pkg/syncer/admissionhandler/cnscsi_admissionhandler_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ type MockCOCommonInterface struct {
4747
mock.Mock
4848
}
4949

50+
func (m *MockCOCommonInterface) GetSnapshotsForPVC(ctx context.Context, pvcName, namespace string) []string {
51+
//TODO implement me
52+
panic("implement me")
53+
}
54+
5055
func (m *MockCOCommonInterface) GetPVCNamespacedNameByUID(uid string) (apitypes.NamespacedName, bool) {
5156
//TODO implement me
5257
panic("implement me")

pkg/syncer/cnsoperator/controller/cnsregistervolume/cnsregistervolume_controller_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,11 @@ func (m *mockVolumeManager) SyncVolume(ctx context.Context,
223223

224224
type mockCOCommon struct{}
225225

226+
func (m *mockCOCommon) GetSnapshotsForPVC(ctx context.Context, pvcName, namespace string) []string {
227+
//TODO implement me
228+
panic("implement me")
229+
}
230+
226231
func (m *mockCOCommon) GetPVCNamespacedNameByUID(uid string) (types.NamespacedName, bool) {
227232
//TODO implement me
228233
panic("implement me")

0 commit comments

Comments
 (0)