Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/source/markdown/podman-info.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ podman\-info - Display Podman related system information
## DESCRIPTION

Displays information pertinent to the host, current storage stats, configured container registries, and build of podman.
Host information includes configured CDI spec directories and resolved CDI devices when present.


## OPTIONS
Expand Down
8 changes: 8 additions & 0 deletions libpod/define/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ type HostInfo struct {
CgroupManager string `json:"cgroupManager"`
CgroupsVersion string `json:"cgroupVersion"`
CgroupControllers []string `json:"cgroupControllers"`
CDISpecDirs []string `json:"cdiSpecDirs"`
DiscoveredDevices []DeviceInfo `json:"discoveredDevices,omitempty"`
Conmon *ConmonInfo `json:"conmon"`
CPUs int `json:"cpus"`
CPUUtilization *CPUUsage `json:"cpuUtilization"`
Expand Down Expand Up @@ -69,6 +71,12 @@ type HostInfo struct {
EmulatedArchitectures []string `json:"emulatedArchitectures,omitempty"`
}

// DeviceInfo describes a device discovered by a device source.
type DeviceInfo struct {
Source string `json:"source"`
ID string `json:"id"`
}

// RemoteSocket describes information about the API socket
type RemoteSocket struct {
Path string `json:"path,omitempty"`
Expand Down
29 changes: 29 additions & 0 deletions libpod/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"go.podman.io/podman/v6/libpod/define"
"go.podman.io/podman/v6/libpod/linkmode"
"go.podman.io/storage/pkg/system"
"tags.cncf.io/container-device-interface/pkg/cdi"
)

// Info returns the store and host information
Expand Down Expand Up @@ -129,6 +130,7 @@ func (r *Runtime) hostInfo() (*define.HostInfo, error) {
SwapFree: mi.SwapFree,
SwapTotal: mi.SwapTotal,
}
info.CDISpecDirs, info.DiscoveredDevices = r.cdiInfo()
platform := parse.DefaultPlatform()
pArr := strings.Split(platform, "/")
if len(pArr) == 3 {
Expand Down Expand Up @@ -176,6 +178,33 @@ func (r *Runtime) hostInfo() (*define.HostInfo, error) {
return &info, nil
}

func (r *Runtime) cdiInfo() ([]string, []define.DeviceInfo) {
registry, err := cdi.NewCache(
cdi.WithSpecDirs(r.config.Engine.CdiSpecDirs.Get()...),
cdi.WithAutoRefresh(false),
)
if err != nil {
logrus.Debugf("Creating CDI registry for info: %v", err)
return r.config.Engine.CdiSpecDirs.Get(), nil
}
if err := registry.Refresh(); err != nil {
logrus.Debugf("The following error was triggered when refreshing the CDI registry for info: %v", err)
}

return registry.GetSpecDirectories(), cdiDeviceInfo(registry.ListDevices())
}

func cdiDeviceInfo(deviceNames []string) []define.DeviceInfo {
devices := make([]define.DeviceInfo, 0, len(deviceNames))
for _, device := range deviceNames {
devices = append(devices, define.DeviceInfo{
Source: "cdi",
ID: device,
})
}
return devices
}

func (r *Runtime) getContainerStoreInfo() (define.ContainerStore, error) {
var paused, running, stopped int
cs := define.ContainerStore{}
Expand Down
13 changes: 13 additions & 0 deletions pkg/api/handlers/compat/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ func GetInfo(w http.ResponseWriter, r *http.Request) {
CPUSet: sysInfo.Cpuset,
CPUShares: sysInfo.CPUShares,
CgroupDriver: configInfo.Engine.CgroupManager,
CDISpecDirs: infoData.Host.CDISpecDirs,
ContainerdCommit: dockerSystem.Commit{},
Containers: infoData.Store.ContainerStore.Number,
ContainersPaused: stateInfo[define.ContainerStatePaused],
Expand All @@ -70,6 +71,7 @@ func GetInfo(w http.ResponseWriter, r *http.Request) {
Debug: log.IsLevelEnabled(log.DebugLevel),
DefaultAddressPools: getDefaultAddressPools(configInfo),
DefaultRuntime: configInfo.Engine.OCIRuntime,
DiscoveredDevices: getDiscoveredDevices(infoData.Host.DiscoveredDevices),
DockerRootDir: infoData.Store.GraphRoot,
Driver: infoData.Store.GraphDriverName,
DriverStatus: getGraphStatus(infoData.Store.GraphStatus),
Expand Down Expand Up @@ -132,6 +134,17 @@ func GetInfo(w http.ResponseWriter, r *http.Request) {
utils.WriteResponse(w, http.StatusOK, info)
}

func getDiscoveredDevices(discoveredDevices []define.DeviceInfo) []dockerSystem.DeviceInfo {
devices := make([]dockerSystem.DeviceInfo, 0, len(discoveredDevices))
for _, device := range discoveredDevices {
devices = append(devices, dockerSystem.DeviceInfo{
Source: device.Source,
ID: device.ID,
})
}
return devices
}

func getServiceConfig(runtime *libpod.Runtime) *registry.ServiceConfig {
var indexConfs map[string]*registry.IndexInfo

Expand Down
35 changes: 35 additions & 0 deletions test/e2e/info_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,41 @@ var _ = Describe("Podman Info", func() {
Expect(session.OutputToString()).To(Equal(customNetName))
})

It("Podman info: check CDI spec dirs and devices from configuration", func() {
cdiDir := filepath.Join(podmanTest.TempDir, "cdi")
err := os.MkdirAll(cdiDir, os.ModePerm)
Expect(err).ToNot(HaveOccurred())

cdiSpec := []byte(`{
"cdiVersion": "0.3.0",
"kind": "vendor.com/device",
"devices": [
{
"name": "myKmsg",
"containerEdits": {
"env": ["PODMAN_CDI_INFO_TEST=1"]
}
}
]
}`)
err = os.WriteFile(filepath.Join(cdiDir, "device.json"), cdiSpec, os.ModePerm)
Expect(err).ToNot(HaveOccurred())

configPath := filepath.Join(podmanTest.TempDir, "containers.conf")
configContent := fmt.Sprintf("[engine]\ncdi_spec_dirs = [%q]\n", cdiDir)
err = os.WriteFile(configPath, []byte(configContent), os.ModePerm)
Expect(err).ToNot(HaveOccurred())

os.Setenv("CONTAINERS_CONF_OVERRIDE", configPath)
podmanTest.RestartRemoteService()

session := podmanTest.Podman([]string{"info", "--format", "{{.Host.CDISpecDirs}} {{.Host.DiscoveredDevices}}"})
session.WaitWithDefaultTimeout()
Expect(session).To(ExitCleanly())
Expect(session.OutputToString()).To(ContainSubstring(cdiDir))
Expect(session.OutputToString()).To(ContainSubstring("vendor.com/device=myKmsg"))
})

It("Podman info: check desired storage driver", func() {
// defined in .cirrus.yml
want := os.Getenv("CI_DESIRED_STORAGE")
Expand Down
31 changes: 31 additions & 0 deletions test/system/005-info.bats
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,37 @@ store.imageStore.number | 1
done < <(parse_table "$tests")
}

@test "podman info - CDI spec dirs and devices" {
skip_if_remote "--cdi-spec-dir flag is not supported for remote"

cdi_dir=$PODMAN_TMPDIR/cdi
mkdir -p "$cdi_dir"
cat >"$cdi_dir/device.json" <<EOF
{
"cdiVersion": "0.3.0",
"kind": "vendor.com/device",
"devices": [
{
"name": "myKmsg",
"containerEdits": {
"env": ["PODMAN_CDI_INFO_TEST=1"]
}
}
]
}
EOF

run_podman --cdi-spec-dir "$cdi_dir" info --format=json
cdi_spec_dirs=$(echo "$output" | jq -r '.host.cdiSpecDirs[]')
cdi_devices=$(echo "$output" | jq -r '.host.discoveredDevices[] | select(.source == "cdi") | .id')
assert "$cdi_spec_dirs" =~ "$cdi_dir" "info includes configured CDI spec dir"
assert "$cdi_devices" =~ "vendor.com/device=myKmsg" "info includes resolved CDI device"

run_podman --cdi-spec-dir "$cdi_dir" system info --format '{{.Host.CDISpecDirs}} {{.Host.DiscoveredDevices}}'
assert "$output" =~ "$cdi_dir" "system info includes configured CDI spec dir"
assert "$output" =~ "vendor.com/device=myKmsg" "system info includes resolved CDI device"
}

@test "podman info - confirm desired runtime" {
if [[ -z "$CI_DESIRED_RUNTIME" ]]; then
# When running in Cirrus, CI_DESIRED_RUNTIME *must* be defined
Expand Down