mirror of https://github.com/k3s-io/k3s
Add a mounter that uses google's safe_format_and_mount.
parent
6ba8b7dfb2
commit
ac21ac24fa
|
@ -28,7 +28,9 @@ import (
|
|||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/cloudprovider"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/cloudprovider/gce"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/util/exec"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/util/mount"
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
// 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
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/util/exec"
|
||||
)
|
||||
|
||||
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 FlagReadOnly = syscall.MS_RDONLY
|
||||
|
||||
type mounter struct{}
|
||||
type Mounter struct{}
|
||||
|
||||
// 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)
|
||||
return syscall.Mount(source, target, fstype, flags, data)
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// How many times to retry for a consistent read of /proc/mounts.
|
||||
const maxListTries = 3
|
||||
|
||||
func (mounter *mounter) List() ([]MountPoint, error) {
|
||||
func (*Mounter) List() ([]MountPoint, error) {
|
||||
hash1, err := readProcMounts(nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -37,7 +37,7 @@ type Interface interface {
|
|||
|
||||
// New returns a mount.Interface for the current system.
|
||||
func New() Interface {
|
||||
return &mounter{}
|
||||
return &Mounter{}
|
||||
}
|
||||
|
||||
// This represents a single line in /proc/mounts or /etc/fstab.
|
||||
|
|
Loading…
Reference in New Issue