Fixed segfault in stats where container had netNS none or from container

Signed-off-by: haircommander <pehunt@redhat.com>

Closes: #1306
Approved by: rhatdan
This commit is contained in:
haircommander 2018-08-20 18:24:35 -04:00 committed by Atomic Bot
parent 021027a24b
commit 149481a571
3 changed files with 58 additions and 3 deletions

View File

@ -249,9 +249,35 @@ func (r *Runtime) teardownNetNS(ctr *Container) error {
return nil
}
func getContainerNetNS(ctr *Container) (string, error) {
if ctr.state.NetNS != nil {
return ctr.state.NetNS.Path(), nil
}
if ctr.config.NetNsCtr != "" {
c, err := ctr.runtime.GetContainer(ctr.config.NetNsCtr)
if err != nil {
return "", err
}
if err = c.syncContainer(); err != nil {
return "", err
}
return c.state.NetNS.Path(), nil
}
return "", nil
}
func getContainerNetIO(ctr *Container) (*netlink.LinkStatistics, error) {
var netStats *netlink.LinkStatistics
err := ns.WithNetNSPath(ctr.state.NetNS.Path(), func(_ ns.NetNS) error {
netNSPath, netPathErr := getContainerNetNS(ctr)
if netPathErr != nil {
return nil, netPathErr
}
if netNSPath == "" {
// If netNSPath is empty, it was set as none, and no netNS was set up
// this is a valid state and thus return no error, nor any statistics
return nil, nil
}
err := ns.WithNetNSPath(netNSPath, func(_ ns.NetNS) error {
link, err := netlink.LinkByName(ocicni.DefaultInterfaceName)
if err != nil {
return err

View File

@ -66,8 +66,14 @@ func (c *Container) GetContainerStats(previousStats *ContainerStats) (*Container
stats.BlockInput, stats.BlockOutput = calculateBlockIO(cgroupStats)
stats.CPUNano = cgroupStats.CPU.Usage.Total
stats.SystemNano = cgroupStats.CPU.Usage.Kernel
stats.NetInput = netStats.TxBytes
stats.NetOutput = netStats.RxBytes
// Handle case where the container is not in a network namespace
if netStats != nil {
stats.NetInput = netStats.TxBytes
stats.NetOutput = netStats.RxBytes
} else {
stats.NetInput = 0
stats.NetOutput = 0
}
return stats, nil
}

View File

@ -90,4 +90,27 @@ var _ = Describe("Podman stats", func() {
Expect(session.IsJSONOutputValid()).To(BeTrue())
})
It("podman stats on a container with no net ns", func() {
session := podmanTest.Podman([]string{"run", "-d", "--net", "none", ALPINE, "top"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
session = podmanTest.Podman([]string{"stats", "--no-stream", "-a"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
})
It("podman stats on a container that joined another's net ns", func() {
session := podmanTest.RunTopContainer("")
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
cid := session.OutputToString()
session = podmanTest.Podman([]string{"run", "-d", "--net", fmt.Sprintf("container:%s", cid), ALPINE, "top"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
session = podmanTest.Podman([]string{"stats", "--no-stream", "-a"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
})
})