Skip to content

Commit

Permalink
support pod and container updates
Browse files Browse the repository at this point in the history
Signed-off-by: Kathryn Baldauf <[email protected]>
  • Loading branch information
katiewasnothere committed May 18, 2021
1 parent 5a7e7e0 commit 93561ea
Show file tree
Hide file tree
Showing 50 changed files with 1,486 additions and 319 deletions.
21 changes: 0 additions & 21 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,21 +0,0 @@
The MIT License (MIT)

Copyright (c) 2015 Microsoft

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
172 changes: 86 additions & 86 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,87 +1,87 @@
BASE:=base.tar.gz

GO:=go
GO_FLAGS:=-ldflags "-s -w" # strip Go binaries
CGO_ENABLED:=0
GOMODVENDOR:=

CFLAGS:=-O2 -Wall
LDFLAGS:=-static -s # strip C binaries

GO_FLAGS_EXTRA:=
ifeq "$(GOMODVENDOR)" "1"
GO_FLAGS_EXTRA += -mod=vendor
endif
GO_BUILD:=CGO_ENABLED=$(CGO_ENABLED) $(GO) build $(GO_FLAGS) $(GO_FLAGS_EXTRA)

SRCROOT=$(dir $(abspath $(firstword $(MAKEFILE_LIST))))

# The link aliases for gcstools
GCS_TOOLS=\
generichook

.PHONY: all always rootfs test

all: out/initrd.img out/rootfs.tar.gz

clean:
find -name '*.o' -print0 | xargs -0 -r rm
rm -rf bin deps rootfs out

test:
cd $(SRCROOT) && go test ./internal/guest/...

out/delta.tar.gz: bin/init bin/vsockexec bin/cmd/gcs bin/cmd/gcstools Makefile
@mkdir -p out
rm -rf rootfs
mkdir -p rootfs/bin/
cp bin/init rootfs/
cp bin/vsockexec rootfs/bin/
cp bin/cmd/gcs rootfs/bin/
cp bin/cmd/gcstools rootfs/bin/
for tool in $(GCS_TOOLS); do ln -s gcstools rootfs/bin/$$tool; done
git -C $(SRCROOT) rev-parse HEAD > rootfs/gcs.commit && \
git -C $(SRCROOT) rev-parse --abbrev-ref HEAD > rootfs/gcs.branch
tar -zcf $@ -C rootfs .
rm -rf rootfs

out/rootfs.tar.gz: out/initrd.img
rm -rf rootfs-conv
mkdir rootfs-conv
gunzip -c out/initrd.img | (cd rootfs-conv && cpio -imd)
tar -zcf $@ -C rootfs-conv .
rm -rf rootfs-conv

out/initrd.img: $(BASE) out/delta.tar.gz $(SRCROOT)/hack/catcpio.sh
$(SRCROOT)/hack/catcpio.sh "$(BASE)" out/delta.tar.gz > out/initrd.img.uncompressed
gzip -c out/initrd.img.uncompressed > $@
rm out/initrd.img.uncompressed

-include deps/cmd/gcs.gomake
-include deps/cmd/gcstools.gomake

# Implicit rule for includes that define Go targets.
%.gomake: $(SRCROOT)/Makefile
@mkdir -p $(dir $@)
@/bin/echo $(@:deps/%.gomake=bin/%): $(SRCROOT)/hack/gomakedeps.sh > $@.new
@/bin/echo -e '\t@mkdir -p $$(dir $$@) $(dir $@)' >> $@.new
@/bin/echo -e '\t$$(GO_BUILD) -o [email protected] $$(SRCROOT)/$$(@:bin/%=%)' >> $@.new
@/bin/echo -e '\tGO="$(GO)" $$(SRCROOT)/hack/gomakedeps.sh $$@ $$(SRCROOT)/$$(@:bin/%=%) $$(GO_FLAGS) $$(GO_FLAGS_EXTRA) > $(@:%.gomake=%.godeps).new' >> $@.new
@/bin/echo -e '\tmv $(@:%.gomake=%.godeps).new $(@:%.gomake=%.godeps)' >> $@.new
@/bin/echo -e '\tmv [email protected] $$@' >> $@.new
@/bin/echo -e '-include $(@:%.gomake=%.godeps)' >> $@.new
mv $@.new $@

