Merge pull request #19502 from swagiaal/internalize-ownership

Auto commit by PR queue bot
This commit is contained in:
k8s-merge-robot 2016-01-26 23:06:39 -08:00
commit 3f5e417999
43 changed files with 219 additions and 227 deletions

View File

@ -56,8 +56,6 @@ import (
"k8s.io/kubernetes/pkg/kubelet/server" "k8s.io/kubernetes/pkg/kubelet/server"
kubetypes "k8s.io/kubernetes/pkg/kubelet/types" kubetypes "k8s.io/kubernetes/pkg/kubelet/types"
"k8s.io/kubernetes/pkg/util" "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/io"
"k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/util/mount"
nodeutil "k8s.io/kubernetes/pkg/util/node" nodeutil "k8s.io/kubernetes/pkg/util/node"
@ -134,9 +132,6 @@ func UnsecuredKubeletConfig(s *options.KubeletServer) (*KubeletConfig, error) {
writer = &io.NsenterWriter{} writer = &io.NsenterWriter{}
} }
chmodRunner := chmod.New()
chownRunner := chown.New()
tlsOptions, err := InitializeTLS(s) tlsOptions, err := InitializeTLS(s)
if err != nil { if err != nil {
return nil, err return nil, err
@ -216,8 +211,6 @@ func UnsecuredKubeletConfig(s *options.KubeletServer) (*KubeletConfig, error) {
MaxPods: s.MaxPods, MaxPods: s.MaxPods,
MinimumGCAge: s.MinimumGCAge.Duration, MinimumGCAge: s.MinimumGCAge.Duration,
Mounter: mounter, Mounter: mounter,
ChownRunner: chownRunner,
ChmodRunner: chmodRunner,
NetworkPluginName: s.NetworkPluginName, NetworkPluginName: s.NetworkPluginName,
NetworkPlugins: ProbeNetworkPlugins(s.NetworkPluginDir), NetworkPlugins: ProbeNetworkPlugins(s.NetworkPluginDir),
NodeLabels: s.NodeLabels, NodeLabels: s.NodeLabels,
@ -510,8 +503,6 @@ func SimpleKubelet(client *client.Client,
MaxPods: maxPods, MaxPods: maxPods,
MinimumGCAge: minimumGCAge, MinimumGCAge: minimumGCAge,
Mounter: mount.New(), Mounter: mount.New(),
ChownRunner: chown.New(),
ChmodRunner: chmod.New(),
NodeStatusUpdateFrequency: nodeStatusUpdateFrequency, NodeStatusUpdateFrequency: nodeStatusUpdateFrequency,
OOMAdjuster: oom.NewFakeOOMAdjuster(), OOMAdjuster: oom.NewFakeOOMAdjuster(),
OSInterface: osInterface, OSInterface: osInterface,
@ -694,8 +685,6 @@ type KubeletConfig struct {
MaxPods int MaxPods int
MinimumGCAge time.Duration MinimumGCAge time.Duration
Mounter mount.Interface Mounter mount.Interface
ChownRunner chown.Interface
ChmodRunner chmod.Interface
NetworkPluginName string NetworkPluginName string
NetworkPlugins []network.NetworkPlugin NetworkPlugins []network.NetworkPlugin
NodeName string NodeName string
@ -800,8 +789,6 @@ func CreateAndInitKubelet(kc *KubeletConfig) (k KubeletBootstrap, pc *config.Pod
kc.RktStage1Image, kc.RktStage1Image,
kc.Mounter, kc.Mounter,
kc.Writer, kc.Writer,
kc.ChownRunner,
kc.ChmodRunner,
kc.DockerDaemonContainer, kc.DockerDaemonContainer,
kc.SystemContainer, kc.SystemContainer,
kc.ConfigureCBR0, kc.ConfigureCBR0,

View File

@ -69,8 +69,6 @@ import (
"k8s.io/kubernetes/pkg/util" "k8s.io/kubernetes/pkg/util"
"k8s.io/kubernetes/pkg/util/atomic" "k8s.io/kubernetes/pkg/util/atomic"
"k8s.io/kubernetes/pkg/util/bandwidth" "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" utilerrors "k8s.io/kubernetes/pkg/util/errors"
kubeio "k8s.io/kubernetes/pkg/util/io" kubeio "k8s.io/kubernetes/pkg/util/io"
"k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/util/mount"
@ -178,8 +176,6 @@ func NewMainKubelet(
rktStage1Image string, rktStage1Image string,
mounter mount.Interface, mounter mount.Interface,
writer kubeio.Writer, writer kubeio.Writer,
chownRunner chown.Interface,
chmodRunner chmod.Interface,
dockerDaemonContainer string, dockerDaemonContainer string,
systemContainer string, systemContainer string,
configureCBR0 bool, configureCBR0 bool,
@ -299,8 +295,6 @@ func NewMainKubelet(
oomWatcher: oomWatcher, oomWatcher: oomWatcher,
cgroupRoot: cgroupRoot, cgroupRoot: cgroupRoot,
mounter: mounter, mounter: mounter,
chmodRunner: chmodRunner,
chownRunner: chownRunner,
writer: writer, writer: writer,
configureCBR0: configureCBR0, configureCBR0: configureCBR0,
nonMasqueradeCIDR: nonMasqueradeCIDR, nonMasqueradeCIDR: nonMasqueradeCIDR,
@ -595,10 +589,6 @@ type Kubelet struct {
// Mounter to use for volumes. // Mounter to use for volumes.
mounter mount.Interface 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 interface to use for volumes.
writer kubeio.Writer writer kubeio.Writer

View File

@ -524,7 +524,7 @@ func TestGetPodVolumesFromDisk(t *testing.T) {
expectedPaths := []string{} expectedPaths := []string{}
for i := range volsOnDisk { for i := range volsOnDisk {
fv := volume.FakeVolume{PodUID: volsOnDisk[i].podUID, VolName: volsOnDisk[i].volName, Plugin: plug} fv := volume.FakeVolume{PodUID: volsOnDisk[i].podUID, VolName: volsOnDisk[i].volName, Plugin: plug}
fv.SetUp() fv.SetUp(nil)
expectedPaths = append(expectedPaths, fv.GetPath()) expectedPaths = append(expectedPaths, fv.GetPath())
} }
@ -559,11 +559,11 @@ func (f *stubVolume) GetAttributes() volume.Attributes {
return volume.Attributes{} return volume.Attributes{}
} }
func (f *stubVolume) SetUp() error { func (f *stubVolume) SetUp(fsGroup *int64) error {
return nil return nil
} }
func (f *stubVolume) SetUpAt(dir string) error { func (f *stubVolume) SetUpAt(dir string, fsGroup *int64) error {
return nil return nil
} }

View File

@ -132,11 +132,9 @@ func (kl *Kubelet) mountExternalVolumes(pod *api.Pod) (kubecontainer.VolumeMap,
podVolumes := make(kubecontainer.VolumeMap) podVolumes := make(kubecontainer.VolumeMap)
for i := range pod.Spec.Volumes { for i := range pod.Spec.Volumes {
volSpec := &pod.Spec.Volumes[i] volSpec := &pod.Spec.Volumes[i]
hasFSGroup := false var fsGroup *int64
var fsGroup int64 = 0
if pod.Spec.SecurityContext != nil && pod.Spec.SecurityContext.FSGroup != nil { 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() rootContext, err := kl.getRootDirContext()
@ -154,21 +152,10 @@ func (kl *Kubelet) mountExternalVolumes(pod *api.Pod) (kubecontainer.VolumeMap,
if builder == nil { if builder == nil {
return nil, errUnsupportedVolumeType return nil, errUnsupportedVolumeType
} }
err = builder.SetUp() err = builder.SetUp(fsGroup)
if err != nil { if err != nil {
return nil, err 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} podVolumes[volSpec.Name] = kubecontainer.VolumeInfo{Builder: builder}
} }
return podVolumes, nil return podVolumes, nil

View File

@ -222,20 +222,19 @@ var _ volume.Builder = &awsElasticBlockStoreBuilder{}
func (b *awsElasticBlockStoreBuilder) GetAttributes() volume.Attributes { func (b *awsElasticBlockStoreBuilder) GetAttributes() volume.Attributes {
return volume.Attributes{ return volume.Attributes{
ReadOnly: b.readOnly, ReadOnly: b.readOnly,
Managed: !b.readOnly, Managed: !b.readOnly,
SupportsOwnershipManagement: true, SupportsSELinux: true,
SupportsSELinux: true,
} }
} }
// SetUp attaches the disk and bind mounts to the volume path. // SetUp attaches the disk and bind mounts to the volume path.
func (b *awsElasticBlockStoreBuilder) SetUp() error { func (b *awsElasticBlockStoreBuilder) SetUp(fsGroup *int64) error {
return b.SetUpAt(b.GetPath()) return b.SetUpAt(b.GetPath(), fsGroup)
} }
// SetUpAt attaches the disk and bind mounts to the volume path. // 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. // TODO: handle failed mounts here.
notMnt, err := b.mounter.IsLikelyNotMountPoint(dir) notMnt, err := b.mounter.IsLikelyNotMountPoint(dir)
glog.V(4).Infof("PersistentDisk set up: %s %v %v", dir, !notMnt, err) 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 return err
} }
if !b.readOnly {
volume.SetVolumeOwnership(b, fsGroup)
}
return nil return nil
} }

View File

@ -153,7 +153,7 @@ func TestPlugin(t *testing.T) {
t.Errorf("Got unexpected path: %s", path) 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) t.Errorf("Expected success, got: %v", err)
} }
if _, err := os.Stat(path); err != nil { if _, err := os.Stat(path); err != nil {

View File

@ -155,20 +155,19 @@ var _ volume.Builder = &cephfsBuilder{}
func (cephfsVolume *cephfsBuilder) GetAttributes() volume.Attributes { func (cephfsVolume *cephfsBuilder) GetAttributes() volume.Attributes {
return volume.Attributes{ return volume.Attributes{
ReadOnly: cephfsVolume.readonly, ReadOnly: cephfsVolume.readonly,
Managed: false, Managed: false,
SupportsOwnershipManagement: false, SupportsSELinux: false,
SupportsSELinux: false,
} }
} }
// SetUp attaches the disk and bind mounts to the volume path. // SetUp attaches the disk and bind mounts to the volume path.
func (cephfsVolume *cephfsBuilder) SetUp() error { func (cephfsVolume *cephfsBuilder) SetUp(fsGroup *int64) error {
return cephfsVolume.SetUpAt(cephfsVolume.GetPath()) return cephfsVolume.SetUpAt(cephfsVolume.GetPath(), fsGroup)
} }
// SetUpAt attaches the disk and bind mounts to the volume path. // 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) notMnt, err := cephfsVolume.mounter.IsLikelyNotMountPoint(dir)
glog.V(4).Infof("CephFS mount set up: %s %v %v", dir, !notMnt, err) glog.V(4).Infof("CephFS mount set up: %s %v %v", dir, !notMnt, err)
if err != nil && !os.IsNotExist(err) { if err != nil && !os.IsNotExist(err) {

View File

@ -88,7 +88,7 @@ func TestPlugin(t *testing.T) {
if path != volpath { if path != volpath {
t.Errorf("Got unexpected path: %s", path) 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) t.Errorf("Expected success, got: %v", err)
} }
if _, err := os.Stat(volumePath); err != nil { if _, err := os.Stat(volumePath); err != nil {

View File

@ -216,19 +216,18 @@ func detachDiskLogError(cd *cinderVolume) {
func (b *cinderVolumeBuilder) GetAttributes() volume.Attributes { func (b *cinderVolumeBuilder) GetAttributes() volume.Attributes {
return volume.Attributes{ return volume.Attributes{
ReadOnly: b.readOnly, ReadOnly: b.readOnly,
Managed: !b.readOnly, Managed: !b.readOnly,
SupportsOwnershipManagement: true, SupportsSELinux: true,
SupportsSELinux: true,
} }
} }
func (b *cinderVolumeBuilder) SetUp() error { func (b *cinderVolumeBuilder) SetUp(fsGroup *int64) error {
return b.SetUpAt(b.GetPath()) return b.SetUpAt(b.GetPath(), fsGroup)
} }
// SetUp attaches the disk and bind mounts to the volume path. // 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. // TODO: handle failed mounts here.
notmnt, err := b.mounter.IsLikelyNotMountPoint(dir) notmnt, err := b.mounter.IsLikelyNotMountPoint(dir)
glog.V(4).Infof("PersistentDisk set up: %s %v %v", dir, !notmnt, err) 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 return err
} }
if !b.readOnly {
volume.SetVolumeOwnership(b, fsGroup)
}
return nil return nil
} }

View File

@ -121,7 +121,7 @@ func TestPlugin(t *testing.T) {
t.Errorf("Got unexpected path: %s", path) 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) t.Errorf("Expected success, got: %v", err)
} }
if _, err := os.Stat(path); err != nil { if _, err := os.Stat(path); err != nil {

View File

@ -118,10 +118,9 @@ var _ volume.Builder = &downwardAPIVolumeBuilder{}
// downward API volumes are always ReadOnlyManaged // downward API volumes are always ReadOnlyManaged
func (d *downwardAPIVolume) GetAttributes() volume.Attributes { func (d *downwardAPIVolume) GetAttributes() volume.Attributes {
return volume.Attributes{ return volume.Attributes{
ReadOnly: true, ReadOnly: true,
Managed: true, Managed: true,
SupportsOwnershipManagement: true, SupportsSELinux: 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. // 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. // The internal sync interval of kubelet will drive the refresh of data.
// TODO: Add volume specific ticker and refresh loop // TODO: Add volume specific ticker and refresh loop
func (b *downwardAPIVolumeBuilder) SetUp() error { func (b *downwardAPIVolumeBuilder) SetUp(fsGroup *int64) error {
return b.SetUpAt(b.GetPath()) 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) 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 // 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) 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()) 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 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()) 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 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) 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 return nil
} }

View File

@ -138,7 +138,7 @@ func TestLabels(t *testing.T) {
volumePath := builder.GetPath() volumePath := builder.GetPath()
err = builder.SetUp() err = builder.SetUp(nil)
if err != nil { if err != nil {
t.Errorf("Failed to setup volume: %v", err) t.Errorf("Failed to setup volume: %v", err)
} }
@ -219,7 +219,7 @@ func TestAnnotations(t *testing.T) {
volumePath := builder.GetPath() volumePath := builder.GetPath()
err = builder.SetUp() err = builder.SetUp(nil)
if err != nil { if err != nil {
t.Errorf("Failed to setup volume: %v", err) t.Errorf("Failed to setup volume: %v", err)
} }
@ -285,7 +285,7 @@ func TestName(t *testing.T) {
volumePath := builder.GetPath() volumePath := builder.GetPath()
err = builder.SetUp() err = builder.SetUp(nil)
if err != nil { if err != nil {
t.Errorf("Failed to setup volume: %v", err) t.Errorf("Failed to setup volume: %v", err)
} }
@ -352,7 +352,7 @@ func TestNamespace(t *testing.T) {
volumePath := builder.GetPath() volumePath := builder.GetPath()
err = builder.SetUp() err = builder.SetUp(nil)
if err != nil { if err != nil {
t.Errorf("Failed to setup volume: %v", err) t.Errorf("Failed to setup volume: %v", err)
} }
@ -421,7 +421,7 @@ func TestWriteTwiceNoUpdate(t *testing.T) {
} }
volumePath := builder.GetPath() volumePath := builder.GetPath()
err = builder.SetUp() err = builder.SetUp(nil)
if err != nil { if err != nil {
t.Errorf("Failed to setup volume: %v", err) 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()) 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 { if err != nil {
t.Errorf("Failed to re-setup volume: %v", err) t.Errorf("Failed to re-setup volume: %v", err)
} }
@ -511,7 +511,7 @@ func TestWriteTwiceWithUpdate(t *testing.T) {
} }
volumePath := builder.GetPath() volumePath := builder.GetPath()
err = builder.SetUp() err = builder.SetUp(nil)
if err != nil { if err != nil {
t.Errorf("Failed to setup volume: %v", err) t.Errorf("Failed to setup volume: %v", err)
} }
@ -538,7 +538,7 @@ func TestWriteTwiceWithUpdate(t *testing.T) {
// Now update the labels // Now update the labels
pod.ObjectMeta.Labels = newLabels pod.ObjectMeta.Labels = newLabels
err = builder.SetUp() // now re-run Setup err = builder.SetUp(nil) // now re-run Setup
if err != nil { if err != nil {
t.Errorf("Failed to re-setup volume: %v", err) t.Errorf("Failed to re-setup volume: %v", err)
} }
@ -623,7 +623,7 @@ func TestWriteWithUnixPath(t *testing.T) {
} }
volumePath := builder.GetPath() volumePath := builder.GetPath()
err = builder.SetUp() err = builder.SetUp(nil)
if err != nil { if err != nil {
t.Errorf("Failed to setup volume: %v", err) t.Errorf("Failed to setup volume: %v", err)
} }
@ -709,7 +709,7 @@ func TestWriteWithUnixPathBadPath(t *testing.T) {
volumePath := builder.GetPath() volumePath := builder.GetPath()
defer CleanEverything(plugin, testVolumeName, volumePath, testPodUID, t) defer CleanEverything(plugin, testVolumeName, volumePath, testPodUID, t)
err = builder.SetUp() err = builder.SetUp(nil)
if err != nil { if err != nil {
t.Fatalf("Failed to setup volume: %v", err) t.Fatalf("Failed to setup volume: %v", err)
} }

View File

@ -142,20 +142,19 @@ type emptyDir struct {
func (ed *emptyDir) GetAttributes() volume.Attributes { func (ed *emptyDir) GetAttributes() volume.Attributes {
return volume.Attributes{ return volume.Attributes{
ReadOnly: false, ReadOnly: false,
Managed: true, Managed: true,
SupportsOwnershipManagement: true, SupportsSELinux: true,
SupportsSELinux: true,
} }
} }
// SetUp creates new directory. // SetUp creates new directory.
func (ed *emptyDir) SetUp() error { func (ed *emptyDir) SetUp(fsGroup *int64) error {
return ed.SetUpAt(ed.GetPath()) return ed.SetUpAt(ed.GetPath(), fsGroup)
} }
// SetUpAt creates new directory. // 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) notMnt, err := ed.mounter.IsLikelyNotMountPoint(dir)
// Getting an os.IsNotExist err from is a contingency; the directory // Getting an os.IsNotExist err from is a contingency; the directory
// may not exist yet, in which case, setup should run. // 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) err = fmt.Errorf("unknown storage medium %q", ed.medium)
} }
volume.SetVolumeOwnership(ed, fsGroup)
if err == nil { if err == nil {
volumeutil.SetReady(ed.getMetaDir()) volumeutil.SetReady(ed.getMetaDir())
} }

View File

@ -185,7 +185,7 @@ func doTestPlugin(t *testing.T, config pluginTestConfig) {
t.Errorf("Got unexpected path: %s", volPath) 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) t.Errorf("Expected success, got: %v", err)
} }

View File

@ -21,6 +21,7 @@ import (
"github.com/golang/glog" "github.com/golang/glog"
"k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/util/mount"
"k8s.io/kubernetes/pkg/volume"
) )
// Abstract interface to disk operations. // Abstract interface to disk operations.
@ -33,7 +34,7 @@ type diskManager interface {
} }
// utility to mount a disk based filesystem // 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) globalPDPath := manager.MakeGlobalPDName(*b.fcDisk)
// TODO: handle failed mounts here. // TODO: handle failed mounts here.
noMnt, err := mounter.IsLikelyNotMountPoint(volPath) 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) glog.Errorf("failed to bind mount:%s", globalPDPath)
return err return err
} }
if !b.readOnly {
volume.SetVolumeOwnership(&b, fsGroup)
}
return nil return nil
} }

View File

@ -170,19 +170,18 @@ var _ volume.Builder = &fcDiskBuilder{}
func (b *fcDiskBuilder) GetAttributes() volume.Attributes { func (b *fcDiskBuilder) GetAttributes() volume.Attributes {
return volume.Attributes{ return volume.Attributes{
ReadOnly: b.readOnly, ReadOnly: b.readOnly,
Managed: !b.readOnly, Managed: !b.readOnly,
SupportsOwnershipManagement: true, SupportsSELinux: true,
SupportsSELinux: true,
} }
} }
func (b *fcDiskBuilder) SetUp() error { func (b *fcDiskBuilder) SetUp(fsGroup *int64) error {
return b.SetUpAt(b.GetPath()) 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 // 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 { if err != nil {
glog.Errorf("fc: failed to setup") glog.Errorf("fc: failed to setup")
} }

View File

@ -120,7 +120,7 @@ func doTestPlugin(t *testing.T, spec *volume.Spec) {
t.Errorf("Got unexpected path: %s", path) 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) t.Errorf("Expected success, got: %v", err)
} }
if _, err := os.Stat(path); err != nil { if _, err := os.Stat(path); err != nil {

View File

@ -223,18 +223,17 @@ type flexVolumeBuilder struct {
} }
// SetUp creates new directory. // SetUp creates new directory.
func (f *flexVolumeBuilder) SetUp() error { func (f *flexVolumeBuilder) SetUp(fsGroup *int64) error {
return f.SetUpAt(f.GetPath()) return f.SetUpAt(f.GetPath(), fsGroup)
} }
// GetAttributes get the flex volume attributes. The attributes will be queried // GetAttributes get the flex volume attributes. The attributes will be queried
// using plugin callout after we finalize the callout syntax. // using plugin callout after we finalize the callout syntax.
func (f flexVolumeBuilder) GetAttributes() volume.Attributes { func (f flexVolumeBuilder) GetAttributes() volume.Attributes {
return volume.Attributes{ return volume.Attributes{
ReadOnly: f.readOnly, ReadOnly: f.readOnly,
Managed: false, Managed: false,
SupportsOwnershipManagement: false, SupportsSELinux: false,
SupportsSELinux: false,
} }
} }
@ -251,7 +250,7 @@ type flexVolumeManager interface {
} }
// SetUpAt creates new directory. // 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) notmnt, err := f.blockDeviceMounter.IsLikelyNotMountPoint(dir)
if err != nil && !os.IsNotExist(err) { if err != nil && !os.IsNotExist(err) {

View File

@ -238,7 +238,7 @@ func doTestPluginAttachDetach(t *testing.T, spec *volume.Spec) {
if path != "/tmp/fake/pods/poduid/volumes/kubernetes.io~fakeAttacher/vol1" { if path != "/tmp/fake/pods/poduid/volumes/kubernetes.io~fakeAttacher/vol1" {
t.Errorf("Got unexpected path: %s", path) 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) t.Errorf("Expected success, got: %v", err)
} }
if _, err := os.Stat(volumePath); err != nil { 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" { if path != "/tmp/fake/pods/poduid/volumes/kubernetes.io~fakeMounter/vol1" {
t.Errorf("Got unexpected path: %s", path) 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) t.Errorf("Expected success, got: %v", err)
} }
if _, err := os.Stat(volumePath); err != nil { if _, err := os.Stat(volumePath); err != nil {

View File

@ -117,18 +117,17 @@ type flockerBuilder struct {
func (b flockerBuilder) GetAttributes() volume.Attributes { func (b flockerBuilder) GetAttributes() volume.Attributes {
return volume.Attributes{ return volume.Attributes{
ReadOnly: b.readOnly, ReadOnly: b.readOnly,
Managed: false, Managed: false,
SupportsOwnershipManagement: false, SupportsSELinux: false,
SupportsSELinux: false,
} }
} }
func (b flockerBuilder) GetPath() string { func (b flockerBuilder) GetPath() string {
return b.flocker.path return b.flocker.path
} }
func (b flockerBuilder) SetUp() error { func (b flockerBuilder) SetUp(fsGroup *int64) error {
return b.SetUpAt(b.flocker.datasetName) return b.SetUpAt(b.flocker.datasetName, fsGroup)
} }
// newFlockerClient uses environment variables and pod attributes to return a // 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. need to update the Primary UUID for this volume.
5. Wait until the Primary UUID was updated or timeout. 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()) { if volumeutil.IsReady(b.getMetaDir()) {
return nil return nil
} }

View File

@ -211,6 +211,6 @@ func TestSetUpAtInternal(t *testing.T) {
b := flockerBuilder{flocker: &flocker{pod: pod, plugin: plug.(*flockerPlugin)}} b := flockerBuilder{flocker: &flocker{pod: pod, plugin: plug.(*flockerPlugin)}}
b.client = newMockFlockerClient("dataset-id", "primary-uid", mockPath) 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) assert.Equal(expectedPath, b.flocker.path)
} }

View File

@ -211,20 +211,19 @@ var _ volume.Builder = &gcePersistentDiskBuilder{}
func (b *gcePersistentDiskBuilder) GetAttributes() volume.Attributes { func (b *gcePersistentDiskBuilder) GetAttributes() volume.Attributes {
return volume.Attributes{ return volume.Attributes{
ReadOnly: b.readOnly, ReadOnly: b.readOnly,
Managed: !b.readOnly, Managed: !b.readOnly,
SupportsOwnershipManagement: true, SupportsSELinux: true,
SupportsSELinux: true,
} }
} }
// SetUp attaches the disk and bind mounts to the volume path. // SetUp attaches the disk and bind mounts to the volume path.
func (b *gcePersistentDiskBuilder) SetUp() error { func (b *gcePersistentDiskBuilder) SetUp(fsGroup *int64) error {
return b.SetUpAt(b.GetPath()) return b.SetUpAt(b.GetPath(), fsGroup)
} }
// SetUpAt attaches the disk and bind mounts to the volume path. // 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. // TODO: handle failed mounts here.
notMnt, err := b.mounter.IsLikelyNotMountPoint(dir) notMnt, err := b.mounter.IsLikelyNotMountPoint(dir)
glog.V(4).Infof("PersistentDisk set up: %s %v %v", dir, !notMnt, err) 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 return err
} }
if !b.readOnly {
volume.SetVolumeOwnership(b, fsGroup)
}
return nil return nil
} }

View File

@ -161,7 +161,7 @@ func TestPlugin(t *testing.T) {
t.Errorf("Got unexpected path: %s", path) 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) t.Errorf("Expected success, got: %v", err)
} }
if _, err := os.Stat(path); err != nil { if _, err := os.Stat(path); err != nil {

View File

@ -120,20 +120,19 @@ var _ volume.Builder = &gitRepoVolumeBuilder{}
func (b *gitRepoVolumeBuilder) GetAttributes() volume.Attributes { func (b *gitRepoVolumeBuilder) GetAttributes() volume.Attributes {
return volume.Attributes{ return volume.Attributes{
ReadOnly: false, ReadOnly: false,
Managed: true, Managed: true,
SupportsOwnershipManagement: false, SupportsSELinux: true, // xattr change should be okay, TODO: double check
SupportsSELinux: true, // xattr change should be okay, TODO: double check
} }
} }
// SetUp creates new directory and clones a git repo. // SetUp creates new directory and clones a git repo.
func (b *gitRepoVolumeBuilder) SetUp() error { func (b *gitRepoVolumeBuilder) SetUp(fsGroup *int64) error {
return b.SetUpAt(b.GetPath()) return b.SetUpAt(b.GetPath(), fsGroup)
} }
// SetUpAt creates new directory and clones a git repo. // 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()) { if volumeutil.IsReady(b.getMetaDir()) {
return nil return nil
} }
@ -143,7 +142,7 @@ func (b *gitRepoVolumeBuilder) SetUpAt(dir string) error {
if err != nil { if err != nil {
return err return err
} }
if err := wrapped.SetUpAt(dir); err != nil { if err := wrapped.SetUpAt(dir, fsGroup); err != nil {
return err return err
} }

View File

@ -351,7 +351,7 @@ func doTestSetUp(scenario struct {
g := builder.(*gitRepoVolumeBuilder) g := builder.(*gitRepoVolumeBuilder)
g.exec = &fake g.exec = &fake
g.SetUp() g.SetUp(nil)
if fake.CommandCalls != len(expecteds) { if fake.CommandCalls != len(expecteds) {
allErrs = append(allErrs, allErrs = append(allErrs,

View File

@ -158,19 +158,18 @@ var _ volume.Builder = &glusterfsBuilder{}
func (b *glusterfsBuilder) GetAttributes() volume.Attributes { func (b *glusterfsBuilder) GetAttributes() volume.Attributes {
return volume.Attributes{ return volume.Attributes{
ReadOnly: b.readOnly, ReadOnly: b.readOnly,
Managed: false, Managed: false,
SupportsOwnershipManagement: false, SupportsSELinux: false,
SupportsSELinux: false,
} }
} }
// SetUp attaches the disk and bind mounts to the volume path. // SetUp attaches the disk and bind mounts to the volume path.
func (b *glusterfsBuilder) SetUp() error { func (b *glusterfsBuilder) SetUp(fsGroup *int64) error {
return b.SetUpAt(b.GetPath()) 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) notMnt, err := b.mounter.IsLikelyNotMountPoint(dir)
glog.V(4).Infof("glusterfs: mount set up: %s %v %v", dir, !notMnt, err) glog.V(4).Infof("glusterfs: mount set up: %s %v %v", dir, !notMnt, err)
if err != nil && !os.IsNotExist(err) { if err != nil && !os.IsNotExist(err) {

View File

@ -104,7 +104,7 @@ func doTestPlugin(t *testing.T, spec *volume.Spec) {
if path != "/tmp/fake/pods/poduid/volumes/kubernetes.io~glusterfs/vol1" { if path != "/tmp/fake/pods/poduid/volumes/kubernetes.io~glusterfs/vol1" {
t.Errorf("Got unexpected path: %s", path) 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) t.Errorf("Expected success, got: %v", err)
} }
if _, err := os.Stat(volumePath); err != nil { if _, err := os.Stat(volumePath); err != nil {

View File

@ -178,20 +178,19 @@ var _ volume.Builder = &hostPathBuilder{}
func (b *hostPathBuilder) GetAttributes() volume.Attributes { func (b *hostPathBuilder) GetAttributes() volume.Attributes {
return volume.Attributes{ return volume.Attributes{
ReadOnly: b.readOnly, ReadOnly: b.readOnly,
Managed: false, Managed: false,
SupportsOwnershipManagement: false, SupportsSELinux: false,
SupportsSELinux: false,
} }
} }
// SetUp does nothing. // SetUp does nothing.
func (b *hostPathBuilder) SetUp() error { func (b *hostPathBuilder) SetUp(fsGroup *int64) error {
return nil return nil
} }
// SetUpAt does not make sense for host paths - probably programmer error. // 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") return fmt.Errorf("SetUpAt() does not make sense for host paths")
} }

View File

@ -210,7 +210,7 @@ func TestPlugin(t *testing.T) {
t.Errorf("Got unexpected path: %s", path) 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) t.Errorf("Expected success, got: %v", err)
} }

View File

@ -21,6 +21,7 @@ import (
"github.com/golang/glog" "github.com/golang/glog"
"k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/util/mount"
"k8s.io/kubernetes/pkg/volume"
) )
// Abstract interface to disk operations. // Abstract interface to disk operations.
@ -33,7 +34,7 @@ type diskManager interface {
} }
// utility to mount a disk based filesystem // 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) globalPDPath := manager.MakeGlobalPDName(*b.iscsiDisk)
// TODO: handle failed mounts here. // TODO: handle failed mounts here.
notMnt, err := mounter.IsLikelyNotMountPoint(volPath) 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) glog.Errorf("failed to bind mount:%s", globalPDPath)
return err return err
} }
if !b.readOnly {
volume.SetVolumeOwnership(&b, fsGroup)
}
return nil return nil
} }

View File

@ -168,20 +168,19 @@ var _ volume.Builder = &iscsiDiskBuilder{}
func (b *iscsiDiskBuilder) GetAttributes() volume.Attributes { func (b *iscsiDiskBuilder) GetAttributes() volume.Attributes {
return volume.Attributes{ return volume.Attributes{
ReadOnly: b.readOnly, ReadOnly: b.readOnly,
Managed: !b.readOnly, Managed: !b.readOnly,
SupportsOwnershipManagement: true, SupportsSELinux: true,
SupportsSELinux: true,
} }
} }
func (b *iscsiDiskBuilder) SetUp() error { func (b *iscsiDiskBuilder) SetUp(fsGroup *int64) error {
return b.SetUpAt(b.GetPath()) 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 // 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 { if err != nil {
glog.Errorf("iscsi: failed to setup") glog.Errorf("iscsi: failed to setup")
} }

View File

@ -120,7 +120,7 @@ func doTestPlugin(t *testing.T, spec *volume.Spec) {
t.Errorf("Got unexpected path: %s", path) 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) t.Errorf("Expected success, got: %v", err)
} }
if _, err := os.Stat(path); err != nil { if _, err := os.Stat(path); err != nil {

View File

@ -151,19 +151,18 @@ var _ volume.Builder = &nfsBuilder{}
func (b *nfsBuilder) GetAttributes() volume.Attributes { func (b *nfsBuilder) GetAttributes() volume.Attributes {
return volume.Attributes{ return volume.Attributes{
ReadOnly: b.readOnly, ReadOnly: b.readOnly,
Managed: false, Managed: false,
SupportsOwnershipManagement: false, SupportsSELinux: false,
SupportsSELinux: false,
} }
} }
// SetUp attaches the disk and bind mounts to the volume path. // SetUp attaches the disk and bind mounts to the volume path.
func (b *nfsBuilder) SetUp() error { func (b *nfsBuilder) SetUp(fsGroup *int64) error {
return b.SetUpAt(b.GetPath()) 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) notMnt, err := b.mounter.IsLikelyNotMountPoint(dir)
glog.V(4).Infof("NFS mount set up: %s %v %v", dir, !notMnt, err) glog.V(4).Infof("NFS mount set up: %s %v %v", dir, !notMnt, err)
if err != nil && !os.IsNotExist(err) { if err != nil && !os.IsNotExist(err) {

View File

@ -133,7 +133,7 @@ func doTestPlugin(t *testing.T, spec *volume.Spec) {
if path != "/tmp/fake/pods/poduid/volumes/kubernetes.io~nfs/vol1" { if path != "/tmp/fake/pods/poduid/volumes/kubernetes.io~nfs/vol1" {
t.Errorf("Got unexpected path: %s", path) 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) t.Errorf("Expected success, got: %v", err)
} }
if _, err := os.Stat(volumePath); err != nil { if _, err := os.Stat(volumePath); err != nil {

View File

@ -27,6 +27,7 @@ import (
"github.com/golang/glog" "github.com/golang/glog"
"k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/util/mount"
"k8s.io/kubernetes/pkg/volume"
) )
// Abstract interface to disk operations. // Abstract interface to disk operations.
@ -39,7 +40,7 @@ type diskManager interface {
} }
// utility to mount a disk based filesystem // 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) globalPDPath := manager.MakeGlobalPDName(*b.rbd)
// TODO: handle failed mounts here. // TODO: handle failed mounts here.
notMnt, err := mounter.IsLikelyNotMountPoint(volPath) 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) glog.Errorf("failed to bind mount:%s", globalPDPath)
return err return err
} }
if !b.ReadOnly {
volume.SetVolumeOwnership(&b, fsGroup)
}
return nil return nil
} }

