diff --git a/csi/node_server.go b/csi/node_server.go index f79028c532..f53f7ecbd8 100644 --- a/csi/node_server.go +++ b/csi/node_server.go @@ -280,6 +280,9 @@ func (ns *NodeServer) nodeStageSharedVolume(volumeID, shareEndpoint, targetPath if err == nil { return nil } + // Still failed. Log with mounting node and kernel version for possible troubleshooting. + osInfo := getOSInfo() + log.WithError(err).Warnf("Failed to mount volume %v on node %s with kernel release %s.", volumeID, ns.nodeID, osInfo) } return status.Error(codes.Internal, err.Error()) } diff --git a/csi/util.go b/csi/util.go index f71d0c72ff..20081c5d7d 100644 --- a/csi/util.go +++ b/csi/util.go @@ -10,6 +10,7 @@ import ( "path/filepath" "strconv" "strings" + "syscall" "time" "github.com/container-storage-interface/spec/lib/go/csi" @@ -460,3 +461,28 @@ func requiresSharedAccess(vol *longhornclient.Volume, cap *csi.VolumeCapability) func getStageBlockVolumePath(stagingTargetPath, volumeID string) string { return filepath.Join(stagingTargetPath, volumeID) } + +// We use this utility function because csi-plugin has no datastore object to ask about kubernetes node, +// and the go-common-lib/ns functions won't work because the /proc mount path is different. +func getOSInfo() string { + utsname := &syscall.Utsname{} + if err := syscall.Uname(utsname); err != nil { + logrus.WithError(err).Warn("Failed making syscall Uname.") + return "" + } + + extract := func(field [65]int8) string { + output := make([]byte, 0, len(field)) + for _, b := range field { + if b == 0x00 { + break + } + output = append(output, byte(b)) + } + return string(output) + } + + // Extract the kernel release and OS version from the utsname structure + osInfo := extract(utsname.Release) + ", " + extract(utsname.Version) + return osInfo +}