VPATH=$(SRCROOT)

bin/vsockexec: vsockexec/vsockexec.o vsockexec/vsock.o
@mkdir -p bin
$(CC) $(LDFLAGS) -o $@ $^

bin/init: init/init.o vsockexec/vsock.o
@mkdir -p bin
$(CC) $(LDFLAGS) -o $@ $^

%.o: %.c
@mkdir -p $(dir $@)
BASE:=base.tar.gz

GO:=go
GO_FLAGS:=-ldflags "-s -w" # strip Go binaries
CGO_ENABLED:=0
GOMODVENDOR:=

CFLAGS:=-O2 -Wall
LDFLAGS:=-static -s # strip C binaries

GO_FLAGS_EXTRA:=
ifeq "$(GOMODVENDOR)" "1"
GO_FLAGS_EXTRA += -mod=vendor
endif
GO_BUILD:=CGO_ENABLED=$(CGO_ENABLED) $(GO) build $(GO_FLAGS) $(GO_FLAGS_EXTRA)

SRCROOT=$(dir $(abspath $(firstword $(MAKEFILE_LIST))))

# The link aliases for gcstools
GCS_TOOLS=\
generichook

.PHONY: all always rootfs test

all: out/initrd.img out/rootfs.tar.gz

clean:
find -name '*.o' -print0 | xargs -0 -r rm
rm -rf bin deps rootfs out

test:
cd $(SRCROOT) && go test ./internal/guest/...

out/delta.tar.gz: bin/init bin/vsockexec bin/cmd/gcs bin/cmd/gcstools Makefile
@mkdir -p out
rm -rf rootfs
mkdir -p rootfs/bin/
cp bin/init rootfs/
cp bin/vsockexec rootfs/bin/
cp bin/cmd/gcs rootfs/bin/
cp bin/cmd/gcstools rootfs/bin/
for tool in $(GCS_TOOLS); do ln -s gcstools rootfs/bin/$$tool; done
git -C $(SRCROOT) rev-parse HEAD > rootfs/gcs.commit && \
git -C $(SRCROOT) rev-parse --abbrev-ref HEAD > rootfs/gcs.branch
tar -zcf $@ -C rootfs .
rm -rf rootfs

out/rootfs.tar.gz: out/initrd.img
rm -rf rootfs-conv
mkdir rootfs-conv
gunzip -c out/initrd.img | (cd rootfs-conv && cpio -imd)
tar -zcf $@ -C rootfs-conv .
rm -rf rootfs-conv

out/initrd.img: $(BASE) out/delta.tar.gz $(SRCROOT)/hack/catcpio.sh
$(SRCROOT)/hack/catcpio.sh "$(BASE)" out/delta.tar.gz > out/initrd.img.uncompressed
gzip -c out/initrd.img.uncompressed > $@
rm out/initrd.img.uncompressed

-include deps/cmd/gcs.gomake
-include deps/cmd/gcstools.gomake

# Implicit rule for includes that define Go targets.
%.gomake: $(SRCROOT)/Makefile
@mkdir -p $(dir $@)
@/bin/echo $(@:deps/%.gomake=bin/%): $(SRCROOT)/hack/gomakedeps.sh > $@.new
@/bin/echo -e '\t@mkdir -p $$(dir $$@) $(dir $@)' >> $@.new
@/bin/echo -e '\t$$(GO_BUILD) -o [email protected] $$(SRCROOT)/$$(@:bin/%=%)' >> $@.new
@/bin/echo -e '\tGO="$(GO)" $$(SRCROOT)/hack/gomakedeps.sh $$@ $$(SRCROOT)/$$(@:bin/%=%) $$(GO_FLAGS) $$(GO_FLAGS_EXTRA) > $(@:%.gomake=%.godeps).new' >> $@.new
@/bin/echo -e '\tmv $(@:%.gomake=%.godeps).new $(@:%.gomake=%.godeps)' >> $@.new
@/bin/echo -e '\tmv [email protected] $$@' >> $@.new
@/bin/echo -e '-include $(@:%.gomake=%.godeps)' >> $@.new
mv $@.new $@

VPATH=$(SRCROOT)

bin/vsockexec: vsockexec/vsockexec.o vsockexec/vsock.o
@mkdir -p bin
$(CC) $(LDFLAGS) -o $@ $^

bin/init: init/init.o vsockexec/vsock.o
@mkdir -p bin
$(CC) $(LDFLAGS) -o $@ $^

%.o: %.c
@mkdir -p $(dir $@)
$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
12 changes: 11 additions & 1 deletion cmd/containerd-shim-runhcs-v1/service_internal.go
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,17 @@ func (s *service) closeIOInternal(ctx context.Context, req *task.CloseIORequest)
}

func (s *service) updateInternal(ctx context.Context, req *task.UpdateTaskRequest) (*google_protobuf1.Empty, error) {
return nil, errdefs.ErrNotImplemented
if req.Resources == nil {
return nil, errors.Wrapf(errdefs.ErrInvalidArgument, "resources cannot be empty, updating container %s resources failed", req.ID)
}
t, err := s.getTask(req.ID)
if err != nil {
return nil, err
}
if err := t.Update(ctx, req); err != nil {
return nil, err
}
return empty, nil
}

func (s *service) waitInternal(ctx context.Context, req *task.WaitRequest) (*task.WaitResponse, error) {
Expand Down
44 changes: 38 additions & 6 deletions cmd/containerd-shim-runhcs-v1/service_internal_podshim_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/runtime/v2/task"
"github.com/containerd/typeurl"
specs "github.com/opencontainers/runtime-spec/specs-go"
)

func setupPodServiceWithFakes(t *testing.T) (*service, *testShimTask, *testShimTask, *testShimExec) {
Expand Down Expand Up @@ -573,15 +574,46 @@ func Test_PodShim_closeIOInternal_2ndTaskID_2ndExecID_Success(t *testing.T) {
}
}

