Skip to content

Commit

Permalink
cc-check: Always run all tests
Browse files Browse the repository at this point in the history
Change "cc-check" so that it always runs all commands before erroring.

Previously, it would fail on first error, but this could mask the real
reason for failure. For example, on a system with nesting and vhost
disabled, "cc-check" would fail with a nesting error. But the nesting
check is not strictly required (clearcontainers#281) whereas vhost definitely is which
lead to confusing results for users.

"cc-check" will now run all tests and display an error message at the end
if any errors were found in the set of tests run.

Fixes clearcontainers#638.

Signed-off-by: James O. D. Hunt <[email protected]>
  • Loading branch information
jodh-intel committed Sep 27, 2017
1 parent d9897e1 commit c761552
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 41 deletions.
77 changes: 56 additions & 21 deletions cc-check.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
package main

import (
"errors"
"fmt"
"os/exec"
"path/filepath"
Expand All @@ -38,6 +37,7 @@ const (
moduleParamDir = "parameters"
cpuFlagsTag = "flags"
successMessage = "System is capable of running " + project
failMessage = "System is not capable of running " + project
)

// variables rather than consts to allow tests to modify them
Expand Down Expand Up @@ -83,7 +83,7 @@ var requiredKernelModules = map[string]kernelModule{
},
}

// return details of the first CPU
// getCPUInfo returns details of the first CPU
func getCPUInfo(cpuInfoFile string) (string, error) {
text, err := getFileContents(cpuInfoFile)
if err != nil {
Expand Down Expand Up @@ -137,38 +137,51 @@ func haveKernelModule(module string) bool {
return err == nil
}

func checkCPU(tag, cpuinfo string, attribs map[string]string) error {
// checkCPU checks all required CPU attributes modules and returns a count of
// the number of CPU attribute errors (all of which are logged by this
// function). Only fatal errors result in an error return.
func checkCPU(tag, cpuinfo string, attribs map[string]string) (count uint32, err error) {
if cpuinfo == "" {
return fmt.Errorf("Need cpuinfo")
return 0, fmt.Errorf("Need cpuinfo")
}

for attrib, desc := range attribs {
found := findAnchoredString(cpuinfo, attrib)
if !found {
return fmt.Errorf("CPU does not have required %v: %q (%s)", tag, desc, attrib)
ccLog.Errorf("CPU does not have required %v: %q (%s)", tag, desc, attrib)
count++
continue

}

ccLog.Infof("Found CPU %v %q (%s)", tag, desc, attrib)
}

return nil
return count, nil
}
func checkCPUFlags(cpuflags string, required map[string]string) error {

func checkCPUFlags(cpuflags string, required map[string]string) (uint32, error) {
return checkCPU("flag", cpuflags, required)
}

func checkCPUAttribs(cpuinfo string, attribs map[string]string) error {
func checkCPUAttribs(cpuinfo string, attribs map[string]string) (uint32, error) {
return checkCPU("attribute", cpuinfo, attribs)
}

func checkKernelModules(modules map[string]kernelModule) error {
// checkKernelModules checks all required kernel modules modules and returns a count of
// the number of module errors (all of which are logged by this
// function). Only fatal errors result in an error return.
func checkKernelModules(modules map[string]kernelModule) (count uint32, err error) {
onVMM, err := vc.RunningOnVMM(procCPUInfo)
if err != nil {
return err
return 0, err
}

for module, details := range modules {
if !haveKernelModule(module) {
return fmt.Errorf("kernel module %q (%s) not found", module, details.desc)
ccLog.Errorf("kernel module %q (%s) not found", module, details.desc)
count++
continue
}

ccLog.Infof("Found kernel module %q (%s)", details.desc, module)
Expand All @@ -177,7 +190,7 @@ func checkKernelModules(modules map[string]kernelModule) error {
path := filepath.Join(sysModuleDir, module, moduleParamDir, param)
value, err := getFileContents(path)
if err != nil {
return err
return 0, err
}

value = strings.TrimRight(value, "\n\r")
Expand All @@ -192,14 +205,15 @@ func checkKernelModules(modules map[string]kernelModule) error {
continue
}

return errors.New(msg)
ccLog.Error(msg)
count++
}

ccLog.Infof("Kernel module %q parameter %q has correct value", details.desc, param)
}
}

return nil
return count, nil
}

// hostIsClearContainersCapable determines if the system is capable of
Expand All @@ -210,20 +224,41 @@ func hostIsClearContainersCapable(cpuinfoFile string) error {
return err
}

if err = checkCPUAttribs(cpuinfo, requiredCPUAttribs); err != nil {
return err
}

cpuFlags := getCPUFlags(cpuinfo)
if cpuFlags == "" {
return fmt.Errorf("Cannot find CPU flags")
}

if err = checkCPUFlags(cpuFlags, requiredCPUFlags); err != nil {
// Keep a track of the error count, but don't error until all tests
// have been performed!
errorCount := uint32(0)

count, err := checkCPUAttribs(cpuinfo, requiredCPUAttribs)
if err != nil {
return err
}

return checkKernelModules(requiredKernelModules)
errorCount += count

count, err = checkCPUFlags(cpuFlags, requiredCPUFlags)
if err != nil {
return err
}

errorCount += count

count, err = checkKernelModules(requiredKernelModules)
if err != nil {
return err
}

errorCount += count

if errorCount == 0 {
return nil
}

return fmt.Errorf("ERROR: %s", failMessage)
}

var ccCheckCLICommand = cli.Command{
Expand All @@ -232,7 +267,7 @@ var ccCheckCLICommand = cli.Command{
Action: func(context *cli.Context) error {
err := hostIsClearContainersCapable(procCPUInfo)
if err != nil {
return fmt.Errorf("ERROR: %v", err)
return err
}

ccLog.Info("")
Expand Down
Loading

0 comments on commit c761552

Please sign in to comment.