-
Notifications
You must be signed in to change notification settings - Fork 143
Add volume capability to ControllerExpandVolume CSI call #70
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
64ffa0d
e0df338
f3eb9f7
f745bac
3b462ac
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,6 +22,7 @@ import ( | |
"fmt" | ||
"time" | ||
|
||
csilib "github.com/container-storage-interface/spec/lib/go/csi" | ||
"github.com/kubernetes-csi/csi-lib-utils/metrics" | ||
"github.com/kubernetes-csi/external-resizer/pkg/csi" | ||
"github.com/kubernetes-csi/external-resizer/pkg/util" | ||
|
@@ -36,6 +37,10 @@ import ( | |
"k8s.io/klog" | ||
) | ||
|
||
const ( | ||
defaultFSType = "ext4" | ||
) | ||
|
||
var ( | ||
controllerServiceNotSupportErr = errors.New("CSI driver does not support controller service") | ||
resizeNotSupportErr = errors.New("CSI driver neither supports controller resize nor node resize") | ||
|
@@ -157,10 +162,12 @@ func (r *csiResizer) Resize(pv *v1.PersistentVolume, requestSize resource.Quanti | |
|
||
var volumeID string | ||
var source *v1.CSIPersistentVolumeSource | ||
var pvSpec v1.PersistentVolumeSpec | ||
if pv.Spec.CSI != nil { | ||
// handle CSI volume | ||
source = pv.Spec.CSI | ||
volumeID = source.VolumeHandle | ||
pvSpec = pv.Spec | ||
} else { | ||
if csitranslationlib.IsMigratedCSIDriverByName(r.name) { | ||
// handle migrated in-tree volume | ||
|
@@ -169,6 +176,7 @@ func (r *csiResizer) Resize(pv *v1.PersistentVolume, requestSize resource.Quanti | |
return oldSize, false, fmt.Errorf("failed to translate persistent volume: %v", err) | ||
} | ||
source = csiPV.Spec.CSI | ||
pvSpec = csiPV.Spec | ||
volumeID = source.VolumeHandle | ||
} else { | ||
// non-migrated in-tree volume | ||
|
@@ -190,16 +198,82 @@ func (r *csiResizer) Resize(pv *v1.PersistentVolume, requestSize resource.Quanti | |
} | ||
} | ||
|
||
capability, err := GetVolumeCapabilities(pvSpec) | ||
if err != nil { | ||
return oldSize, false, fmt.Errorf("failed to get capabilities of volume %s with %v", pv.Name, err) | ||
} | ||
|
||
ctx, cancel := timeoutCtx(r.timeout) | ||
defer cancel() | ||
newSizeBytes, nodeResizeRequired, err := r.client.Expand(ctx, volumeID, requestSize.Value(), secrets) | ||
newSizeBytes, nodeResizeRequired, err := r.client.Expand(ctx, volumeID, requestSize.Value(), secrets, capability) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What happens if you call this against a driver that doesn't have this new field? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If the server is compiled (i.e the driver) with a version of CSI which does not have this field then the driver will not simply see it. |
||
if err != nil { | ||
return oldSize, nodeResizeRequired, err | ||
} | ||
|
||
return *resource.NewQuantity(newSizeBytes, resource.BinarySI), nodeResizeRequired, err | ||
} | ||
|
||
// GetVolumeCapabilities returns volumecapability from PV spec | ||
func GetVolumeCapabilities(pvSpec v1.PersistentVolumeSpec) (*csilib.VolumeCapability, error) { | ||
gnufied marked this conversation as resolved.
Show resolved
Hide resolved
|
||
m := map[v1.PersistentVolumeAccessMode]bool{} | ||
for _, mode := range pvSpec.AccessModes { | ||
m[mode] = true | ||
} | ||
|
||
if pvSpec.CSI == nil { | ||
return nil, errors.New("CSI volume source was nil") | ||
} | ||
|
||
var cap *csilib.VolumeCapability | ||
if pvSpec.VolumeMode != nil && *pvSpec.VolumeMode == v1.PersistentVolumeBlock { | ||
cap = &csilib.VolumeCapability{ | ||
AccessType: &csilib.VolumeCapability_Block{ | ||
Block: &csilib.VolumeCapability_BlockVolume{}, | ||
}, | ||
AccessMode: &csilib.VolumeCapability_AccessMode{}, | ||
} | ||
|
||
} else { | ||
fsType := pvSpec.CSI.FSType | ||
if len(fsType) == 0 { | ||
fsType = defaultFSType | ||
} | ||
|
||
cap = &csilib.VolumeCapability{ | ||
AccessType: &csilib.VolumeCapability_Mount{ | ||
Mount: &csilib.VolumeCapability_MountVolume{ | ||
FsType: fsType, | ||
MountFlags: pvSpec.MountOptions, | ||
}, | ||
}, | ||
AccessMode: &csilib.VolumeCapability_AccessMode{}, | ||
} | ||
} | ||
|
||
// Translate array of modes into single VolumeCapability | ||
switch { | ||
case m[v1.ReadWriteMany]: | ||
// ReadWriteMany trumps everything, regardless what other modes are set | ||
cap.AccessMode.Mode = csilib.VolumeCapability_AccessMode_MULTI_NODE_MULTI_WRITER | ||
|
||
case m[v1.ReadOnlyMany] && m[v1.ReadWriteOnce]: | ||
// This is no way how to translate this to CSI... | ||
return nil, fmt.Errorf("CSI does not support ReadOnlyMany and ReadWriteOnce on the same PersistentVolume") | ||
|
||
case m[v1.ReadOnlyMany]: | ||
// There is only ReadOnlyMany set | ||
cap.AccessMode.Mode = csilib.VolumeCapability_AccessMode_MULTI_NODE_READER_ONLY | ||
|
||
case m[v1.ReadWriteOnce]: | ||
// There is only ReadWriteOnce set | ||
cap.AccessMode.Mode = csilib.VolumeCapability_AccessMode_SINGLE_NODE_WRITER | ||
|
||
default: | ||
return nil, fmt.Errorf("unsupported AccessMode combination: %+v", pvSpec.AccessModes) | ||
} | ||
return cap, nil | ||
} | ||
|
||
func getDriverName(client csi.Client, timeout time.Duration) (string, error) { | ||
ctx, cancel := timeoutCtx(timeout) | ||
defer cancel() | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given what we have discussed here: https://github.com/kubernetes-csi/external-provisioner/pull/400/files#diff-38b23914da9991d96c9ec4fc3c2525aaR76, should this also be configurable and allow default to be "none"?
@msau42 ^^
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For control-plane volume expansion it should not ideally matter. This exists mostly for being on same page as external-attacher , what we really want to pass is block vs fs type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let me know if this is okay. Feel free to remove the hold if you are fine with this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think resizer should not have a defaultFSType. Just keep "fsType := pvSpec.CSI.FSType" but don't set a default to be consistent with the proposed change in external-provisioner. Otherwise we could potentially have a default fstype set to ext4 while driver internally use a different type.
In the external-provisioner, if we let driver set default to "none", driver will determine internally what fstype to use.
Unfortunately this fstype is not returned by CreateVolumeResponse in CSI. So pvSpec.CSI.FSType could be not set even if driver has used a non-ext4 type internally. If we change pvSpec.CSI.FSType to ext4 in resizer in this case, that will be the wrong fstype.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
okay I have dropped default fstype from this PR.