diff --git a/pkg/server/container_update_resources.go b/pkg/server/container_update_resources.go index a6d7079d4..55f2eeaf7 100644 --- a/pkg/server/container_update_resources.go +++ b/pkg/server/container_update_resources.go @@ -17,14 +17,51 @@ limitations under the License. package server import ( - "errors" + "fmt" + "github.com/containerd/containerd" + "github.com/golang/glog" + "github.com/golang/protobuf/proto" + runtimespec "github.com/opencontainers/runtime-spec/specs-go" "golang.org/x/net/context" - "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" ) // UpdateContainerResources updates ContainerConfig of the container. -func (c *criContainerdService) UpdateContainerResources(ctx context.Context, r *runtime.UpdateContainerResourcesRequest) (*runtime.UpdateContainerResourcesResponse, error) { - return nil, errors.New("not implemented") +func (c *criContainerdService) UpdateContainerResources(ctx context.Context, r *runtime.UpdateContainerResourcesRequest) (retRes *runtime.UpdateContainerResourcesResponse, retErr error) { + glog.V(2).Infof("UpdateContainerResources for container %q with %+v", r.GetContainerId(), r.GetLinux()) + defer func() { + if retErr == nil { + glog.V(2).Infof("UpdateContainerResources for container %q returns successfully", r.GetContainerId()) + } + }() + cntr, err := c.containerStore.Get(r.GetContainerId()) + if err != nil { + return nil, fmt.Errorf("failed to find container: %v", err) + } + task, err := cntr.Container.Task(ctx, nil) + if err != nil { + return nil, fmt.Errorf("failed to find task: %v", err) + } + resources := toOCIResources(r.GetLinux()) + if err := task.Update(ctx, containerd.WithResources(resources)); err != nil { + return nil, fmt.Errorf("failed to update resources: %v", err) + } + return &runtime.UpdateContainerResourcesResponse{}, nil +} + +// toOCIResources converts CRI resource constraints to OCI. +func toOCIResources(r *runtime.LinuxContainerResources) *runtimespec.LinuxResources { + return &runtimespec.LinuxResources{ + CPU: &runtimespec.LinuxCPU{ + Shares: proto.Uint64(uint64(r.GetCpuShares())), + Quota: proto.Int64(r.GetCpuQuota()), + Period: proto.Uint64(uint64(r.GetCpuPeriod())), + Cpus: r.GetCpusetCpus(), + Mems: r.GetCpusetMems(), + }, + Memory: &runtimespec.LinuxMemory{ + Limit: proto.Int64(r.GetMemoryLimitInBytes()), + }, + } } diff --git a/pkg/server/container_update_resources_test.go b/pkg/server/container_update_resources_test.go new file mode 100644 index 000000000..c8ccff0f9 --- /dev/null +++ b/pkg/server/container_update_resources_test.go @@ -0,0 +1,51 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package server + +import ( + "testing" + + "github.com/golang/protobuf/proto" + runtimespec "github.com/opencontainers/runtime-spec/specs-go" + "github.com/stretchr/testify/assert" + "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" +) + +func TestToOCIResources(t *testing.T) { + resources := &runtime.LinuxContainerResources{ + CpuPeriod: 10000, + CpuQuota: 20000, + CpuShares: 300, + MemoryLimitInBytes: 4000000, + OomScoreAdj: -500, + CpusetCpus: "6,7", + CpusetMems: "8,9", + } + expected := &runtimespec.LinuxResources{ + CPU: &runtimespec.LinuxCPU{ + Period: proto.Uint64(10000), + Quota: proto.Int64(20000), + Shares: proto.Uint64(300), + Cpus: "6,7", + Mems: "8,9", + }, + Memory: &runtimespec.LinuxMemory{ + Limit: proto.Int64(4000000), + }, + } + assert.Equal(t, expected, toOCIResources(resources)) +}