Commit 34ef93aa authored by Jing Xu's avatar Jing Xu

Add mounterPath to mounter interface

In order to be able to use new mounter library, this PR adds the mounterPath flag to kubelet which passes the flag to the mount interface. If flag is empty, mount uses default mount path.
parent a9e53ded
...@@ -67,7 +67,7 @@ func (realConntracker) SetTCPEstablishedTimeout(seconds int) error { ...@@ -67,7 +67,7 @@ func (realConntracker) SetTCPEstablishedTimeout(seconds int) error {
func isSysFSWritable() (bool, error) { func isSysFSWritable() (bool, error) {
const permWritable = "rw" const permWritable = "rw"
const sysfsDevice = "sysfs" const sysfsDevice = "sysfs"
m := mount.New() m := mount.New("" /* default mount path */)
mountPoints, err := m.List() mountPoints, err := m.List()
if err != nil { if err != nil {
glog.Errorf("failed to list mount points: %v", err) glog.Errorf("failed to list mount points: %v", err)
......
...@@ -174,6 +174,7 @@ func (s *KubeletServer) AddFlags(fs *pflag.FlagSet) { ...@@ -174,6 +174,7 @@ func (s *KubeletServer) AddFlags(fs *pflag.FlagSet) {
fs.StringVar(&s.LockFilePath, "lock-file", s.LockFilePath, "<Warning: Alpha feature> The path to file for kubelet to use as a lock file.") fs.StringVar(&s.LockFilePath, "lock-file", s.LockFilePath, "<Warning: Alpha feature> The path to file for kubelet to use as a lock file.")
fs.BoolVar(&s.ExitOnLockContention, "exit-on-lock-contention", s.ExitOnLockContention, "Whether kubelet should exit upon lock-file contention.") fs.BoolVar(&s.ExitOnLockContention, "exit-on-lock-contention", s.ExitOnLockContention, "Whether kubelet should exit upon lock-file contention.")
fs.StringVar(&s.RktPath, "rkt-path", s.RktPath, "Path of rkt binary. Leave empty to use the first rkt in $PATH. Only used if --container-runtime='rkt'.") fs.StringVar(&s.RktPath, "rkt-path", s.RktPath, "Path of rkt binary. Leave empty to use the first rkt in $PATH. Only used if --container-runtime='rkt'.")
fs.StringVar(&s.MounterPath, "mounter-path", s.MounterPath, "Path of mounter binary. Leave empty to use the default mount.")
fs.StringVar(&s.RktAPIEndpoint, "rkt-api-endpoint", s.RktAPIEndpoint, "The endpoint of the rkt API service to communicate with. Only used if --container-runtime='rkt'.") fs.StringVar(&s.RktAPIEndpoint, "rkt-api-endpoint", s.RktAPIEndpoint, "The endpoint of the rkt API service to communicate with. Only used if --container-runtime='rkt'.")
fs.StringVar(&s.RktStage1Image, "rkt-stage1-image", s.RktStage1Image, "image to use as stage1. Local paths and http/https URLs are supported. If empty, the 'stage1.aci' in the same directory as '--rkt-path' will be used.") fs.StringVar(&s.RktStage1Image, "rkt-stage1-image", s.RktStage1Image, "image to use as stage1. Local paths and http/https URLs are supported. If empty, the 'stage1.aci' in the same directory as '--rkt-path' will be used.")
fs.MarkDeprecated("rkt-stage1-image", "Will be removed in a future version. The default stage1 image will be specified by the rkt configurations, see https://github.com/coreos/rkt/blob/master/Documentation/configuration.md for more details.") fs.MarkDeprecated("rkt-stage1-image", "Will be removed in a future version. The default stage1 image will be specified by the rkt configurations, see https://github.com/coreos/rkt/blob/master/Documentation/configuration.md for more details.")
......
...@@ -117,7 +117,7 @@ func UnsecuredKubeletDeps(s *options.KubeletServer) (*kubelet.KubeletDeps, error ...@@ -117,7 +117,7 @@ func UnsecuredKubeletDeps(s *options.KubeletServer) (*kubelet.KubeletDeps, error
return nil, err return nil, err
} }
mounter := mount.New() mounter := mount.New(s.MounterPath)
var writer kubeio.Writer = &kubeio.StdWriter{} var writer kubeio.Writer = &kubeio.StdWriter{}
if s.Containerized { if s.Containerized {
glog.V(2).Info("Running kubelet in containerized mode (experimental)") glog.V(2).Info("Running kubelet in containerized mode (experimental)")
......
...@@ -371,6 +371,7 @@ minion-max-log-age ...@@ -371,6 +371,7 @@ minion-max-log-age
minion-max-log-backups minion-max-log-backups
minion-max-log-size minion-max-log-size
minion-path-override minion-path-override
mounter-path
namespace-sync-period namespace-sync-period
network-plugin network-plugin
network-plugin-dir network-plugin-dir
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -313,6 +313,8 @@ type KubeletConfiguration struct { ...@@ -313,6 +313,8 @@ type KubeletConfiguration struct {
// $PATH. // $PATH.
// +optional // +optional
RktPath string `json:"rktPath,omitempty"` RktPath string `json:"rktPath,omitempty"`
// mounterPath is the path of mounter binary. Leave empty to use the default mount path
MounterPath string `json:"mounterPath,omitempty"`
// rktApiEndpoint is the endpoint of the rkt API service to communicate with. // rktApiEndpoint is the endpoint of the rkt API service to communicate with.
// +optional // +optional
RktAPIEndpoint string `json:"rktAPIEndpoint,omitempty"` RktAPIEndpoint string `json:"rktAPIEndpoint,omitempty"`
......
...@@ -360,6 +360,9 @@ type KubeletConfiguration struct { ...@@ -360,6 +360,9 @@ type KubeletConfiguration struct {
// rktPath is the path of rkt binary. Leave empty to use the first rkt in // rktPath is the path of rkt binary. Leave empty to use the first rkt in
// $PATH. // $PATH.
RktPath string `json:"rktPath"` RktPath string `json:"rktPath"`
// mounterPath is the path to mounter binary. If not set, kubelet will attempt to use mount
// binary that is available via $PATH,
MounterPath string `json:"mounterPath,omitempty"`
// rktApiEndpoint is the endpoint of the rkt API service to communicate with. // rktApiEndpoint is the endpoint of the rkt API service to communicate with.
RktAPIEndpoint string `json:"rktAPIEndpoint"` RktAPIEndpoint string `json:"rktAPIEndpoint"`
// rktStage1Image is the image to use as stage1. Local paths and // rktStage1Image is the image to use as stage1. Local paths and
......
...@@ -251,6 +251,7 @@ func autoConvert_v1alpha1_KubeletConfiguration_To_componentconfig_KubeletConfigu ...@@ -251,6 +251,7 @@ func autoConvert_v1alpha1_KubeletConfiguration_To_componentconfig_KubeletConfigu
out.RemoteImageEndpoint = in.RemoteImageEndpoint out.RemoteImageEndpoint = in.RemoteImageEndpoint
out.RuntimeRequestTimeout = in.RuntimeRequestTimeout out.RuntimeRequestTimeout = in.RuntimeRequestTimeout
out.RktPath = in.RktPath out.RktPath = in.RktPath
out.MounterPath = in.MounterPath
out.RktAPIEndpoint = in.RktAPIEndpoint out.RktAPIEndpoint = in.RktAPIEndpoint
out.RktStage1Image = in.RktStage1Image out.RktStage1Image = in.RktStage1Image
if err := api.Convert_Pointer_string_To_string(&in.LockFilePath, &out.LockFilePath, s); err != nil { if err := api.Convert_Pointer_string_To_string(&in.LockFilePath, &out.LockFilePath, s); err != nil {
...@@ -429,6 +430,7 @@ func autoConvert_componentconfig_KubeletConfiguration_To_v1alpha1_KubeletConfigu ...@@ -429,6 +430,7 @@ func autoConvert_componentconfig_KubeletConfiguration_To_v1alpha1_KubeletConfigu
out.RemoteImageEndpoint = in.RemoteImageEndpoint out.RemoteImageEndpoint = in.RemoteImageEndpoint
out.RuntimeRequestTimeout = in.RuntimeRequestTimeout out.RuntimeRequestTimeout = in.RuntimeRequestTimeout
out.RktPath = in.RktPath out.RktPath = in.RktPath
out.MounterPath = in.MounterPath
out.RktAPIEndpoint = in.RktAPIEndpoint out.RktAPIEndpoint = in.RktAPIEndpoint
out.RktStage1Image = in.RktStage1Image out.RktStage1Image = in.RktStage1Image
if err := api.Convert_string_To_Pointer_string(&in.LockFilePath, &out.LockFilePath, s); err != nil { if err := api.Convert_string_To_Pointer_string(&in.LockFilePath, &out.LockFilePath, s); err != nil {
......
...@@ -263,6 +263,7 @@ func DeepCopy_v1alpha1_KubeletConfiguration(in interface{}, out interface{}, c * ...@@ -263,6 +263,7 @@ func DeepCopy_v1alpha1_KubeletConfiguration(in interface{}, out interface{}, c *
out.RemoteImageEndpoint = in.RemoteImageEndpoint out.RemoteImageEndpoint = in.RemoteImageEndpoint
out.RuntimeRequestTimeout = in.RuntimeRequestTimeout out.RuntimeRequestTimeout = in.RuntimeRequestTimeout
out.RktPath = in.RktPath out.RktPath = in.RktPath
out.MounterPath = in.MounterPath
out.RktAPIEndpoint = in.RktAPIEndpoint out.RktAPIEndpoint = in.RktAPIEndpoint
out.RktStage1Image = in.RktStage1Image out.RktStage1Image = in.RktStage1Image
if in.LockFilePath != nil { if in.LockFilePath != nil {
......
...@@ -277,6 +277,7 @@ func DeepCopy_componentconfig_KubeletConfiguration(in interface{}, out interface ...@@ -277,6 +277,7 @@ func DeepCopy_componentconfig_KubeletConfiguration(in interface{}, out interface
out.RemoteImageEndpoint = in.RemoteImageEndpoint out.RemoteImageEndpoint = in.RemoteImageEndpoint
out.RuntimeRequestTimeout = in.RuntimeRequestTimeout out.RuntimeRequestTimeout = in.RuntimeRequestTimeout
out.RktPath = in.RktPath out.RktPath = in.RktPath
out.MounterPath = in.MounterPath
out.RktAPIEndpoint = in.RktAPIEndpoint out.RktAPIEndpoint = in.RktAPIEndpoint
out.RktStage1Image = in.RktStage1Image out.RktStage1Image = in.RktStage1Image
out.LockFilePath = in.LockFilePath out.LockFilePath = in.LockFilePath
......
...@@ -95,7 +95,7 @@ func getMetadataFromConfigDrive() (*Metadata, error) { ...@@ -95,7 +95,7 @@ func getMetadataFromConfigDrive() (*Metadata, error) {
glog.V(4).Infof("Attempting to mount configdrive %s on %s", dev, mntdir) glog.V(4).Infof("Attempting to mount configdrive %s on %s", dev, mntdir)
mounter := mount.New() mounter := mount.New("" /* default mount path */)
err = mounter.Mount(dev, mntdir, "iso9660", []string{"ro"}) err = mounter.Mount(dev, mntdir, "iso9660", []string{"ro"})
if err != nil { if err != nil {
err = mounter.Mount(dev, mntdir, "vfat", []string{"ro"}) err = mounter.Mount(dev, mntdir, "vfat", []string{"ro"})
......
...@@ -2568,6 +2568,13 @@ var OpenAPIDefinitions *common.OpenAPIDefinitions = &common.OpenAPIDefinitions{ ...@@ -2568,6 +2568,13 @@ var OpenAPIDefinitions *common.OpenAPIDefinitions = &common.OpenAPIDefinitions{
Format: "", Format: "",
}, },
}, },
"mounterPath": {
SchemaProps: spec.SchemaProps{
Description: "mounterPath is the path of mounter binary. Leave empty to use the default mount path",
Type: []string{"string"},
Format: "",
},
},
"rktAPIEndpoint": { "rktAPIEndpoint": {
SchemaProps: spec.SchemaProps{ SchemaProps: spec.SchemaProps{
Description: "rktApiEndpoint is the endpoint of the rkt API service to communicate with.", Description: "rktApiEndpoint is the endpoint of the rkt API service to communicate with.",
...@@ -2882,7 +2889,7 @@ var OpenAPIDefinitions *common.OpenAPIDefinitions = &common.OpenAPIDefinitions{ ...@@ -2882,7 +2889,7 @@ var OpenAPIDefinitions *common.OpenAPIDefinitions = &common.OpenAPIDefinitions{
}, },
}, },
}, },
Required: []string{"TypeMeta", "podManifestPath", "syncFrequency", "fileCheckFrequency", "httpCheckFrequency", "manifestURL", "manifestURLHeader", "enableServer", "address", "port", "readOnlyPort", "tlsCertFile", "tlsPrivateKeyFile", "certDirectory", "hostnameOverride", "podInfraContainerImage", "dockerEndpoint", "rootDirectory", "seccompProfileRoot", "allowPrivileged", "hostNetworkSources", "hostPIDSources", "hostIPCSources", "registryPullQPS", "registryBurst", "eventRecordQPS", "eventBurst", "enableDebuggingHandlers", "minimumGCAge", "maxPerPodContainerCount", "maxContainerCount", "cAdvisorPort", "healthzPort", "healthzBindAddress", "oomScoreAdj", "registerNode", "clusterDomain", "masterServiceNamespace", "clusterDNS", "streamingConnectionIdleTimeout", "nodeStatusUpdateFrequency", "imageMinimumGCAge", "imageGCHighThresholdPercent", "imageGCLowThresholdPercent", "lowDiskSpaceThresholdMB", "volumeStatsAggPeriod", "networkPluginName", "networkPluginMTU", "networkPluginDir", "cniConfDir", "cniBinDir", "volumePluginDir", "containerRuntime", "remoteRuntimeEndpoint", "remoteImageEndpoint", "lockFilePath", "exitOnLockContention", "hairpinMode", "babysitDaemons", "maxPods", "nvidiaGPUs", "dockerExecHandlerName", "podCIDR", "resolvConf", "cpuCFSQuota", "containerized", "maxOpenFiles", "reconcileCIDR", "registerSchedulable", "contentType", "kubeAPIQPS", "kubeAPIBurst", "serializeImagePulls", "nodeLabels", "nonMasqueradeCIDR", "enableCustomMetrics", "podsPerCore", "enableControllerAttachDetach", "systemReserved", "kubeReserved", "protectKernelDefaults", "makeIPTablesUtilChains", "iptablesMasqueradeBit", "iptablesDropBit"}, Required: []string{"TypeMeta", "podManifestPath", "syncFrequency", "fileCheckFrequency", "httpCheckFrequency", "manifestURL", "manifestURLHeader", "enableServer", "address", "port", "readOnlyPort", "tlsCertFile", "tlsPrivateKeyFile", "certDirectory", "hostnameOverride", "podInfraContainerImage", "dockerEndpoint", "rootDirectory", "seccompProfileRoot", "allowPrivileged", "hostNetworkSources", "hostPIDSources", "hostIPCSources", "registryPullQPS", "registryBurst", "eventRecordQPS", "eventBurst", "enableDebuggingHandlers", "minimumGCAge", "maxPerPodContainerCount", "maxContainerCount", "cAdvisorPort", "healthzPort", "healthzBindAddress", "oomScoreAdj", "registerNode", "clusterDomain", "masterServiceNamespace", "clusterDNS", "streamingConnectionIdleTimeout", "nodeStatusUpdateFrequency", "imageMinimumGCAge", "imageGCHighThresholdPercent", "imageGCLowThresholdPercent", "lowDiskSpaceThresholdMB", "volumeStatsAggPeriod", "networkPluginName", "networkPluginMTU", "networkPluginDir", "cniConfDir", "cniBinDir", "volumePluginDir", "containerRuntime", "remoteRuntimeEndpoint", "remoteImageEndpoint", "mounterPath", "lockFilePath", "exitOnLockContention", "hairpinMode", "babysitDaemons", "maxPods", "nvidiaGPUs", "dockerExecHandlerName", "podCIDR", "resolvConf", "cpuCFSQuota", "containerized", "maxOpenFiles", "reconcileCIDR", "registerSchedulable", "contentType", "kubeAPIQPS", "kubeAPIBurst", "serializeImagePulls", "nodeLabels", "nonMasqueradeCIDR", "enableCustomMetrics", "podsPerCore", "enableControllerAttachDetach", "systemReserved", "kubeReserved", "protectKernelDefaults", "makeIPTablesUtilChains", "iptablesMasqueradeBit", "iptablesDropBit"},
}, },
}, },
Dependencies: []string{ Dependencies: []string{
...@@ -14167,6 +14174,13 @@ var OpenAPIDefinitions *common.OpenAPIDefinitions = &common.OpenAPIDefinitions{ ...@@ -14167,6 +14174,13 @@ var OpenAPIDefinitions *common.OpenAPIDefinitions = &common.OpenAPIDefinitions{
Format: "", Format: "",
}, },
}, },
"mounterPath": {
SchemaProps: spec.SchemaProps{
Description: "mounterPath is the path to mounter binary. If not set, kubelet will attempt to use mount binary that is available via $PATH,",
Type: []string{"string"},
Format: "",
},
},
"rktAPIEndpoint": { "rktAPIEndpoint": {
SchemaProps: spec.SchemaProps{ SchemaProps: spec.SchemaProps{
Description: "rktApiEndpoint is the endpoint of the rkt API service to communicate with.", Description: "rktApiEndpoint is the endpoint of the rkt API service to communicate with.",
...@@ -14481,7 +14495,7 @@ var OpenAPIDefinitions *common.OpenAPIDefinitions = &common.OpenAPIDefinitions{ ...@@ -14481,7 +14495,7 @@ var OpenAPIDefinitions *common.OpenAPIDefinitions = &common.OpenAPIDefinitions{
}, },
}, },
}, },
Required: []string{"TypeMeta", "podManifestPath", "syncFrequency", "fileCheckFrequency", "httpCheckFrequency", "manifestURL", "manifestURLHeader", "enableServer", "address", "port", "readOnlyPort", "tlsCertFile", "tlsPrivateKeyFile", "certDirectory", "hostnameOverride", "podInfraContainerImage", "dockerEndpoint", "rootDirectory", "seccompProfileRoot", "allowPrivileged", "hostNetworkSources", "hostPIDSources", "hostIPCSources", "registryPullQPS", "registryBurst", "eventRecordQPS", "eventBurst", "enableDebuggingHandlers", "minimumGCAge", "maxPerPodContainerCount", "maxContainerCount", "cAdvisorPort", "healthzPort", "healthzBindAddress", "oomScoreAdj", "registerNode", "clusterDomain", "masterServiceNamespace", "clusterDNS", "streamingConnectionIdleTimeout", "nodeStatusUpdateFrequency", "imageMinimumGCAge", "imageGCHighThresholdPercent", "imageGCLowThresholdPercent", "lowDiskSpaceThresholdMB", "volumeStatsAggPeriod", "networkPluginName", "networkPluginDir", "cniConfDir", "cniBinDir", "networkPluginMTU", "volumePluginDir", "cloudProvider", "cloudConfigFile", "kubeletCgroups", "runtimeCgroups", "systemCgroups", "cgroupRoot", "containerRuntime", "remoteRuntimeEndpoint", "remoteImageEndpoint", "runtimeRequestTimeout", "rktPath", "rktAPIEndpoint", "rktStage1Image", "lockFilePath", "exitOnLockContention", "hairpinMode", "babysitDaemons", "maxPods", "nvidiaGPUs", "dockerExecHandlerName", "podCIDR", "resolvConf", "cpuCFSQuota", "containerized", "maxOpenFiles", "reconcileCIDR", "registerSchedulable", "contentType", "kubeAPIQPS", "kubeAPIBurst", "serializeImagePulls", "outOfDiskTransitionFrequency", "nodeIP", "nodeLabels", "nonMasqueradeCIDR", "enableCustomMetrics", "evictionHard", "evictionSoft", "evictionSoftGracePeriod", "evictionPressureTransitionPeriod", "evictionMaxPodGracePeriod", "evictionMinimumReclaim", "podsPerCore", "enableControllerAttachDetach", "systemReserved", "kubeReserved", "protectKernelDefaults", "makeIPTablesUtilChains", "iptablesMasqueradeBit", "iptablesDropBit"}, Required: []string{"TypeMeta", "podManifestPath", "syncFrequency", "fileCheckFrequency", "httpCheckFrequency", "manifestURL", "manifestURLHeader", "enableServer", "address", "port", "readOnlyPort", "tlsCertFile", "tlsPrivateKeyFile", "certDirectory", "hostnameOverride", "podInfraContainerImage", "dockerEndpoint", "rootDirectory", "seccompProfileRoot", "allowPrivileged", "hostNetworkSources", "hostPIDSources", "hostIPCSources", "registryPullQPS", "registryBurst", "eventRecordQPS", "eventBurst", "enableDebuggingHandlers", "minimumGCAge", "maxPerPodContainerCount", "maxContainerCount", "cAdvisorPort", "healthzPort", "healthzBindAddress", "oomScoreAdj", "registerNode", "clusterDomain", "masterServiceNamespace", "clusterDNS", "streamingConnectionIdleTimeout", "nodeStatusUpdateFrequency", "imageMinimumGCAge", "imageGCHighThresholdPercent", "imageGCLowThresholdPercent", "lowDiskSpaceThresholdMB", "volumeStatsAggPeriod", "networkPluginName", "networkPluginDir", "cniConfDir", "cniBinDir", "networkPluginMTU", "volumePluginDir", "cloudProvider", "cloudConfigFile", "kubeletCgroups", "runtimeCgroups", "systemCgroups", "cgroupRoot", "containerRuntime", "remoteRuntimeEndpoint", "remoteImageEndpoint", "runtimeRequestTimeout", "rktPath", "mounterPath", "rktAPIEndpoint", "rktStage1Image", "lockFilePath", "exitOnLockContention", "hairpinMode", "babysitDaemons", "maxPods", "nvidiaGPUs", "dockerExecHandlerName", "podCIDR", "resolvConf", "cpuCFSQuota", "containerized", "maxOpenFiles", "reconcileCIDR", "registerSchedulable", "contentType", "kubeAPIQPS", "kubeAPIBurst", "serializeImagePulls", "outOfDiskTransitionFrequency", "nodeIP", "nodeLabels", "nonMasqueradeCIDR", "enableCustomMetrics", "evictionHard", "evictionSoft", "evictionSoftGracePeriod", "evictionPressureTransitionPeriod", "evictionMaxPodGracePeriod", "evictionMinimumReclaim", "podsPerCore", "enableControllerAttachDetach", "systemReserved", "kubeReserved", "protectKernelDefaults", "makeIPTablesUtilChains", "iptablesMasqueradeBit", "iptablesDropBit"},
}, },
}, },
Dependencies: []string{ Dependencies: []string{
......
...@@ -72,7 +72,7 @@ func NewHollowKubelet( ...@@ -72,7 +72,7 @@ func NewHollowKubelet(
TLSOptions: nil, TLSOptions: nil,
OOMAdjuster: oom.NewFakeOOMAdjuster(), OOMAdjuster: oom.NewFakeOOMAdjuster(),
Writer: &kubeio.StdWriter{}, Writer: &kubeio.StdWriter{},
Mounter: mount.New(), Mounter: mount.New("" /* default mount path */),
} }
return &HollowKubelet{ return &HollowKubelet{
......
...@@ -28,6 +28,11 @@ import ( ...@@ -28,6 +28,11 @@ import (
"k8s.io/kubernetes/pkg/util/exec" "k8s.io/kubernetes/pkg/util/exec"
) )
const (
// Default mount command if mounter path is not specified
mount = "mount"
)
type Interface interface { type Interface interface {
// Mount mounts source to target as fstype with given options. // Mount mounts source to target as fstype with given options.
Mount(source string, target string, fstype string, options []string) error Mount(source string, target string, fstype string, options []string) error
...@@ -89,8 +94,14 @@ func (mounter *SafeFormatAndMount) FormatAndMount(source string, target string, ...@@ -89,8 +94,14 @@ func (mounter *SafeFormatAndMount) FormatAndMount(source string, target string,
} }
// New returns a mount.Interface for the current system. // New returns a mount.Interface for the current system.
func New() Interface { func New(mounterPath string) Interface {
return &Mounter{} // If mounter-path flag is not set, use default mount path
if len(mounterPath) == 0 {
mounterPath = mount
}
return &Mounter{
mounterPath: mounterPath,
}
} }
// GetMountRefs finds all other references to the device referenced // GetMountRefs finds all other references to the device referenced
......
...@@ -52,7 +52,9 @@ const ( ...@@ -52,7 +52,9 @@ const (
// Mounter provides the default implementation of mount.Interface // Mounter provides the default implementation of mount.Interface
// for the linux platform. This implementation assumes that the // for the linux platform. This implementation assumes that the
// kubelet is running in the host's root mount namespace. // kubelet is running in the host's root mount namespace.
type Mounter struct{} type Mounter struct {
mounterPath string
}
// Mount mounts source to target as fstype with given options. 'source' and 'fstype' must // Mount mounts source to target as fstype with given options. 'source' and 'fstype' must
// be an emtpy string in case it's not required, e.g. for remount, or for auto filesystem // be an emtpy string in case it's not required, e.g. for remount, or for auto filesystem
...@@ -61,15 +63,14 @@ type Mounter struct{} ...@@ -61,15 +63,14 @@ type Mounter struct{}
// required, call Mount with an empty string list or nil. // required, call Mount with an empty string list or nil.
func (mounter *Mounter) Mount(source string, target string, fstype string, options []string) error { func (mounter *Mounter) Mount(source string, target string, fstype string, options []string) error {
bind, bindRemountOpts := isBind(options) bind, bindRemountOpts := isBind(options)
if bind { if bind {
err := doMount(source, target, fstype, []string{"bind"}) err := doMount(mounter.mounterPath, source, target, fstype, []string{"bind"})
if err != nil { if err != nil {
return err return err
} }
return doMount(source, target, fstype, bindRemountOpts) return doMount(mounter.mounterPath, source, target, fstype, bindRemountOpts)
} else { } else {
return doMount(source, target, fstype, options) return doMount(mounter.mounterPath, source, target, fstype, options)
} }
} }
...@@ -99,10 +100,11 @@ func isBind(options []string) (bool, []string) { ...@@ -99,10 +100,11 @@ func isBind(options []string) (bool, []string) {
} }
// doMount runs the mount command. // doMount runs the mount command.
func doMount(source string, target string, fstype string, options []string) error { func doMount(mountCmd string, source string, target string, fstype string, options []string) error {
glog.V(5).Infof("Mounting %s %s %s %v", source, target, fstype, options) glog.V(5).Infof("Mounting %s %s %s %v", source, target, fstype, options)
mountArgs := makeMountArgs(source, target, fstype, options) mountArgs := makeMountArgs(source, target, fstype, options)
command := exec.Command("mount", mountArgs...)
command := exec.Command(mountCmd, mountArgs...)
output, err := command.CombinedOutput() output, err := command.CombinedOutput()
if err != nil { if err != nil {
glog.Errorf("Mount failed: %v\nMounting arguments: %s %s %s %v\nOutput: %s\n", err, source, target, fstype, options, string(output)) glog.Errorf("Mount failed: %v\nMounting arguments: %s %s %s %v\nOutput: %s\n", err, source, target, fstype, options, string(output))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment