Merge pull request #41929 from abrarshivani/fstype_in_storage_class

Automatic merge from submit-queue (batch tested with PRs 44008, 41929)

vSphere Cloud Provider: Fstype in storage class

This PR does following,

1. Adds fstype support in storage class for vSphere Cloud Provider.
2. Modify examples to include fstype in storage class.
3. Adds fstype support in storage class for Photon Controller Cloud Provider (@luomiao)

Internally reviewed [here](https://github.com/vmware/kubernetes/pull/88).

cc @pdhamdhere @tusharnt @kerneltime @BaluDontu @divyenpatel @luomiao
This commit is contained in:
Kubernetes Submit Queue 2017-04-04 16:50:20 -07:00 committed by GitHub
commit 5ef8148b5e
9 changed files with 75 additions and 47 deletions

View File

@ -61,9 +61,11 @@ metadata:
provisioner: kubernetes.io/vsphere-volume provisioner: kubernetes.io/vsphere-volume
parameters: parameters:
diskformat: eagerzeroedthick diskformat: eagerzeroedthick
fstype: ext3
``` ```
* `diskformat`: `thin`, `zeroedthick` and `eagerzeroedthick`. See vSphere docs for details. Default: `"thin"`. * `diskformat`: `thin`, `zeroedthick` and `eagerzeroedthick`. See vSphere docs for details. Default: `"thin"`.
* `fstype`: fstype that are supported by kubernetes. Default: `"ext4"`.
#### Portworx Volume #### Portworx Volume

View File

@ -214,6 +214,7 @@
provisioner: kubernetes.io/vsphere-volume provisioner: kubernetes.io/vsphere-volume
parameters: parameters:
diskformat: zeroedthick diskformat: zeroedthick
fstype: ext3
``` ```
[Download example](vsphere-volume-sc-fast.yaml?raw=true) [Download example](vsphere-volume-sc-fast.yaml?raw=true)
@ -244,11 +245,12 @@
Verifying storage class is created: Verifying storage class is created:
``` bash ``` bash
$ kubectl describe storageclass fast $ kubectl describe storageclass fast
Name: fast Name: fast
Annotations: <none> IsDefaultClass: No
Provisioner: kubernetes.io/vsphere-volume Annotations: <none>
Parameters: diskformat=zeroedthick Provisioner: kubernetes.io/vsphere-volume
Parameters: diskformat=zeroedthick,fstype=ext3
No events. No events.
``` ```
@ -283,14 +285,19 @@
``` bash ``` bash
$ kubectl describe pvc pvcsc001 $ kubectl describe pvc pvcsc001
Name: pvcsc001 Name: pvcsc001
Namespace: default Namespace: default
Status: Bound StorageClass: fast
Volume: pvc-80f7b5c1-94b6-11e6-a24f-005056a79d2d Status: Bound
Labels: <none> Volume: pvc-83295256-f8e0-11e6-8263-005056b2349c
Capacity: 2Gi Labels: <none>
Access Modes: RWO Capacity: 2Gi
No events. 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. Persistent Volume is automatically created and is bounded to this pvc.
@ -298,19 +305,20 @@
Verifying persistent volume claim is created: Verifying persistent volume claim is created:
``` bash ``` bash
$ kubectl describe pv pvc-80f7b5c1-94b6-11e6-a24f-005056a79d2d $ kubectl describe pv pvc-83295256-f8e0-11e6-8263-005056b2349c
Name: pvc-80f7b5c1-94b6-11e6-a24f-005056a79d2d Name: pvc-83295256-f8e0-11e6-8263-005056b2349c
Labels: <none> Labels: <none>
Status: Bound StorageClass: fast
Claim: default/pvcsc001 Status: Bound
Reclaim Policy: Delete Claim: default/pvcsc001
Access Modes: RWO Reclaim Policy: Delete
Capacity: 2Gi Access Modes: RWO
Capacity: 2Gi
Message: Message:
Source: Source:
Type: vSphereVolume (a Persistent Disk resource in vSphere) Type: vSphereVolume (a Persistent Disk resource in vSphere)
VolumePath: [datastore1] kubevols/kubernetes-dynamic-pvc-80f7b5c1-94b6-11e6-a24f-005056a79d2d.vmdk VolumePath: [datastore1] kubevols/kubernetes-dynamic-pvc-83295256-f8e0-11e6-8263-005056b2349c.vmdk
FSType: ext4 FSType: ext3
No events. No events.
``` ```

View File

@ -4,4 +4,5 @@ metadata:
name: fast name: fast
provisioner: kubernetes.io/vsphere-volume provisioner: kubernetes.io/vsphere-volume
parameters: parameters:
diskformat: zeroedthick diskformat: zeroedthick
fstype: ext3

View File

@ -151,7 +151,7 @@ func (plugin *photonPersistentDiskPlugin) ConstructVolumeSpec(volumeSpecName, mo
// Abstract interface to disk operations. // Abstract interface to disk operations.
type pdManager interface { type pdManager interface {
// Creates a volume // 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 // Deletes a volume
DeleteVolume(deleter *photonPersistentDiskDeleter) error DeleteVolume(deleter *photonPersistentDiskDeleter) error
} }
@ -342,11 +342,15 @@ func (plugin *photonPersistentDiskPlugin) newProvisionerInternal(options volume.
} }
func (p *photonPersistentDiskProvisioner) Provision() (*v1.PersistentVolume, error) { 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 { if err != nil {
return nil, err return nil, err
} }
if fstype == "" {
fstype = "ext4"
}
pv := &v1.PersistentVolume{ pv := &v1.PersistentVolume{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: p.options.PVName, Name: p.options.PVName,
@ -364,7 +368,7 @@ func (p *photonPersistentDiskProvisioner) Provision() (*v1.PersistentVolume, err
PersistentVolumeSource: v1.PersistentVolumeSource{ PersistentVolumeSource: v1.PersistentVolumeSource{
PhotonPersistentDisk: &v1.PhotonPersistentDiskVolumeSource{ PhotonPersistentDisk: &v1.PhotonPersistentDiskVolumeSource{
PdID: pdID, PdID: pdID,
FSType: "ext4", FSType: fstype,
}, },
}, },
}, },

View File

@ -88,8 +88,8 @@ func contains(modes []v1.PersistentVolumeAccessMode, mode v1.PersistentVolumeAcc
type fakePDManager struct { type fakePDManager struct {
} }
func (fake *fakePDManager) CreateVolume(c *photonPersistentDiskProvisioner) (pdID string, volumeSizeGB int, err error) { func (fake *fakePDManager) CreateVolume(c *photonPersistentDiskProvisioner) (pdID string, volumeSizeGB int, fstype string, err error) {
return "test-photon-pd-id", 10, nil return "test-photon-pd-id", 10, "ext4", nil
} }
func (fake *fakePDManager) DeleteVolume(cd *photonPersistentDiskDeleter) error { func (fake *fakePDManager) DeleteVolume(cd *photonPersistentDiskDeleter) error {

View File

@ -80,11 +80,11 @@ func verifyDevicePath(path string) (string, error) {
} }
// CreateVolume creates a PhotonController persistent disk. // 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()) cloud, err := getCloudProvider(p.plugin.host.GetCloudProvider())
if err != nil { if err != nil {
glog.Errorf("Photon Controller Util: CreateVolume failed to get cloud provider. Error [%v]", err) 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)] 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) { switch strings.ToLower(parameter) {
case "flavor": case "flavor":
volumeOptions.Flavor = value volumeOptions.Flavor = value
case "fstype":
fstype = value
glog.V(4).Infof("Photon Controller Util: Setting fstype to %s", fstype)
default: default:
glog.Errorf("Photon Controller Util: invalid option %s for volume plugin %s.", parameter, p.plugin.GetPluginName()) 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) pdID, err = cloud.CreateDisk(volumeOptions)
if err != nil { if err != nil {
glog.Errorf("Photon Controller Util: failed to CreateDisk. Error [%v]", err) 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) 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. // DeleteVolume deletes a vSphere volume.

View File

@ -152,7 +152,7 @@ func (plugin *vsphereVolumePlugin) ConstructVolumeSpec(volumeName, mountPath str
// Abstract interface to disk operations. // Abstract interface to disk operations.
type vdManager interface { type vdManager interface {
// Creates a volume // 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 // Deletes a volume
DeleteVolume(deleter *vsphereVolumeDeleter) error DeleteVolume(deleter *vsphereVolumeDeleter) error
} }
@ -344,11 +344,15 @@ func (plugin *vsphereVolumePlugin) newProvisionerInternal(options volume.VolumeO
} }
func (v *vsphereVolumeProvisioner) Provision() (*v1.PersistentVolume, error) { 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 { if err != nil {
return nil, err return nil, err
} }
if fstype == "" {
fstype = "ext4"
}
pv := &v1.PersistentVolume{ pv := &v1.PersistentVolume{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: v.options.PVName, Name: v.options.PVName,
@ -366,7 +370,7 @@ func (v *vsphereVolumeProvisioner) Provision() (*v1.PersistentVolume, error) {
PersistentVolumeSource: v1.PersistentVolumeSource{ PersistentVolumeSource: v1.PersistentVolumeSource{
VsphereVolume: &v1.VsphereVirtualDiskVolumeSource{ VsphereVolume: &v1.VsphereVirtualDiskVolumeSource{
VolumePath: vmDiskPath, VolumePath: vmDiskPath,
FSType: "ext4", FSType: fstype,
}, },
}, },
}, },

View File

@ -63,8 +63,8 @@ func getFakeDeviceName(host volume.VolumeHost, volPath string) string {
return path.Join(host.GetPluginDir(vsphereVolumePluginName), "device", volPath) return path.Join(host.GetPluginDir(vsphereVolumePluginName), "device", volPath)
} }
func (fake *fakePDManager) CreateVolume(v *vsphereVolumeProvisioner) (vmDiskPath string, volumeSizeKB int, err error) { func (fake *fakePDManager) CreateVolume(v *vsphereVolumeProvisioner) (vmDiskPath string, volumeSizeKB int, fstype string, err error) {
return "[local] test-volume-name.vmdk", 100, nil return "[local] test-volume-name.vmdk", 100, "ext4", nil
} }
func (fake *fakePDManager) DeleteVolume(vd *vsphereVolumeDeleter) error { func (fake *fakePDManager) DeleteVolume(vd *vsphereVolumeDeleter) error {

View File

@ -38,6 +38,7 @@ const (
diskSCSIPrefix = "wwn-0x" diskSCSIPrefix = "wwn-0x"
diskformat = "diskformat" diskformat = "diskformat"
datastore = "datastore" datastore = "datastore"
Fstype = "fstype"
HostFailuresToTolerateCapability = "hostfailurestotolerate" HostFailuresToTolerateCapability = "hostfailurestotolerate"
ForceProvisioningCapability = "forceprovisioning" ForceProvisioningCapability = "forceprovisioning"
@ -73,10 +74,11 @@ func verifyDevicePath(path string) (string, error) {
} }
// CreateVolume creates a vSphere volume. // 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()) cloud, err := getCloudProvider(v.plugin.host.GetCloudProvider())
if err != nil { if err != nil {
return "", 0, err return "", 0, "", err
} }
capacity := v.options.PVC.Spec.Resources.Requests[v1.ResourceName(v1.ResourceStorage)] 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 volumeOptions.DiskFormat = value
case datastore: case datastore:
volumeOptions.Datastore = value volumeOptions.Datastore = value
case Fstype:
fstype = value
glog.V(4).Infof("Setting fstype as %q", fstype)
case HostFailuresToTolerateCapability, ForceProvisioningCapability, case HostFailuresToTolerateCapability, ForceProvisioningCapability,
CacheReservationCapability, DiskStripesCapability, CacheReservationCapability, DiskStripesCapability,
ObjectSpaceReservationCapability, IopsLimitCapability: ObjectSpaceReservationCapability, IopsLimitCapability:
capabilityData, err := validateVSANCapability(strings.ToLower(parameter), value) capabilityData, err := validateVSANCapability(strings.ToLower(parameter), value)
if err != nil { if err != nil {
return "", 0, err return "", 0, "", err
} else { } else {
volumeOptions.StorageProfileData += capabilityData volumeOptions.StorageProfileData += capabilityData
} }
default: 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) glog.V(1).Infof("StorageProfileData in vsphere volume %q", volumeOptions.StorageProfileData)
// TODO: implement PVC.Selector parsing // TODO: implement PVC.Selector parsing
if v.options.PVC.Spec.Selector != nil { 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) vmDiskPath, err = cloud.CreateVolume(volumeOptions)
if err != nil { if err != nil {
glog.V(2).Infof("Error creating vsphere volume: %v", err) 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) glog.V(2).Infof("Successfully created vsphere volume %s", name)
return vmDiskPath, volSizeKB, nil return vmDiskPath, volSizeKB, fstype, nil
} }
// DeleteVolume deletes a vSphere volume. // DeleteVolume deletes a vSphere volume.