Skip to content

Commit ce6f39a

Browse files
author
Paweł Szulik
committed
podman handler: Work in progress.
Signed-off-by: Paweł Szulik <pawel.szulik@intel.com>
1 parent 5cfac3f commit ce6f39a

File tree

23 files changed

+2697
-146
lines changed

23 files changed

+2697
-146
lines changed

cmd/go.mod

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,11 @@ require (
1919
github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7
2020
github.com/influxdb/influxdb v0.9.6-0.20151125225445-9eab56311373
2121
github.com/mesos/mesos-go v0.0.7-0.20180413204204-29de6ff97b48
22-
github.com/pquerna/ffjson v0.0.0-20171002144729-d49c2bc1aa13 // indirect
2322
github.com/prometheus/client_golang v1.8.0
2423
github.com/stretchr/testify v1.7.0
25-
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43
26-
google.golang.org/api v0.34.0
24+
golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602
25+
google.golang.org/api v0.44.0
2726
gopkg.in/olivere/elastic.v2 v2.0.12
28-
k8s.io/klog/v2 v2.4.0
27+
k8s.io/klog/v2 v2.9.0
2928
k8s.io/utils v0.0.0-20201110183641-67b214c5f920
3029
)

cmd/go.sum

Lines changed: 830 additions & 48 deletions
Large diffs are not rendered by default.

cmd/internal/container/install/install.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,6 @@ import (
2121
_ "github.com/google/cadvisor/container/containerd/install"
2222
_ "github.com/google/cadvisor/container/crio/install"
2323
_ "github.com/google/cadvisor/container/docker/install"
24+
_ "github.com/google/cadvisor/container/podman/install"
2425
_ "github.com/google/cadvisor/container/systemd/install"
2526
)

cmd/internal/pages/assets/html/containers.html

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ <h1>{{.DisplayName}}</h1>
5050
<div class="col-sm-12">
5151
<h4><a href="../docker">Docker Containers</a></h4>
5252
</div>
53+
<div class="col-sm-12">
54+
<h4><a href="../podman">Podman Containers</a></h4>
55+
</div>
5356
{{end}}
5457
{{if .Subcontainers}}
5558
<div class="col-sm-12">

cmd/internal/pages/docker.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,12 @@ func toStatusKV(status info.DockerStatus) ([]keyVal, []keyVal) {
3939
ds = append(ds, keyVal{Key: k, Value: v})
4040
}
4141
return []keyVal{
42-
{Key: "Docker Version", Value: status.Version},
43-
{Key: "Docker API Version", Value: status.APIVersion},
42+
{Key: "Version", Value: status.Version},
43+
{Key: "API Version", Value: status.APIVersion},
4444
{Key: "Kernel Version", Value: status.KernelVersion},
4545
{Key: "OS Version", Value: status.OS},
4646
{Key: "Host Name", Value: status.Hostname},
47-
{Key: "Docker Root Directory", Value: status.RootDir},
47+
{Key: "Root Directory", Value: status.RootDir},
4848
{Key: "Execution Driver", Value: status.ExecDriver},
4949
{Key: "Number of Images", Value: strconv.Itoa(status.NumImages)},
5050
{Key: "Number of Containers", Value: strconv.Itoa(status.NumContainers)},

cmd/internal/pages/pages.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,12 @@ func dockerHandler(containerManager manager.Manager) auth.AuthenticatedHandlerFu
9999
}
100100
}
101101

