Skip to content

Commit ddbe3bb

Browse files
committed
feat: support per-PVC adoption annotation at volume creation time
Add support for the `nasty-csi.io/adoptable: "true"` PVC annotation to mark individual volumes for adoption at creation time, without requiring the StorageClass-wide `markAdoptable` parameter. The controller now initializes a k8s client and looks up the PVC during CreateVolume to check for the annotation. This gives users selective adoption — mark only important stateful volumes (databases, etc.) without bulk-marking everything via the StorageClass. Usage: apiVersion: v1 kind: PersistentVolumeClaim metadata: name: my-database annotations: nasty-csi.io/adoptable: "true" spec: storageClassName: nasty-nfs ... RBAC: no changes needed — the Helm chart already grants PVC get/list.
1 parent 30698e5 commit ddbe3bb

5 files changed

Lines changed: 55 additions & 0 deletions

File tree

pkg/driver/controller.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ import (
1313
nastyapi "github.com/nasty-project/nasty-go"
1414
"google.golang.org/grpc/codes"
1515
"google.golang.org/grpc/status"
16+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
17+
"k8s.io/client-go/kubernetes"
18+
"k8s.io/client-go/rest"
1619
"k8s.io/klog/v2"
1720
)
1821

@@ -174,6 +177,7 @@ type ControllerService struct {
174177
csi.UnimplementedControllerServer
175178
apiClient nastyapi.ClientInterface
176179
nodeRegistry *NodeRegistry
180+
kubeClient kubernetes.Interface
177181
// publishedVolumes tracks volumes published to nodes with their readonly state.
178182
// Key format: "volumeID:nodeID", value: readonly state.
179183
// Used to detect incompatible re-publish attempts per CSI spec.
@@ -184,14 +188,45 @@ type ControllerService struct {
184188

185189
// NewControllerService creates a new controller service.
186190
func NewControllerService(apiClient nastyapi.ClientInterface, nodeRegistry *NodeRegistry, clusterID string) *ControllerService {
191+
var kubeClient kubernetes.Interface
192+
if config, err := rest.InClusterConfig(); err == nil {
193+
if cs, err := kubernetes.NewForConfig(config); err == nil {
194+
kubeClient = cs
195+
} else {
196+
klog.Warningf("Failed to create k8s client: %v", err)
197+
}
198+
}
187199
return &ControllerService{
188200
apiClient: apiClient,
189201
nodeRegistry: nodeRegistry,
202+
kubeClient: kubeClient,
190203
clusterID: clusterID,
191204
publishedVolumes: make(map[string]bool),
192205
}
193206
}
194207

208+
// AnnotationAdoptable is the PVC annotation that marks a volume for adoption at creation time.
209+
const AnnotationAdoptable = "nasty-csi.io/adoptable"
210+
211+
// pvcHasAdoptableAnnotation checks if the PVC that triggered this CreateVolume
212+
// has the nasty-csi.io/adoptable annotation set to "true".
213+
func (s *ControllerService) pvcHasAdoptableAnnotation(ctx context.Context, params map[string]string) bool {
214+
if s.kubeClient == nil {
215+
return false
216+
}
217+
pvcName := params["csi.storage.k8s.io/pvc/name"]
218+
pvcNamespace := params["csi.storage.k8s.io/pvc/namespace"]
219+
if pvcName == "" || pvcNamespace == "" {
220+
return false
221+
}
222+
pvc, err := s.kubeClient.CoreV1().PersistentVolumeClaims(pvcNamespace).Get(ctx, pvcName, metav1.GetOptions{})
223+
if err != nil {
224+
klog.V(4).Infof("Failed to read PVC %s/%s for adoption annotation: %v", pvcNamespace, pvcName, err)
225+
return false
226+
}
227+
return pvc.Annotations[AnnotationAdoptable] == VolumeContextValueTrue
228+
}
229+
195230
// isDatasetPathVolumeID returns true if the volume ID is a full dataset path (new format).
196231
// New-format IDs contain "/" (e.g., "filesystem/parent/pvc-xxx"), while legacy IDs are plain names ("pvc-xxx").
197232
func isDatasetPathVolumeID(volumeID string) bool {

pkg/driver/controller_iscsi.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,11 @@ func (s *ControllerService) createISCSIVolume(ctx context.Context, req *csi.Crea
164164
return nil, err
165165
}
166166

167+
// Per-PVC adoption annotation overrides StorageClass default
168+
if !params.markAdoptable && s.pvcHasAdoptableAnnotation(ctx, req.GetParameters()) {
169+
params.markAdoptable = true
170+
}
171+
167172
klog.V(4).Infof("Creating iSCSI volume: %s with size: %d bytes", params.volumeName, params.requestedCapacity)
168173

169174
// Check if subvolume already exists (idempotency)

pkg/driver/controller_nfs.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,11 @@ func (s *ControllerService) createNFSVolume(ctx context.Context, req *csi.Create
331331
return nil, err
332332
}
333333

334+
// Per-PVC adoption annotation overrides StorageClass default
335+
if !params.markAdoptable && s.pvcHasAdoptableAnnotation(ctx, req.GetParameters()) {
336+
params.markAdoptable = true
337+
}
338+
334339
klog.V(4).Infof("Creating subvolume: %s/%s with capacity: %d bytes", params.filesystem, params.subvolumeName, params.requestedCapacity)
335340

336341
// Check if subvolume already exists (idempotency)

pkg/driver/controller_nvmeof.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,11 @@ func (s *ControllerService) createNVMeOFVolume(ctx context.Context, req *csi.Cre
189189
return nil, err
190190
}
191191

192+
// Per-PVC adoption annotation overrides StorageClass default
193+
if !params.markAdoptable && s.pvcHasAdoptableAnnotation(ctx, req.GetParameters()) {
194+
params.markAdoptable = true
195+
}
196+
192197
klog.V(4).Infof("Creating NVMe-oF volume: %s with size: %d bytes, NQN: %s",
193198
params.volumeName, params.requestedCapacity, params.subsystemNQN)
194199

pkg/driver/controller_smb.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,11 @@ func (s *ControllerService) createSMBVolume(ctx context.Context, req *csi.Create
214214
return nil, err
215215
}
216216

217+
// Per-PVC adoption annotation overrides StorageClass default
218+
if !params.markAdoptable && s.pvcHasAdoptableAnnotation(ctx, req.GetParameters()) {
219+
params.markAdoptable = true
220+
}
221+
217222
klog.V(4).Infof("Creating subvolume: %s/%s with capacity: %d bytes", params.filesystem, params.subvolumeName, params.requestedCapacity)
218223

219224
// Check if subvolume already exists (idempotency)

0 commit comments

Comments
 (0)