mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-27 13:37:30 +00:00
Add a mounter that uses google's safe_format_and_mount.
This commit is contained in:
parent
6ba8b7dfb2
commit
ac21ac24fa
@ -28,7 +28,9 @@ import (
|
|||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/cloudprovider"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/cloudprovider"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/cloudprovider/gce"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/cloudprovider/gce"
|
||||||
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/util/exec"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/util/mount"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/util/mount"
|
||||||
|
"github.com/golang/glog"
|
||||||
)
|
)
|
||||||
|
|
||||||
const partitionRegex = "[a-z][a-z]*(?P<partition>[0-9][0-9]*)?"
|
const partitionRegex = "[a-z][a-z]*(?P<partition>[0-9][0-9]*)?"
|
||||||
@ -139,3 +141,30 @@ func (util *GCEDiskUtil) DetachDisk(pd *gcePersistentDisk, devicePath string) er
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// safe_format_and_mount is a utility script on GCE VMs that probes a persistent disk, and if
|
||||||
|
// necessary formats it before mounting it.
|
||||||
|
// This eliminates the necesisty to format a PD before it is used with a Pod on GCE.
|
||||||
|
// TODO: port this script into Go and use it for all Linux platforms
|
||||||
|
type gceSafeFormatAndMount struct {
|
||||||
|
mount.Mounter
|
||||||
|
runner exec.Interface
|
||||||
|
}
|
||||||
|
|
||||||
|
// uses /usr/share/google/safe_format_and_mount to optionally mount, and format a disk
|
||||||
|
func (mounter *gceSafeFormatAndMount) Mount(source string, target string, fstype string, flags uintptr, data string) error {
|
||||||
|
args := []string{}
|
||||||
|
// ext4 is the default for safe_format_and_mount
|
||||||
|
if len(fstype) > 0 && fstype != "ext4" {
|
||||||
|
args = append(args, "-m", fmt.Sprintf("mkfs.%s", fstype))
|
||||||
|
}
|
||||||
|
args = append(args, source, target)
|
||||||
|
// TODO: Accept other options here?
|
||||||
|
glog.V(5).Infof("exec-ing: /usr/share/google/safe_format_and_mount %v", args)
|
||||||
|
cmd := mounter.runner.Command("/usr/share/google/safe_format_and_mount", args...)
|
||||||
|
dataOut, err := cmd.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
glog.V(5).Infof("error running /usr/share/google/safe_format_and_mount\n%s", string(dataOut))
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
@ -17,7 +17,10 @@ limitations under the License.
|
|||||||
package gce_pd
|
package gce_pd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/util/exec"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGetDeviceName(t *testing.T) {
|
func TestGetDeviceName(t *testing.T) {
|
||||||
@ -53,3 +56,63 @@ func TestGetDeviceName(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSafeFormatAndMount(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
fstype string
|
||||||
|
expectedArgs []string
|
||||||
|
err error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
fstype: "ext4",
|
||||||
|
expectedArgs: []string{"/dev/foo", "/mnt/bar"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fstype: "vfat",
|
||||||
|
expectedArgs: []string{"-m", "mkfs.vfat", "/dev/foo", "/mnt/bar"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
err: fmt.Errorf("test error"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, test := range tests {
|
||||||
|
|
||||||
|
var cmdOut string
|
||||||
|
var argsOut []string
|
||||||
|
fake := exec.FakeExec{
|
||||||
|
CommandScript: []exec.FakeCommandAction{
|
||||||
|
func(cmd string, args ...string) exec.Cmd {
|
||||||
|
cmdOut = cmd
|
||||||
|
argsOut = args
|
||||||
|
fake := exec.FakeCmd{
|
||||||
|
CombinedOutputScript: []exec.FakeCombinedOutputAction{
|
||||||
|
func() ([]byte, error) { return []byte{}, test.err },
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return exec.InitFakeCmd(&fake, cmd, args...)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
mounter := gceSafeFormatAndMount{
|
||||||
|
runner: &fake,
|
||||||
|
}
|
||||||
|
|
||||||
|
err := mounter.Mount("/dev/foo", "/mnt/bar", test.fstype, 0, "")
|
||||||
|
if test.err == nil && err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if test.err != nil {
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("unexpected non-error")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if cmdOut != "/usr/share/google/safe_format_and_mount" {
|
||||||
|
t.Errorf("unexpected command: %s", cmdOut)
|
||||||
|
}
|
||||||
|
if len(argsOut) != len(test.expectedArgs) {
|
||||||
|
t.Errorf("unexpected args: %v, expected: %v", argsOut, test.expectedArgs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -34,23 +34,23 @@ import (
|
|||||||
const FlagBind = syscall.MS_BIND
|
const FlagBind = syscall.MS_BIND
|
||||||
const FlagReadOnly = syscall.MS_RDONLY
|
const FlagReadOnly = syscall.MS_RDONLY
|
||||||
|
|
||||||
type mounter struct{}
|
type Mounter struct{}
|
||||||
|
|
||||||
// Wraps syscall.Mount()
|
// Wraps syscall.Mount()
|
||||||
func (mounter *mounter) Mount(source string, target string, fstype string, flags uintptr, data string) error {
|
func (mounter *Mounter) Mount(source string, target string, fstype string, flags uintptr, data string) error {
|
||||||
glog.V(5).Infof("Mounting %s %s %s %d %s", source, target, fstype, flags, data)
|
glog.V(5).Infof("Mounting %s %s %s %d %s", source, target, fstype, flags, data)
|
||||||
return syscall.Mount(source, target, fstype, flags, data)
|
return syscall.Mount(source, target, fstype, flags, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wraps syscall.Unmount()
|
// Wraps syscall.Unmount()
|
||||||
func (mounter *mounter) Unmount(target string, flags int) error {
|
func (mounter *Mounter) Unmount(target string, flags int) error {
|
||||||
return syscall.Unmount(target, flags)
|
return syscall.Unmount(target, flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
// How many times to retry for a consistent read of /proc/mounts.
|
// How many times to retry for a consistent read of /proc/mounts.
|
||||||
const maxListTries = 3
|
const maxListTries = 3
|
||||||
|
|
||||||
func (mounter *mounter) List() ([]MountPoint, error) {
|
func (*Mounter) List() ([]MountPoint, error) {
|
||||||
hash1, err := readProcMounts(nil)
|
hash1, err := readProcMounts(nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -37,7 +37,7 @@ type Interface interface {
|
|||||||
|
|
||||||
// New returns a mount.Interface for the current system.
|
// New returns a mount.Interface for the current system.
|
||||||
func New() Interface {
|
func New() Interface {
|
||||||
return &mounter{}
|
return &Mounter{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This represents a single line in /proc/mounts or /etc/fstab.
|
// This represents a single line in /proc/mounts or /etc/fstab.
|
||||||
|
Loading…
Reference in New Issue
Block a user