-
Notifications
You must be signed in to change notification settings - Fork 218
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feature: support external-health-monitor #210
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -63,5 +63,10 @@ func handle() { | |
fmt.Printf("Failed to initialize driver: %s", err.Error()) | ||
os.Exit(1) | ||
} | ||
driver.Run() | ||
|
||
if err := driver.Run(); err != nil { | ||
fmt.Printf("Failed to run driver: %s", err.Error()) | ||
os.Exit(1) | ||
|
||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here? This looks like an unrelated enhancement. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. An error may be returned from that function, just checking it right? |
||
} |
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,202 @@ | ||
package hostpath | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"os" | ||
"os/exec" | ||
"path/filepath" | ||
"strings" | ||
|
||
"github.com/golang/glog" | ||
fs "k8s.io/kubernetes/pkg/volume/util/fs" | ||
) | ||
|
||
const ( | ||
podVolumeTargetPath = "/var/lib/kubelet/pods" | ||
csiSignOfVolumeTargetPath = "kubernetes.io~csi/pvc" | ||
) | ||
|
||
type MountPointInfo struct { | ||
Target string `json:"target"` | ||
Source string `json:"source"` | ||
FsType string `json:"fstype"` | ||
Options string `json:"options"` | ||
ContainerFileSystem []MountPointInfo `json:"children,omitempty"` | ||
} | ||
|
||
type ContainerFileSystem struct { | ||
Children []MountPointInfo `json:"children"` | ||
} | ||
|
||
type FileSystems struct { | ||
Filsystem []ContainerFileSystem `json:"filesystems"` | ||
} | ||
|
||
func locateCommandPath(commandName string) string { | ||
// default to root | ||
binary := filepath.Join("/", commandName) | ||
for _, path := range []string{"/bin", "/usr/sbin", "/usr/bin"} { | ||
binPath := filepath.Join(path, binary) | ||
if _, err := os.Stat(binPath); err != nil { | ||
continue | ||
} | ||
|
||
return binPath | ||
} | ||
|
||
return "" | ||
} | ||
|
||
func getSourcePath(volumeHandle string) string { | ||
return fmt.Sprintf("%s/%s", dataRoot, volumeHandle) | ||
} | ||
|
||
func checkSourcePathExist(volumeHandle string) (bool, error) { | ||
sourcePath := getSourcePath(volumeHandle) | ||
glog.V(3).Infof("Volume: %s Source path is: %s", volumeHandle, sourcePath) | ||
_, err := os.Stat(sourcePath) | ||
if err != nil { | ||
if os.IsNotExist(err) { | ||
return false, nil | ||
} | ||
|
||
return false, err | ||
} | ||
|
||
return true, nil | ||
} | ||
|
||
func parseMountInfo(originalMountInfo []byte) ([]MountPointInfo, error) { | ||
fs := FileSystems{ | ||
Filsystem: make([]ContainerFileSystem, 0), | ||
} | ||
|
||
if err := json.Unmarshal(originalMountInfo, &fs); err != nil { | ||
return nil, err | ||
} | ||
|
||
if len(fs.Filsystem) <= 0 { | ||
return nil, fmt.Errorf("failed to get mount info") | ||
} | ||
|
||
return fs.Filsystem[0].Children, nil | ||
} | ||
|
||
func checkMountPointExist(sourcePath string) (bool, error) { | ||
cmdPath := locateCommandPath("findmnt") | ||
out, err := exec.Command(cmdPath, "--json").CombinedOutput() | ||
if err != nil { | ||
glog.V(3).Infof("failed to execute command: %+v", cmdPath) | ||
return false, err | ||
} | ||
|
||
if len(out) < 1 { | ||
return false, fmt.Errorf("mount point info is nil") | ||
} | ||
|
||
mountInfos, err := parseMountInfo([]byte(out)) | ||
if err != nil { | ||
return false, fmt.Errorf("failed to parse the mount infos: %+v", err) | ||
} | ||
|
||
mountInfosOfPod := MountPointInfo{} | ||
for _, mountInfo := range mountInfos { | ||
if mountInfo.Target == podVolumeTargetPath { | ||
mountInfosOfPod = mountInfo | ||
break | ||
} | ||
} | ||
|
||
for _, mountInfo := range mountInfosOfPod.ContainerFileSystem { | ||
if !strings.Contains(mountInfo.Source, sourcePath) { | ||
continue | ||
} | ||
|
||
_, err = os.Stat(mountInfo.Target) | ||
if err != nil { | ||
if os.IsNotExist(err) { | ||
return false, nil | ||
} | ||
|
||
return false, err | ||
} | ||
|
||
return true, nil | ||
} | ||
|
||
return false, nil | ||
} | ||
|
||
func checkPVCapacityValid(volumeHandle string) (bool, error) { | ||
sourcePath := getSourcePath(volumeHandle) | ||
_, fscapacity, _, _, _, _, err := fs.FsInfo(sourcePath) | ||
if err != nil { | ||
return false, fmt.Errorf("failed to get capacity info: %+v", err) | ||
} | ||
|
||
volumeCapacity := hostPathVolumes[volumeHandle].VolSize | ||
glog.V(3).Infof("volume capacity: %+v fs capacity:%+v", volumeCapacity, fscapacity) | ||
return fscapacity >= volumeCapacity, nil | ||
} | ||
|
||
func getPVCapacity(volumeHandle string) (int64, int64, int64, error) { | ||
sourcePath := getSourcePath(volumeHandle) | ||
fsavailable, fscapacity, fsused, _, _, _, err := fs.FsInfo(sourcePath) | ||
return fscapacity, fsused, fsavailable, err | ||
} | ||
|
||
func checkPVUsage(volumeHandle string) (bool, error) { | ||
sourcePath := getSourcePath(volumeHandle) | ||
fsavailable, _, _, _, _, _, err := fs.FsInfo(sourcePath) | ||
if err != nil { | ||
return false, err | ||
} | ||
|
||
glog.V(3).Infof("fs available: %+v", fsavailable) | ||
return fsavailable > 0, nil | ||
} | ||
|
||
func doHealthCheckInControllerSide(volumeHandle string) (bool, string) { | ||
spExist, err := checkSourcePathExist(volumeHandle) | ||
if err != nil { | ||
return false, err.Error() | ||
} | ||
|
||
if !spExist { | ||
return false, "The source path of the volume doesn't exist" | ||
} | ||
|
||
capValid, err := checkPVCapacityValid(volumeHandle) | ||
if err != nil { | ||
return false, err.Error() | ||
} | ||
|
||
if !capValid { | ||
return false, "The capacity of volume is greater than actual storage" | ||
} | ||
|
||
available, err := checkPVUsage(volumeHandle) | ||
if err != nil { | ||
return false, err.Error() | ||
} | ||
|
||
if !available { | ||
return false, "The free space of the volume is insufficient" | ||
} | ||
|
||
return true, "" | ||
} | ||
|
||
func doHealthCheckInNodeSide(volumeHandle string) (bool, string) { | ||
mpExist, err := checkMountPointExist(volumeHandle) | ||
if err != nil { | ||
return false, err.Error() | ||
} | ||
|
||
if !mpExist { | ||
return false, "The volume isn't mounted" | ||
} | ||
|
||
return true, "" | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How is this related to "support external-health-monitor"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When I implement this feature, I found I need run findmnt command with
json
argument. It was supported in newer version. So, I update it