diff --git a/cmd/kubelet/app/server.go b/cmd/kubelet/app/server.go index 1e54f7cb8ce..29d36e14654 100644 --- a/cmd/kubelet/app/server.go +++ b/cmd/kubelet/app/server.go @@ -56,8 +56,6 @@ import ( "k8s.io/kubernetes/pkg/kubelet/server" kubetypes "k8s.io/kubernetes/pkg/kubelet/types" "k8s.io/kubernetes/pkg/util" - "k8s.io/kubernetes/pkg/util/chmod" - "k8s.io/kubernetes/pkg/util/chown" "k8s.io/kubernetes/pkg/util/io" "k8s.io/kubernetes/pkg/util/mount" nodeutil "k8s.io/kubernetes/pkg/util/node" @@ -134,9 +132,6 @@ func UnsecuredKubeletConfig(s *options.KubeletServer) (*KubeletConfig, error) { writer = &io.NsenterWriter{} } - chmodRunner := chmod.New() - chownRunner := chown.New() - tlsOptions, err := InitializeTLS(s) if err != nil { return nil, err @@ -216,8 +211,6 @@ func UnsecuredKubeletConfig(s *options.KubeletServer) (*KubeletConfig, error) { MaxPods: s.MaxPods, MinimumGCAge: s.MinimumGCAge.Duration, Mounter: mounter, - ChownRunner: chownRunner, - ChmodRunner: chmodRunner, NetworkPluginName: s.NetworkPluginName, NetworkPlugins: ProbeNetworkPlugins(s.NetworkPluginDir), NodeLabels: s.NodeLabels, @@ -510,8 +503,6 @@ func SimpleKubelet(client *client.Client, MaxPods: maxPods, MinimumGCAge: minimumGCAge, Mounter: mount.New(), - ChownRunner: chown.New(), - ChmodRunner: chmod.New(), NodeStatusUpdateFrequency: nodeStatusUpdateFrequency, OOMAdjuster: oom.NewFakeOOMAdjuster(), OSInterface: osInterface, @@ -694,8 +685,6 @@ type KubeletConfig struct { MaxPods int MinimumGCAge time.Duration Mounter mount.Interface - ChownRunner chown.Interface - ChmodRunner chmod.Interface NetworkPluginName string NetworkPlugins []network.NetworkPlugin NodeName string @@ -800,8 +789,6 @@ func CreateAndInitKubelet(kc *KubeletConfig) (k KubeletBootstrap, pc *config.Pod kc.RktStage1Image, kc.Mounter, kc.Writer, - kc.ChownRunner, - kc.ChmodRunner, kc.DockerDaemonContainer, kc.SystemContainer, kc.ConfigureCBR0, diff --git a/pkg/kubelet/kubelet.go b/pkg/kubelet/kubelet.go index b24bbb4244b..597489deb95 100644 --- a/pkg/kubelet/kubelet.go +++ b/pkg/kubelet/kubelet.go @@ -69,8 +69,6 @@ import ( "k8s.io/kubernetes/pkg/util" "k8s.io/kubernetes/pkg/util/atomic" "k8s.io/kubernetes/pkg/util/bandwidth" - "k8s.io/kubernetes/pkg/util/chmod" - "k8s.io/kubernetes/pkg/util/chown" utilerrors "k8s.io/kubernetes/pkg/util/errors" kubeio "k8s.io/kubernetes/pkg/util/io" "k8s.io/kubernetes/pkg/util/mount" @@ -178,8 +176,6 @@ func NewMainKubelet( rktStage1Image string, mounter mount.Interface, writer kubeio.Writer, - chownRunner chown.Interface, - chmodRunner chmod.Interface, dockerDaemonContainer string, systemContainer string, configureCBR0 bool, @@ -299,8 +295,6 @@ func NewMainKubelet( oomWatcher: oomWatcher, cgroupRoot: cgroupRoot, mounter: mounter, - chmodRunner: chmodRunner, - chownRunner: chownRunner, writer: writer, configureCBR0: configureCBR0, nonMasqueradeCIDR: nonMasqueradeCIDR, @@ -595,10 +589,6 @@ type Kubelet struct { // Mounter to use for volumes. mounter mount.Interface - // chown.Interface implementation to use - chownRunner chown.Interface - // chmod.Interface implementation to use - chmodRunner chmod.Interface // Writer interface to use for volumes. writer kubeio.Writer diff --git a/pkg/kubelet/kubelet_test.go b/pkg/kubelet/kubelet_test.go index f34e72d765c..a8834d64091 100644 --- a/pkg/kubelet/kubelet_test.go +++ b/pkg/kubelet/kubelet_test.go @@ -524,7 +524,7 @@ func TestGetPodVolumesFromDisk(t *testing.T) { expectedPaths := []string{} for i := range volsOnDisk { fv := volume.FakeVolume{PodUID: volsOnDisk[i].podUID, VolName: volsOnDisk[i].volName, Plugin: plug} - fv.SetUp() + fv.SetUp(nil) expectedPaths = append(expectedPaths, fv.GetPath()) } @@ -559,11 +559,11 @@ func (f *stubVolume) GetAttributes() volume.Attributes { return volume.Attributes{} } -func (f *stubVolume) SetUp() error { +func (f *stubVolume) SetUp(fsGroup *int64) error { return nil } -func (f *stubVolume) SetUpAt(dir string) error { +func (f *stubVolume) SetUpAt(dir string, fsGroup *int64) error { return nil } diff --git a/pkg/kubelet/volumes.go b/pkg/kubelet/volumes.go index 6e179584063..2372826f31f 100644 --- a/pkg/kubelet/volumes.go +++ b/pkg/kubelet/volumes.go @@ -132,11 +132,9 @@ func (kl *Kubelet) mountExternalVolumes(pod *api.Pod) (kubecontainer.VolumeMap, podVolumes := make(kubecontainer.VolumeMap) for i := range pod.Spec.Volumes { volSpec := &pod.Spec.Volumes[i] - hasFSGroup := false - var fsGroup int64 = 0 + var fsGroup *int64 if pod.Spec.SecurityContext != nil && pod.Spec.SecurityContext.FSGroup != nil { - hasFSGroup = true - fsGroup = *pod.Spec.SecurityContext.FSGroup + fsGroup = pod.Spec.SecurityContext.FSGroup } rootContext, err := kl.getRootDirContext() @@ -154,21 +152,10 @@ func (kl *Kubelet) mountExternalVolumes(pod *api.Pod) (kubecontainer.VolumeMap, if builder == nil { return nil, errUnsupportedVolumeType } - err = builder.SetUp() + err = builder.SetUp(fsGroup) if err != nil { return nil, err } - if hasFSGroup && - builder.GetAttributes().Managed && - builder.GetAttributes().SupportsOwnershipManagement { - err := kl.manageVolumeOwnership(pod, internal, builder, fsGroup) - if err != nil { - glog.Errorf("Error managing ownership of volume %v for pod %v/%v: %v", internal.Name(), pod.Namespace, pod.Name, err) - return nil, err - } else { - glog.V(3).Infof("Managed ownership of volume %v for pod %v/%v", internal.Name(), pod.Namespace, pod.Name) - } - } podVolumes[volSpec.Name] = kubecontainer.VolumeInfo{Builder: builder} } return podVolumes, nil diff --git a/pkg/volume/aws_ebs/aws_ebs.go b/pkg/volume/aws_ebs/aws_ebs.go index 401ac551676..5df20b8d1fb 100644 --- a/pkg/volume/aws_ebs/aws_ebs.go +++ b/pkg/volume/aws_ebs/aws_ebs.go @@ -222,20 +222,19 @@ var _ volume.Builder = &awsElasticBlockStoreBuilder{} func (b *awsElasticBlockStoreBuilder) GetAttributes() volume.Attributes { return volume.Attributes{ - ReadOnly: b.readOnly, - Managed: !b.readOnly, - SupportsOwnershipManagement: true, - SupportsSELinux: true, + ReadOnly: b.readOnly, + Managed: !b.readOnly, + SupportsSELinux: true, } } // SetUp attaches the disk and bind mounts to the volume path. -func (b *awsElasticBlockStoreBuilder) SetUp() error { - return b.SetUpAt(b.GetPath()) +func (b *awsElasticBlockStoreBuilder) SetUp(fsGroup *int64) error { + return b.SetUpAt(b.GetPath(), fsGroup) } // SetUpAt attaches the disk and bind mounts to the volume path. -func (b *awsElasticBlockStoreBuilder) SetUpAt(dir string) error { +func (b *awsElasticBlockStoreBuilder) SetUpAt(dir string, fsGroup *int64) error { // TODO: handle failed mounts here. notMnt, err := b.mounter.IsLikelyNotMountPoint(dir) glog.V(4).Infof("PersistentDisk set up: %s %v %v", dir, !notMnt, err) @@ -291,6 +290,10 @@ func (b *awsElasticBlockStoreBuilder) SetUpAt(dir string) error { return err } + if !b.readOnly { + volume.SetVolumeOwnership(b, fsGroup) + } + return nil } diff --git a/pkg/volume/aws_ebs/aws_ebs_test.go b/pkg/volume/aws_ebs/aws_ebs_test.go index 736fd8e0d99..73c34a25b0b 100644 --- a/pkg/volume/aws_ebs/aws_ebs_test.go +++ b/pkg/volume/aws_ebs/aws_ebs_test.go @@ -153,7 +153,7 @@ func TestPlugin(t *testing.T) { t.Errorf("Got unexpected path: %s", path) } - if err := builder.SetUp(); err != nil { + if err := builder.SetUp(nil); err != nil { t.Errorf("Expected success, got: %v", err) } if _, err := os.Stat(path); err != nil { diff --git a/pkg/volume/cephfs/cephfs.go b/pkg/volume/cephfs/cephfs.go index 09a85db2aac..366fecbb8cf 100644 --- a/pkg/volume/cephfs/cephfs.go +++ b/pkg/volume/cephfs/cephfs.go @@ -155,20 +155,19 @@ var _ volume.Builder = &cephfsBuilder{} func (cephfsVolume *cephfsBuilder) GetAttributes() volume.Attributes { return volume.Attributes{ - ReadOnly: cephfsVolume.readonly, - Managed: false, - SupportsOwnershipManagement: false, - SupportsSELinux: false, + ReadOnly: cephfsVolume.readonly, + Managed: false, + SupportsSELinux: false, } } // SetUp attaches the disk and bind mounts to the volume path. -func (cephfsVolume *cephfsBuilder) SetUp() error { - return cephfsVolume.SetUpAt(cephfsVolume.GetPath()) +func (cephfsVolume *cephfsBuilder) SetUp(fsGroup *int64) error { + return cephfsVolume.SetUpAt(cephfsVolume.GetPath(), fsGroup) } // SetUpAt attaches the disk and bind mounts to the volume path. -func (cephfsVolume *cephfsBuilder) SetUpAt(dir string) error { +func (cephfsVolume *cephfsBuilder) SetUpAt(dir string, fsGroup *int64) error { notMnt, err := cephfsVolume.mounter.IsLikelyNotMountPoint(dir) glog.V(4).Infof("CephFS mount set up: %s %v %v", dir, !notMnt, err) if err != nil && !os.IsNotExist(err) { diff --git a/pkg/volume/cephfs/cephfs_test.go b/pkg/volume/cephfs/cephfs_test.go index e68106cd48a..b2e8d5bf725 100644 --- a/pkg/volume/cephfs/cephfs_test.go +++ b/pkg/volume/cephfs/cephfs_test.go @@ -88,7 +88,7 @@ func TestPlugin(t *testing.T) { if path != volpath { t.Errorf("Got unexpected path: %s", path) } - if err := builder.SetUp(); err != nil { + if err := builder.SetUp(nil); err != nil { t.Errorf("Expected success, got: %v", err) } if _, err := os.Stat(volumePath); err != nil { diff --git a/pkg/volume/cinder/cinder.go b/pkg/volume/cinder/cinder.go index 8240fd707a0..d8c222e837c 100644 --- a/pkg/volume/cinder/cinder.go +++ b/pkg/volume/cinder/cinder.go @@ -216,19 +216,18 @@ func detachDiskLogError(cd *cinderVolume) { func (b *cinderVolumeBuilder) GetAttributes() volume.Attributes { return volume.Attributes{ - ReadOnly: b.readOnly, - Managed: !b.readOnly, - SupportsOwnershipManagement: true, - SupportsSELinux: true, + ReadOnly: b.readOnly, + Managed: !b.readOnly, + SupportsSELinux: true, } } -func (b *cinderVolumeBuilder) SetUp() error { - return b.SetUpAt(b.GetPath()) +func (b *cinderVolumeBuilder) SetUp(fsGroup *int64) error { + return b.SetUpAt(b.GetPath(), fsGroup) } // SetUp attaches the disk and bind mounts to the volume path. -func (b *cinderVolumeBuilder) SetUpAt(dir string) error { +func (b *cinderVolumeBuilder) SetUpAt(dir string, fsGroup *int64) error { // TODO: handle failed mounts here. notmnt, err := b.mounter.IsLikelyNotMountPoint(dir) glog.V(4).Infof("PersistentDisk set up: %s %v %v", dir, !notmnt, err) @@ -284,6 +283,10 @@ func (b *cinderVolumeBuilder) SetUpAt(dir string) error { return err } + if !b.readOnly { + volume.SetVolumeOwnership(b, fsGroup) + } + return nil } diff --git a/pkg/volume/cinder/cinder_test.go b/pkg/volume/cinder/cinder_test.go index e22519f10d4..3613ed5c3a0 100644 --- a/pkg/volume/cinder/cinder_test.go +++ b/pkg/volume/cinder/cinder_test.go @@ -121,7 +121,7 @@ func TestPlugin(t *testing.T) { t.Errorf("Got unexpected path: %s", path) } - if err := builder.SetUp(); err != nil { + if err := builder.SetUp(nil); err != nil { t.Errorf("Expected success, got: %v", err) } if _, err := os.Stat(path); err != nil { diff --git a/pkg/volume/downwardapi/downwardapi.go b/pkg/volume/downwardapi/downwardapi.go index 014ef07ca4c..d6fcca78007 100644 --- a/pkg/volume/downwardapi/downwardapi.go +++ b/pkg/volume/downwardapi/downwardapi.go @@ -118,10 +118,9 @@ var _ volume.Builder = &downwardAPIVolumeBuilder{} // downward API volumes are always ReadOnlyManaged func (d *downwardAPIVolume) GetAttributes() volume.Attributes { return volume.Attributes{ - ReadOnly: true, - Managed: true, - SupportsOwnershipManagement: true, - SupportsSELinux: true, + ReadOnly: true, + Managed: true, + SupportsSELinux: true, } } @@ -129,11 +128,11 @@ func (d *downwardAPIVolume) GetAttributes() volume.Attributes { // This function is not idempotent by design. We want the data to be refreshed periodically. // The internal sync interval of kubelet will drive the refresh of data. // TODO: Add volume specific ticker and refresh loop -func (b *downwardAPIVolumeBuilder) SetUp() error { - return b.SetUpAt(b.GetPath()) +func (b *downwardAPIVolumeBuilder) SetUp(fsGroup *int64) error { + return b.SetUpAt(b.GetPath(), fsGroup) } -func (b *downwardAPIVolumeBuilder) SetUpAt(dir string) error { +func (b *downwardAPIVolumeBuilder) SetUpAt(dir string, fsGroup *int64) error { glog.V(3).Infof("Setting up a downwardAPI volume %v for pod %v/%v at %v", b.volName, b.pod.Namespace, b.pod.Name, dir) // Wrap EmptyDir. Here we rely on the idempotency of the wrapped plugin to avoid repeatedly mounting wrapped, err := b.plugin.host.NewWrapperBuilder(b.volName, wrappedVolumeSpec, b.pod, *b.opts) @@ -141,7 +140,7 @@ func (b *downwardAPIVolumeBuilder) SetUpAt(dir string) error { glog.Errorf("Couldn't setup downwardAPI volume %v for pod %v/%v: %s", b.volName, b.pod.Namespace, b.pod.Name, err.Error()) return err } - if err := wrapped.SetUpAt(dir); err != nil { + if err := wrapped.SetUpAt(dir, fsGroup); err != nil { glog.Errorf("Unable to setup downwardAPI volume %v for pod %v/%v: %s", b.volName, b.pod.Namespace, b.pod.Name, err.Error()) return err } @@ -163,6 +162,9 @@ func (b *downwardAPIVolumeBuilder) SetUpAt(dir string) error { } glog.V(3).Infof("Data dumped for downwardAPI volume %v for pod %v/%v", b.volName, b.pod.Namespace, b.pod.Name) + + volume.SetVolumeOwnership(b, fsGroup) + return nil } diff --git a/pkg/volume/downwardapi/downwardapi_test.go b/pkg/volume/downwardapi/downwardapi_test.go index 20432d73e91..ca857bf5041 100644 --- a/pkg/volume/downwardapi/downwardapi_test.go +++ b/pkg/volume/downwardapi/downwardapi_test.go @@ -138,7 +138,7 @@ func TestLabels(t *testing.T) { volumePath := builder.GetPath() - err = builder.SetUp() + err = builder.SetUp(nil) if err != nil { t.Errorf("Failed to setup volume: %v", err) } @@ -219,7 +219,7 @@ func TestAnnotations(t *testing.T) { volumePath := builder.GetPath() - err = builder.SetUp() + err = builder.SetUp(nil) if err != nil { t.Errorf("Failed to setup volume: %v", err) } @@ -285,7 +285,7 @@ func TestName(t *testing.T) { volumePath := builder.GetPath() - err = builder.SetUp() + err = builder.SetUp(nil) if err != nil { t.Errorf("Failed to setup volume: %v", err) } @@ -352,7 +352,7 @@ func TestNamespace(t *testing.T) { volumePath := builder.GetPath() - err = builder.SetUp() + err = builder.SetUp(nil) if err != nil { t.Errorf("Failed to setup volume: %v", err) } @@ -421,7 +421,7 @@ func TestWriteTwiceNoUpdate(t *testing.T) { } volumePath := builder.GetPath() - err = builder.SetUp() + err = builder.SetUp(nil) if err != nil { t.Errorf("Failed to setup volume: %v", err) } @@ -432,7 +432,7 @@ func TestWriteTwiceNoUpdate(t *testing.T) { t.Errorf(".current should be a link... %s\n", err.Error()) } - err = builder.SetUp() // now re-run Setup + err = builder.SetUp(nil) // now re-run Setup if err != nil { t.Errorf("Failed to re-setup volume: %v", err) } @@ -511,7 +511,7 @@ func TestWriteTwiceWithUpdate(t *testing.T) { } volumePath := builder.GetPath() - err = builder.SetUp() + err = builder.SetUp(nil) if err != nil { t.Errorf("Failed to setup volume: %v", err) } @@ -538,7 +538,7 @@ func TestWriteTwiceWithUpdate(t *testing.T) { // Now update the labels pod.ObjectMeta.Labels = newLabels - err = builder.SetUp() // now re-run Setup + err = builder.SetUp(nil) // now re-run Setup if err != nil { t.Errorf("Failed to re-setup volume: %v", err) } @@ -623,7 +623,7 @@ func TestWriteWithUnixPath(t *testing.T) { } volumePath := builder.GetPath() - err = builder.SetUp() + err = builder.SetUp(nil) if err != nil { t.Errorf("Failed to setup volume: %v", err) } @@ -709,7 +709,7 @@ func TestWriteWithUnixPathBadPath(t *testing.T) { volumePath := builder.GetPath() defer CleanEverything(plugin, testVolumeName, volumePath, testPodUID, t) - err = builder.SetUp() + err = builder.SetUp(nil) if err != nil { t.Fatalf("Failed to setup volume: %v", err) } diff --git a/pkg/volume/empty_dir/empty_dir.go b/pkg/volume/empty_dir/empty_dir.go index 15ad499bc78..4d862930408 100644 --- a/pkg/volume/empty_dir/empty_dir.go +++ b/pkg/volume/empty_dir/empty_dir.go @@ -142,20 +142,19 @@ type emptyDir struct { func (ed *emptyDir) GetAttributes() volume.Attributes { return volume.Attributes{ - ReadOnly: false, - Managed: true, - SupportsOwnershipManagement: true, - SupportsSELinux: true, + ReadOnly: false, + Managed: true, + SupportsSELinux: true, } } // SetUp creates new directory. -func (ed *emptyDir) SetUp() error { - return ed.SetUpAt(ed.GetPath()) +func (ed *emptyDir) SetUp(fsGroup *int64) error { + return ed.SetUpAt(ed.GetPath(), fsGroup) } // SetUpAt creates new directory. -func (ed *emptyDir) SetUpAt(dir string) error { +func (ed *emptyDir) SetUpAt(dir string, fsGroup *int64) error { notMnt, err := ed.mounter.IsLikelyNotMountPoint(dir) // Getting an os.IsNotExist err from is a contingency; the directory // may not exist yet, in which case, setup should run. @@ -190,6 +189,8 @@ func (ed *emptyDir) SetUpAt(dir string) error { err = fmt.Errorf("unknown storage medium %q", ed.medium) } + volume.SetVolumeOwnership(ed, fsGroup) + if err == nil { volumeutil.SetReady(ed.getMetaDir()) } diff --git a/pkg/volume/empty_dir/empty_dir_test.go b/pkg/volume/empty_dir/empty_dir_test.go index dd19f47693a..a1e4044bb45 100644 --- a/pkg/volume/empty_dir/empty_dir_test.go +++ b/pkg/volume/empty_dir/empty_dir_test.go @@ -185,7 +185,7 @@ func doTestPlugin(t *testing.T, config pluginTestConfig) { t.Errorf("Got unexpected path: %s", volPath) } - if err := builder.SetUp(); err != nil { + if err := builder.SetUp(nil); err != nil { t.Errorf("Expected success, got: %v", err) } diff --git a/pkg/volume/fc/disk_manager.go b/pkg/volume/fc/disk_manager.go index b7419ecc95b..c064eada605 100644 --- a/pkg/volume/fc/disk_manager.go +++ b/pkg/volume/fc/disk_manager.go @@ -21,6 +21,7 @@ import ( "github.com/golang/glog" "k8s.io/kubernetes/pkg/util/mount" + "k8s.io/kubernetes/pkg/volume" ) // Abstract interface to disk operations. @@ -33,7 +34,7 @@ type diskManager interface { } // utility to mount a disk based filesystem -func diskSetUp(manager diskManager, b fcDiskBuilder, volPath string, mounter mount.Interface) error { +func diskSetUp(manager diskManager, b fcDiskBuilder, volPath string, mounter mount.Interface, fsGroup *int64) error { globalPDPath := manager.MakeGlobalPDName(*b.fcDisk) // TODO: handle failed mounts here. noMnt, err := mounter.IsLikelyNotMountPoint(volPath) @@ -64,6 +65,11 @@ func diskSetUp(manager diskManager, b fcDiskBuilder, volPath string, mounter mou glog.Errorf("failed to bind mount:%s", globalPDPath) return err } + + if !b.readOnly { + volume.SetVolumeOwnership(&b, fsGroup) + } + return nil } diff --git a/pkg/volume/fc/fc.go b/pkg/volume/fc/fc.go index 1d99393ebd3..0c0fc1014d0 100644 --- a/pkg/volume/fc/fc.go +++ b/pkg/volume/fc/fc.go @@ -170,19 +170,18 @@ var _ volume.Builder = &fcDiskBuilder{} func (b *fcDiskBuilder) GetAttributes() volume.Attributes { return volume.Attributes{ - ReadOnly: b.readOnly, - Managed: !b.readOnly, - SupportsOwnershipManagement: true, - SupportsSELinux: true, + ReadOnly: b.readOnly, + Managed: !b.readOnly, + SupportsSELinux: true, } } -func (b *fcDiskBuilder) SetUp() error { - return b.SetUpAt(b.GetPath()) +func (b *fcDiskBuilder) SetUp(fsGroup *int64) error { + return b.SetUpAt(b.GetPath(), fsGroup) } -func (b *fcDiskBuilder) SetUpAt(dir string) error { +func (b *fcDiskBuilder) SetUpAt(dir string, fsGroup *int64) error { // diskSetUp checks mountpoints and prevent repeated calls - err := diskSetUp(b.manager, *b, dir, b.mounter) + err := diskSetUp(b.manager, *b, dir, b.mounter, fsGroup) if err != nil { glog.Errorf("fc: failed to setup") } diff --git a/pkg/volume/fc/fc_test.go b/pkg/volume/fc/fc_test.go index 21214f30034..2d2e29f70c3 100644 --- a/pkg/volume/fc/fc_test.go +++ b/pkg/volume/fc/fc_test.go @@ -120,7 +120,7 @@ func doTestPlugin(t *testing.T, spec *volume.Spec) { t.Errorf("Got unexpected path: %s", path) } - if err := builder.SetUp(); err != nil { + if err := builder.SetUp(nil); err != nil { t.Errorf("Expected success, got: %v", err) } if _, err := os.Stat(path); err != nil { diff --git a/pkg/volume/flexvolume/flexvolume.go b/pkg/volume/flexvolume/flexvolume.go index 0096d5698d1..de2159327ae 100644 --- a/pkg/volume/flexvolume/flexvolume.go +++ b/pkg/volume/flexvolume/flexvolume.go @@ -223,18 +223,17 @@ type flexVolumeBuilder struct { } // SetUp creates new directory. -func (f *flexVolumeBuilder) SetUp() error { - return f.SetUpAt(f.GetPath()) +func (f *flexVolumeBuilder) SetUp(fsGroup *int64) error { + return f.SetUpAt(f.GetPath(), fsGroup) } // GetAttributes get the flex volume attributes. The attributes will be queried // using plugin callout after we finalize the callout syntax. func (f flexVolumeBuilder) GetAttributes() volume.Attributes { return volume.Attributes{ - ReadOnly: f.readOnly, - Managed: false, - SupportsOwnershipManagement: false, - SupportsSELinux: false, + ReadOnly: f.readOnly, + Managed: false, + SupportsSELinux: false, } } @@ -251,7 +250,7 @@ type flexVolumeManager interface { } // SetUpAt creates new directory. -func (f *flexVolumeBuilder) SetUpAt(dir string) error { +func (f *flexVolumeBuilder) SetUpAt(dir string, fsGroup *int64) error { notmnt, err := f.blockDeviceMounter.IsLikelyNotMountPoint(dir) if err != nil && !os.IsNotExist(err) { diff --git a/pkg/volume/flexvolume/flexvolume_test.go b/pkg/volume/flexvolume/flexvolume_test.go index f5438af9bd5..fe01c7a347d 100644 --- a/pkg/volume/flexvolume/flexvolume_test.go +++ b/pkg/volume/flexvolume/flexvolume_test.go @@ -238,7 +238,7 @@ func doTestPluginAttachDetach(t *testing.T, spec *volume.Spec) { if path != "/tmp/fake/pods/poduid/volumes/kubernetes.io~fakeAttacher/vol1" { t.Errorf("Got unexpected path: %s", path) } - if err := builder.SetUp(); err != nil { + if err := builder.SetUp(nil); err != nil { t.Errorf("Expected success, got: %v", err) } if _, err := os.Stat(volumePath); err != nil { @@ -310,7 +310,7 @@ func doTestPluginMountUnmount(t *testing.T, spec *volume.Spec) { if path != "/tmp/fake/pods/poduid/volumes/kubernetes.io~fakeMounter/vol1" { t.Errorf("Got unexpected path: %s", path) } - if err := builder.SetUp(); err != nil { + if err := builder.SetUp(nil); err != nil { t.Errorf("Expected success, got: %v", err) } if _, err := os.Stat(volumePath); err != nil { diff --git a/pkg/volume/flocker/plugin.go b/pkg/volume/flocker/plugin.go index a7c6a9c7af6..e32618b036f 100644 --- a/pkg/volume/flocker/plugin.go +++ b/pkg/volume/flocker/plugin.go @@ -117,18 +117,17 @@ type flockerBuilder struct { func (b flockerBuilder) GetAttributes() volume.Attributes { return volume.Attributes{ - ReadOnly: b.readOnly, - Managed: false, - SupportsOwnershipManagement: false, - SupportsSELinux: false, + ReadOnly: b.readOnly, + Managed: false, + SupportsSELinux: false, } } func (b flockerBuilder) GetPath() string { return b.flocker.path } -func (b flockerBuilder) SetUp() error { - return b.SetUpAt(b.flocker.datasetName) +func (b flockerBuilder) SetUp(fsGroup *int64) error { + return b.SetUpAt(b.flocker.datasetName, fsGroup) } // newFlockerClient uses environment variables and pod attributes to return a @@ -168,7 +167,7 @@ control service: need to update the Primary UUID for this volume. 5. Wait until the Primary UUID was updated or timeout. */ -func (b flockerBuilder) SetUpAt(dir string) error { +func (b flockerBuilder) SetUpAt(dir string, fsGroup *int64) error { if volumeutil.IsReady(b.getMetaDir()) { return nil } diff --git a/pkg/volume/flocker/plugin_test.go b/pkg/volume/flocker/plugin_test.go index e172d2badc7..10574d5a6a2 100644 --- a/pkg/volume/flocker/plugin_test.go +++ b/pkg/volume/flocker/plugin_test.go @@ -211,6 +211,6 @@ func TestSetUpAtInternal(t *testing.T) { b := flockerBuilder{flocker: &flocker{pod: pod, plugin: plug.(*flockerPlugin)}} b.client = newMockFlockerClient("dataset-id", "primary-uid", mockPath) - assert.NoError(b.SetUpAt(dir)) + assert.NoError(b.SetUpAt(dir, nil)) assert.Equal(expectedPath, b.flocker.path) } diff --git a/pkg/volume/gce_pd/gce_pd.go b/pkg/volume/gce_pd/gce_pd.go index 86a42ea7822..f97f7278af6 100644 --- a/pkg/volume/gce_pd/gce_pd.go +++ b/pkg/volume/gce_pd/gce_pd.go @@ -211,20 +211,19 @@ var _ volume.Builder = &gcePersistentDiskBuilder{} func (b *gcePersistentDiskBuilder) GetAttributes() volume.Attributes { return volume.Attributes{ - ReadOnly: b.readOnly, - Managed: !b.readOnly, - SupportsOwnershipManagement: true, - SupportsSELinux: true, + ReadOnly: b.readOnly, + Managed: !b.readOnly, + SupportsSELinux: true, } } // SetUp attaches the disk and bind mounts to the volume path. -func (b *gcePersistentDiskBuilder) SetUp() error { - return b.SetUpAt(b.GetPath()) +func (b *gcePersistentDiskBuilder) SetUp(fsGroup *int64) error { + return b.SetUpAt(b.GetPath(), fsGroup) } // SetUpAt attaches the disk and bind mounts to the volume path. -func (b *gcePersistentDiskBuilder) SetUpAt(dir string) error { +func (b *gcePersistentDiskBuilder) SetUpAt(dir string, fsGroup *int64) error { // TODO: handle failed mounts here. notMnt, err := b.mounter.IsLikelyNotMountPoint(dir) glog.V(4).Infof("PersistentDisk set up: %s %v %v", dir, !notMnt, err) @@ -280,6 +279,10 @@ func (b *gcePersistentDiskBuilder) SetUpAt(dir string) error { return err } + if !b.readOnly { + volume.SetVolumeOwnership(b, fsGroup) + } + return nil } diff --git a/pkg/volume/gce_pd/gce_pd_test.go b/pkg/volume/gce_pd/gce_pd_test.go index 881ad3a3bd7..af3f769de60 100644 --- a/pkg/volume/gce_pd/gce_pd_test.go +++ b/pkg/volume/gce_pd/gce_pd_test.go @@ -161,7 +161,7 @@ func TestPlugin(t *testing.T) { t.Errorf("Got unexpected path: %s", path) } - if err := builder.SetUp(); err != nil { + if err := builder.SetUp(nil); err != nil { t.Errorf("Expected success, got: %v", err) } if _, err := os.Stat(path); err != nil { diff --git a/pkg/volume/git_repo/git_repo.go b/pkg/volume/git_repo/git_repo.go index b27203af266..b21c20b8cf4 100644 --- a/pkg/volume/git_repo/git_repo.go +++ b/pkg/volume/git_repo/git_repo.go @@ -120,20 +120,19 @@ var _ volume.Builder = &gitRepoVolumeBuilder{} func (b *gitRepoVolumeBuilder) GetAttributes() volume.Attributes { return volume.Attributes{ - ReadOnly: false, - Managed: true, - SupportsOwnershipManagement: false, - SupportsSELinux: true, // xattr change should be okay, TODO: double check + ReadOnly: false, + Managed: true, + SupportsSELinux: true, // xattr change should be okay, TODO: double check } } // SetUp creates new directory and clones a git repo. -func (b *gitRepoVolumeBuilder) SetUp() error { - return b.SetUpAt(b.GetPath()) +func (b *gitRepoVolumeBuilder) SetUp(fsGroup *int64) error { + return b.SetUpAt(b.GetPath(), fsGroup) } // SetUpAt creates new directory and clones a git repo. -func (b *gitRepoVolumeBuilder) SetUpAt(dir string) error { +func (b *gitRepoVolumeBuilder) SetUpAt(dir string, fsGroup *int64) error { if volumeutil.IsReady(b.getMetaDir()) { return nil } @@ -143,7 +142,7 @@ func (b *gitRepoVolumeBuilder) SetUpAt(dir string) error { if err != nil { return err } - if err := wrapped.SetUpAt(dir); err != nil { + if err := wrapped.SetUpAt(dir, fsGroup); err != nil { return err } diff --git a/pkg/volume/git_repo/git_repo_test.go b/pkg/volume/git_repo/git_repo_test.go index 5c4140ed9c3..54453b4d143 100644 --- a/pkg/volume/git_repo/git_repo_test.go +++ b/pkg/volume/git_repo/git_repo_test.go @@ -351,7 +351,7 @@ func doTestSetUp(scenario struct { g := builder.(*gitRepoVolumeBuilder) g.exec = &fake - g.SetUp() + g.SetUp(nil) if fake.CommandCalls != len(expecteds) { allErrs = append(allErrs, diff --git a/pkg/volume/glusterfs/glusterfs.go b/pkg/volume/glusterfs/glusterfs.go index 50e2d435d1a..d745e88b4c5 100644 --- a/pkg/volume/glusterfs/glusterfs.go +++ b/pkg/volume/glusterfs/glusterfs.go @@ -158,19 +158,18 @@ var _ volume.Builder = &glusterfsBuilder{} func (b *glusterfsBuilder) GetAttributes() volume.Attributes { return volume.Attributes{ - ReadOnly: b.readOnly, - Managed: false, - SupportsOwnershipManagement: false, - SupportsSELinux: false, + ReadOnly: b.readOnly, + Managed: false, + SupportsSELinux: false, } } // SetUp attaches the disk and bind mounts to the volume path. -func (b *glusterfsBuilder) SetUp() error { - return b.SetUpAt(b.GetPath()) +func (b *glusterfsBuilder) SetUp(fsGroup *int64) error { + return b.SetUpAt(b.GetPath(), fsGroup) } -func (b *glusterfsBuilder) SetUpAt(dir string) error { +func (b *glusterfsBuilder) SetUpAt(dir string, fsGroup *int64) error { notMnt, err := b.mounter.IsLikelyNotMountPoint(dir) glog.V(4).Infof("glusterfs: mount set up: %s %v %v", dir, !notMnt, err) if err != nil && !os.IsNotExist(err) { diff --git a/pkg/volume/glusterfs/glusterfs_test.go b/pkg/volume/glusterfs/glusterfs_test.go index bedcfb9a91d..3987231631b 100644 --- a/pkg/volume/glusterfs/glusterfs_test.go +++ b/pkg/volume/glusterfs/glusterfs_test.go @@ -104,7 +104,7 @@ func doTestPlugin(t *testing.T, spec *volume.Spec) { if path != "/tmp/fake/pods/poduid/volumes/kubernetes.io~glusterfs/vol1" { t.Errorf("Got unexpected path: %s", path) } - if err := builder.SetUp(); err != nil { + if err := builder.SetUp(nil); err != nil { t.Errorf("Expected success, got: %v", err) } if _, err := os.Stat(volumePath); err != nil { diff --git a/pkg/volume/host_path/host_path.go b/pkg/volume/host_path/host_path.go index 636369e816e..1dfcec7503b 100644 --- a/pkg/volume/host_path/host_path.go +++ b/pkg/volume/host_path/host_path.go @@ -178,20 +178,19 @@ var _ volume.Builder = &hostPathBuilder{} func (b *hostPathBuilder) GetAttributes() volume.Attributes { return volume.Attributes{ - ReadOnly: b.readOnly, - Managed: false, - SupportsOwnershipManagement: false, - SupportsSELinux: false, + ReadOnly: b.readOnly, + Managed: false, + SupportsSELinux: false, } } // SetUp does nothing. -func (b *hostPathBuilder) SetUp() error { +func (b *hostPathBuilder) SetUp(fsGroup *int64) error { return nil } // SetUpAt does not make sense for host paths - probably programmer error. -func (b *hostPathBuilder) SetUpAt(dir string) error { +func (b *hostPathBuilder) SetUpAt(dir string, fsGroup *int64) error { return fmt.Errorf("SetUpAt() does not make sense for host paths") } diff --git a/pkg/volume/host_path/host_path_test.go b/pkg/volume/host_path/host_path_test.go index 88623d2636c..33b1c628185 100644 --- a/pkg/volume/host_path/host_path_test.go +++ b/pkg/volume/host_path/host_path_test.go @@ -210,7 +210,7 @@ func TestPlugin(t *testing.T) { t.Errorf("Got unexpected path: %s", path) } - if err := builder.SetUp(); err != nil { + if err := builder.SetUp(nil); err != nil { t.Errorf("Expected success, got: %v", err) } diff --git a/pkg/volume/iscsi/disk_manager.go b/pkg/volume/iscsi/disk_manager.go index 800633ae46e..70dd679e61e 100644 --- a/pkg/volume/iscsi/disk_manager.go +++ b/pkg/volume/iscsi/disk_manager.go @@ -21,6 +21,7 @@ import ( "github.com/golang/glog" "k8s.io/kubernetes/pkg/util/mount" + "k8s.io/kubernetes/pkg/volume" ) // Abstract interface to disk operations. @@ -33,7 +34,7 @@ type diskManager interface { } // utility to mount a disk based filesystem -func diskSetUp(manager diskManager, b iscsiDiskBuilder, volPath string, mounter mount.Interface) error { +func diskSetUp(manager diskManager, b iscsiDiskBuilder, volPath string, mounter mount.Interface, fsGroup *int64) error { globalPDPath := manager.MakeGlobalPDName(*b.iscsiDisk) // TODO: handle failed mounts here. notMnt, err := mounter.IsLikelyNotMountPoint(volPath) @@ -64,6 +65,11 @@ func diskSetUp(manager diskManager, b iscsiDiskBuilder, volPath string, mounter glog.Errorf("failed to bind mount:%s", globalPDPath) return err } + + if !b.readOnly { + volume.SetVolumeOwnership(&b, fsGroup) + } + return nil } diff --git a/pkg/volume/iscsi/iscsi.go b/pkg/volume/iscsi/iscsi.go index 6d01b31336b..fe2f32ff13d 100644 --- a/pkg/volume/iscsi/iscsi.go +++ b/pkg/volume/iscsi/iscsi.go @@ -168,20 +168,19 @@ var _ volume.Builder = &iscsiDiskBuilder{} func (b *iscsiDiskBuilder) GetAttributes() volume.Attributes { return volume.Attributes{ - ReadOnly: b.readOnly, - Managed: !b.readOnly, - SupportsOwnershipManagement: true, - SupportsSELinux: true, + ReadOnly: b.readOnly, + Managed: !b.readOnly, + SupportsSELinux: true, } } -func (b *iscsiDiskBuilder) SetUp() error { - return b.SetUpAt(b.GetPath()) +func (b *iscsiDiskBuilder) SetUp(fsGroup *int64) error { + return b.SetUpAt(b.GetPath(), fsGroup) } -func (b *iscsiDiskBuilder) SetUpAt(dir string) error { +func (b *iscsiDiskBuilder) SetUpAt(dir string, fsGroup *int64) error { // diskSetUp checks mountpoints and prevent repeated calls - err := diskSetUp(b.manager, *b, dir, b.mounter) + err := diskSetUp(b.manager, *b, dir, b.mounter, fsGroup) if err != nil { glog.Errorf("iscsi: failed to setup") } diff --git a/pkg/volume/iscsi/iscsi_test.go b/pkg/volume/iscsi/iscsi_test.go index bc99b65922b..4cc82e55768 100644 --- a/pkg/volume/iscsi/iscsi_test.go +++ b/pkg/volume/iscsi/iscsi_test.go @@ -120,7 +120,7 @@ func doTestPlugin(t *testing.T, spec *volume.Spec) { t.Errorf("Got unexpected path: %s", path) } - if err := builder.SetUp(); err != nil { + if err := builder.SetUp(nil); err != nil { t.Errorf("Expected success, got: %v", err) } if _, err := os.Stat(path); err != nil { diff --git a/pkg/volume/nfs/nfs.go b/pkg/volume/nfs/nfs.go index 4b1934f85f4..4065cb168c6 100644 --- a/pkg/volume/nfs/nfs.go +++ b/pkg/volume/nfs/nfs.go @@ -151,19 +151,18 @@ var _ volume.Builder = &nfsBuilder{} func (b *nfsBuilder) GetAttributes() volume.Attributes { return volume.Attributes{ - ReadOnly: b.readOnly, - Managed: false, - SupportsOwnershipManagement: false, - SupportsSELinux: false, + ReadOnly: b.readOnly, + Managed: false, + SupportsSELinux: false, } } // SetUp attaches the disk and bind mounts to the volume path. -func (b *nfsBuilder) SetUp() error { - return b.SetUpAt(b.GetPath()) +func (b *nfsBuilder) SetUp(fsGroup *int64) error { + return b.SetUpAt(b.GetPath(), fsGroup) } -func (b *nfsBuilder) SetUpAt(dir string) error { +func (b *nfsBuilder) SetUpAt(dir string, fsGroup *int64) error { notMnt, err := b.mounter.IsLikelyNotMountPoint(dir) glog.V(4).Infof("NFS mount set up: %s %v %v", dir, !notMnt, err) if err != nil && !os.IsNotExist(err) { diff --git a/pkg/volume/nfs/nfs_test.go b/pkg/volume/nfs/nfs_test.go index b9ebc48ac99..781b82c7ae6 100644 --- a/pkg/volume/nfs/nfs_test.go +++ b/pkg/volume/nfs/nfs_test.go @@ -133,7 +133,7 @@ func doTestPlugin(t *testing.T, spec *volume.Spec) { if path != "/tmp/fake/pods/poduid/volumes/kubernetes.io~nfs/vol1" { t.Errorf("Got unexpected path: %s", path) } - if err := builder.SetUp(); err != nil { + if err := builder.SetUp(nil); err != nil { t.Errorf("Expected success, got: %v", err) } if _, err := os.Stat(volumePath); err != nil { diff --git a/pkg/volume/rbd/disk_manager.go b/pkg/volume/rbd/disk_manager.go index 229827fd903..37982491b0c 100644 --- a/pkg/volume/rbd/disk_manager.go +++ b/pkg/volume/rbd/disk_manager.go @@ -27,6 +27,7 @@ import ( "github.com/golang/glog" "k8s.io/kubernetes/pkg/util/mount" + "k8s.io/kubernetes/pkg/volume" ) // Abstract interface to disk operations. @@ -39,7 +40,7 @@ type diskManager interface { } // utility to mount a disk based filesystem -func diskSetUp(manager diskManager, b rbdBuilder, volPath string, mounter mount.Interface) error { +func diskSetUp(manager diskManager, b rbdBuilder, volPath string, mounter mount.Interface, fsGroup *int64) error { globalPDPath := manager.MakeGlobalPDName(*b.rbd) // TODO: handle failed mounts here. notMnt, err := mounter.IsLikelyNotMountPoint(volPath) @@ -70,6 +71,11 @@ func diskSetUp(manager diskManager, b rbdBuilder, volPath string, mounter mount. glog.Errorf("failed to bind mount:%s", globalPDPath) return err } + + if !b.ReadOnly { + volume.SetVolumeOwnership(&b, fsGroup) + } + return nil } diff --git a/pkg/volume/rbd/rbd.go b/pkg/volume/rbd/rbd.go index c40aa4a67ff..deb089df8b1 100644 --- a/pkg/volume/rbd/rbd.go +++ b/pkg/volume/rbd/rbd.go @@ -196,20 +196,19 @@ var _ volume.Builder = &rbdBuilder{} func (b *rbd) GetAttributes() volume.Attributes { return volume.Attributes{ - ReadOnly: b.ReadOnly, - Managed: !b.ReadOnly, - SupportsOwnershipManagement: true, - SupportsSELinux: true, + ReadOnly: b.ReadOnly, + Managed: !b.ReadOnly, + SupportsSELinux: true, } } -func (b *rbdBuilder) SetUp() error { - return b.SetUpAt(b.GetPath()) +func (b *rbdBuilder) SetUp(fsGroup *int64) error { + return b.SetUpAt(b.GetPath(), fsGroup) } -func (b *rbdBuilder) SetUpAt(dir string) error { +func (b *rbdBuilder) SetUpAt(dir string, fsGroup *int64) error { // diskSetUp checks mountpoints and prevent repeated calls - err := diskSetUp(b.manager, *b, dir, b.mounter) + err := diskSetUp(b.manager, *b, dir, b.mounter, fsGroup) if err != nil { glog.Errorf("rbd: failed to setup") } diff --git a/pkg/volume/rbd/rbd_test.go b/pkg/volume/rbd/rbd_test.go index d0c2b8997f4..c71f29e4a6a 100644 --- a/pkg/volume/rbd/rbd_test.go +++ b/pkg/volume/rbd/rbd_test.go @@ -87,7 +87,7 @@ func doTestPlugin(t *testing.T, spec *volume.Spec) { t.Errorf("Got unexpected path: %s", path) } - if err := builder.SetUp(); err != nil { + if err := builder.SetUp(nil); err != nil { t.Errorf("Expected success, got: %v", err) } if _, err := os.Stat(path); err != nil { diff --git a/pkg/volume/secret/secret.go b/pkg/volume/secret/secret.go index 5f6d2d3e767..8c9f91620fd 100644 --- a/pkg/volume/secret/secret.go +++ b/pkg/volume/secret/secret.go @@ -122,21 +122,20 @@ var _ volume.Builder = &secretVolumeBuilder{} func (sv *secretVolume) GetAttributes() volume.Attributes { return volume.Attributes{ - ReadOnly: true, - Managed: true, - SupportsOwnershipManagement: true, - SupportsSELinux: true, + ReadOnly: true, + Managed: true, + SupportsSELinux: true, } } -func (b *secretVolumeBuilder) SetUp() error { - return b.SetUpAt(b.GetPath()) +func (b *secretVolumeBuilder) SetUp(fsGroup *int64) error { + return b.SetUpAt(b.GetPath(), fsGroup) } func (b *secretVolumeBuilder) getMetaDir() string { return path.Join(b.plugin.host.GetPodPluginDir(b.podUID, strings.EscapeQualifiedNameForDisk(secretPluginName)), b.volName) } -func (b *secretVolumeBuilder) SetUpAt(dir string) error { +func (b *secretVolumeBuilder) SetUpAt(dir string, fsGroup *int64) error { notMnt, err := b.mounter.IsLikelyNotMountPoint(dir) // Getting an os.IsNotExist err from is a contingency; the directory // may not exist yet, in which case, setup should run. @@ -157,7 +156,7 @@ func (b *secretVolumeBuilder) SetUpAt(dir string) error { if err != nil { return err } - if err := wrapped.SetUpAt(dir); err != nil { + if err := wrapped.SetUpAt(dir, fsGroup); err != nil { return err } @@ -189,6 +188,8 @@ func (b *secretVolumeBuilder) SetUpAt(dir string) error { } } + volume.SetVolumeOwnership(b, fsGroup) + volumeutil.SetReady(b.getMetaDir()) return nil diff --git a/pkg/volume/secret/secret_test.go b/pkg/volume/secret/secret_test.go index 654f3782fb8..9d1d36e9a35 100644 --- a/pkg/volume/secret/secret_test.go +++ b/pkg/volume/secret/secret_test.go @@ -98,7 +98,7 @@ func TestPlugin(t *testing.T) { t.Errorf("Got unexpected path: %s", volumePath) } - err = builder.SetUp() + err = builder.SetUp(nil) if err != nil { t.Errorf("Failed to setup volume: %v", err) } @@ -166,7 +166,7 @@ func TestPluginIdempotent(t *testing.T) { } volumePath := builder.GetPath() - err = builder.SetUp() + err = builder.SetUp(nil) if err != nil { t.Errorf("Failed to setup volume: %v", err) } @@ -224,7 +224,7 @@ func TestPluginReboot(t *testing.T) { t.Errorf("Got unexpected path: %s", volumePath) } - err = builder.SetUp() + err = builder.SetUp(nil) if err != nil { t.Errorf("Failed to setup volume: %v", err) } diff --git a/pkg/volume/testing.go b/pkg/volume/testing.go index d9d1f175a9b..e7cb4d870f1 100644 --- a/pkg/volume/testing.go +++ b/pkg/volume/testing.go @@ -189,18 +189,17 @@ type FakeVolume struct { func (_ *FakeVolume) GetAttributes() Attributes { return Attributes{ - ReadOnly: false, - Managed: true, - SupportsOwnershipManagement: true, - SupportsSELinux: true, + ReadOnly: false, + Managed: true, + SupportsSELinux: true, } } -func (fv *FakeVolume) SetUp() error { - return fv.SetUpAt(fv.GetPath()) +func (fv *FakeVolume) SetUp(fsGroup *int64) error { + return fv.SetUpAt(fv.GetPath(), fsGroup) } -func (fv *FakeVolume) SetUpAt(dir string) error { +func (fv *FakeVolume) SetUpAt(dir string, fsGroup *int64) error { return os.MkdirAll(dir, 0750) } diff --git a/pkg/volume/volume.go b/pkg/volume/volume.go index aab01158f2b..c8c9a70b9bd 100644 --- a/pkg/volume/volume.go +++ b/pkg/volume/volume.go @@ -20,6 +20,7 @@ import ( "io/ioutil" "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/resource" + "os" "path" ) @@ -59,24 +60,28 @@ type Metrics struct { // Attributes represents the attributes of this builder. type Attributes struct { - ReadOnly bool - Managed bool - SupportsOwnershipManagement bool - SupportsSELinux bool + ReadOnly bool + Managed bool + SupportsSELinux bool } // Builder interface provides methods to set up/mount the volume. type Builder interface { // Uses Interface to provide the path for Docker binds. Volume - // SetUp prepares and mounts/unpacks the volume to a self-determined - // directory path. This may be called more than once, so + // SetUp prepares and mounts/unpacks the volume to a + // self-determined directory path. The mount point and its + // content should be owned by 'fsGroup' so that it can be + // accessed by the pod. This may be called more than once, so // implementations must be idempotent. - SetUp() error - // SetUpAt prepares and mounts/unpacks the volume to the specified - // directory path, which may or may not exist yet. This may be called - // more than once, so implementations must be idempotent. - SetUpAt(dir string) error + SetUp(fsGroup *int64) error + // SetUpAt prepares and mounts/unpacks the volume to the + // specified directory path, which may or may not exist yet. + // The mount point and its content should be owned by + // 'fsGroup' so that it can be accessed by the pod. This may + // be called more than once, so implementations must be + // idempotent. + SetUpAt(dir string, sGroup *int64) error // GetAttributes returns the attributes of the builder. GetAttributes() Attributes } diff --git a/pkg/kubelet/volumes_linux.go b/pkg/volume/volume_linux.go similarity index 62% rename from pkg/kubelet/volumes_linux.go rename to pkg/volume/volume_linux.go index 3f20a0a10bb..d99d3f780d2 100644 --- a/pkg/kubelet/volumes_linux.go +++ b/pkg/volume/volume_linux.go @@ -1,7 +1,7 @@ // +build linux /* -Copyright 2014 The Kubernetes Authors All rights reserved. +Copyright 2016 The Kubernetes Authors All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -16,26 +16,34 @@ See the License for the specific language governing permissions and limitations under the License. */ -package kubelet +package volume import ( - "os" + "k8s.io/kubernetes/pkg/util/chmod" + "k8s.io/kubernetes/pkg/util/chown" "path/filepath" "syscall" "github.com/golang/glog" - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/volume" + "os" ) -// Bitmasks to OR with current ownership of volumes that allow ownership management by the Kubelet const ( rwMask = os.FileMode(0660) roMask = os.FileMode(0440) ) -// manageVolumeOwnership modifies the given volume to be owned by fsGroup. -func (kl *Kubelet) manageVolumeOwnership(pod *api.Pod, volSpec *volume.Spec, builder volume.Builder, fsGroup int64) error { +// SetVolumeOwnership modifies the given volume to be owned by +// fsGroup, and sets SetGid so that newly created files are owned by +// fsGroup. If fsGroup is nil nothing is done. +func SetVolumeOwnership(builder Builder, fsGroup *int64) error { + + if fsGroup == nil { + return nil + } + + chownRunner := chown.New() + chmodRunner := chmod.New() return filepath.Walk(builder.GetPath(), func(path string, info os.FileInfo, err error) error { if err != nil { return err @@ -47,11 +55,11 @@ func (kl *Kubelet) manageVolumeOwnership(pod *api.Pod, volSpec *volume.Spec, bui } if stat == nil { - glog.Errorf("Got nil stat_t for path %v while managing ownership of volume %v for pod %s/%s", path, volSpec.Name, pod.Namespace, pod.Name) + glog.Errorf("Got nil stat_t for path %v while setting ownership of volume", path) return nil } - err = kl.chownRunner.Chown(path, int(stat.Uid), int(fsGroup)) + err = chownRunner.Chown(path, int(stat.Uid), int(*fsGroup)) if err != nil { glog.Errorf("Chown failed on %v: %v", path, err) } @@ -61,7 +69,7 @@ func (kl *Kubelet) manageVolumeOwnership(pod *api.Pod, volSpec *volume.Spec, bui mask = roMask } - err = kl.chmodRunner.Chmod(path, info.Mode()|mask|os.ModeSetgid) + err = chmodRunner.Chmod(path, info.Mode()|mask|os.ModeSetgid) if err != nil { glog.Errorf("Chmod failed on %v: %v", path, err) } diff --git a/pkg/kubelet/volumes_unsupported.go b/pkg/volume/volume_unsupported.go similarity index 67% rename from pkg/kubelet/volumes_unsupported.go rename to pkg/volume/volume_unsupported.go index 7590e0a8979..dd86d0e06f6 100644 --- a/pkg/kubelet/volumes_unsupported.go +++ b/pkg/volume/volume_unsupported.go @@ -1,7 +1,7 @@ // +build !linux /* -Copyright 2014 The Kubernetes Authors All rights reserved. +Copyright 2016 The Kubernetes Authors All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -16,13 +16,8 @@ See the License for the specific language governing permissions and limitations under the License. */ -package kubelet +package volume -import ( - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/volume" -) - -func (_ *Kubelet) manageVolumeOwnership(pod *api.Pod, volSpec *volume.Spec, builder volume.Builder, fsGroup int64) error { +func SetVolumeOwnership(builder Builder, fsGroup *int64) error { return nil }