Pass snapshot metadata to CSI driver

This commit is contained in:
Chris Henzie
2020-09-11 15:28:45 -07:00
parent fff475cd5f
commit f705b23bbd
8 changed files with 59 additions and 24 deletions

View File

@@ -62,6 +62,7 @@ var (
showVersion = flag.Bool("version", false, "Show version.") showVersion = flag.Bool("version", false, "Show version.")
threads = flag.Int("worker-threads", 10, "Number of worker threads.") threads = flag.Int("worker-threads", 10, "Number of worker threads.")
csiTimeout = flag.Duration("timeout", defaultCSITimeout, "The timeout for any RPCs to the CSI driver. Default is 1 minute.") csiTimeout = flag.Duration("timeout", defaultCSITimeout, "The timeout for any RPCs to the CSI driver. Default is 1 minute.")
extraCreateMetadata = flag.Bool("extra-create-metadata", false, "If set, add snapshot metadata to plugin snapshot requests as parameters.")
leaderElection = flag.Bool("leader-election", false, "Enables leader election.") leaderElection = flag.Bool("leader-election", false, "Enables leader election.")
leaderElectionNamespace = flag.String("leader-election-namespace", "", "The namespace where the leader election resource exists. Defaults to the pod namespace if not set.") leaderElectionNamespace = flag.String("leader-election-namespace", "", "The namespace where the leader election resource exists. Defaults to the pod namespace if not set.")
@@ -173,6 +174,7 @@ func main() {
*resyncPeriod, *resyncPeriod,
*snapshotNamePrefix, *snapshotNamePrefix,
*snapshotNameUUIDLength, *snapshotNameUUIDLength,
*extraCreateMetadata,
) )
run := func(context.Context) { run := func(context.Context) {

View File

@@ -41,6 +41,11 @@ func TestSyncContent(t *testing.T) {
snapshotName: "snapshot-snapuid1-1", snapshotName: "snapshot-snapuid1-1",
driverName: mockDriverName, driverName: mockDriverName,
snapshotId: "snapuid1-1", snapshotId: "snapuid1-1",
parameters: map[string]string{
utils.PrefixedVolumeSnapshotNameKey: "snap1-1",
utils.PrefixedVolumeSnapshotNamespaceKey: "default",
utils.PrefixedVolumeSnapshotContentNameKey: "content1-1",
},
creationTime: timeNow, creationTime: timeNow,
readyToUse: true, readyToUse: true,
}, },
@@ -63,6 +68,11 @@ func TestSyncContent(t *testing.T) {
snapshotName: "snapshot-snapuid1-2", snapshotName: "snapshot-snapuid1-2",
driverName: mockDriverName, driverName: mockDriverName,
snapshotId: "snapuid1-2", snapshotId: "snapuid1-2",
parameters: map[string]string{
utils.PrefixedVolumeSnapshotNameKey: "snap1-2",
utils.PrefixedVolumeSnapshotNamespaceKey: "default",
utils.PrefixedVolumeSnapshotContentNameKey: "content1-2",
},
creationTime: timeNow, creationTime: timeNow,
readyToUse: true, readyToUse: true,
size: defaultSize, size: defaultSize,
@@ -114,7 +124,13 @@ func TestSyncContent(t *testing.T) {
{ {
volumeHandle: "volume-handle-1-4", volumeHandle: "volume-handle-1-4",
snapshotName: "snapshot-snapuid1-4", snapshotName: "snapshot-snapuid1-4",
parameters: class5Parameters, parameters: map[string]string{
utils.AnnDeletionSecretRefName: "secret",
utils.AnnDeletionSecretRefNamespace: "default",
utils.PrefixedVolumeSnapshotNameKey: "snap1-4",
utils.PrefixedVolumeSnapshotNamespaceKey: "default",
utils.PrefixedVolumeSnapshotContentNameKey: "content1-4",
},
secrets: map[string]string{ secrets: map[string]string{
"foo": "bar", "foo": "bar",
}, },

View File

@@ -24,7 +24,6 @@ import (
crdv1 "github.com/kubernetes-csi/external-snapshotter/client/v3/apis/volumesnapshot/v1beta1" crdv1 "github.com/kubernetes-csi/external-snapshotter/client/v3/apis/volumesnapshot/v1beta1"
"github.com/kubernetes-csi/external-snapshotter/v3/pkg/snapshotter" "github.com/kubernetes-csi/external-snapshotter/v3/pkg/snapshotter"
"github.com/kubernetes-csi/external-snapshotter/v3/pkg/utils"
) )
// Handler is responsible for handling VolumeSnapshot events from informer. // Handler is responsible for handling VolumeSnapshot events from informer.
@@ -74,11 +73,7 @@ func (handler *csiHandler) CreateSnapshot(content *crdv1.VolumeSnapshotContent,
if err != nil { if err != nil {
return "", "", time.Time{}, 0, false, err return "", "", time.Time{}, 0, false, err
} }
newParameters, err := utils.RemovePrefixedParameters(parameters) return handler.snapshotter.CreateSnapshot(ctx, snapshotName, *content.Spec.Source.VolumeHandle, parameters, snapshotterCredentials)
if err != nil {
return "", "", time.Time{}, 0, false, fmt.Errorf("failed to remove CSI Parameters of prefixed keys: %v", err)
}
return handler.snapshotter.CreateSnapshot(ctx, snapshotName, *content.Spec.Source.VolumeHandle, newParameters, snapshotterCredentials)
} }
func (handler *csiHandler) DeleteSnapshot(content *crdv1.VolumeSnapshotContent, snapshotterCredentials map[string]string) error { func (handler *csiHandler) DeleteSnapshot(content *crdv1.VolumeSnapshotContent, snapshotterCredentials map[string]string) error {

View File

@@ -521,6 +521,7 @@ func newTestController(kubeClient kubernetes.Interface, clientset clientset.Inte
60*time.Second, 60*time.Second,
"snapshot", "snapshot",
-1, -1,
true,
) )
ctrl.eventRecorder = record.NewFakeRecorder(1000) ctrl.eventRecorder = record.NewFakeRecorder(1000)

View File

@@ -284,7 +284,17 @@ func (ctrl *csiSnapshotSideCarController) createSnapshotWrapper(content *crdv1.V
return nil, fmt.Errorf("failed to add VolumeSnapshotBeingCreated annotation on the content %s: %q", content.Name, err) return nil, fmt.Errorf("failed to add VolumeSnapshotBeingCreated annotation on the content %s: %q", content.Name, err)
} }
driverName, snapshotID, creationTime, size, readyToUse, err := ctrl.handler.CreateSnapshot(content, class.Parameters, snapshotterCredentials) parameters, err := utils.RemovePrefixedParameters(class.Parameters)
if err != nil {
return nil, fmt.Errorf("failed to remove CSI Parameters of prefixed keys: %v", err)
}
if ctrl.extraCreateMetadata {
parameters[utils.PrefixedVolumeSnapshotNameKey] = content.Spec.VolumeSnapshotRef.Name
parameters[utils.PrefixedVolumeSnapshotNamespaceKey] = content.Spec.VolumeSnapshotRef.Namespace
parameters[utils.PrefixedVolumeSnapshotContentNameKey] = content.Name
}
driverName, snapshotID, creationTime, size, readyToUse, err := ctrl.handler.CreateSnapshot(content, parameters, snapshotterCredentials)
if err != nil { if err != nil {
// NOTE(xyang): handle create timeout // NOTE(xyang): handle create timeout
// If it is a final error, remove annotation to indicate // If it is a final error, remove annotation to indicate

View File

@@ -45,6 +45,7 @@ type csiSnapshotSideCarController struct {
driverName string driverName string
eventRecorder record.EventRecorder eventRecorder record.EventRecorder
contentQueue workqueue.RateLimitingInterface contentQueue workqueue.RateLimitingInterface
extraCreateMetadata bool
contentLister storagelisters.VolumeSnapshotContentLister contentLister storagelisters.VolumeSnapshotContentLister
contentListerSynced cache.InformerSynced contentListerSynced cache.InformerSynced
@@ -70,6 +71,7 @@ func NewCSISnapshotSideCarController(
resyncPeriod time.Duration, resyncPeriod time.Duration,
snapshotNamePrefix string, snapshotNamePrefix string,
snapshotNameUUIDLength int, snapshotNameUUIDLength int,
extraCreateMetadata bool,
) *csiSnapshotSideCarController { ) *csiSnapshotSideCarController {
broadcaster := record.NewBroadcaster() broadcaster := record.NewBroadcaster()
broadcaster.StartLogging(klog.Infof) broadcaster.StartLogging(klog.Infof)
@@ -86,6 +88,7 @@ func NewCSISnapshotSideCarController(
resyncPeriod: resyncPeriod, resyncPeriod: resyncPeriod,
contentStore: cache.NewStore(cache.DeletionHandlingMetaNamespaceKeyFunc), contentStore: cache.NewStore(cache.DeletionHandlingMetaNamespaceKeyFunc),
contentQueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "csi-snapshotter-content"), contentQueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "csi-snapshotter-content"),
extraCreateMetadata: extraCreateMetadata,
} }
volumeSnapshotContentInformer.Informer().AddEventHandlerWithResyncPeriod( volumeSnapshotContentInformer.Informer().AddEventHandlerWithResyncPeriod(

View File

@@ -49,7 +49,9 @@ const (
// CSI Parameters prefixed with csiParameterPrefix are not passed through // CSI Parameters prefixed with csiParameterPrefix are not passed through
// to the driver on CreateSnapshotRequest calls. Instead they are intended // to the driver on CreateSnapshotRequest calls. Instead they are intended
// to be used by the CSI external-snapshotter and maybe used to populate // to be used by the CSI external-snapshotter and maybe used to populate
// fields in subsequent CSI calls or Kubernetes API objects. // fields in subsequent CSI calls or Kubernetes API objects. An exception
// exists for the volume snapshot and volume snapshot content keys, which are
// passed as parameters on CreateSnapshotRequest calls.
csiParameterPrefix = "csi.storage.k8s.io/" csiParameterPrefix = "csi.storage.k8s.io/"
PrefixedSnapshotterSecretNameKey = csiParameterPrefix + "snapshotter-secret-name" // Prefixed name key for DeleteSnapshot secret PrefixedSnapshotterSecretNameKey = csiParameterPrefix + "snapshotter-secret-name" // Prefixed name key for DeleteSnapshot secret
@@ -58,6 +60,10 @@ const (
PrefixedSnapshotterListSecretNameKey = csiParameterPrefix + "snapshotter-list-secret-name" // Prefixed name key for ListSnapshots secret PrefixedSnapshotterListSecretNameKey = csiParameterPrefix + "snapshotter-list-secret-name" // Prefixed name key for ListSnapshots secret
PrefixedSnapshotterListSecretNamespaceKey = csiParameterPrefix + "snapshotter-list-secret-namespace" // Prefixed namespace key for ListSnapshots secret PrefixedSnapshotterListSecretNamespaceKey = csiParameterPrefix + "snapshotter-list-secret-namespace" // Prefixed namespace key for ListSnapshots secret
PrefixedVolumeSnapshotNameKey = csiParameterPrefix + "volumesnapshot/name" // Prefixed VolumeSnapshot name key
PrefixedVolumeSnapshotNamespaceKey = csiParameterPrefix + "volumesnapshot/namespace" // Prefixed VolumeSnapshot namespace key
PrefixedVolumeSnapshotContentNameKey = csiParameterPrefix + "volumesnapshotcontent/name" // Prefixed VolumeSnapshotContent name key
// Name of finalizer on VolumeSnapshotContents that are bound by VolumeSnapshots // Name of finalizer on VolumeSnapshotContents that are bound by VolumeSnapshots
VolumeSnapshotContentFinalizer = "snapshot.storage.kubernetes.io/volumesnapshotcontent-bound-protection" VolumeSnapshotContentFinalizer = "snapshot.storage.kubernetes.io/volumesnapshotcontent-bound-protection"
// Name of finalizer on VolumeSnapshot that is being used as a source to create a PVC // Name of finalizer on VolumeSnapshot that is being used as a source to create a PVC

View File

@@ -171,6 +171,8 @@ func TestRemovePrefixedCSIParams(t *testing.T) {
params: map[string]string{ params: map[string]string{
PrefixedSnapshotterSecretNameKey: "csiBar", PrefixedSnapshotterSecretNameKey: "csiBar",
PrefixedSnapshotterSecretNamespaceKey: "csiBar", PrefixedSnapshotterSecretNamespaceKey: "csiBar",
PrefixedSnapshotterListSecretNameKey: "csiBar",
PrefixedSnapshotterListSecretNamespaceKey: "csiBar",
}, },
expectedParams: map[string]string{}, expectedParams: map[string]string{},
}, },