Merge pull request #19502 from swagiaal/internalize-ownership

Auto commit by PR queue bot
pull/6/head
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"
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,

View File

@ -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

View File

@ -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
}

View File

@ -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

View File

@ -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
}

View File

@ -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 {

View File

@ -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) {

View File

@ -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 {

View File

@ -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
}

View File

@ -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 {

View File

@ -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
}

View File

@ -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)
}

View File

@ -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())
}

View File

@ -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)
}

View File

@ -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
}

View File

@ -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")
}

View File

@ -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 {

View File

@ -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) {

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" {
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 {

View File

@ -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
}

View File

@ -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)
}

View File

@ -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
}

View File

@ -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 {

View File

@ -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
}

View File

@ -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,

View File

@ -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) {

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" {
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 {

View File

@ -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")
}

View File

@ -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)
}

View File

@ -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
}

View File

@ -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")
}

View File

@ -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 {

View File

@ -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) {

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" {
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 {

View File

@ -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
}

View File

@ -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")
}

View File

@ -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 {

View File

@ -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

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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
}

View File

@ -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)
}

View File

@ -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
}