Skip to content
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

update GCE plugin for block support #58710

Merged
merged 1 commit into from
Feb 26, 2018

Conversation

screeley44
Copy link
Contributor

@screeley44 screeley44 commented Jan 23, 2018

update GCE plugin for block volume support

cc @gnufied @mtanino @jsafrane

GCE PD volume plugin got block volume support

@k8s-ci-robot k8s-ci-robot added do-not-merge/release-note-label-needed Indicates that a PR should not merge because it's missing one of the release note labels. size/L Denotes a PR that changes 100-499 lines, ignoring generated files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. labels Jan 23, 2018
@screeley44
Copy link
Contributor Author

/sig storage

@k8s-ci-robot k8s-ci-robot added the sig/storage Categorizes an issue or PR as relevant to SIG Storage. label Jan 23, 2018
@screeley44
Copy link
Contributor Author

/test pull-kubernetes-unit

@screeley44 screeley44 force-pushed the gce-block-update2 branch 2 times, most recently from 00a6c37 to 616f0ce Compare January 25, 2018 20:09
@screeley44 screeley44 force-pushed the gce-block-update2 branch 2 times, most recently from 802bb95 to 3bffe56 Compare January 26, 2018 01:41
@screeley44
Copy link
Contributor Author

/test pull-kubernetes-unit