View File

@ -196,20 +196,19 @@ var _ volume.Builder = &rbdBuilder{}
func (b *rbd) GetAttributes() volume.Attributes { func (b *rbd) GetAttributes() volume.Attributes {
return volume.Attributes{ return volume.Attributes{
ReadOnly: b.ReadOnly, ReadOnly: b.ReadOnly,
Managed: !b.ReadOnly, Managed: !b.ReadOnly,
SupportsOwnershipManagement: true, SupportsSELinux: true,
SupportsSELinux: true,
} }
} }
func (b *rbdBuilder) SetUp() error { func (b *rbdBuilder) SetUp(fsGroup *int64) error {
return b.SetUpAt(b.GetPath()) 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 // 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 { if err != nil {
glog.Errorf("rbd: failed to setup") glog.Errorf("rbd: failed to setup")
} }

View File

@ -87,7 +87,7 @@ func doTestPlugin(t *testing.T, spec *volume.Spec) {
t.Errorf("Got unexpected path: %s", path) 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) t.Errorf("Expected success, got: %v", err)
} }
if _, err := os.Stat(path); err != nil { if _, err := os.Stat(path); err != nil {

View File

@ -122,21 +122,20 @@ var _ volume.Builder = &secretVolumeBuilder{}
func (sv *secretVolume) GetAttributes() volume.Attributes { func (sv *secretVolume) GetAttributes() volume.Attributes {
return volume.Attributes{ return volume.Attributes{
ReadOnly: true, ReadOnly: true,
Managed: true, Managed: true,
SupportsOwnershipManagement: true, SupportsSELinux: true,
SupportsSELinux: true,
} }
} }
func (b *secretVolumeBuilder) SetUp() error { func (b *secretVolumeBuilder) SetUp(fsGroup *int64) error {
return b.SetUpAt(b.GetPath()) return b.SetUpAt(b.GetPath(), fsGroup)
} }
func (b *secretVolumeBuilder) getMetaDir() string { func (b *secretVolumeBuilder) getMetaDir() string {
return path.Join(b.plugin.host.GetPodPluginDir(b.podUID, strings.EscapeQualifiedNameForDisk(secretPluginName)), b.volName) 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) notMnt, err := b.mounter.IsLikelyNotMountPoint(dir)
// Getting an os.IsNotExist err from is a contingency; the directory // Getting an os.IsNotExist err from is a contingency; the directory
// may not exist yet, in which case, setup should run. // may not exist yet, in which case, setup should run.
@ -157,7 +156,7 @@ func (b *secretVolumeBuilder) SetUpAt(dir string) error {
if err != nil { if err != nil {
return err return err
} }
if err := wrapped.SetUpAt(dir); err != nil { if err := wrapped.SetUpAt(dir, fsGroup); err != nil {
return err return err
} }
@ -189,6 +188,8 @@ func (b *secretVolumeBuilder) SetUpAt(dir string) error {
} }
} }
volume.SetVolumeOwnership(b, fsGroup)
volumeutil.SetReady(b.getMetaDir()) volumeutil.SetReady(b.getMetaDir())
return nil return nil

View File

@ -98,7 +98,7 @@ func TestPlugin(t *testing.T) {
t.Errorf("Got unexpected path: %s", volumePath) t.Errorf("Got unexpected path: %s", volumePath)
} }
err = builder.SetUp() err = builder.SetUp(nil)
if err != nil { if err != nil {
t.Errorf("Failed to setup volume: %v", err) t.Errorf("Failed to setup volume: %v", err)
} }
@ -166,7 +166,7 @@ func TestPluginIdempotent(t *testing.T) {
} }
volumePath := builder.GetPath() volumePath := builder.GetPath()
err = builder.SetUp() err = builder.SetUp(nil)
if err != nil { if err != nil {
t.Errorf("Failed to setup volume: %v", err) t.Errorf("Failed to setup volume: %v", err)
} }
@ -224,7 +224,7 @@ func TestPluginReboot(t *testing.T) {
t.Errorf("Got unexpected path: %s", volumePath) t.Errorf("Got unexpected path: %s", volumePath)
} }
err = builder.SetUp() err = builder.SetUp(nil)
if err != nil { if err != nil {
t.Errorf("Failed to setup volume: %v", err) t.Errorf("Failed to setup volume: %v", err)
} }

