diff --git a/examples/persistent-volume-provisioning/README.md b/examples/persistent-volume-provisioning/README.md index 07de703c503..f31e63ad7e1 100644 --- a/examples/persistent-volume-provisioning/README.md +++ b/examples/persistent-volume-provisioning/README.md @@ -61,9 +61,11 @@ metadata: provisioner: kubernetes.io/vsphere-volume parameters: diskformat: eagerzeroedthick + fstype: ext3 ``` * `diskformat`: `thin`, `zeroedthick` and `eagerzeroedthick`. See vSphere docs for details. Default: `"thin"`. +* `fstype`: fstype that are supported by kubernetes. Default: `"ext4"`. #### Portworx Volume diff --git a/examples/volumes/vsphere/README.md b/examples/volumes/vsphere/README.md index aacb37ff661..d50fbbe37db 100644 --- a/examples/volumes/vsphere/README.md +++ b/examples/volumes/vsphere/README.md @@ -214,6 +214,7 @@ provisioner: kubernetes.io/vsphere-volume parameters: diskformat: zeroedthick + fstype: ext3 ``` [Download example](vsphere-volume-sc-fast.yaml?raw=true) @@ -244,11 +245,12 @@ Verifying storage class is created: ``` bash - $ kubectl describe storageclass fast - Name: fast - Annotations: - Provisioner: kubernetes.io/vsphere-volume - Parameters: diskformat=zeroedthick + $ kubectl describe storageclass fast + Name: fast + IsDefaultClass: No + Annotations: + Provisioner: kubernetes.io/vsphere-volume + Parameters: diskformat=zeroedthick,fstype=ext3 No events. ``` @@ -283,14 +285,19 @@ ``` bash $ kubectl describe pvc pvcsc001 - Name: pvcsc001 - Namespace: default - Status: Bound - Volume: pvc-80f7b5c1-94b6-11e6-a24f-005056a79d2d - Labels: - Capacity: 2Gi - Access Modes: RWO - No events. + Name: pvcsc001 + Namespace: default + StorageClass: fast + Status: Bound + Volume: pvc-83295256-f8e0-11e6-8263-005056b2349c + Labels: + Capacity: 2Gi + Access Modes: RWO + Events: + FirstSeen LastSeen Count From SubObjectPath Type Reason Message + --------- -------- ----- ---- ------------- -------- ------ ------- + 1m 1m 1 persistentvolume-controller Normal ProvisioningSucceeded Successfully provisioned volume pvc-83295256-f8e0-11e6-8263-005056b2349c using kubernetes.io/vsphere-volume + ``` Persistent Volume is automatically created and is bounded to this pvc. @@ -298,19 +305,20 @@ Verifying persistent volume claim is created: ``` bash - $ kubectl describe pv pvc-80f7b5c1-94b6-11e6-a24f-005056a79d2d - Name: pvc-80f7b5c1-94b6-11e6-a24f-005056a79d2d - Labels: - Status: Bound - Claim: default/pvcsc001 - Reclaim Policy: Delete - Access Modes: RWO - Capacity: 2Gi + $ kubectl describe pv pvc-83295256-f8e0-11e6-8263-005056b2349c + Name: pvc-83295256-f8e0-11e6-8263-005056b2349c + Labels: + StorageClass: fast + Status: Bound + Claim: default/pvcsc001 + Reclaim Policy: Delete + Access Modes: RWO + Capacity: 2Gi Message: Source: - Type: vSphereVolume (a Persistent Disk resource in vSphere) - VolumePath: [datastore1] kubevols/kubernetes-dynamic-pvc-80f7b5c1-94b6-11e6-a24f-005056a79d2d.vmdk - FSType: ext4 + Type: vSphereVolume (a Persistent Disk resource in vSphere) + VolumePath: [datastore1] kubevols/kubernetes-dynamic-pvc-83295256-f8e0-11e6-8263-005056b2349c.vmdk + FSType: ext3 No events. ``` diff --git a/examples/volumes/vsphere/vsphere-volume-sc-fast.yaml b/examples/volumes/vsphere/vsphere-volume-sc-fast.yaml index eac5049df04..b2b436f8e0d 100644 --- a/examples/volumes/vsphere/vsphere-volume-sc-fast.yaml +++ b/examples/volumes/vsphere/vsphere-volume-sc-fast.yaml @@ -4,4 +4,5 @@ metadata: name: fast provisioner: kubernetes.io/vsphere-volume parameters: - diskformat: zeroedthick \ No newline at end of file + diskformat: zeroedthick + fstype: ext3 \ No newline at end of file diff --git a/pkg/volume/photon_pd/photon_pd.go b/pkg/volume/photon_pd/photon_pd.go index 606c57b1a93..c3d1d0287fb 100644 --- a/pkg/volume/photon_pd/photon_pd.go +++ b/pkg/volume/photon_pd/photon_pd.go @@ -151,7 +151,7 @@ func (plugin *photonPersistentDiskPlugin) ConstructVolumeSpec(volumeSpecName, mo // Abstract interface to disk operations. type pdManager interface { // Creates a volume - CreateVolume(provisioner *photonPersistentDiskProvisioner) (pdID string, volumeSizeGB int, err error) + CreateVolume(provisioner *photonPersistentDiskProvisioner) (pdID string, volumeSizeGB int, fstype string, err error) // Deletes a volume DeleteVolume(deleter *photonPersistentDiskDeleter) error } @@ -342,11 +342,15 @@ func (plugin *photonPersistentDiskPlugin) newProvisionerInternal(options volume. } func (p *photonPersistentDiskProvisioner) Provision() (*v1.PersistentVolume, error) { - pdID, sizeGB, err := p.manager.CreateVolume(p) + pdID, sizeGB, fstype, err := p.manager.CreateVolume(p) if err != nil { return nil, err } + if fstype == "" { + fstype = "ext4" + } + pv := &v1.PersistentVolume{ ObjectMeta: metav1.ObjectMeta{ Name: p.options.PVName, @@ -364,7 +368,7 @@ func (p *photonPersistentDiskProvisioner) Provision() (*v1.PersistentVolume, err PersistentVolumeSource: v1.PersistentVolumeSource{ PhotonPersistentDisk: &v1.PhotonPersistentDiskVolumeSource{ PdID: pdID, - FSType: "ext4", + FSType: fstype, }, }, }, diff --git a/pkg/volume/photon_pd/photon_pd_test.go b/pkg/volume/photon_pd/photon_pd_test.go index 2d843542b7e..3484aa3f5b3 100644 --- a/pkg/volume/photon_pd/photon_pd_test.go +++ b/pkg/volume/photon_pd/photon_pd_test.go @@ -88,8 +88,8 @@ func contains(modes []v1.PersistentVolumeAccessMode, mode v1.PersistentVolumeAcc type fakePDManager struct { } -func (fake *fakePDManager) CreateVolume(c *photonPersistentDiskProvisioner) (pdID string, volumeSizeGB int, err error) { - return "test-photon-pd-id", 10, nil +func (fake *fakePDManager) CreateVolume(c *photonPersistentDiskProvisioner) (pdID string, volumeSizeGB int, fstype string, err error) { + return "test-photon-pd-id", 10, "ext4", nil } func (fake *fakePDManager) DeleteVolume(cd *photonPersistentDiskDeleter) error { diff --git a/pkg/volume/photon_pd/photon_util.go b/pkg/volume/photon_pd/photon_util.go index f3c1936645d..1963f37b52f 100644 --- a/pkg/volume/photon_pd/photon_util.go +++ b/pkg/volume/photon_pd/photon_util.go @@ -80,11 +80,11 @@ func verifyDevicePath(path string) (string, error) { } // CreateVolume creates a PhotonController persistent disk. -func (util *PhotonDiskUtil) CreateVolume(p *photonPersistentDiskProvisioner) (pdID string, capacityGB int, err error) { +func (util *PhotonDiskUtil) CreateVolume(p *photonPersistentDiskProvisioner) (pdID string, capacityGB int, fstype string, err error) { cloud, err := getCloudProvider(p.plugin.host.GetCloudProvider()) if err != nil { glog.Errorf("Photon Controller Util: CreateVolume failed to get cloud provider. Error [%v]", err) - return "", 0, err + return "", 0, "", err } capacity := p.options.PVC.Spec.Resources.Requests[v1.ResourceName(v1.ResourceStorage)] @@ -102,20 +102,23 @@ func (util *PhotonDiskUtil) CreateVolume(p *photonPersistentDiskProvisioner) (pd switch strings.ToLower(parameter) { case "flavor": volumeOptions.Flavor = value + case "fstype": + fstype = value + glog.V(4).Infof("Photon Controller Util: Setting fstype to %s", fstype) default: glog.Errorf("Photon Controller Util: invalid option %s for volume plugin %s.", parameter, p.plugin.GetPluginName()) - return "", 0, fmt.Errorf("Photon Controller Util: invalid option %s for volume plugin %s.", parameter, p.plugin.GetPluginName()) + return "", 0, "", fmt.Errorf("Photon Controller Util: invalid option %s for volume plugin %s.", parameter, p.plugin.GetPluginName()) } } pdID, err = cloud.CreateDisk(volumeOptions) if err != nil { glog.Errorf("Photon Controller Util: failed to CreateDisk. Error [%v]", err) - return "", 0, err + return "", 0, "", err } glog.V(4).Infof("Successfully created Photon Controller persistent disk %s", name) - return pdID, volSizeGB, nil + return pdID, volSizeGB, "", nil } // DeleteVolume deletes a vSphere volume. diff --git a/pkg/volume/vsphere_volume/vsphere_volume.go b/pkg/volume/vsphere_volume/vsphere_volume.go index 64b1946d35f..4f8df5b240c 100644 --- a/pkg/volume/vsphere_volume/vsphere_volume.go +++ b/pkg/volume/vsphere_volume/vsphere_volume.go @@ -152,7 +152,7 @@ func (plugin *vsphereVolumePlugin) ConstructVolumeSpec(volumeName, mountPath str // Abstract interface to disk operations. type vdManager interface { // Creates a volume - CreateVolume(provisioner *vsphereVolumeProvisioner) (vmDiskPath string, volumeSizeGB int, err error) + CreateVolume(provisioner *vsphereVolumeProvisioner) (vmDiskPath string, volumeSizeGB int, fstype string, err error) // Deletes a volume DeleteVolume(deleter *vsphereVolumeDeleter) error } @@ -344,11 +344,15 @@ func (plugin *vsphereVolumePlugin) newProvisionerInternal(options volume.VolumeO } func (v *vsphereVolumeProvisioner) Provision() (*v1.PersistentVolume, error) { - vmDiskPath, sizeKB, err := v.manager.CreateVolume(v) + vmDiskPath, sizeKB, fstype, err := v.manager.CreateVolume(v) if err != nil { return nil, err } + if fstype == "" { + fstype = "ext4" + } + pv := &v1.PersistentVolume{ ObjectMeta: metav1.ObjectMeta{ Name: v.options.PVName, @@ -366,7 +370,7 @@ func (v *vsphereVolumeProvisioner) Provision() (*v1.PersistentVolume, error) { PersistentVolumeSource: v1.PersistentVolumeSource{ VsphereVolume: &v1.VsphereVirtualDiskVolumeSource{ VolumePath: vmDiskPath, - FSType: "ext4", + FSType: fstype, }, }, }, diff --git a/pkg/volume/vsphere_volume/vsphere_volume_test.go b/pkg/volume/vsphere_volume/vsphere_volume_test.go index a0b19ee2736..6608c513f64 100644 --- a/pkg/volume/vsphere_volume/vsphere_volume_test.go +++ b/pkg/volume/vsphere_volume/vsphere_volume_test.go @@ -63,8 +63,8 @@ func getFakeDeviceName(host volume.VolumeHost, volPath string) string { return path.Join(host.GetPluginDir(vsphereVolumePluginName), "device", volPath) } -func (fake *fakePDManager) CreateVolume(v *vsphereVolumeProvisioner) (vmDiskPath string, volumeSizeKB int, err error) { - return "[local] test-volume-name.vmdk", 100, nil +func (fake *fakePDManager) CreateVolume(v *vsphereVolumeProvisioner) (vmDiskPath string, volumeSizeKB int, fstype string, err error) { + return "[local] test-volume-name.vmdk", 100, "ext4", nil } func (fake *fakePDManager) DeleteVolume(vd *vsphereVolumeDeleter) error { diff --git a/pkg/volume/vsphere_volume/vsphere_volume_util.go b/pkg/volume/vsphere_volume/vsphere_volume_util.go index 117b12eda0a..7f97dda56b2 100644 --- a/pkg/volume/vsphere_volume/vsphere_volume_util.go +++ b/pkg/volume/vsphere_volume/vsphere_volume_util.go @@ -38,6 +38,7 @@ const ( diskSCSIPrefix = "wwn-0x" diskformat = "diskformat" datastore = "datastore" + Fstype = "fstype" HostFailuresToTolerateCapability = "hostfailurestotolerate" ForceProvisioningCapability = "forceprovisioning" @@ -73,10 +74,11 @@ func verifyDevicePath(path string) (string, error) { } // CreateVolume creates a vSphere volume. -func (util *VsphereDiskUtil) CreateVolume(v *vsphereVolumeProvisioner) (vmDiskPath string, volumeSizeKB int, err error) { +func (util *VsphereDiskUtil) CreateVolume(v *vsphereVolumeProvisioner) (vmDiskPath string, volumeSizeKB int, fstype string, err error) { + cloud, err := getCloudProvider(v.plugin.host.GetCloudProvider()) if err != nil { - return "", 0, err + return "", 0, "", err } capacity := v.options.PVC.Spec.Resources.Requests[v1.ResourceName(v1.ResourceStorage)] @@ -98,17 +100,21 @@ func (util *VsphereDiskUtil) CreateVolume(v *vsphereVolumeProvisioner) (vmDiskPa volumeOptions.DiskFormat = value case datastore: volumeOptions.Datastore = value + case Fstype: + fstype = value + glog.V(4).Infof("Setting fstype as %q", fstype) case HostFailuresToTolerateCapability, ForceProvisioningCapability, CacheReservationCapability, DiskStripesCapability, ObjectSpaceReservationCapability, IopsLimitCapability: capabilityData, err := validateVSANCapability(strings.ToLower(parameter), value) if err != nil { - return "", 0, err + return "", 0, "", err } else { volumeOptions.StorageProfileData += capabilityData } + default: - return "", 0, fmt.Errorf("invalid option %q for volume plugin %s", parameter, v.plugin.GetPluginName()) + return "", 0, "", fmt.Errorf("invalid option %q for volume plugin %s", parameter, v.plugin.GetPluginName()) } } @@ -118,16 +124,16 @@ func (util *VsphereDiskUtil) CreateVolume(v *vsphereVolumeProvisioner) (vmDiskPa glog.V(1).Infof("StorageProfileData in vsphere volume %q", volumeOptions.StorageProfileData) // TODO: implement PVC.Selector parsing if v.options.PVC.Spec.Selector != nil { - return "", 0, fmt.Errorf("claim.Spec.Selector is not supported for dynamic provisioning on vSphere") + return "", 0, "", fmt.Errorf("claim.Spec.Selector is not supported for dynamic provisioning on vSphere") } vmDiskPath, err = cloud.CreateVolume(volumeOptions) if err != nil { glog.V(2).Infof("Error creating vsphere volume: %v", err) - return "", 0, err + return "", 0, "", err } glog.V(2).Infof("Successfully created vsphere volume %s", name) - return vmDiskPath, volSizeKB, nil + return vmDiskPath, volSizeKB, fstype, nil } // DeleteVolume deletes a vSphere volume.