Signed-off-by: Lei Jitang <leijitang@huawei.com>
| ... | ... |
@@ -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 |
+} |