summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pkg/api/handlers/libpod/containers_create.go17
-rw-r--r--pkg/specgenutil/specgen.go20
-rw-r--r--test/apiv2/python/rest_api/test_v2_0_0_container.py29
3 files changed, 58 insertions, 8 deletions
diff --git a/pkg/api/handlers/libpod/containers_create.go b/pkg/api/handlers/libpod/containers_create.go
index 4f9dc008d..1043dec4d 100644
--- a/pkg/api/handlers/libpod/containers_create.go
+++ b/pkg/api/handlers/libpod/containers_create.go
@@ -4,6 +4,7 @@ import (
"context"
"encoding/json"
"net/http"
+ "strconv"
"github.com/containers/podman/v4/libpod"
"github.com/containers/podman/v4/pkg/api/handlers/utils"
@@ -11,6 +12,7 @@ import (
"github.com/containers/podman/v4/pkg/domain/entities"
"github.com/containers/podman/v4/pkg/specgen"
"github.com/containers/podman/v4/pkg/specgen/generate"
+ "github.com/containers/podman/v4/pkg/specgenutil"
"github.com/pkg/errors"
)
@@ -39,6 +41,20 @@ func CreateContainer(w http.ResponseWriter, r *http.Request) {
t := true
sg.Passwd = &t
}
+
+ // need to check for memory limit to adjust swap
+ if sg.ResourceLimits != nil && sg.ResourceLimits.Memory != nil {
+ s := ""
+ var l int64 = 0
+ if sg.ResourceLimits.Memory.Swap != nil {
+ s = strconv.Itoa(int(*sg.ResourceLimits.Memory.Swap))
+ }
+ if sg.ResourceLimits.Memory.Limit != nil {
+ l = *sg.ResourceLimits.Memory.Limit
+ }
+ specgenutil.LimitToSwap(sg.ResourceLimits.Memory, s, l)
+ }
+
warn, err := generate.CompleteSpec(r.Context(), runtime, &sg)
if err != nil {
utils.InternalServerError(w, err)
@@ -54,6 +70,7 @@ func CreateContainer(w http.ResponseWriter, r *http.Request) {
utils.InternalServerError(w, err)
return
}
+
response := entities.ContainerCreateResponse{ID: ctr.ID(), Warnings: warn}
utils.WriteJSON(w, http.StatusCreated, response)
}
diff --git a/pkg/specgenutil/specgen.go b/pkg/specgenutil/specgen.go
index c86af7295..00de99817 100644
--- a/pkg/specgenutil/specgen.go
+++ b/pkg/specgenutil/specgen.go
@@ -126,6 +126,16 @@ func getIOLimits(s *specgen.SpecGenerator, c *entities.ContainerCreateOptions) (
return io, nil
}
+func LimitToSwap(memory *specs.LinuxMemory, swap string, ml int64) {
+ if ml > 0 {
+ memory.Limit = &ml
+ if swap == "" {
+ limit := 2 * ml
+ memory.Swap = &(limit)
+ }
+ }
+}
+
func getMemoryLimits(s *specgen.SpecGenerator, c *entities.ContainerCreateOptions) (*specs.LinuxMemory, error) {
var err error
memory := &specs.LinuxMemory{}
@@ -135,14 +145,8 @@ func getMemoryLimits(s *specgen.SpecGenerator, c *entities.ContainerCreateOption
if err != nil {
return nil, errors.Wrapf(err, "invalid value for memory")
}
- if ml > 0 {
- memory.Limit = &ml
- if c.MemorySwap == "" {
- limit := 2 * ml
- memory.Swap = &(limit)
- }
- hasLimits = true
- }
+ LimitToSwap(memory, c.MemorySwap, ml)
+ hasLimits = true
}
if m := c.MemoryReservation; len(m) > 0 {
mr, err := units.RAMInBytes(m)
diff --git a/test/apiv2/python/rest_api/test_v2_0_0_container.py b/test/apiv2/python/rest_api/test_v2_0_0_container.py
index 0386116a8..a44786c0d 100644
--- a/test/apiv2/python/rest_api/test_v2_0_0_container.py
+++ b/test/apiv2/python/rest_api/test_v2_0_0_container.py
@@ -328,6 +328,35 @@ class ContainerTestCase(APITestCase):
self.fail("Server failed to respond in 10s")
top.join()
+ def test_memory(self):
+ r = requests.post(
+ self.podman_url + "/v1.4.0/libpod/containers/create",
+ json={
+ "Name": "memory",
+ "Cmd": ["top"],
+ "Image": "alpine:latest",
+ "Resource_Limits": {
+ "Memory":{
+ "Limit": 1000,
+ },
+ "CPU":{
+ "Shares": 200,
+ },
+ },
+ },
+ )
+ self.assertEqual(r.status_code, 201, r.text)
+ payload = r.json()
+ container_id = payload["Id"]
+ self.assertIsNotNone(container_id)
+
+ r = requests.get(self.podman_url + f"/v1.40/containers/{container_id}/json")
+ self.assertEqual(r.status_code, 200, r.text)
+ self.assertId(r.content)
+ out = r.json()
+ self.assertEqual(2000, out["HostConfig"]["MemorySwap"])
+ self.assertEqual(1000, out["HostConfig"]["Memory"])
+
if __name__ == "__main__":
unittest.main()