代码拉取完成,页面将自动刷新
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package system
import (
"bufio"
"bytes"
"compress/gzip"
"fmt"
"io"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"regexp"
"strings"
"github.com/pkg/errors"
errorsutil "k8s.io/apimachinery/pkg/util/errors"
"k8s.io/klog"
)
var _ Validator = &KernelValidator{}
// KernelValidator validates kernel. Currently only validate kernel version
// and kernel configuration.
type KernelValidator struct {
kernelRelease string
Reporter Reporter
}
func (k *KernelValidator) Name() string {
return "kernel"
}
// kConfigOption is the possible kernel config option.
type kConfigOption string
const (
builtIn kConfigOption = "y"
asModule kConfigOption = "m"
leftOut kConfigOption = "n"
// validKConfigRegex is the regex matching kernel configuration line.
validKConfigRegex = "^CONFIG_[A-Z0-9_]+=[myn]"
// kConfigPrefix is the prefix of kernel configuration.
kConfigPrefix = "CONFIG_"
)
func (k *KernelValidator) Validate(spec SysSpec) (error, error) {
helper := KernelValidatorHelperImpl{}
release, err := helper.GetKernelReleaseVersion()
if err != nil {
return nil, errors.Wrap(err, "failed to get kernel release")
}
k.kernelRelease = release
var errs []error
errs = append(errs, k.validateKernelVersion(spec.KernelSpec))
// only validate kernel config when necessary (currently no kernel config for windows)
if len(spec.KernelSpec.Required) > 0 || len(spec.KernelSpec.Forbidden) > 0 || len(spec.KernelSpec.Optional) > 0 {
errs = append(errs, k.validateKernelConfig(spec.KernelSpec))
}
return nil, errorsutil.NewAggregate(errs)
}
// validateKernelVersion validates the kernel version.
func (k *KernelValidator) validateKernelVersion(kSpec KernelSpec) error {
versionRegexps := kSpec.Versions
for _, versionRegexp := range versionRegexps {
r := regexp.MustCompile(versionRegexp)
if r.MatchString(k.kernelRelease) {
k.Reporter.Report("KERNEL_VERSION", k.kernelRelease, good)
return nil
}
}
k.Reporter.Report("KERNEL_VERSION", k.kernelRelease, bad)
return errors.Errorf("unsupported kernel release: %s", k.kernelRelease)
}
// validateKernelConfig validates the kernel configurations.
func (k *KernelValidator) validateKernelConfig(kSpec KernelSpec) error {
allConfig, err := k.getKernelConfig()
if err != nil {
return errors.Wrap(err, "failed to parse kernel config")
}
return k.validateCachedKernelConfig(allConfig, kSpec)
}
// validateCachedKernelConfig validates the kernel confgiurations cached in internal data type.
func (k *KernelValidator) validateCachedKernelConfig(allConfig map[string]kConfigOption, kSpec KernelSpec) error {
badConfigs := []string{}
// reportAndRecord is a helper function to record bad config when
// report.
reportAndRecord := func(name, msg, desc string, result ValidationResultType) {
if result == bad {
badConfigs = append(badConfigs, name)
}
// report description when the config is bad or warn.
if result != good && desc != "" {
msg = msg + " - " + desc
}
k.Reporter.Report(name, msg, result)
}
const (
required = iota
optional
forbidden
)
validateOpt := func(config KernelConfig, expect int) {
var found, missing ValidationResultType
switch expect {
case required:
found, missing = good, bad
case optional:
found, missing = good, warn
case forbidden:
found, missing = bad, good
}
var name string
var opt kConfigOption
var ok bool
for _, name = range append([]string{config.Name}, config.Aliases...) {
name = kConfigPrefix + name
if opt, ok = allConfig[name]; ok {
break
}
}
if !ok {
reportAndRecord(name, "not set", config.Description, missing)
return
}
switch opt {
case builtIn:
reportAndRecord(name, "enabled", config.Description, found)
case asModule:
reportAndRecord(name, "enabled (as module)", config.Description, found)
case leftOut:
reportAndRecord(name, "disabled", config.Description, missing)
default:
reportAndRecord(name, fmt.Sprintf("unknown option: %s", opt), config.Description, missing)
}
}
for _, config := range kSpec.Required {
validateOpt(config, required)
}
for _, config := range kSpec.Optional {
validateOpt(config, optional)
}
for _, config := range kSpec.Forbidden {
validateOpt(config, forbidden)
}
if len(badConfigs) > 0 {
return errors.Errorf("unexpected kernel config: %s", strings.Join(badConfigs, " "))
}
return nil
}
// getKernelConfigReader search kernel config file in a predefined list. Once the kernel config
// file is found it will read the configurations into a byte buffer and return. If the kernel
// config file is not found, it will try to load kernel config module and retry again.
func (k *KernelValidator) getKernelConfigReader() (io.Reader, error) {
possibePaths := []string{
"/proc/config.gz",
"/boot/config-" + k.kernelRelease,
"/usr/src/linux-" + k.kernelRelease + "/.config",
"/usr/src/linux/.config",
"/usr/lib/modules/" + k.kernelRelease + "/config",
"/usr/lib/ostree-boot/config-" + k.kernelRelease,
"/usr/lib/kernel/config-" + k.kernelRelease,
"/usr/src/linux-headers-" + k.kernelRelease + "/.config",
"/lib/modules/" + k.kernelRelease + "/build/.config",
}
configsModule := "configs"
modprobeCmd := "modprobe"
// loadModule indicates whether we've tried to load kernel config module ourselves.
loadModule := false
for {
for _, path := range possibePaths {
_, err := os.Stat(path)
if err != nil {
continue
}
// Buffer the whole file, so that we can close the file and unload
// kernel config module in this function.
b, err := ioutil.ReadFile(path)
if err != nil {
return nil, err
}
var r io.Reader
r = bytes.NewReader(b)
// This is a gzip file (config.gz), unzip it.
if filepath.Ext(path) == ".gz" {
r, err = gzip.NewReader(r)
if err != nil {
return nil, err
}
}
return r, nil
}
// If we've tried to load kernel config module, break and return error.
if loadModule {
break
}
// If the kernel config file is not found, try to load the kernel
// config module and check again.
output, err := exec.Command(modprobeCmd, configsModule).CombinedOutput()
if err != nil {
return nil, errors.Wrapf(err, "unable to load kernel module: %q, output: %q, err",
configsModule, output)
}
// Unload the kernel config module to make sure the validation have no side effect.
defer exec.Command(modprobeCmd, "-r", configsModule).Run()
loadModule = true
}
return nil, errors.Errorf("no config path in %v is available", possibePaths)
}
// getKernelConfig gets kernel config from kernel config file and convert kernel config to internal type.
func (k *KernelValidator) getKernelConfig() (map[string]kConfigOption, error) {
r, err := k.getKernelConfigReader()
if err != nil {
return nil, err
}
return k.parseKernelConfig(r)
}
// parseKernelConfig converts kernel config to internal type.
func (k *KernelValidator) parseKernelConfig(r io.Reader) (map[string]kConfigOption, error) {
config := map[string]kConfigOption{}
regex := regexp.MustCompile(validKConfigRegex)
s := bufio.NewScanner(r)
for s.Scan() {
if err := s.Err(); err != nil {
return nil, err
}
line := strings.TrimSpace(s.Text())
if !regex.MatchString(line) {
continue
}
fields := strings.Split(line, "=")
if len(fields) != 2 {
klog.Errorf("Unexpected fields number in config %q", line)
continue
}
config[fields[0]] = kConfigOption(fields[1])
}
return config, nil
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。