102+
func podmanHandlerNoAuth(containerManager manager.Manager) http.HandlerFunc {
103+
return func(w http.ResponseWriter, r *http.Request) {
104+
servePodmanPage(containerManager, w, r.URL)
105+
}
106+
}
107+
102108
// Register http handlers
103109
func RegisterHandlersDigest(mux httpmux.Mux, containerManager manager.Manager, authenticator *auth.DigestAuth, urlBasePrefix string) error {
104110
// Register the handler for the containers page.
@@ -127,9 +133,11 @@ func RegisterHandlersBasic(mux httpmux.Mux, containerManager manager.Manager, au
127133
if authenticator != nil {
128134
mux.HandleFunc(ContainersPage, authenticator.Wrap(containerHandler(containerManager)))
129135
mux.HandleFunc(DockerPage, authenticator.Wrap(dockerHandler(containerManager)))
136+
// TODO (Creatone): Add Podman.
130137
} else {
131138
mux.HandleFunc(ContainersPage, containerHandlerNoAuth(containerManager))
132139
mux.HandleFunc(DockerPage, dockerHandlerNoAuth(containerManager))
140+
mux.HandleFunc(PodmanPage, podmanHandlerNoAuth(containerManager))
133141
}
134142

135143
if ContainersPage[len(ContainersPage)-1] == '/' {

cmd/internal/pages/podman.go

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
// Copyright 2021 Google Inc. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package pages
16+
17+
import (
18+
"fmt"
19+
"net/http"
20+
"net/url"
21+
"path"
22+
"time"
23+
24+
"github.com/google/cadvisor/container/podman"
25+
info "github.com/google/cadvisor/info/v1"
26+
"github.com/google/cadvisor/manager"
27+
28+
"k8s.io/klog/v2"
29+
)
30+
31+
const PodmanPage = "/podman/"
32+
33+
func servePodmanPage(m manager.Manager, w http.ResponseWriter, u *url.URL) {
34+
start := time.Now()
35+
36+
containerName := u.Path[len(PodmanPage)-1:]
37+
rootDir := getRootDir(containerName)
38+
39+
var data *pageData
40+
41+
if containerName == "/" {
42+
// Scenario for all containers.
43+
reqParams := info.ContainerInfoRequest{
44+
NumStats: 0,
45+
}
46+
conts, err := m.AllPodmanContainers(&reqParams)
47+
if err != nil {
48+
http.Error(w, fmt.Sprintf("failed to get container %q with error: %v", containerName, err), http.StatusNotFound)
49+
return
50+
}
51+
subcontainers := make([]link, 0, len(conts))
52+
for _, cont := range conts {
53+
subcontainers = append(subcontainers, link{
54+
Text: getContainerDisplayName(cont.ContainerReference),
55+
Link: path.Join(rootDir, PodmanPage, podman.ContainerNameToPodmanID(cont.ContainerReference.Name)),
56+
})
57+
}
58+
59+
// Get Podman status
60+
status, err := podman.Status()
61+
if err != nil {
62+
http.Error(w, fmt.Sprintf("failed to get docker info: %v", err), http.StatusInternalServerError)
63+
return
64+
}
65+
66+
podmanStatus, driverStatus := toStatusKV(info.DockerStatus(status))
67+
// Get Podman Images
68+
images, err := podman.Images()
69+
if err != nil {
70+
http.Error(w, fmt.Sprintf("failed to get podman images: %v", err), http.StatusInternalServerError)
71+
return
72+
}
73+
74+
podmanContainerText := "Podman Containers"
75+
data = &pageData{
76+
DisplayName: podmanContainerText,
77+
ParentContainers: []link{
78+
{
79+
Text: podmanContainerText,
80+
Link: path.Join(rootDir, PodmanPage),
81+
}},
82+
Subcontainers: subcontainers,
83+
Root: rootDir,
84+
DockerStatus: podmanStatus,
85+
DockerDriverStatus: driverStatus,
86+
DockerImages: images,
87+
}
88+
} else {
89+
// Scenario for specific container.
90+
reqParams := info.ContainerInfoRequest{
91+
NumStats: 60,
92+
}
93+
cont, err := m.PodmanContainer(containerName[1:], &reqParams)
94+
if err != nil {
95+
http.Error(w, fmt.Sprintf("failed to get container %v with error: %v", containerName, err), http.StatusNotFound)
96+
return
97+
}
98+
displayName := getContainerDisplayName(cont.ContainerReference)
99+
100+
var parentContainers []link
101+
parentContainers = append(parentContainers, link{
102+
Text: "Podman Containers",
103+
Link: path.Join(rootDir, PodmanPage),
104+
})
105+
parentContainers = append(parentContainers, link{
106+
Text: displayName,
107+
Link: path.Join(rootDir, PodmanPage, podman.ContainerNameToPodmanID(cont.Name)),
108+
})
109+
110+
machineInfo, err := m.GetMachineInfo()
111+
if err != nil {
112+
http.Error(w, fmt.Sprintf("failed to get machine info: %v", err), http.StatusInternalServerError)
113+
return
114+
}
115+
data = &pageData{
116+
DisplayName: displayName,
117+
ContainerName: escapeContainerName(cont.Name),
118+
ParentContainers: parentContainers,
119+
Spec: cont.Spec,
120+
Stats: cont.Stats,
121+
MachineInfo: machineInfo,
122+
ResourcesAvailable: cont.Spec.HasCpu || cont.Spec.HasMemory || cont.Spec.HasNetwork,
123+
CpuAvailable: cont.Spec.HasCpu,
124+
MemoryAvailable: cont.Spec.HasMemory,
125+
NetworkAvailable: cont.Spec.HasNetwork,
126+
FsAvailable: cont.Spec.HasFilesystem,
127+
CustomMetricsAvailable: cont.Spec.HasCustomMetrics,
128+
Root: rootDir,
129+
}
130+
}
131+
132+
err := pageTemplate.Execute(w, data)
133+
if err != nil {
134+
klog.Errorf("Failed to apply template: %s", err)
135+
}
136+
137+
klog.V(5).Infof("Request took %s", time.Since(start))
138+
}

cmd/internal/pages/templates.go

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

container/container.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ const (
3535
ContainerTypeCrio
3636
ContainerTypeContainerd
3737
ContainerTypeMesos
38+
ContainerTypePodman
3839
)
3940

4041
// Interface for container operation handlers.

container/docker/fs.go

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
package docker
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/google/cadvisor/container"
7+
"github.com/google/cadvisor/container/common"
8+
"github.com/google/cadvisor/fs"
9+
info "github.com/google/cadvisor/info/v1"
10+
11+
"k8s.io/klog/v2"
12+
)
13+
14+
func GetFsStats(
15+
stats *info.ContainerStats,
16+
machineInfoFactory info.MachineInfoFactory,
17+
metrics container.MetricSet,
18+
storageDriver storageDriver,
19+
fsHandler common.FsHandler,
20+
globalFsInfo fs.FsInfo,
21+
poolName string,
22+
rootfsStorageDir string,
23+
zfsParent string,
24+
) error {
25+
mi, err := machineInfoFactory.GetMachineInfo()
26+
if err != nil {
27+
return err
28+
}
29+
30+
if metrics.Has(container.DiskIOMetrics) {
31+
common.AssignDeviceNamesToDiskStats((*common.MachineInfoNamer)(mi), &stats.DiskIo)
32+
}
33+
34+
if metrics.Has(container.DiskUsageMetrics) {
35+
var device string
36+
switch storageDriver {
37+
case devicemapperStorageDriver:
38+
device = poolName
39+
case aufsStorageDriver, overlayStorageDriver, overlay2StorageDriver, vfsStorageDriver:
40+
deviceInfo, err := globalFsInfo.GetDirFsDevice(rootfsStorageDir)
41+
if err != nil {
42+
return fmt.Errorf("unable to determine device info for dir: %v: %v", rootfsStorageDir, err)
43+
}
44+
device = deviceInfo.Device
45+
case zfsStorageDriver:
46+
device = zfsParent
47+
default:
48+
return nil
49+
}
50+
51+
var (
52+
limit uint64
53+
fsType string
54+
)
55+
56+
var fsInfo *info.FsInfo
57+
58+
for _, fs := range mi.Filesystems {
59+
if fs.Device == device {
60+
limit = fs.Capacity
61+
fsType = fs.Type
62+
fsInfo = &fs
63+
break
64+
}
65+
}
66+
67+
fsStat := info.FsStats{Device: device, Type: fsType, Limit: limit}
68+
usage := fsHandler.Usage()
69+
fsStat.BaseUsage = usage.BaseUsageBytes
70+
fsStat.Usage = usage.TotalUsageBytes
71+
fsStat.Inodes = usage.InodeUsage
72+
73+
if fsInfo != nil {
74+
fileSystems, err := globalFsInfo.GetGlobalFsInfo()
75+
76+
if err == nil {
77+
addDiskStats(fileSystems, fsInfo, &fsStat)
78+
} else {
79+
klog.Errorf("Unable to obtain diskstats for filesystem %s: %v", fsStat.Device, err)
80+
}
81+
}
82+
83+
stats.Filesystem = append(stats.Filesystem, fsStat)
84+
}
85+
86+
return nil
87+
}
88+
89+
func addDiskStats(fileSystems []fs.Fs, fsInfo *info.FsInfo, fsStats *info.FsStats) {
90+
if fsInfo == nil {
91+
return
92+
}
93+
94+
for _, fileSys := range fileSystems {
95+
if fsInfo.DeviceMajor == fileSys.DiskStats.Major &&
96+
fsInfo.DeviceMinor == fileSys.DiskStats.Minor {
97+
fsStats.ReadsCompleted = fileSys.DiskStats.ReadsCompleted
98+
fsStats.ReadsMerged = fileSys.DiskStats.ReadsMerged
99+
fsStats.SectorsRead = fileSys.DiskStats.SectorsRead
100+
fsStats.ReadTime = fileSys.DiskStats.ReadTime
101+
fsStats.WritesCompleted = fileSys.DiskStats.WritesCompleted
102+
fsStats.WritesMerged = fileSys.DiskStats.WritesMerged
103+
fsStats.SectorsWritten = fileSys.DiskStats.SectorsWritten
104+
fsStats.WriteTime = fileSys.DiskStats.WriteTime
105+
fsStats.IoInProgress = fileSys.DiskStats.IoInProgress
106+
fsStats.IoTime = fileSys.DiskStats.IoTime
107+
fsStats.WeightedIoTime = fileSys.DiskStats.WeightedIoTime
108+
break
109+
}
110+
}
111+
}

0 commit comments

Comments
 (0)