Browse code

Fix docker stats missing memory limit

Signed-off-by: Lei Jitang <leijitang@huawei.com>

Lei Jitang authored on 2016/04/08 11:09:07
Showing 3 changed files
... ...
@@ -1098,6 +1098,11 @@ func (daemon *Daemon) stats(c *container.Container) (*types.StatsJSON, error) {
1098 1098
 			MaxUsage: mem.MaxUsage,
1099 1099
 			Stats:    cgs.MemoryStats.Stats,
1100 1100
 			Failcnt:  mem.Failcnt,
1101
+			Limit:    mem.Limit,
1102
+		}
1103
+		// if the container does not set memory limit, use the machineMemory
1104
+		if mem.Limit > daemon.statsCollector.machineMemory && daemon.statsCollector.machineMemory > 0 {
1105
+			s.MemoryStats.Limit = daemon.statsCollector.machineMemory
1101 1106
 		}
1102 1107
 		if cgs.PidsStats != nil {
1103 1108
 			s.PidsStats = types.PidsStats{
... ...
@@ -14,6 +14,7 @@ import (
14 14
 	"github.com/Sirupsen/logrus"
15 15
 	"github.com/docker/docker/container"
16 16
 	"github.com/docker/docker/pkg/pubsub"
17
+	sysinfo "github.com/docker/docker/pkg/system"
17 18
 	"github.com/docker/engine-api/types"
18 19
 	"github.com/opencontainers/runc/libcontainer/system"
19 20
 )
... ...
@@ -35,6 +36,11 @@ func (daemon *Daemon) newStatsCollector(interval time.Duration) *statsCollector
35 35
 		clockTicksPerSecond: uint64(system.GetClockTicks()),
36 36
 		bufReader:           bufio.NewReaderSize(nil, 128),
37 37
 	}
38
+	meminfo, err := sysinfo.ReadMemInfo()
39
+	if err == nil && meminfo.MemTotal > 0 {
40
+		s.machineMemory = uint64(meminfo.MemTotal)
41
+	}
42
+
38 43
 	go s.run()
39 44
 	return s
40 45
 }
... ...
@@ -47,6 +53,7 @@ type statsCollector struct {
47 47
 	clockTicksPerSecond uint64
48 48
 	publishers          map[*container.Container]*pubsub.Publisher
49 49
 	bufReader           *bufio.Reader
50
+	machineMemory       uint64
50 51
 }
51 52
 
52 53
 // collect registers the container with the collector and adds it to
... ...
@@ -227,3 +227,31 @@ func (s *DockerSuite) TestApiStatsContainerNotFound(c *check.C) {
227 227
 	c.Assert(err, checker.IsNil)
228 228
 	c.Assert(status, checker.Equals, http.StatusNotFound)
229 229
 }
230
+
231
+func (s *DockerSuite) TestApiStatsContainerGetMemoryLimit(c *check.C) {
232
+	testRequires(c, DaemonIsLinux)
233
+
234
+	resp, body, err := sockRequestRaw("GET", "/info", nil, "application/json")
235
+	c.Assert(err, checker.IsNil)
236
+	c.Assert(resp.StatusCode, checker.Equals, http.StatusOK)
237
+	var info types.Info
238
+	err = json.NewDecoder(body).Decode(&info)
239
+	c.Assert(err, checker.IsNil)
240
+	body.Close()
241
+
242
+	// don't set a memory limit, the memory limit should be system memory
243
+	conName := "foo"
244
+	dockerCmd(c, "run", "-d", "--name", conName, "busybox", "top")
245
+	c.Assert(waitRun(conName), checker.IsNil)
246
+
247
+	resp, body, err = sockRequestRaw("GET", fmt.Sprintf("/containers/%s/stats?stream=false", conName), nil, "")
248
+	c.Assert(err, checker.IsNil)
249
+	c.Assert(resp.StatusCode, checker.Equals, http.StatusOK)
250
+	c.Assert(resp.Header.Get("Content-Type"), checker.Equals, "application/json")
251
+
252
+	var v *types.Stats
253
+	err = json.NewDecoder(body).Decode(&v)
254
+	c.Assert(err, checker.IsNil)
255
+	body.Close()
256
+	c.Assert(fmt.Sprintf("%d", v.MemoryStats.Limit), checker.Equals, fmt.Sprintf("%d", info.MemTotal))
257
+}