291 lines
11 KiB
Go
291 lines
11 KiB
Go
/*
|
|
Copyright 2019 The Kubernetes Authors All rights reserved.
|
|
|
|
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 oci
|
|
|
|
import (
|
|
"encoding/json"
|
|
"os/exec"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/pkg/errors"
|
|
"k8s.io/klog/v2"
|
|
)
|
|
|
|
// SysInfo Info represents common system Information between docker and podman that minikube cares
|
|
type SysInfo struct {
|
|
CPUs int // CPUs is Number of CPUs
|
|
TotalMemory int64 // TotalMemory Total available ram
|
|
OSType string // container's OsType (windows or linux)
|
|
Swarm bool // Weather or not the docker swarm is active
|
|
Rootless bool // Weather or not the docker is running on rootless mode
|
|
StorageDriver string // the storage driver for the daemon (for example overlay2)
|
|
Errors []string // any server issues
|
|
DockerOS string // used to detect if using Docker Desktop or Docker Engine on Linux
|
|
}
|
|
|
|
var (
|
|
cachedSysInfo *SysInfo
|
|
cachedSysInfoErr *error
|
|
)
|
|
|
|
// CachedDaemonInfo will run and return a docker/podman info only once per minikube run time. to avoid performance
|
|
var CachedDaemonInfo = func(ociBin string) (SysInfo, error) {
|
|
if cachedSysInfo == nil {
|
|
si, err := DaemonInfo(ociBin)
|
|
cachedSysInfo = &si
|
|
cachedSysInfoErr = &err
|
|
}
|
|
if cachedSysInfoErr == nil {
|
|
return *cachedSysInfo, nil
|
|
}
|
|
return *cachedSysInfo, *cachedSysInfoErr
|
|
}
|
|
|
|
// DaemonInfo returns common docker/podman daemon system info that minikube cares about
|
|
func DaemonInfo(ociBin string) (SysInfo, error) {
|
|
if ociBin == Podman {
|
|
p, err := podmanSystemInfo()
|
|
cachedSysInfo = &SysInfo{CPUs: p.Host.Cpus, TotalMemory: p.Host.MemTotal, OSType: p.Host.Os, Swarm: false, Rootless: p.Host.Security.Rootless, StorageDriver: p.Store.GraphDriverName}
|
|
return *cachedSysInfo, err
|
|
}
|
|
d, err := dockerSystemInfo()
|
|
rootless := false
|
|
for _, se := range d.SecurityOptions {
|
|
if strings.HasPrefix(se, "name=rootless") {
|
|
rootless = true
|
|
break
|
|
}
|
|
}
|
|
cachedSysInfo = &SysInfo{CPUs: d.NCPU, TotalMemory: d.MemTotal, OSType: d.OSType, Swarm: d.Swarm.LocalNodeState == "active", Rootless: rootless, StorageDriver: d.Driver, Errors: d.ServerErrors, DockerOS: d.OperatingSystem}
|
|
return *cachedSysInfo, err
|
|
}
|
|
|
|
// dockerSysInfo represents the output of docker system info --format '{{json .}}'
|
|
type dockerSysInfo struct {
|
|
ID string `json:"ID"`
|
|
Containers int `json:"Containers"`
|
|
ContainersRunning int `json:"ContainersRunning"`
|
|
ContainersPaused int `json:"ContainersPaused"`
|
|
ContainersStopped int `json:"ContainersStopped"`
|
|
Images int `json:"Images"`
|
|
Driver string `json:"Driver"`
|
|
DriverStatus [][]string `json:"DriverStatus"`
|
|
SystemStatus interface{} `json:"SystemStatus"`
|
|
Plugins struct {
|
|
Volume []string `json:"Volume"`
|
|
Network []string `json:"Network"`
|
|
Authorization interface{} `json:"Authorization"`
|
|
Log []string `json:"Log"`
|
|
} `json:"Plugins"`
|
|
MemoryLimit bool `json:"MemoryLimit"`
|
|
SwapLimit bool `json:"SwapLimit"`
|
|
KernelMemory bool `json:"KernelMemory"`
|
|
KernelMemoryTCP bool `json:"KernelMemoryTCP"`
|
|
CPUCfsPeriod bool `json:"CpuCfsPeriod"`
|
|
CPUCfsQuota bool `json:"CpuCfsQuota"`
|
|
CPUShares bool `json:"CPUShares"`
|
|
CPUSet bool `json:"CPUSet"`
|
|
PidsLimit bool `json:"PidsLimit"`
|
|
IPv4Forwarding bool `json:"IPv4Forwarding"`
|
|
BridgeNfIptables bool `json:"BridgeNfIptables"`
|
|
BridgeNfIP6Tables bool `json:"BridgeNfIp6tables"`
|
|
Debug bool `json:"Debug"`
|
|
NFd int `json:"NFd"`
|
|
OomKillDisable bool `json:"OomKillDisable"`
|
|
NGoroutines int `json:"NGoroutines"`
|
|
SystemTime time.Time `json:"SystemTime"`
|
|
LoggingDriver string `json:"LoggingDriver"`
|
|
CgroupDriver string `json:"CgroupDriver"`
|
|
NEventsListener int `json:"NEventsListener"`
|
|
KernelVersion string `json:"KernelVersion"`
|
|
OperatingSystem string `json:"OperatingSystem"`
|
|
OSType string `json:"OSType"`
|
|
Architecture string `json:"Architecture"`
|
|
IndexServerAddress string `json:"IndexServerAddress"`
|
|
RegistryConfig struct {
|
|
AllowNondistributableArtifactsCIDRs []interface{} `json:"AllowNondistributableArtifactsCIDRs"`
|
|
AllowNondistributableArtifactsHostnames []interface{} `json:"AllowNondistributableArtifactsHostnames"`
|
|
InsecureRegistryCIDRs []string `json:"InsecureRegistryCIDRs"`
|
|
IndexConfigs struct {
|
|
DockerIo struct {
|
|
Name string `json:"Name"`
|
|
Mirrors []interface{} `json:"Mirrors"`
|
|
Secure bool `json:"Secure"`
|
|
Official bool `json:"Official"`
|
|
} `json:"docker.io"`
|
|
} `json:"IndexConfigs"`
|
|
Mirrors []interface{} `json:"Mirrors"`
|
|
} `json:"RegistryConfig"`
|
|
NCPU int `json:"NCPU"`
|
|
MemTotal int64 `json:"MemTotal"`
|
|
GenericResources interface{} `json:"GenericResources"`
|
|
DockerRootDir string `json:"DockerRootDir"`
|
|
HTTPProxy string `json:"HttpProxy"`
|
|
HTTPSProxy string `json:"HttpsProxy"`
|
|
NoProxy string `json:"NoProxy"`
|
|
Name string `json:"Name"`
|
|
Labels []interface{} `json:"Labels"`
|
|
ExperimentalBuild bool `json:"ExperimentalBuild"`
|
|
ServerVersion string `json:"ServerVersion"`
|
|
ClusterStore string `json:"ClusterStore"`
|
|
ClusterAdvertise string `json:"ClusterAdvertise"`
|
|
Runtimes struct {
|
|
Runc struct {
|
|
Path string `json:"path"`
|
|
} `json:"runc"`
|
|
} `json:"Runtimes"`
|
|
DefaultRuntime string `json:"DefaultRuntime"`
|
|
Swarm struct {
|
|
NodeID string `json:"NodeID"`
|
|
NodeAddr string `json:"NodeAddr"`
|
|
LocalNodeState string `json:"LocalNodeState"`
|
|
ControlAvailable bool `json:"ControlAvailable"`
|
|
Error string `json:"Error"`
|
|
RemoteManagers interface{} `json:"RemoteManagers"`
|
|
} `json:"Swarm"`
|
|
LiveRestoreEnabled bool `json:"LiveRestoreEnabled"`
|
|
Isolation string `json:"Isolation"`
|
|
InitBinary string `json:"InitBinary"`
|
|
ContainerdCommit struct {
|
|
ID string `json:"ID"`
|
|
Expected string `json:"Expected"`
|
|
} `json:"ContainerdCommit"`
|
|
RuncCommit struct {
|
|
ID string `json:"ID"`
|
|
Expected string `json:"Expected"`
|
|
} `json:"RuncCommit"`
|
|
InitCommit struct {
|
|
ID string `json:"ID"`
|
|
Expected string `json:"Expected"`
|
|
} `json:"InitCommit"`
|
|
SecurityOptions []string `json:"SecurityOptions"`
|
|
ProductLicense string `json:"ProductLicense"`
|
|
Warnings interface{} `json:"Warnings"`
|
|
ServerErrors []string
|
|
ClientInfo struct {
|
|
Debug bool `json:"Debug"`
|
|
Plugins []interface{} `json:"Plugins"`
|
|
Warnings interface{} `json:"Warnings"`
|
|
} `json:"ClientInfo"`
|
|
}
|
|
|
|
// podmanSysInfo represents the output of podman system info --format '{{json .}}'
|
|
type podmanSysInfo struct {
|
|
Host struct {
|
|
BuildahVersion string `json:"BuildahVersion"`
|
|
CgroupVersion string `json:"CgroupVersion"`
|
|
Conmon struct {
|
|
Package string `json:"package"`
|
|
Path string `json:"path"`
|
|
Version string `json:"version"`
|
|
} `json:"Conmon"`
|
|
Distribution struct {
|
|
Distribution string `json:"distribution"`
|
|
Version string `json:"version"`
|
|
} `json:"Distribution"`
|
|
MemFree int `json:"MemFree"`
|
|
MemTotal int64 `json:"MemTotal"`
|
|
OCIRuntime struct {
|
|
Name string `json:"name"`
|
|
Package string `json:"package"`
|
|
Path string `json:"path"`
|
|
Version string `json:"version"`
|
|
} `json:"OCIRuntime"`
|
|
SwapFree int `json:"SwapFree"`
|
|
SwapTotal int `json:"SwapTotal"`
|
|
Arch string `json:"arch"`
|
|
Cpus int `json:"cpus"`
|
|
Eventlogger string `json:"eventlogger"`
|
|
Hostname string `json:"hostname"`
|
|
Kernel string `json:"kernel"`
|
|
Os string `json:"os"`
|
|
Security struct {
|
|
Rootless bool `json:"rootless"`
|
|
} `json:"security"`
|
|
Uptime string `json:"uptime"`
|
|
} `json:"host"`
|
|
Registries struct {
|
|
Search []string `json:"search"`
|
|
} `json:"registries"`
|
|
Store struct {
|
|
ConfigFile string `json:"ConfigFile"`
|
|
ContainerStore struct {
|
|
Number int `json:"number"`
|
|
} `json:"ContainerStore"`
|
|
GraphDriverName string `json:"GraphDriverName"`
|
|
GraphOptions struct {
|
|
} `json:"GraphOptions"`
|
|
GraphRoot string `json:"GraphRoot"`
|
|
GraphStatus struct {
|
|
BackingFilesystem string `json:"Backing Filesystem"`
|
|
NativeOverlayDiff string `json:"Native Overlay Diff"`
|
|
SupportsDType string `json:"Supports d_type"`
|
|
UsingMetacopy string `json:"Using metacopy"`
|
|
} `json:"GraphStatus"`
|
|
ImageStore struct {
|
|
Number int `json:"number"`
|
|
} `json:"ImageStore"`
|
|
RunRoot string `json:"RunRoot"`
|
|
VolumePath string `json:"VolumePath"`
|
|
} `json:"store"`
|
|
}
|
|
|
|
var dockerInfoGetter = func() (string, error) {
|
|
rr, err := runCmd(exec.Command(Docker, "system", "info", "--format", "{{json .}}"))
|
|
return rr.Stdout.String(), err
|
|
}
|
|
|
|
// dockerSystemInfo returns docker system info --format '{{json .}}'
|
|
func dockerSystemInfo() (dockerSysInfo, error) {
|
|
var ds dockerSysInfo
|
|
rawJSON, err := dockerInfoGetter()
|
|
if err != nil {
|
|
klog.Warningf("docker info: %v", err)
|
|
return ds, errors.Wrap(err, "docker system info")
|
|
}
|
|
if err := json.Unmarshal([]byte(strings.TrimSpace(rawJSON)), &ds); err != nil {
|
|
klog.Warningf("unmarshal docker info: %v", err)
|
|
return ds, errors.Wrapf(err, "unmarshal docker system info")
|
|
}
|
|
|
|
klog.Infof("docker info: %+v", ds)
|
|
return ds, nil
|
|
}
|
|
|
|
var podmanInfoGetter = func() (string, error) {
|
|
rr, err := runCmd(exec.Command(Podman, "system", "info", "--format", "json"))
|
|
return rr.Stdout.String(), err
|
|
}
|
|
|
|
// podmanSystemInfo returns podman system info --format '{{json .}}'
|
|
func podmanSystemInfo() (podmanSysInfo, error) {
|
|
var ps podmanSysInfo
|
|
rawJSON, err := podmanInfoGetter()
|
|
if err != nil {
|
|
klog.Warningf("podman info: %v", err)
|
|
return ps, errors.Wrap(err, "podman system info")
|
|
}
|
|
|
|
if err := json.Unmarshal([]byte(strings.TrimSpace(rawJSON)), &ps); err != nil {
|
|
klog.Warningf("unmarshal podman info: %v", err)
|
|
return ps, errors.Wrapf(err, "unmarshal podman system info")
|
|
}
|
|
klog.Infof("podman info: %+v", ps)
|
|
return ps, nil
|
|
}
|