mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-10-22 12:29:49 +00:00
- Add kata-runtime - Add unit test - Add Makefile to build cli Fixes: #33 Signed-off-by: Julio Montes <julio.montes@intel.com> Signed-off-by: James O. D. Hunt <james.o.hunt@intel.com> Signed-off-by: Jose Carlos Venegas Munoz <jose.carlos.venegas.munoz@intel.com>
208 lines
5.0 KiB
Go
208 lines
5.0 KiB
Go
// Copyright (c) 2017 Intel Corporation
|
|
//
|
|
// 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 main
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"strings"
|
|
)
|
|
|
|
const unknown = "<<unknown>>"
|
|
|
|
// variables to allow tests to modify the values
|
|
var (
|
|
procVersion = "/proc/version"
|
|
osRelease = "/etc/os-release"
|
|
|
|
// Clear Linux has a different path (for stateless support)
|
|
osReleaseClr = "/usr/lib/os-release"
|
|
)
|
|
|
|
func fileExists(path string) bool {
|
|
if _, err := os.Stat(path); os.IsNotExist(err) {
|
|
return false
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
func getFileContents(file string) (string, error) {
|
|
bytes, err := ioutil.ReadFile(file)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return string(bytes), nil
|
|
}
|
|
|
|
func getKernelVersion() (string, error) {
|
|
contents, err := getFileContents(procVersion)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
fields := strings.Fields(contents)
|
|
|
|
if len(fields) < 3 {
|
|
return "", fmt.Errorf("unexpected contents in %v", procVersion)
|
|
}
|
|
|
|
version := fields[2]
|
|
|
|
return version, nil
|
|
}
|
|
|
|
// getDistroDetails returns the distributions name and version string.
|
|
// If it is not possible to determine both values an error is
|
|
// returned.
|
|
func getDistroDetails() (name, version string, err error) {
|
|
files := []string{osRelease, osReleaseClr}
|
|
|
|
for _, file := range files {
|
|
contents, err := getFileContents(file)
|
|
if err != nil {
|
|
if os.IsNotExist(err) {
|
|
continue
|
|
}
|
|
|
|
return "", "", err
|
|
}
|
|
|
|
lines := strings.Split(contents, "\n")
|
|
|
|
for _, line := range lines {
|
|
if strings.HasPrefix(line, "NAME=") {
|
|
fields := strings.Split(line, "=")
|
|
name = strings.Trim(fields[1], `"`)
|
|
} else if strings.HasPrefix(line, "VERSION_ID=") {
|
|
fields := strings.Split(line, "=")
|
|
version = strings.Trim(fields[1], `"`)
|
|
}
|
|
}
|
|
|
|
if name != "" && version != "" {
|
|
return name, version, nil
|
|
}
|
|
}
|
|
|
|
return "", "", fmt.Errorf("failed to find expected fields in one of %v", files)
|
|
}
|
|
|
|
// getCPUDetails returns the vendor and model of the CPU.
|
|
// If it is not possible to determine both values an error is
|
|
// returned.
|
|
func getCPUDetails() (vendor, model string, err error) {
|
|
cpuinfo, err := getCPUInfo(procCPUInfo)
|
|
if err != nil {
|
|
return "", "", err
|
|
}
|
|
|
|
lines := strings.Split(cpuinfo, "\n")
|
|
|
|
for _, line := range lines {
|
|
if strings.HasPrefix(line, "vendor_id") {
|
|
fields := strings.Split(line, ":")
|
|
if len(fields) > 1 {
|
|
vendor = strings.TrimSpace(fields[1])
|
|
}
|
|
} else if strings.HasPrefix(line, "model name") {
|
|
fields := strings.Split(line, ":")
|
|
if len(fields) > 1 {
|
|
model = strings.TrimSpace(fields[1])
|
|
}
|
|
}
|
|
}
|
|
|
|
if vendor != "" && model != "" {
|
|
return vendor, model, nil
|
|
}
|
|
|
|
return "", "", fmt.Errorf("failed to find expected fields in file %v", procCPUInfo)
|
|
}
|
|
|
|
// resolvePath returns the fully resolved and expanded value of the
|
|
// specified path.
|
|
func resolvePath(path string) (string, error) {
|
|
if path == "" {
|
|
return "", fmt.Errorf("path must be specified")
|
|
}
|
|
|
|
absolute, err := filepath.Abs(path)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
resolved, err := filepath.EvalSymlinks(absolute)
|
|
if err != nil {
|
|
if os.IsNotExist(err) {
|
|
// Make the error clearer than the default
|
|
return "", fmt.Errorf("file %v does not exist", absolute)
|
|
}
|
|
|
|
return "", err
|
|
}
|
|
|
|
return resolved, nil
|
|
}
|
|
|
|
// runCommandFull returns the commands space-trimmed standard output and
|
|
// error on success. Note that if the command fails, the requested output will
|
|
// still be returned, along with an error.
|
|
func runCommandFull(args []string, includeStderr bool) (string, error) {
|
|
cmd := exec.Command(args[0], args[1:]...)
|
|
var err error
|
|
var bytes []byte
|
|
|
|
if includeStderr {
|
|
bytes, err = cmd.CombinedOutput()
|
|
} else {
|
|
bytes, err = cmd.Output()
|
|
}
|
|
|
|
trimmed := strings.TrimSpace(string(bytes))
|
|
|
|
return trimmed, err
|
|
}
|
|
|
|
// runCommand returns the commands space-trimmed standard output on success
|
|
func runCommand(args []string) (string, error) {
|
|
return runCommandFull(args, false)
|
|
}
|
|
|
|
// writeFile write data into specified file
|
|
func writeFile(filePath string, data string, fileMode os.FileMode) error {
|
|
// Normally dir should not be empty, one case is that cgroup subsystem
|
|
// is not mounted, we will get empty dir, and we want it fail here.
|
|
if filePath == "" {
|
|
return fmt.Errorf("no such file for %s", filePath)
|
|
}
|
|
|
|
if err := ioutil.WriteFile(filePath, []byte(data), fileMode); err != nil {
|
|
return fmt.Errorf("failed to write %v to %v: %v", data, filePath, err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// isEmptyString return if string is empty
|
|
func isEmptyString(b []byte) bool {
|
|
return len(bytes.Trim(b, "\n")) == 0
|
|
}
|