View File

@ -189,18 +189,17 @@ type FakeVolume struct {
func (_ *FakeVolume) GetAttributes() Attributes { func (_ *FakeVolume) GetAttributes() Attributes {
return Attributes{ return Attributes{
ReadOnly: false, ReadOnly: false,
Managed: true, Managed: true,
SupportsOwnershipManagement: true, SupportsSELinux: true,
SupportsSELinux: true,
} }
} }
func (fv *FakeVolume) SetUp() error { func (fv *FakeVolume) SetUp(fsGroup *int64) error {
return fv.SetUpAt(fv.GetPath()) 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) return os.MkdirAll(dir, 0750)
} }

View File

@ -20,6 +20,7 @@ import (
"io/ioutil" "io/ioutil"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/resource" "k8s.io/kubernetes/pkg/api/resource"
"os" "os"
"path" "path"
) )
@ -59,24 +60,28 @@ type Metrics struct {
// Attributes represents the attributes of this builder. // Attributes represents the attributes of this builder.
type Attributes struct { type Attributes struct {
ReadOnly bool ReadOnly bool
Managed bool Managed bool
SupportsOwnershipManagement bool SupportsSELinux bool
SupportsSELinux bool
} }
// Builder interface provides methods to set up/mount the volume. // Builder interface provides methods to set up/mount the volume.
type Builder interface { type Builder interface {
// Uses Interface to provide the path for Docker binds. // Uses Interface to provide the path for Docker binds.
Volume Volume
// SetUp prepares and mounts/unpacks the volume to a self-determined // SetUp prepares and mounts/unpacks the volume to a
// directory path. This may be called more than once, so // 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. // implementations must be idempotent.
SetUp() error SetUp(fsGroup *int64) error
// SetUpAt prepares and mounts/unpacks the volume to the specified // SetUpAt prepares and mounts/unpacks the volume to the
// directory path, which may or may not exist yet. This may be called // specified directory path, which may or may not exist yet.
// more than once, so implementations must be idempotent. // The mount point and its content should be owned by
SetUpAt(dir string) error // '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 returns the attributes of the builder.
GetAttributes() Attributes GetAttributes() Attributes
} }

View File

@ -1,7 +1,7 @@
// +build linux // +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"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with 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. limitations under the License.
*/ */
package kubelet package volume
import ( import (
"os" "k8s.io/kubernetes/pkg/util/chmod"
"k8s.io/kubernetes/pkg/util/chown"
"path/filepath" "path/filepath"
"syscall" "syscall"
"github.com/golang/glog" "github.com/golang/glog"
"k8s.io/kubernetes/pkg/api" "os"
"k8s.io/kubernetes/pkg/volume"
) )
// Bitmasks to OR with current ownership of volumes that allow ownership management by the Kubelet
const ( const (
rwMask = os.FileMode(0660) rwMask = os.FileMode(0660)
roMask = os.FileMode(0440) roMask = os.FileMode(0440)
) )
// manageVolumeOwnership modifies the given volume to be owned by fsGroup. // SetVolumeOwnership modifies the given volume to be owned by
func (kl *Kubelet) manageVolumeOwnership(pod *api.Pod, volSpec *volume.Spec, builder volume.Builder, fsGroup int64) error { // 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 { return filepath.Walk(builder.GetPath(), func(path string, info os.FileInfo, err error) error {
if err != nil { if err != nil {
return err return err
@ -47,11 +55,11 @@ func (kl *Kubelet) manageVolumeOwnership(pod *api.Pod, volSpec *volume.Spec, bui
} }
if stat == nil { 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 return nil
} }
err = kl.chownRunner.Chown(path, int(stat.Uid), int(fsGroup)) err = chownRunner.Chown(path, int(stat.Uid), int(*fsGroup))
if err != nil { if err != nil {
glog.Errorf("Chown failed on %v: %v", path, err) 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 mask = roMask
} }
err = kl.chmodRunner.Chmod(path, info.Mode()|mask|os.ModeSetgid) err = chmodRunner.Chmod(path, info.Mode()|mask|os.ModeSetgid)
if err != nil { if err != nil {
glog.Errorf("Chmod failed on %v: %v", path, err) glog.Errorf("Chmod failed on %v: %v", path, err)
} }

View File

@ -1,7 +1,7 @@
// +build !linux // +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"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with 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. limitations under the License.
*/ */
package kubelet package volume
import ( func SetVolumeOwnership(builder Builder, fsGroup *int64) error {
"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 {
return nil return nil
} }