mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-27 05:27:21 +00:00
Merge pull request #8530 from swagiaal/add-fomat-and-mount
Support formatting and mounting GCE PD without 'safe_format_and_mount'
This commit is contained in:
commit
a5fe33b8a3
@ -18,7 +18,12 @@ limitations under the License.
|
|||||||
// an alternate platform, we will need to abstract further.
|
// an alternate platform, we will need to abstract further.
|
||||||
package mount
|
package mount
|
||||||
|
|
||||||
import "github.com/golang/glog"
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/golang/glog"
|
||||||
|
"k8s.io/kubernetes/pkg/util/exec"
|
||||||
|
)
|
||||||
|
|
||||||
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.
|
||||||
@ -44,6 +49,69 @@ type MountPoint struct {
|
|||||||
Pass int
|
Pass int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SafeFormatAndMount probes a device to see if it is formatted. If
|
||||||
|
// so it mounts it otherwise it formats it and mounts it
|
||||||
|
type SafeFormatAndMount struct {
|
||||||
|
Interface
|
||||||
|
Runner exec.Interface
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mount mounts the given disk. If the disk is not formatted and the disk is not being mounted as read only
|
||||||
|
// it will format the disk first then mount it.
|
||||||
|
func (mounter *SafeFormatAndMount) Mount(source string, target string, fstype string, options []string) error {
|
||||||
|
// Don't attempt to format if mounting as readonly. Go straight to mounting.
|
||||||
|
for _, option := range options {
|
||||||
|
if option == "ro" {
|
||||||
|
return mounter.Interface.Mount(source, target, fstype, options)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mounter.formatAndMount(source, target, fstype, options)
|
||||||
|
}
|
||||||
|
|
||||||
|
// formatAndMount uses unix utils to format and mount the given disk
|
||||||
|
func (mounter *SafeFormatAndMount) formatAndMount(source string, target string, fstype string, options []string) error {
|
||||||
|
options = append(options, "defaults")
|
||||||
|
|
||||||
|
// Try to mount the disk
|
||||||
|
err := mounter.Interface.Mount(source, target, fstype, options)
|
||||||
|
if err != nil {
|
||||||
|
// It is possible that this disk is not formatted. Double check using 'file'
|
||||||
|
notFormatted, err := mounter.diskLooksUnformatted(source)
|
||||||
|
if err == nil && notFormatted {
|
||||||
|
// Disk is unformatted so format it.
|
||||||
|
// Use 'ext4' as the default
|
||||||
|
if len(fstype) == 0 {
|
||||||
|
fstype = "ext4"
|
||||||
|
}
|
||||||
|
args := []string{"-E", "lazy_itable_init=0,lazy_journal_init=0", "-F", source}
|
||||||
|
cmd := mounter.Runner.Command("mkfs."+fstype, args...)
|
||||||
|
_, err := cmd.CombinedOutput()
|
||||||
|
if err == nil {
|
||||||
|
// the disk has been formatted sucessfully try to mount it again.
|
||||||
|
return mounter.Interface.Mount(source, target, fstype, options)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// diskLooksUnformatted uses 'file' to see if the given disk is unformated
|
||||||
|
func (mounter *SafeFormatAndMount) diskLooksUnformatted(disk string) (bool, error) {
|
||||||
|
args := []string{"-L", "--special-files", disk}
|
||||||
|
cmd := mounter.Runner.Command("file", args...)
|
||||||
|
dataOut, err := cmd.CombinedOutput()
|
||||||
|
|
||||||
|
// TODO (#13212): check if this disk has partitions and return false, and
|
||||||
|
// an error if so.
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return !strings.Contains(string(dataOut), "filesystem"), nil
|
||||||
|
}
|
||||||
|
|
||||||
// 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{}
|
||||||
|
172
pkg/util/mount/safe_format_and_mount_test.go
Normal file
172
pkg/util/mount/safe_format_and_mount_test.go
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2014 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.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package mount
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"k8s.io/kubernetes/pkg/util/exec"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ErrorMounter struct {
|
||||||
|
*FakeMounter
|
||||||
|
errIndex int
|
||||||
|
err []error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mounter *ErrorMounter) Mount(source string, target string, fstype string, options []string) error {
|
||||||
|
i := mounter.errIndex
|
||||||
|
mounter.errIndex++
|
||||||
|
if mounter.err != nil && mounter.err[i] != nil {
|
||||||
|
return mounter.err[i]
|
||||||
|
}
|
||||||
|
return mounter.FakeMounter.Mount(source, target, fstype, options)
|
||||||
|
}
|
||||||
|
|
||||||
|
type ExecArgs struct {
|
||||||
|
command string
|
||||||
|
args []string
|
||||||
|
output string
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSafeFormatAndMount(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
fstype string
|
||||||
|
mountOptions []string
|
||||||
|
execScripts []ExecArgs
|
||||||
|
mountErrs []error
|
||||||
|
expectedError error
|
||||||
|
}{
|
||||||
|
{ // Test a read only mount
|
||||||
|
fstype: "ext4",
|
||||||
|
mountOptions: []string{"ro"},
|
||||||
|
},
|
||||||
|
{ // Test a normal mount
|
||||||
|
fstype: "ext4",
|
||||||
|
},
|
||||||
|
|
||||||
|
{ // Test that 'file' is called and fails
|
||||||
|
fstype: "ext4",
|
||||||
|
mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'")},
|
||||||
|
execScripts: []ExecArgs{
|
||||||
|
{"file", []string{"-L", "--special-files", "/dev/foo"}, "ext4 filesystem", nil},
|
||||||
|
},
|
||||||
|
expectedError: fmt.Errorf("unknown filesystem type '(null)'"),
|
||||||
|
},
|
||||||
|
{ // Test that 'file' is called and confirms unformatted disk, format fails
|
||||||
|
fstype: "ext4",
|
||||||
|
mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'")},
|
||||||
|
execScripts: []ExecArgs{
|
||||||
|
{"file", []string{"-L", "--special-files", "/dev/foo"}, "data", nil},
|
||||||
|
{"mkfs.ext4", []string{"-E", "lazy_itable_init=0,lazy_journal_init=0", "-F", "/dev/foo"}, "", fmt.Errorf("formatting failed")},
|
||||||
|
},
|
||||||
|
expectedError: fmt.Errorf("formatting failed"),
|
||||||
|
},
|
||||||
|
{ // Test that 'file' is called and confirms unformatted disk, format passes, second mount fails
|
||||||
|
fstype: "ext4",
|
||||||
|
mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'"), fmt.Errorf("Still cannot mount")},
|
||||||
|
execScripts: []ExecArgs{
|
||||||
|
{"file", []string{"-L", "--special-files", "/dev/foo"}, "data", nil},
|
||||||
|
{"mkfs.ext4", []string{"-E", "lazy_itable_init=0,lazy_journal_init=0", "-F", "/dev/foo"}, "", nil},
|
||||||
|
},
|
||||||
|
expectedError: fmt.Errorf("Still cannot mount"),
|
||||||
|
},
|
||||||
|
{ // Test that 'file' is called and confirms unformatted disk, format passes, second mount passes
|
||||||
|
fstype: "ext4",
|
||||||
|
mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'"), nil},
|
||||||
|
execScripts: []ExecArgs{
|
||||||
|
{"file", []string{"-L", "--special-files", "/dev/foo"}, "data", nil},
|
||||||
|
{"mkfs.ext4", []string{"-E", "lazy_itable_init=0,lazy_journal_init=0", "-F", "/dev/foo"}, "", nil},
|
||||||
|
},
|
||||||
|
expectedError: nil,
|
||||||
|
},
|
||||||
|
{ // Test that 'file' is called and confirms unformatted disk, format passes, second mount passes with ext3
|
||||||
|
fstype: "ext3",
|
||||||
|
mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'"), nil},
|
||||||
|
execScripts: []ExecArgs{
|
||||||
|
{"file", []string{"-L", "--special-files", "/dev/foo"}, "data", nil},
|
||||||
|
{"mkfs.ext3", []string{"-E", "lazy_itable_init=0,lazy_journal_init=0", "-F", "/dev/foo"}, "", nil},
|
||||||
|
},
|
||||||
|
expectedError: nil,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
commandScripts := []exec.FakeCommandAction{}
|
||||||
|
for _, expected := range test.execScripts {
|
||||||
|
ecmd := expected.command
|
||||||
|
eargs := expected.args
|
||||||
|
output := expected.output
|
||||||
|
err := expected.err
|
||||||
|
commandScript := func(cmd string, args ...string) exec.Cmd {
|
||||||
|
if cmd != ecmd {
|
||||||
|
t.Errorf("Unexpected command %s. Expecting %s", cmd, ecmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
for j := range args {
|
||||||
|
if args[j] != eargs[j] {
|
||||||
|
t.Errorf("Unexpected args %v. Expecting %v", args, eargs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fake := exec.FakeCmd{
|
||||||
|
CombinedOutputScript: []exec.FakeCombinedOutputAction{
|
||||||
|
func() ([]byte, error) { return []byte(output), err },
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return exec.InitFakeCmd(&fake, cmd, args...)
|
||||||
|
}
|
||||||
|
commandScripts = append(commandScripts, commandScript)
|
||||||
|
}
|
||||||
|
|
||||||
|
fake := exec.FakeExec{
|
||||||
|
CommandScript: commandScripts,
|
||||||
|
}
|
||||||
|
|
||||||
|
fakeMounter := ErrorMounter{&FakeMounter{}, 0, test.mountErrs}
|
||||||
|
mounter := SafeFormatAndMount{
|
||||||
|
Interface: &fakeMounter,
|
||||||
|
Runner: &fake,
|
||||||
|
}
|
||||||
|
|
||||||
|
device := "/dev/foo"
|
||||||
|
dest := "/mnt/bar"
|
||||||
|
err := mounter.Mount(device, dest, test.fstype, test.mountOptions)
|
||||||
|
if test.expectedError == nil {
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected non-error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that something was mounted on the directory
|
||||||
|
isNotMountPoint, err := fakeMounter.IsLikelyNotMountPoint(dest)
|
||||||
|
if err != nil || isNotMountPoint {
|
||||||
|
t.Errorf("the directory was not mounted")
|
||||||
|
}
|
||||||
|
|
||||||
|
//check that the correct device was mounted
|
||||||
|
mountedDevice, _, err := GetDeviceNameFromMount(fakeMounter.FakeMounter, dest)
|
||||||
|
if err != nil || mountedDevice != device {
|
||||||
|
t.Errorf("the correct device was not mounted")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err == nil || test.expectedError.Error() != err.Error() {
|
||||||
|
t.Errorf("unexpected error: %v. Expecting %v", err, test.expectedError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -106,7 +106,7 @@ func (plugin *awsElasticBlockStorePlugin) newBuilderInternal(spec *volume.Spec,
|
|||||||
fsType: fsType,
|
fsType: fsType,
|
||||||
partition: partition,
|
partition: partition,
|
||||||
readOnly: readOnly,
|
readOnly: readOnly,
|
||||||
diskMounter: &awsSafeFormatAndMount{mounter, exec.New()}}, nil
|
diskMounter: &mount.SafeFormatAndMount{mounter, exec.New()}}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (plugin *awsElasticBlockStorePlugin) NewCleaner(volName string, podUID types.UID, mounter mount.Interface) (volume.Cleaner, error) {
|
func (plugin *awsElasticBlockStorePlugin) NewCleaner(volName string, podUID types.UID, mounter mount.Interface) (volume.Cleaner, error) {
|
||||||
|
@ -18,13 +18,10 @@ package aws_ebs
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"k8s.io/kubernetes/pkg/util/exec"
|
|
||||||
"k8s.io/kubernetes/pkg/util/mount"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type AWSDiskUtil struct{}
|
type AWSDiskUtil struct{}
|
||||||
@ -110,37 +107,3 @@ func (util *AWSDiskUtil) DetachDisk(c *awsElasticBlockStoreCleaner) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// safe_format_and_mount is a utility script on AWS VMs that probes a persistent disk, and if
|
|
||||||
// necessary formats it before mounting it.
|
|
||||||
// This eliminates the necessity to format a PD before it is used with a Pod on AWS.
|
|
||||||
// TODO: port this script into Go and use it for all Linux platforms
|
|
||||||
type awsSafeFormatAndMount struct {
|
|
||||||
mount.Interface
|
|
||||||
runner exec.Interface
|
|
||||||
}
|
|
||||||
|
|
||||||
// uses /usr/share/google/safe_format_and_mount to optionally mount, and format a disk
|
|
||||||
func (mounter *awsSafeFormatAndMount) Mount(source string, target string, fstype string, options []string) error {
|
|
||||||
// Don't attempt to format if mounting as readonly. Go straight to mounting.
|
|
||||||
// Don't attempt to format if mounting as readonly. Go straight to mounting.
|
|
||||||
for _, option := range options {
|
|
||||||
if option == "ro" {
|
|
||||||
return mounter.Interface.Mount(source, target, fstype, options)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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, options...)
|
|
||||||
args = append(args, source, target)
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
@ -1,84 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2014 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.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package aws_ebs
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/util/exec"
|
|
||||||
)
|
|
||||||
|
|
||||||
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 := awsSafeFormatAndMount{
|
|
||||||
runner: &fake,
|
|
||||||
}
|
|
||||||
|
|
||||||
err := mounter.Mount("/dev/foo", "/mnt/bar", test.fstype, nil)
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -103,7 +103,7 @@ func (plugin *gcePersistentDiskPlugin) newBuilderInternal(spec *volume.Spec, pod
|
|||||||
},
|
},
|
||||||
fsType: fsType,
|
fsType: fsType,
|
||||||
readOnly: readOnly,
|
readOnly: readOnly,
|
||||||
diskMounter: &gceSafeFormatAndMount{mounter, exec.New()}}, nil
|
diskMounter: &mount.SafeFormatAndMount{mounter, exec.New()}}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (plugin *gcePersistentDiskPlugin) NewCleaner(volName string, podUID types.UID, mounter mount.Interface) (volume.Cleaner, error) {
|
func (plugin *gcePersistentDiskPlugin) NewCleaner(volName string, podUID types.UID, mounter mount.Interface) (volume.Cleaner, error) {
|
||||||
|
@ -29,7 +29,6 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce"
|
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce"
|
||||||
"k8s.io/kubernetes/pkg/util"
|
"k8s.io/kubernetes/pkg/util"
|
||||||
"k8s.io/kubernetes/pkg/util/exec"
|
"k8s.io/kubernetes/pkg/util/exec"
|
||||||
"k8s.io/kubernetes/pkg/util/mount"
|
|
||||||
"k8s.io/kubernetes/pkg/util/operationmanager"
|
"k8s.io/kubernetes/pkg/util/operationmanager"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -332,36 +331,3 @@ func udevadmChangeToDrive(drivePath string) error {
|
|||||||
}
|
}
|
||||||
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.Interface
|
|
||||||
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, options []string) error {
|
|
||||||
// Don't attempt to format if mounting as readonly. Go straight to mounting.
|
|
||||||
for _, option := range options {
|
|
||||||
if option == "ro" {
|
|
||||||
return mounter.Interface.Mount(source, target, fstype, options)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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, options...)
|
|
||||||
args = append(args, source, target)
|
|
||||||
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.Errorf("error running /usr/share/google/safe_format_and_mount\n%s", string(dataOut))
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
@ -1,84 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2014 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.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package gce_pd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/util/exec"
|
|
||||||
)
|
|
||||||
|
|
||||||
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, nil)
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user