This repository has been archived by the owner on Jan 10, 2023. It is now read-only.
/
fs.go
125 lines (113 loc) · 3.62 KB
/
fs.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package main
import (
"context"
"fmt"
"os/exec"
"strings"
"github.com/Netflix/titus-executor/logger"
)
type fsType string
func isMkfsNeeded(ctx context.Context, device string, fstype fsType) (bool, error) {
l := logger.GetLogger(ctx)
existingFormat, err := getDiskFormat(ctx, device)
if err != nil {
return false, err
}
if existingFormat == "" {
return true, nil
}
l.Infof("Existing format on disks detected, no mkfs needed: %q", existingFormat)
return false, nil
}
func mkfs(ctx context.Context, device string, fstype fsType) error {
if fstype == "ext4" || fstype == "ext3" || fstype == "" {
if fstype == "" {
// Mimicing default linux behavior here
fstype = "ext4"
}
args := []string{
"-F", // Force flag
"-m0", // Zero blocks reserved for super-user
device,
}
return runMkfs(ctx, device, fstype, args)
} else if fstype == "xfs" {
args := []string{
"-f", // Force flag
device,
}
return runMkfs(ctx, device, fstype, args)
}
return fmt.Errorf("Not implemented: unable to mkfs for format '%s'", fstype)
}
// runMkfs is modeled after the code in kubelet for formatAndMount
func runMkfs(ctx context.Context, device string, fstype fsType, args []string) error {
l := logger.GetLogger(ctx)
mkfsCmd := string("mkfs." + fstype)
out, err := exec.Command(mkfsCmd, args...).CombinedOutput()
if err == nil {
// the disk has been formatted successfully try to mount it again.
l.Infof("Disk successfully formatted (mkfs): %s - %s", fstype, device)
return nil
}
l.WithError(fmt.Errorf("format of disk %s failed: %s - %s)", device, err, string(out)))
return err
}
// getDiskFormat is copied from kubelet. Returns empty string if there is no filesystem
// in place, indicating it is safe to mkfs
func getDiskFormat(ctx context.Context, disk string) (string, error) {
l := logger.GetLogger(ctx)
args := []string{"-p", "-s", "TYPE", "-s", "PTTYPE", "-o", "export", disk}
l.Infof("Attempting to determine if disk %q is formatted using blkid with args: (%v)", disk, args)
dataOut, err := exec.Command("blkid", args...).CombinedOutput()
output := string(dataOut)
if err != nil {
if exit, ok := err.(*exec.ExitError); ok {
if exit.ExitCode() == 2 {
// Disk device is unformatted.
// For `blkid`, if the specified token (TYPE/PTTYPE, etc) was
// not found, or no (specified) devices could be identified, an
// exit code of 2 is returned.
return "", nil
}
}
l.WithError(fmt.Errorf("Could not determine if disk %q is formatted (%v)", disk, err))
return "", err
}
var fstype, pttype string
lines := strings.Split(output, "\n")
for _, l := range lines {
if len(l) <= 0 {
// Ignore empty line.
continue
}
cs := strings.Split(l, "=")
if len(cs) != 2 {
return "", fmt.Errorf("blkid returns invalid output: %s", output)
}
// TYPE is filesystem type, and PTTYPE is partition table type, according
// to https://www.kernel.org/pub/linux/utils/util-linux/v2.21/libblkid-docs/.
if cs[0] == "TYPE" {
fstype = cs[1]
} else if cs[0] == "PTTYPE" {
pttype = cs[1]
}
}
if len(pttype) > 0 {
l.Infof("Disk %s detected partition table type: %s", disk, pttype)
// Returns a special non-empty string as filesystem type, then kubelet
// will not format it.
return "unknown data, probably partitions", nil
}
return fstype, nil
}
func fsck(ctx context.Context, device string, fstype string) {
l := logger.GetLogger(ctx)
args := []string{"-a", device}
fsckCmd := "fsck." + fstype
out, err := exec.Command(fsckCmd, args...).CombinedOutput()
if err == nil {
l.Warnf("fsck errors on %s - %s", device, string(out))
}
l.Infof("fsck output on %s - %s", device, string(out))
}