@@ -0,0 +1,173 @@
/*
Copyright 2014 The Kubernetes Authors.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

year needs to be updated

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

glog.V(5).Infof("globalMapPathUUID: %v, err: %v", globalMapPathUUID, err)

globalMapPath := filepath.Dir(globalMapPathUUID)
if len(globalMapPath) == 1 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why 1?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well if the path is empty Dir returns "."

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be <= 1, like the check below? Can you also add a comment

// plugins/kubernetes.io/{PluginName}/{DefaultKubeletVolumeDevicesDirName}/{volumeID}
// plugins/kubernetes.io/gce-pd/volumeDevices/vol-XXXXXX
pdName := filepath.Base(globalMapPath)
if len(pdName) <= 1 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, why 1?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same, Base returns "." for an empty path so would indicate an error condition

Spec: v1.PersistentVolumeSpec{
PersistentVolumeSource: v1.PersistentVolumeSource{
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
PDName: pdName,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm partition is not being reconstructed (same with filesystem). I wonder if that could be a problem. I need to think about that a little more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When we unmap, do we need to know the actual device path? Or do we just cleanup the symlinks that only use volume name?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need the devicePath, Unmap will clean up the sym links and the loopback devices as far as I can tell.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, In order to remove loopback device, devicePath like /dev/sdc is needed. If the block volume is created for partitioned device like /dev/sdc1, then kubelet needs devicePath + partition number to remove loopback device.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So for regular scenario, the device path for partitions should be what attacher returns. For reconstruction, do we need to correctly reconstruct the partition number?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So for regular scenario, the device path for partitions should be what attacher returns.

Correct.

For reconstruction, do we need to correctly reconstruct the partition number?

I suppose we don't need to create full spec during reconstruction but at least, reconstructed spec must have members to create block volume mapper successfully. If block volume is created by partitioned devicePath in previous, symlink is connected to the devicePath including partition number. Therefore kubelet can retrieve devicePath from symlink instead of using value of partition .

We need this logic in @jingxu97 's next reconstruction update PR.

manager: manager,
mounter: mounter,
plugin: plugin,
MetricsProvider: volume.NewMetricsStatFS(getPath(podUID, spec.Name(), plugin.host)),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think StatFS is not going to work for block since there's no filesystem on it. Do usage metrics even make sense for block volumes? You can't really tell how much is used on a raw block device.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, was thinking the same thing, I can remove this I think

MetricsProvider: volume.NewMetricsStatFS(getPath(podUID, spec.Name(), plugin.host)),
},
readOnly: readOnly,
diskMounter: volumehelper.NewSafeFormatAndMountFromHost(plugin.GetPluginName(), plugin.host)}, nil
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this? We shouldn't be formatting or mounting anything for block volumes

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

carry over from FS - will remove it

volName: spec.Name(),
podUID: podUID,
pdName: pdName,
partition: partition,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where does partition get used to return the correct device path?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think partition gets used for block that I can tell, it was probably carry over from the FS struct, I will remove it

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's still legit to pass in a partition, although it's only supported with static PVs at the moment. I think you need to use the partition information when returning the device path.

Copy link
Contributor Author

@screeley44 screeley44 Feb 21, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@msau42 - when I tested it after commenting it out like this, I was able to get devicePath with no issues and the plugin worked correctly when in happy path. I also couldn't find where it is being used for block (maybe missed it), I see that is a volume partition like /dev/sda1 the partition would be 1 but just not sure where it is being called for block?. Anyway, I can add back in if you think we really do need it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If a user creates a PV with partition = 1, then we'll want the block device path to be /dev/sda1 (or whatever the gce pd device path format is). If it's partition = 2, then sda2, etc. Each partition should still be treated as a separate block device.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, I see now, I'll add back in

@screeley44 screeley44 force-pushed the gce-block-update2 branch 6 times, most recently from 3105fb9 to be4b24d Compare February 21, 2018 19:26
volName: spec.Name(),
podUID: podUID,
pdName: pdName,
partition: partition,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need to use this partition number when returning the global device path for this volume. @mtanino is it SetUp() that returns the global device path?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or because this is attachable, is it returned in the attach method?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is used in the attacher

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or because this is attachable, is it returned in the attach method?

yes, gce plugins is attachable and cloud provider supports remote attach for the plugin.
So the devicePath is returned during Attach() operation.

if err1a != nil {
t.Fatalf("can't make a temp dir: %v", err1a)
}
spec, err := getVolumeSpecFromGlobalMapPath(path1a)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you want to validate the fields in this spec?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is that necessary since that is already done within the api/validation and the existing unit tests there?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean, validate that this function return an appropriate spec with the correct pdName based on the given path.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

of course, my bad


// GetGlobalMapPath returns global map path and error
// path: plugins/kubernetes.io/{PluginName}/volumeDevices/pdName
func (pd *gcePersistentDisk) GetGlobalMapPath(spec *volume.Spec) (string, error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test case for this function?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll add one


// GetPodDeviceMapPath returns pod device map path and volume name
// path: pods/{podUid}/volumeDevices/kubernetes.io~aws
func (pd *gcePersistentDisk) GetPodDeviceMapPath() (string, string) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test case?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll add one

volName: spec.Name(),
podUID: podUID,
pdName: pdName,
partition: partition,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or because this is attachable, is it returned in the attach method?

@msau42
Copy link
Member

msau42 commented Feb 22, 2018

Also any plans to write an e2e test?

@screeley44
Copy link
Contributor Author

yes, we def plan on adding e2e tests but not sure we will make this release, I need to sync up with Erin and @mtanino

@@ -0,0 +1,135 @@
/*
Copyright 2014 The Kubernetes Authors.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

year

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ack

t.Fatalf("Failed to get spec from GlobalMapPath: %v", err)
}
if spec.PersistentVolume.Spec.GCEPersistentDisk.PDName != testPdName {
t.Fatalf("Invalid pdName retrieved from GlobalMapPath spec: %s", spec.PersistentVolume.Spec.GCEPersistentDisk.PDName)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe just Errorf instead of Fatalf here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ack

block := v1.PersistentVolumeBlock
specMode := spec.PersistentVolume.Spec.VolumeMode
if *specMode != block {
t.Fatalf("Invalid volumeMode retrieved from GlobalMapPath spec: %v - %v", *specMode, block)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same errorF. Also check for nil

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ack


expectedGlobalPath := path.Join(tmpVDir, testGlobalPath)

spec, err := getVolumeSpecFromGlobalMapPath(expectedGlobalPath)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also a test case with invalid global map path

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ack

@screeley44 screeley44 force-pushed the gce-block-update2 branch 4 times, most recently from b07f43f to 974bcbd Compare February 23, 2018 17:14
glog.V(5).Infof("globalMapPathUUID: %v, err: %v", globalMapPathUUID, err)

globalMapPath := filepath.Dir(globalMapPathUUID)
if len(globalMapPath) == 1 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be <= 1, like the check below? Can you also add a comment

//Bad Path
badspec, err := getVolumeSpecFromGlobalMapPath("")
if badspec != nil || err == nil {
t.Fatalf("Expected not to get spec from GlobalMapPath but did")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Errorf is fine here

t.Fatalf("Invalid GlobalMapPath from spec: %s", spec.PersistentVolume.Spec.GCEPersistentDisk.PDName)
}
if gMapPath != expectedGlobalPath {
t.Fatalf("Failed to get GlobalMapPath: %s %s", gMapPath, expectedGlobalPath)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Errorf

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ack to all

@msau42
Copy link
Member

msau42 commented Feb 23, 2018

/lgtm

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Feb 23, 2018
@jsafrane
Copy link
Member

/approve no-issue

@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: jsafrane, msau42, screeley44

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot added approved Indicates a PR has been approved by an approver from all required OWNERS files. release-note Denotes a PR that will be considered when it comes time to generate release notes. and removed do-not-merge/release-note-label-needed Indicates that a PR should not merge because it's missing one of the release note labels. labels Feb 26, 2018
@jsafrane jsafrane added this to the v1.10 milestone Feb 26, 2018
@jsafrane
Copy link
Member

@screeley44, I added release note to the first comment, please review.

@k8s-github-robot
Copy link

/test all [submit-queue is verifying that this PR is safe to merge]

@k8s-github-robot
Copy link

Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions here.

@k8s-github-robot k8s-github-robot merged commit 2aed8d7 into kubernetes:master Feb 26, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. lgtm "Looks good to me", indicates that a PR is ready to be merged. release-note Denotes a PR that will be considered when it comes time to generate release notes. sig/storage Categorizes an issue or PR as relevant to SIG Storage. size/L Denotes a PR that changes 100-499 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants