mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-13 13:55:41 +00:00
Run fsck before formatting disk
Signed-off-by: Sami Wagiaalla <swagiaal@redhat.com>
This commit is contained in:
parent
9e896e3416
commit
10688f1a11
@ -30,6 +30,7 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
|
utilExec "k8s.io/kubernetes/pkg/util/exec"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -240,13 +241,31 @@ func readProcMountsFrom(file io.Reader, out *[]MountPoint) (uint32, error) {
|
|||||||
func (mounter *SafeFormatAndMount) formatAndMount(source string, target string, fstype string, options []string) error {
|
func (mounter *SafeFormatAndMount) formatAndMount(source string, target string, fstype string, options []string) error {
|
||||||
options = append(options, "defaults")
|
options = append(options, "defaults")
|
||||||
|
|
||||||
|
// Run fsck on the disk to fix repairable issues
|
||||||
|
args := []string{"-a", source}
|
||||||
|
cmd := mounter.Runner.Command("fsck", args...)
|
||||||
|
out, err := cmd.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
ee, isExitError := err.(utilExec.ExitError)
|
||||||
|
switch {
|
||||||
|
case err == utilExec.ErrExecutableNotFound:
|
||||||
|
glog.Warningf("'fsck' not found on system; continuing mount without running 'fsck'.")
|
||||||
|
case isExitError && ee.ExitStatus() == 1:
|
||||||
|
glog.Infof("Device %s has errors which were corrected by fsck.", source)
|
||||||
|
case isExitError && ee.ExitStatus() == 4:
|
||||||
|
return fmt.Errorf("'fsck' found errors on device %s but could not correct them: %s.", source, string(out))
|
||||||
|
case isExitError && ee.ExitStatus() > 4:
|
||||||
|
glog.Infof("`fsck` error %s", string(out))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Try to mount the disk
|
// Try to mount the disk
|
||||||
err := mounter.Interface.Mount(source, target, fstype, options)
|
err = mounter.Interface.Mount(source, target, fstype, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// It is possible that this disk is not formatted. Double check using diskLooksUnformatted
|
// It is possible that this disk is not formatted. Double check using diskLooksUnformatted
|
||||||
notFormatted, err := mounter.diskLooksUnformatted(source)
|
notFormatted, err := mounter.diskLooksUnformatted(source)
|
||||||
if err == nil && notFormatted {
|
if err == nil && notFormatted {
|
||||||
args := []string{source}
|
args = []string{source}
|
||||||
// Disk is unformatted so format it.
|
// Disk is unformatted so format it.
|
||||||
// Use 'ext4' as the default
|
// Use 'ext4' as the default
|
||||||
if len(fstype) == 0 {
|
if len(fstype) == 0 {
|
||||||
|
@ -47,69 +47,107 @@ type ExecArgs struct {
|
|||||||
|
|
||||||
func TestSafeFormatAndMount(t *testing.T) {
|
func TestSafeFormatAndMount(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
|
description string
|
||||||
fstype string
|
fstype string
|
||||||
mountOptions []string
|
mountOptions []string
|
||||||
execScripts []ExecArgs
|
execScripts []ExecArgs
|
||||||
mountErrs []error
|
mountErrs []error
|
||||||
expectedError error
|
expectedError error
|
||||||
}{
|
}{
|
||||||
{ // Test a read only mount
|
{
|
||||||
|
description: "Test a read only mount",
|
||||||
fstype: "ext4",
|
fstype: "ext4",
|
||||||
mountOptions: []string{"ro"},
|
mountOptions: []string{"ro"},
|
||||||
},
|
},
|
||||||
{ // Test a normal mount
|
{
|
||||||
fstype: "ext4",
|
description: "Test a normal mount",
|
||||||
},
|
fstype: "ext4",
|
||||||
|
|
||||||
{ // Test that 'lsblk' is called and fails
|
|
||||||
fstype: "ext4",
|
|
||||||
mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'")},
|
|
||||||
execScripts: []ExecArgs{
|
execScripts: []ExecArgs{
|
||||||
|
{"fsck", []string{"-a", "/dev/foo"}, "", nil},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "Test 'fsck' fails with exit status 4",
|
||||||
|
fstype: "ext4",
|
||||||
|
execScripts: []ExecArgs{
|
||||||
|
{"fsck", []string{"-a", "/dev/foo"}, "", &exec.FakeExitError{Status: 4}},
|
||||||
|
},
|
||||||
|
expectedError: fmt.Errorf("'fsck' found errors on device /dev/foo but could not correct them: ."),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "Test 'fsck' fails with exit status 1 (errors found and corrected)",
|
||||||
|
fstype: "ext4",
|
||||||
|
execScripts: []ExecArgs{
|
||||||
|
{"fsck", []string{"-a", "/dev/foo"}, "", &exec.FakeExitError{Status: 1}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "Test 'fsck' fails with exit status other than 1 and 4 (likely unformatted device)",
|
||||||
|
fstype: "ext4",
|
||||||
|
execScripts: []ExecArgs{
|
||||||
|
{"fsck", []string{"-a", "/dev/foo"}, "", &exec.FakeExitError{Status: 8}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "Test that 'lsblk' is called and fails",
|
||||||
|
fstype: "ext4",
|
||||||
|
mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'")},
|
||||||
|
execScripts: []ExecArgs{
|
||||||
|
{"fsck", []string{"-a", "/dev/foo"}, "", nil},
|
||||||
{"lsblk", []string{"-nd", "-o", "FSTYPE", "/dev/foo"}, "ext4", nil},
|
{"lsblk", []string{"-nd", "-o", "FSTYPE", "/dev/foo"}, "ext4", nil},
|
||||||
},
|
},
|
||||||
expectedError: fmt.Errorf("unknown filesystem type '(null)'"),
|
expectedError: fmt.Errorf("unknown filesystem type '(null)'"),
|
||||||
},
|
},
|
||||||
{ // Test that 'lsblk' is called and confirms unformatted disk, format fails
|
{
|
||||||
fstype: "ext4",
|
description: "Test that 'lsblk' is called and confirms unformatted disk, format fails",
|
||||||
mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'")},
|
fstype: "ext4",
|
||||||
|
mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'")},
|
||||||
execScripts: []ExecArgs{
|
execScripts: []ExecArgs{
|
||||||
|
{"fsck", []string{"-a", "/dev/foo"}, "", nil},
|
||||||
{"lsblk", []string{"-nd", "-o", "FSTYPE", "/dev/foo"}, "", nil},
|
{"lsblk", []string{"-nd", "-o", "FSTYPE", "/dev/foo"}, "", nil},
|
||||||
{"mkfs.ext4", []string{"-E", "lazy_itable_init=0,lazy_journal_init=0", "-F", "/dev/foo"}, "", fmt.Errorf("formatting failed")},
|
{"mkfs.ext4", []string{"-E", "lazy_itable_init=0,lazy_journal_init=0", "-F", "/dev/foo"}, "", fmt.Errorf("formatting failed")},
|
||||||
},
|
},
|
||||||
expectedError: fmt.Errorf("formatting failed"),
|
expectedError: fmt.Errorf("formatting failed"),
|
||||||
},
|
},
|
||||||
{ // Test that 'lsblk' is called and confirms unformatted disk, format passes, second mount fails
|
{
|
||||||
fstype: "ext4",
|
description: "Test that 'lsblk' is called and confirms unformatted disk, format passes, second mount fails",
|
||||||
mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'"), fmt.Errorf("Still cannot mount")},
|
fstype: "ext4",
|
||||||
|
mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'"), fmt.Errorf("Still cannot mount")},
|
||||||
execScripts: []ExecArgs{
|
execScripts: []ExecArgs{
|
||||||
|
{"fsck", []string{"-a", "/dev/foo"}, "", nil},
|
||||||
{"lsblk", []string{"-nd", "-o", "FSTYPE", "/dev/foo"}, "", nil},
|
{"lsblk", []string{"-nd", "-o", "FSTYPE", "/dev/foo"}, "", nil},
|
||||||
{"mkfs.ext4", []string{"-E", "lazy_itable_init=0,lazy_journal_init=0", "-F", "/dev/foo"}, "", nil},
|
{"mkfs.ext4", []string{"-E", "lazy_itable_init=0,lazy_journal_init=0", "-F", "/dev/foo"}, "", nil},
|
||||||
},
|
},
|
||||||
expectedError: fmt.Errorf("Still cannot mount"),
|
expectedError: fmt.Errorf("Still cannot mount"),
|
||||||
},
|
},
|
||||||
{ // Test that 'lsblk' is called and confirms unformatted disk, format passes, second mount passes
|
{
|
||||||
fstype: "ext4",
|
description: "Test that 'lsblk' is called and confirms unformatted disk, format passes, second mount passes",
|
||||||
mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'"), nil},
|
fstype: "ext4",
|
||||||
|
mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'"), nil},
|
||||||
execScripts: []ExecArgs{
|
execScripts: []ExecArgs{
|
||||||
|
{"fsck", []string{"-a", "/dev/foo"}, "", nil},
|
||||||
{"lsblk", []string{"-nd", "-o", "FSTYPE", "/dev/foo"}, "", nil},
|
{"lsblk", []string{"-nd", "-o", "FSTYPE", "/dev/foo"}, "", nil},
|
||||||
{"mkfs.ext4", []string{"-E", "lazy_itable_init=0,lazy_journal_init=0", "-F", "/dev/foo"}, "", nil},
|
{"mkfs.ext4", []string{"-E", "lazy_itable_init=0,lazy_journal_init=0", "-F", "/dev/foo"}, "", nil},
|
||||||
},
|
},
|
||||||
expectedError: nil,
|
expectedError: nil,
|
||||||
},
|
},
|
||||||
{ // Test that 'lsblk' is called and confirms unformatted disk, format passes, second mount passes with ext3
|
{
|
||||||
fstype: "ext3",
|
description: "Test that 'lsblk' is called and confirms unformatted disk, format passes, second mount passes with ext3",
|
||||||
mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'"), nil},
|
fstype: "ext3",
|
||||||
|
mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'"), nil},
|
||||||
execScripts: []ExecArgs{
|
execScripts: []ExecArgs{
|
||||||
|
{"fsck", []string{"-a", "/dev/foo"}, "", nil},
|
||||||
{"lsblk", []string{"-nd", "-o", "FSTYPE", "/dev/foo"}, "", nil},
|
{"lsblk", []string{"-nd", "-o", "FSTYPE", "/dev/foo"}, "", nil},
|
||||||
{"mkfs.ext3", []string{"-E", "lazy_itable_init=0,lazy_journal_init=0", "-F", "/dev/foo"}, "", nil},
|
{"mkfs.ext3", []string{"-E", "lazy_itable_init=0,lazy_journal_init=0", "-F", "/dev/foo"}, "", nil},
|
||||||
},
|
},
|
||||||
expectedError: nil,
|
expectedError: nil,
|
||||||
},
|
},
|
||||||
{ // Test that 'lsblk' is called and confirms unformatted disk, format passes, second mount passes
|
{
|
||||||
// test that none ext4 fs does not get called with ext4 options.
|
description: "test that none ext4 fs does not get called with ext4 options.",
|
||||||
fstype: "xfs",
|
fstype: "xfs",
|
||||||
mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'"), nil},
|
mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'"), nil},
|
||||||
execScripts: []ExecArgs{
|
execScripts: []ExecArgs{
|
||||||
|
{"fsck", []string{"-a", "/dev/foo"}, "", nil},
|
||||||
{"lsblk", []string{"-nd", "-o", "FSTYPE", "/dev/foo"}, "", nil},
|
{"lsblk", []string{"-nd", "-o", "FSTYPE", "/dev/foo"}, "", nil},
|
||||||
{"mkfs.xfs", []string{"/dev/foo"}, "", nil},
|
{"mkfs.xfs", []string{"/dev/foo"}, "", nil},
|
||||||
},
|
},
|
||||||
@ -159,23 +197,23 @@ func TestSafeFormatAndMount(t *testing.T) {
|
|||||||
err := mounter.FormatAndMount(device, dest, test.fstype, test.mountOptions)
|
err := mounter.FormatAndMount(device, dest, test.fstype, test.mountOptions)
|
||||||
if test.expectedError == nil {
|
if test.expectedError == nil {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unexpected non-error: %v", err)
|
t.Errorf("test \"%s\" unexpected non-error: %v", test.description, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that something was mounted on the directory
|
// Check that something was mounted on the directory
|
||||||
isNotMountPoint, err := fakeMounter.IsLikelyNotMountPoint(dest)
|
isNotMountPoint, err := fakeMounter.IsLikelyNotMountPoint(dest)
|
||||||
if err != nil || isNotMountPoint {
|
if err != nil || isNotMountPoint {
|
||||||
t.Errorf("the directory was not mounted")
|
t.Errorf("test \"%s\" the directory was not mounted", test.description)
|
||||||
}
|
}
|
||||||
|
|
||||||
//check that the correct device was mounted
|
//check that the correct device was mounted
|
||||||
mountedDevice, _, err := GetDeviceNameFromMount(fakeMounter.FakeMounter, dest)
|
mountedDevice, _, err := GetDeviceNameFromMount(fakeMounter.FakeMounter, dest)
|
||||||
if err != nil || mountedDevice != device {
|
if err != nil || mountedDevice != device {
|
||||||
t.Errorf("the correct device was not mounted")
|
t.Errorf("test \"%s\" the correct device was not mounted", test.description)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if err == nil || test.expectedError.Error() != err.Error() {
|
if err == nil || test.expectedError.Error() != err.Error() {
|
||||||
t.Errorf("unexpected error: %v. Expecting %v", err, test.expectedError)
|
t.Errorf("test \"%s\" unexpected error: \n [%v]. \nExpecting [%v]", test.description, err, test.expectedError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user