From 1fa59fa40122c6e7c2416cef31a72e37f9ee75b3 Mon Sep 17 00:00:00 2001 From: Harvey Lowndes Date: Tue, 12 Jun 2018 13:43:38 +0100 Subject: [PATCH] Storage type used to dispatch custom logic --- pkg/provisioner/block/block.go | 49 ++++++++++++++++++++++++----- pkg/provisioner/block/block_test.go | 23 ++++++++++++-- pkg/provisioner/core/provisioner.go | 30 ++++++++++++++---- 3 files changed, 85 insertions(+), 17 deletions(-) diff --git a/pkg/provisioner/block/block.go b/pkg/provisioner/block/block.go index 4a8f1998e..01a895e57 100644 --- a/pkg/provisioner/block/block.go +++ b/pkg/provisioner/block/block.go @@ -41,7 +41,10 @@ const ( ociVolumeID = "ociVolumeID" ociVolumeBackupID = "volume.beta.kubernetes.io/oci-volume-source" volumePrefixEnvVarName = "OCI_VOLUME_NAME_PREFIX" - fsType = "fsType" +) + +var ( + validFsTypes = [2]string{"ext3", "ext4"} ) // blockProvisioner is the internal provisioner for OCI block volumes @@ -68,12 +71,33 @@ func mapVolumeIDToName(volumeID string) string { return strings.Split(volumeID, ".")[4] } -func resolveFSType(options controller.VolumeOptions) string { - fs := "ext4" // default to ext4 - if fsType, ok := options.Parameters[fsType]; ok { +func resolveStorageType(options controller.VolumeOptions) string { + t := "blockStorage" + if sType, ok := options.Parameters["type"]; ok { + t = sType + } + return t +} + +func resolveFSType(options controller.VolumeOptions) (string, error) { + fs := "ext4" + if fsType, ok := options.Parameters["fsType"]; ok { fs = fsType } - return fs + err := validateFSType(fs) + if err != nil { + return "", err + } + return fs, nil +} + +func validateFSType(fsType string) error { + for _, f := range validFsTypes { + if f == fsType { + return nil + } + } + return fmt.Errorf("invalid fsType value '%s'", fsType) } func roundUpSize(volumeSizeBytes int64, allocationUnitBytes int64) int64 { @@ -132,7 +156,7 @@ func (block *blockProvisioner) Provision(options controller.VolumeOptions, ad *i return nil, err } - filesystemType := resolveFSType(options) + storageType := resolveStorageType(options) region, ok := os.LookupEnv("OCI_SHORT_REGION") if !ok { @@ -162,13 +186,22 @@ func (block *blockProvisioner) Provision(options controller.VolumeOptions, ad *i }, PersistentVolumeSource: v1.PersistentVolumeSource{ FlexVolume: &v1.FlexVolumeSource{ - Driver: plugin.OCIProvisionerName, - FSType: filesystemType, + Driver: plugin.OCIProvisionerName, + Options: map[string]string{"type": storageType}, }, }, }, } + // FsType only concerns blockStorage volumes + if pv.Spec.PersistentVolumeSource.FlexVolume.Options["type"] == "blockStorage" { + filesystemType, err := resolveFSType(options) + if err != nil { + return nil, err + } + pv.Spec.PersistentVolumeSource.FlexVolume.FSType = filesystemType + } + return pv, nil } diff --git a/pkg/provisioner/block/block_test.go b/pkg/provisioner/block/block_test.go index 84172f196..81fde436c 100644 --- a/pkg/provisioner/block/block_test.go +++ b/pkg/provisioner/block/block_test.go @@ -37,10 +37,25 @@ var ( defaultAD = identity.AvailabilityDomain{Name: common.String("PHX-AD-1"), CompartmentId: common.String("ocid1.compartment.oc1")} ) +func TestValidateFsType(t *testing.T) { + err := validateFSType("ext3") + if err != nil { + t.Fatalf("Unexpected validation error for fsType: '%s'", "ext3") + } + err = validateFSType("ext4") + if err != nil { + t.Fatalf("Unexpected validation error for fsType: '%s'", "ext4") + } + err = validateFSType("abc3") + if err == nil { + t.Fatalf("Unexpected validation pass for fsType: '%s'", "abc3") + } +} + func TestResolveFSTypeWhenNotConfigured(t *testing.T) { options := controller.VolumeOptions{Parameters: make(map[string]string)} // test default fsType of 'ext4' is always returned. - fst := resolveFSType(options) + fst, _ := resolveFSType(options) if fst != "ext4" { t.Fatalf("Unexpected filesystem type: '%s'.", fst) } @@ -48,8 +63,10 @@ func TestResolveFSTypeWhenNotConfigured(t *testing.T) { func TestResolveFSTypeWhenConfigured(t *testing.T) { // test default fsType of 'ext3' is always returned when configured. - options := controller.VolumeOptions{Parameters: map[string]string{fsType: "ext3"}} - fst := resolveFSType(options) + parameters := make(map[string]string) + parameters["fsType"] = "ext3" + options := controller.VolumeOptions{Parameters: parameters} + fst, _ := resolveFSType(options) if fst != "ext3" { t.Fatalf("Unexpected filesystem type: '%s'.", fst) } diff --git a/pkg/provisioner/core/provisioner.go b/pkg/provisioner/core/provisioner.go index 21e1fad17..8604ae805 100644 --- a/pkg/provisioner/core/provisioner.go +++ b/pkg/provisioner/core/provisioner.go @@ -87,8 +87,7 @@ func NewOCIProvisioner(kubeClient kubernetes.Interface, nodeInformer informersv1 nodeLister: nodeInformer.Lister(), nodeListerSynced: nodeInformer.Informer().HasSynced, storageClassProvisioners: map[string]plugin.ProvisionerPlugin{ - "oci": blockProvisioner, - "oci-ext3": blockProvisioner, + "blockStorage": blockProvisioner, }, } } @@ -109,6 +108,18 @@ func mapAvailabilityDomainToFailureDomain(AD string) string { return parts[len(parts)-1] } +func resolveStorageType(options controller.VolumeOptions) string { + return getStorageTypeWithDefault(options.Parameters["type"]) +} + +func getStorageTypeWithDefault(sType string) string { + t := "blockStorage" + if sType != "" { + t = sType + } + return t +} + // Provision creates a storage asset and returns a PV object representing it. func (p *OCIProvisioner) Provision(options controller.VolumeOptions) (*v1.PersistentVolume, error) { availabilityDomainName, availabilityDomain, err := p.chooseAvailabilityDomain(options.PVC) @@ -116,9 +127,10 @@ func (p *OCIProvisioner) Provision(options controller.VolumeOptions) (*v1.Persis return nil, err } - provisioner, ok := p.storageClassProvisioners[*options.PVC.Spec.StorageClassName] + storageType := resolveStorageType(options) + provisioner, ok := p.storageClassProvisioners[storageType] if !ok { - return nil, fmt.Errorf("Storage class '%s' not supported", *options.PVC.Spec.StorageClassName) + return nil, fmt.Errorf("Storage type '%s' not supported", storageType) } persistentVolume, err := provisioner.Provision(options, availabilityDomain) @@ -142,9 +154,15 @@ func (p *OCIProvisioner) Delete(volume *v1.PersistentVolume) error { return &controller.IgnoredError{Reason: "identity annotation on PV does not match ours"} } - provisioner, ok := p.storageClassProvisioners[volume.Spec.StorageClassName] + storageClass, err := p.kubeClient.Storage().StorageClasses().Get(volume.Spec.StorageClassName, metav1.GetOptions{}) + if err != nil { + return fmt.Errorf("Could not find storage class with the associated name '%s'", volume.Spec.StorageClassName) + } + + storageType := getStorageTypeWithDefault(storageClass.Parameters["type"]) + provisioner, ok := p.storageClassProvisioners[storageType] if !ok { - return fmt.Errorf("Storage class '%s' not supported", volume.Spec.StorageClassName) + return fmt.Errorf("Could not find a provisioner for storageType '%s'", storageType) } return provisioner.Delete(volume)