func Test_PodShim_updateInternal_Error(t *testing.T) {
s := service{
tid: t.Name(),
isSandbox: true,
func Test_PodShim_updateInternal_Success(t *testing.T) {
s, t1, _, _ := setupPodServiceWithFakes(t)

var limit uint64 = 100
resources := &specs.WindowsResources{
Memory: &specs.WindowsMemoryResources{
Limit: &limit,
},
}

resp, err := s.updateInternal(context.TODO(), &task.UpdateTaskRequest{ID: t.Name()})
any, err := typeurl.MarshalAny(resources)
if err != nil {
t.Fatal(err)
}

verifyExpectedError(t, resp, err, errdefs.ErrNotImplemented)
resp, err := s.updateInternal(context.TODO(), &task.UpdateTaskRequest{ID: t1.ID(), Resources: any})
if err != nil {
t.Fatalf("should not have failed with error, got: %v", err)
}
if resp == nil {
t.Fatalf("should have returned an empty resp")
}
}

func Test_PodShim_updateInternal_Error(t *testing.T) {
s, t1, _, _ := setupPodServiceWithFakes(t)

// resources must be of type *WindowsResources or *LinuxResources
resources := &specs.Process{}
any, err := typeurl.MarshalAny(resources)
if err != nil {
t.Fatal(err)
}
_, err = s.updateInternal(context.TODO(), &task.UpdateTaskRequest{ID: t1.ID(), Resources: any})
if err == nil {
t.Fatal("expected to get an error for incorrect resource's type")
}
if err != errNotSupportedResourcesRequest {
t.Fatalf("expected to get errNotSupportedResourcesRequest, instead got %v", err)
}
}

func Test_PodShim_waitInternal_NoTask_Error(t *testing.T) {
Expand Down
45 changes: 39 additions & 6 deletions cmd/containerd-shim-runhcs-v1/service_internal_taskshim_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/runtime/v2/task"
"github.com/containerd/typeurl"
"github.com/opencontainers/runtime-spec/specs-go"
)

func setupTaskServiceWithFakes(t *testing.T) (*service, *testShimTask, *testShimExec) {
Expand Down Expand Up @@ -493,15 +494,47 @@ func Test_TaskShim_closeIOInternal_InitTaskID_2ndExecID_Success(t *testing.T) {
}
}

func Test_TaskShim_updateInternal_Error(t *testing.T) {
s := service{
tid: t.Name(),
isSandbox: true,
func Test_TaskShim_updateInternal_Success(t *testing.T) {
s, t1, _ := setupTaskServiceWithFakes(t)

var limit uint64 = 100
resources := &specs.WindowsResources{
Memory: &specs.WindowsMemoryResources{
Limit: &limit,
},
}

resp, err := s.updateInternal(context.TODO(), &task.UpdateTaskRequest{ID: t.Name()})
any, err := typeurl.MarshalAny(resources)
if err != nil {
t.Fatal(err)
}

verifyExpectedError(t, resp, err, errdefs.ErrNotImplemented)
resp, err := s.updateInternal(context.TODO(), &task.UpdateTaskRequest{ID: t1.ID(), Resources: any})
if err != nil {
t.Fatalf("should not have failed with error, got: %v", err)
}
if resp == nil {
t.Fatalf("should have returned an empty resp")
}
}

func Test_TaskShim_updateInternal_Error(t *testing.T) {
s, t1, _ := setupTaskServiceWithFakes(t)

// resources must be of type *WindowsResources or *LinuxResources
resources := &specs.Process{}
any, err := typeurl.MarshalAny(resources)
if err != nil {
t.Fatal(err)
}

_, err = s.updateInternal(context.TODO(), &task.UpdateTaskRequest{ID: t1.ID(), Resources: any})
if err == nil {
t.Fatal("expected to get an error for incorrect resource's type")
}
if err != errNotSupportedResourcesRequest {
t.Fatalf("expected to get errNotSupportedResourcesRequest, instead got %v", err)
}
}

func Test_TaskShim_waitInternal_NoTask_Error(t *testing.T) {
Expand Down
17 changes: 16 additions & 1 deletion cmd/containerd-shim-runhcs-v1/task.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ import (
specs "github.com/opencontainers/runtime-spec/specs-go"
)

var errTaskNotIsolated = errors.New("task is not isolated")
var (
errTaskNotIsolated = errors.New("task is not isolated")
errNotSupportedResourcesRequest = errors.New("update resources must be of type *WindowsResources or *LinuxResources")
)

type shimTask interface {
// ID returns the original id used at `Create`.
Expand Down Expand Up @@ -86,6 +89,18 @@ type shimTask interface {
// If the host is hypervisor isolated and this task owns the host additional
// metrics on the UVM may be returned as well.
Stats(ctx context.Context) (*stats.Statistics, error)
// Update updates a task's container
Update(ctx context.Context, req *task.UpdateTaskRequest) error
}

func verifyTaskUpdateResourcesType(data interface{}) error {
switch data.(type) {
case *specs.WindowsResources:
case *specs.LinuxResources:
default:
return errNotSupportedResourcesRequest
}
return nil
}

// isStatsNotFound returns true if the err corresponds to a scenario
Expand Down
Loading

0 comments on commit 93561ea

Please sign in to comment.