From d33a227cb11a7731d55523813c20324534b5f10a Mon Sep 17 00:00:00 2001 From: Raphanus Lo Date: Mon, 25 Nov 2024 22:33:03 +0800 Subject: [PATCH] fix(preflight): check the system default NFS version in mount config ref: longhorn/longhorn-9830 Signed-off-by: Raphanus Lo --- docs/longhornctl.md | 2 +- docs/longhornctl_check.md | 2 +- docs/longhornctl_check_preflight.md | 2 +- docs/longhornctl_doc.md | 2 +- docs/longhornctl_export.md | 2 +- docs/longhornctl_export_replica.md | 2 +- docs/longhornctl_export_replica_stop.md | 2 +- docs/longhornctl_get.md | 2 +- docs/longhornctl_get_replica.md | 2 +- docs/longhornctl_global-options.md | 2 +- docs/longhornctl_install.md | 2 +- docs/longhornctl_install_preflight.md | 2 +- docs/longhornctl_install_preflight_stop.md | 2 +- docs/longhornctl_trim.md | 2 +- docs/longhornctl_trim_volume.md | 2 +- docs/longhornctl_version.md | 2 +- pkg/local/preflight/checker.go | 80 ++++++++------- .../longhorn/go-common-libs/nfs/nfs.go | 97 +++++++++++++++++++ vendor/modules.txt | 1 + 19 files changed, 159 insertions(+), 51 deletions(-) create mode 100644 vendor/github.com/longhorn/go-common-libs/nfs/nfs.go diff --git a/docs/longhornctl.md b/docs/longhornctl.md index 5dd634e9..738b0d2b 100644 --- a/docs/longhornctl.md +++ b/docs/longhornctl.md @@ -26,4 +26,4 @@ CLI for Longhorn troubleshooting and operations. * [longhornctl trim](longhornctl_trim.md) - Longhorn trimming operations * [longhornctl version](longhornctl_version.md) - Print longhornctl version -###### Auto generated by spf13/cobra on 13-Oct-2024 +###### Auto generated by spf13/cobra on 27-Nov-2024 diff --git a/docs/longhornctl_check.md b/docs/longhornctl_check.md index 80ef696b..759cbc25 100644 --- a/docs/longhornctl_check.md +++ b/docs/longhornctl_check.md @@ -16,4 +16,4 @@ Longhorn checking operations * [longhornctl](longhornctl.md) - Longhorn commandline interface. * [longhornctl check preflight](longhornctl_check_preflight.md) - Check Longhorn preflight -###### Auto generated by spf13/cobra on 13-Oct-2024 +###### Auto generated by spf13/cobra on 27-Nov-2024 diff --git a/docs/longhornctl_check_preflight.md b/docs/longhornctl_check_preflight.md index 41c64600..07ead385 100644 --- a/docs/longhornctl_check_preflight.md +++ b/docs/longhornctl_check_preflight.md @@ -57,4 +57,4 @@ INFO[2024-07-16T17:17:42+08:00] Completed preflight checker * [longhornctl check](longhornctl_check.md) - Longhorn checking operations -###### Auto generated by spf13/cobra on 13-Oct-2024 +###### Auto generated by spf13/cobra on 27-Nov-2024 diff --git a/docs/longhornctl_doc.md b/docs/longhornctl_doc.md index f834d8b3..22627ead 100644 --- a/docs/longhornctl_doc.md +++ b/docs/longhornctl_doc.md @@ -28,4 +28,4 @@ longhornctl doc [output directory] [flags] * [longhornctl](longhornctl.md) - Longhorn commandline interface. -###### Auto generated by spf13/cobra on 13-Oct-2024 +###### Auto generated by spf13/cobra on 27-Nov-2024 diff --git a/docs/longhornctl_export.md b/docs/longhornctl_export.md index 096f8c2d..adc4d718 100644 --- a/docs/longhornctl_export.md +++ b/docs/longhornctl_export.md @@ -16,4 +16,4 @@ Export Longhorn resources * [longhornctl](longhornctl.md) - Longhorn commandline interface. * [longhornctl export replica](longhornctl_export_replica.md) - Export Longhorn replica -###### Auto generated by spf13/cobra on 13-Oct-2024 +###### Auto generated by spf13/cobra on 27-Nov-2024 diff --git a/docs/longhornctl_export_replica.md b/docs/longhornctl_export_replica.md index ffe3ace1..6b76d1f7 100644 --- a/docs/longhornctl_export_replica.md +++ b/docs/longhornctl_export_replica.md @@ -62,4 +62,4 @@ lost+found * [longhornctl export](longhornctl_export.md) - Export Longhorn resources * [longhornctl export replica stop](longhornctl_export_replica_stop.md) - Stop exporting Longhorn replica -###### Auto generated by spf13/cobra on 13-Oct-2024 +###### Auto generated by spf13/cobra on 27-Nov-2024 diff --git a/docs/longhornctl_export_replica_stop.md b/docs/longhornctl_export_replica_stop.md index e9895d2b..c45abb74 100644 --- a/docs/longhornctl_export_replica_stop.md +++ b/docs/longhornctl_export_replica_stop.md @@ -31,4 +31,4 @@ INFO[2024-07-16T17:29:14+08:00] Successfully stopped exporting replica * [longhornctl export replica](longhornctl_export_replica.md) - Export Longhorn replica -###### Auto generated by spf13/cobra on 13-Oct-2024 +###### Auto generated by spf13/cobra on 27-Nov-2024 diff --git a/docs/longhornctl_get.md b/docs/longhornctl_get.md index 14d6a5e0..ff2b84aa 100644 --- a/docs/longhornctl_get.md +++ b/docs/longhornctl_get.md @@ -16,4 +16,4 @@ Longhorn information gathering operations * [longhornctl](longhornctl.md) - Longhorn commandline interface. * [longhornctl get replica](longhornctl_get_replica.md) - Get Longhorn replica information -###### Auto generated by spf13/cobra on 13-Oct-2024 +###### Auto generated by spf13/cobra on 27-Nov-2024 diff --git a/docs/longhornctl_get_replica.md b/docs/longhornctl_get_replica.md index 9e7c91db..bda11678 100644 --- a/docs/longhornctl_get_replica.md +++ b/docs/longhornctl_get_replica.md @@ -60,4 +60,4 @@ INFO[2024-07-16T17:23:51+08:00] Completed replica getter * [longhornctl get](longhornctl_get.md) - Longhorn information gathering operations -###### Auto generated by spf13/cobra on 13-Oct-2024 +###### Auto generated by spf13/cobra on 27-Nov-2024 diff --git a/docs/longhornctl_global-options.md b/docs/longhornctl_global-options.md index 0984fd29..5b57e275 100644 --- a/docs/longhornctl_global-options.md +++ b/docs/longhornctl_global-options.md @@ -28,4 +28,4 @@ longhornctl global-options [flags] * [longhornctl](longhornctl.md) - Longhorn commandline interface. -###### Auto generated by spf13/cobra on 13-Oct-2024 +###### Auto generated by spf13/cobra on 27-Nov-2024 diff --git a/docs/longhornctl_install.md b/docs/longhornctl_install.md index c19e6824..20c332fc 100644 --- a/docs/longhornctl_install.md +++ b/docs/longhornctl_install.md @@ -16,4 +16,4 @@ Longhorn installation operations * [longhornctl](longhornctl.md) - Longhorn commandline interface. * [longhornctl install preflight](longhornctl_install_preflight.md) - Install Longhorn preflight -###### Auto generated by spf13/cobra on 13-Oct-2024 +###### Auto generated by spf13/cobra on 27-Nov-2024 diff --git a/docs/longhornctl_install_preflight.md b/docs/longhornctl_install_preflight.md index 32578b49..1518cec1 100644 --- a/docs/longhornctl_install_preflight.md +++ b/docs/longhornctl_install_preflight.md @@ -45,4 +45,4 @@ INFO[2024-07-16T17:09:08+08:00] Completed preflight installer. Use 'longhornctl * [longhornctl install](longhornctl_install.md) - Longhorn installation operations * [longhornctl install preflight stop](longhornctl_install_preflight_stop.md) - Stop Longhorn preflight installer -###### Auto generated by spf13/cobra on 13-Oct-2024 +###### Auto generated by spf13/cobra on 27-Nov-2024 diff --git a/docs/longhornctl_install_preflight_stop.md b/docs/longhornctl_install_preflight_stop.md index b5e2718f..5c8e7369 100644 --- a/docs/longhornctl_install_preflight_stop.md +++ b/docs/longhornctl_install_preflight_stop.md @@ -32,4 +32,4 @@ INFO[2024-07-16T17:21:32+08:00] Successfully stopped preflight installer * [longhornctl install preflight](longhornctl_install_preflight.md) - Install Longhorn preflight -###### Auto generated by spf13/cobra on 13-Oct-2024 +###### Auto generated by spf13/cobra on 27-Nov-2024 diff --git a/docs/longhornctl_trim.md b/docs/longhornctl_trim.md index ccce939c..089e95b9 100644 --- a/docs/longhornctl_trim.md +++ b/docs/longhornctl_trim.md @@ -16,4 +16,4 @@ Longhorn trimming operations * [longhornctl](longhornctl.md) - Longhorn commandline interface. * [longhornctl trim volume](longhornctl_trim_volume.md) - Trim a Longhorn volume -###### Auto generated by spf13/cobra on 13-Oct-2024 +###### Auto generated by spf13/cobra on 27-Nov-2024 diff --git a/docs/longhornctl_trim_volume.md b/docs/longhornctl_trim_volume.md index e85b2e30..2f7bc138 100644 --- a/docs/longhornctl_trim_volume.md +++ b/docs/longhornctl_trim_volume.md @@ -42,4 +42,4 @@ INFO[2024-07-16T17:32:01+08:00] Completed volume trimmer vo * [longhornctl trim](longhornctl_trim.md) - Longhorn trimming operations -###### Auto generated by spf13/cobra on 13-Oct-2024 +###### Auto generated by spf13/cobra on 27-Nov-2024 diff --git a/docs/longhornctl_version.md b/docs/longhornctl_version.md index d4a14fe6..4685eca0 100644 --- a/docs/longhornctl_version.md +++ b/docs/longhornctl_version.md @@ -24,4 +24,4 @@ longhornctl version [flags] * [longhornctl](longhornctl.md) - Longhorn commandline interface. -###### Auto generated by spf13/cobra on 13-Oct-2024 +###### Auto generated by spf13/cobra on 27-Nov-2024 diff --git a/pkg/local/preflight/checker.go b/pkg/local/preflight/checker.go index f2ce45df..f15d5cb6 100644 --- a/pkg/local/preflight/checker.go +++ b/pkg/local/preflight/checker.go @@ -1,10 +1,8 @@ package preflight import ( - "bufio" "encoding/json" "fmt" - "os" "path/filepath" "runtime" "strconv" @@ -17,7 +15,9 @@ import ( kubeclient "k8s.io/client-go/kubernetes" commonkube "github.com/longhorn/go-common-libs/kubernetes" + commonnfs "github.com/longhorn/go-common-libs/nfs" commonns "github.com/longhorn/go-common-libs/ns" + commonsys "github.com/longhorn/go-common-libs/sys" commontypes "github.com/longhorn/go-common-libs/types" "github.com/longhorn/cli/pkg/consts" @@ -420,52 +420,62 @@ func (local *Checker) checkModulesLoaded(spdkDependent bool) error { func (local *Checker) checkNFSv4Support() error { logrus.Info("Checking if NFS4 (either 4.0, 4.1 or 4.2) is supported") + // check kernel capability + var isKernelSupport = false + kernelVersion, err := utils.GetKernelVersion() if err != nil { return err } - kernelConfigPath := "/boot/config-" + kernelVersion - kernelConfigPath = filepath.Join(consts.VolumeMountHostDirectory, kernelConfigPath) - configFile, err := os.Open(kernelConfigPath) + hostBootDir := filepath.Join(consts.VolumeMountHostDirectory, commontypes.SysBootDirectory) + kernelConfigMap, err := commonsys.GetBootKernelConfigMap(hostBootDir, kernelVersion) if err != nil { return err } - defer func(configFile *os.File) { - _ = configFile.Close() - }(configFile) - - scanner := bufio.NewScanner(configFile) - - for scanner.Scan() { - line := scanner.Text() - if strings.HasPrefix(line, "CONFIG_NFS_V4_2=") || - strings.HasPrefix(line, "CONFIG_NFS_V4_1=") || - strings.HasPrefix(line, "CONFIG_NFS_V4=") { - option := strings.Split(line, "=") - if len(option) == 2 { - if option[1] == "y" { - local.collection.Log.Info = append(local.collection.Log.Info, "NFS4 is supported") - return nil - } else if option[1] == "m" { - // Check if the module is loaded - moduleLoaded, err := utils.IsModuleLoaded(option[0]) - if err != nil { - continue - } - if moduleLoaded { - local.collection.Log.Info = append(local.collection.Log.Info, "NFS4 is supported") - return nil - } - } + for configItem, module := range map[string]string{"CONFIG_NFS_V4_2": "nfs", "CONFIG_NFS_V4_1": "nfs", "CONFIG_NFS_V4": "nfs"} { + if configVal, exist := kernelConfigMap[configItem]; !exist { + continue + } else if configVal == "y" { + isKernelSupport = true + break + } else if configVal == "m" { + // Check if the module is loaded + moduleLoaded, err := utils.IsModuleLoaded(module) + if err != nil { + continue + } + if moduleLoaded { + isKernelSupport = true + break } } } - if err := scanner.Err(); err != nil { - return errors.Wrap(err, "failed to check NFS4 support") + if !isKernelSupport { + local.collection.Log.Error = append(local.collection.Log.Error, "NFS4 is not supported") + return nil + } + + // check default NFS protocol version + var isSupportedNFSVersion bool + + hostEtcDir := filepath.Join(consts.VolumeMountHostDirectory, commontypes.SysEtcDirectory) + nfsMajor, nfsMinor, err := commonnfs.GetSystemDefaultNFSVersion(hostEtcDir) + if err == nil { + isSupportedNFSVersion = nfsMajor == 4 && (nfsMinor == 0 || nfsMinor == 1 || nfsMinor == 2) + } else if errors.Is(err, commontypes.ErrNotConfigured) { + // NFSv4 by default + isSupportedNFSVersion = true + } else { + local.collection.Log.Error = append(local.collection.Log.Error, "Failed to read NFS mount config") + return err + } + + if !isSupportedNFSVersion { + local.collection.Log.Warn = append(local.collection.Log.Warn, "NFS4 is supported, but default protocol version is not 4, 4.1, or 4.2. Please refer to the NFS mount configuration manual page for more information: man 5 nfsmount.conf") } - local.collection.Log.Error = append(local.collection.Log.Error, "NFS4 is not supported") + local.collection.Log.Info = append(local.collection.Log.Info, "NFS4 is supported") return nil } diff --git a/vendor/github.com/longhorn/go-common-libs/nfs/nfs.go b/vendor/github.com/longhorn/go-common-libs/nfs/nfs.go new file mode 100644 index 00000000..a566ef72 --- /dev/null +++ b/vendor/github.com/longhorn/go-common-libs/nfs/nfs.go @@ -0,0 +1,97 @@ +package nfs + +import ( + "bufio" + "fmt" + "os" + "path/filepath" + "strconv" + "strings" + + "github.com/pkg/errors" + + "github.com/longhorn/go-common-libs/types" +) + +const ( + nfsmountGlobalSection = "NFSMount_Global_Options" + nfsmountDefaultVersion = "Defaultvers" +) + +// GetSystemDefaultNFSVersion reads the system default NFS version. This config can be overridden by nfsmount.conf under +// configDir. If configDir is empty, it will be /etc by default. If the nfsmount.conf is absent, or the default +// version is not overridden in the configuration file, a wrapped ErrNotConfigured error will be returned. It is possible +// for the caller to tell if the configuration is overridden by errors.Is(err, types.ErrNotConfigured). +func GetSystemDefaultNFSVersion(configDir string) (major, minor int, err error) { + if configDir == "" { + configDir = types.SysEtcDirectory + } + + configMap, err := getSystemNFSMountConfigMap(configDir) + if os.IsNotExist(err) { + return 0, 0, fmt.Errorf("system default NFS version is not overridden under %q: %w", configDir, types.ErrNotConfigured) + } else if err != nil { + return 0, 0, err + } + if globalSection, ok := configMap[nfsmountGlobalSection]; ok { + if configured, ok := globalSection[nfsmountDefaultVersion]; ok { + majorStr, minorStr, _ := strings.Cut(configured, ".") + major, err := strconv.Atoi(majorStr) + if err != nil { + return 0, 0, errors.Wrapf(err, "invalid NFS major version %q", configured) + } + + minor := 0 + if minorStr != "" { + minor, err = strconv.Atoi(minorStr) + if err != nil { + return 0, 0, errors.Wrapf(err, "invalid NFS minor version %q", configured) + } + } + return major, minor, nil + } + } + return 0, 0, fmt.Errorf("system default NFS version is not overridden under %q: %w", configDir, types.ErrNotConfigured) +} + +// getSystemNFSMountConfigMap reads the nfsmount.conf under configDir. The returned result is in +// map[section]map[key]value structure, and the global options is result["NFSMount_Global_Options"]. Refer to man page +// for more detail: man 5 nfsmount.conf +func getSystemNFSMountConfigMap(configDir string) (map[string]map[string]string, error) { + configFilePath := filepath.Join(configDir, types.NFSMountFileName) + configFile, err := os.Open(configFilePath) + if err != nil { + return nil, err + } + defer configFile.Close() + + configMap := make(map[string]map[string]string) + scanner := bufio.NewScanner(configFile) + var section = "" + var sectionMap map[string]string + + for scanner.Scan() { + line := strings.TrimSpace(scanner.Text()) + if line == "" || strings.HasPrefix(line, "#") { + continue + } + if strings.HasPrefix(line, "[") { + section = strings.TrimSpace(strings.Trim(line, "[]")) + continue + } + if sectionMap = configMap[section]; sectionMap == nil { + sectionMap = make(map[string]string) + configMap[section] = sectionMap + } + if key, val, isParsable := strings.Cut(line, "="); isParsable { + sectionMap[strings.TrimSpace(key)] = strings.TrimSpace(val) + } else { + return nil, fmt.Errorf("invalid key-value pair: '%s'", line) + } + } + + if err := scanner.Err(); err != nil { + return nil, err + } + return configMap, nil +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 4911cad3..e9a27ad7 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -139,6 +139,7 @@ github.com/longhorn/go-common-libs/exec github.com/longhorn/go-common-libs/io github.com/longhorn/go-common-libs/kubernetes github.com/longhorn/go-common-libs/longhorn +github.com/longhorn/go-common-libs/nfs github.com/longhorn/go-common-libs/ns github.com/longhorn/go-common-libs/proc github.com/longhorn/go-common-libs/sync