diff --git a/hack/test-integration.sh b/hack/test-integration.sh index 883f4dc59..565cd0e77 100755 --- a/hack/test-integration.sh +++ b/hack/test-integration.sh @@ -33,7 +33,7 @@ mkdir -p ${REPORT_DIR} test_setup ${REPORT_DIR} # Run integration test. -sudo ${ROOT}/_output/integration.test --test.run="${FOCUS}" --test.v \ +sudo PATH=${PATH} ${ROOT}/_output/integration.test --test.run="${FOCUS}" --test.v \ --cri-endpoint=${CONTAINERD_SOCK} \ --cri-root=${CRI_ROOT} \ --runtime-handler=${RUNTIME} diff --git a/integration/restart_test.go b/integration/restart_test.go index 676bfa500..90525d378 100644 --- a/integration/restart_test.go +++ b/integration/restart_test.go @@ -17,8 +17,11 @@ limitations under the License. package integration import ( + "os" + "os/exec" "sort" "testing" + "time" "github.com/containerd/containerd" "github.com/stretchr/testify/assert" @@ -192,3 +195,149 @@ func TestContainerdRestart(t *testing.T) { assert.True(t, found, "should find image %+v", i1) } } + +// Note: The test moves runc binary. +// The test requires: +// 1) The runtime is runc; +// 2) runc is in PATH; +func TestUnknownStateAfterContainerdRestart(t *testing.T) { + if *runtimeHandler != "" { + t.Skip("unsupported config: runtime handler is set") + } + runcPath, err := exec.LookPath("runc") + if err != nil { + t.Skip("unsupported config: runc not in PATH") + } + + const testImage = "busybox" + t.Logf("Pull test image %q", testImage) + img, err := imageService.PullImage(&runtime.ImageSpec{Image: testImage}, nil) + require.NoError(t, err) + defer func() { + assert.NoError(t, imageService.RemoveImage(&runtime.ImageSpec{Image: img})) + }() + + sbConfig := PodSandboxConfig("sandbox", "sandbox-unknown-state") + t.Log("Should not be able to create sandbox without runc") + tmpRuncPath := Randomize(runcPath) + require.NoError(t, os.Rename(runcPath, tmpRuncPath)) + defer func() { + os.Rename(tmpRuncPath, runcPath) + }() + sb, err := runtimeService.RunPodSandbox(sbConfig, "") + if err == nil { + assert.NoError(t, runtimeService.StopPodSandbox(sb)) + assert.NoError(t, runtimeService.RemovePodSandbox(sb)) + t.Skip("unsupported config: runc is not being used") + } + require.NoError(t, os.Rename(tmpRuncPath, runcPath)) + + t.Log("Create a sandbox") + sb, err = runtimeService.RunPodSandbox(sbConfig, "") + require.NoError(t, err) + defer func() { + // Make sure the sandbox is cleaned up in any case. + runtimeService.StopPodSandbox(sb) + runtimeService.RemovePodSandbox(sb) + }() + ps, err := runtimeService.PodSandboxStatus(sb) + require.NoError(t, err) + assert.Equal(t, runtime.PodSandboxState_SANDBOX_READY, ps.GetState()) + + t.Log("Create a container") + cnConfig := ContainerConfig( + "container-unknown-state", + testImage, + WithCommand("sleep", "1000"), + ) + cn, err := runtimeService.CreateContainer(sb, cnConfig, sbConfig) + require.NoError(t, err) + + t.Log("Start the container") + require.NoError(t, runtimeService.StartContainer(cn)) + cs, err := runtimeService.ContainerStatus(cn) + require.NoError(t, err) + assert.Equal(t, runtime.ContainerState_CONTAINER_RUNNING, cs.GetState()) + + t.Log("Move runc binary, so that container/sandbox can't be loaded after restart") + tmpRuncPath = Randomize(runcPath) + require.NoError(t, os.Rename(runcPath, tmpRuncPath)) + defer func() { + os.Rename(tmpRuncPath, runcPath) + }() + + t.Log("Restart containerd") + RestartContainerd(t) + + t.Log("Sandbox should be in NOTREADY state after containerd restart") + ps, err = runtimeService.PodSandboxStatus(sb) + require.NoError(t, err) + assert.Equal(t, runtime.PodSandboxState_SANDBOX_NOTREADY, ps.GetState()) + + t.Log("Container should be in UNKNOWN state after containerd restart") + cs, err = runtimeService.ContainerStatus(cn) + require.NoError(t, err) + assert.Equal(t, runtime.ContainerState_CONTAINER_UNKNOWN, cs.GetState()) + + t.Log("Stop/remove the sandbox should fail for the lack of runc") + assert.Error(t, runtimeService.StopPodSandbox(sb)) + assert.Error(t, runtimeService.RemovePodSandbox(sb)) + + t.Log("Stop/remove the container should fail for the lack of runc") + assert.Error(t, runtimeService.StopContainer(cn, 10)) + assert.Error(t, runtimeService.RemoveContainer(cn)) + + t.Log("Move runc back") + require.NoError(t, os.Rename(tmpRuncPath, runcPath)) + + t.Log("Sandbox should still be in NOTREADY state") + ps, err = runtimeService.PodSandboxStatus(sb) + require.NoError(t, err) + assert.Equal(t, runtime.PodSandboxState_SANDBOX_NOTREADY, ps.GetState()) + + t.Log("Container should still be in UNKNOWN state") + cs, err = runtimeService.ContainerStatus(cn) + require.NoError(t, err) + assert.Equal(t, runtime.ContainerState_CONTAINER_UNKNOWN, cs.GetState()) + + t.Log("Sandbox operations which require running state should fail") + _, err = runtimeService.PortForward(&runtime.PortForwardRequest{ + PodSandboxId: sb, + Port: []int32{8080}, + }) + assert.Error(t, err) + + t.Log("Container operations which require running state should fail") + assert.Error(t, runtimeService.ReopenContainerLog(cn)) + _, _, err = runtimeService.ExecSync(cn, []string{"ls"}, 10*time.Second) + assert.Error(t, err) + _, err = runtimeService.Attach(&runtime.AttachRequest{ + ContainerId: cn, + Stdin: true, + Stdout: true, + Stderr: true, + }) + assert.Error(t, err) + + t.Log("Containerd should still be running now") + _, err = runtimeService.Status() + require.NoError(t, err) + + t.Log("Remove the container should fail in this state") + assert.Error(t, runtimeService.RemoveContainer(cn)) + + t.Log("Remove the sandbox should fail in this state") + assert.Error(t, runtimeService.RemovePodSandbox(sb)) + + t.Log("Should be able to stop container in this state") + assert.NoError(t, runtimeService.StopContainer(cn, 10)) + + t.Log("Should be able to stop sandbox in this state") + assert.NoError(t, runtimeService.StopPodSandbox(sb)) + + t.Log("Should be able to remove container after stop") + assert.NoError(t, runtimeService.RemoveContainer(cn)) + + t.Log("Should be able to remove sandbox after stop") + assert.NoError(t, runtimeService.RemovePodSandbox(sb)) +} diff --git a/pkg/server/container_remove.go b/pkg/server/container_remove.go index e05d79618..fe37a8ac7 100644 --- a/pkg/server/container_remove.go +++ b/pkg/server/container_remove.go @@ -98,9 +98,12 @@ func (c *criService) RemoveContainer(ctx context.Context, r *runtime.RemoveConta // container will not be started or removed again. func setContainerRemoving(container containerstore.Container) error { return container.Status.Update(func(status containerstore.Status) (containerstore.Status, error) { - // Do not remove container if it's still running. + // Do not remove container if it's still running or unknown. if status.State() == runtime.ContainerState_CONTAINER_RUNNING { - return status, errors.New("container is still running") + return status, errors.New("container is still running, to stop first") + } + if status.State() == runtime.ContainerState_CONTAINER_UNKNOWN { + return status, errors.New("container state is unknown, to stop first") } if status.Removing { return status, errors.New("container is already in removing state") diff --git a/pkg/server/container_status.go b/pkg/server/container_status.go index e4200acab..1e43bd42f 100644 --- a/pkg/server/container_status.go +++ b/pkg/server/container_status.go @@ -60,6 +60,15 @@ func (c *criService) ContainerStatus(ctx context.Context, r *runtime.ContainerSt } } status := toCRIContainerStatus(container, spec, imageRef) + if status.GetCreatedAt() == 0 { + // CRI doesn't allow CreatedAt == 0. + info, err := container.Container.Info(ctx) + if err != nil { + return nil, errors.Wrapf(err, "failed to get CreatedAt in %q state", status.State) + } + status.CreatedAt = info.CreatedAt.UnixNano() + } + info, err := toCRIContainerInfo(ctx, container, r.GetVerbose()) if err != nil { return nil, errors.Wrap(err, "failed to get verbose container info") diff --git a/pkg/server/container_stop.go b/pkg/server/container_stop.go index ddee397ae..f6d380d65 100644 --- a/pkg/server/container_stop.go +++ b/pkg/server/container_stop.go @@ -19,6 +19,8 @@ package server import ( "time" + "github.com/containerd/containerd" + eventtypes "github.com/containerd/containerd/api/events" "github.com/containerd/containerd/errdefs" "github.com/docker/docker/pkg/signal" "github.com/pkg/errors" @@ -60,8 +62,9 @@ func (c *criService) stopContainer(ctx context.Context, container containerstore // Return without error if container is not running. This makes sure that // stop only takes real action after the container is started. state := container.Status.Get().State() - if state != runtime.ContainerState_CONTAINER_RUNNING { - logrus.Infof("Container to stop %q is not running, current state %q", + if state != runtime.ContainerState_CONTAINER_RUNNING && + state != runtime.ContainerState_CONTAINER_UNKNOWN { + logrus.Infof("Container to stop %q must be in running or unknown state, current state %q", id, criContainerStateToString(state)) return nil } @@ -69,9 +72,39 @@ func (c *criService) stopContainer(ctx context.Context, container containerstore task, err := container.Container.Task(ctx, nil) if err != nil { if !errdefs.IsNotFound(err) { - return errors.Wrapf(err, "failed to stop container, task not found for container %q", id) + return errors.Wrapf(err, "failed to get task for container %q", id) + } + // Don't return for unknown state, some cleanup needs to be done. + if state != runtime.ContainerState_CONTAINER_UNKNOWN { + return nil + } + // Task is an interface, explicitly set it to nil just in case. + task = nil + } + + // Handle unknown state. + if state == runtime.ContainerState_CONTAINER_UNKNOWN { + status, err := getTaskStatus(ctx, task) + if err != nil { + return errors.Wrapf(err, "failed to get task status for %q", id) + } + switch status.Status { + case containerd.Running, containerd.Created: + // The task is still running, continue stopping the task. + case containerd.Stopped: + // The task has exited. If the task exited after containerd + // started, the event monitor will receive its exit event; if it + // exited before containerd started, the event monitor will never + // receive its exit event. + // However, we can't tell that because the task state was not + // successfully loaded during containerd start (container is + // in UNKNOWN state). + // So always do cleanup here, just in case that we've missed the + // exit event. + return cleanupUnknownContainer(ctx, id, status, container) + default: + return errors.Wrapf(err, "unsupported task status %q", status.Status) } - return nil } // We only need to kill the task. The event handler will Delete the @@ -141,3 +174,21 @@ func (c *criService) waitContainerStop(ctx context.Context, container containers return nil } } + +// cleanupUnknownContainer cleanup stopped container in unknown state. +func cleanupUnknownContainer(ctx context.Context, id string, status containerd.Status, + cntr containerstore.Container) error { + // Reuse handleContainerExit to do the cleanup. + // NOTE(random-liu): If the task did exit after containerd started, both + // the event monitor and the cleanup function would update the container + // state. The final container state will be whatever being updated first. + // There is no way to completely avoid this race condition, and for best + // effort unknown state container cleanup, this seems acceptable. + return handleContainerExit(ctx, &eventtypes.TaskExit{ + ContainerID: id, + ID: id, + Pid: 0, + ExitStatus: status.ExitStatus, + ExitedAt: status.ExitTime, + }, cntr) +} diff --git a/pkg/server/events.go b/pkg/server/events.go index 87169b544..bc384f754 100644 --- a/pkg/server/events.go +++ b/pkg/server/events.go @@ -213,7 +213,7 @@ func (em *eventMonitor) handleEvent(any interface{}) error { } else if err != store.ErrNotExist { return errors.Wrap(err, "can't find container for TaskExit event") } - // Use GetAll to include sandbox in unknown state. + // Use GetAll to include sandbox in init state. sb, err := em.c.sandboxStore.GetAll(e.ID) if err == nil { if err := handleSandboxExit(ctx, e, sb); err != nil { @@ -260,7 +260,16 @@ func handleContainerExit(ctx context.Context, e *eventtypes.TaskExit, cntr conta // Attach container IO so that `Delete` could cleanup the stream properly. task, err := cntr.Container.Task(ctx, func(*containerdio.FIFOSet) (containerdio.IO, error) { - return cntr.IO, nil + // We can't directly return cntr.IO here, because + // even if cntr.IO is nil, the cio.IO interface + // is not. + // See https://tour.golang.org/methods/12: + // Note that an interface value that holds a nil + // concrete value is itself non-nil. + if cntr.IO != nil { + return cntr.IO, nil + } + return nil, nil }, ) if err != nil { @@ -313,13 +322,13 @@ func handleSandboxExit(ctx context.Context, e *eventtypes.TaskExit, sb sandboxst } } err = sb.Status.Update(func(status sandboxstore.Status) (sandboxstore.Status, error) { - // NOTE(random-liu): We SHOULD NOT change UNKNOWN state here. - // If sandbox state is UNKNOWN when event monitor receives an TaskExit event, + // NOTE(random-liu): We SHOULD NOT change INIT state here. + // If sandbox state is INIT when event monitor receives an TaskExit event, // it means that sandbox start has failed. In that case, `RunPodSandbox` will // cleanup everything immediately. - // Once sandbox state goes out of UNKNOWN, it becomes visable to the user, which + // Once sandbox state goes out of INIT, it becomes visable to the user, which // is not what we want. - if status.State != sandboxstore.StateUnknown { + if status.State != sandboxstore.StateInit { status.State = sandboxstore.StateNotReady } status.Pid = 0 diff --git a/pkg/server/helpers.go b/pkg/server/helpers.go index 0727ba177..b44be5a2a 100644 --- a/pkg/server/helpers.go +++ b/pkg/server/helpers.go @@ -25,9 +25,12 @@ import ( "regexp" "strconv" "strings" + "time" "github.com/BurntSushi/toml" + "github.com/containerd/containerd" "github.com/containerd/containerd/containers" + "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/runtime/linux/runctypes" runcoptions "github.com/containerd/containerd/runtime/v2/runc/options" "github.com/containerd/typeurl" @@ -44,7 +47,9 @@ import ( runtimeoptions "github.com/containerd/cri/pkg/api/runtimeoptions/v1" criconfig "github.com/containerd/cri/pkg/config" "github.com/containerd/cri/pkg/store" + containerstore "github.com/containerd/cri/pkg/store/container" imagestore "github.com/containerd/cri/pkg/store/image" + sandboxstore "github.com/containerd/cri/pkg/store/sandbox" "github.com/containerd/cri/pkg/util" ) @@ -524,3 +529,53 @@ func restrictOOMScoreAdj(preferredOOMScoreAdj int) (int, error) { } return preferredOOMScoreAdj, nil } + +const ( + // unknownExitCode is the exit code when exit reason is unknown. + unknownExitCode = 255 + // unknownExitReason is the exit reason when exit reason is unknown. + unknownExitReason = "Unknown" +) + +// unknownContainerStatus returns the default container status when its status is unknown. +func unknownContainerStatus() containerstore.Status { + return containerstore.Status{ + CreatedAt: 0, + StartedAt: 0, + FinishedAt: 0, + ExitCode: unknownExitCode, + Reason: unknownExitReason, + } +} + +// unknownSandboxStatus returns the default sandbox status when its status is unknown. +func unknownSandboxStatus() sandboxstore.Status { + return sandboxstore.Status{ + State: sandboxstore.StateUnknown, + } +} + +// unknownExitStatus generates containerd.Status for container exited with unknown exit code. +func unknownExitStatus() containerd.Status { + return containerd.Status{ + Status: containerd.Stopped, + ExitStatus: unknownExitCode, + ExitTime: time.Now(), + } +} + +// getTaskStatus returns status for a given task. It returns unknown exit status if +// the task is nil or not found. +func getTaskStatus(ctx context.Context, task containerd.Task) (containerd.Status, error) { + if task == nil { + return unknownExitStatus(), nil + } + status, err := task.Status(ctx) + if err != nil { + if !errdefs.IsNotFound(err) { + return containerd.Status{}, err + } + return unknownExitStatus(), nil + } + return status, nil +} diff --git a/pkg/server/restart.go b/pkg/server/restart.go index b45fe31a6..7d1c1c8f7 100644 --- a/pkg/server/restart.go +++ b/pkg/server/restart.go @@ -179,140 +179,130 @@ func (c *criService) loadContainer(ctx context.Context, cntr containerd.Containe status = unknownContainerStatus() } - // Load up-to-date status from containerd. var containerIO *cio.ContainerIO - t, err := cntr.Task(ctx, func(fifos *containerdio.FIFOSet) (_ containerdio.IO, err error) { - stdoutWC, stderrWC, err := c.createContainerLoggers(meta.LogPath, meta.Config.GetTty()) - if err != nil { - return nil, err - } - defer func() { + err = func() error { + // Load up-to-date status from containerd. + t, err := cntr.Task(ctx, func(fifos *containerdio.FIFOSet) (_ containerdio.IO, err error) { + stdoutWC, stderrWC, err := c.createContainerLoggers(meta.LogPath, meta.Config.GetTty()) if err != nil { - if stdoutWC != nil { - stdoutWC.Close() - } - if stderrWC != nil { - stderrWC.Close() - } + return nil, err } - }() - containerIO, err = cio.NewContainerIO(id, - cio.WithFIFOs(fifos), - ) - if err != nil { - return nil, err - } - containerIO.AddOutput("log", stdoutWC, stderrWC) - containerIO.Pipe() - return containerIO, nil - }) - if err != nil && !errdefs.IsNotFound(err) { - return container, errors.Wrap(err, "failed to load task") - } - var s containerd.Status - var notFound bool - if errdefs.IsNotFound(err) { - // Task is not found. - notFound = true - } else { - // Task is found. Get task status. - s, err = t.Status(ctx) - if err != nil { - // It's still possible that task is deleted during this window. - if !errdefs.IsNotFound(err) { - return container, errors.Wrap(err, "failed to get task status") - } - notFound = true - } - } - if notFound { - // Task is not created or has been deleted, use the checkpointed status - // to generate container status. - switch status.State() { - case runtime.ContainerState_CONTAINER_CREATED: - // NOTE: Another possibility is that we've tried to start the container, but - // containerd got restarted during that. In that case, we still - // treat the container as `CREATED`. + defer func() { + if err != nil { + if stdoutWC != nil { + stdoutWC.Close() + } + if stderrWC != nil { + stderrWC.Close() + } + } + }() containerIO, err = cio.NewContainerIO(id, - cio.WithNewFIFOs(volatileContainerDir, meta.Config.GetTty(), meta.Config.GetStdin()), + cio.WithFIFOs(fifos), ) if err != nil { - return container, errors.Wrap(err, "failed to create container io") + return nil, err } - case runtime.ContainerState_CONTAINER_RUNNING: - // Container was in running state, but its task has been deleted, - // set unknown exited state. Container io is not needed in this case. - status.FinishedAt = time.Now().UnixNano() - status.ExitCode = unknownExitCode - status.Reason = unknownExitReason - default: - // Container is in exited/unknown state, return the status as it is. + containerIO.AddOutput("log", stdoutWC, stderrWC) + containerIO.Pipe() + return containerIO, nil + }) + if err != nil && !errdefs.IsNotFound(err) { + return errors.Wrap(err, "failed to load task") } - } else { - // Task status is found. Update container status based on the up-to-date task status. - switch s.Status { - case containerd.Created: - // Task has been created, but not started yet. This could only happen if containerd - // gets restarted during container start. - // Container must be in `CREATED` state. - if _, err := t.Delete(ctx, containerd.WithProcessKill); err != nil && !errdefs.IsNotFound(err) { - return container, errors.Wrap(err, "failed to delete task") + var s containerd.Status + var notFound bool + if errdefs.IsNotFound(err) { + // Task is not found. + notFound = true + } else { + // Task is found. Get task status. + s, err = t.Status(ctx) + if err != nil { + // It's still possible that task is deleted during this window. + if !errdefs.IsNotFound(err) { + return errors.Wrap(err, "failed to get task status") + } + notFound = true } - if status.State() != runtime.ContainerState_CONTAINER_CREATED { - return container, errors.Errorf("unexpected container state for created task: %q", status.State()) - } - case containerd.Running: - // Task is running. Container must be in `RUNNING` state, based on our assuption that - // "task should not be started when containerd is down". + } + if notFound { + // Task is not created or has been deleted, use the checkpointed status + // to generate container status. switch status.State() { - case runtime.ContainerState_CONTAINER_EXITED: - return container, errors.Errorf("unexpected container state for running task: %q", status.State()) + case runtime.ContainerState_CONTAINER_CREATED: + // NOTE: Another possibility is that we've tried to start the container, but + // containerd got restarted during that. In that case, we still + // treat the container as `CREATED`. + containerIO, err = cio.NewContainerIO(id, + cio.WithNewFIFOs(volatileContainerDir, meta.Config.GetTty(), meta.Config.GetStdin()), + ) + if err != nil { + return errors.Wrap(err, "failed to create container io") + } case runtime.ContainerState_CONTAINER_RUNNING: + // Container was in running state, but its task has been deleted, + // set unknown exited state. Container io is not needed in this case. + status.FinishedAt = time.Now().UnixNano() + status.ExitCode = unknownExitCode + status.Reason = unknownExitReason default: - // This may happen if containerd gets restarted after task is started, but - // before status is checkpointed. - status.StartedAt = time.Now().UnixNano() - status.Pid = t.Pid() + // Container is in exited/unknown state, return the status as it is. } - case containerd.Stopped: - // Task is stopped. Updata status and delete the task. - if _, err := t.Delete(ctx, containerd.WithProcessKill); err != nil && !errdefs.IsNotFound(err) { - return container, errors.Wrap(err, "failed to delete task") + } else { + // Task status is found. Update container status based on the up-to-date task status. + switch s.Status { + case containerd.Created: + // Task has been created, but not started yet. This could only happen if containerd + // gets restarted during container start. + // Container must be in `CREATED` state. + if _, err := t.Delete(ctx, containerd.WithProcessKill); err != nil && !errdefs.IsNotFound(err) { + return errors.Wrap(err, "failed to delete task") + } + if status.State() != runtime.ContainerState_CONTAINER_CREATED { + return errors.Errorf("unexpected container state for created task: %q", status.State()) + } + case containerd.Running: + // Task is running. Container must be in `RUNNING` state, based on our assuption that + // "task should not be started when containerd is down". + switch status.State() { + case runtime.ContainerState_CONTAINER_EXITED: + return errors.Errorf("unexpected container state for running task: %q", status.State()) + case runtime.ContainerState_CONTAINER_RUNNING: + default: + // This may happen if containerd gets restarted after task is started, but + // before status is checkpointed. + status.StartedAt = time.Now().UnixNano() + status.Pid = t.Pid() + } + case containerd.Stopped: + // Task is stopped. Updata status and delete the task. + if _, err := t.Delete(ctx, containerd.WithProcessKill); err != nil && !errdefs.IsNotFound(err) { + return errors.Wrap(err, "failed to delete task") + } + status.FinishedAt = s.ExitTime.UnixNano() + status.ExitCode = int32(s.ExitStatus) + default: + return errors.Errorf("unexpected task status %q", s.Status) } - status.FinishedAt = s.ExitTime.UnixNano() - status.ExitCode = int32(s.ExitStatus) - default: - return container, errors.Errorf("unexpected task status %q", s.Status) } + return nil + }() + if err != nil { + logrus.WithError(err).Errorf("Failed to load container status for %q", id) + status = unknownContainerStatus() } opts := []containerstore.Opts{ containerstore.WithStatus(status, containerDir), containerstore.WithContainer(cntr), } + // containerIO could be nil for container in unknown state. if containerIO != nil { opts = append(opts, containerstore.WithContainerIO(containerIO)) } return containerstore.NewContainer(*meta, opts...) } -const ( - // unknownExitCode is the exit code when exit reason is unknown. - unknownExitCode = 255 - // unknownExitReason is the exit reason when exit reason is unknown. - unknownExitReason = "Unknown" -) - -// unknownContainerStatus returns the default container status when its status is unknown. -func unknownContainerStatus() containerstore.Status { - return containerstore.Status{ - CreatedAt: 0, - StartedAt: 0, - FinishedAt: 0, - ExitCode: unknownExitCode, - Reason: unknownExitReason, - } -} - // loadSandbox loads sandbox from containerd. func loadSandbox(ctx context.Context, cntr containerd.Container) (sandboxstore.Sandbox, error) { ctx, cancel := context.WithTimeout(ctx, loadContainerTimeout) @@ -333,61 +323,59 @@ func loadSandbox(ctx context.Context, cntr containerd.Container) (sandboxstore.S } meta := data.(*sandboxstore.Metadata) - // Load sandbox created timestamp. - info, err := cntr.Info(ctx) - if err != nil { - return sandbox, errors.Wrap(err, "failed to get sandbox container info") - } - createdAt := info.CreatedAt - - // Load sandbox status. - t, err := cntr.Task(ctx, nil) - if err != nil && !errdefs.IsNotFound(err) { - return sandbox, errors.Wrap(err, "failed to load task") - } - var s containerd.Status - var notFound bool - if errdefs.IsNotFound(err) { - // Task is not found. - notFound = true - } else { - // Task is found. Get task status. - s, err = t.Status(ctx) + s, err := func() (sandboxstore.Status, error) { + status := unknownSandboxStatus() + // Load sandbox created timestamp. + info, err := cntr.Info(ctx) if err != nil { - // It's still possible that task is deleted during this window. - if !errdefs.IsNotFound(err) { - return sandbox, errors.Wrap(err, "failed to get task status") - } + return status, errors.Wrap(err, "failed to get sandbox container info") + } + status.CreatedAt = info.CreatedAt + + // Load sandbox state. + t, err := cntr.Task(ctx, nil) + if err != nil && !errdefs.IsNotFound(err) { + return status, errors.Wrap(err, "failed to load task") + } + var taskStatus containerd.Status + var notFound bool + if errdefs.IsNotFound(err) { + // Task is not found. notFound = true - } - } - var state sandboxstore.State - var pid uint32 - if notFound { - // Task does not exist, set sandbox state as NOTREADY. - state = sandboxstore.StateNotReady - } else { - if s.Status == containerd.Running { - // Task is running, set sandbox state as READY. - state = sandboxstore.StateReady - pid = t.Pid() } else { - // Task is not running. Delete the task and set sandbox state as NOTREADY. - if _, err := t.Delete(ctx, containerd.WithProcessKill); err != nil && !errdefs.IsNotFound(err) { - return sandbox, errors.Wrap(err, "failed to delete task") + // Task is found. Get task status. + taskStatus, err = t.Status(ctx) + if err != nil { + // It's still possible that task is deleted during this window. + if !errdefs.IsNotFound(err) { + return status, errors.Wrap(err, "failed to get task status") + } + notFound = true } - state = sandboxstore.StateNotReady } + if notFound { + // Task does not exist, set sandbox state as NOTREADY. + status.State = sandboxstore.StateNotReady + } else { + if taskStatus.Status == containerd.Running { + // Task is running, set sandbox state as READY. + status.State = sandboxstore.StateReady + status.Pid = t.Pid() + } else { + // Task is not running. Delete the task and set sandbox state as NOTREADY. + if _, err := t.Delete(ctx, containerd.WithProcessKill); err != nil && !errdefs.IsNotFound(err) { + return status, errors.Wrap(err, "failed to delete task") + } + status.State = sandboxstore.StateNotReady + } + } + return status, nil + }() + if err != nil { + logrus.WithError(err).Errorf("Failed to load sandbox status for %q", cntr.ID()) } - sandbox = sandboxstore.NewSandbox( - *meta, - sandboxstore.Status{ - Pid: pid, - CreatedAt: createdAt, - State: state, - }, - ) + sandbox = sandboxstore.NewSandbox(*meta, s) sandbox.Container = cntr // Load network namespace. diff --git a/pkg/server/sandbox_list_test.go b/pkg/server/sandbox_list_test.go index ff0126129..2fda7a7c9 100644 --- a/pkg/server/sandbox_list_test.go +++ b/pkg/server/sandbox_list_test.go @@ -63,6 +63,10 @@ func TestToCRISandbox(t *testing.T) { state: sandboxstore.StateNotReady, expectedState: runtime.PodSandboxState_SANDBOX_NOTREADY, }, + "sandbox state unknown": { + state: sandboxstore.StateUnknown, + expectedState: runtime.PodSandboxState_SANDBOX_NOTREADY, + }, } { status := sandboxstore.Status{ CreatedAt: createdAt, diff --git a/pkg/server/sandbox_remove.go b/pkg/server/sandbox_remove.go index 29ebd44ed..b4ad03fe1 100644 --- a/pkg/server/sandbox_remove.go +++ b/pkg/server/sandbox_remove.go @@ -46,8 +46,9 @@ func (c *criService) RemovePodSandbox(ctx context.Context, r *runtime.RemovePodS // Use the full sandbox id. id := sandbox.ID - // Return error if sandbox container is still running. - if sandbox.Status.Get().State == sandboxstore.StateReady { + // Return error if sandbox container is still running or unknown. + state := sandbox.Status.Get().State + if state == sandboxstore.StateReady || state == sandboxstore.StateUnknown { return nil, errors.Errorf("sandbox container %q is not fully stopped", id) } diff --git a/pkg/server/sandbox_run.go b/pkg/server/sandbox_run.go index 3f2d206f3..f844a0107 100644 --- a/pkg/server/sandbox_run.go +++ b/pkg/server/sandbox_run.go @@ -85,7 +85,7 @@ func (c *criService) RunPodSandbox(ctx context.Context, r *runtime.RunPodSandbox RuntimeHandler: r.GetRuntimeHandler(), }, sandboxstore.Status{ - State: sandboxstore.StateUnknown, + State: sandboxstore.StateInit, }, ) @@ -258,7 +258,7 @@ func (c *criService) RunPodSandbox(ctx context.Context, r *runtime.RunPodSandbox return nil, errors.Wrap(err, "failed to update sandbox created timestamp") } - // Add sandbox into sandbox store in UNKNOWN state. + // Add sandbox into sandbox store in INIT state. sandbox.Container = container if err := c.sandboxStore.Add(sandbox); err != nil { return nil, errors.Wrapf(err, "failed to add sandbox %+v into store", sandbox) @@ -269,7 +269,7 @@ func (c *criService) RunPodSandbox(ctx context.Context, r *runtime.RunPodSandbox c.sandboxStore.Delete(id) } }() - // NOTE(random-liu): Sandbox state only stay in UNKNOWN state after this point + // NOTE(random-liu): Sandbox state only stay in INIT state after this point // and before the end of this function. // * If `Update` succeeds, sandbox state will become READY in one transaction. // * If `Update` fails, sandbox will be removed from the store in the defer above. @@ -279,8 +279,8 @@ func (c *criService) RunPodSandbox(ctx context.Context, r *runtime.RunPodSandbox // * If the task is running, sandbox state will be READY, // * Or else, sandbox state will be NOTREADY. // - // In any case, sandbox will leave UNKNOWN state, so it's safe to ignore sandbox - // in UNKNOWN state in other functions. + // In any case, sandbox will leave INIT state, so it's safe to ignore sandbox + // in INIT state in other functions. // Start sandbox container in one transaction to avoid race condition with // event monitor. @@ -293,8 +293,8 @@ func (c *criService) RunPodSandbox(ctx context.Context, r *runtime.RunPodSandbox // see the sandbox disappear after the defer clean up, which may confuse // them. // - // Given so, we should keep the sandbox in UNKNOWN state if `Update` fails, - // and ignore sandbox in UNKNOWN state in all the inspection functions. + // Given so, we should keep the sandbox in INIT state if `Update` fails, + // and ignore sandbox in INIT state in all the inspection functions. // Create sandbox task in containerd. log.Tracef("Create sandbox container (id=%q, name=%q).", diff --git a/pkg/server/sandbox_status.go b/pkg/server/sandbox_status.go index fb8f3d928..6e0e01501 100644 --- a/pkg/server/sandbox_status.go +++ b/pkg/server/sandbox_status.go @@ -42,6 +42,14 @@ func (c *criService) PodSandboxStatus(ctx context.Context, r *runtime.PodSandbox return nil, errors.Wrap(err, "failed to get sandbox ip") } status := toCRISandboxStatus(sandbox.Metadata, sandbox.Status.Get(), ip) + if status.GetCreatedAt() == 0 { + // CRI doesn't allow CreatedAt == 0. + info, err := sandbox.Container.Info(ctx) + if err != nil { + return nil, errors.Wrapf(err, "failed to get CreatedAt for sandbox container in %q state", status.State) + } + status.CreatedAt = info.CreatedAt.UnixNano() + } if !r.GetVerbose() { return &runtime.PodSandboxStatusResponse{Status: status}, nil } diff --git a/pkg/server/sandbox_status_test.go b/pkg/server/sandbox_status_test.go index 23453d32b..3ef23db0e 100644 --- a/pkg/server/sandbox_status_test.go +++ b/pkg/server/sandbox_status_test.go @@ -86,6 +86,10 @@ func TestPodSandboxStatus(t *testing.T) { state: sandboxstore.StateNotReady, expectedState: runtime.PodSandboxState_SANDBOX_NOTREADY, }, + "sandbox state unknown": { + state: sandboxstore.StateUnknown, + expectedState: runtime.PodSandboxState_SANDBOX_NOTREADY, + }, } { t.Logf("TestCase: %s", desc) status := sandboxstore.Status{ diff --git a/pkg/server/sandbox_stop.go b/pkg/server/sandbox_stop.go index 5fc78e8ab..69e2038b1 100644 --- a/pkg/server/sandbox_stop.go +++ b/pkg/server/sandbox_stop.go @@ -19,6 +19,8 @@ package server import ( "time" + "github.com/containerd/containerd" + eventtypes "github.com/containerd/containerd/api/events" "github.com/containerd/containerd/errdefs" cni "github.com/containerd/go-cni" "github.com/pkg/errors" @@ -60,10 +62,11 @@ func (c *criService) StopPodSandbox(ctx context.Context, r *runtime.StopPodSandb return nil, errors.Wrap(err, "failed to unmount sandbox files") } - // Only stop sandbox container when it's running. - if sandbox.Status.Get().State == sandboxstore.StateReady { + // Only stop sandbox container when it's running or unknown. + state := sandbox.Status.Get().State + if state == sandboxstore.StateReady || state == sandboxstore.StateUnknown { if err := c.stopSandboxContainer(ctx, sandbox); err != nil { - return nil, errors.Wrapf(err, "failed to stop sandbox container %q", id) + return nil, errors.Wrapf(err, "failed to stop sandbox container %q in %q state", id, state) } } @@ -95,12 +98,36 @@ func (c *criService) StopPodSandbox(ctx context.Context, r *runtime.StopPodSandb // the event monitor handles the `TaskExit` event. func (c *criService) stopSandboxContainer(ctx context.Context, sandbox sandboxstore.Sandbox) error { container := sandbox.Container + state := sandbox.Status.Get().State task, err := container.Task(ctx, nil) if err != nil { - if errdefs.IsNotFound(err) { + if !errdefs.IsNotFound(err) { + return errors.Wrap(err, "failed to get sandbox container") + } + // Don't return for unknown state, some cleanup needs to be done. + if state != sandboxstore.StateUnknown { return nil } - return errors.Wrap(err, "failed to get sandbox container") + // Task is an interface, explicitly set it to nil just in case. + task = nil + } + + // Handle unknown state. + // The cleanup logic is the same with container unknown state. + if state == sandboxstore.StateUnknown { + status, err := getTaskStatus(ctx, task) + if err != nil { + return errors.Wrapf(err, "failed to get task status for %q", sandbox.ID) + } + switch status.Status { + case containerd.Running, containerd.Created: + // The task is still running, continue stopping the task. + case containerd.Stopped: + // The task has exited, explicitly cleanup. + return cleanupUnknownSandbox(ctx, sandbox.ID, status, sandbox) + default: + return errors.Wrapf(err, "unsupported task status %q", status.Status) + } } // Kill the sandbox container. @@ -137,3 +164,16 @@ func (c *criService) teardownPod(id string, path string, config *runtime.PodSand cni.WithLabels(labels), cni.WithCapabilityPortMap(toCNIPortMappings(config.GetPortMappings()))) } + +// cleanupUnknownSandbox cleanup stopped sandbox in unknown state. +func cleanupUnknownSandbox(ctx context.Context, id string, status containerd.Status, + sandbox sandboxstore.Sandbox) error { + // Reuse handleSandboxExit to do the cleanup. + return handleSandboxExit(ctx, &eventtypes.TaskExit{ + ContainerID: id, + ID: id, + Pid: 0, + ExitStatus: status.ExitStatus, + ExitedAt: status.ExitTime, + }, sandbox) +} diff --git a/pkg/store/container/container.go b/pkg/store/container/container.go index fb6cad133..07a57b187 100644 --- a/pkg/store/container/container.go +++ b/pkg/store/container/container.go @@ -36,7 +36,8 @@ type Container struct { Status StatusStorage // Container is the containerd container client. Container containerd.Container - // Container IO + // Container IO. + // IO could only be nil when the container is in unknown state. IO *cio.ContainerIO // StopCh is used to propagate the stop information of the container. *store.StopCh diff --git a/pkg/store/container/status.go b/pkg/store/container/status.go index 7dfe1cdb0..b73a2ef66 100644 --- a/pkg/store/container/status.go +++ b/pkg/store/container/status.go @@ -28,6 +28,38 @@ import ( runtime "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2" ) +// The container state machine in the CRI plugin: +// +// + + +// | | +// | Create | Load +// | | +// +----v----+ | +// | | | +// | CREATED <---------+-----------+ +// | | | | +// +----+----- | | +// | | | +// | Start | | +// | | | +// +----v----+ | | +// Exec +--------+ | | | +// Attach | | RUNNING <---------+ | +// LogReopen +--------> | | | +// +----+----+ | | +// | | | +// | Stop/Exit | | +// | | | +// +----v----+ | | +// | <---------+ +----v----+ +// | EXITED | | | +// | <----------------+ UNKNOWN | +// +----+----+ Stop | | +// | +---------+ +// | Remove +// v +// DELETED + // statusVersion is current version of container status. const statusVersion = "v1" // nolint diff --git a/pkg/store/sandbox/sandbox.go b/pkg/store/sandbox/sandbox.go index 764b2760b..69189069f 100644 --- a/pkg/store/sandbox/sandbox.go +++ b/pkg/store/sandbox/sandbox.go @@ -93,7 +93,7 @@ func (s *Store) Get(id string) (Sandbox, error) { if err != nil { return sb, err } - if sb.Status.Get().State == StateUnknown { + if sb.Status.Get().State == StateInit { return Sandbox{}, store.ErrNotExist } return sb, nil @@ -123,7 +123,7 @@ func (s *Store) List() []Sandbox { defer s.lock.RUnlock() var sandboxes []Sandbox for _, sb := range s.sandboxes { - if sb.Status.Get().State == StateUnknown { + if sb.Status.Get().State == StateInit { continue } sandboxes = append(sandboxes, sb) diff --git a/pkg/store/sandbox/sandbox_test.go b/pkg/store/sandbox/sandbox_test.go index 538e573d9..23523e292 100644 --- a/pkg/store/sandbox/sandbox_test.go +++ b/pkg/store/sandbox/sandbox_test.go @@ -106,7 +106,7 @@ func TestSandboxStore(t *testing.T) { }, NetNSPath: "TestNetNS-3defg", }, - Status{State: StateUnknown}, + Status{State: StateInit}, ) assert := assertlib.New(t) s := NewStore() diff --git a/pkg/store/sandbox/status.go b/pkg/store/sandbox/status.go index 6dedb8ae3..201b19ba4 100644 --- a/pkg/store/sandbox/status.go +++ b/pkg/store/sandbox/status.go @@ -21,16 +21,52 @@ import ( "time" ) +// The sandbox state machine in the CRI plugin: +// + + +// | | +// | Create(Run) | Load +// | | +// Start +----v----+ | +// (failed) | | | +// +-------------+ INIT | +-----------+ +// | | | | | +// | +----+----+ | | +// | | | | +// | | Start(Run) | | +// | | | | +// | PortForward +----v----+ | | +// | +------+ | | | +// | | | READY <---------+ | +// | +------> | | | +// | +----+----+ | | +// | | | | +// | | Stop/Exit | | +// | | | | +// | +----v----+ | | +// | | <---------+ +----v----+ +// | | NOTREADY| | | +// | | <----------------+ UNKNOWN | +// | +----+----+ Stop | | +// | | +---------+ +// | | Remove +// | v +// +-------------> DELETED + // State is the sandbox state we use in containerd/cri. -// It has unknown state defined. +// It includes init and unknown, which are internal states not defined in CRI. +// The state mapping from internal states to CRI states: +// * ready -> ready +// * not ready -> not ready +// * init -> not exist +// * unknown -> not ready type State uint32 const ( - // StateUnknown is unknown state of sandbox. Sandbox - // is in unknown state before its corresponding sandbox container - // is created. Sandbox in unknown state should be ignored by most + // StateInit is init state of sandbox. Sandbox + // is in init state before its corresponding sandbox container + // is created. Sandbox in init state should be ignored by most // functions, unless the caller needs to update sandbox state. - StateUnknown State = iota + StateInit State = iota // StateReady is ready state, it means sandbox container // is running. StateReady @@ -40,6 +76,9 @@ const ( // cleanup resources other than sandbox container, e.g. network namespace. // This is an assumption made in CRI. StateNotReady + // StateUnknown is unknown state. Sandbox only goes + // into unknown state when its status fails to be loaded. + StateUnknown ) // Status is the status of a sandbox. diff --git a/pkg/store/sandbox/status_test.go b/pkg/store/sandbox/status_test.go index 6973ac66c..31e9253ee 100644 --- a/pkg/store/sandbox/status_test.go +++ b/pkg/store/sandbox/status_test.go @@ -28,7 +28,7 @@ func TestStatus(t *testing.T) { testStatus := Status{ Pid: 123, CreatedAt: time.Now(), - State: StateUnknown, + State: StateInit, } updateStatus := Status{ Pid: 456, diff --git a/vendor.conf b/vendor.conf index f59340b54..7575e238f 100644 --- a/vendor.conf +++ b/vendor.conf @@ -1,14 +1,14 @@ github.com/beorn7/perks 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9 github.com/blang/semver v3.1.0 github.com/BurntSushi/toml a368813c5e648fee92e5f6c30e3944ff9d5e8895 -github.com/containerd/cgroups 5e610833b72089b37d0e615de9a92dfc043757c2 +github.com/containerd/cgroups 1152b960fcee041f50df15cdc67c29dbccf801ef github.com/containerd/console c12b1e7919c14469339a5d38f2f8ed9b64a9de23 -github.com/containerd/containerd 6937c5a3ba8280edff9e9030767e3b0cb742581c +github.com/containerd/containerd 5ba368748b0275d8f45f909413d94738992f0050 github.com/containerd/continuity bd77b46c8352f74eb12c85bdc01f4b90f69d66b4 github.com/containerd/fifo 3d5202aec260678c48179c56f40e6f38a095738c github.com/containerd/go-cni 40bcf8ec8acd7372be1d77031d585d5d8e561c90 github.com/containerd/go-runc 5a6d9f37cfa36b15efba46dc7ea349fa9b7143c3 -github.com/containerd/ttrpc 2a805f71863501300ae1976d29f0454ae003e85a +github.com/containerd/ttrpc f02858b1457c5ca3aaec3a0803eb0d59f96e41d6 github.com/containerd/typeurl a93fcdb778cd272c6e9b3028b2f42d813e785d40 github.com/containernetworking/cni v0.6.0 github.com/containernetworking/plugins v0.7.0 @@ -32,12 +32,12 @@ github.com/hashicorp/go-multierror ed905158d87462226a13fe39ddf685ea65f1c11f github.com/json-iterator/go 1.1.5 github.com/matttproud/golang_protobuf_extensions v1.0.0 github.com/Microsoft/go-winio v0.4.11 -github.com/Microsoft/hcsshim v0.8.2 +github.com/Microsoft/hcsshim v0.8.5 github.com/modern-go/concurrent 1.0.3 github.com/modern-go/reflect2 1.0.1 github.com/opencontainers/go-digest c9281466c8b2f606084ac71339773efd177436e7 github.com/opencontainers/image-spec v1.0.1 -github.com/opencontainers/runc v1.0.0-rc6 +github.com/opencontainers/runc 12f6a991201fdb8f82579582d5e00e28fba06d0a github.com/opencontainers/runtime-spec eba862dc2470385a233c7507392675cbeadf7353 github.com/opencontainers/runtime-tools fb101d5d42ab9c040f7d0a004e78336e5d5cb197 github.com/opencontainers/selinux b6fa367ed7f534f9ba25391cc2d467085dbb445a @@ -60,7 +60,7 @@ go.etcd.io/bbolt v1.3.1-etcd.8 golang.org/x/crypto 49796115aa4b964c318aad4f3084fdb41e9aa067 golang.org/x/net b3756b4b77d7b13260a0a2ec658753cf48922eac golang.org/x/oauth2 a6bd8cefa1811bd24b86f8902872e4e8225f74c4 -golang.org/x/sync 450f422ab23cf9881c94e2db30cac0eb1b7cf80c +golang.org/x/sync 42b317875d0fa942474b76e1b46a6060d720ae6e golang.org/x/sys 1b2967e3c290b7c545b3db0deeda16e9be4f98a2 https://github.com/golang/sys golang.org/x/text 19e51611da83d6be54ddafce4a4af510cb3e9ea4 golang.org/x/time f51c12702a4d776e4c1fa9b0fabab841babae631 diff --git a/vendor/github.com/Microsoft/hcsshim/hnspolicylist.go b/vendor/github.com/Microsoft/hcsshim/hnspolicylist.go index 12c2b9702..55aaa4a50 100644 --- a/vendor/github.com/Microsoft/hcsshim/hnspolicylist.go +++ b/vendor/github.com/Microsoft/hcsshim/hnspolicylist.go @@ -37,8 +37,8 @@ func GetPolicyListByID(policyListID string) (*PolicyList, error) { } // AddLoadBalancer policy list for the specified endpoints -func AddLoadBalancer(endpoints []HNSEndpoint, isILB bool, isDSR bool, sourceVIP, vip string, protocol uint16, internalPort uint16, externalPort uint16) (*PolicyList, error) { - return hns.AddLoadBalancer(endpoints, isILB, isDSR, sourceVIP, vip, protocol, internalPort, externalPort) +func AddLoadBalancer(endpoints []HNSEndpoint, isILB bool, sourceVIP, vip string, protocol uint16, internalPort uint16, externalPort uint16) (*PolicyList, error) { + return hns.AddLoadBalancer(endpoints, isILB, sourceVIP, vip, protocol, internalPort, externalPort) } // AddRoute adds route policy list for the specified endpoints diff --git a/vendor/github.com/Microsoft/hcsshim/internal/guestrequest/types.go b/vendor/github.com/Microsoft/hcsshim/internal/guestrequest/types.go index 9f926c6be..5d3d0dfef 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/guestrequest/types.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/guestrequest/types.go @@ -1,6 +1,8 @@ package guestrequest -import "github.com/Microsoft/hcsshim/internal/schema2" +import ( + "github.com/Microsoft/hcsshim/internal/schema2" +) // Arguably, many of these (at least CombinedLayers) should have been generated // by swagger. @@ -47,6 +49,19 @@ type LCOWMappedVPMemDevice struct { MountPath string `json:"MountPath,omitempty"` // /tmp/pN } +type LCOWNetworkAdapter struct { + NamespaceID string `json:",omitempty"` + ID string `json:",omitempty"` + MacAddress string `json:",omitempty"` + IPAddress string `json:",omitempty"` + PrefixLength uint8 `json:",omitempty"` + GatewayAddress string `json:",omitempty"` + DNSSuffix string `json:",omitempty"` + DNSServerList string `json:",omitempty"` + EnableLowMetric bool `json:",omitempty"` + EncapOverhead uint16 `json:",omitempty"` +} + type ResourceType string const ( diff --git a/vendor/github.com/Microsoft/hcsshim/internal/hcs/callback.go b/vendor/github.com/Microsoft/hcsshim/internal/hcs/callback.go index e41c40ec8..f9a922a4b 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/hcs/callback.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/hcs/callback.go @@ -5,6 +5,7 @@ import ( "syscall" "github.com/Microsoft/hcsshim/internal/interop" + "github.com/sirupsen/logrus" ) var ( @@ -15,11 +16,20 @@ var ( notificationWatcherCallback = syscall.NewCallback(notificationWatcher) // Notifications for HCS_SYSTEM handles - hcsNotificationSystemExited hcsNotification = 0x00000001 - hcsNotificationSystemCreateCompleted hcsNotification = 0x00000002 - hcsNotificationSystemStartCompleted hcsNotification = 0x00000003 - hcsNotificationSystemPauseCompleted hcsNotification = 0x00000004 - hcsNotificationSystemResumeCompleted hcsNotification = 0x00000005 + hcsNotificationSystemExited hcsNotification = 0x00000001 + hcsNotificationSystemCreateCompleted hcsNotification = 0x00000002 + hcsNotificationSystemStartCompleted hcsNotification = 0x00000003 + hcsNotificationSystemPauseCompleted hcsNotification = 0x00000004 + hcsNotificationSystemResumeCompleted hcsNotification = 0x00000005 + hcsNotificationSystemCrashReport hcsNotification = 0x00000006 + hcsNotificationSystemSiloJobCreated hcsNotification = 0x00000007 + hcsNotificationSystemSaveCompleted hcsNotification = 0x00000008 + hcsNotificationSystemRdpEnhancedModeStateChanged hcsNotification = 0x00000009 + hcsNotificationSystemShutdownFailed hcsNotification = 0x0000000A + hcsNotificationSystemGetPropertiesCompleted hcsNotification = 0x0000000B + hcsNotificationSystemModifyCompleted hcsNotification = 0x0000000C + hcsNotificationSystemCrashInitiated hcsNotification = 0x0000000D + hcsNotificationSystemGuestConnectionClosed hcsNotification = 0x0000000E // Notifications for HCS_PROCESS handles hcsNotificationProcessExited hcsNotification = 0x00010000 @@ -49,16 +59,23 @@ func newChannels() notificationChannels { channels[hcsNotificationSystemResumeCompleted] = make(notificationChannel, 1) channels[hcsNotificationProcessExited] = make(notificationChannel, 1) channels[hcsNotificationServiceDisconnect] = make(notificationChannel, 1) + channels[hcsNotificationSystemCrashReport] = make(notificationChannel, 1) + channels[hcsNotificationSystemSiloJobCreated] = make(notificationChannel, 1) + channels[hcsNotificationSystemSaveCompleted] = make(notificationChannel, 1) + channels[hcsNotificationSystemRdpEnhancedModeStateChanged] = make(notificationChannel, 1) + channels[hcsNotificationSystemShutdownFailed] = make(notificationChannel, 1) + channels[hcsNotificationSystemGetPropertiesCompleted] = make(notificationChannel, 1) + channels[hcsNotificationSystemModifyCompleted] = make(notificationChannel, 1) + channels[hcsNotificationSystemCrashInitiated] = make(notificationChannel, 1) + channels[hcsNotificationSystemGuestConnectionClosed] = make(notificationChannel, 1) + return channels } + func closeChannels(channels notificationChannels) { - close(channels[hcsNotificationSystemExited]) - close(channels[hcsNotificationSystemCreateCompleted]) - close(channels[hcsNotificationSystemStartCompleted]) - close(channels[hcsNotificationSystemPauseCompleted]) - close(channels[hcsNotificationSystemResumeCompleted]) - close(channels[hcsNotificationProcessExited]) - close(channels[hcsNotificationServiceDisconnect]) + for _, c := range channels { + close(c) + } } func notificationWatcher(notificationType hcsNotification, callbackNumber uintptr, notificationStatus uintptr, notificationData *uint16) uintptr { @@ -75,7 +92,13 @@ func notificationWatcher(notificationType hcsNotification, callbackNumber uintpt return 0 } - context.channels[notificationType] <- result + if channel, ok := context.channels[notificationType]; ok { + channel <- result + } else { + logrus.WithFields(logrus.Fields{ + "notification-type": notificationType, + }).Warn("Received a callback of an unsupported type") + } return 0 } diff --git a/vendor/github.com/Microsoft/hcsshim/internal/hcs/errors.go b/vendor/github.com/Microsoft/hcsshim/internal/hcs/errors.go index 7471f5cc1..079b56535 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/hcs/errors.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/hcs/errors.go @@ -7,6 +7,7 @@ import ( "syscall" "github.com/Microsoft/hcsshim/internal/interop" + "github.com/Microsoft/hcsshim/internal/logfields" "github.com/sirupsen/logrus" ) @@ -72,6 +73,9 @@ var ( // ErrVmcomputeUnknownMessage is an error encountered guest compute system doesn't support the message ErrVmcomputeUnknownMessage = syscall.Errno(0xc037010b) + // ErrVmcomputeUnexpectedExit is an error encountered when the compute system terminates unexpectedly + ErrVmcomputeUnexpectedExit = syscall.Errno(0xC0370106) + // ErrNotSupported is an error encountered when hcs doesn't support the request ErrPlatformNotSupported = errors.New("unsupported platform request") ) @@ -116,10 +120,14 @@ func (ev *ErrorEvent) String() string { func processHcsResult(resultp *uint16) []ErrorEvent { if resultp != nil { resultj := interop.ConvertAndFreeCoTaskMemString(resultp) - logrus.Debugf("Result: %s", resultj) + logrus.WithField(logfields.JSON, resultj). + Debug("HCS Result") result := &hcsResult{} if err := json.Unmarshal([]byte(resultj), result); err != nil { - logrus.Warnf("Could not unmarshal HCS result %s: %s", resultj, err) + logrus.WithFields(logrus.Fields{ + logfields.JSON: resultj, + logrus.ErrorKey: err, + }).Warning("Could not unmarshal HCS result") return nil } return result.ErrorEvents diff --git a/vendor/github.com/Microsoft/hcsshim/internal/hcs/log.go b/vendor/github.com/Microsoft/hcsshim/internal/hcs/log.go new file mode 100644 index 000000000..90d164e35 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/hcs/log.go @@ -0,0 +1,15 @@ +package hcs + +import "github.com/sirupsen/logrus" + +func logOperationBegin(ctx logrus.Fields, msg string) { + logrus.WithFields(ctx).Debug(msg) +} + +func logOperationEnd(ctx logrus.Fields, msg string, err error) { + if err == nil { + logrus.WithFields(ctx).Debug(msg) + } else { + logrus.WithFields(ctx).WithError(err).Error(msg) + } +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/hcs/process.go b/vendor/github.com/Microsoft/hcsshim/internal/hcs/process.go index d356cdc4d..4c35c732c 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/hcs/process.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/hcs/process.go @@ -2,7 +2,6 @@ package hcs import ( "encoding/json" - "fmt" "io" "sync" "syscall" @@ -10,6 +9,7 @@ import ( "github.com/Microsoft/hcsshim/internal/guestrequest" "github.com/Microsoft/hcsshim/internal/interop" + "github.com/Microsoft/hcsshim/internal/logfields" "github.com/sirupsen/logrus" ) @@ -21,6 +21,21 @@ type Process struct { system *System cachedPipes *cachedPipes callbackNumber uintptr + + logctx logrus.Fields +} + +func newProcess(process hcsProcess, processID int, computeSystem *System) *Process { + return &Process{ + handle: process, + processID: processID, + system: computeSystem, + logctx: logrus.Fields{ + logfields.HCSOperation: "", + logfields.ContainerID: computeSystem.ID(), + logfields.ProcessID: processID, + }, + } } type cachedPipes struct { @@ -72,13 +87,36 @@ func (process *Process) SystemID() string { return process.system.ID() } +func (process *Process) logOperationBegin(operation string) { + process.logctx[logfields.HCSOperation] = operation + logOperationBegin( + process.logctx, + "hcsshim::Process - Begin Operation") +} + +func (process *Process) logOperationEnd(err error) { + var result string + if err == nil { + result = "Success" + } else { + result = "Error" + } + + logOperationEnd( + process.logctx, + "hcsshim::Process - End Operation - "+result, + err) + process.logctx[logfields.HCSOperation] = "" +} + // Signal signals the process with `options`. -func (process *Process) Signal(options guestrequest.SignalProcessOptions) error { +func (process *Process) Signal(options guestrequest.SignalProcessOptions) (err error) { process.handleLock.RLock() defer process.handleLock.RUnlock() - operation := "Signal" - title := "hcsshim::Process::" + operation - logrus.Debugf(title+" processid=%d", process.processID) + + operation := "hcsshim::Process::Signal" + process.logOperationBegin(operation) + defer func() { process.logOperationEnd(err) }() if process.handle == 0 { return makeProcessError(process, operation, ErrAlreadyClosed, nil) @@ -92,83 +130,79 @@ func (process *Process) Signal(options guestrequest.SignalProcessOptions) error optionsStr := string(optionsb) var resultp *uint16 - completed := false - go syscallWatcher(fmt.Sprintf("SignalProcess %s: %d", process.SystemID(), process.Pid()), &completed) - err = hcsSignalProcess(process.handle, optionsStr, &resultp) - completed = true + syscallWatcher(process.logctx, func() { + err = hcsSignalProcess(process.handle, optionsStr, &resultp) + }) events := processHcsResult(resultp) if err != nil { return makeProcessError(process, operation, err, events) } - logrus.Debugf(title+" succeeded processid=%d", process.processID) return nil } // Kill signals the process to terminate but does not wait for it to finish terminating. -func (process *Process) Kill() error { +func (process *Process) Kill() (err error) { process.handleLock.RLock() defer process.handleLock.RUnlock() - operation := "Kill" - title := "hcsshim::Process::" + operation - logrus.Debugf(title+" processid=%d", process.processID) + + operation := "hcsshim::Process::Kill" + process.logOperationBegin(operation) + defer func() { process.logOperationEnd(err) }() if process.handle == 0 { return makeProcessError(process, operation, ErrAlreadyClosed, nil) } var resultp *uint16 - completed := false - go syscallWatcher(fmt.Sprintf("TerminateProcess %s: %d", process.SystemID(), process.Pid()), &completed) - err := hcsTerminateProcess(process.handle, &resultp) - completed = true + syscallWatcher(process.logctx, func() { + err = hcsTerminateProcess(process.handle, &resultp) + }) events := processHcsResult(resultp) if err != nil { return makeProcessError(process, operation, err, events) } - logrus.Debugf(title+" succeeded processid=%d", process.processID) return nil } // Wait waits for the process to exit. -func (process *Process) Wait() error { - operation := "Wait" - title := "hcsshim::Process::" + operation - logrus.Debugf(title+" processid=%d", process.processID) +func (process *Process) Wait() (err error) { + operation := "hcsshim::Process::Wait" + process.logOperationBegin(operation) + defer func() { process.logOperationEnd(err) }() - err := waitForNotification(process.callbackNumber, hcsNotificationProcessExited, nil) + err = waitForNotification(process.callbackNumber, hcsNotificationProcessExited, nil) if err != nil { return makeProcessError(process, operation, err, nil) } - logrus.Debugf(title+" succeeded processid=%d", process.processID) return nil } // WaitTimeout waits for the process to exit or the duration to elapse. It returns // false if timeout occurs. -func (process *Process) WaitTimeout(timeout time.Duration) error { - operation := "WaitTimeout" - title := "hcsshim::Process::" + operation - logrus.Debugf(title+" processid=%d", process.processID) +func (process *Process) WaitTimeout(timeout time.Duration) (err error) { + operation := "hcssshim::Process::WaitTimeout" + process.logOperationBegin(operation) + defer func() { process.logOperationEnd(err) }() - err := waitForNotification(process.callbackNumber, hcsNotificationProcessExited, &timeout) + err = waitForNotification(process.callbackNumber, hcsNotificationProcessExited, &timeout) if err != nil { return makeProcessError(process, operation, err, nil) } - logrus.Debugf(title+" succeeded processid=%d", process.processID) return nil } // ResizeConsole resizes the console of the process. -func (process *Process) ResizeConsole(width, height uint16) error { +func (process *Process) ResizeConsole(width, height uint16) (err error) { process.handleLock.RLock() defer process.handleLock.RUnlock() - operation := "ResizeConsole" - title := "hcsshim::Process::" + operation - logrus.Debugf(title+" processid=%d", process.processID) + + operation := "hcsshim::Process::ResizeConsole" + process.logOperationBegin(operation) + defer func() { process.logOperationEnd(err) }() if process.handle == 0 { return makeProcessError(process, operation, ErrAlreadyClosed, nil) @@ -196,16 +230,16 @@ func (process *Process) ResizeConsole(width, height uint16) error { return makeProcessError(process, operation, err, events) } - logrus.Debugf(title+" succeeded processid=%d", process.processID) return nil } -func (process *Process) Properties() (*ProcessStatus, error) { +func (process *Process) Properties() (_ *ProcessStatus, err error) { process.handleLock.RLock() defer process.handleLock.RUnlock() - operation := "Properties" - title := "hcsshim::Process::" + operation - logrus.Debugf(title+" processid=%d", process.processID) + + operation := "hcsshim::Process::Properties" + process.logOperationBegin(operation) + defer func() { process.logOperationEnd(err) }() if process.handle == 0 { return nil, makeProcessError(process, operation, ErrAlreadyClosed, nil) @@ -215,10 +249,9 @@ func (process *Process) Properties() (*ProcessStatus, error) { resultp *uint16 propertiesp *uint16 ) - completed := false - go syscallWatcher(fmt.Sprintf("GetProcessProperties %s: %d", process.SystemID(), process.Pid()), &completed) - err := hcsGetProcessProperties(process.handle, &propertiesp, &resultp) - completed = true + syscallWatcher(process.logctx, func() { + err = hcsGetProcessProperties(process.handle, &propertiesp, &resultp) + }) events := processHcsResult(resultp) if err != nil { return nil, makeProcessError(process, operation, err, events) @@ -234,14 +267,16 @@ func (process *Process) Properties() (*ProcessStatus, error) { return nil, makeProcessError(process, operation, err, nil) } - logrus.Debugf(title+" succeeded processid=%d, properties=%s", process.processID, propertiesRaw) return properties, nil } // ExitCode returns the exit code of the process. The process must have // already terminated. -func (process *Process) ExitCode() (int, error) { - operation := "ExitCode" +func (process *Process) ExitCode() (_ int, err error) { + operation := "hcsshim::Process::ExitCode" + process.logOperationBegin(operation) + defer func() { process.logOperationEnd(err) }() + properties, err := process.Properties() if err != nil { return 0, makeProcessError(process, operation, err, nil) @@ -261,12 +296,13 @@ func (process *Process) ExitCode() (int, error) { // Stdio returns the stdin, stdout, and stderr pipes, respectively. Closing // these pipes does not close the underlying pipes; it should be possible to // call this multiple times to get multiple interfaces. -func (process *Process) Stdio() (io.WriteCloser, io.ReadCloser, io.ReadCloser, error) { +func (process *Process) Stdio() (_ io.WriteCloser, _ io.ReadCloser, _ io.ReadCloser, err error) { process.handleLock.RLock() defer process.handleLock.RUnlock() - operation := "Stdio" - title := "hcsshim::Process::" + operation - logrus.Debugf(title+" processid=%d", process.processID) + + operation := "hcsshim::Process::Stdio" + process.logOperationBegin(operation) + defer func() { process.logOperationEnd(err) }() if process.handle == 0 { return nil, nil, nil, makeProcessError(process, operation, ErrAlreadyClosed, nil) @@ -279,7 +315,7 @@ func (process *Process) Stdio() (io.WriteCloser, io.ReadCloser, io.ReadCloser, e processInfo hcsProcessInformation resultp *uint16 ) - err := hcsGetProcessInfo(process.handle, &processInfo, &resultp) + err = hcsGetProcessInfo(process.handle, &processInfo, &resultp) events := processHcsResult(resultp) if err != nil { return nil, nil, nil, makeProcessError(process, operation, err, events) @@ -299,18 +335,18 @@ func (process *Process) Stdio() (io.WriteCloser, io.ReadCloser, io.ReadCloser, e return nil, nil, nil, makeProcessError(process, operation, err, nil) } - logrus.Debugf(title+" succeeded processid=%d", process.processID) return pipes[0], pipes[1], pipes[2], nil } // CloseStdin closes the write side of the stdin pipe so that the process is // notified on the read side that there is no more data in stdin. -func (process *Process) CloseStdin() error { +func (process *Process) CloseStdin() (err error) { process.handleLock.RLock() defer process.handleLock.RUnlock() - operation := "CloseStdin" - title := "hcsshim::Process::" + operation - logrus.Debugf(title+" processid=%d", process.processID) + + operation := "hcsshim::Process::CloseStdin" + process.logOperationBegin(operation) + defer func() { process.logOperationEnd(err) }() if process.handle == 0 { return makeProcessError(process, operation, ErrAlreadyClosed, nil) @@ -337,35 +373,34 @@ func (process *Process) CloseStdin() error { return makeProcessError(process, operation, err, events) } - logrus.Debugf(title+" succeeded processid=%d", process.processID) return nil } // Close cleans up any state associated with the process but does not kill // or wait on it. -func (process *Process) Close() error { +func (process *Process) Close() (err error) { process.handleLock.Lock() defer process.handleLock.Unlock() - operation := "Close" - title := "hcsshim::Process::" + operation - logrus.Debugf(title+" processid=%d", process.processID) + + operation := "hcsshim::Process::Close" + process.logOperationBegin(operation) + defer func() { process.logOperationEnd(err) }() // Don't double free this if process.handle == 0 { return nil } - if err := process.unregisterCallback(); err != nil { + if err = process.unregisterCallback(); err != nil { return makeProcessError(process, operation, err, nil) } - if err := hcsCloseProcess(process.handle); err != nil { + if err = hcsCloseProcess(process.handle); err != nil { return makeProcessError(process, operation, err, nil) } process.handle = 0 - logrus.Debugf(title+" succeeded processid=%d", process.processID) return nil } diff --git a/vendor/github.com/Microsoft/hcsshim/internal/hcs/system.go b/vendor/github.com/Microsoft/hcsshim/internal/hcs/system.go index 57afd5ec6..50f768b72 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/hcs/system.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/hcs/system.go @@ -2,7 +2,6 @@ package hcs import ( "encoding/json" - "fmt" "os" "strconv" "sync" @@ -10,6 +9,7 @@ import ( "time" "github.com/Microsoft/hcsshim/internal/interop" + "github.com/Microsoft/hcsshim/internal/logfields" "github.com/Microsoft/hcsshim/internal/schema1" "github.com/Microsoft/hcsshim/internal/timeout" "github.com/sirupsen/logrus" @@ -41,16 +41,49 @@ type System struct { handle hcsSystem id string callbackNumber uintptr + + logctx logrus.Fields +} + +func newSystem(id string) *System { + return &System{ + id: id, + logctx: logrus.Fields{ + logfields.HCSOperation: "", + logfields.ContainerID: id, + }, + } +} + +func (computeSystem *System) logOperationBegin(operation string) { + computeSystem.logctx[logfields.HCSOperation] = operation + logOperationBegin( + computeSystem.logctx, + "hcsshim::ComputeSystem - Begin Operation") +} + +func (computeSystem *System) logOperationEnd(err error) { + var result string + if err == nil { + result = "Success" + } else { + result = "Error" + } + + logOperationEnd( + computeSystem.logctx, + "hcsshim::ComputeSystem - End Operation - "+result, + err) + computeSystem.logctx[logfields.HCSOperation] = "" } // CreateComputeSystem creates a new compute system with the given configuration but does not start it. -func CreateComputeSystem(id string, hcsDocumentInterface interface{}) (*System, error) { - operation := "CreateComputeSystem" - title := "hcsshim::" + operation +func CreateComputeSystem(id string, hcsDocumentInterface interface{}) (_ *System, err error) { + operation := "hcsshim::CreateComputeSystem" - computeSystem := &System{ - id: id, - } + computeSystem := newSystem(id) + computeSystem.logOperationBegin(operation) + defer func() { computeSystem.logOperationEnd(err) }() hcsDocumentB, err := json.Marshal(hcsDocumentInterface) if err != nil { @@ -58,19 +91,22 @@ func CreateComputeSystem(id string, hcsDocumentInterface interface{}) (*System, } hcsDocument := string(hcsDocumentB) - logrus.Debugf(title+" ID=%s config=%s", id, hcsDocument) + + logrus.WithFields(computeSystem.logctx). + WithField(logfields.JSON, hcsDocument). + Debug("HCS ComputeSystem Document") var ( - resultp *uint16 - identity syscall.Handle + resultp *uint16 + identity syscall.Handle + createError error ) - completed := false - go syscallWatcher(fmt.Sprintf("CreateCompleteSystem %s: %s", id, hcsDocument), &completed) - createError := hcsCreateComputeSystem(id, hcsDocument, identity, &computeSystem.handle, &resultp) - completed = true + syscallWatcher(computeSystem.logctx, func() { + createError = hcsCreateComputeSystem(id, hcsDocument, identity, &computeSystem.handle, &resultp) + }) if createError == nil || IsPending(createError) { - if err := computeSystem.registerCallback(); err != nil { + if err = computeSystem.registerCallback(); err != nil { // Terminate the compute system if it still exists. We're okay to // ignore a failure here. computeSystem.Terminate() @@ -88,25 +124,28 @@ func CreateComputeSystem(id string, hcsDocumentInterface interface{}) (*System, return nil, makeSystemError(computeSystem, operation, hcsDocument, err, events) } - logrus.Debugf(title+" succeeded id=%s handle=%d", id, computeSystem.handle) return computeSystem, nil } // OpenComputeSystem opens an existing compute system by ID. -func OpenComputeSystem(id string) (*System, error) { - operation := "OpenComputeSystem" - title := "hcsshim::" + operation - logrus.Debugf(title+" ID=%s", id) +func OpenComputeSystem(id string) (_ *System, err error) { + operation := "hcsshim::OpenComputeSystem" - computeSystem := &System{ - id: id, - } + computeSystem := newSystem(id) + computeSystem.logOperationBegin(operation) + defer func() { + if IsNotExist(err) { + computeSystem.logOperationEnd(nil) + } else { + computeSystem.logOperationEnd(err) + } + }() var ( handle hcsSystem resultp *uint16 ) - err := hcsOpenComputeSystem(id, &handle, &resultp) + err = hcsOpenComputeSystem(id, &handle, &resultp) events := processHcsResult(resultp) if err != nil { return nil, makeSystemError(computeSystem, operation, "", err, events) @@ -114,18 +153,36 @@ func OpenComputeSystem(id string) (*System, error) { computeSystem.handle = handle - if err := computeSystem.registerCallback(); err != nil { + if err = computeSystem.registerCallback(); err != nil { return nil, makeSystemError(computeSystem, operation, "", err, nil) } - logrus.Debugf(title+" succeeded id=%s handle=%d", id, handle) return computeSystem, nil } // GetComputeSystems gets a list of the compute systems on the system that match the query -func GetComputeSystems(q schema1.ComputeSystemQuery) ([]schema1.ContainerProperties, error) { - operation := "GetComputeSystems" - title := "hcsshim::" + operation +func GetComputeSystems(q schema1.ComputeSystemQuery) (_ []schema1.ContainerProperties, err error) { + operation := "hcsshim::GetComputeSystems" + fields := logrus.Fields{ + logfields.HCSOperation: operation, + } + logOperationBegin( + fields, + "hcsshim::ComputeSystem - Begin Operation") + + defer func() { + var result string + if err == nil { + result = "Success" + } else { + result = "Error" + } + + logOperationEnd( + fields, + "hcsshim::ComputeSystem - End Operation - "+result, + err) + }() queryb, err := json.Marshal(q) if err != nil { @@ -133,16 +190,19 @@ func GetComputeSystems(q schema1.ComputeSystemQuery) ([]schema1.ContainerPropert } query := string(queryb) - logrus.Debugf(title+" query=%s", query) + + logrus.WithFields(fields). + WithField(logfields.JSON, query). + Debug("HCS ComputeSystem Query") var ( resultp *uint16 computeSystemsp *uint16 ) - completed := false - go syscallWatcher(fmt.Sprintf("GetComputeSystems %s:", query), &completed) - err = hcsEnumerateComputeSystems(query, &computeSystemsp, &resultp) - completed = true + + syscallWatcher(fields, func() { + err = hcsEnumerateComputeSystems(query, &computeSystemsp, &resultp) + }) events := processHcsResult(resultp) if err != nil { return nil, &HcsError{Op: operation, Err: err, Events: events} @@ -153,20 +213,21 @@ func GetComputeSystems(q schema1.ComputeSystemQuery) ([]schema1.ContainerPropert } computeSystemsRaw := interop.ConvertAndFreeCoTaskMemBytes(computeSystemsp) computeSystems := []schema1.ContainerProperties{} - if err := json.Unmarshal(computeSystemsRaw, &computeSystems); err != nil { + if err = json.Unmarshal(computeSystemsRaw, &computeSystems); err != nil { return nil, err } - logrus.Debugf(title + " succeeded") return computeSystems, nil } // Start synchronously starts the computeSystem. -func (computeSystem *System) Start() error { +func (computeSystem *System) Start() (err error) { computeSystem.handleLock.RLock() defer computeSystem.handleLock.RUnlock() - title := "hcsshim::ComputeSystem::Start ID=" + computeSystem.ID() - logrus.Debugf(title) + + operation := "hcsshim::ComputeSystem::Start" + computeSystem.logOperationBegin(operation) + defer func() { computeSystem.logOperationEnd(err) }() if computeSystem.handle == 0 { return makeSystemError(computeSystem, "Start", "", ErrAlreadyClosed, nil) @@ -199,16 +260,14 @@ func (computeSystem *System) Start() error { } var resultp *uint16 - completed := false - go syscallWatcher(fmt.Sprintf("StartComputeSystem %s:", computeSystem.ID()), &completed) - err := hcsStartComputeSystem(computeSystem.handle, "", &resultp) - completed = true + syscallWatcher(computeSystem.logctx, func() { + err = hcsStartComputeSystem(computeSystem.handle, "", &resultp) + }) events, err := processAsyncHcsResult(err, resultp, computeSystem.callbackNumber, hcsNotificationSystemStartCompleted, &timeout.SystemStart) if err != nil { return makeSystemError(computeSystem, "Start", "", err, events) } - logrus.Debugf(title + " succeeded") return nil } @@ -219,98 +278,133 @@ func (computeSystem *System) ID() string { // Shutdown requests a compute system shutdown, if IsPending() on the error returned is true, // it may not actually be shut down until Wait() succeeds. -func (computeSystem *System) Shutdown() error { +func (computeSystem *System) Shutdown() (err error) { computeSystem.handleLock.RLock() defer computeSystem.handleLock.RUnlock() - title := "hcsshim::ComputeSystem::Shutdown" - logrus.Debugf(title) + + operation := "hcsshim::ComputeSystem::Shutdown" + computeSystem.logOperationBegin(operation) + defer func() { + if IsAlreadyStopped(err) { + computeSystem.logOperationEnd(nil) + } else { + computeSystem.logOperationEnd(err) + } + }() + if computeSystem.handle == 0 { return makeSystemError(computeSystem, "Shutdown", "", ErrAlreadyClosed, nil) } var resultp *uint16 - completed := false - go syscallWatcher(fmt.Sprintf("ShutdownComputeSystem %s:", computeSystem.ID()), &completed) - err := hcsShutdownComputeSystem(computeSystem.handle, "", &resultp) - completed = true + syscallWatcher(computeSystem.logctx, func() { + err = hcsShutdownComputeSystem(computeSystem.handle, "", &resultp) + }) events := processHcsResult(resultp) if err != nil { return makeSystemError(computeSystem, "Shutdown", "", err, events) } - logrus.Debugf(title + " succeeded") return nil } // Terminate requests a compute system terminate, if IsPending() on the error returned is true, // it may not actually be shut down until Wait() succeeds. -func (computeSystem *System) Terminate() error { +func (computeSystem *System) Terminate() (err error) { computeSystem.handleLock.RLock() defer computeSystem.handleLock.RUnlock() - title := "hcsshim::ComputeSystem::Terminate ID=" + computeSystem.ID() - logrus.Debugf(title) + + operation := "hcsshim::ComputeSystem::Terminate" + computeSystem.logOperationBegin(operation) + defer func() { + if IsPending(err) { + computeSystem.logOperationEnd(nil) + } else { + computeSystem.logOperationEnd(err) + } + }() if computeSystem.handle == 0 { return makeSystemError(computeSystem, "Terminate", "", ErrAlreadyClosed, nil) } var resultp *uint16 - completed := false - go syscallWatcher(fmt.Sprintf("TerminateComputeSystem %s:", computeSystem.ID()), &completed) - err := hcsTerminateComputeSystem(computeSystem.handle, "", &resultp) - completed = true + syscallWatcher(computeSystem.logctx, func() { + err = hcsTerminateComputeSystem(computeSystem.handle, "", &resultp) + }) events := processHcsResult(resultp) - if err != nil { + if err != nil && err != ErrVmcomputeAlreadyStopped { return makeSystemError(computeSystem, "Terminate", "", err, events) } - logrus.Debugf(title + " succeeded") return nil } // Wait synchronously waits for the compute system to shutdown or terminate. -func (computeSystem *System) Wait() error { - title := "hcsshim::ComputeSystem::Wait ID=" + computeSystem.ID() - logrus.Debugf(title) +func (computeSystem *System) Wait() (err error) { + operation := "hcsshim::ComputeSystem::Wait" + computeSystem.logOperationBegin(operation) + defer func() { computeSystem.logOperationEnd(err) }() - err := waitForNotification(computeSystem.callbackNumber, hcsNotificationSystemExited, nil) + err = waitForNotification(computeSystem.callbackNumber, hcsNotificationSystemExited, nil) if err != nil { return makeSystemError(computeSystem, "Wait", "", err, nil) } - logrus.Debugf(title + " succeeded") + return nil +} + +// WaitExpectedError synchronously waits for the compute system to shutdown or +// terminate, and ignores the passed error if it occurs. +func (computeSystem *System) WaitExpectedError(expected error) (err error) { + operation := "hcsshim::ComputeSystem::WaitExpectedError" + computeSystem.logOperationBegin(operation) + defer func() { computeSystem.logOperationEnd(err) }() + + err = waitForNotification(computeSystem.callbackNumber, hcsNotificationSystemExited, nil) + if err != nil && err != expected { + return makeSystemError(computeSystem, "WaitExpectedError", "", err, nil) + } + return nil } // WaitTimeout synchronously waits for the compute system to terminate or the duration to elapse. // If the timeout expires, IsTimeout(err) == true -func (computeSystem *System) WaitTimeout(timeout time.Duration) error { - title := "hcsshim::ComputeSystem::WaitTimeout ID=" + computeSystem.ID() - logrus.Debugf(title) +func (computeSystem *System) WaitTimeout(timeout time.Duration) (err error) { + operation := "hcsshim::ComputeSystem::WaitTimeout" + computeSystem.logOperationBegin(operation) + defer func() { computeSystem.logOperationEnd(err) }() - err := waitForNotification(computeSystem.callbackNumber, hcsNotificationSystemExited, &timeout) + err = waitForNotification(computeSystem.callbackNumber, hcsNotificationSystemExited, &timeout) if err != nil { return makeSystemError(computeSystem, "WaitTimeout", "", err, nil) } - logrus.Debugf(title + " succeeded") return nil } -func (computeSystem *System) Properties(types ...schema1.PropertyType) (*schema1.ContainerProperties, error) { +func (computeSystem *System) Properties(types ...schema1.PropertyType) (_ *schema1.ContainerProperties, err error) { computeSystem.handleLock.RLock() defer computeSystem.handleLock.RUnlock() + operation := "hcsshim::ComputeSystem::Properties" + computeSystem.logOperationBegin(operation) + defer func() { computeSystem.logOperationEnd(err) }() + queryj, err := json.Marshal(schema1.PropertyQuery{types}) if err != nil { return nil, makeSystemError(computeSystem, "Properties", "", err, nil) } + logrus.WithFields(computeSystem.logctx). + WithField(logfields.JSON, queryj). + Debug("HCS ComputeSystem Properties Query") + var resultp, propertiesp *uint16 - completed := false - go syscallWatcher(fmt.Sprintf("GetComputeSystemProperties %s:", computeSystem.ID()), &completed) - err = hcsGetComputeSystemProperties(computeSystem.handle, string(queryj), &propertiesp, &resultp) - completed = true + syscallWatcher(computeSystem.logctx, func() { + err = hcsGetComputeSystemProperties(computeSystem.handle, string(queryj), &propertiesp, &resultp) + }) events := processHcsResult(resultp) if err != nil { return nil, makeSystemError(computeSystem, "Properties", "", err, events) @@ -324,64 +418,69 @@ func (computeSystem *System) Properties(types ...schema1.PropertyType) (*schema1 if err := json.Unmarshal(propertiesRaw, properties); err != nil { return nil, makeSystemError(computeSystem, "Properties", "", err, nil) } + return properties, nil } // Pause pauses the execution of the computeSystem. This feature is not enabled in TP5. -func (computeSystem *System) Pause() error { +func (computeSystem *System) Pause() (err error) { computeSystem.handleLock.RLock() defer computeSystem.handleLock.RUnlock() - title := "hcsshim::ComputeSystem::Pause ID=" + computeSystem.ID() - logrus.Debugf(title) + + operation := "hcsshim::ComputeSystem::Pause" + computeSystem.logOperationBegin(operation) + defer func() { computeSystem.logOperationEnd(err) }() if computeSystem.handle == 0 { return makeSystemError(computeSystem, "Pause", "", ErrAlreadyClosed, nil) } var resultp *uint16 - completed := false - go syscallWatcher(fmt.Sprintf("PauseComputeSystem %s:", computeSystem.ID()), &completed) - err := hcsPauseComputeSystem(computeSystem.handle, "", &resultp) - completed = true + syscallWatcher(computeSystem.logctx, func() { + err = hcsPauseComputeSystem(computeSystem.handle, "", &resultp) + }) events, err := processAsyncHcsResult(err, resultp, computeSystem.callbackNumber, hcsNotificationSystemPauseCompleted, &timeout.SystemPause) if err != nil { return makeSystemError(computeSystem, "Pause", "", err, events) } - logrus.Debugf(title + " succeeded") return nil } // Resume resumes the execution of the computeSystem. This feature is not enabled in TP5. -func (computeSystem *System) Resume() error { +func (computeSystem *System) Resume() (err error) { computeSystem.handleLock.RLock() defer computeSystem.handleLock.RUnlock() - title := "hcsshim::ComputeSystem::Resume ID=" + computeSystem.ID() - logrus.Debugf(title) + + operation := "hcsshim::ComputeSystem::Resume" + computeSystem.logOperationBegin(operation) + defer func() { computeSystem.logOperationEnd(err) }() if computeSystem.handle == 0 { return makeSystemError(computeSystem, "Resume", "", ErrAlreadyClosed, nil) } var resultp *uint16 - completed := false - go syscallWatcher(fmt.Sprintf("ResumeComputeSystem %s:", computeSystem.ID()), &completed) - err := hcsResumeComputeSystem(computeSystem.handle, "", &resultp) - completed = true + syscallWatcher(computeSystem.logctx, func() { + err = hcsResumeComputeSystem(computeSystem.handle, "", &resultp) + }) events, err := processAsyncHcsResult(err, resultp, computeSystem.callbackNumber, hcsNotificationSystemResumeCompleted, &timeout.SystemResume) if err != nil { return makeSystemError(computeSystem, "Resume", "", err, events) } - logrus.Debugf(title + " succeeded") return nil } // CreateProcess launches a new process within the computeSystem. -func (computeSystem *System) CreateProcess(c interface{}) (*Process, error) { +func (computeSystem *System) CreateProcess(c interface{}) (_ *Process, err error) { computeSystem.handleLock.RLock() defer computeSystem.handleLock.RUnlock() - title := "hcsshim::ComputeSystem::CreateProcess ID=" + computeSystem.ID() + + operation := "hcsshim::ComputeSystem::CreateProcess" + computeSystem.logOperationBegin(operation) + defer func() { computeSystem.logOperationEnd(err) }() + var ( processInfo hcsProcessInformation processHandle hcsProcess @@ -398,42 +497,50 @@ func (computeSystem *System) CreateProcess(c interface{}) (*Process, error) { } configuration := string(configurationb) - logrus.Debugf(title+" config=%s", configuration) - completed := false - go syscallWatcher(fmt.Sprintf("CreateProcess %s: %s", computeSystem.ID(), configuration), &completed) - err = hcsCreateProcess(computeSystem.handle, configuration, &processInfo, &processHandle, &resultp) - completed = true + logrus.WithFields(computeSystem.logctx). + WithField(logfields.JSON, configuration). + Debug("HCS ComputeSystem Process Document") + + syscallWatcher(computeSystem.logctx, func() { + err = hcsCreateProcess(computeSystem.handle, configuration, &processInfo, &processHandle, &resultp) + }) events := processHcsResult(resultp) if err != nil { return nil, makeSystemError(computeSystem, "CreateProcess", configuration, err, events) } - process := &Process{ - handle: processHandle, - processID: int(processInfo.ProcessId), - system: computeSystem, - cachedPipes: &cachedPipes{ - stdIn: processInfo.StdInput, - stdOut: processInfo.StdOutput, - stdErr: processInfo.StdError, - }, + logrus.WithFields(computeSystem.logctx). + WithField(logfields.ProcessID, processInfo.ProcessId). + Debug("HCS ComputeSystem CreateProcess PID") + + process := newProcess(processHandle, int(processInfo.ProcessId), computeSystem) + process.cachedPipes = &cachedPipes{ + stdIn: processInfo.StdInput, + stdOut: processInfo.StdOutput, + stdErr: processInfo.StdError, } - if err := process.registerCallback(); err != nil { + if err = process.registerCallback(); err != nil { return nil, makeSystemError(computeSystem, "CreateProcess", "", err, nil) } - logrus.Debugf(title+" succeeded processid=%d", process.processID) return process, nil } // OpenProcess gets an interface to an existing process within the computeSystem. -func (computeSystem *System) OpenProcess(pid int) (*Process, error) { +func (computeSystem *System) OpenProcess(pid int) (_ *Process, err error) { computeSystem.handleLock.RLock() defer computeSystem.handleLock.RUnlock() - title := "hcsshim::ComputeSystem::OpenProcess ID=" + computeSystem.ID() - logrus.Debugf(title+" processid=%d", pid) + + // Add PID for the context of this operation + computeSystem.logctx[logfields.ProcessID] = pid + defer delete(computeSystem.logctx, logfields.ProcessID) + + operation := "hcsshim::ComputeSystem::OpenProcess" + computeSystem.logOperationBegin(operation) + defer func() { computeSystem.logOperationEnd(err) }() + var ( processHandle hcsProcess resultp *uint16 @@ -443,56 +550,49 @@ func (computeSystem *System) OpenProcess(pid int) (*Process, error) { return nil, makeSystemError(computeSystem, "OpenProcess", "", ErrAlreadyClosed, nil) } - completed := false - go syscallWatcher(fmt.Sprintf("OpenProcess %s: %d", computeSystem.ID(), pid), &completed) - err := hcsOpenProcess(computeSystem.handle, uint32(pid), &processHandle, &resultp) - completed = true + syscallWatcher(computeSystem.logctx, func() { + err = hcsOpenProcess(computeSystem.handle, uint32(pid), &processHandle, &resultp) + }) events := processHcsResult(resultp) if err != nil { return nil, makeSystemError(computeSystem, "OpenProcess", "", err, events) } - process := &Process{ - handle: processHandle, - processID: pid, - system: computeSystem, - } - - if err := process.registerCallback(); err != nil { + process := newProcess(processHandle, pid, computeSystem) + if err = process.registerCallback(); err != nil { return nil, makeSystemError(computeSystem, "OpenProcess", "", err, nil) } - logrus.Debugf(title+" succeeded processid=%s", process.processID) return process, nil } // Close cleans up any state associated with the compute system but does not terminate or wait for it. -func (computeSystem *System) Close() error { +func (computeSystem *System) Close() (err error) { computeSystem.handleLock.Lock() defer computeSystem.handleLock.Unlock() - title := "hcsshim::ComputeSystem::Close ID=" + computeSystem.ID() - logrus.Debugf(title) + + operation := "hcsshim::ComputeSystem::Close" + computeSystem.logOperationBegin(operation) + defer func() { computeSystem.logOperationEnd(err) }() // Don't double free this if computeSystem.handle == 0 { return nil } - if err := computeSystem.unregisterCallback(); err != nil { + if err = computeSystem.unregisterCallback(); err != nil { return makeSystemError(computeSystem, "Close", "", err, nil) } - completed := false - go syscallWatcher(fmt.Sprintf("CloseComputeSystem %s:", computeSystem.ID()), &completed) - err := hcsCloseComputeSystem(computeSystem.handle) - completed = true + syscallWatcher(computeSystem.logctx, func() { + err = hcsCloseComputeSystem(computeSystem.handle) + }) if err != nil { return makeSystemError(computeSystem, "Close", "", err, nil) } computeSystem.handle = 0 - logrus.Debugf(title + " succeeded") return nil } @@ -553,11 +653,14 @@ func (computeSystem *System) unregisterCallback() error { return nil } -// Modifies the System by sending a request to HCS -func (computeSystem *System) Modify(config interface{}) error { +// Modify the System by sending a request to HCS +func (computeSystem *System) Modify(config interface{}) (err error) { computeSystem.handleLock.RLock() defer computeSystem.handleLock.RUnlock() - title := "hcsshim::Modify ID=" + computeSystem.id + + operation := "hcsshim::ComputeSystem::Modify" + computeSystem.logOperationBegin(operation) + defer func() { computeSystem.logOperationEnd(err) }() if computeSystem.handle == 0 { return makeSystemError(computeSystem, "Modify", "", ErrAlreadyClosed, nil) @@ -569,17 +672,19 @@ func (computeSystem *System) Modify(config interface{}) error { } requestString := string(requestJSON) - logrus.Debugf(title + " " + requestString) + + logrus.WithFields(computeSystem.logctx). + WithField(logfields.JSON, requestString). + Debug("HCS ComputeSystem Modify Document") var resultp *uint16 - completed := false - go syscallWatcher(fmt.Sprintf("ModifyComputeSystem %s: %s", computeSystem.ID(), requestString), &completed) - err = hcsModifyComputeSystem(computeSystem.handle, requestString, &resultp) - completed = true + syscallWatcher(computeSystem.logctx, func() { + err = hcsModifyComputeSystem(computeSystem.handle, requestString, &resultp) + }) events := processHcsResult(resultp) if err != nil { return makeSystemError(computeSystem, "Modify", requestString, err, events) } - logrus.Debugf(title + " succeeded ") + return nil } diff --git a/vendor/github.com/Microsoft/hcsshim/internal/hcs/watcher.go b/vendor/github.com/Microsoft/hcsshim/internal/hcs/watcher.go index 6b94bc9ff..f85ed3187 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/hcs/watcher.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/hcs/watcher.go @@ -1,8 +1,9 @@ package hcs import ( - "time" + "context" + "github.com/Microsoft/hcsshim/internal/logfields" "github.com/Microsoft/hcsshim/internal/timeout" "github.com/sirupsen/logrus" ) @@ -16,15 +17,25 @@ import ( // // Usage is: // -// completed := false -// go syscallWatcher("some description", &completed) -// -// completed = true +// syscallWatcher(logContext, func() { +// err = (args...) +// }) // -func syscallWatcher(description string, syscallCompleted *bool) { - time.Sleep(timeout.SyscallWatcher) - if *syscallCompleted { - return - } - logrus.Warnf("%s: Did not complete within %s. This may indicate a platform issue. If it appears to be making no forward progress, obtain the stacks and see is there is a syscall stuck in the platform API for a significant length of time.", description, timeout.SyscallWatcher) + +func syscallWatcher(logContext logrus.Fields, syscallLambda func()) { + ctx, cancel := context.WithTimeout(context.Background(), timeout.SyscallWatcher) + defer cancel() + go watchFunc(ctx, logContext) + syscallLambda() +} + +func watchFunc(ctx context.Context, logContext logrus.Fields) { + select { + case <-ctx.Done(): + if ctx.Err() != context.Canceled { + logrus.WithFields(logContext). + WithField(logfields.Timeout, timeout.SyscallWatcher). + Warning("Syscall did not complete within operation timeout. This may indicate a platform issue. If it appears to be making no forward progress, obtain the stacks and see if there is a syscall stuck in the platform API for a significant length of time.") + } + } } diff --git a/vendor/github.com/Microsoft/hcsshim/internal/hcs/zsyscall_windows.go b/vendor/github.com/Microsoft/hcsshim/internal/hcs/zsyscall_windows.go index 925c65e28..fcd5cdc87 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/hcs/zsyscall_windows.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/hcs/zsyscall_windows.go @@ -1,4 +1,4 @@ -// MACHINE GENERATED BY 'go generate' COMMAND; DO NOT EDIT +// Code generated mksyscall_windows.exe DO NOT EDIT package hcs @@ -6,7 +6,6 @@ import ( "syscall" "unsafe" - "github.com/Microsoft/hcsshim/internal/interop" "golang.org/x/sys/windows" ) @@ -81,7 +80,10 @@ func _hcsEnumerateComputeSystems(query *uint16, computeSystems **uint16, result } r0, _, _ := syscall.Syscall(procHcsEnumerateComputeSystems.Addr(), 3, uintptr(unsafe.Pointer(query)), uintptr(unsafe.Pointer(computeSystems)), uintptr(unsafe.Pointer(result))) if int32(r0) < 0 { - hr = interop.Win32FromHresult(r0) + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) } return } @@ -106,7 +108,10 @@ func _hcsCreateComputeSystem(id *uint16, configuration *uint16, identity syscall } r0, _, _ := syscall.Syscall6(procHcsCreateComputeSystem.Addr(), 5, uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(configuration)), uintptr(identity), uintptr(unsafe.Pointer(computeSystem)), uintptr(unsafe.Pointer(result)), 0) if int32(r0) < 0 { - hr = interop.Win32FromHresult(r0) + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) } return } @@ -126,7 +131,10 @@ func _hcsOpenComputeSystem(id *uint16, computeSystem *hcsSystem, result **uint16 } r0, _, _ := syscall.Syscall(procHcsOpenComputeSystem.Addr(), 3, uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(computeSystem)), uintptr(unsafe.Pointer(result))) if int32(r0) < 0 { - hr = interop.Win32FromHresult(r0) + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) } return } @@ -137,7 +145,10 @@ func hcsCloseComputeSystem(computeSystem hcsSystem) (hr error) { } r0, _, _ := syscall.Syscall(procHcsCloseComputeSystem.Addr(), 1, uintptr(computeSystem), 0, 0) if int32(r0) < 0 { - hr = interop.Win32FromHresult(r0) + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) } return } @@ -157,7 +168,10 @@ func _hcsStartComputeSystem(computeSystem hcsSystem, options *uint16, result **u } r0, _, _ := syscall.Syscall(procHcsStartComputeSystem.Addr(), 3, uintptr(computeSystem), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(result))) if int32(r0) < 0 { - hr = interop.Win32FromHresult(r0) + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) } return } @@ -177,7 +191,10 @@ func _hcsShutdownComputeSystem(computeSystem hcsSystem, options *uint16, result } r0, _, _ := syscall.Syscall(procHcsShutdownComputeSystem.Addr(), 3, uintptr(computeSystem), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(result))) if int32(r0) < 0 { - hr = interop.Win32FromHresult(r0) + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) } return } @@ -197,7 +214,10 @@ func _hcsTerminateComputeSystem(computeSystem hcsSystem, options *uint16, result } r0, _, _ := syscall.Syscall(procHcsTerminateComputeSystem.Addr(), 3, uintptr(computeSystem), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(result))) if int32(r0) < 0 { - hr = interop.Win32FromHresult(r0) + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) } return } @@ -217,7 +237,10 @@ func _hcsPauseComputeSystem(computeSystem hcsSystem, options *uint16, result **u } r0, _, _ := syscall.Syscall(procHcsPauseComputeSystem.Addr(), 3, uintptr(computeSystem), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(result))) if int32(r0) < 0 { - hr = interop.Win32FromHresult(r0) + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) } return } @@ -237,7 +260,10 @@ func _hcsResumeComputeSystem(computeSystem hcsSystem, options *uint16, result ** } r0, _, _ := syscall.Syscall(procHcsResumeComputeSystem.Addr(), 3, uintptr(computeSystem), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(result))) if int32(r0) < 0 { - hr = interop.Win32FromHresult(r0) + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) } return } @@ -257,7 +283,10 @@ func _hcsGetComputeSystemProperties(computeSystem hcsSystem, propertyQuery *uint } r0, _, _ := syscall.Syscall6(procHcsGetComputeSystemProperties.Addr(), 4, uintptr(computeSystem), uintptr(unsafe.Pointer(propertyQuery)), uintptr(unsafe.Pointer(properties)), uintptr(unsafe.Pointer(result)), 0, 0) if int32(r0) < 0 { - hr = interop.Win32FromHresult(r0) + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) } return } @@ -277,7 +306,10 @@ func _hcsModifyComputeSystem(computeSystem hcsSystem, configuration *uint16, res } r0, _, _ := syscall.Syscall(procHcsModifyComputeSystem.Addr(), 3, uintptr(computeSystem), uintptr(unsafe.Pointer(configuration)), uintptr(unsafe.Pointer(result))) if int32(r0) < 0 { - hr = interop.Win32FromHresult(r0) + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) } return } @@ -288,7 +320,10 @@ func hcsRegisterComputeSystemCallback(computeSystem hcsSystem, callback uintptr, } r0, _, _ := syscall.Syscall6(procHcsRegisterComputeSystemCallback.Addr(), 4, uintptr(computeSystem), uintptr(callback), uintptr(context), uintptr(unsafe.Pointer(callbackHandle)), 0, 0) if int32(r0) < 0 { - hr = interop.Win32FromHresult(r0) + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) } return } @@ -299,7 +334,10 @@ func hcsUnregisterComputeSystemCallback(callbackHandle hcsCallback) (hr error) { } r0, _, _ := syscall.Syscall(procHcsUnregisterComputeSystemCallback.Addr(), 1, uintptr(callbackHandle), 0, 0) if int32(r0) < 0 { - hr = interop.Win32FromHresult(r0) + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) } return } @@ -319,7 +357,10 @@ func _hcsCreateProcess(computeSystem hcsSystem, processParameters *uint16, proce } r0, _, _ := syscall.Syscall6(procHcsCreateProcess.Addr(), 5, uintptr(computeSystem), uintptr(unsafe.Pointer(processParameters)), uintptr(unsafe.Pointer(processInformation)), uintptr(unsafe.Pointer(process)), uintptr(unsafe.Pointer(result)), 0) if int32(r0) < 0 { - hr = interop.Win32FromHresult(r0) + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) } return } @@ -330,7 +371,10 @@ func hcsOpenProcess(computeSystem hcsSystem, pid uint32, process *hcsProcess, re } r0, _, _ := syscall.Syscall6(procHcsOpenProcess.Addr(), 4, uintptr(computeSystem), uintptr(pid), uintptr(unsafe.Pointer(process)), uintptr(unsafe.Pointer(result)), 0, 0) if int32(r0) < 0 { - hr = interop.Win32FromHresult(r0) + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) } return } @@ -341,7 +385,10 @@ func hcsCloseProcess(process hcsProcess) (hr error) { } r0, _, _ := syscall.Syscall(procHcsCloseProcess.Addr(), 1, uintptr(process), 0, 0) if int32(r0) < 0 { - hr = interop.Win32FromHresult(r0) + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) } return } @@ -352,7 +399,10 @@ func hcsTerminateProcess(process hcsProcess, result **uint16) (hr error) { } r0, _, _ := syscall.Syscall(procHcsTerminateProcess.Addr(), 2, uintptr(process), uintptr(unsafe.Pointer(result)), 0) if int32(r0) < 0 { - hr = interop.Win32FromHresult(r0) + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) } return } @@ -372,7 +422,10 @@ func _hcsSignalProcess(process hcsProcess, options *uint16, result **uint16) (hr } r0, _, _ := syscall.Syscall(procHcsTerminateProcess.Addr(), 3, uintptr(process), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(result))) if int32(r0) < 0 { - hr = interop.Win32FromHresult(r0) + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) } return } @@ -383,7 +436,10 @@ func hcsGetProcessInfo(process hcsProcess, processInformation *hcsProcessInforma } r0, _, _ := syscall.Syscall(procHcsGetProcessInfo.Addr(), 3, uintptr(process), uintptr(unsafe.Pointer(processInformation)), uintptr(unsafe.Pointer(result))) if int32(r0) < 0 { - hr = interop.Win32FromHresult(r0) + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) } return } @@ -394,7 +450,10 @@ func hcsGetProcessProperties(process hcsProcess, processProperties **uint16, res } r0, _, _ := syscall.Syscall(procHcsGetProcessProperties.Addr(), 3, uintptr(process), uintptr(unsafe.Pointer(processProperties)), uintptr(unsafe.Pointer(result))) if int32(r0) < 0 { - hr = interop.Win32FromHresult(r0) + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) } return } @@ -414,7 +473,10 @@ func _hcsModifyProcess(process hcsProcess, settings *uint16, result **uint16) (h } r0, _, _ := syscall.Syscall(procHcsModifyProcess.Addr(), 3, uintptr(process), uintptr(unsafe.Pointer(settings)), uintptr(unsafe.Pointer(result))) if int32(r0) < 0 { - hr = interop.Win32FromHresult(r0) + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) } return } @@ -434,7 +496,10 @@ func _hcsGetServiceProperties(propertyQuery *uint16, properties **uint16, result } r0, _, _ := syscall.Syscall(procHcsGetServiceProperties.Addr(), 3, uintptr(unsafe.Pointer(propertyQuery)), uintptr(unsafe.Pointer(properties)), uintptr(unsafe.Pointer(result))) if int32(r0) < 0 { - hr = interop.Win32FromHresult(r0) + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) } return } @@ -445,7 +510,10 @@ func hcsRegisterProcessCallback(process hcsProcess, callback uintptr, context ui } r0, _, _ := syscall.Syscall6(procHcsRegisterProcessCallback.Addr(), 4, uintptr(process), uintptr(callback), uintptr(context), uintptr(unsafe.Pointer(callbackHandle)), 0, 0) if int32(r0) < 0 { - hr = interop.Win32FromHresult(r0) + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) } return } @@ -456,7 +524,10 @@ func hcsUnregisterProcessCallback(callbackHandle hcsCallback) (hr error) { } r0, _, _ := syscall.Syscall(procHcsUnregisterProcessCallback.Addr(), 1, uintptr(callbackHandle), 0, 0) if int32(r0) < 0 { - hr = interop.Win32FromHresult(r0) + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) } return } diff --git a/vendor/github.com/Microsoft/hcsshim/internal/hcserror/hcserror.go b/vendor/github.com/Microsoft/hcsshim/internal/hcserror/hcserror.go index c8d362c66..921c2c855 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/hcserror/hcserror.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/hcserror/hcserror.go @@ -36,10 +36,6 @@ func New(err error, title, rest string) error { return &HcsError{title, rest, err} } -func Errorf(err error, title, format string, a ...interface{}) error { - return New(err, title, fmt.Sprintf(format, a...)) -} - func Win32FromError(err error) uint32 { if herr, ok := err.(*HcsError); ok { return Win32FromError(herr.Err) diff --git a/vendor/github.com/Microsoft/hcsshim/internal/hns/hnsendpoint.go b/vendor/github.com/Microsoft/hcsshim/internal/hns/hnsendpoint.go index ce636458c..59ec7004c 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/hns/hnsendpoint.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/hns/hnsendpoint.go @@ -23,7 +23,9 @@ type HNSEndpoint struct { DisableICC bool `json:",omitempty"` PrefixLength uint8 `json:",omitempty"` IsRemoteEndpoint bool `json:",omitempty"` + EnableLowMetric bool `json:",omitempty"` Namespace *Namespace `json:",omitempty"` + EncapOverhead uint16 `json:",omitempty"` } //SystemType represents the type of the system on which actions are done diff --git a/vendor/github.com/Microsoft/hcsshim/internal/hns/hnspolicylist.go b/vendor/github.com/Microsoft/hcsshim/internal/hns/hnspolicylist.go index cc98b49e0..31322a681 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/hns/hnspolicylist.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/hns/hnspolicylist.go @@ -140,7 +140,7 @@ func (policylist *PolicyList) RemoveEndpoint(endpoint *HNSEndpoint) (*PolicyList } // AddLoadBalancer policy list for the specified endpoints -func AddLoadBalancer(endpoints []HNSEndpoint, isILB bool, isDSR bool, sourceVIP, vip string, protocol uint16, internalPort uint16, externalPort uint16) (*PolicyList, error) { +func AddLoadBalancer(endpoints []HNSEndpoint, isILB bool, sourceVIP, vip string, protocol uint16, internalPort uint16, externalPort uint16) (*PolicyList, error) { operation := "AddLoadBalancer" title := "hcsshim::PolicyList::" + operation logrus.Debugf(title+" endpointId=%v, isILB=%v, sourceVIP=%s, vip=%s, protocol=%v, internalPort=%v, externalPort=%v", endpoints, isILB, sourceVIP, vip, protocol, internalPort, externalPort) @@ -150,7 +150,6 @@ func AddLoadBalancer(endpoints []HNSEndpoint, isILB bool, isDSR bool, sourceVIP, elbPolicy := &ELBPolicy{ SourceVIP: sourceVIP, ILB: isILB, - DSR: isDSR, } if len(vip) > 0 { diff --git a/vendor/github.com/Microsoft/hcsshim/internal/hns/zsyscall_windows.go b/vendor/github.com/Microsoft/hcsshim/internal/hns/zsyscall_windows.go index 863e3429c..204633a48 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/hns/zsyscall_windows.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/hns/zsyscall_windows.go @@ -1,4 +1,4 @@ -// MACHINE GENERATED BY 'go generate' COMMAND; DO NOT EDIT +// Code generated mksyscall_windows.exe DO NOT EDIT package hns @@ -6,7 +6,6 @@ import ( "syscall" "unsafe" - "github.com/Microsoft/hcsshim/internal/interop" "golang.org/x/sys/windows" ) @@ -68,7 +67,10 @@ func __hnsCall(method *uint16, path *uint16, object *uint16, response **uint16) } r0, _, _ := syscall.Syscall6(procHNSCall.Addr(), 4, uintptr(unsafe.Pointer(method)), uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(object)), uintptr(unsafe.Pointer(response)), 0, 0) if int32(r0) < 0 { - hr = interop.Win32FromHresult(r0) + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) } return } diff --git a/vendor/github.com/Microsoft/hcsshim/internal/interop/interop.go b/vendor/github.com/Microsoft/hcsshim/internal/interop/interop.go index f10c88d08..2f6ec029e 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/interop/interop.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/interop/interop.go @@ -5,9 +5,9 @@ import ( "unsafe" ) -//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go interop.go +//go:generate go run ../../mksyscall_windows.go -output zsyscall_windows.go interop.go -//sys coTaskMemFree(buffer unsafe.Pointer) = ole32.CoTaskMemFree +//sys coTaskMemFree(buffer unsafe.Pointer) = api_ms_win_core_com_l1_1_0.CoTaskMemFree func ConvertAndFreeCoTaskMemString(buffer *uint16) string { str := syscall.UTF16ToString((*[1 << 29]uint16)(unsafe.Pointer(buffer))[:]) diff --git a/vendor/github.com/Microsoft/hcsshim/internal/interop/zsyscall_windows.go b/vendor/github.com/Microsoft/hcsshim/internal/interop/zsyscall_windows.go index 2f5bf8f55..12b0c71c5 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/interop/zsyscall_windows.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/interop/zsyscall_windows.go @@ -1,4 +1,4 @@ -// Code generated by 'go generate'; DO NOT EDIT. +// Code generated mksyscall_windows.exe DO NOT EDIT package interop @@ -37,9 +37,9 @@ func errnoErr(e syscall.Errno) error { } var ( - modole32 = windows.NewLazySystemDLL("ole32.dll") + modapi_ms_win_core_com_l1_1_0 = windows.NewLazySystemDLL("api-ms-win-core-com-l1-1-0.dll") - procCoTaskMemFree = modole32.NewProc("CoTaskMemFree") + procCoTaskMemFree = modapi_ms_win_core_com_l1_1_0.NewProc("CoTaskMemFree") ) func coTaskMemFree(buffer unsafe.Pointer) { diff --git a/vendor/github.com/Microsoft/hcsshim/internal/logfields/fields.go b/vendor/github.com/Microsoft/hcsshim/internal/logfields/fields.go new file mode 100644 index 000000000..a1527d706 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/logfields/fields.go @@ -0,0 +1,37 @@ +package logfields + +const ( + // Identifiers + + ContainerID = "cid" + UVMID = "uvm-id" + ProcessID = "pid" + + // Common Misc + + // Timeout represents an operation timeout. + Timeout = "timeout" + JSON = "json" + + // Keys/values + + Field = "field" + OCIAnnotation = "oci-annotation" + Value = "value" + + // Golang type's + + ExpectedType = "expected-type" + Bool = "bool" + Uint32 = "uint32" + Uint64 = "uint64" + + // HCS + + HCSOperation = "hcs-op" + HCSOperationResult = "hcs-op-result" + + // runhcs + + VMShimOperation = "vmshim-op" +) diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/chipset.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/chipset.go index 3fb24e250..ca75277a3 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/schema2/chipset.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/chipset.go @@ -10,7 +10,6 @@ package hcsschema type Chipset struct { - Uefi *Uefi `json:"Uefi,omitempty"` IsNumLockDisabled bool `json:"IsNumLockDisabled,omitempty"` @@ -22,4 +21,7 @@ type Chipset struct { ChassisAssetTag string `json:"ChassisAssetTag,omitempty"` UseUtc bool `json:"UseUtc,omitempty"` + + // LinuxKernelDirect - Added in v2.2 Builds >=181117 + LinuxKernelDirect *LinuxKernelDirect `json:"LinuxKernelDirect,omitempty"` } diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/linux_kernel_direct.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/linux_kernel_direct.go new file mode 100644 index 000000000..0ab6c280f --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/linux_kernel_direct.go @@ -0,0 +1,18 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.2 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type LinuxKernelDirect struct { + KernelFilePath string `json:"KernelFilePath,omitempty"` + + InitRdPath string `json:"InitRdPath,omitempty"` + + KernelCmdLine string `json:"KernelCmdLine,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/plan9_share.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/plan9_share.go index b2bc58b83..eb171817a 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/schema2/plan9_share.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/plan9_share.go @@ -20,6 +20,13 @@ type Plan9Share struct { Port int32 `json:"Port,omitempty"` + // Flags are marked private. Until they are exported correctly + // + // ReadOnly 0x00000001 + // LinuxMetadata 0x00000004 + // CaseSensitive 0x00000008 + Flags int32 `json:"Flags,omitempty"` + ReadOnly bool `json:"ReadOnly,omitempty"` UseShareRootIdentity bool `json:"UseShareRootIdentity,omitempty"` diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/virtual_machine.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/virtual_machine.go index 11f39eea7..2d22b1bcb 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/schema2/virtual_machine.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/virtual_machine.go @@ -11,6 +11,9 @@ package hcsschema type VirtualMachine struct { + // StopOnReset is private in the schema. If regenerated need to put back. + StopOnReset bool `json:"StopOnReset,omitempty"` + Chipset *Chipset `json:"Chipset,omitempty"` ComputeTopology *Topology `json:"ComputeTopology,omitempty"` diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/activatelayer.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/activatelayer.go index 3a0d4bc58..dcb919268 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/activatelayer.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/activatelayer.go @@ -9,17 +9,24 @@ import ( // For a read/write layer, the mounted filesystem will appear as a volume on the // host, while a read-only layer is generally expected to be a no-op. // An activated layer must later be deactivated via DeactivateLayer. -func ActivateLayer(path string) error { - title := "hcsshim::ActivateLayer " - logrus.Debugf(title+"path %s", path) - - err := activateLayer(&stdDriverInfo, path) - if err != nil { - err = hcserror.Errorf(err, title, "path=%s", path) - logrus.Error(err) - return err +func ActivateLayer(path string) (err error) { + title := "hcsshim::ActivateLayer" + fields := logrus.Fields{ + "path": path, } + logrus.WithFields(fields).Debug(title) + defer func() { + if err != nil { + fields[logrus.ErrorKey] = err + logrus.WithFields(fields).Error(err) + } else { + logrus.WithFields(fields).Debug(title + " - succeeded") + } + }() - logrus.Debugf(title+" - succeeded path=%s", path) + err = activateLayer(&stdDriverInfo, path) + if err != nil { + return hcserror.New(err, title+" - failed", "") + } return nil } diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/createlayer.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/createlayer.go index d15817730..be2bc3fd6 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/createlayer.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/createlayer.go @@ -7,17 +7,25 @@ import ( // CreateLayer creates a new, empty, read-only layer on the filesystem based on // the parent layer provided. -func CreateLayer(path, parent string) error { - title := "hcsshim::CreateLayer " - logrus.Debugf(title+"ID %s parent %s", path, parent) - - err := createLayer(&stdDriverInfo, path, parent) - if err != nil { - err = hcserror.Errorf(err, title, "path=%s parent=%s", path, parent) - logrus.Error(err) - return err +func CreateLayer(path, parent string) (err error) { + title := "hcsshim::CreateLayer" + fields := logrus.Fields{ + "parent": parent, + "path": path, } + logrus.WithFields(fields).Debug(title) + defer func() { + if err != nil { + fields[logrus.ErrorKey] = err + logrus.WithFields(fields).Error(err) + } else { + logrus.WithFields(fields).Debug(title + " - succeeded") + } + }() - logrus.Debugf(title+"- succeeded path=%s parent=%s", path, parent) + err = createLayer(&stdDriverInfo, path, parent) + if err != nil { + return hcserror.New(err, title+" - failed", "") + } return nil } diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/createscratchlayer.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/createscratchlayer.go index bf2fece19..7e3351289 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/createscratchlayer.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/createscratchlayer.go @@ -9,9 +9,20 @@ import ( // This requires both the id of the direct parent layer, as well as the full list // of paths to all parent layers up to the base (and including the direct parent // whose id was provided). -func CreateScratchLayer(path string, parentLayerPaths []string) error { - title := "hcsshim::CreateScratchLayer " - logrus.Debugf(title+"path %s", path) +func CreateScratchLayer(path string, parentLayerPaths []string) (err error) { + title := "hcsshim::CreateScratchLayer" + fields := logrus.Fields{ + "path": path, + } + logrus.WithFields(fields).Debug(title) + defer func() { + if err != nil { + fields[logrus.ErrorKey] = err + logrus.WithFields(fields).Error(err) + } else { + logrus.WithFields(fields).Debug(title + " - succeeded") + } + }() // Generate layer descriptors layers, err := layerPathsToDescriptors(parentLayerPaths) @@ -21,11 +32,7 @@ func CreateScratchLayer(path string, parentLayerPaths []string) error { err = createSandboxLayer(&stdDriverInfo, path, 0, layers) if err != nil { - err = hcserror.Errorf(err, title, "path=%s", path) - logrus.Error(err) - return err + return hcserror.New(err, title+" - failed", "") } - - logrus.Debugf(title+"- succeeded path=%s", path) return nil } diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/deactivatelayer.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/deactivatelayer.go index b998f8a19..2dd5d5715 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/deactivatelayer.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/deactivatelayer.go @@ -6,17 +6,24 @@ import ( ) // DeactivateLayer will dismount a layer that was mounted via ActivateLayer. -func DeactivateLayer(path string) error { - title := "hcsshim::DeactivateLayer " - logrus.Debugf(title+"path %s", path) - - err := deactivateLayer(&stdDriverInfo, path) - if err != nil { - err = hcserror.Errorf(err, title, "path=%s", path) - logrus.Error(err) - return err +func DeactivateLayer(path string) (err error) { + title := "hcsshim::DeactivateLayer" + fields := logrus.Fields{ + "path": path, } + logrus.WithFields(fields).Debug(title) + defer func() { + if err != nil { + fields[logrus.ErrorKey] = err + logrus.WithFields(fields).Error(err) + } else { + logrus.WithFields(fields).Debug(title + " - succeeded") + } + }() - logrus.Debugf(title+"succeeded path=%s", path) + err = deactivateLayer(&stdDriverInfo, path) + if err != nil { + return hcserror.New(err, title+"- failed", "") + } return nil } diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/destroylayer.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/destroylayer.go index dc14cecc4..4da690c20 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/destroylayer.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/destroylayer.go @@ -7,17 +7,24 @@ import ( // DestroyLayer will remove the on-disk files representing the layer with the given // path, including that layer's containing folder, if any. -func DestroyLayer(path string) error { - title := "hcsshim::DestroyLayer " - logrus.Debugf(title+"path %s", path) - - err := destroyLayer(&stdDriverInfo, path) - if err != nil { - err = hcserror.Errorf(err, title, "path=%s", path) - logrus.Error(err) - return err +func DestroyLayer(path string) (err error) { + title := "hcsshim::DestroyLayer" + fields := logrus.Fields{ + "path": path, } + logrus.WithFields(fields).Debug(title) + defer func() { + if err != nil { + fields[logrus.ErrorKey] = err + logrus.WithFields(fields).Error(err) + } else { + logrus.WithFields(fields).Debug(title + " - succeeded") + } + }() - logrus.Debugf(title+"succeeded path=%s", path) + err = destroyLayer(&stdDriverInfo, path) + if err != nil { + return hcserror.New(err, title+" - failed", "") + } return nil } diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/expandscratchsize.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/expandscratchsize.go index 7832bb452..651676fb2 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/expandscratchsize.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/expandscratchsize.go @@ -6,17 +6,25 @@ import ( ) // ExpandScratchSize expands the size of a layer to at least size bytes. -func ExpandScratchSize(path string, size uint64) error { - title := "hcsshim::ExpandScratchSize " - logrus.Debugf(title+"path=%s size=%d", path, size) - - err := expandSandboxSize(&stdDriverInfo, path, size) - if err != nil { - err = hcserror.Errorf(err, title, "path=%s size=%d", path, size) - logrus.Error(err) - return err +func ExpandScratchSize(path string, size uint64) (err error) { + title := "hcsshim::ExpandScratchSize" + fields := logrus.Fields{ + "path": path, + "size": size, } + logrus.WithFields(fields).Debug(title) + defer func() { + if err != nil { + fields[logrus.ErrorKey] = err + logrus.WithFields(fields).Error(err) + } else { + logrus.WithFields(fields).Debug(title + " - succeeded") + } + }() - logrus.Debugf(title+"- succeeded path=%s size=%d", path, size) + err = expandSandboxSize(&stdDriverInfo, path, size) + if err != nil { + return hcserror.New(err, title+" - failed", "") + } return nil } diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/exportlayer.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/exportlayer.go index c6b3480ce..0425b3395 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/exportlayer.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/exportlayer.go @@ -1,14 +1,11 @@ package wclayer import ( - "io" "io/ioutil" "os" - "syscall" "github.com/Microsoft/go-winio" "github.com/Microsoft/hcsshim/internal/hcserror" - "github.com/Microsoft/hcsshim/internal/interop" "github.com/sirupsen/logrus" ) @@ -17,9 +14,21 @@ import ( // format includes any metadata required for later importing the layer (using // ImportLayer), and requires the full list of parent layer paths in order to // perform the export. -func ExportLayer(path string, exportFolderPath string, parentLayerPaths []string) error { - title := "hcsshim::ExportLayer " - logrus.Debugf(title+"path %s folder %s", path, exportFolderPath) +func ExportLayer(path string, exportFolderPath string, parentLayerPaths []string) (err error) { + title := "hcsshim::ExportLayer" + fields := logrus.Fields{ + "path": path, + "exportFolderPath": exportFolderPath, + } + logrus.WithFields(fields).Debug(title) + defer func() { + if err != nil { + fields[logrus.ErrorKey] = err + logrus.WithFields(fields).Error(err) + } else { + logrus.WithFields(fields).Debug(title + " - succeeded") + } + }() // Generate layer descriptors layers, err := layerPathsToDescriptors(parentLayerPaths) @@ -29,12 +38,8 @@ func ExportLayer(path string, exportFolderPath string, parentLayerPaths []string err = exportLayer(&stdDriverInfo, path, exportFolderPath, layers) if err != nil { - err = hcserror.Errorf(err, title, "path=%s folder=%s", path, exportFolderPath) - logrus.Error(err) - return err + return hcserror.New(err, title+" - failed", "") } - - logrus.Debugf(title+"succeeded path=%s folder=%s", path, exportFolderPath) return nil } @@ -44,96 +49,20 @@ type LayerReader interface { Close() error } -// FilterLayerReader provides an interface for extracting the contents of an on-disk layer. -type FilterLayerReader struct { - context uintptr -} - -// Next reads the next available file from a layer, ensuring that parent directories are always read -// before child files and directories. -// -// Next returns the file's relative path, size, and basic file metadata. Read() should be used to -// extract a Win32 backup stream with the remainder of the metadata and the data. -func (r *FilterLayerReader) Next() (string, int64, *winio.FileBasicInfo, error) { - var fileNamep *uint16 - fileInfo := &winio.FileBasicInfo{} - var deleted uint32 - var fileSize int64 - err := exportLayerNext(r.context, &fileNamep, fileInfo, &fileSize, &deleted) - if err != nil { - if err == syscall.ERROR_NO_MORE_FILES { - err = io.EOF - } else { - err = hcserror.New(err, "ExportLayerNext", "") - } - return "", 0, nil, err - } - fileName := interop.ConvertAndFreeCoTaskMemString(fileNamep) - if deleted != 0 { - fileInfo = nil - } - if fileName[0] == '\\' { - fileName = fileName[1:] - } - return fileName, fileSize, fileInfo, nil -} - -// Read reads from the current file's Win32 backup stream. -func (r *FilterLayerReader) Read(b []byte) (int, error) { - var bytesRead uint32 - err := exportLayerRead(r.context, b, &bytesRead) - if err != nil { - return 0, hcserror.New(err, "ExportLayerRead", "") - } - if bytesRead == 0 { - return 0, io.EOF - } - return int(bytesRead), nil -} - -// Close frees resources associated with the layer reader. It will return an -// error if there was an error while reading the layer or of the layer was not -// completely read. -func (r *FilterLayerReader) Close() (err error) { - if r.context != 0 { - err = exportLayerEnd(r.context) - if err != nil { - err = hcserror.New(err, "ExportLayerEnd", "") - } - r.context = 0 - } - return -} - // NewLayerReader returns a new layer reader for reading the contents of an on-disk layer. // The caller must have taken the SeBackupPrivilege privilege // to call this and any methods on the resulting LayerReader. func NewLayerReader(path string, parentLayerPaths []string) (LayerReader, error) { - if procExportLayerBegin.Find() != nil { - // The new layer reader is not available on this Windows build. Fall back to the - // legacy export code path. - exportPath, err := ioutil.TempDir("", "hcs") - if err != nil { - return nil, err - } - err = ExportLayer(path, exportPath, parentLayerPaths) - if err != nil { - os.RemoveAll(exportPath) - return nil, err - } - return &legacyLayerReaderWrapper{newLegacyLayerReader(exportPath)}, nil - } - - layers, err := layerPathsToDescriptors(parentLayerPaths) + exportPath, err := ioutil.TempDir("", "hcs") if err != nil { return nil, err } - r := &FilterLayerReader{} - err = exportLayerBegin(&stdDriverInfo, path, layers, &r.context) + err = ExportLayer(path, exportPath, parentLayerPaths) if err != nil { - return nil, hcserror.New(err, "ExportLayerBegin", "") + os.RemoveAll(exportPath) + return nil, err } - return r, err + return &legacyLayerReaderWrapper{newLegacyLayerReader(exportPath)}, nil } type legacyLayerReaderWrapper struct { diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/getlayermountpath.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/getlayermountpath.go index 8c37549a0..d60b6ed53 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/getlayermountpath.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/getlayermountpath.go @@ -11,20 +11,29 @@ import ( // the path at which that layer can be accessed. This path may be a volume path // if the layer is a mounted read-write layer, otherwise it is expected to be the // folder path at which the layer is stored. -func GetLayerMountPath(path string) (string, error) { - title := "hcsshim::GetLayerMountPath " - logrus.Debugf(title+"path %s", path) +func GetLayerMountPath(path string) (_ string, err error) { + title := "hcsshim::GetLayerMountPath" + fields := logrus.Fields{ + "path": path, + } + logrus.WithFields(fields).Debug(title) + defer func() { + if err != nil { + fields[logrus.ErrorKey] = err + logrus.WithFields(fields).Error(err) + } else { + logrus.WithFields(fields).Debug(title + " - succeeded") + } + }() var mountPathLength uintptr mountPathLength = 0 // Call the procedure itself. - logrus.Debugf("Calling proc (1)") - err := getLayerMountPath(&stdDriverInfo, path, &mountPathLength, nil) + logrus.WithFields(fields).Debug("Calling proc (1)") + err = getLayerMountPath(&stdDriverInfo, path, &mountPathLength, nil) if err != nil { - err = hcserror.Errorf(err, title, "(first call) path=%s", path) - logrus.Error(err) - return "", err + return "", hcserror.New(err, title+" - failed", "(first call)") } // Allocate a mount path of the returned length. @@ -35,15 +44,13 @@ func GetLayerMountPath(path string) (string, error) { mountPathp[0] = 0 // Call the procedure again - logrus.Debugf("Calling proc (2)") + logrus.WithFields(fields).Debug("Calling proc (2)") err = getLayerMountPath(&stdDriverInfo, path, &mountPathLength, &mountPathp[0]) if err != nil { - err = hcserror.Errorf(err, title, "(second call) path=%s", path) - logrus.Error(err) - return "", err + return "", hcserror.New(err, title+" - failed", "(second call)") } mountPath := syscall.UTF16ToString(mountPathp[0:]) - logrus.Debugf(title+"succeeded path=%s mountPath=%s", path, mountPath) + fields["mountPath"] = mountPath return mountPath, nil } diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/getsharedbaseimages.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/getsharedbaseimages.go index 10899c68a..dbd83ef2b 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/getsharedbaseimages.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/getsharedbaseimages.go @@ -10,17 +10,20 @@ import ( // image store and return descriptive info about those images for the purpose // of registering them with the graphdriver, graph, and tagstore. func GetSharedBaseImages() (imageData string, err error) { - title := "hcsshim::GetSharedBaseImages " + title := "hcsshim::GetSharedBaseImages" + logrus.Debug(title) + defer func() { + if err != nil { + logrus.WithError(err).Error(err) + } else { + logrus.WithField("imageData", imageData).Debug(title + " - succeeded") + } + }() - logrus.Debugf("Calling proc") var buffer *uint16 err = getBaseImages(&buffer) if err != nil { - err = hcserror.New(err, title, "") - logrus.Error(err) - return + return "", hcserror.New(err, title+" - failed", "") } - imageData = interop.ConvertAndFreeCoTaskMemString(buffer) - logrus.Debugf(title+" - succeeded output=%s", imageData) - return + return interop.ConvertAndFreeCoTaskMemString(buffer), nil } diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/grantvmaccess.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/grantvmaccess.go index d86e67827..05735df6c 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/grantvmaccess.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/grantvmaccess.go @@ -1,24 +1,30 @@ package wclayer import ( - "fmt" - "github.com/Microsoft/hcsshim/internal/hcserror" "github.com/sirupsen/logrus" ) // GrantVmAccess adds access to a file for a given VM -func GrantVmAccess(vmid string, filepath string) error { - title := fmt.Sprintf("hcsshim::GrantVmAccess id:%s path:%s ", vmid, filepath) - logrus.Debugf(title) - - err := grantVmAccess(vmid, filepath) - if err != nil { - err = hcserror.Errorf(err, title, "path=%s", filepath) - logrus.Error(err) - return err +func GrantVmAccess(vmid string, filepath string) (err error) { + title := "hcsshim::GrantVmAccess" + fields := logrus.Fields{ + "vm-id": vmid, + "path": filepath, } + logrus.WithFields(fields).Debug(title) + defer func() { + if err != nil { + fields[logrus.ErrorKey] = err + logrus.WithFields(fields).Error(err) + } else { + logrus.WithFields(fields).Debug(title + " - succeeded") + } + }() - logrus.Debugf(title + " - succeeded") + err = grantVmAccess(vmid, filepath) + if err != nil { + return hcserror.New(err, title+" - failed", "") + } return nil } diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/importlayer.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/importlayer.go index c978450f8..76a804f2a 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/importlayer.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/importlayer.go @@ -1,7 +1,6 @@ package wclayer import ( - "errors" "io/ioutil" "os" "path/filepath" @@ -16,9 +15,21 @@ import ( // that into a layer with the id layerId. Note that in order to correctly populate // the layer and interperet the transport format, all parent layers must already // be present on the system at the paths provided in parentLayerPaths. -func ImportLayer(path string, importFolderPath string, parentLayerPaths []string) error { - title := "hcsshim::ImportLayer " - logrus.Debugf(title+"path %s folder %s", path, importFolderPath) +func ImportLayer(path string, importFolderPath string, parentLayerPaths []string) (err error) { + title := "hcsshim::ImportLayer" + fields := logrus.Fields{ + "path": path, + "importFolderPath": importFolderPath, + } + logrus.WithFields(fields).Debug(title) + defer func() { + if err != nil { + fields[logrus.ErrorKey] = err + logrus.WithFields(fields).Error(err) + } else { + logrus.WithFields(fields).Debug(title + " - succeeded") + } + }() // Generate layer descriptors layers, err := layerPathsToDescriptors(parentLayerPaths) @@ -28,12 +39,8 @@ func ImportLayer(path string, importFolderPath string, parentLayerPaths []string err = importLayer(&stdDriverInfo, path, importFolderPath, layers) if err != nil { - err = hcserror.Errorf(err, title, "path=%s folder=%s", path, importFolderPath) - logrus.Error(err) - return err + return hcserror.New(err, title+" - failed", "") } - - logrus.Debugf(title+"succeeded path=%s folder=%s", path, importFolderPath) return nil } @@ -52,69 +59,6 @@ type LayerWriter interface { Close() error } -// FilterLayerWriter provides an interface to write the contents of a layer to the file system. -type FilterLayerWriter struct { - context uintptr -} - -// Add adds a file or directory to the layer. The file's parent directory must have already been added. -// -// name contains the file's relative path. fileInfo contains file times and file attributes; the rest -// of the file metadata and the file data must be written as a Win32 backup stream to the Write() method. -// winio.BackupStreamWriter can be used to facilitate this. -func (w *FilterLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) error { - if name[0] != '\\' { - name = `\` + name - } - err := importLayerNext(w.context, name, fileInfo) - if err != nil { - return hcserror.New(err, "ImportLayerNext", "") - } - return nil -} - -// AddLink adds a hard link to the layer. The target of the link must have already been added. -func (w *FilterLayerWriter) AddLink(name string, target string) error { - return errors.New("hard links not yet supported") -} - -// Remove removes a file from the layer. The file must have been present in the parent layer. -// -// name contains the file's relative path. -func (w *FilterLayerWriter) Remove(name string) error { - if name[0] != '\\' { - name = `\` + name - } - err := importLayerNext(w.context, name, nil) - if err != nil { - return hcserror.New(err, "ImportLayerNext", "") - } - return nil -} - -// Write writes more backup stream data to the current file. -func (w *FilterLayerWriter) Write(b []byte) (int, error) { - err := importLayerWrite(w.context, b) - if err != nil { - err = hcserror.New(err, "ImportLayerWrite", "") - return 0, err - } - return len(b), err -} - -// Close completes the layer write operation. The error must be checked to ensure that the -// operation was successful. -func (w *FilterLayerWriter) Close() (err error) { - if w.context != 0 { - err = importLayerEnd(w.context) - if err != nil { - err = hcserror.New(err, "ImportLayerEnd", "") - } - w.context = 0 - } - return -} - type legacyLayerWriterWrapper struct { *legacyLayerWriter path string @@ -175,32 +119,17 @@ func NewLayerWriter(path string, parentLayerPaths []string) (LayerWriter, error) }, nil } - if procImportLayerBegin.Find() != nil { - // The new layer reader is not available on this Windows build. Fall back to the - // legacy export code path. - importPath, err := ioutil.TempDir("", "hcs") - if err != nil { - return nil, err - } - w, err := newLegacyLayerWriter(importPath, parentLayerPaths, path) - if err != nil { - return nil, err - } - return &legacyLayerWriterWrapper{ - legacyLayerWriter: w, - path: importPath, - parentLayerPaths: parentLayerPaths, - }, nil - } - layers, err := layerPathsToDescriptors(parentLayerPaths) + importPath, err := ioutil.TempDir("", "hcs") if err != nil { return nil, err } - - w := &FilterLayerWriter{} - err = importLayerBegin(&stdDriverInfo, path, layers, &w.context) + w, err := newLegacyLayerWriter(importPath, parentLayerPaths, path) if err != nil { - return nil, hcserror.New(err, "ImportLayerStart", "") + return nil, err } - return w, nil + return &legacyLayerWriterWrapper{ + legacyLayerWriter: w, + path: importPath, + parentLayerPaths: parentLayerPaths, + }, nil } diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/layerexists.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/layerexists.go index 71287ff8a..258167a57 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/layerexists.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/layerexists.go @@ -7,19 +7,27 @@ import ( // LayerExists will return true if a layer with the given id exists and is known // to the system. -func LayerExists(path string) (bool, error) { - title := "hcsshim::LayerExists " - logrus.Debugf(title+"path %s", path) +func LayerExists(path string) (_ bool, err error) { + title := "hcsshim::LayerExists" + fields := logrus.Fields{ + "path": path, + } + logrus.WithFields(fields).Debug(title) + defer func() { + if err != nil { + fields[logrus.ErrorKey] = err + logrus.WithFields(fields).Error(err) + } else { + logrus.WithFields(fields).Debug(title + " - succeeded") + } + }() // Call the procedure itself. var exists uint32 - err := layerExists(&stdDriverInfo, path, &exists) + err = layerExists(&stdDriverInfo, path, &exists) if err != nil { - err = hcserror.Errorf(err, title, "path=%s", path) - logrus.Error(err) - return false, err + return false, hcserror.New(err, title+" - failed", "") } - - logrus.Debugf(title+"succeeded path=%s exists=%d", path, exists) + fields["layer-exists"] = exists != 0 return exists != 0, nil } diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/layerutils.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/layerutils.go index a1b8b9882..6d0ae8a07 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/layerutils.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/layerutils.go @@ -75,13 +75,13 @@ func layerPathsToDescriptors(parentLayerPaths []string) ([]WC_LAYER_DESCRIPTOR, for i := 0; i < len(parentLayerPaths); i++ { g, err := LayerID(parentLayerPaths[i]) if err != nil { - logrus.Debugf("Failed to convert name to guid %s", err) + logrus.WithError(err).Debug("Failed to convert name to guid") return nil, err } p, err := syscall.UTF16PtrFromString(parentLayerPaths[i]) if err != nil { - logrus.Debugf("Failed conversion of parentLayerPath to pointer %s", err) + logrus.WithError(err).Debug("Failed conversion of parentLayerPath to pointer") return nil, err } diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/nametoguid.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/nametoguid.go index 741994ba4..45a63cf65 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/nametoguid.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/nametoguid.go @@ -10,15 +10,25 @@ import ( // Host Compute Service, ensuring GUIDs generated with the same string are common // across all clients. func NameToGuid(name string) (id guid.GUID, err error) { - title := "hcsshim::NameToGuid " + title := "hcsshim::NameToGuid" + fields := logrus.Fields{ + "name": name, + } + logrus.WithFields(fields).Debug(title) + defer func() { + if err != nil { + fields[logrus.ErrorKey] = err + logrus.WithFields(fields).Error(err) + } else { + logrus.WithFields(fields).Debug(title + " - succeeded") + } + }() err = nameToGuid(name, &id) if err != nil { - err = hcserror.Errorf(err, title, "name=%s", name) - logrus.Error(err) + err = hcserror.New(err, title+" - failed", "") return } - - logrus.Debugf(title+"name:%s guid:%s", name, id.String()) + fields["guid"] = id.String() return } diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/preparelayer.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/preparelayer.go index bd4005dc4..2b65b0186 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/preparelayer.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/preparelayer.go @@ -14,9 +14,20 @@ var prepareLayerLock sync.Mutex // parent layers, and is necessary in order to view or interact with the layer // as an actual filesystem (reading and writing files, creating directories, etc). // Disabling the filter must be done via UnprepareLayer. -func PrepareLayer(path string, parentLayerPaths []string) error { - title := "hcsshim::PrepareLayer " - logrus.Debugf(title+"path %s", path) +func PrepareLayer(path string, parentLayerPaths []string) (err error) { + title := "hcsshim::PrepareLayer" + fields := logrus.Fields{ + "path": path, + } + logrus.WithFields(fields).Debug(title) + defer func() { + if err != nil { + fields[logrus.ErrorKey] = err + logrus.WithFields(fields).Error(err) + } else { + logrus.WithFields(fields).Debug(title + " - succeeded") + } + }() // Generate layer descriptors layers, err := layerPathsToDescriptors(parentLayerPaths) @@ -30,11 +41,7 @@ func PrepareLayer(path string, parentLayerPaths []string) error { defer prepareLayerLock.Unlock() err = prepareLayer(&stdDriverInfo, path, layers) if err != nil { - err = hcserror.Errorf(err, title, "path=%s", path) - logrus.Error(err) - return err + return hcserror.New(err, title+" - failed", "") } - - logrus.Debugf(title+"succeeded path=%s", path) return nil } diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/unpreparelayer.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/unpreparelayer.go index 5f1b4f4f4..bccd45969 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/unpreparelayer.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/unpreparelayer.go @@ -7,17 +7,24 @@ import ( // UnprepareLayer disables the filesystem filter for the read-write layer with // the given id. -func UnprepareLayer(path string) error { - title := "hcsshim::UnprepareLayer " - logrus.Debugf(title+"path %s", path) - - err := unprepareLayer(&stdDriverInfo, path) - if err != nil { - err = hcserror.Errorf(err, title, "path=%s", path) - logrus.Error(err) - return err +func UnprepareLayer(path string) (err error) { + title := "hcsshim::UnprepareLayer" + fields := logrus.Fields{ + "path": path, } + logrus.WithFields(fields).Debug(title) + defer func() { + if err != nil { + fields[logrus.ErrorKey] = err + logrus.WithFields(fields).Error(err) + } else { + logrus.WithFields(fields).Debug(title + " - succeeded") + } + }() - logrus.Debugf(title+"succeeded path=%s", path) + err = unprepareLayer(&stdDriverInfo, path) + if err != nil { + return hcserror.New(err, title+" - failed", "") + } return nil } diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/wclayer.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/wclayer.go index 768a6f2f1..78f2aacd8 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/wclayer.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/wclayer.go @@ -2,7 +2,7 @@ package wclayer import "github.com/Microsoft/hcsshim/internal/guid" -//go:generate go run ../../mksyscall_windows.go -output zsyscall_windows.go -winio wclayer.go +//go:generate go run ../../mksyscall_windows.go -output zsyscall_windows.go wclayer.go //sys activateLayer(info *driverInfo, id string) (hr error) = vmcompute.ActivateLayer? //sys copyLayer(info *driverInfo, srcId string, dstId string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) = vmcompute.CopyLayer? @@ -22,16 +22,6 @@ import "github.com/Microsoft/hcsshim/internal/guid" //sys processBaseImage(path string) (hr error) = vmcompute.ProcessBaseImage? //sys processUtilityImage(path string) (hr error) = vmcompute.ProcessUtilityImage? -//sys importLayerBegin(info *driverInfo, id string, descriptors []WC_LAYER_DESCRIPTOR, context *uintptr) (hr error) = vmcompute.ImportLayerBegin? -//sys importLayerNext(context uintptr, fileName string, fileInfo *winio.FileBasicInfo) (hr error) = vmcompute.ImportLayerNext? -//sys importLayerWrite(context uintptr, buffer []byte) (hr error) = vmcompute.ImportLayerWrite? -//sys importLayerEnd(context uintptr) (hr error) = vmcompute.ImportLayerEnd? - -//sys exportLayerBegin(info *driverInfo, id string, descriptors []WC_LAYER_DESCRIPTOR, context *uintptr) (hr error) = vmcompute.ExportLayerBegin? -//sys exportLayerNext(context uintptr, fileName **uint16, fileInfo *winio.FileBasicInfo, fileSize *int64, deleted *uint32) (hr error) = vmcompute.ExportLayerNext? -//sys exportLayerRead(context uintptr, buffer []byte, bytesRead *uint32) (hr error) = vmcompute.ExportLayerRead? -//sys exportLayerEnd(context uintptr) (hr error) = vmcompute.ExportLayerEnd? - //sys grantVmAccess(vmid string, filepath string) (hr error) = vmcompute.GrantVmAccess? type _guid = guid.GUID diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/zsyscall_windows.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/zsyscall_windows.go index cb813aa3d..d853ab259 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/zsyscall_windows.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/zsyscall_windows.go @@ -1,4 +1,4 @@ -// MACHINE GENERATED BY 'go generate' COMMAND; DO NOT EDIT +// Code generated mksyscall_windows.exe DO NOT EDIT package wclayer @@ -6,8 +6,6 @@ import ( "syscall" "unsafe" - "github.com/Microsoft/go-winio" - "github.com/Microsoft/hcsshim/internal/interop" "golang.org/x/sys/windows" ) @@ -58,14 +56,6 @@ var ( procUnprepareLayer = modvmcompute.NewProc("UnprepareLayer") procProcessBaseImage = modvmcompute.NewProc("ProcessBaseImage") procProcessUtilityImage = modvmcompute.NewProc("ProcessUtilityImage") - procImportLayerBegin = modvmcompute.NewProc("ImportLayerBegin") - procImportLayerNext = modvmcompute.NewProc("ImportLayerNext") - procImportLayerWrite = modvmcompute.NewProc("ImportLayerWrite") - procImportLayerEnd = modvmcompute.NewProc("ImportLayerEnd") - procExportLayerBegin = modvmcompute.NewProc("ExportLayerBegin") - procExportLayerNext = modvmcompute.NewProc("ExportLayerNext") - procExportLayerRead = modvmcompute.NewProc("ExportLayerRead") - procExportLayerEnd = modvmcompute.NewProc("ExportLayerEnd") procGrantVmAccess = modvmcompute.NewProc("GrantVmAccess") ) @@ -84,7 +74,10 @@ func _activateLayer(info *driverInfo, id *uint16) (hr error) { } r0, _, _ := syscall.Syscall(procActivateLayer.Addr(), 2, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), 0) if int32(r0) < 0 { - hr = interop.Win32FromHresult(r0) + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) } return } @@ -113,7 +106,10 @@ func _copyLayer(info *driverInfo, srcId *uint16, dstId *uint16, descriptors []WC } r0, _, _ := syscall.Syscall6(procCopyLayer.Addr(), 5, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(srcId)), uintptr(unsafe.Pointer(dstId)), uintptr(unsafe.Pointer(_p2)), uintptr(len(descriptors)), 0) if int32(r0) < 0 { - hr = interop.Win32FromHresult(r0) + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) } return } @@ -138,7 +134,10 @@ func _createLayer(info *driverInfo, id *uint16, parent *uint16) (hr error) { } r0, _, _ := syscall.Syscall(procCreateLayer.Addr(), 3, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(parent))) if int32(r0) < 0 { - hr = interop.Win32FromHresult(r0) + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) } return } @@ -162,7 +161,10 @@ func _createSandboxLayer(info *driverInfo, id *uint16, parent uintptr, descripto } r0, _, _ := syscall.Syscall6(procCreateSandboxLayer.Addr(), 5, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(parent), uintptr(unsafe.Pointer(_p1)), uintptr(len(descriptors)), 0) if int32(r0) < 0 { - hr = interop.Win32FromHresult(r0) + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) } return } @@ -182,7 +184,10 @@ func _expandSandboxSize(info *driverInfo, id *uint16, size uint64) (hr error) { } r0, _, _ := syscall.Syscall(procExpandSandboxSize.Addr(), 3, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(size)) if int32(r0) < 0 { - hr = interop.Win32FromHresult(r0) + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) } return } @@ -202,7 +207,10 @@ func _deactivateLayer(info *driverInfo, id *uint16) (hr error) { } r0, _, _ := syscall.Syscall(procDeactivateLayer.Addr(), 2, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), 0) if int32(r0) < 0 { - hr = interop.Win32FromHresult(r0) + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) } return } @@ -222,7 +230,10 @@ func _destroyLayer(info *driverInfo, id *uint16) (hr error) { } r0, _, _ := syscall.Syscall(procDestroyLayer.Addr(), 2, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), 0) if int32(r0) < 0 { - hr = interop.Win32FromHresult(r0) + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) } return } @@ -251,7 +262,10 @@ func _exportLayer(info *driverInfo, id *uint16, path *uint16, descriptors []WC_L } r0, _, _ := syscall.Syscall6(procExportLayer.Addr(), 5, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(_p2)), uintptr(len(descriptors)), 0) if int32(r0) < 0 { - hr = interop.Win32FromHresult(r0) + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) } return } @@ -271,7 +285,10 @@ func _getLayerMountPath(info *driverInfo, id *uint16, length *uintptr, buffer *u } r0, _, _ := syscall.Syscall6(procGetLayerMountPath.Addr(), 4, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(length)), uintptr(unsafe.Pointer(buffer)), 0, 0) if int32(r0) < 0 { - hr = interop.Win32FromHresult(r0) + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) } return } @@ -282,7 +299,10 @@ func getBaseImages(buffer **uint16) (hr error) { } r0, _, _ := syscall.Syscall(procGetBaseImages.Addr(), 1, uintptr(unsafe.Pointer(buffer)), 0, 0) if int32(r0) < 0 { - hr = interop.Win32FromHresult(r0) + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) } return } @@ -311,7 +331,10 @@ func _importLayer(info *driverInfo, id *uint16, path *uint16, descriptors []WC_L } r0, _, _ := syscall.Syscall6(procImportLayer.Addr(), 5, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(_p2)), uintptr(len(descriptors)), 0) if int32(r0) < 0 { - hr = interop.Win32FromHresult(r0) + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) } return } @@ -331,7 +354,10 @@ func _layerExists(info *driverInfo, id *uint16, exists *uint32) (hr error) { } r0, _, _ := syscall.Syscall(procLayerExists.Addr(), 3, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(exists))) if int32(r0) < 0 { - hr = interop.Win32FromHresult(r0) + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) } return } @@ -351,7 +377,10 @@ func _nameToGuid(name *uint16, guid *_guid) (hr error) { } r0, _, _ := syscall.Syscall(procNameToGuid.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(guid)), 0) if int32(r0) < 0 { - hr = interop.Win32FromHresult(r0) + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) } return } @@ -375,7 +404,10 @@ func _prepareLayer(info *driverInfo, id *uint16, descriptors []WC_LAYER_DESCRIPT } r0, _, _ := syscall.Syscall6(procPrepareLayer.Addr(), 4, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(_p1)), uintptr(len(descriptors)), 0, 0) if int32(r0) < 0 { - hr = interop.Win32FromHresult(r0) + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) } return } @@ -395,7 +427,10 @@ func _unprepareLayer(info *driverInfo, id *uint16) (hr error) { } r0, _, _ := syscall.Syscall(procUnprepareLayer.Addr(), 2, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), 0) if int32(r0) < 0 { - hr = interop.Win32FromHresult(r0) + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) } return } @@ -415,7 +450,10 @@ func _processBaseImage(path *uint16) (hr error) { } r0, _, _ := syscall.Syscall(procProcessBaseImage.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0) if int32(r0) < 0 { - hr = interop.Win32FromHresult(r0) + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) } return } @@ -435,138 +473,10 @@ func _processUtilityImage(path *uint16) (hr error) { } r0, _, _ := syscall.Syscall(procProcessUtilityImage.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0) if int32(r0) < 0 { - hr = interop.Win32FromHresult(r0) - } - return -} - -func importLayerBegin(info *driverInfo, id string, descriptors []WC_LAYER_DESCRIPTOR, context *uintptr) (hr error) { - var _p0 *uint16 - _p0, hr = syscall.UTF16PtrFromString(id) - if hr != nil { - return - } - return _importLayerBegin(info, _p0, descriptors, context) -} - -func _importLayerBegin(info *driverInfo, id *uint16, descriptors []WC_LAYER_DESCRIPTOR, context *uintptr) (hr error) { - var _p1 *WC_LAYER_DESCRIPTOR - if len(descriptors) > 0 { - _p1 = &descriptors[0] - } - if hr = procImportLayerBegin.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall6(procImportLayerBegin.Addr(), 5, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(_p1)), uintptr(len(descriptors)), uintptr(unsafe.Pointer(context)), 0) - if int32(r0) < 0 { - hr = interop.Win32FromHresult(r0) - } - return -} - -func importLayerNext(context uintptr, fileName string, fileInfo *winio.FileBasicInfo) (hr error) { - var _p0 *uint16 - _p0, hr = syscall.UTF16PtrFromString(fileName) - if hr != nil { - return - } - return _importLayerNext(context, _p0, fileInfo) -} - -func _importLayerNext(context uintptr, fileName *uint16, fileInfo *winio.FileBasicInfo) (hr error) { - if hr = procImportLayerNext.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall(procImportLayerNext.Addr(), 3, uintptr(context), uintptr(unsafe.Pointer(fileName)), uintptr(unsafe.Pointer(fileInfo))) - if int32(r0) < 0 { - hr = interop.Win32FromHresult(r0) - } - return -} - -func importLayerWrite(context uintptr, buffer []byte) (hr error) { - var _p0 *byte - if len(buffer) > 0 { - _p0 = &buffer[0] - } - if hr = procImportLayerWrite.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall(procImportLayerWrite.Addr(), 3, uintptr(context), uintptr(unsafe.Pointer(_p0)), uintptr(len(buffer))) - if int32(r0) < 0 { - hr = interop.Win32FromHresult(r0) - } - return -} - -func importLayerEnd(context uintptr) (hr error) { - if hr = procImportLayerEnd.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall(procImportLayerEnd.Addr(), 1, uintptr(context), 0, 0) - if int32(r0) < 0 { - hr = interop.Win32FromHresult(r0) - } - return -} - -func exportLayerBegin(info *driverInfo, id string, descriptors []WC_LAYER_DESCRIPTOR, context *uintptr) (hr error) { - var _p0 *uint16 - _p0, hr = syscall.UTF16PtrFromString(id) - if hr != nil { - return - } - return _exportLayerBegin(info, _p0, descriptors, context) -} - -func _exportLayerBegin(info *driverInfo, id *uint16, descriptors []WC_LAYER_DESCRIPTOR, context *uintptr) (hr error) { - var _p1 *WC_LAYER_DESCRIPTOR - if len(descriptors) > 0 { - _p1 = &descriptors[0] - } - if hr = procExportLayerBegin.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall6(procExportLayerBegin.Addr(), 5, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(_p1)), uintptr(len(descriptors)), uintptr(unsafe.Pointer(context)), 0) - if int32(r0) < 0 { - hr = interop.Win32FromHresult(r0) - } - return -} - -func exportLayerNext(context uintptr, fileName **uint16, fileInfo *winio.FileBasicInfo, fileSize *int64, deleted *uint32) (hr error) { - if hr = procExportLayerNext.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall6(procExportLayerNext.Addr(), 5, uintptr(context), uintptr(unsafe.Pointer(fileName)), uintptr(unsafe.Pointer(fileInfo)), uintptr(unsafe.Pointer(fileSize)), uintptr(unsafe.Pointer(deleted)), 0) - if int32(r0) < 0 { - hr = interop.Win32FromHresult(r0) - } - return -} - -func exportLayerRead(context uintptr, buffer []byte, bytesRead *uint32) (hr error) { - var _p0 *byte - if len(buffer) > 0 { - _p0 = &buffer[0] - } - if hr = procExportLayerRead.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall6(procExportLayerRead.Addr(), 4, uintptr(context), uintptr(unsafe.Pointer(_p0)), uintptr(len(buffer)), uintptr(unsafe.Pointer(bytesRead)), 0, 0) - if int32(r0) < 0 { - hr = interop.Win32FromHresult(r0) - } - return -} - -func exportLayerEnd(context uintptr) (hr error) { - if hr = procExportLayerEnd.Find(); hr != nil { - return - } - r0, _, _ := syscall.Syscall(procExportLayerEnd.Addr(), 1, uintptr(context), 0, 0) - if int32(r0) < 0 { - hr = interop.Win32FromHresult(r0) + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) } return } @@ -591,7 +501,10 @@ func _grantVmAccess(vmid *uint16, filepath *uint16) (hr error) { } r0, _, _ := syscall.Syscall(procGrantVmAccess.Addr(), 2, uintptr(unsafe.Pointer(vmid)), uintptr(unsafe.Pointer(filepath)), 0) if int32(r0) < 0 { - hr = interop.Win32FromHresult(r0) + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) } return } diff --git a/vendor/github.com/Microsoft/hcsshim/layer.go b/vendor/github.com/Microsoft/hcsshim/layer.go index d143efc49..df0e63bbd 100644 --- a/vendor/github.com/Microsoft/hcsshim/layer.go +++ b/vendor/github.com/Microsoft/hcsshim/layer.go @@ -5,7 +5,6 @@ import ( "path/filepath" "github.com/Microsoft/hcsshim/internal/guid" - "github.com/Microsoft/hcsshim/internal/wclayer" ) @@ -74,9 +73,6 @@ type DriverInfo struct { HomeDir string } -type FilterLayerReader = wclayer.FilterLayerReader -type FilterLayerWriter = wclayer.FilterLayerWriter - type GUID [16]byte func NameToGuid(name string) (id GUID, err error) { diff --git a/vendor/github.com/Microsoft/hcsshim/vendor.conf b/vendor/github.com/Microsoft/hcsshim/vendor.conf new file mode 100644 index 000000000..6e0ed1566 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/vendor.conf @@ -0,0 +1,21 @@ +github.com/blang/semver v3.1.0 +github.com/containerd/console c12b1e7919c14469339a5d38f2f8ed9b64a9de23 +github.com/containerd/go-runc 5a6d9f37cfa36b15efba46dc7ea349fa9b7143c3 +github.com/hashicorp/errwrap 7554cd9344cec97297fa6649b055a8c98c2a1e55 +github.com/hashicorp/go-multierror ed905158d87462226a13fe39ddf685ea65f1c11f +github.com/konsorten/go-windows-terminal-sequences v1.0.1 +github.com/linuxkit/virtsock 8e79449dea0735c1c056d814934dd035734cc97c +github.com/Microsoft/go-winio 16cfc975803886a5e47c4257a24c8d8c52e178b2 +github.com/Microsoft/opengcs v0.3.9 +github.com/opencontainers/runtime-spec eba862dc2470385a233c7507392675cbeadf7353 +github.com/opencontainers/runtime-tools 1d69bd0f9c39677d0630e50664fbc3154ae61b88 +github.com/pkg/errors v0.8.1 +github.com/sirupsen/logrus v1.3.0 +github.com/syndtr/gocapability db04d3cc01c8b54962a58ec7e491717d06cfcc16 +github.com/urfave/cli 7bc6a0acffa589f415f88aca16cc1de5ffd66f9c +github.com/xeipuuv/gojsonpointer 4e3ac2762d5f479393488629ee9370b50873b3a6 +github.com/xeipuuv/gojsonreference bd5ef7bd5415a7ac448318e64f11a24cd21e594b +github.com/xeipuuv/gojsonschema 1d523034197ff1f222f6429836dd36a2457a1874 +golang.org/x/crypto ff983b9c42bc9fbf91556e191cc8efb585c16908 +golang.org/x/sync 37e7f081c4d4c64e13b10787722085407fe5d15f +golang.org/x/sys e5ecc2a6747ce8d4af18ed98b3de5ae30eb3a5bb \ No newline at end of file diff --git a/vendor/github.com/Microsoft/hcsshim/zsyscall_windows.go b/vendor/github.com/Microsoft/hcsshim/zsyscall_windows.go index cd471295b..8bed84857 100644 --- a/vendor/github.com/Microsoft/hcsshim/zsyscall_windows.go +++ b/vendor/github.com/Microsoft/hcsshim/zsyscall_windows.go @@ -1,4 +1,4 @@ -// MACHINE GENERATED BY 'go generate' COMMAND; DO NOT EDIT +// Code generated mksyscall_windows.exe DO NOT EDIT package hcsshim @@ -6,7 +6,6 @@ import ( "syscall" "unsafe" - "github.com/Microsoft/hcsshim/internal/interop" "golang.org/x/sys/windows" ) @@ -46,7 +45,10 @@ var ( func SetCurrentThreadCompartmentId(compartmentId uint32) (hr error) { r0, _, _ := syscall.Syscall(procSetCurrentThreadCompartmentId.Addr(), 1, uintptr(compartmentId), 0, 0) if int32(r0) < 0 { - hr = interop.Win32FromHresult(r0) + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) } return } diff --git a/vendor/github.com/containerd/cgroups/README.md b/vendor/github.com/containerd/cgroups/README.md index 69e932a9f..81ad11cc7 100644 --- a/vendor/github.com/containerd/cgroups/README.md +++ b/vendor/github.com/containerd/cgroups/README.md @@ -1,8 +1,9 @@ # cgroups [![Build Status](https://travis-ci.org/containerd/cgroups.svg?branch=master)](https://travis-ci.org/containerd/cgroups) - [![codecov](https://codecov.io/gh/containerd/cgroups/branch/master/graph/badge.svg)](https://codecov.io/gh/containerd/cgroups) +[![GoDoc](https://godoc.org/github.com/containerd/cgroups?status.svg)](https://godoc.org/github.com/containerd/cgroups) +[![Go Report Card](https://goreportcard.com/badge/github.com/containerd/cgroups)](https://goreportcard.com/report/github.com/containerd/cgroups) Go package for creating, managing, inspecting, and destroying cgroups. The resources format for settings on the cgroup uses the OCI runtime-spec found @@ -110,3 +111,14 @@ err := control.MoveTo(destination) ```go subCgroup, err := control.New("child", resources) ``` + +## Project details + +Cgroups is a containerd sub-project, licensed under the [Apache 2.0 license](./LICENSE). +As a containerd sub-project, you will find the: + + * [Project governance](https://github.com/containerd/project/blob/master/GOVERNANCE.md), + * [Maintainers](https://github.com/containerd/project/blob/master/MAINTAINERS), + * and [Contributing guidelines](https://github.com/containerd/project/blob/master/CONTRIBUTING.md) + +information in our [`containerd/project`](https://github.com/containerd/project) repository. diff --git a/vendor/github.com/containerd/cgroups/blkio.go b/vendor/github.com/containerd/cgroups/blkio.go index fc1e689cb..875fb5546 100644 --- a/vendor/github.com/containerd/cgroups/blkio.go +++ b/vendor/github.com/containerd/cgroups/blkio.go @@ -191,31 +191,42 @@ func (b *blkioController) readEntry(devices map[deviceKey]string, path, name str } func createBlkioSettings(blkio *specs.LinuxBlockIO) []blkioSettings { - settings := []blkioSettings{ - { - name: "weight", - value: blkio.Weight, - format: uintf, - }, - { - name: "leaf_weight", - value: blkio.LeafWeight, - format: uintf, - }, - } - for _, wd := range blkio.WeightDevice { + settings := []blkioSettings{} + + if blkio.Weight != nil { settings = append(settings, blkioSettings{ - name: "weight_device", - value: wd, - format: weightdev, - }, - blkioSettings{ - name: "leaf_weight_device", - value: wd, - format: weightleafdev, + name: "weight", + value: blkio.Weight, + format: uintf, }) } + if blkio.LeafWeight != nil { + settings = append(settings, + blkioSettings{ + name: "leaf_weight", + value: blkio.LeafWeight, + format: uintf, + }) + } + for _, wd := range blkio.WeightDevice { + if wd.Weight != nil { + settings = append(settings, + blkioSettings{ + name: "weight_device", + value: wd, + format: weightdev, + }) + } + if wd.LeafWeight != nil { + settings = append(settings, + blkioSettings{ + name: "leaf_weight_device", + value: wd, + format: weightleafdev, + }) + } + } for _, t := range []struct { name string list []specs.LinuxThrottleDevice @@ -265,12 +276,12 @@ func uintf(v interface{}) []byte { func weightdev(v interface{}) []byte { wd := v.(specs.LinuxWeightDevice) - return []byte(fmt.Sprintf("%d:%d %d", wd.Major, wd.Minor, wd.Weight)) + return []byte(fmt.Sprintf("%d:%d %d", wd.Major, wd.Minor, *wd.Weight)) } func weightleafdev(v interface{}) []byte { wd := v.(specs.LinuxWeightDevice) - return []byte(fmt.Sprintf("%d:%d %d", wd.Major, wd.Minor, wd.LeafWeight)) + return []byte(fmt.Sprintf("%d:%d %d", wd.Major, wd.Minor, *wd.LeafWeight)) } func throttleddev(v interface{}) []byte { diff --git a/vendor/github.com/containerd/cgroups/cgroup.go b/vendor/github.com/containerd/cgroups/cgroup.go index 7959feb49..03fcb9284 100644 --- a/vendor/github.com/containerd/cgroups/cgroup.go +++ b/vendor/github.com/containerd/cgroups/cgroup.go @@ -48,11 +48,12 @@ func New(hierarchy Hierarchy, path Path, resources *specs.LinuxResources) (Cgrou // Load will load an existing cgroup and allow it to be controlled func Load(hierarchy Hierarchy, path Path) (Cgroup, error) { + var activeSubsystems []Subsystem subsystems, err := hierarchy() if err != nil { return nil, err } - // check the the subsystems still exist + // check that the subsystems still exist, and keep only those that actually exist for _, s := range pathers(subsystems) { p, err := path(s.Name()) if err != nil { @@ -63,14 +64,15 @@ func Load(hierarchy Hierarchy, path Path) (Cgroup, error) { } if _, err := os.Lstat(s.Path(p)); err != nil { if os.IsNotExist(err) { - return nil, ErrCgroupDeleted + continue } return nil, err } + activeSubsystems = append(activeSubsystems, s) } return &cgroup{ path: path, - subsystems: subsystems, + subsystems: activeSubsystems, }, nil } @@ -319,6 +321,49 @@ func (c *cgroup) processes(subsystem Name, recursive bool) ([]Process, error) { return processes, err } +// Tasks returns the tasks running inside the cgroup along +// with the subsystem used, pid, and path +func (c *cgroup) Tasks(subsystem Name, recursive bool) ([]Task, error) { + c.mu.Lock() + defer c.mu.Unlock() + if c.err != nil { + return nil, c.err + } + return c.tasks(subsystem, recursive) +} + +func (c *cgroup) tasks(subsystem Name, recursive bool) ([]Task, error) { + s := c.getSubsystem(subsystem) + sp, err := c.path(subsystem) + if err != nil { + return nil, err + } + path := s.(pather).Path(sp) + var tasks []Task + err = filepath.Walk(path, func(p string, info os.FileInfo, err error) error { + if err != nil { + return err + } + if !recursive && info.IsDir() { + if p == path { + return nil + } + return filepath.SkipDir + } + dir, name := filepath.Split(p) + if name != cgroupTasks { + return nil + } + procs, err := readTasksPids(dir, subsystem) + if err != nil { + return err + } + tasks = append(tasks, procs...) + return nil + }) + return tasks, err +} + // Freeze freezes the entire cgroup and all the processes inside it func (c *cgroup) Freeze() error { c.mu.Lock() diff --git a/vendor/github.com/containerd/cgroups/control.go b/vendor/github.com/containerd/cgroups/control.go index 63e2df93d..1f62c54f3 100644 --- a/vendor/github.com/containerd/cgroups/control.go +++ b/vendor/github.com/containerd/cgroups/control.go @@ -44,6 +44,15 @@ type Process struct { Path string } +type Task struct { + // Subsystem is the name of the subsystem that the task is in + Subsystem Name + // Pid is the process id of the task + Pid int + // Path is the full path of the subsystem and location that the task is in + Path string +} + // Cgroup handles interactions with the individual groups to perform // actions on them as them main interface to this cgroup package type Cgroup interface { @@ -64,6 +73,8 @@ type Cgroup interface { Update(resources *specs.LinuxResources) error // Processes returns all the processes in a select subsystem for the cgroup Processes(Name, bool) ([]Process, error) + // Tasks returns all the tasks in a select subsystem for the cgroup + Tasks(Name, bool) ([]Task, error) // Freeze freezes or pauses all processes inside the cgroup Freeze() error // Thaw thaw or resumes all processes inside the cgroup diff --git a/vendor/github.com/containerd/cgroups/cpuset.go b/vendor/github.com/containerd/cgroups/cpuset.go index f182aa68c..30208515e 100644 --- a/vendor/github.com/containerd/cgroups/cpuset.go +++ b/vendor/github.com/containerd/cgroups/cpuset.go @@ -57,21 +57,21 @@ func (c *cpusetController) Create(path string, resources *specs.LinuxResources) if resources.CPU != nil { for _, t := range []struct { name string - value *string + value string }{ { name: "cpus", - value: &resources.CPU.Cpus, + value: resources.CPU.Cpus, }, { name: "mems", - value: &resources.CPU.Mems, + value: resources.CPU.Mems, }, } { - if t.value != nil { + if t.value != "" { if err := ioutil.WriteFile( filepath.Join(c.Path(path), fmt.Sprintf("cpuset.%s", t.name)), - []byte(*t.value), + []byte(t.value), defaultFilePerm, ); err != nil { return err diff --git a/vendor/github.com/containerd/cgroups/devices.go b/vendor/github.com/containerd/cgroups/devices.go index f9a118b22..f6a3b1947 100644 --- a/vendor/github.com/containerd/cgroups/devices.go +++ b/vendor/github.com/containerd/cgroups/devices.go @@ -58,6 +58,9 @@ func (d *devicesController) Create(path string, resources *specs.LinuxResources) if device.Allow { file = allowDeviceFile } + if device.Type == "" { + device.Type = "a" + } if err := ioutil.WriteFile( filepath.Join(d.Path(path), file), []byte(deviceString(device)), diff --git a/vendor/github.com/containerd/cgroups/net_prio.go b/vendor/github.com/containerd/cgroups/net_prio.go index c77169215..612e1bcd2 100644 --- a/vendor/github.com/containerd/cgroups/net_prio.go +++ b/vendor/github.com/containerd/cgroups/net_prio.go @@ -50,7 +50,7 @@ func (n *netprioController) Create(path string, resources *specs.LinuxResources) if resources.Network != nil { for _, prio := range resources.Network.Priorities { if err := ioutil.WriteFile( - filepath.Join(n.Path(path), "net_prio_ifpriomap"), + filepath.Join(n.Path(path), "net_prio.ifpriomap"), formatPrio(prio.Name, prio.Priority), defaultFilePerm, ); err != nil { diff --git a/vendor/github.com/containerd/cgroups/subsystem.go b/vendor/github.com/containerd/cgroups/subsystem.go index 933a6c38d..23de04d49 100644 --- a/vendor/github.com/containerd/cgroups/subsystem.go +++ b/vendor/github.com/containerd/cgroups/subsystem.go @@ -42,7 +42,7 @@ const ( ) // Subsystems returns a complete list of the default cgroups -// avaliable on most linux systems +// available on most linux systems func Subsystems() []Name { n := []Name{ Hugetlb, diff --git a/vendor/github.com/containerd/cgroups/systemd.go b/vendor/github.com/containerd/cgroups/systemd.go index 8153d744c..c5d4e3081 100644 --- a/vendor/github.com/containerd/cgroups/systemd.go +++ b/vendor/github.com/containerd/cgroups/systemd.go @@ -32,6 +32,11 @@ const ( defaultSlice = "system.slice" ) +var ( + canDelegate bool + once sync.Once +) + func Systemd() ([]Subsystem, error) { root, err := v1MountPoint() if err != nil { @@ -54,7 +59,7 @@ func Slice(slice, name string) Path { slice = defaultSlice } return func(subsystem Name) (string, error) { - return filepath.Join(slice, unitName(name)), nil + return filepath.Join(slice, name), nil } } @@ -80,15 +85,39 @@ func (s *SystemdController) Create(path string, resources *specs.LinuxResources) } defer conn.Close() slice, name := splitName(path) + // We need to see if systemd can handle the delegate property + // Systemd will return an error if it cannot handle delegate regardless + // of its bool setting. + checkDelegate := func() { + canDelegate = true + dlSlice := newProperty("Delegate", true) + if _, err := conn.StartTransientUnit(slice, "testdelegate", []systemdDbus.Property{dlSlice}, nil); err != nil { + if dbusError, ok := err.(dbus.Error); ok { + // Starting with systemd v237, Delegate is not even a property of slices anymore, + // so the D-Bus call fails with "InvalidArgs" error. + if strings.Contains(dbusError.Name, "org.freedesktop.DBus.Error.PropertyReadOnly") || strings.Contains(dbusError.Name, "org.freedesktop.DBus.Error.InvalidArgs") { + canDelegate = false + } + } + } + + conn.StopUnit(slice, "testDelegate", nil) + } + once.Do(checkDelegate) properties := []systemdDbus.Property{ systemdDbus.PropDescription(fmt.Sprintf("cgroup %s", name)), systemdDbus.PropWants(slice), newProperty("DefaultDependencies", false), - newProperty("Delegate", true), newProperty("MemoryAccounting", true), newProperty("CPUAccounting", true), newProperty("BlockIOAccounting", true), } + + // If we can delegate, we add the property back in + if canDelegate { + properties = append(properties, newProperty("Delegate", true)) + } + ch := make(chan string) _, err = conn.StartTransientUnit(name, "replace", properties, ch) if err != nil { diff --git a/vendor/github.com/containerd/cgroups/utils.go b/vendor/github.com/containerd/cgroups/utils.go index 345be4e46..f3129b1a3 100644 --- a/vendor/github.com/containerd/cgroups/utils.go +++ b/vendor/github.com/containerd/cgroups/utils.go @@ -111,7 +111,7 @@ func remove(path string) error { return fmt.Errorf("cgroups: unable to remove path %q", path) } -// readPids will read all the pids in a cgroup by the provided path +// readPids will read all the pids of processes in a cgroup by the provided path func readPids(path string, subsystem Name) ([]Process, error) { f, err := os.Open(filepath.Join(path, cgroupProcs)) if err != nil { @@ -138,6 +138,33 @@ func readPids(path string, subsystem Name) ([]Process, error) { return out, nil } +// readTasksPids will read all the pids of tasks in a cgroup by the provided path +func readTasksPids(path string, subsystem Name) ([]Task, error) { + f, err := os.Open(filepath.Join(path, cgroupTasks)) + if err != nil { + return nil, err + } + defer f.Close() + var ( + out []Task + s = bufio.NewScanner(f) + ) + for s.Scan() { + if t := s.Text(); t != "" { + pid, err := strconv.Atoi(t) + if err != nil { + return nil, err + } + out = append(out, Task{ + Pid: pid, + Subsystem: subsystem, + Path: path, + }) + } + } + return out, nil +} + func hugePageSizes() ([]string, error) { var ( pageSizes []string diff --git a/vendor/github.com/containerd/containerd/README.md b/vendor/github.com/containerd/containerd/README.md index 4a90fc8a0..3d9947ddf 100644 --- a/vendor/github.com/containerd/containerd/README.md +++ b/vendor/github.com/containerd/containerd/README.md @@ -172,11 +172,9 @@ checkpoint, err := task.Checkpoint(context) err := client.Push(context, "myregistry/checkpoints/redis:master", checkpoint) // on a new machine pull the checkpoint and restore the redis container -image, err := client.Pull(context, "myregistry/checkpoints/redis:master") +checkpoint, err := client.Pull(context, "myregistry/checkpoints/redis:master") -checkpoint := image.Target() - -redis, err = client.NewContainer(context, "redis-master", containerd.WithCheckpoint(checkpoint, "redis-rootfs")) +redis, err = client.NewContainer(context, "redis-master", containerd.WithNewSnapshot("redis-rootfs", checkpoint)) defer container.Delete(context) task, err = redis.NewTask(context, cio.Stdio, containerd.WithTaskCheckpoint(checkpoint)) @@ -212,11 +210,6 @@ See [PLUGINS.md](PLUGINS.md) for how to create plugins Please see [RELEASES.md](RELEASES.md) for details on versioning and stability of containerd components. -### Development reports. - -Weekly summary on the progress and what is being worked on. -https://github.com/containerd/containerd/tree/master/reports - ### Communication For async communication and long running discussions please use issues and pull requests on the github repo. @@ -227,6 +220,10 @@ For sync communication we have a community slack with a #containerd channel that **Slack:** Catch us in the #containerd and #containerd-dev channels on dockercommunity.slack.com. [Click here for an invite to docker community slack.](https://join.slack.com/t/dockercommunity/shared_invite/enQtNDY4MDc1Mzc0MzIwLTgxZDBlMmM4ZGEyNDc1N2FkMzlhODJkYmE1YTVkYjM1MDE3ZjAwZjBkOGFlOTJkZjRmZGYzNjYyY2M3ZTUxYzQ) +### Security audit + +A third party security audit was performed by Cure53 in 4Q2018; the [full report](docs/SECURITY_AUDIT.pdf) is available in our docs/ directory. + ### Reporting security issues __If you are reporting a security issue, please reach out discreetly at security@containerd.io__. diff --git a/vendor/github.com/containerd/containerd/archive/tar.go b/vendor/github.com/containerd/containerd/archive/tar.go index 1a61b4134..0d9e0e750 100644 --- a/vendor/github.com/containerd/containerd/archive/tar.go +++ b/vendor/github.com/containerd/containerd/archive/tar.go @@ -100,7 +100,7 @@ const ( // readdir calls to this directory do not follow to lower layers. whiteoutOpaqueDir = whiteoutMetaPrefix + ".opq" - paxSchilyXattr = "SCHILY.xattrs." + paxSchilyXattr = "SCHILY.xattr." ) // Apply applies a tar stream of an OCI style diff tar. diff --git a/vendor/github.com/containerd/containerd/archive/tar_windows.go b/vendor/github.com/containerd/containerd/archive/tar_windows.go index a3f585ac8..b97631fcc 100644 --- a/vendor/github.com/containerd/containerd/archive/tar_windows.go +++ b/vendor/github.com/containerd/containerd/archive/tar_windows.go @@ -74,7 +74,7 @@ func tarName(p string) (string, error) { // in file names, it is mostly safe to replace however we must // check just in case if strings.Contains(p, "/") { - return "", fmt.Errorf("Windows path contains forward slash: %s", p) + return "", fmt.Errorf("windows path contains forward slash: %s", p) } return strings.Replace(p, string(os.PathSeparator), "/", -1), nil @@ -130,11 +130,7 @@ func skipFile(hdr *tar.Header) bool { // specific or Linux-specific, this warning should be changed to an error // to cater for the situation where someone does manage to upload a Linux // image but have it tagged as Windows inadvertently. - if strings.Contains(hdr.Name, ":") { - return true - } - - return false + return strings.Contains(hdr.Name, ":") } // handleTarTypeBlockCharFifo is an OS-specific helper function used by diff --git a/vendor/github.com/containerd/containerd/archive/time_unix.go b/vendor/github.com/containerd/containerd/archive/time_unix.go index 53d655be4..fd8d98bf3 100644 --- a/vendor/github.com/containerd/containerd/archive/time_unix.go +++ b/vendor/github.com/containerd/containerd/archive/time_unix.go @@ -1,4 +1,4 @@ -// +build freebsd linux openbsd solaris +// +build !windows /* Copyright The containerd Authors. diff --git a/vendor/github.com/containerd/containerd/cio/io.go b/vendor/github.com/containerd/containerd/cio/io.go index a9c6d2b15..1f8abf5f0 100644 --- a/vendor/github.com/containerd/containerd/cio/io.go +++ b/vendor/github.com/containerd/containerd/cio/io.go @@ -275,3 +275,7 @@ func Load(set *FIFOSet) (IO, error) { closers: []io.Closer{set}, }, nil } + +func (p *pipes) closers() []io.Closer { + return []io.Closer{p.Stdin, p.Stdout, p.Stderr} +} diff --git a/vendor/github.com/containerd/containerd/cio/io_unix.go b/vendor/github.com/containerd/containerd/cio/io_unix.go index 3ab2a30b0..eb2ada80b 100644 --- a/vendor/github.com/containerd/containerd/cio/io_unix.go +++ b/vendor/github.com/containerd/containerd/cio/io_unix.go @@ -152,7 +152,3 @@ func NewDirectIO(ctx context.Context, fifos *FIFOSet) (*DirectIO, error) { }, }, err } - -func (p *pipes) closers() []io.Closer { - return []io.Closer{p.Stdin, p.Stdout, p.Stderr} -} diff --git a/vendor/github.com/containerd/containerd/cio/io_windows.go b/vendor/github.com/containerd/containerd/cio/io_windows.go index 5208f3eaa..4e5d18231 100644 --- a/vendor/github.com/containerd/containerd/cio/io_windows.go +++ b/vendor/github.com/containerd/containerd/cio/io_windows.go @@ -17,6 +17,7 @@ package cio import ( + "context" "fmt" "io" "net" @@ -144,3 +145,22 @@ func NewDirectIO(stdin io.WriteCloser, stdout, stderr io.ReadCloser, terminal bo }, } } + +// NewDirectIOFromFIFOSet returns an IO implementation that exposes the IO streams as io.ReadCloser +// and io.WriteCloser. +func NewDirectIOFromFIFOSet(ctx context.Context, stdin io.WriteCloser, stdout, stderr io.ReadCloser, fifos *FIFOSet) *DirectIO { + _, cancel := context.WithCancel(ctx) + pipes := pipes{ + Stdin: stdin, + Stdout: stdout, + Stderr: stderr, + } + return &DirectIO{ + pipes: pipes, + cio: cio{ + config: fifos.Config, + closers: append(pipes.closers(), fifos), + cancel: cancel, + }, + } +} diff --git a/vendor/github.com/containerd/containerd/client.go b/vendor/github.com/containerd/containerd/client.go index bc86590c2..eefeb4e94 100644 --- a/vendor/github.com/containerd/containerd/client.go +++ b/vendor/github.com/containerd/containerd/client.go @@ -61,6 +61,7 @@ import ( ocispec "github.com/opencontainers/image-spec/specs-go/v1" specs "github.com/opencontainers/runtime-spec/specs-go" "github.com/pkg/errors" + "golang.org/x/sync/semaphore" "google.golang.org/grpc" "google.golang.org/grpc/health/grpc_health_v1" ) @@ -292,6 +293,9 @@ type RemoteContext struct { // platforms will be used to create a PlatformMatcher with no ordering // preference. Platforms []string + + // MaxConcurrentDownloads is the max concurrent content downloads for each pull. + MaxConcurrentDownloads int } func defaultRemoteContext() *RemoteContext { @@ -403,12 +407,23 @@ func (c *Client) fetch(ctx context.Context, rCtx *RemoteContext, ref string, lim } var ( - schema1Converter *schema1.Converter - handler images.Handler + handler images.Handler + + isConvertible bool + converterFunc func(context.Context, ocispec.Descriptor) (ocispec.Descriptor, error) + limiter *semaphore.Weighted ) + if desc.MediaType == images.MediaTypeDockerSchema1Manifest && rCtx.ConvertSchema1 { - schema1Converter = schema1.NewConverter(store, fetcher) + schema1Converter := schema1.NewConverter(store, fetcher) + handler = images.Handlers(append(rCtx.BaseHandlers, schema1Converter)...) + + isConvertible = true + + converterFunc = func(ctx context.Context, _ ocispec.Descriptor) (ocispec.Descriptor, error) { + return schema1Converter.Convert(ctx) + } } else { // Get all the children for a descriptor childrenHandler := images.ChildrenHandler(store) @@ -421,18 +436,37 @@ func (c *Client) fetch(ctx context.Context, rCtx *RemoteContext, ref string, lim childrenHandler = images.LimitManifests(childrenHandler, rCtx.PlatformMatcher, limit) } + // set isConvertible to true if there is application/octet-stream media type + convertibleHandler := images.HandlerFunc( + func(_ context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) { + if desc.MediaType == docker.LegacyConfigMediaType { + isConvertible = true + } + + return []ocispec.Descriptor{}, nil + }, + ) + handler = images.Handlers(append(rCtx.BaseHandlers, remotes.FetchHandler(store, fetcher), + convertibleHandler, childrenHandler, )...) + + converterFunc = func(ctx context.Context, desc ocispec.Descriptor) (ocispec.Descriptor, error) { + return docker.ConvertManifest(ctx, store, desc) + } } - if err := images.Dispatch(ctx, handler, desc); err != nil { + if rCtx.MaxConcurrentDownloads > 0 { + limiter = semaphore.NewWeighted(int64(rCtx.MaxConcurrentDownloads)) + } + if err := images.Dispatch(ctx, handler, limiter, desc); err != nil { return images.Image{}, err } - if schema1Converter != nil { - desc, err = schema1Converter.Convert(ctx) - if err != nil { + + if isConvertible { + if desc, err = converterFunc(ctx, desc); err != nil { return images.Image{}, err } } diff --git a/vendor/github.com/containerd/containerd/client_opts.go b/vendor/github.com/containerd/containerd/client_opts.go index b7431ad29..cb3792fb3 100644 --- a/vendor/github.com/containerd/containerd/client_opts.go +++ b/vendor/github.com/containerd/containerd/client_opts.go @@ -178,3 +178,11 @@ func WithImageHandler(h images.Handler) RemoteOpt { return nil } } + +// WithMaxConcurrentDownloads sets max concurrent download limit. +func WithMaxConcurrentDownloads(max int) RemoteOpt { + return func(client *Client, c *RemoteContext) error { + c.MaxConcurrentDownloads = max + return nil + } +} diff --git a/vendor/github.com/containerd/containerd/cmd/containerd/command/service_windows.go b/vendor/github.com/containerd/containerd/cmd/containerd/command/service_windows.go index c5741a685..1ad30f535 100644 --- a/vendor/github.com/containerd/containerd/cmd/containerd/command/service_windows.go +++ b/vendor/github.com/containerd/containerd/cmd/containerd/command/service_windows.go @@ -387,18 +387,16 @@ func (h *handler) Execute(_ []string, r <-chan svc.ChangeRequest, s chan<- svc.S h.fromsvc <- nil s <- svc.Status{State: svc.Running, Accepts: svc.AcceptStop | svc.AcceptShutdown | svc.Accepted(windows.SERVICE_ACCEPT_PARAMCHANGE)} + Loop: - for { - select { - case c := <-r: - switch c.Cmd { - case svc.Interrogate: - s <- c.CurrentStatus - case svc.Stop, svc.Shutdown: - s <- svc.Status{State: svc.StopPending, Accepts: 0} - h.s.Stop() - break Loop - } + for c := range r { + switch c.Cmd { + case svc.Interrogate: + s <- c.CurrentStatus + case svc.Stop, svc.Shutdown: + s <- svc.Status{State: svc.StopPending, Accepts: 0} + h.s.Stop() + break Loop } } diff --git a/vendor/github.com/containerd/containerd/cmd/ctr/commands/commands.go b/vendor/github.com/containerd/containerd/cmd/ctr/commands/commands.go index 7c3d95998..6d9fb5488 100644 --- a/vendor/github.com/containerd/containerd/cmd/ctr/commands/commands.go +++ b/vendor/github.com/containerd/containerd/cmd/ctr/commands/commands.go @@ -124,6 +124,10 @@ var ( Name: "allow-new-privs", Usage: "turn off OCI spec's NoNewPrivileges feature flag", }, + cli.Uint64Flag{ + Name: "memory-limit", + Usage: "memory limit (in bytes) for the container", + }, } ) diff --git a/vendor/github.com/containerd/containerd/archive/time_darwin.go b/vendor/github.com/containerd/containerd/cmd/ctr/commands/commands_windows.go similarity index 64% rename from vendor/github.com/containerd/containerd/archive/time_darwin.go rename to vendor/github.com/containerd/containerd/cmd/ctr/commands/commands_windows.go index 9c2b656b0..4bd3d2596 100644 --- a/vendor/github.com/containerd/containerd/archive/time_darwin.go +++ b/vendor/github.com/containerd/containerd/cmd/ctr/commands/commands_windows.go @@ -1,3 +1,5 @@ +// +build windows + /* Copyright The containerd Authors. @@ -14,17 +16,15 @@ limitations under the License. */ -package archive +package commands import ( - "time" - - "github.com/pkg/errors" + "github.com/urfave/cli" ) -// as at MacOS 10.12 there is apparently no way to set timestamps -// with nanosecond precision. We could fall back to utimes/lutimes -// and lose the precision as a temporary workaround. -func chtimes(path string, atime, mtime time.Time) error { - return errors.New("OSX missing UtimesNanoAt") +func init() { + ContainerFlags = append(ContainerFlags, cli.Uint64Flag{ + Name: "cpu-count", + Usage: "number of CPUs available to the container", + }) } diff --git a/vendor/github.com/containerd/containerd/cmd/ctr/commands/content/content.go b/vendor/github.com/containerd/containerd/cmd/ctr/commands/content/content.go index 2eee81507..737fc1672 100644 --- a/vendor/github.com/containerd/containerd/cmd/ctr/commands/content/content.go +++ b/vendor/github.com/containerd/containerd/cmd/ctr/commands/content/content.go @@ -290,6 +290,11 @@ var ( Name: "validate", Usage: "validate the result against a format (json, mediatype, etc.)", }, + cli.StringFlag{ + Name: "editor", + Usage: "select editor (vim, emacs, etc.)", + EnvVar: "EDITOR", + }, }, Action: func(context *cli.Context) error { var ( @@ -320,7 +325,7 @@ var ( } defer ra.Close() - nrc, err := edit(content.NewReader(ra)) + nrc, err := edit(context, content.NewReader(ra)) if err != nil { return err } @@ -505,7 +510,12 @@ var ( } ) -func edit(rd io.Reader) (io.ReadCloser, error) { +func edit(context *cli.Context, rd io.Reader) (io.ReadCloser, error) { + editor := context.String("editor") + if editor == "" { + return nil, fmt.Errorf("editor is required") + } + tmp, err := ioutil.TempFile(os.Getenv("XDG_RUNTIME_DIR"), "edit-") if err != nil { return nil, err @@ -516,7 +526,7 @@ func edit(rd io.Reader) (io.ReadCloser, error) { return nil, err } - cmd := exec.Command("sh", "-c", "$EDITOR "+tmp.Name()) + cmd := exec.Command("sh", "-c", fmt.Sprintf("%s %s", editor, tmp.Name())) cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout diff --git a/vendor/github.com/containerd/containerd/cmd/ctr/commands/images/export.go b/vendor/github.com/containerd/containerd/cmd/ctr/commands/images/export.go index d62a55181..629f49330 100644 --- a/vendor/github.com/containerd/containerd/cmd/ctr/commands/images/export.go +++ b/vendor/github.com/containerd/containerd/cmd/ctr/commands/images/export.go @@ -21,7 +21,7 @@ import ( "os" "github.com/containerd/containerd/cmd/ctr/commands" - oci "github.com/containerd/containerd/images/oci" + "github.com/containerd/containerd/images/oci" "github.com/containerd/containerd/reference" digest "github.com/opencontainers/go-digest" ocispec "github.com/opencontainers/image-spec/specs-go/v1" @@ -52,6 +52,10 @@ Currently, only OCI format is supported. Usage: "media type of manifest digest", Value: ocispec.MediaTypeImageManifest, }, + cli.BoolFlag{ + Name: "all-platforms", + Usage: "exports content from all platforms", + }, }, Action: func(context *cli.Context) error { var ( @@ -101,7 +105,14 @@ Currently, only OCI format is supported. return nil } } - r, err := client.Export(ctx, &oci.V1Exporter{}, desc) + + var ( + exportOpts []oci.V1ExporterOpt + ) + + exportOpts = append(exportOpts, oci.WithAllPlatforms(context.Bool("all-platforms"))) + + r, err := client.Export(ctx, desc, exportOpts...) if err != nil { return err } diff --git a/vendor/github.com/containerd/containerd/cmd/ctr/commands/run/run.go b/vendor/github.com/containerd/containerd/cmd/ctr/commands/run/run.go index c3f3f3bf5..2f01247ac 100644 --- a/vendor/github.com/containerd/containerd/cmd/ctr/commands/run/run.go +++ b/vendor/github.com/containerd/containerd/cmd/ctr/commands/run/run.go @@ -86,9 +86,10 @@ func parseMountFlag(m string) (specs.Mount, error) { // Command runs a container var Command = cli.Command{ - Name: "run", - Usage: "run a container", - ArgsUsage: "[flags] Image|RootFS ID [COMMAND] [ARG...]", + Name: "run", + Usage: "run a container", + ArgsUsage: "[flags] Image|RootFS ID [COMMAND] [ARG...]", + SkipArgReorder: true, Flags: append([]cli.Flag{ cli.BoolFlag{ Name: "rm", diff --git a/vendor/github.com/containerd/containerd/cmd/ctr/commands/run/run_unix.go b/vendor/github.com/containerd/containerd/cmd/ctr/commands/run/run_unix.go index 295259614..52a3205ab 100644 --- a/vendor/github.com/containerd/containerd/cmd/ctr/commands/run/run_unix.go +++ b/vendor/github.com/containerd/containerd/cmd/ctr/commands/run/run_unix.go @@ -139,6 +139,10 @@ func NewContainer(ctx gocontext.Context, client *containerd.Client, context *cli // NOTE: can be set to "" explicitly for disabling cgroup. opts = append(opts, oci.WithCgroup(context.String("cgroup"))) } + limit := context.Uint64("memory-limit") + if limit != 0 { + opts = append(opts, oci.WithMemoryLimit(limit)) + } } cOpts = append(cOpts, containerd.WithRuntime(context.String("runtime"), nil)) diff --git a/vendor/github.com/containerd/containerd/cmd/ctr/commands/run/run_windows.go b/vendor/github.com/containerd/containerd/cmd/ctr/commands/run/run_windows.go index bd81678ee..40f2608c9 100644 --- a/vendor/github.com/containerd/containerd/cmd/ctr/commands/run/run_windows.go +++ b/vendor/github.com/containerd/containerd/cmd/ctr/commands/run/run_windows.go @@ -105,6 +105,14 @@ func NewContainer(ctx gocontext.Context, client *containerd.Client, context *cli if context.Bool("isolated") { opts = append(opts, oci.WithWindowsHyperV) } + limit := context.Uint64("memory-limit") + if limit != 0 { + opts = append(opts, oci.WithMemoryLimit(limit)) + } + ccount := context.Uint64("cpu-count") + if ccount != 0 { + opts = append(opts, oci.WithWindowsCPUCount(ccount)) + } } cOpts = append(cOpts, containerd.WithContainerLabels(commands.LabelArgs(context.StringSlice("label")))) diff --git a/vendor/github.com/containerd/containerd/cmd/ctr/commands/tasks/checkpoint.go b/vendor/github.com/containerd/containerd/cmd/ctr/commands/tasks/checkpoint.go index 4d580ef12..94309e38c 100644 --- a/vendor/github.com/containerd/containerd/cmd/ctr/commands/tasks/checkpoint.go +++ b/vendor/github.com/containerd/containerd/cmd/ctr/commands/tasks/checkpoint.go @@ -36,6 +36,14 @@ var checkpointCommand = cli.Command{ Name: "exit", Usage: "stop the container after the checkpoint", }, + cli.StringFlag{ + Name: "image-path", + Usage: "path to criu image files", + }, + cli.StringFlag{ + Name: "work-path", + Usage: "path to criu work files and logs", + }, }, Action: func(context *cli.Context) error { id := context.Args().First() @@ -59,40 +67,55 @@ var checkpointCommand = cli.Command{ if err != nil { return err } - var opts []containerd.CheckpointTaskOpts - if context.Bool("exit") { - opts = append(opts, withExit(info.Runtime.Name)) - } + opts := []containerd.CheckpointTaskOpts{withCheckpointOpts(info.Runtime.Name, context)} checkpoint, err := task.Checkpoint(ctx, opts...) if err != nil { return err } - fmt.Println(checkpoint.Name()) + if context.String("image-path") == "" { + fmt.Println(checkpoint.Name()) + } return nil }, } -func withExit(rt string) containerd.CheckpointTaskOpts { +// withCheckpointOpts only suitable for runc runtime now +func withCheckpointOpts(rt string, context *cli.Context) containerd.CheckpointTaskOpts { return func(r *containerd.CheckpointTaskInfo) error { + imagePath := context.String("image-path") + workPath := context.String("work-path") + switch rt { case "io.containerd.runc.v1": if r.Options == nil { - r.Options = &options.CheckpointOptions{ - Exit: true, - } - } else { - opts, _ := r.Options.(*options.CheckpointOptions) + r.Options = &options.CheckpointOptions{} + } + opts, _ := r.Options.(*options.CheckpointOptions) + + if context.Bool("exit") { opts.Exit = true } - default: + if imagePath != "" { + opts.ImagePath = imagePath + } + if workPath != "" { + opts.WorkPath = workPath + } + case "io.containerd.runtime.v1.linux": if r.Options == nil { - r.Options = &runctypes.CheckpointOptions{ - Exit: true, - } - } else { - opts, _ := r.Options.(*runctypes.CheckpointOptions) + r.Options = &runctypes.CheckpointOptions{} + } + opts, _ := r.Options.(*runctypes.CheckpointOptions) + + if context.Bool("exit") { opts.Exit = true } + if imagePath != "" { + opts.ImagePath = imagePath + } + if workPath != "" { + opts.WorkPath = workPath + } } return nil } diff --git a/vendor/github.com/containerd/containerd/cmd/ctr/commands/tasks/exec.go b/vendor/github.com/containerd/containerd/cmd/ctr/commands/tasks/exec.go index 9c5bce78b..59f5bdef9 100644 --- a/vendor/github.com/containerd/containerd/cmd/ctr/commands/tasks/exec.go +++ b/vendor/github.com/containerd/containerd/cmd/ctr/commands/tasks/exec.go @@ -28,9 +28,10 @@ import ( //TODO:(jessvalarezo) exec-id is optional here, update to required arg var execCommand = cli.Command{ - Name: "exec", - Usage: "execute additional processes in an existing container", - ArgsUsage: "[flags] CONTAINER CMD [ARG...]", + Name: "exec", + Usage: "execute additional processes in an existing container", + ArgsUsage: "[flags] CONTAINER CMD [ARG...]", + SkipArgReorder: true, Flags: []cli.Flag{ cli.StringFlag{ Name: "cwd", diff --git a/vendor/github.com/containerd/containerd/content/local/locks.go b/vendor/github.com/containerd/containerd/content/local/locks.go index 411c29a9d..bc3bd18e0 100644 --- a/vendor/github.com/containerd/containerd/content/local/locks.go +++ b/vendor/github.com/containerd/containerd/content/local/locks.go @@ -47,7 +47,5 @@ func unlock(ref string) { locksMu.Lock() defer locksMu.Unlock() - if _, ok := locks[ref]; ok { - delete(locks, ref) - } + delete(locks, ref) } diff --git a/vendor/github.com/containerd/containerd/diff/apply/apply.go b/vendor/github.com/containerd/containerd/diff/apply/apply.go index e5e77cbdf..d5b4ff45d 100644 --- a/vendor/github.com/containerd/containerd/diff/apply/apply.go +++ b/vendor/github.com/containerd/containerd/diff/apply/apply.go @@ -58,7 +58,7 @@ func (s *fsApplier) Apply(ctx context.Context, desc ocispec.Descriptor, mounts [ defer func() { if err == nil { log.G(ctx).WithFields(logrus.Fields{ - "d": time.Now().Sub(t1), + "d": time.Since(t1), "dgst": desc.Digest, "size": desc.Size, "media": desc.MediaType, diff --git a/vendor/github.com/containerd/containerd/export.go b/vendor/github.com/containerd/containerd/export.go index bfc25316c..f5552231e 100644 --- a/vendor/github.com/containerd/containerd/export.go +++ b/vendor/github.com/containerd/containerd/export.go @@ -20,36 +20,23 @@ import ( "context" "io" - "github.com/containerd/containerd/images" + "github.com/containerd/containerd/images/oci" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" ) -type exportOpts struct { -} - -// ExportOpt allows the caller to specify export-specific options -type ExportOpt func(c *exportOpts) error - -func resolveExportOpt(opts ...ExportOpt) (exportOpts, error) { - var eopts exportOpts - for _, o := range opts { - if err := o(&eopts); err != nil { - return eopts, err - } - } - return eopts, nil -} - // Export exports an image to a Tar stream. // OCI format is used by default. // It is up to caller to put "org.opencontainers.image.ref.name" annotation to desc. // TODO(AkihiroSuda): support exporting multiple descriptors at once to a single archive stream. -func (c *Client) Export(ctx context.Context, exporter images.Exporter, desc ocispec.Descriptor, opts ...ExportOpt) (io.ReadCloser, error) { - _, err := resolveExportOpt(opts...) // unused now +func (c *Client) Export(ctx context.Context, desc ocispec.Descriptor, opts ...oci.V1ExporterOpt) (io.ReadCloser, error) { + + exporter, err := oci.ResolveV1ExportOpt(opts...) if err != nil { return nil, err } + pr, pw := io.Pipe() go func() { pw.CloseWithError(errors.Wrap(exporter.Export(ctx, c.ContentStore(), desc, pw), "export failed")) diff --git a/vendor/github.com/containerd/containerd/filters/scanner.go b/vendor/github.com/containerd/containerd/filters/scanner.go index c3961962c..45c52606d 100644 --- a/vendor/github.com/containerd/containerd/filters/scanner.go +++ b/vendor/github.com/containerd/containerd/filters/scanner.go @@ -185,7 +185,6 @@ func (s *scanner) scanQuoted(quote rune) { ch = s.next() } } - return } func (s *scanner) scanEscape(quote rune) rune { diff --git a/vendor/github.com/containerd/containerd/identifiers/validate.go b/vendor/github.com/containerd/containerd/identifiers/validate.go index c58513c02..c0dd820ff 100644 --- a/vendor/github.com/containerd/containerd/identifiers/validate.go +++ b/vendor/github.com/containerd/containerd/identifiers/validate.go @@ -45,7 +45,7 @@ var ( // Validate return nil if the string s is a valid identifier. // // identifiers must be valid domain names according to RFC 1035, section 2.3.1. To -// enforce case insensitvity, all characters must be lower case. +// enforce case insensitivity, all characters must be lower case. // // In general, identifiers that pass this validation, should be safe for use as // a domain names or filesystem path component. diff --git a/vendor/github.com/containerd/containerd/image.go b/vendor/github.com/containerd/containerd/image.go index 62fba9de7..14bfea91b 100644 --- a/vendor/github.com/containerd/containerd/image.go +++ b/vendor/github.com/containerd/containerd/image.go @@ -170,26 +170,22 @@ func (i *image) Unpack(ctx context.Context, snapshotterName string) error { chain = append(chain, layer.Diff.Digest) } - if unpacked { - desc, err := i.i.Config(ctx, cs, i.platform) - if err != nil { - return err - } - - rootfs := identity.ChainID(chain).String() - - cinfo := content.Info{ - Digest: desc.Digest, - Labels: map[string]string{ - fmt.Sprintf("containerd.io/gc.ref.snapshot.%s", snapshotterName): rootfs, - }, - } - if _, err := cs.Update(ctx, cinfo, fmt.Sprintf("labels.containerd.io/gc.ref.snapshot.%s", snapshotterName)); err != nil { - return err - } + desc, err := i.i.Config(ctx, cs, i.platform) + if err != nil { + return err } - return nil + rootfs := identity.ChainID(chain).String() + + cinfo := content.Info{ + Digest: desc.Digest, + Labels: map[string]string{ + fmt.Sprintf("containerd.io/gc.ref.snapshot.%s", snapshotterName): rootfs, + }, + } + + _, err = cs.Update(ctx, cinfo, fmt.Sprintf("labels.containerd.io/gc.ref.snapshot.%s", snapshotterName)) + return err } func (i *image) getLayers(ctx context.Context, platform platforms.MatchComparer) ([]rootfs.Layer, error) { diff --git a/vendor/github.com/containerd/containerd/images/handlers.go b/vendor/github.com/containerd/containerd/images/handlers.go index 230a9caf8..dac701bb8 100644 --- a/vendor/github.com/containerd/containerd/images/handlers.go +++ b/vendor/github.com/containerd/containerd/images/handlers.go @@ -26,6 +26,7 @@ import ( ocispec "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" "golang.org/x/sync/errgroup" + "golang.org/x/sync/semaphore" ) var ( @@ -108,19 +109,30 @@ func Walk(ctx context.Context, handler Handler, descs ...ocispec.Descriptor) err // handler may return `ErrSkipDesc` to signal to the dispatcher to not traverse // any children. // +// A concurrency limiter can be passed in to limit the number of concurrent +// handlers running. When limiter is nil, there is no limit. +// // Typically, this function will be used with `FetchHandler`, often composed // with other handlers. // // If any handler returns an error, the dispatch session will be canceled. -func Dispatch(ctx context.Context, handler Handler, descs ...ocispec.Descriptor) error { +func Dispatch(ctx context.Context, handler Handler, limiter *semaphore.Weighted, descs ...ocispec.Descriptor) error { eg, ctx := errgroup.WithContext(ctx) for _, desc := range descs { desc := desc + if limiter != nil { + if err := limiter.Acquire(ctx, 1); err != nil { + return err + } + } eg.Go(func() error { desc := desc children, err := handler.Handle(ctx, desc) + if limiter != nil { + limiter.Release(1) + } if err != nil { if errors.Cause(err) == ErrSkipDesc { return nil // don't traverse the children. @@ -129,7 +141,7 @@ func Dispatch(ctx context.Context, handler Handler, descs ...ocispec.Descriptor) } if len(children) > 0 { - return Dispatch(ctx, handler, children...) + return Dispatch(ctx, handler, limiter, children...) } return nil diff --git a/vendor/github.com/containerd/containerd/images/oci/exporter.go b/vendor/github.com/containerd/containerd/images/oci/exporter.go index bf5751e6a..8bb535489 100644 --- a/vendor/github.com/containerd/containerd/images/oci/exporter.go +++ b/vendor/github.com/containerd/containerd/images/oci/exporter.go @@ -25,6 +25,7 @@ import ( "github.com/containerd/containerd/content" "github.com/containerd/containerd/images" + "github.com/containerd/containerd/platforms" ocispecs "github.com/opencontainers/image-spec/specs-go" ocispec "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" @@ -37,6 +38,36 @@ import ( // e.g. application/vnd.docker.image.rootfs.diff.tar.gzip // -> application/vnd.oci.image.layer.v1.tar+gzip type V1Exporter struct { + AllPlatforms bool +} + +// V1ExporterOpt allows the caller to set additional options to a new V1Exporter +type V1ExporterOpt func(c *V1Exporter) error + +// DefaultV1Exporter return a default V1Exporter pointer +func DefaultV1Exporter() *V1Exporter { + return &V1Exporter{ + AllPlatforms: false, + } +} + +// ResolveV1ExportOpt return a new V1Exporter with V1ExporterOpt +func ResolveV1ExportOpt(opts ...V1ExporterOpt) (*V1Exporter, error) { + exporter := DefaultV1Exporter() + for _, o := range opts { + if err := o(exporter); err != nil { + return exporter, err + } + } + return exporter, nil +} + +// WithAllPlatforms set V1Exporter`s AllPlatforms option +func WithAllPlatforms(allPlatforms bool) V1ExporterOpt { + return func(c *V1Exporter) error { + c.AllPlatforms = allPlatforms + return nil + } } // Export implements Exporter. @@ -56,8 +87,15 @@ func (oe *V1Exporter) Export(ctx context.Context, store content.Provider, desc o return nil, nil } + childrenHandler := images.ChildrenHandler(store) + + if !oe.AllPlatforms { + // get local default platform to fetch image manifest + childrenHandler = images.FilterPlatforms(childrenHandler, platforms.Any(platforms.DefaultSpec())) + } + handlers := images.Handlers( - images.ChildrenHandler(store), + childrenHandler, images.HandlerFunc(exportHandler), ) diff --git a/vendor/github.com/containerd/containerd/import.go b/vendor/github.com/containerd/containerd/import.go index 365056824..e00f502a0 100644 --- a/vendor/github.com/containerd/containerd/import.go +++ b/vendor/github.com/containerd/containerd/import.go @@ -99,8 +99,7 @@ func (c *Client) Import(ctx context.Context, reader io.Reader, opts ...ImportOpt }) } - var handler images.HandlerFunc - handler = func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) { + var handler images.HandlerFunc = func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) { // Only save images at top level if desc.Digest != index.Digest { return images.Children(ctx, cs, desc) diff --git a/vendor/github.com/containerd/containerd/install.go b/vendor/github.com/containerd/containerd/install.go index 5e4c6a2c8..4545d4554 100644 --- a/vendor/github.com/containerd/containerd/install.go +++ b/vendor/github.com/containerd/containerd/install.go @@ -59,7 +59,6 @@ func (c *Client) Install(ctx context.Context, image Image, opts ...InstallOpts) if err != nil { return err } - defer r.Close() if _, err := archive.Apply(ctx, path, r, archive.WithFilter(func(hdr *tar.Header) (bool, error) { d := filepath.Dir(hdr.Name) result := d == "bin" @@ -73,8 +72,10 @@ func (c *Client) Install(ctx context.Context, image Image, opts ...InstallOpts) } return result, nil })); err != nil { + r.Close() return err } + r.Close() } return nil } diff --git a/vendor/github.com/containerd/containerd/metadata/content.go b/vendor/github.com/containerd/containerd/metadata/content.go index 8ee0f2e20..4d244914d 100644 --- a/vendor/github.com/containerd/containerd/metadata/content.go +++ b/vendor/github.com/containerd/containerd/metadata/content.go @@ -38,16 +38,31 @@ import ( type contentStore struct { content.Store - db *DB - l sync.RWMutex + db *DB + shared bool + l sync.RWMutex } // newContentStore returns a namespaced content store using an existing // content store interface. -func newContentStore(db *DB, cs content.Store) *contentStore { +// policy defines the sharing behavior for content between namespaces. Both +// modes will result in shared storage in the backend for committed. Choose +// "shared" to prevent separate namespaces from having to pull the same content +// twice. Choose "isolated" if the content must not be shared between +// namespaces. +// +// If the policy is "shared", writes will try to resolve the "expected" digest +// against the backend, allowing imports of content from other namespaces. In +// "isolated" mode, the client must prove they have the content by providing +// the entire blob before the content can be added to another namespace. +// +// Since we have only two policies right now, it's simpler using bool to +// represent it internally. +func newContentStore(db *DB, shared bool, cs content.Store) *contentStore { return &contentStore{ - Store: cs, - db: db, + Store: cs, + db: db, + shared: shared, } } @@ -383,13 +398,15 @@ func (cs *contentStore) Writer(ctx context.Context, opts ...content.WriterOpt) ( return nil } - if st, err := cs.Store.Info(ctx, wOpts.Desc.Digest); err == nil { - // Ensure the expected size is the same, it is likely - // an error if the size is mismatched but the caller - // must resolve this on commit - if wOpts.Desc.Size == 0 || wOpts.Desc.Size == st.Size { - shared = true - wOpts.Desc.Size = st.Size + if cs.shared { + if st, err := cs.Store.Info(ctx, wOpts.Desc.Digest); err == nil { + // Ensure the expected size is the same, it is likely + // an error if the size is mismatched but the caller + // must resolve this on commit + if wOpts.Desc.Size == 0 || wOpts.Desc.Size == st.Size { + shared = true + wOpts.Desc.Size = st.Size + } } } } @@ -762,7 +779,7 @@ func (cs *contentStore) garbageCollect(ctx context.Context) (d time.Duration, er t1 := time.Now() defer func() { if err == nil { - d = time.Now().Sub(t1) + d = time.Since(t1) } cs.l.Unlock() }() diff --git a/vendor/github.com/containerd/containerd/metadata/db.go b/vendor/github.com/containerd/containerd/metadata/db.go index 507d6d22d..7f1b27b38 100644 --- a/vendor/github.com/containerd/containerd/metadata/db.go +++ b/vendor/github.com/containerd/containerd/metadata/db.go @@ -46,6 +46,19 @@ const ( dbVersion = 3 ) +// DBOpt configures how we set up the DB +type DBOpt func(*dbOptions) + +// WithPolicyIsolated isolates contents between namespaces +func WithPolicyIsolated(o *dbOptions) { + o.shared = false +} + +// dbOptions configure db options. +type dbOptions struct { + shared bool +} + // DB represents a metadata database backed by a bolt // database. The database is fully namespaced and stores // image, container, namespace, snapshot, and content data @@ -72,19 +85,28 @@ type DB struct { // mutationCallbacks are called after each mutation with the flag // set indicating whether any dirty flags are set mutationCallbacks []func(bool) + + dbopts dbOptions } // NewDB creates a new metadata database using the provided // bolt database, content store, and snapshotters. -func NewDB(db *bolt.DB, cs content.Store, ss map[string]snapshots.Snapshotter) *DB { +func NewDB(db *bolt.DB, cs content.Store, ss map[string]snapshots.Snapshotter, opts ...DBOpt) *DB { m := &DB{ db: db, ss: make(map[string]*snapshotter, len(ss)), dirtySS: map[string]struct{}{}, + dbopts: dbOptions{ + shared: true, + }, + } + + for _, opt := range opts { + opt(&m.dbopts) } // Initialize data stores - m.cs = newContentStore(m, cs) + m.cs = newContentStore(m, m.dbopts.shared, cs) for name, sn := range ss { m.ss[name] = newSnapshotter(m, name, sn) } @@ -154,7 +176,7 @@ func (m *DB) Init(ctx context.Context) error { if err := m.migrate(tx); err != nil { return errors.Wrapf(err, "failed to migrate to %s.%d", m.schema, m.version) } - log.G(ctx).WithField("d", time.Now().Sub(t0)).Debugf("finished database migration to %s.%d", m.schema, m.version) + log.G(ctx).WithField("d", time.Since(t0)).Debugf("finished database migration to %s.%d", m.schema, m.version) } } @@ -306,7 +328,7 @@ func (m *DB) GarbageCollect(ctx context.Context) (gc.Stats, error) { m.cleanupSnapshotter(snapshotterName) sl.Lock() - stats.SnapshotD[snapshotterName] = time.Now().Sub(st1) + stats.SnapshotD[snapshotterName] = time.Since(st1) sl.Unlock() wg.Done() @@ -321,7 +343,7 @@ func (m *DB) GarbageCollect(ctx context.Context) (gc.Stats, error) { go func() { ct1 := time.Now() m.cleanupContent() - stats.ContentD = time.Now().Sub(ct1) + stats.ContentD = time.Since(ct1) wg.Done() }() m.dirtyCS = false @@ -329,7 +351,7 @@ func (m *DB) GarbageCollect(ctx context.Context) (gc.Stats, error) { m.dirtyL.Unlock() - stats.MetaD = time.Now().Sub(t1) + stats.MetaD = time.Since(t1) m.wlock.Unlock() wg.Wait() diff --git a/vendor/github.com/containerd/containerd/metadata/gc.go b/vendor/github.com/containerd/containerd/metadata/gc.go index a670ce1a3..99503fad7 100644 --- a/vendor/github.com/containerd/containerd/metadata/gc.go +++ b/vendor/github.com/containerd/containerd/metadata/gc.go @@ -296,10 +296,6 @@ func references(ctx context.Context, tx *bolt.Tx, node gc.Node, fn func(gc.Node) bkt := getBucket(tx, bucketKeyVersion, []byte(node.Namespace), bucketKeyObjectSnapshots, []byte(ss), []byte(name)) if bkt == nil { - getBucket(tx, bucketKeyVersion, []byte(node.Namespace), bucketKeyObjectSnapshots).ForEach(func(k, v []byte) error { - return nil - }) - // Node may be created from dead edge return nil } diff --git a/vendor/github.com/containerd/containerd/metadata/snapshot.go b/vendor/github.com/containerd/containerd/metadata/snapshot.go index 75b80b0bc..b1665c019 100644 --- a/vendor/github.com/containerd/containerd/metadata/snapshot.go +++ b/vendor/github.com/containerd/containerd/metadata/snapshot.go @@ -628,7 +628,7 @@ func (s *snapshotter) garbageCollect(ctx context.Context) (d time.Duration, err } } if err == nil { - d = time.Now().Sub(t1) + d = time.Since(t1) } }() diff --git a/vendor/github.com/containerd/containerd/oci/spec_opts.go b/vendor/github.com/containerd/containerd/oci/spec_opts.go index 8b599f805..b9949f837 100644 --- a/vendor/github.com/containerd/containerd/oci/spec_opts.go +++ b/vendor/github.com/containerd/containerd/oci/spec_opts.go @@ -141,8 +141,10 @@ func WithEnv(environmentVariables []string) SpecOpts { // replaced by env key or appended to the list func replaceOrAppendEnvValues(defaults, overrides []string) []string { cache := make(map[string]int, len(defaults)) + results := make([]string, 0, len(defaults)) for i, e := range defaults { parts := strings.SplitN(e, "=", 2) + results = append(results, e) cache[parts[0]] = i } @@ -150,7 +152,7 @@ func replaceOrAppendEnvValues(defaults, overrides []string) []string { // Values w/o = means they want this env to be removed/unset. if !strings.Contains(value, "=") { if i, exists := cache[value]; exists { - defaults[i] = "" // Used to indicate it should be removed + results[i] = "" // Used to indicate it should be removed } continue } @@ -158,21 +160,21 @@ func replaceOrAppendEnvValues(defaults, overrides []string) []string { // Just do a normal set/update parts := strings.SplitN(value, "=", 2) if i, exists := cache[parts[0]]; exists { - defaults[i] = value + results[i] = value } else { - defaults = append(defaults, value) + results = append(results, value) } } // Now remove all entries that we want to "unset" - for i := 0; i < len(defaults); i++ { - if defaults[i] == "" { - defaults = append(defaults[:i], defaults[i+1:]...) + for i := 0; i < len(results); i++ { + if results[i] == "" { + results = append(results[:i], results[i+1:]...) i-- } } - return defaults + return results } // WithProcessArgs replaces the args on the generated spec @@ -310,7 +312,7 @@ func WithImageConfigArgs(image Image, args []string) SpecOpts { setProcess(s) if s.Linux != nil { - s.Process.Env = append(s.Process.Env, config.Env...) + s.Process.Env = replaceOrAppendEnvValues(s.Process.Env, config.Env) cmd := config.Cmd if len(args) > 0 { cmd = args @@ -332,8 +334,14 @@ func WithImageConfigArgs(image Image, args []string) SpecOpts { // even if there is no specified user in the image config return WithAdditionalGIDs("root")(ctx, client, c, s) } else if s.Windows != nil { - s.Process.Env = config.Env - s.Process.Args = append(config.Entrypoint, config.Cmd...) + s.Process.Env = replaceOrAppendEnvValues(s.Process.Env, config.Env) + cmd := config.Cmd + if len(args) > 0 { + cmd = args + } + s.Process.Args = append(config.Entrypoint, cmd...) + + s.Process.Cwd = config.WorkingDir s.Process.User = specs.User{ Username: config.User, } @@ -1026,3 +1034,32 @@ func WithWindowsHyperV(_ context.Context, _ Client, _ *containers.Container, s * } return nil } + +// WithMemoryLimit sets the `Linux.LinuxResources.Memory.Limit` section to the +// `limit` specified if the `Linux` section is not `nil`. Additionally sets the +// `Windows.WindowsResources.Memory.Limit` section if the `Windows` section is +// not `nil`. +func WithMemoryLimit(limit uint64) SpecOpts { + return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { + if s.Linux != nil { + if s.Linux.Resources == nil { + s.Linux.Resources = &specs.LinuxResources{} + } + if s.Linux.Resources.Memory == nil { + s.Linux.Resources.Memory = &specs.LinuxMemory{} + } + l := int64(limit) + s.Linux.Resources.Memory.Limit = &l + } + if s.Windows != nil { + if s.Windows.Resources == nil { + s.Windows.Resources = &specs.WindowsResources{} + } + if s.Windows.Resources.Memory == nil { + s.Windows.Resources.Memory = &specs.WindowsMemoryResources{} + } + s.Windows.Resources.Memory.Limit = &limit + } + return nil + } +} diff --git a/vendor/github.com/containerd/containerd/oci/spec_opts_windows.go b/vendor/github.com/containerd/containerd/oci/spec_opts_windows.go new file mode 100644 index 000000000..7b82769f3 --- /dev/null +++ b/vendor/github.com/containerd/containerd/oci/spec_opts_windows.go @@ -0,0 +1,41 @@ +// +build windows + +/* + Copyright The containerd 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 oci + +import ( + "context" + + "github.com/containerd/containerd/containers" + specs "github.com/opencontainers/runtime-spec/specs-go" +) + +// WithWindowsCPUCount sets the `Windows.Resources.CPU.Count` section to the +// `count` specified. +func WithWindowsCPUCount(count uint64) SpecOpts { + return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { + if s.Windows.Resources == nil { + s.Windows.Resources = &specs.WindowsResources{} + } + if s.Windows.Resources.CPU == nil { + s.Windows.Resources.CPU = &specs.WindowsCPUResources{} + } + s.Windows.Resources.CPU.Count = &count + return nil + } +} diff --git a/vendor/github.com/containerd/containerd/pkg/progress/bar.go b/vendor/github.com/containerd/containerd/pkg/progress/bar.go index 649e69451..cbe41a925 100644 --- a/vendor/github.com/containerd/containerd/pkg/progress/bar.go +++ b/vendor/github.com/containerd/containerd/pkg/progress/bar.go @@ -70,9 +70,9 @@ func (h Bar) Format(state fmt.State, r rune) { negative := width - pad - positive n := 1 - n += copy(p[n:], []byte(green)) + n += copy(p[n:], green) n += copy(p[n:], bytes.Repeat([]byte("+"), positive)) - n += copy(p[n:], []byte(reset)) + n += copy(p[n:], reset) if negative > 0 { copy(p[n:len(p)-1], bytes.Repeat([]byte("-"), negative)) diff --git a/vendor/github.com/containerd/containerd/pkg/progress/escape.go b/vendor/github.com/containerd/containerd/pkg/progress/escape.go index 471219efb..73505f69d 100644 --- a/vendor/github.com/containerd/containerd/pkg/progress/escape.go +++ b/vendor/github.com/containerd/containerd/pkg/progress/escape.go @@ -19,6 +19,6 @@ package progress const ( escape = "\x1b" reset = escape + "[0m" - red = escape + "[31m" // nolint: unused, varcheck + red = escape + "[31m" // nolint: staticcheck, varcheck green = escape + "[32m" ) diff --git a/vendor/github.com/containerd/containerd/plugin/plugin.go b/vendor/github.com/containerd/containerd/plugin/plugin.go index 0847ae7f2..4d2d486d0 100644 --- a/vendor/github.com/containerd/containerd/plugin/plugin.go +++ b/vendor/github.com/containerd/containerd/plugin/plugin.go @@ -42,10 +42,7 @@ var ( // IsSkipPlugin returns true if the error is skipping the plugin func IsSkipPlugin(err error) bool { - if errors.Cause(err) == ErrSkipPlugin { - return true - } - return false + return errors.Cause(err) == ErrSkipPlugin } // Type is the type of the plugin diff --git a/vendor/github.com/containerd/containerd/process.go b/vendor/github.com/containerd/containerd/process.go index ff7d838cd..42f3b84a9 100644 --- a/vendor/github.com/containerd/containerd/process.go +++ b/vendor/github.com/containerd/containerd/process.go @@ -111,9 +111,11 @@ func (p *process) Start(ctx context.Context) error { ExecID: p.id, }) if err != nil { - p.io.Cancel() - p.io.Wait() - p.io.Close() + if p.io != nil { + p.io.Cancel() + p.io.Wait() + p.io.Close() + } return errdefs.FromGRPC(err) } p.pid = r.Pid diff --git a/vendor/github.com/containerd/containerd/remotes/docker/auth.go b/vendor/github.com/containerd/containerd/remotes/docker/auth.go index 80bcb9dcf..70cfdea4f 100644 --- a/vendor/github.com/containerd/containerd/remotes/docker/auth.go +++ b/vendor/github.com/containerd/containerd/remotes/docker/auth.go @@ -79,8 +79,8 @@ func init() { var t octetType isCtl := c <= 31 || c == 127 isChar := 0 <= c && c <= 127 - isSeparator := strings.IndexRune(" \t\"(),/:;<=>?@[]\\{}", rune(c)) >= 0 - if strings.IndexRune(" \t\r\n", rune(c)) >= 0 { + isSeparator := strings.ContainsRune(" \t\"(),/:;<=>?@[]\\{}", rune(c)) + if strings.ContainsRune(" \t\r\n", rune(c)) { t |= isSpace } if isChar && !isCtl && !isSeparator { diff --git a/vendor/github.com/containerd/containerd/remotes/docker/authorizer.go b/vendor/github.com/containerd/containerd/remotes/docker/authorizer.go index e17628750..73adb5a2f 100644 --- a/vendor/github.com/containerd/containerd/remotes/docker/authorizer.go +++ b/vendor/github.com/containerd/containerd/remotes/docker/authorizer.go @@ -194,7 +194,11 @@ func (a *dockerAuthorizer) fetchTokenWithOAuth(ctx context.Context, to tokenOpti form.Set("password", to.secret) } - resp, err := ctxhttp.PostForm(ctx, a.client, to.realm, form) + resp, err := ctxhttp.Post( + ctx, a.client, to.realm, + "application/x-www-form-urlencoded; charset=utf-8", + strings.NewReader(form.Encode()), + ) if err != nil { return "", err } diff --git a/vendor/github.com/containerd/containerd/remotes/docker/converter.go b/vendor/github.com/containerd/containerd/remotes/docker/converter.go new file mode 100644 index 000000000..43e6b372c --- /dev/null +++ b/vendor/github.com/containerd/containerd/remotes/docker/converter.go @@ -0,0 +1,88 @@ +/* + Copyright The containerd 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 docker + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + + "github.com/containerd/containerd/content" + "github.com/containerd/containerd/images" + "github.com/containerd/containerd/log" + "github.com/containerd/containerd/remotes" + digest "github.com/opencontainers/go-digest" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" + "github.com/pkg/errors" +) + +// LegacyConfigMediaType should be replaced by OCI image spec. +// +// More detail: docker/distribution#1622 +const LegacyConfigMediaType = "application/octet-stream" + +// ConvertManifest changes application/octet-stream to schema2 config media type if need. +// +// NOTE: +// 1. original manifest will be deleted by next gc round. +// 2. don't cover manifest list. +func ConvertManifest(ctx context.Context, store content.Store, desc ocispec.Descriptor) (ocispec.Descriptor, error) { + if !(desc.MediaType == images.MediaTypeDockerSchema2Manifest || + desc.MediaType == ocispec.MediaTypeImageManifest) { + + log.G(ctx).Warnf("do nothing for media type: %s", desc.MediaType) + return desc, nil + } + + // read manifest data + mb, err := content.ReadBlob(ctx, store, desc) + if err != nil { + return ocispec.Descriptor{}, errors.Wrap(err, "failed to read index data") + } + + var manifest ocispec.Manifest + if err := json.Unmarshal(mb, &manifest); err != nil { + return ocispec.Descriptor{}, errors.Wrap(err, "failed to unmarshal data into manifest") + } + + // check config media type + if manifest.Config.MediaType != LegacyConfigMediaType { + return desc, nil + } + + manifest.Config.MediaType = images.MediaTypeDockerSchema2Config + data, err := json.MarshalIndent(manifest, "", " ") + if err != nil { + return ocispec.Descriptor{}, errors.Wrap(err, "failed to marshal manifest") + } + + // update manifest with gc labels + desc.Digest = digest.Canonical.FromBytes(data) + desc.Size = int64(len(data)) + + labels := map[string]string{} + for i, c := range append([]ocispec.Descriptor{manifest.Config}, manifest.Layers...) { + labels[fmt.Sprintf("containerd.io/gc.ref.content.%d", i)] = c.Digest.String() + } + + ref := remotes.MakeRefKey(ctx, desc) + if err := content.WriteBlob(ctx, store, ref, bytes.NewReader(data), desc, content.WithLabels(labels)); err != nil { + return ocispec.Descriptor{}, errors.Wrap(err, "failed to update content") + } + return desc, nil +} diff --git a/vendor/github.com/containerd/containerd/remotes/handlers.go b/vendor/github.com/containerd/containerd/remotes/handlers.go index 77310fb62..86922de99 100644 --- a/vendor/github.com/containerd/containerd/remotes/handlers.go +++ b/vendor/github.com/containerd/containerd/remotes/handlers.go @@ -181,7 +181,7 @@ func PushContent(ctx context.Context, pusher Pusher, desc ocispec.Descriptor, pr pushHandler, ) - if err := images.Dispatch(ctx, images.Handlers(handlers...), desc); err != nil { + if err := images.Dispatch(ctx, images.Handlers(handlers...), nil, desc); err != nil { return err } diff --git a/vendor/github.com/containerd/containerd/runtime/linux/runctypes/runc.pb.go b/vendor/github.com/containerd/containerd/runtime/linux/runctypes/runc.pb.go index c13d23359..b6b573887 100644 --- a/vendor/github.com/containerd/containerd/runtime/linux/runctypes/runc.pb.go +++ b/vendor/github.com/containerd/containerd/runtime/linux/runctypes/runc.pb.go @@ -60,6 +60,8 @@ type CreateOptions struct { ShimCgroup string `protobuf:"bytes,9,opt,name=shim_cgroup,json=shimCgroup,proto3" json:"shim_cgroup,omitempty"` IoUid uint32 `protobuf:"varint,10,opt,name=io_uid,json=ioUid,proto3" json:"io_uid,omitempty"` IoGid uint32 `protobuf:"varint,11,opt,name=io_gid,json=ioGid,proto3" json:"io_gid,omitempty"` + CriuWorkPath string `protobuf:"bytes,12,opt,name=criu_work_path,json=criuWorkPath,proto3" json:"criu_work_path,omitempty"` + CriuImagePath string `protobuf:"bytes,13,opt,name=criu_image_path,json=criuImagePath,proto3" json:"criu_image_path,omitempty"` } func (m *CreateOptions) Reset() { *m = CreateOptions{} } @@ -74,6 +76,8 @@ type CheckpointOptions struct { FileLocks bool `protobuf:"varint,5,opt,name=file_locks,json=fileLocks,proto3" json:"file_locks,omitempty"` EmptyNamespaces []string `protobuf:"bytes,6,rep,name=empty_namespaces,json=emptyNamespaces" json:"empty_namespaces,omitempty"` CgroupsMode string `protobuf:"bytes,7,opt,name=cgroups_mode,json=cgroupsMode,proto3" json:"cgroups_mode,omitempty"` + WorkPath string `protobuf:"bytes,8,opt,name=work_path,json=workPath,proto3" json:"work_path,omitempty"` + ImagePath string `protobuf:"bytes,9,opt,name=image_path,json=imagePath,proto3" json:"image_path,omitempty"` } func (m *CheckpointOptions) Reset() { *m = CheckpointOptions{} } @@ -252,6 +256,18 @@ func (m *CreateOptions) MarshalTo(dAtA []byte) (int, error) { i++ i = encodeVarintRunc(dAtA, i, uint64(m.IoGid)) } + if len(m.CriuWorkPath) > 0 { + dAtA[i] = 0x62 + i++ + i = encodeVarintRunc(dAtA, i, uint64(len(m.CriuWorkPath))) + i += copy(dAtA[i:], m.CriuWorkPath) + } + if len(m.CriuImagePath) > 0 { + dAtA[i] = 0x6a + i++ + i = encodeVarintRunc(dAtA, i, uint64(len(m.CriuImagePath))) + i += copy(dAtA[i:], m.CriuImagePath) + } return i, nil } @@ -341,6 +357,18 @@ func (m *CheckpointOptions) MarshalTo(dAtA []byte) (int, error) { i = encodeVarintRunc(dAtA, i, uint64(len(m.CgroupsMode))) i += copy(dAtA[i:], m.CgroupsMode) } + if len(m.WorkPath) > 0 { + dAtA[i] = 0x42 + i++ + i = encodeVarintRunc(dAtA, i, uint64(len(m.WorkPath))) + i += copy(dAtA[i:], m.WorkPath) + } + if len(m.ImagePath) > 0 { + dAtA[i] = 0x4a + i++ + i = encodeVarintRunc(dAtA, i, uint64(len(m.ImagePath))) + i += copy(dAtA[i:], m.ImagePath) + } return i, nil } @@ -439,6 +467,14 @@ func (m *CreateOptions) Size() (n int) { if m.IoGid != 0 { n += 1 + sovRunc(uint64(m.IoGid)) } + l = len(m.CriuWorkPath) + if l > 0 { + n += 1 + l + sovRunc(uint64(l)) + } + l = len(m.CriuImagePath) + if l > 0 { + n += 1 + l + sovRunc(uint64(l)) + } return n } @@ -470,6 +506,14 @@ func (m *CheckpointOptions) Size() (n int) { if l > 0 { n += 1 + l + sovRunc(uint64(l)) } + l = len(m.WorkPath) + if l > 0 { + n += 1 + l + sovRunc(uint64(l)) + } + l = len(m.ImagePath) + if l > 0 { + n += 1 + l + sovRunc(uint64(l)) + } return n } @@ -525,6 +569,8 @@ func (this *CreateOptions) String() string { `ShimCgroup:` + fmt.Sprintf("%v", this.ShimCgroup) + `,`, `IoUid:` + fmt.Sprintf("%v", this.IoUid) + `,`, `IoGid:` + fmt.Sprintf("%v", this.IoGid) + `,`, + `CriuWorkPath:` + fmt.Sprintf("%v", this.CriuWorkPath) + `,`, + `CriuImagePath:` + fmt.Sprintf("%v", this.CriuImagePath) + `,`, `}`, }, "") return s @@ -541,6 +587,8 @@ func (this *CheckpointOptions) String() string { `FileLocks:` + fmt.Sprintf("%v", this.FileLocks) + `,`, `EmptyNamespaces:` + fmt.Sprintf("%v", this.EmptyNamespaces) + `,`, `CgroupsMode:` + fmt.Sprintf("%v", this.CgroupsMode) + `,`, + `WorkPath:` + fmt.Sprintf("%v", this.WorkPath) + `,`, + `ImagePath:` + fmt.Sprintf("%v", this.ImagePath) + `,`, `}`, }, "") return s @@ -994,6 +1042,64 @@ func (m *CreateOptions) Unmarshal(dAtA []byte) error { break } } + case 12: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CriuWorkPath", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRunc + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthRunc + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.CriuWorkPath = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 13: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CriuImagePath", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRunc + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthRunc + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.CriuImagePath = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipRunc(dAtA[iNdEx:]) @@ -1202,6 +1308,64 @@ func (m *CheckpointOptions) Unmarshal(dAtA []byte) error { } m.CgroupsMode = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field WorkPath", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRunc + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthRunc + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.WorkPath = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 9: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ImagePath", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRunc + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthRunc + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ImagePath = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipRunc(dAtA[iNdEx:]) @@ -1412,39 +1576,43 @@ func init() { } var fileDescriptorRunc = []byte{ - // 541 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x93, 0xc1, 0x6e, 0xd3, 0x40, - 0x10, 0x86, 0x6b, 0xda, 0x26, 0xce, 0xa4, 0x29, 0xb0, 0x50, 0xc9, 0x14, 0x91, 0x86, 0x00, 0x52, - 0xb8, 0xa4, 0x12, 0x88, 0x13, 0xb7, 0xa6, 0x08, 0x55, 0x40, 0xa9, 0x0c, 0x95, 0x10, 0x42, 0x5a, - 0xb9, 0xeb, 0x21, 0x59, 0xc5, 0xde, 0x59, 0x79, 0xd7, 0xd4, 0xb9, 0xf5, 0x09, 0x78, 0xae, 0x1e, - 0x39, 0x72, 0x42, 0x34, 0x2f, 0x02, 0xf2, 0xda, 0x0e, 0x9c, 0x39, 0x72, 0xfb, 0xe7, 0xfb, 0xc7, - 0x9e, 0xd1, 0xbf, 0x1a, 0x98, 0x4c, 0xa5, 0x9d, 0xe5, 0x67, 0x63, 0x41, 0xe9, 0xbe, 0x20, 0x65, - 0x23, 0xa9, 0x30, 0x8b, 0xff, 0x96, 0x59, 0xae, 0xac, 0x4c, 0x71, 0x3f, 0x91, 0x2a, 0x2f, 0xca, - 0x4a, 0xd8, 0x85, 0x46, 0xe3, 0xd4, 0x58, 0x67, 0x64, 0x89, 0xed, 0xfc, 0x69, 0x1f, 0xbb, 0xb6, - 0x71, 0x69, 0xee, 0xde, 0x9e, 0xd2, 0x94, 0x5c, 0xc7, 0x7e, 0xa9, 0xaa, 0xe6, 0xe1, 0x57, 0x0f, - 0xba, 0x61, 0xae, 0xc4, 0x5b, 0x6d, 0x25, 0x29, 0xc3, 0x02, 0x68, 0xd7, 0x23, 0x02, 0x6f, 0xe0, - 0x8d, 0x3a, 0x61, 0x53, 0xb2, 0xfb, 0xb0, 0x55, 0x4b, 0x9e, 0x11, 0xd9, 0xe0, 0x9a, 0xb3, 0xbb, - 0x35, 0x0b, 0x89, 0x2c, 0xbb, 0x0b, 0x1d, 0x91, 0xc9, 0x9c, 0xeb, 0xc8, 0xce, 0x82, 0x75, 0xe7, - 0xfb, 0x25, 0x38, 0x89, 0xec, 0x8c, 0x3d, 0x82, 0x6d, 0xb3, 0x30, 0x16, 0xd3, 0x98, 0x8b, 0x69, - 0x46, 0xb9, 0x0e, 0x36, 0x06, 0xde, 0xc8, 0x0f, 0x7b, 0x35, 0x9d, 0x38, 0x38, 0xbc, 0x58, 0x87, - 0xde, 0x24, 0xc3, 0xc8, 0x62, 0xb3, 0xd2, 0x10, 0x7a, 0x8a, 0xb8, 0x96, 0x5f, 0xc8, 0x56, 0x93, - 0x3d, 0xf7, 0x5d, 0x57, 0xd1, 0x49, 0xc9, 0xdc, 0xe4, 0x3b, 0xe0, 0x93, 0x46, 0xc5, 0xad, 0xd0, - 0x6e, 0x31, 0x3f, 0x6c, 0x97, 0xf5, 0x7b, 0xa1, 0xd9, 0x13, 0xd8, 0xc1, 0xc2, 0x62, 0xa6, 0xa2, - 0x84, 0xe7, 0x4a, 0x16, 0xdc, 0x90, 0x98, 0xa3, 0x35, 0x6e, 0x41, 0x3f, 0xbc, 0xd5, 0x98, 0xa7, - 0x4a, 0x16, 0xef, 0x2a, 0x8b, 0xed, 0x82, 0x6f, 0x31, 0x4b, 0xa5, 0x8a, 0x92, 0x7a, 0xcb, 0x55, - 0xcd, 0xee, 0x01, 0x7c, 0x96, 0x09, 0xf2, 0x84, 0xc4, 0xdc, 0x04, 0x9b, 0xce, 0xed, 0x94, 0xe4, - 0x75, 0x09, 0xd8, 0x63, 0xb8, 0x81, 0xa9, 0xb6, 0x0b, 0xae, 0xa2, 0x14, 0x8d, 0x8e, 0x04, 0x9a, - 0xa0, 0x35, 0x58, 0x1f, 0x75, 0xc2, 0xeb, 0x8e, 0x1f, 0xaf, 0x70, 0x99, 0x68, 0x95, 0x84, 0xe1, - 0x29, 0xc5, 0x18, 0xb4, 0xab, 0x44, 0x6b, 0xf6, 0x86, 0x62, 0x64, 0x0f, 0x61, 0x5b, 0x11, 0x57, - 0x78, 0xce, 0xe7, 0xb8, 0xc8, 0xa4, 0x9a, 0x06, 0xbe, 0x1b, 0xb8, 0xa5, 0xe8, 0x18, 0xcf, 0x5f, - 0x55, 0x8c, 0xed, 0x41, 0xd7, 0xcc, 0x64, 0xda, 0xe4, 0xda, 0x71, 0xff, 0x81, 0x12, 0x55, 0xa1, - 0xb2, 0x1d, 0x68, 0x49, 0xe2, 0xb9, 0x8c, 0x03, 0x18, 0x78, 0xa3, 0x5e, 0xb8, 0x29, 0xe9, 0x54, - 0xc6, 0x35, 0x9e, 0xca, 0x38, 0xe8, 0x36, 0xf8, 0xa5, 0x8c, 0x87, 0xbf, 0x3c, 0xb8, 0x39, 0x99, - 0xa1, 0x98, 0x6b, 0x92, 0xca, 0x36, 0xcf, 0xc0, 0x60, 0x03, 0x0b, 0xd9, 0xa4, 0xef, 0xf4, 0xff, - 0x1a, 0xfb, 0xf0, 0x19, 0x6c, 0x9f, 0x64, 0x24, 0xd0, 0x98, 0x43, 0xb4, 0x91, 0x4c, 0x0c, 0x7b, - 0x00, 0x6d, 0x2c, 0x50, 0x70, 0x19, 0x57, 0x77, 0x71, 0x00, 0xcb, 0x1f, 0x7b, 0xad, 0x17, 0x05, - 0x8a, 0xa3, 0xc3, 0xb0, 0x55, 0x5a, 0x47, 0xf1, 0xc1, 0xa7, 0xcb, 0xab, 0xfe, 0xda, 0xf7, 0xab, - 0xfe, 0xda, 0xc5, 0xb2, 0xef, 0x5d, 0x2e, 0xfb, 0xde, 0xb7, 0x65, 0xdf, 0xfb, 0xb9, 0xec, 0x7b, - 0x1f, 0x0f, 0xfe, 0xf5, 0xb0, 0x9f, 0xaf, 0xd4, 0x87, 0xb5, 0xb3, 0x96, 0xbb, 0xd9, 0xa7, 0xbf, - 0x03, 0x00, 0x00, 0xff, 0xff, 0x18, 0xa1, 0x4b, 0x5b, 0x27, 0x04, 0x00, 0x00, + // 604 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x94, 0xcf, 0x6e, 0xd3, 0x40, + 0x10, 0xc6, 0xeb, 0xfe, 0x49, 0x9c, 0x49, 0xd2, 0xc2, 0x42, 0x25, 0xd3, 0xaa, 0x69, 0x08, 0x7f, + 0x14, 0x2e, 0xa9, 0x04, 0xe2, 0xc4, 0xad, 0x29, 0x42, 0x15, 0x50, 0x2a, 0x43, 0x05, 0x42, 0x48, + 0x2b, 0x77, 0x3d, 0x24, 0xab, 0xc4, 0x3b, 0x96, 0x77, 0x4d, 0x92, 0x1b, 0x4f, 0xc0, 0x0b, 0xf1, + 0x02, 0x3d, 0x21, 0x8e, 0x9c, 0x10, 0xcd, 0x93, 0xa0, 0x5d, 0xc7, 0x69, 0xcf, 0x1c, 0xb9, 0xcd, + 0xfc, 0xe6, 0xb3, 0x67, 0xf4, 0x7d, 0xb2, 0xa1, 0x3f, 0x90, 0x66, 0x98, 0x9f, 0xf7, 0x04, 0x25, + 0x07, 0x82, 0x94, 0x89, 0xa4, 0xc2, 0x2c, 0xbe, 0x5e, 0x66, 0xb9, 0x32, 0x32, 0xc1, 0x83, 0xb1, + 0x54, 0xf9, 0xd4, 0x76, 0xc2, 0xcc, 0x52, 0xd4, 0xae, 0xea, 0xa5, 0x19, 0x19, 0x62, 0xdb, 0x57, + 0xf2, 0x9e, 0x93, 0xf5, 0xec, 0x70, 0xe7, 0xf6, 0x80, 0x06, 0xe4, 0x14, 0x07, 0xb6, 0x2a, 0xc4, + 0x9d, 0x6f, 0x1e, 0xd4, 0xc3, 0x5c, 0x89, 0x37, 0xa9, 0x91, 0xa4, 0x34, 0x0b, 0xa0, 0xba, 0x58, + 0x11, 0x78, 0x6d, 0xaf, 0x5b, 0x0b, 0xcb, 0x96, 0xdd, 0x85, 0xc6, 0xa2, 0xe4, 0x19, 0x91, 0x09, + 0x56, 0xdd, 0xb8, 0xbe, 0x60, 0x21, 0x91, 0x61, 0xbb, 0x50, 0x13, 0x99, 0xcc, 0x79, 0x1a, 0x99, + 0x61, 0xb0, 0xe6, 0xe6, 0xbe, 0x05, 0xa7, 0x91, 0x19, 0xb2, 0x07, 0xb0, 0xa9, 0x67, 0xda, 0x60, + 0x12, 0x73, 0x31, 0xc8, 0x28, 0x4f, 0x83, 0xf5, 0xb6, 0xd7, 0xf5, 0xc3, 0xe6, 0x82, 0xf6, 0x1d, + 0xec, 0xfc, 0x58, 0x83, 0x66, 0x3f, 0xc3, 0xc8, 0x60, 0x79, 0x52, 0x07, 0x9a, 0x8a, 0x78, 0x2a, + 0xbf, 0x90, 0x29, 0x36, 0x7b, 0xee, 0xb9, 0xba, 0xa2, 0x53, 0xcb, 0xdc, 0xe6, 0x3b, 0xe0, 0x53, + 0x8a, 0x8a, 0x1b, 0x91, 0xba, 0xc3, 0xfc, 0xb0, 0x6a, 0xfb, 0x77, 0x22, 0x65, 0x8f, 0x61, 0x1b, + 0xa7, 0x06, 0x33, 0x15, 0x8d, 0x79, 0xae, 0xe4, 0x94, 0x6b, 0x12, 0x23, 0x34, 0xda, 0x1d, 0xe8, + 0x87, 0xb7, 0xca, 0xe1, 0x99, 0x92, 0xd3, 0xb7, 0xc5, 0x88, 0xed, 0x80, 0x6f, 0x30, 0x4b, 0xa4, + 0x8a, 0xc6, 0x8b, 0x2b, 0x97, 0x3d, 0xdb, 0x03, 0xf8, 0x2c, 0xc7, 0xc8, 0xc7, 0x24, 0x46, 0x3a, + 0xd8, 0x70, 0xd3, 0x9a, 0x25, 0xaf, 0x2c, 0x60, 0x8f, 0xe0, 0x06, 0x26, 0xa9, 0x99, 0x71, 0x15, + 0x25, 0xa8, 0xd3, 0x48, 0xa0, 0x0e, 0x2a, 0xed, 0xb5, 0x6e, 0x2d, 0xdc, 0x72, 0xfc, 0x64, 0x89, + 0xad, 0xa3, 0x85, 0x13, 0x9a, 0x27, 0x14, 0x63, 0x50, 0x2d, 0x1c, 0x5d, 0xb0, 0xd7, 0x14, 0x23, + 0xbb, 0x0f, 0x9b, 0x8a, 0xb8, 0xc2, 0x09, 0x1f, 0xe1, 0x2c, 0x93, 0x6a, 0x10, 0xf8, 0x6e, 0x61, + 0x43, 0xd1, 0x09, 0x4e, 0x5e, 0x16, 0x8c, 0xed, 0x43, 0x5d, 0x0f, 0x65, 0x52, 0xfa, 0x5a, 0x73, + 0xef, 0x01, 0x8b, 0x0a, 0x53, 0xd9, 0x36, 0x54, 0x24, 0xf1, 0x5c, 0xc6, 0x01, 0xb4, 0xbd, 0x6e, + 0x33, 0xdc, 0x90, 0x74, 0x26, 0xe3, 0x05, 0x1e, 0xc8, 0x38, 0xa8, 0x97, 0xf8, 0x85, 0x8c, 0xed, + 0x52, 0x17, 0xe3, 0x84, 0xb2, 0x51, 0x91, 0x65, 0xc3, 0xbd, 0xb1, 0x61, 0xe9, 0x7b, 0xca, 0x46, + 0x2e, 0xcf, 0x87, 0xb0, 0xe5, 0x54, 0x32, 0x89, 0x06, 0x58, 0xc8, 0x9a, 0x4e, 0xd6, 0xb4, 0xf8, + 0xd8, 0x52, 0xab, 0xeb, 0x7c, 0x5f, 0x85, 0x9b, 0xfd, 0x21, 0x8a, 0x51, 0x4a, 0x52, 0x99, 0x32, + 0x54, 0x06, 0xeb, 0x38, 0x95, 0x65, 0x96, 0xae, 0xfe, 0x6f, 0x43, 0xdc, 0x85, 0xda, 0x95, 0x95, + 0x7e, 0xf1, 0x59, 0x4c, 0x4a, 0x1b, 0xf7, 0x00, 0xae, 0x39, 0x58, 0x44, 0x57, 0x93, 0x4b, 0xf7, + 0x9e, 0xc2, 0xe6, 0x69, 0x46, 0x02, 0xb5, 0x3e, 0x42, 0x13, 0xc9, 0xb1, 0x66, 0xf7, 0xa0, 0x8a, + 0x53, 0x14, 0x5c, 0xc6, 0xc5, 0x17, 0x7a, 0x08, 0xf3, 0xdf, 0xfb, 0x95, 0xe7, 0x53, 0x14, 0xc7, + 0x47, 0x61, 0xc5, 0x8e, 0x8e, 0xe3, 0xc3, 0x4f, 0x17, 0x97, 0xad, 0x95, 0x5f, 0x97, 0xad, 0x95, + 0xaf, 0xf3, 0x96, 0x77, 0x31, 0x6f, 0x79, 0x3f, 0xe7, 0x2d, 0xef, 0xcf, 0xbc, 0xe5, 0x7d, 0x3c, + 0xfc, 0xd7, 0x5f, 0xcc, 0xb3, 0x65, 0xf5, 0x61, 0xe5, 0xbc, 0xe2, 0xfe, 0x1e, 0x4f, 0xfe, 0x06, + 0x00, 0x00, 0xff, 0xff, 0x7f, 0x24, 0x6f, 0x2e, 0xb1, 0x04, 0x00, 0x00, } diff --git a/vendor/github.com/containerd/containerd/runtime/linux/runctypes/runc.proto b/vendor/github.com/containerd/containerd/runtime/linux/runctypes/runc.proto index ddd3f8d11..78e3abf4c 100644 --- a/vendor/github.com/containerd/containerd/runtime/linux/runctypes/runc.proto +++ b/vendor/github.com/containerd/containerd/runtime/linux/runctypes/runc.proto @@ -25,6 +25,8 @@ message CreateOptions { string shim_cgroup = 9; uint32 io_uid = 10; uint32 io_gid = 11; + string criu_work_path = 12; + string criu_image_path = 13; } message CheckpointOptions { @@ -35,6 +37,8 @@ message CheckpointOptions { bool file_locks = 5; repeated string empty_namespaces = 6; string cgroups_mode = 7; + string work_path = 8; + string image_path = 9; } message ProcessDetails { diff --git a/vendor/github.com/containerd/containerd/runtime/runtime.go b/vendor/github.com/containerd/containerd/runtime/runtime.go index 1b3f87c15..5a3f654bd 100644 --- a/vendor/github.com/containerd/containerd/runtime/runtime.go +++ b/vendor/github.com/containerd/containerd/runtime/runtime.go @@ -69,4 +69,8 @@ type PlatformRuntime interface { // Tasks returns all the current tasks for the runtime. // Any container runs at most one task at a time. Tasks(context.Context, bool) ([]Task, error) + // Add adds a task into runtime. + Add(context.Context, Task) error + // Delete remove a task. + Delete(context.Context, string) } diff --git a/vendor/github.com/containerd/containerd/runtime/v1/linux/bundle.go b/vendor/github.com/containerd/containerd/runtime/v1/linux/bundle.go index d73866a2f..74a9f2aba 100644 --- a/vendor/github.com/containerd/containerd/runtime/v1/linux/bundle.go +++ b/vendor/github.com/containerd/containerd/runtime/v1/linux/bundle.go @@ -20,6 +20,7 @@ package linux import ( "context" + "fmt" "io/ioutil" "os" "path/filepath" @@ -114,12 +115,12 @@ func (b *bundle) NewShimClient(ctx context.Context, namespace string, getClientO // Delete deletes the bundle from disk func (b *bundle) Delete() error { - err := os.RemoveAll(b.path) + err := atomicDelete(b.path) if err == nil { - return os.RemoveAll(b.workDir) + return atomicDelete(b.workDir) } // error removing the bundle path; still attempt removing work dir - err2 := os.RemoveAll(b.workDir) + err2 := atomicDelete(b.workDir) if err2 == nil { return err } @@ -152,3 +153,13 @@ func (b *bundle) shimConfig(namespace string, c *Config, runcOptions *runctypes. SystemdCgroup: systemdCgroup, } } + +// atomicDelete renames the path to a hidden file before removal +func atomicDelete(path string) error { + // create a hidden dir for an atomic removal + atomicPath := filepath.Join(filepath.Dir(path), fmt.Sprintf(".%s", filepath.Base(path))) + if err := os.Rename(path, atomicPath); err != nil { + return err + } + return os.RemoveAll(atomicPath) +} diff --git a/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/deleted_state.go b/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/deleted_state.go index bc9aefb7f..ab89c3ecb 100644 --- a/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/deleted_state.go +++ b/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/deleted_state.go @@ -69,7 +69,3 @@ func (s *deletedState) SetExited(status int) { func (s *deletedState) Exec(ctx context.Context, path string, r *ExecConfig) (proc.Process, error) { return nil, errors.Errorf("cannot exec in a deleted state") } - -func (s *deletedState) Pid() int { - return -1 -} diff --git a/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/exec.go b/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/exec.go index 4c0e99e89..5dbfbaf62 100644 --- a/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/exec.go +++ b/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/exec.go @@ -49,7 +49,7 @@ type execProcess struct { io runc.IO status int exited time.Time - pid int + pid *safePid closers []io.Closer stdin io.Closer stdio proc.Stdio @@ -69,11 +69,7 @@ func (e *execProcess) ID() string { } func (e *execProcess) Pid() int { - return e.execState.Pid() -} - -func (e *execProcess) pidv() int { - return e.pid + return e.pid.get() } func (e *execProcess) ExitStatus() int { @@ -145,7 +141,7 @@ func (e *execProcess) Kill(ctx context.Context, sig uint32, _ bool) error { } func (e *execProcess) kill(ctx context.Context, sig uint32, _ bool) error { - pid := e.pid + pid := e.pid.get() if pid != 0 { if err := unix.Kill(pid, syscall.Signal(sig)); err != nil { return errors.Wrapf(checkKillError(err), "exec kill error") @@ -170,6 +166,12 @@ func (e *execProcess) Start(ctx context.Context) error { } func (e *execProcess) start(ctx context.Context) (err error) { + // The reaper may receive exit signal right after + // the container is started, before the e.pid is updated. + // In that case, we want to block the signal handler to + // access e.pid until it is updated. + e.pid.Lock() + defer e.pid.Unlock() var ( socket *runc.Socket pidfile = filepath.Join(e.path, fmt.Sprintf("%s.pid", e.id)) @@ -201,7 +203,7 @@ func (e *execProcess) start(ctx context.Context) (err error) { return e.parent.runtimeError(err, "OCI runtime exec failed") } if e.stdio.Stdin != "" { - sc, err := fifo.OpenFifo(ctx, e.stdio.Stdin, syscall.O_WRONLY|syscall.O_NONBLOCK, 0) + sc, err := fifo.OpenFifo(context.Background(), e.stdio.Stdin, syscall.O_WRONLY|syscall.O_NONBLOCK, 0) if err != nil { return errors.Wrapf(err, "failed to open stdin fifo %s", e.stdio.Stdin) } @@ -209,6 +211,8 @@ func (e *execProcess) start(ctx context.Context) (err error) { e.stdin = sc } var copyWaitGroup sync.WaitGroup + ctx, cancel := context.WithTimeout(ctx, 30*time.Second) + defer cancel() if socket != nil { console, err := socket.ReceiveMaster() if err != nil { @@ -227,7 +231,7 @@ func (e *execProcess) start(ctx context.Context) (err error) { if err != nil { return errors.Wrap(err, "failed to retrieve OCI runtime exec pid") } - e.pid = pid + e.pid.pid = pid return nil } @@ -245,11 +249,11 @@ func (e *execProcess) Status(ctx context.Context) (string, error) { e.mu.Lock() defer e.mu.Unlock() // if we don't have a pid then the exec process has just been created - if e.pid == 0 { + if e.pid.get() == 0 { return "created", nil } // if we have a pid and it can be signaled, the process is running - if err := unix.Kill(e.pid, 0); err == nil { + if err := unix.Kill(e.pid.get(), 0); err == nil { return "running", nil } // else if we have a pid but it can nolonger be signaled, it has stopped diff --git a/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/exec_state.go b/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/exec_state.go index 0e0bc3fcf..12489501b 100644 --- a/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/exec_state.go +++ b/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/exec_state.go @@ -31,7 +31,6 @@ type execState interface { Delete(context.Context) error Kill(context.Context, uint32, bool) error SetExited(int) - Pid() int } type execCreatedState struct { @@ -83,12 +82,6 @@ func (s *execCreatedState) SetExited(status int) { } } -func (s *execCreatedState) Pid() int { - s.p.mu.Lock() - defer s.p.mu.Unlock() - return s.p.pidv() -} - type execRunningState struct { p *execProcess } @@ -127,12 +120,6 @@ func (s *execRunningState) SetExited(status int) { } } -func (s *execRunningState) Pid() int { - s.p.mu.Lock() - defer s.p.mu.Unlock() - return s.p.pidv() -} - type execStoppedState struct { p *execProcess } @@ -170,7 +157,3 @@ func (s *execStoppedState) Kill(ctx context.Context, sig uint32, all bool) error func (s *execStoppedState) SetExited(status int) { // no op } - -func (s *execStoppedState) Pid() int { - return s.p.pidv() -} diff --git a/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/init.go b/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/init.go index fa23b5e88..81f6d9514 100644 --- a/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/init.go +++ b/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/init.go @@ -76,6 +76,7 @@ type Init struct { IoGID int NoPivotRoot bool NoNewKeyring bool + CriuWorkPath string } // NewRunc returns a new runc instance for a process @@ -132,7 +133,7 @@ func (p *Init) Create(ctx context.Context, r *CreateConfig) error { opts := &runc.RestoreOpts{ CheckpointOpts: runc.CheckpointOpts{ ImagePath: r.Checkpoint, - WorkDir: p.WorkDir, + WorkDir: p.CriuWorkPath, ParentPath: r.ParentCheckpoint, }, PidFile: pidFile, @@ -160,7 +161,7 @@ func (p *Init) Create(ctx context.Context, r *CreateConfig) error { return p.runtimeError(err, "OCI runtime create failed") } if r.Stdin != "" { - sc, err := fifo.OpenFifo(ctx, r.Stdin, syscall.O_WRONLY|syscall.O_NONBLOCK, 0) + sc, err := fifo.OpenFifo(context.Background(), r.Stdin, syscall.O_WRONLY|syscall.O_NONBLOCK, 0) if err != nil { return errors.Wrapf(err, "failed to open stdin fifo %s", r.Stdin) } @@ -168,6 +169,8 @@ func (p *Init) Create(ctx context.Context, r *CreateConfig) error { p.closers = append(p.closers, sc) } var copyWaitGroup sync.WaitGroup + ctx, cancel := context.WithTimeout(ctx, 30*time.Second) + defer cancel() if socket != nil { console, err := socket.ReceiveMaster() if err != nil { @@ -404,6 +407,7 @@ func (p *Init) exec(ctx context.Context, path string, r *ExecConfig) (proc.Proce Terminal: r.Terminal, }, waitBlock: make(chan struct{}), + pid: &safePid{}, } e.execState = &execCreatedState{p: e} return e, nil @@ -422,8 +426,12 @@ func (p *Init) checkpoint(ctx context.Context, r *CheckpointConfig) error { if !r.Exit { actions = append(actions, runc.LeaveRunning) } - work := filepath.Join(p.WorkDir, "criu-work") - defer os.RemoveAll(work) + // keep criu work directory if criu work dir is set + work := r.WorkDir + if work == "" { + work = filepath.Join(p.WorkDir, "criu-work") + defer os.RemoveAll(work) + } if err := p.runtime.Checkpoint(ctx, p.id, &runc.CheckpointOpts{ WorkDir: work, ImagePath: r.Path, diff --git a/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/init_state.go b/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/init_state.go index 37798de20..62cbe38cd 100644 --- a/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/init_state.go +++ b/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/init_state.go @@ -172,7 +172,7 @@ func (s *createdCheckpointState) Start(ctx context.Context) error { return p.runtimeError(err, "OCI runtime restore failed") } if sio.Stdin != "" { - sc, err := fifo.OpenFifo(ctx, sio.Stdin, syscall.O_WRONLY|syscall.O_NONBLOCK, 0) + sc, err := fifo.OpenFifo(context.Background(), sio.Stdin, syscall.O_WRONLY|syscall.O_NONBLOCK, 0) if err != nil { return errors.Wrapf(err, "failed to open stdin fifo %s", sio.Stdin) } diff --git a/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/io.go b/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/io.go index 71f6ee1bb..aed349a86 100644 --- a/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/io.go +++ b/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/io.go @@ -111,7 +111,7 @@ func copyPipes(ctx context.Context, rio runc.IO, stdin, stdout, stderr string, w if stdin == "" { return nil } - f, err := fifo.OpenFifo(ctx, stdin, syscall.O_RDONLY|syscall.O_NONBLOCK, 0) + f, err := fifo.OpenFifo(context.Background(), stdin, syscall.O_RDONLY|syscall.O_NONBLOCK, 0) if err != nil { return fmt.Errorf("containerd-shim: opening %s failed: %s", stdin, err) } diff --git a/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/types.go b/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/types.go index 2bea98dc8..5d705c030 100644 --- a/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/types.go +++ b/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/types.go @@ -55,6 +55,7 @@ type ExecConfig struct { // CheckpointConfig holds task checkpoint configuration type CheckpointConfig struct { + WorkDir string Path string Exit bool AllowOpenTCP bool diff --git a/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/utils.go b/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/utils.go index 3d0334c45..075ef2617 100644 --- a/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/utils.go +++ b/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/utils.go @@ -23,6 +23,7 @@ import ( "io" "os" "strings" + "sync" "time" "github.com/containerd/containerd/errdefs" @@ -31,6 +32,18 @@ import ( "golang.org/x/sys/unix" ) +// safePid is a thread safe wrapper for pid. +type safePid struct { + sync.Mutex + pid int +} + +func (s *safePid) get() int { + s.Lock() + defer s.Unlock() + return s.pid +} + // TODO(mlaventure): move to runc package? func getLastRuntimeError(r *runc.Runc) (string, error) { if r.Log == "" { @@ -93,7 +106,9 @@ func checkKillError(err error) error { if err == nil { return nil } - if strings.Contains(err.Error(), "os: process already finished") || err == unix.ESRCH { + if strings.Contains(err.Error(), "os: process already finished") || + strings.Contains(err.Error(), "container not running") || + err == unix.ESRCH { return errors.Wrapf(errdefs.ErrNotFound, "process already finished") } return errors.Wrapf(err, "unknown error after kill") diff --git a/vendor/github.com/containerd/containerd/runtime/v1/linux/runtime.go b/vendor/github.com/containerd/containerd/runtime/v1/linux/runtime.go index e1b3cacea..545e2167a 100644 --- a/vendor/github.com/containerd/containerd/runtime/v1/linux/runtime.go +++ b/vendor/github.com/containerd/containerd/runtime/v1/linux/runtime.go @@ -290,6 +290,10 @@ func (r *Runtime) restoreTasks(ctx context.Context) ([]*Task, error) { continue } name := namespace.Name() + // skip hidden directories + if len(name) > 0 && name[0] == '.' { + continue + } log.G(ctx).WithField("namespace", name).Debug("loading tasks in namespace") tasks, err := r.loadTasks(ctx, name) if err != nil { @@ -305,6 +309,16 @@ func (r *Runtime) Get(ctx context.Context, id string) (runtime.Task, error) { return r.tasks.Get(ctx, id) } +// Add a runtime task +func (r *Runtime) Add(ctx context.Context, task runtime.Task) error { + return r.tasks.Add(ctx, task) +} + +// Delete a runtime task +func (r *Runtime) Delete(ctx context.Context, id string) { + r.tasks.Delete(ctx, id) +} + func (r *Runtime) loadTasks(ctx context.Context, ns string) ([]*Task, error) { dir, err := ioutil.ReadDir(filepath.Join(r.state, ns)) if err != nil { diff --git a/vendor/github.com/containerd/containerd/runtime/v1/shim.go b/vendor/github.com/containerd/containerd/runtime/v1/shim.go index 3942968e1..0a2018b4c 100644 --- a/vendor/github.com/containerd/containerd/runtime/v1/shim.go +++ b/vendor/github.com/containerd/containerd/runtime/v1/shim.go @@ -29,10 +29,10 @@ import ( // OpenShimStdoutLog opens the shim log for reading func OpenShimStdoutLog(ctx context.Context, logDirPath string) (io.ReadWriteCloser, error) { - return fifo.OpenFifo(ctx, filepath.Join(logDirPath, "shim.stdout.log"), unix.O_RDWR|unix.O_CREAT|unix.O_NONBLOCK, 0700) + return fifo.OpenFifo(ctx, filepath.Join(logDirPath, "shim.stdout.log"), unix.O_RDWR|unix.O_CREAT, 0700) } // OpenShimStderrLog opens the shim log func OpenShimStderrLog(ctx context.Context, logDirPath string) (io.ReadWriteCloser, error) { - return fifo.OpenFifo(ctx, filepath.Join(logDirPath, "shim.stderr.log"), unix.O_RDWR|unix.O_CREAT|unix.O_NONBLOCK, 0700) + return fifo.OpenFifo(ctx, filepath.Join(logDirPath, "shim.stderr.log"), unix.O_RDWR|unix.O_CREAT, 0700) } diff --git a/vendor/github.com/containerd/containerd/runtime/v1/shim/service.go b/vendor/github.com/containerd/containerd/runtime/v1/shim/service.go index df6d8b64e..701dab435 100644 --- a/vendor/github.com/containerd/containerd/runtime/v1/shim/service.go +++ b/vendor/github.com/containerd/containerd/runtime/v1/shim/service.go @@ -448,6 +448,7 @@ func (s *Service) Checkpoint(ctx context.Context, r *shimapi.CheckpointTaskReque AllowTerminal: options.Terminal, FileLocks: options.FileLocks, EmptyNamespaces: options.EmptyNamespaces, + WorkDir: options.WorkPath, }); err != nil { return nil, errdefs.ToGRPC(err) } @@ -657,5 +658,11 @@ func newInit(ctx context.Context, path, workDir, runtimeRoot, namespace, criu st p.IoGID = int(options.IoGid) p.NoPivotRoot = options.NoPivotRoot p.NoNewKeyring = options.NoNewKeyring + p.CriuWorkPath = options.CriuWorkPath + if p.CriuWorkPath == "" { + // if criu work path not set, use container WorkDir + p.CriuWorkPath = p.WorkDir + } + return p, nil } diff --git a/vendor/github.com/containerd/containerd/runtime/v2/README.md b/vendor/github.com/containerd/containerd/runtime/v2/README.md index 481861643..1aeb20b4d 100644 --- a/vendor/github.com/containerd/containerd/runtime/v2/README.md +++ b/vendor/github.com/containerd/containerd/runtime/v2/README.md @@ -36,9 +36,9 @@ This command will launch new shims. The start command MUST accept the following flags: * `-namespace` the namespace for the container -* `-id` the id of the container * `-address` the address of the containerd's main socket * `-publish-binary` the binary path to publish events back to containerd +* `-id` the id of the container The start command, as well as all binary calls to the shim, has the bundle for the container set as the `cwd`. @@ -58,11 +58,12 @@ If a bundle is still on disk but containerd cannot connect to a shim, the delete The delete command MUST accept the following flags: * `-namespace` the namespace for the container -* `-id` the id of the container * `-address` the address of the containerd's main socket * `-publish-binary` the binary path to publish events back to containerd +* `-id` the id of the container +* `-bundle` the path to the bundle to delete. On non-Windows platforms this will match `cwd` -The delete command will be executed in the container's bundle as its `cwd`. +The delete command will be executed in the container's bundle as its `cwd` except for on the Windows platform. ### Host Level Shim Configuration @@ -148,8 +149,27 @@ Filesystems are provided by the containerd snapshotters. ### Events -The shim MUST publish a `runtime.TaskExitEventTopic` when the container exits. -If the shim collects Out of Memory events, it SHOULD also publish a `runtime.TaskOOMEventTopic`. +The Runtime v2 supports an async event model. In order for the an upstream caller (such as Docker) to get these events in the correct order a Runtime v2 shim MUST implement the following events where `Compliance=MUST`. This avoids race conditions between the shim and shim client where for example a call to `Start` can signal a `TaskExitEventTopic` before even returning the results from the `Start` call. With these guarantees of a Runtime v2 shim a call to `Start` is required to have published the async event `TaskStartEventTopic` before the shim can publish the `TaskExitEventTopic`. + +#### Tasks + +| Topic | Compliance | Description | +| ----- | ---------- | ----------- | +| `runtime.TaskCreateEventTopic` | MUST | When a task is successfully created | +| `runtime.TaskStartEventTopic` | MUST (follow `TaskCreateEventTopic`) | When a task is successfully started | +| `runtime.TaskExitEventTopic` | MUST (follow `TaskStartEventTopic`) | When a task exits expected or unexpected | +| `runtime.TaskDeleteEventTopic` | MUST (follow `TaskExitEventTopic` or `TaskCreateEventTopic` if never started) | When a task is removed from a shim | +| `runtime.TaskPausedEventTopic` | SHOULD | When a task is successfully paused | +| `runtime.TaskResumedEventTopic` | SHOULD (follow `TaskPausedEventTopic`) | When a task is successfully resumed | +| `runtime.TaskCheckpointedEventTopic` | SHOULD | When a task is checkpointed | +| `runtime.TaskOOMEventTopic` | SHOULD | If the shim collects Out of Memory events | + +#### Execs + +| Topic | Compliance | Description | +| ----- | ---------- | ----------- | +| `runtime.TaskExecAddedEventTopic` | MUST (follow `TaskCreateEventTopic` ) | When an exec is successfully added | +| `runtime.TaskExecStartedEventTopic` | MUST (follow `TaskExecStartedEventTopic`) | When an exec is successfully started | ### Other diff --git a/vendor/github.com/containerd/containerd/runtime/v2/binary.go b/vendor/github.com/containerd/containerd/runtime/v2/binary.go index 41de0d3e0..8cad501e6 100644 --- a/vendor/github.com/containerd/containerd/runtime/v2/binary.go +++ b/vendor/github.com/containerd/containerd/runtime/v2/binary.go @@ -24,7 +24,6 @@ import ( gruntime "runtime" "strings" - eventstypes "github.com/containerd/containerd/api/events" "github.com/containerd/containerd/events/exchange" "github.com/containerd/containerd/log" "github.com/containerd/containerd/runtime" @@ -152,13 +151,6 @@ func (b *binary) Delete(ctx context.Context) (*runtime.Exit, error) { // remove self from the runtime task list // this seems dirty but it cleans up the API across runtimes, tasks, and the service b.rtTasks.Delete(ctx, b.bundle.ID) - // shim will send the exit event - b.events.Publish(ctx, runtime.TaskDeleteEventTopic, &eventstypes.TaskDelete{ - ContainerID: b.bundle.ID, - ExitStatus: response.ExitStatus, - ExitedAt: response.ExitedAt, - Pid: response.Pid, - }) return &runtime.Exit{ Status: response.ExitStatus, Timestamp: response.ExitedAt, diff --git a/vendor/github.com/containerd/containerd/runtime/v2/bundle.go b/vendor/github.com/containerd/containerd/runtime/v2/bundle.go index 85eeee444..71394102c 100644 --- a/vendor/github.com/containerd/containerd/runtime/v2/bundle.go +++ b/vendor/github.com/containerd/containerd/runtime/v2/bundle.go @@ -18,6 +18,7 @@ package v2 import ( "context" + "fmt" "io/ioutil" "os" "path/filepath" @@ -114,20 +115,30 @@ type Bundle struct { // Delete a bundle atomically func (b *Bundle) Delete() error { work, werr := os.Readlink(filepath.Join(b.Path, "work")) - err := os.RemoveAll(b.Path) + err := atomicDelete(b.Path) if err == nil { if werr == nil { - return os.RemoveAll(work) + return atomicDelete(work) } return nil } // error removing the bundle path; still attempt removing work dir var err2 error if werr == nil { - err2 = os.RemoveAll(work) + err2 = atomicDelete(work) if err2 == nil { return err } } return errors.Wrapf(err, "failed to remove both bundle and workdir locations: %v", err2) } + +// atomicDelete renames the path to a hidden file before removal +func atomicDelete(path string) error { + // create a hidden dir for an atomic removal + atomicPath := filepath.Join(filepath.Dir(path), fmt.Sprintf(".%s", filepath.Base(path))) + if err := os.Rename(path, atomicPath); err != nil { + return err + } + return os.RemoveAll(atomicPath) +} diff --git a/vendor/github.com/containerd/containerd/runtime/v2/manager.go b/vendor/github.com/containerd/containerd/runtime/v2/manager.go index a04082dfa..fe4b40dec 100644 --- a/vendor/github.com/containerd/containerd/runtime/v2/manager.go +++ b/vendor/github.com/containerd/containerd/runtime/v2/manager.go @@ -130,6 +130,16 @@ func (m *TaskManager) Get(ctx context.Context, id string) (runtime.Task, error) return m.tasks.Get(ctx, id) } +// Add a runtime task +func (m *TaskManager) Add(ctx context.Context, task runtime.Task) error { + return m.tasks.Add(ctx, task) +} + +// Delete a runtime task +func (m *TaskManager) Delete(ctx context.Context, id string) { + m.tasks.Delete(ctx, id) +} + // Tasks lists all tasks func (m *TaskManager) Tasks(ctx context.Context, all bool) ([]runtime.Task, error) { return m.tasks.GetAll(ctx, all) @@ -145,6 +155,10 @@ func (m *TaskManager) loadExistingTasks(ctx context.Context) error { continue } ns := nsd.Name() + // skip hidden directories + if len(ns) > 0 && ns[0] == '.' { + continue + } log.G(ctx).WithField("namespace", ns).Debug("loading tasks in namespace") if err := m.loadTasks(namespaces.WithNamespace(ctx, ns)); err != nil { log.G(ctx).WithField("namespace", ns).WithError(err).Error("loading tasks in namespace") diff --git a/vendor/github.com/containerd/containerd/runtime/v2/process.go b/vendor/github.com/containerd/containerd/runtime/v2/process.go index dbff8fd2c..b41935f6a 100644 --- a/vendor/github.com/containerd/containerd/runtime/v2/process.go +++ b/vendor/github.com/containerd/containerd/runtime/v2/process.go @@ -19,7 +19,6 @@ package v2 import ( "context" - eventstypes "github.com/containerd/containerd/api/events" tasktypes "github.com/containerd/containerd/api/types/task" "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/runtime" @@ -114,18 +113,13 @@ func (p *process) CloseIO(ctx context.Context) error { // Start the process func (p *process) Start(ctx context.Context) error { - response, err := p.shim.task.Start(ctx, &task.StartRequest{ + _, err := p.shim.task.Start(ctx, &task.StartRequest{ ID: p.shim.ID(), ExecID: p.id, }) if err != nil { return errdefs.FromGRPC(err) } - p.shim.events.Publish(ctx, runtime.TaskExecStartedEventTopic, &eventstypes.TaskExecStarted{ - ContainerID: p.shim.ID(), - Pid: response.Pid, - ExecID: p.id, - }) return nil } diff --git a/vendor/github.com/containerd/containerd/runtime/v2/runc/options/oci.pb.go b/vendor/github.com/containerd/containerd/runtime/v2/runc/options/oci.pb.go index 67a85d9dd..ebfc3b8ac 100644 --- a/vendor/github.com/containerd/containerd/runtime/v2/runc/options/oci.pb.go +++ b/vendor/github.com/containerd/containerd/runtime/v2/runc/options/oci.pb.go @@ -55,6 +55,10 @@ type Options struct { CriuPath string `protobuf:"bytes,8,opt,name=criu_path,json=criuPath,proto3" json:"criu_path,omitempty"` // enable systemd cgroups SystemdCgroup bool `protobuf:"varint,9,opt,name=systemd_cgroup,json=systemdCgroup,proto3" json:"systemd_cgroup,omitempty"` + // criu image path + CriuImagePath string `protobuf:"bytes,10,opt,name=criu_image_path,json=criuImagePath,proto3" json:"criu_image_path,omitempty"` + // criu work path + CriuWorkPath string `protobuf:"bytes,11,opt,name=criu_work_path,json=criuWorkPath,proto3" json:"criu_work_path,omitempty"` } func (m *Options) Reset() { *m = Options{} } @@ -76,6 +80,10 @@ type CheckpointOptions struct { EmptyNamespaces []string `protobuf:"bytes,6,rep,name=empty_namespaces,json=emptyNamespaces" json:"empty_namespaces,omitempty"` // set the cgroups mode, soft, full, strict CgroupsMode string `protobuf:"bytes,7,opt,name=cgroups_mode,json=cgroupsMode,proto3" json:"cgroups_mode,omitempty"` + // checkpoint image path + ImagePath string `protobuf:"bytes,8,opt,name=image_path,json=imagePath,proto3" json:"image_path,omitempty"` + // checkpoint work path + WorkPath string `protobuf:"bytes,9,opt,name=work_path,json=workPath,proto3" json:"work_path,omitempty"` } func (m *CheckpointOptions) Reset() { *m = CheckpointOptions{} } @@ -175,6 +183,18 @@ func (m *Options) MarshalTo(dAtA []byte) (int, error) { } i++ } + if len(m.CriuImagePath) > 0 { + dAtA[i] = 0x52 + i++ + i = encodeVarintOci(dAtA, i, uint64(len(m.CriuImagePath))) + i += copy(dAtA[i:], m.CriuImagePath) + } + if len(m.CriuWorkPath) > 0 { + dAtA[i] = 0x5a + i++ + i = encodeVarintOci(dAtA, i, uint64(len(m.CriuWorkPath))) + i += copy(dAtA[i:], m.CriuWorkPath) + } return i, nil } @@ -264,6 +284,18 @@ func (m *CheckpointOptions) MarshalTo(dAtA []byte) (int, error) { i = encodeVarintOci(dAtA, i, uint64(len(m.CgroupsMode))) i += copy(dAtA[i:], m.CgroupsMode) } + if len(m.ImagePath) > 0 { + dAtA[i] = 0x42 + i++ + i = encodeVarintOci(dAtA, i, uint64(len(m.ImagePath))) + i += copy(dAtA[i:], m.ImagePath) + } + if len(m.WorkPath) > 0 { + dAtA[i] = 0x4a + i++ + i = encodeVarintOci(dAtA, i, uint64(len(m.WorkPath))) + i += copy(dAtA[i:], m.WorkPath) + } return i, nil } @@ -334,6 +366,14 @@ func (m *Options) Size() (n int) { if m.SystemdCgroup { n += 2 } + l = len(m.CriuImagePath) + if l > 0 { + n += 1 + l + sovOci(uint64(l)) + } + l = len(m.CriuWorkPath) + if l > 0 { + n += 1 + l + sovOci(uint64(l)) + } return n } @@ -365,6 +405,14 @@ func (m *CheckpointOptions) Size() (n int) { if l > 0 { n += 1 + l + sovOci(uint64(l)) } + l = len(m.ImagePath) + if l > 0 { + n += 1 + l + sovOci(uint64(l)) + } + l = len(m.WorkPath) + if l > 0 { + n += 1 + l + sovOci(uint64(l)) + } return n } @@ -405,6 +453,8 @@ func (this *Options) String() string { `Root:` + fmt.Sprintf("%v", this.Root) + `,`, `CriuPath:` + fmt.Sprintf("%v", this.CriuPath) + `,`, `SystemdCgroup:` + fmt.Sprintf("%v", this.SystemdCgroup) + `,`, + `CriuImagePath:` + fmt.Sprintf("%v", this.CriuImagePath) + `,`, + `CriuWorkPath:` + fmt.Sprintf("%v", this.CriuWorkPath) + `,`, `}`, }, "") return s @@ -421,6 +471,8 @@ func (this *CheckpointOptions) String() string { `FileLocks:` + fmt.Sprintf("%v", this.FileLocks) + `,`, `EmptyNamespaces:` + fmt.Sprintf("%v", this.EmptyNamespaces) + `,`, `CgroupsMode:` + fmt.Sprintf("%v", this.CgroupsMode) + `,`, + `ImagePath:` + fmt.Sprintf("%v", this.ImagePath) + `,`, + `WorkPath:` + fmt.Sprintf("%v", this.WorkPath) + `,`, `}`, }, "") return s @@ -686,6 +738,64 @@ func (m *Options) Unmarshal(dAtA []byte) error { } } m.SystemdCgroup = bool(v != 0) + case 10: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CriuImagePath", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOci + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthOci + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.CriuImagePath = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 11: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CriuWorkPath", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOci + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthOci + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.CriuWorkPath = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipOci(dAtA[iNdEx:]) @@ -894,6 +1004,64 @@ func (m *CheckpointOptions) Unmarshal(dAtA []byte) error { } m.CgroupsMode = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ImagePath", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOci + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthOci + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ImagePath = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 9: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field WorkPath", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOci + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthOci + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.WorkPath = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipOci(dAtA[iNdEx:]) @@ -1104,39 +1272,42 @@ func init() { } var fileDescriptorOci = []byte{ - // 529 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x92, 0xcd, 0x6e, 0xd3, 0x4c, - 0x14, 0x86, 0xeb, 0xfe, 0x38, 0xf6, 0xf4, 0xe7, 0xfb, 0x18, 0xa8, 0x64, 0x8a, 0x70, 0x43, 0x00, - 0x29, 0x6c, 0x12, 0x51, 0xc4, 0x8a, 0x0d, 0x6a, 0x8b, 0x50, 0x05, 0x94, 0xca, 0x50, 0x09, 0x75, - 0x33, 0x72, 0xc6, 0x07, 0xe7, 0x28, 0xf1, 0x1c, 0xcb, 0x33, 0x4e, 0x9d, 0x1d, 0xf7, 0xc1, 0x0d, - 0x75, 0xc9, 0x92, 0x15, 0xa2, 0xb9, 0x11, 0x90, 0xc7, 0x4e, 0x61, 0xcd, 0xca, 0xef, 0x3c, 0xef, - 0xf1, 0x68, 0xe6, 0xd1, 0xb0, 0xc3, 0x14, 0xcd, 0xb8, 0x1c, 0x0d, 0x24, 0x65, 0x43, 0x49, 0xca, - 0xc4, 0xa8, 0xa0, 0x48, 0xfe, 0x8e, 0x45, 0xa9, 0x0c, 0x66, 0x30, 0x9c, 0x1d, 0xd4, 0x51, 0x0e, - 0x29, 0x37, 0x48, 0x4a, 0x0f, 0x49, 0xe2, 0x20, 0x2f, 0xc8, 0x10, 0xe7, 0x7f, 0xa6, 0x07, 0xf5, - 0xc8, 0x60, 0xf6, 0x74, 0xef, 0x4e, 0x4a, 0x29, 0xd9, 0x7a, 0x58, 0xa7, 0x66, 0xb2, 0xf7, 0x75, - 0x95, 0x75, 0xde, 0x37, 0xff, 0xf3, 0x1e, 0xdb, 0x56, 0x24, 0x72, 0x9c, 0x91, 0x11, 0x05, 0x91, - 0x09, 0x9c, 0xae, 0xd3, 0xf7, 0xa2, 0x4d, 0x45, 0x67, 0x35, 0x8b, 0x88, 0x0c, 0x7f, 0xc4, 0x76, - 0x14, 0x09, 0x05, 0x97, 0x62, 0x02, 0xf3, 0x02, 0x55, 0x1a, 0xac, 0xda, 0xa1, 0x2d, 0x45, 0xa7, - 0x70, 0xf9, 0xa6, 0x61, 0x7c, 0x9f, 0x6d, 0xea, 0x31, 0x66, 0x42, 0xa6, 0x05, 0x95, 0x79, 0xb0, - 0xd6, 0x75, 0xfa, 0x7e, 0xc4, 0x6a, 0x74, 0x64, 0x09, 0xdf, 0x65, 0x2e, 0x92, 0x28, 0x31, 0x09, - 0xd6, 0xbb, 0x4e, 0x7f, 0x3b, 0xda, 0x40, 0x3a, 0xc7, 0xa4, 0xc5, 0x29, 0x26, 0xc1, 0xc6, 0x12, - 0xbf, 0xc6, 0xa4, 0xde, 0x6e, 0x84, 0x2a, 0x2e, 0xe6, 0x42, 0xc5, 0x19, 0x04, 0x6e, 0xb3, 0x5d, - 0x83, 0x4e, 0xe3, 0x0c, 0x38, 0x67, 0xeb, 0xf6, 0xc0, 0x1d, 0xdb, 0xd8, 0xcc, 0xef, 0x31, 0x5f, - 0x16, 0x58, 0x8a, 0x3c, 0x36, 0xe3, 0xc0, 0xb3, 0x85, 0x57, 0x83, 0xb3, 0xd8, 0x8c, 0xf9, 0x63, - 0xb6, 0xa3, 0xe7, 0xda, 0x40, 0x96, 0x2c, 0xcf, 0xe8, 0xdb, 0x6b, 0x6c, 0xb7, 0xb4, 0x39, 0x66, - 0xef, 0x97, 0xc3, 0x6e, 0x1d, 0x8d, 0x41, 0x4e, 0x72, 0x42, 0x65, 0x96, 0x9e, 0x38, 0x5b, 0x87, - 0x0a, 0x97, 0x7a, 0x6c, 0xe6, 0x77, 0x99, 0x47, 0x39, 0x28, 0x61, 0x64, 0xde, 0x1a, 0xe9, 0xd4, - 0xeb, 0x8f, 0x32, 0xe7, 0x07, 0x6c, 0x17, 0x2a, 0x03, 0x85, 0x8a, 0xa7, 0xa2, 0x54, 0x58, 0x09, - 0x4d, 0x72, 0x02, 0x46, 0x5b, 0x2d, 0x5e, 0x74, 0x7b, 0x59, 0x9e, 0x2b, 0xac, 0x3e, 0x34, 0x15, - 0xdf, 0x63, 0x9e, 0x81, 0x22, 0x43, 0x15, 0x4f, 0xad, 0x21, 0x2f, 0xba, 0x59, 0xf3, 0xfb, 0x8c, - 0x7d, 0xc6, 0x29, 0x88, 0x29, 0xc9, 0x89, 0xb6, 0xa2, 0xbc, 0xc8, 0xaf, 0xc9, 0xdb, 0x1a, 0xf0, - 0x27, 0xec, 0x7f, 0xc8, 0x72, 0xd3, 0xb8, 0xd2, 0x79, 0x2c, 0x41, 0x07, 0x6e, 0x77, 0xad, 0xef, - 0x47, 0xff, 0x59, 0x7e, 0x7a, 0x83, 0xf9, 0x03, 0xb6, 0xd5, 0xdc, 0x5e, 0x8b, 0x8c, 0x12, 0x68, - 0xf5, 0x6d, 0xb6, 0xec, 0x1d, 0x25, 0xd0, 0x7b, 0xce, 0x76, 0xce, 0x0a, 0x92, 0xa0, 0xf5, 0x31, - 0x98, 0x18, 0xa7, 0x9a, 0x3f, 0x64, 0x1d, 0xa8, 0x40, 0x0a, 0x4c, 0xac, 0x00, 0xff, 0x90, 0x2d, - 0x7e, 0xec, 0xbb, 0xaf, 0x2a, 0x90, 0x27, 0xc7, 0x91, 0x5b, 0x57, 0x27, 0xc9, 0xe1, 0xc5, 0xd5, - 0x75, 0xb8, 0xf2, 0xfd, 0x3a, 0x5c, 0xf9, 0xb2, 0x08, 0x9d, 0xab, 0x45, 0xe8, 0x7c, 0x5b, 0x84, - 0xce, 0xcf, 0x45, 0xe8, 0x5c, 0xbc, 0xfc, 0xd7, 0xe7, 0xfd, 0xa2, 0xfd, 0x7e, 0x5a, 0x19, 0xb9, - 0xf6, 0xed, 0x3e, 0xfb, 0x1d, 0x00, 0x00, 0xff, 0xff, 0x78, 0xf4, 0x16, 0x4e, 0x2b, 0x03, 0x00, - 0x00, + // 587 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x93, 0xcf, 0x6e, 0xd3, 0x40, + 0x10, 0x87, 0xeb, 0xfe, 0x49, 0xec, 0x4d, 0x93, 0xc2, 0x42, 0x25, 0xd3, 0x8a, 0x34, 0x94, 0x82, + 0xc2, 0x25, 0x11, 0x45, 0x9c, 0xb8, 0xa0, 0xb6, 0x08, 0x55, 0x40, 0xa9, 0x0c, 0x15, 0xa8, 0x97, + 0x95, 0xbb, 0x1e, 0x9c, 0x51, 0xe2, 0x1d, 0xcb, 0xbb, 0x69, 0xd2, 0x1b, 0xef, 0xc5, 0x0b, 0xf4, + 0xc8, 0x91, 0x13, 0xa2, 0xb9, 0xf1, 0x16, 0x68, 0xd7, 0x4e, 0xdb, 0x33, 0x27, 0xcf, 0x7e, 0xf3, + 0xf3, 0x78, 0xfd, 0xad, 0x96, 0xed, 0xa5, 0x68, 0x06, 0xe3, 0xb3, 0x9e, 0xa4, 0xac, 0x2f, 0x49, + 0x99, 0x18, 0x15, 0x14, 0xc9, 0xed, 0xb2, 0x18, 0x2b, 0x83, 0x19, 0xf4, 0xcf, 0x77, 0x6d, 0x29, + 0xfb, 0x94, 0x1b, 0x24, 0xa5, 0xfb, 0x24, 0xb1, 0x97, 0x17, 0x64, 0x88, 0xf3, 0x9b, 0x74, 0xcf, + 0x46, 0x7a, 0xe7, 0xcf, 0x37, 0xee, 0xa7, 0x94, 0x92, 0x6b, 0xf7, 0x6d, 0x55, 0x26, 0xb7, 0xff, + 0x2e, 0xb2, 0xfa, 0xc7, 0xf2, 0x7d, 0xbe, 0xcd, 0x9a, 0x8a, 0x44, 0x8e, 0xe7, 0x64, 0x44, 0x41, + 0x64, 0x42, 0xaf, 0xe3, 0x75, 0xfd, 0xa8, 0xa1, 0xe8, 0xd8, 0xb2, 0x88, 0xc8, 0xf0, 0x1d, 0xd6, + 0x52, 0x24, 0x14, 0x4c, 0xc4, 0x10, 0x2e, 0x0a, 0x54, 0x69, 0xb8, 0xe8, 0x42, 0xab, 0x8a, 0x8e, + 0x60, 0xf2, 0xae, 0x64, 0x7c, 0x8b, 0x35, 0xf4, 0x00, 0x33, 0x21, 0xd3, 0x82, 0xc6, 0x79, 0xb8, + 0xd4, 0xf1, 0xba, 0x41, 0xc4, 0x2c, 0xda, 0x77, 0x84, 0xaf, 0xb3, 0x1a, 0x92, 0x18, 0x63, 0x12, + 0x2e, 0x77, 0xbc, 0x6e, 0x33, 0x5a, 0x41, 0x3a, 0xc1, 0xa4, 0xc2, 0x29, 0x26, 0xe1, 0xca, 0x1c, + 0xbf, 0xc5, 0xc4, 0x8e, 0x3b, 0x43, 0x15, 0x17, 0x17, 0x42, 0xc5, 0x19, 0x84, 0xb5, 0x72, 0x5c, + 0x89, 0x8e, 0xe2, 0x0c, 0x38, 0x67, 0xcb, 0x6e, 0xc3, 0x75, 0xd7, 0x71, 0x35, 0xdf, 0x64, 0x81, + 0x2c, 0x70, 0x2c, 0xf2, 0xd8, 0x0c, 0x42, 0xdf, 0x35, 0x7c, 0x0b, 0x8e, 0x63, 0x33, 0xe0, 0x4f, + 0x58, 0x4b, 0x5f, 0x68, 0x03, 0x59, 0x32, 0xdf, 0x63, 0xe0, 0x7e, 0xa3, 0x59, 0xd1, 0x6a, 0x9b, + 0x4f, 0xd9, 0x9a, 0x9b, 0x81, 0x59, 0x9c, 0x42, 0x39, 0x89, 0xb9, 0x49, 0x4d, 0x8b, 0x0f, 0x2d, + 0x75, 0xe3, 0x76, 0x58, 0xcb, 0xe5, 0x26, 0x54, 0x0c, 0xcb, 0x58, 0xc3, 0xc5, 0x56, 0x2d, 0xfd, + 0x42, 0xc5, 0xd0, 0xa6, 0xb6, 0x7f, 0x2c, 0xb2, 0xbb, 0xfb, 0x03, 0x90, 0xc3, 0x9c, 0x50, 0x99, + 0xb9, 0x75, 0xce, 0x96, 0x61, 0x8a, 0x73, 0xd9, 0xae, 0xe6, 0x0f, 0x98, 0x4f, 0x39, 0x28, 0x61, + 0x64, 0x5e, 0xf9, 0xad, 0xdb, 0xf5, 0x67, 0x99, 0xf3, 0x5d, 0xb6, 0x0e, 0x53, 0x03, 0x85, 0x8a, + 0x47, 0x62, 0xac, 0x70, 0x2a, 0x34, 0xc9, 0x21, 0x18, 0xed, 0x24, 0xfb, 0xd1, 0xbd, 0x79, 0xf3, + 0x44, 0xe1, 0xf4, 0x53, 0xd9, 0xe2, 0x1b, 0xcc, 0x37, 0x50, 0x64, 0xa8, 0xe2, 0x91, 0xf3, 0xed, + 0x47, 0xd7, 0x6b, 0xfe, 0x90, 0xb1, 0x6f, 0x38, 0x02, 0x31, 0x22, 0x39, 0xd4, 0x4e, 0xbb, 0x1f, + 0x05, 0x96, 0xbc, 0xb7, 0x80, 0x3f, 0x63, 0x77, 0x20, 0xcb, 0x4d, 0x69, 0x5e, 0xe7, 0xb1, 0x04, + 0x1d, 0xd6, 0x3a, 0x4b, 0xdd, 0x20, 0x5a, 0x73, 0xfc, 0xe8, 0x1a, 0xf3, 0x47, 0x6c, 0xb5, 0x74, + 0xa9, 0x45, 0x46, 0x09, 0x54, 0x87, 0xd1, 0xa8, 0xd8, 0x07, 0x4a, 0xc0, 0x7e, 0xec, 0x96, 0xca, + 0xf2, 0x50, 0x02, 0xbc, 0xd6, 0xb8, 0xc9, 0x82, 0x1b, 0x83, 0x41, 0x79, 0x64, 0x93, 0xb9, 0xbd, + 0x97, 0xac, 0x75, 0x5c, 0x90, 0x04, 0xad, 0x0f, 0xc0, 0xc4, 0x38, 0xd2, 0xfc, 0x31, 0xab, 0xc3, + 0x14, 0xa4, 0xc0, 0xc4, 0xc9, 0x0b, 0xf6, 0xd8, 0xec, 0xf7, 0x56, 0xed, 0xcd, 0x14, 0xe4, 0xe1, + 0x41, 0x54, 0xb3, 0xad, 0xc3, 0x64, 0xef, 0xf4, 0xf2, 0xaa, 0xbd, 0xf0, 0xeb, 0xaa, 0xbd, 0xf0, + 0x7d, 0xd6, 0xf6, 0x2e, 0x67, 0x6d, 0xef, 0xe7, 0xac, 0xed, 0xfd, 0x99, 0xb5, 0xbd, 0xd3, 0xd7, + 0xff, 0x7b, 0xd1, 0x5e, 0x55, 0xcf, 0xaf, 0x0b, 0x67, 0x35, 0x77, 0x8b, 0x5e, 0xfc, 0x0b, 0x00, + 0x00, 0xff, 0xff, 0x90, 0x50, 0x79, 0xf2, 0xb5, 0x03, 0x00, 0x00, } diff --git a/vendor/github.com/containerd/containerd/runtime/v2/runc/options/oci.proto b/vendor/github.com/containerd/containerd/runtime/v2/runc/options/oci.proto index e3ee8a81e..6b4bcf462 100644 --- a/vendor/github.com/containerd/containerd/runtime/v2/runc/options/oci.proto +++ b/vendor/github.com/containerd/containerd/runtime/v2/runc/options/oci.proto @@ -25,6 +25,10 @@ message Options { string criu_path = 8; // enable systemd cgroups bool systemd_cgroup = 9; + // criu image path + string criu_image_path = 10; + // criu work path + string criu_work_path = 11; } message CheckpointOptions { @@ -42,6 +46,10 @@ message CheckpointOptions { repeated string empty_namespaces = 6; // set the cgroups mode, soft, full, strict string cgroups_mode = 7; + // checkpoint image path + string image_path = 8; + // checkpoint work path + string work_path = 9; } message ProcessDetails { diff --git a/vendor/github.com/containerd/containerd/runtime/v2/runhcs/options/runhcs.pb.go b/vendor/github.com/containerd/containerd/runtime/v2/runhcs/options/runhcs.pb.go index 0523aafd8..cba419cfb 100644 --- a/vendor/github.com/containerd/containerd/runtime/v2/runhcs/options/runhcs.pb.go +++ b/vendor/github.com/containerd/containerd/runtime/v2/runhcs/options/runhcs.pb.go @@ -39,15 +39,18 @@ type Options_DebugType int32 const ( Options_NPIPE Options_DebugType = 0 Options_FILE Options_DebugType = 1 + Options_ETW Options_DebugType = 2 ) var Options_DebugType_name = map[int32]string{ 0: "NPIPE", 1: "FILE", + 2: "ETW", } var Options_DebugType_value = map[string]int32{ "NPIPE": 0, "FILE": 1, + "ETW": 2, } func (x Options_DebugType) String() string { @@ -55,6 +58,29 @@ func (x Options_DebugType) String() string { } func (Options_DebugType) EnumDescriptor() ([]byte, []int) { return fileDescriptorRunhcs, []int{0, 0} } +type Options_SandboxIsolation int32 + +const ( + Options_PROCESS Options_SandboxIsolation = 0 + Options_HYPERVISOR Options_SandboxIsolation = 1 +) + +var Options_SandboxIsolation_name = map[int32]string{ + 0: "PROCESS", + 1: "HYPERVISOR", +} +var Options_SandboxIsolation_value = map[string]int32{ + "PROCESS": 0, + "HYPERVISOR": 1, +} + +func (x Options_SandboxIsolation) String() string { + return proto.EnumName(Options_SandboxIsolation_name, int32(x)) +} +func (Options_SandboxIsolation) EnumDescriptor() ([]byte, []int) { + return fileDescriptorRunhcs, []int{0, 1} +} + type Options struct { // enable debug tracing Debug bool `protobuf:"varint,1,opt,name=debug,proto3" json:"debug,omitempty"` @@ -62,6 +88,17 @@ type Options struct { DebugType Options_DebugType `protobuf:"varint,2,opt,name=debug_type,json=debugType,proto3,enum=containerd.runhcs.v1.Options_DebugType" json:"debug_type,omitempty"` // registry key root for storage of the runhcs container state RegistryRoot string `protobuf:"bytes,3,opt,name=registry_root,json=registryRoot,proto3" json:"registry_root,omitempty"` + // sandbox_image is the image to use for the sandbox that matches the + // sandbox_platform. + SandboxImage string `protobuf:"bytes,4,opt,name=sandbox_image,json=sandboxImage,proto3" json:"sandbox_image,omitempty"` + // sandbox_platform is a CRI setting that specifies the platform + // architecture for all sandbox's in this runtime. Values are + // 'windows/amd64' and 'linux/amd64'. + SandboxPlatform string `protobuf:"bytes,5,opt,name=sandbox_platform,json=sandboxPlatform,proto3" json:"sandbox_platform,omitempty"` + // sandbox_isolation is a CRI setting that specifies the isolation level of + // the sandbox. For Windows runtime PROCESS and HYPERVISOR are valid. For + // LCOW only HYPERVISOR is valid and default if omitted. + SandboxIsolation Options_SandboxIsolation `protobuf:"varint,6,opt,name=sandbox_isolation,json=sandboxIsolation,proto3,enum=containerd.runhcs.v1.Options_SandboxIsolation" json:"sandbox_isolation,omitempty"` } func (m *Options) Reset() { *m = Options{} } @@ -71,6 +108,7 @@ func (*Options) Descriptor() ([]byte, []int) { return fileDescriptorRunhcs, []in func init() { proto.RegisterType((*Options)(nil), "containerd.runhcs.v1.Options") proto.RegisterEnum("containerd.runhcs.v1.Options_DebugType", Options_DebugType_name, Options_DebugType_value) + proto.RegisterEnum("containerd.runhcs.v1.Options_SandboxIsolation", Options_SandboxIsolation_name, Options_SandboxIsolation_value) } func (m *Options) Marshal() (dAtA []byte, err error) { size := m.Size() @@ -108,6 +146,23 @@ func (m *Options) MarshalTo(dAtA []byte) (int, error) { i = encodeVarintRunhcs(dAtA, i, uint64(len(m.RegistryRoot))) i += copy(dAtA[i:], m.RegistryRoot) } + if len(m.SandboxImage) > 0 { + dAtA[i] = 0x22 + i++ + i = encodeVarintRunhcs(dAtA, i, uint64(len(m.SandboxImage))) + i += copy(dAtA[i:], m.SandboxImage) + } + if len(m.SandboxPlatform) > 0 { + dAtA[i] = 0x2a + i++ + i = encodeVarintRunhcs(dAtA, i, uint64(len(m.SandboxPlatform))) + i += copy(dAtA[i:], m.SandboxPlatform) + } + if m.SandboxIsolation != 0 { + dAtA[i] = 0x30 + i++ + i = encodeVarintRunhcs(dAtA, i, uint64(m.SandboxIsolation)) + } return i, nil } @@ -133,6 +188,17 @@ func (m *Options) Size() (n int) { if l > 0 { n += 1 + l + sovRunhcs(uint64(l)) } + l = len(m.SandboxImage) + if l > 0 { + n += 1 + l + sovRunhcs(uint64(l)) + } + l = len(m.SandboxPlatform) + if l > 0 { + n += 1 + l + sovRunhcs(uint64(l)) + } + if m.SandboxIsolation != 0 { + n += 1 + sovRunhcs(uint64(m.SandboxIsolation)) + } return n } @@ -157,6 +223,9 @@ func (this *Options) String() string { `Debug:` + fmt.Sprintf("%v", this.Debug) + `,`, `DebugType:` + fmt.Sprintf("%v", this.DebugType) + `,`, `RegistryRoot:` + fmt.Sprintf("%v", this.RegistryRoot) + `,`, + `SandboxImage:` + fmt.Sprintf("%v", this.SandboxImage) + `,`, + `SandboxPlatform:` + fmt.Sprintf("%v", this.SandboxPlatform) + `,`, + `SandboxIsolation:` + fmt.Sprintf("%v", this.SandboxIsolation) + `,`, `}`, }, "") return s @@ -266,6 +335,83 @@ func (m *Options) Unmarshal(dAtA []byte) error { } m.RegistryRoot = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SandboxImage", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRunhcs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthRunhcs + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SandboxImage = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SandboxPlatform", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRunhcs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthRunhcs + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SandboxPlatform = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field SandboxIsolation", wireType) + } + m.SandboxIsolation = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRunhcs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.SandboxIsolation |= (Options_SandboxIsolation(b) & 0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipRunhcs(dAtA[iNdEx:]) @@ -397,22 +543,29 @@ func init() { } var fileDescriptorRunhcs = []byte{ - // 265 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x72, 0x4f, 0xcf, 0x2c, 0xc9, - 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xce, 0xcf, 0x2b, 0x49, 0xcc, 0xcc, 0x4b, 0x2d, - 0x4a, 0x41, 0x66, 0x16, 0x95, 0xe6, 0x95, 0x64, 0xe6, 0xa6, 0xea, 0x97, 0x19, 0x81, 0x98, 0x19, - 0xc9, 0xc5, 0xfa, 0xf9, 0x05, 0x25, 0x99, 0xf9, 0x79, 0xc5, 0x50, 0xae, 0x5e, 0x41, 0x51, 0x7e, - 0x49, 0xbe, 0x90, 0x08, 0x42, 0x8b, 0x1e, 0x54, 0xa2, 0xcc, 0x50, 0x4a, 0x24, 0x3d, 0x3f, 0x3d, - 0x1f, 0xac, 0x40, 0x1f, 0xc4, 0x82, 0xa8, 0x55, 0x5a, 0xc7, 0xc8, 0xc5, 0xee, 0x0f, 0x31, 0x44, - 0x48, 0x84, 0x8b, 0x35, 0x25, 0x35, 0xa9, 0x34, 0x5d, 0x82, 0x51, 0x81, 0x51, 0x83, 0x23, 0x08, - 0xc2, 0x11, 0x72, 0xe3, 0xe2, 0x02, 0x33, 0xe2, 0x4b, 0x2a, 0x0b, 0x52, 0x25, 0x98, 0x14, 0x18, - 0x35, 0xf8, 0x8c, 0xd4, 0xf5, 0xb0, 0x59, 0xa1, 0x07, 0x35, 0x48, 0xcf, 0x05, 0xa4, 0x3e, 0xa4, - 0xb2, 0x20, 0x35, 0x88, 0x33, 0x05, 0xc6, 0x14, 0x52, 0xe6, 0xe2, 0x2d, 0x4a, 0x4d, 0xcf, 0x2c, - 0x2e, 0x29, 0xaa, 0x8c, 0x2f, 0xca, 0xcf, 0x2f, 0x91, 0x60, 0x56, 0x60, 0xd4, 0xe0, 0x0c, 0xe2, - 0x81, 0x09, 0x06, 0xe5, 0xe7, 0x97, 0x28, 0x29, 0x70, 0x71, 0xc2, 0x35, 0x0b, 0x71, 0x72, 0xb1, - 0xfa, 0x05, 0x78, 0x06, 0xb8, 0x0a, 0x30, 0x08, 0x71, 0x70, 0xb1, 0xb8, 0x79, 0xfa, 0xb8, 0x0a, - 0x30, 0x3a, 0xc5, 0x9c, 0x78, 0x28, 0xc7, 0x70, 0xe3, 0xa1, 0x1c, 0x43, 0xc3, 0x23, 0x39, 0xc6, - 0x13, 0x8f, 0xe4, 0x18, 0x2f, 0x3c, 0x92, 0x63, 0x7c, 0xf0, 0x48, 0x8e, 0x31, 0xca, 0x89, 0xfc, - 0xf0, 0xb3, 0x86, 0xd2, 0x11, 0x0c, 0x49, 0x6c, 0xe0, 0x70, 0x31, 0x06, 0x04, 0x00, 0x00, 0xff, - 0xff, 0x91, 0x7a, 0xda, 0xa5, 0x8e, 0x01, 0x00, 0x00, + // 383 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x92, 0xcd, 0x6e, 0x9b, 0x40, + 0x14, 0x85, 0x19, 0xff, 0x73, 0xdb, 0xba, 0x74, 0xe4, 0x05, 0xea, 0x02, 0x59, 0xee, 0xa2, 0xf6, + 0x06, 0x54, 0x77, 0xd9, 0x9d, 0x5b, 0xdc, 0x22, 0x55, 0x35, 0x1a, 0xac, 0xb6, 0xf9, 0x91, 0x2c, + 0x30, 0x04, 0x23, 0x19, 0x06, 0xc1, 0xd8, 0x8a, 0x77, 0x79, 0x89, 0xbc, 0x93, 0x97, 0x59, 0x66, + 0x19, 0xf3, 0x24, 0x11, 0x30, 0x38, 0x51, 0x14, 0x65, 0x91, 0x15, 0xe7, 0x1e, 0xbe, 0x7b, 0xee, + 0x5c, 0xcd, 0xc0, 0x4f, 0x3f, 0x60, 0xab, 0x8d, 0xa3, 0x2e, 0x69, 0xa8, 0x2d, 0x69, 0xc4, 0xec, + 0x20, 0xf2, 0x12, 0xf7, 0xb1, 0x4c, 0x36, 0x11, 0x0b, 0x42, 0x4f, 0xdb, 0x8e, 0x73, 0xb9, 0x5a, + 0xa6, 0x1a, 0x8d, 0x59, 0x40, 0xa3, 0x94, 0x97, 0x6a, 0x9c, 0x50, 0x46, 0x71, 0xef, 0xa1, 0x45, + 0xe5, 0x3f, 0xb6, 0x5f, 0x3e, 0xf6, 0x7c, 0xea, 0xd3, 0x02, 0xd0, 0x72, 0x55, 0xb2, 0x83, 0xeb, + 0x3a, 0xb4, 0x67, 0x65, 0x08, 0xee, 0x41, 0xd3, 0xf5, 0x9c, 0x8d, 0x2f, 0xa3, 0x3e, 0x1a, 0x76, + 0x48, 0x59, 0xe0, 0x29, 0x40, 0x21, 0x16, 0x6c, 0x17, 0x7b, 0x72, 0xad, 0x8f, 0x86, 0xdd, 0xf1, + 0x67, 0xf5, 0xb9, 0x11, 0x2a, 0x0f, 0x52, 0x7f, 0xe4, 0xfc, 0x7c, 0x17, 0x7b, 0x44, 0x74, 0x2b, + 0x89, 0x3f, 0xc1, 0xbb, 0xc4, 0xf3, 0x83, 0x94, 0x25, 0xbb, 0x45, 0x42, 0x29, 0x93, 0xeb, 0x7d, + 0x34, 0x14, 0xc9, 0xdb, 0xca, 0x24, 0x94, 0xb2, 0x1c, 0x4a, 0xed, 0xc8, 0x75, 0xe8, 0xe5, 0x22, + 0x08, 0x6d, 0xdf, 0x93, 0x1b, 0x25, 0xc4, 0x4d, 0x23, 0xf7, 0xf0, 0x08, 0xa4, 0x0a, 0x8a, 0xd7, + 0x36, 0xbb, 0xa0, 0x49, 0x28, 0x37, 0x0b, 0xee, 0x3d, 0xf7, 0x4d, 0x6e, 0xe3, 0x33, 0xf8, 0x70, + 0xcc, 0x4b, 0xe9, 0xda, 0xce, 0xcf, 0x27, 0xb7, 0x8a, 0x1d, 0xd4, 0x97, 0x77, 0xb0, 0xf8, 0xc4, + 0xaa, 0x8b, 0x54, 0x33, 0x8f, 0xce, 0x60, 0x04, 0xe2, 0x71, 0x53, 0x2c, 0x42, 0xf3, 0x8f, 0x69, + 0x98, 0xba, 0x24, 0xe0, 0x0e, 0x34, 0xa6, 0xc6, 0x6f, 0x5d, 0x42, 0xb8, 0x0d, 0x75, 0x7d, 0xfe, + 0x4f, 0xaa, 0x0d, 0x34, 0x90, 0x9e, 0x06, 0xe2, 0x37, 0xd0, 0x36, 0xc9, 0xec, 0xbb, 0x6e, 0x59, + 0x92, 0x80, 0xbb, 0x00, 0xbf, 0x4e, 0x4c, 0x9d, 0xfc, 0x35, 0xac, 0x19, 0x91, 0xd0, 0xe4, 0x7c, + 0x7f, 0x50, 0x84, 0xdb, 0x83, 0x22, 0x5c, 0x65, 0x0a, 0xda, 0x67, 0x0a, 0xba, 0xc9, 0x14, 0x74, + 0x97, 0x29, 0xe8, 0x74, 0xf2, 0xfa, 0x67, 0xf2, 0x8d, 0x7f, 0xff, 0x0b, 0x4e, 0xab, 0xb8, 0xfe, + 0xaf, 0xf7, 0x01, 0x00, 0x00, 0xff, 0xff, 0xe8, 0xe0, 0x0a, 0x7a, 0x75, 0x02, 0x00, 0x00, } diff --git a/vendor/github.com/containerd/containerd/runtime/v2/runhcs/options/runhcs.proto b/vendor/github.com/containerd/containerd/runtime/v2/runhcs/options/runhcs.proto index fbb595e42..581925bf0 100644 --- a/vendor/github.com/containerd/containerd/runtime/v2/runhcs/options/runhcs.proto +++ b/vendor/github.com/containerd/containerd/runtime/v2/runhcs/options/runhcs.proto @@ -9,12 +9,35 @@ option go_package = "github.com/containerd/containerd/runtime/v2/runhcs/options; message Options { // enable debug tracing bool debug = 1; + enum DebugType { NPIPE = 0; FILE = 1; + ETW = 2; } + // debug tracing output type DebugType debug_type = 2; + // registry key root for storage of the runhcs container state string registry_root = 3; + + // sandbox_image is the image to use for the sandbox that matches the + // sandbox_platform. + string sandbox_image = 4; + + // sandbox_platform is a CRI setting that specifies the platform + // architecture for all sandbox's in this runtime. Values are + // 'windows/amd64' and 'linux/amd64'. + string sandbox_platform = 5; + + enum SandboxIsolation { + PROCESS = 0; + HYPERVISOR = 1; + } + + // sandbox_isolation is a CRI setting that specifies the isolation level of + // the sandbox. For Windows runtime PROCESS and HYPERVISOR are valid. For + // LCOW only HYPERVISOR is valid and default if omitted. + SandboxIsolation sandbox_isolation = 6; } diff --git a/vendor/github.com/containerd/containerd/runtime/v2/shim.go b/vendor/github.com/containerd/containerd/runtime/v2/shim.go index 982d1bb34..94814e754 100644 --- a/vendor/github.com/containerd/containerd/runtime/v2/shim.go +++ b/vendor/github.com/containerd/containerd/runtime/v2/shim.go @@ -24,7 +24,6 @@ import ( "path/filepath" "time" - eventstypes "github.com/containerd/containerd/api/events" "github.com/containerd/containerd/api/types" tasktypes "github.com/containerd/containerd/api/types/task" "github.com/containerd/containerd/errdefs" @@ -112,7 +111,7 @@ func (s *shim) Shutdown(ctx context.Context) error { _, err := s.task.Shutdown(ctx, &task.ShutdownRequest{ ID: s.ID(), }) - if err != nil && err != ttrpc.ErrClosed { + if err != nil && errors.Cause(err) != ttrpc.ErrClosed { return errdefs.FromGRPC(err) } return nil @@ -163,12 +162,6 @@ func (s *shim) Delete(ctx context.Context) (*runtime.Exit, error) { // remove self from the runtime task list // this seems dirty but it cleans up the API across runtimes, tasks, and the service s.rtTasks.Delete(ctx, s.ID()) - s.events.Publish(ctx, runtime.TaskDeleteEventTopic, &eventstypes.TaskDelete{ - ContainerID: s.ID(), - ExitStatus: response.ExitStatus, - ExitedAt: response.ExitedAt, - Pid: response.Pid, - }) return &runtime.Exit{ Status: response.ExitStatus, Timestamp: response.ExitedAt, @@ -212,9 +205,6 @@ func (s *shim) Pause(ctx context.Context) error { }); err != nil { return errdefs.FromGRPC(err) } - s.events.Publish(ctx, runtime.TaskPausedEventTopic, &eventstypes.TaskPaused{ - ContainerID: s.ID(), - }) return nil } @@ -224,9 +214,6 @@ func (s *shim) Resume(ctx context.Context) error { }); err != nil { return errdefs.FromGRPC(err) } - s.events.Publish(ctx, runtime.TaskResumedEventTopic, &eventstypes.TaskResumed{ - ContainerID: s.ID(), - }) return nil } @@ -238,10 +225,6 @@ func (s *shim) Start(ctx context.Context) error { return errdefs.FromGRPC(err) } s.taskPid = int(response.Pid) - s.events.Publish(ctx, runtime.TaskStartEventTopic, &eventstypes.TaskStart{ - ContainerID: s.ID(), - Pid: uint32(s.taskPid), - }) return nil } @@ -340,9 +323,6 @@ func (s *shim) Checkpoint(ctx context.Context, path string, options *ptypes.Any) if _, err := s.task.Checkpoint(ctx, request); err != nil { return errdefs.FromGRPC(err) } - s.events.Publish(ctx, runtime.TaskCheckpointedEventTopic, &eventstypes.TaskCheckpointed{ - ContainerID: s.ID(), - }) return nil } diff --git a/vendor/github.com/containerd/containerd/runtime/v2/shim/shim.go b/vendor/github.com/containerd/containerd/runtime/v2/shim/shim.go index 39484c191..d60d49663 100644 --- a/vendor/github.com/containerd/containerd/runtime/v2/shim/shim.go +++ b/vendor/github.com/containerd/containerd/runtime/v2/shim/shim.go @@ -62,6 +62,17 @@ type Opts struct { Debug bool } +// BinaryOpts allows the configuration of a shims binary setup +type BinaryOpts func(*Config) + +// Config of shim binary options provided by shim implementations +type Config struct { + // NoSubreaper disables setting the shim as a child subreaper + NoSubreaper bool + // NoReaper disables the shim binary from reaping any child process implicitly + NoReaper bool +} + var ( debugFlag bool idFlag string @@ -118,27 +129,34 @@ func setLogger(ctx context.Context, id string) error { } // Run initializes and runs a shim server -func Run(id string, initFunc Init) { - if err := run(id, initFunc); err != nil { +func Run(id string, initFunc Init, opts ...BinaryOpts) { + var config Config + for _, o := range opts { + o(&config) + } + if err := run(id, initFunc, config); err != nil { fmt.Fprintf(os.Stderr, "%s: %s\n", id, err) os.Exit(1) } } -func run(id string, initFunc Init) error { +func run(id string, initFunc Init, config Config) error { parseFlags() setRuntime() - signals, err := setupSignals() + signals, err := setupSignals(config) if err != nil { return err } - if err := subreaper(); err != nil { - return err + if !config.NoSubreaper { + if err := subreaper(); err != nil { + return err + } } publisher := &remoteEventsPublisher{ address: addressFlag, containerdBinaryPath: containerdBinaryFlag, + noReaper: config.NoReaper, } if namespaceFlag == "" { return fmt.Errorf("shim namespace cannot be empty") @@ -266,4 +284,5 @@ func dumpStacks(logger *logrus.Entry) { type remoteEventsPublisher struct { address string containerdBinaryPath string + noReaper bool } diff --git a/vendor/github.com/containerd/containerd/runtime/v2/shim/shim_freebsd.go b/vendor/github.com/containerd/containerd/runtime/v2/shim/shim_freebsd.go new file mode 100644 index 000000000..4bc636280 --- /dev/null +++ b/vendor/github.com/containerd/containerd/runtime/v2/shim/shim_freebsd.go @@ -0,0 +1,29 @@ +// +build freebsd + +/* + Copyright The containerd 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 shim + +import "github.com/containerd/ttrpc" + +func newServer() (*ttrpc.Server, error) { + return ttrpc.NewServer() +} + +func subreaper() error { + return nil +} diff --git a/vendor/github.com/containerd/containerd/runtime/v2/shim/shim_unix.go b/vendor/github.com/containerd/containerd/runtime/v2/shim/shim_unix.go index 937aaaf0d..eaff20a33 100644 --- a/vendor/github.com/containerd/containerd/runtime/v2/shim/shim_unix.go +++ b/vendor/github.com/containerd/containerd/runtime/v2/shim/shim_unix.go @@ -39,9 +39,13 @@ import ( // setupSignals creates a new signal handler for all signals and sets the shim as a // sub-reaper so that the container processes are reparented -func setupSignals() (chan os.Signal, error) { +func setupSignals(config Config) (chan os.Signal, error) { signals := make(chan os.Signal, 32) - signal.Notify(signals, unix.SIGTERM, unix.SIGINT, unix.SIGCHLD, unix.SIGPIPE) + smp := []os.Signal{unix.SIGTERM, unix.SIGINT, unix.SIGPIPE} + if !config.NoReaper { + smp = append(smp, unix.SIGCHLD) + } + signal.Notify(signals, smp...) return signals, nil } @@ -72,9 +76,9 @@ func serveListener(path string) (net.Listener, error) { func handleSignals(logger *logrus.Entry, signals chan os.Signal) error { logger.Info("starting signal loop") + for { - select { - case s := <-signals: + for s := range signals { switch s { case unix.SIGCHLD: if err := Reap(); err != nil { @@ -102,6 +106,15 @@ func (l *remoteEventsPublisher) Publish(ctx context.Context, topic string, event } cmd := exec.CommandContext(ctx, l.containerdBinaryPath, "--address", l.address, "publish", "--topic", topic, "--namespace", ns) cmd.Stdin = bytes.NewReader(data) + if l.noReaper { + if err := cmd.Start(); err != nil { + return err + } + if err := cmd.Wait(); err != nil { + return errors.Wrap(err, "failed to publish event") + } + return nil + } c, err := Default.Start(cmd) if err != nil { return err diff --git a/vendor/github.com/containerd/containerd/runtime/v2/shim/shim_windows.go b/vendor/github.com/containerd/containerd/runtime/v2/shim/shim_windows.go index bd3f62aea..e9d9db7ba 100644 --- a/vendor/github.com/containerd/containerd/runtime/v2/shim/shim_windows.go +++ b/vendor/github.com/containerd/containerd/runtime/v2/shim/shim_windows.go @@ -40,7 +40,7 @@ import ( ) // setupSignals creates a new signal handler for all signals -func setupSignals() (chan os.Signal, error) { +func setupSignals(config Config) (chan os.Signal, error) { signals := make(chan os.Signal, 32) return signals, nil } @@ -108,12 +108,12 @@ func serveListener(path string) (net.Listener, error) { func handleSignals(logger *logrus.Entry, signals chan os.Signal) error { logger.Info("starting signal loop") + for { - select { - case s := <-signals: + for s := range signals { switch s { case os.Interrupt: - break + return nil } } } diff --git a/vendor/github.com/containerd/containerd/runtime/v2/shim/util.go b/vendor/github.com/containerd/containerd/runtime/v2/shim/util.go index 77afaa1f3..a4e300f86 100644 --- a/vendor/github.com/containerd/containerd/runtime/v2/shim/util.go +++ b/vendor/github.com/containerd/containerd/runtime/v2/shim/util.go @@ -31,8 +31,6 @@ import ( "github.com/pkg/errors" ) -const shimBinaryFormat = "containerd-shim-%s-%s" - var runtimePaths sync.Map // Command returns the shim command with the provided args and configuration @@ -65,7 +63,19 @@ func Command(ctx context.Context, runtime, containerdAddress, path string, cmdAr if cmdPath, lerr = exec.LookPath(name); lerr != nil { if eerr, ok := lerr.(*exec.Error); ok { if eerr.Err == exec.ErrNotFound { - return nil, errors.Wrapf(os.ErrNotExist, "runtime %q binary not installed %q", runtime, name) + // LookPath only finds current directory matches based on + // the callers current directory but the caller is not + // likely in the same directory as the containerd + // executables. Instead match the calling binaries path + // (containerd) and see if they are side by side. If so + // execute the shim found there. + testPath := filepath.Join(filepath.Dir(self), name) + if _, serr := os.Stat(testPath); serr == nil { + cmdPath = testPath + } + if cmdPath == "" { + return nil, errors.Wrapf(os.ErrNotExist, "runtime %q binary not installed %q", runtime, name) + } } } } diff --git a/vendor/github.com/containerd/containerd/runtime/v2/shim/util_unix.go b/vendor/github.com/containerd/containerd/runtime/v2/shim/util_unix.go index 262fe2b36..b86f8624a 100644 --- a/vendor/github.com/containerd/containerd/runtime/v2/shim/util_unix.go +++ b/vendor/github.com/containerd/containerd/runtime/v2/shim/util_unix.go @@ -31,6 +31,8 @@ import ( "github.com/pkg/errors" ) +const shimBinaryFormat = "containerd-shim-%s-%s" + func getSysProcAttr() *syscall.SysProcAttr { return &syscall.SysProcAttr{ Setpgid: true, diff --git a/vendor/github.com/containerd/containerd/runtime/v2/shim/util_windows.go b/vendor/github.com/containerd/containerd/runtime/v2/shim/util_windows.go index 986fc754b..ef26ebe22 100644 --- a/vendor/github.com/containerd/containerd/runtime/v2/shim/util_windows.go +++ b/vendor/github.com/containerd/containerd/runtime/v2/shim/util_windows.go @@ -29,6 +29,8 @@ import ( "github.com/pkg/errors" ) +const shimBinaryFormat = "containerd-shim-%s-%s.exe" + func getSysProcAttr() *syscall.SysProcAttr { return nil } @@ -54,7 +56,7 @@ func AnonDialer(address string, timeout time.Duration) (net.Conn, error) { timedOutError := errors.Errorf("timed out waiting for npipe %s", address) start := time.Now() for { - remaining := timeout - time.Now().Sub(start) + remaining := timeout - time.Since(start) if remaining <= 0 { lastError = timedOutError break @@ -71,7 +73,7 @@ func AnonDialer(address string, timeout time.Duration) (net.Conn, error) { // serve it within 5 seconds. We use the passed in timeout for the // `DialPipe` timeout if the pipe exists however to give the pipe time // to `Accept` the connection. - if time.Now().Sub(start) >= 5*time.Second { + if time.Since(start) >= 5*time.Second { lastError = timedOutError break } diff --git a/vendor/github.com/containerd/containerd/runtime/v2/shim_unix.go b/vendor/github.com/containerd/containerd/runtime/v2/shim_unix.go index 1a08be5d1..6738a7787 100644 --- a/vendor/github.com/containerd/containerd/runtime/v2/shim_unix.go +++ b/vendor/github.com/containerd/containerd/runtime/v2/shim_unix.go @@ -28,5 +28,5 @@ import ( ) func openShimLog(ctx context.Context, bundle *Bundle) (io.ReadCloser, error) { - return fifo.OpenFifo(ctx, filepath.Join(bundle.Path, "log"), unix.O_RDONLY|unix.O_CREAT|unix.O_NONBLOCK, 0700) + return fifo.OpenFifo(ctx, filepath.Join(bundle.Path, "log"), unix.O_RDWR|unix.O_CREAT, 0700) } diff --git a/vendor/github.com/containerd/containerd/services/containers/local.go b/vendor/github.com/containerd/containerd/services/containers/local.go index 95a09872e..7b1a24b8f 100644 --- a/vendor/github.com/containerd/containerd/services/containers/local.go +++ b/vendor/github.com/containerd/containerd/services/containers/local.go @@ -147,9 +147,7 @@ func (l *local) Update(ctx context.Context, req *api.UpdateContainerRequest, _ . if err := l.withStoreUpdate(ctx, func(ctx context.Context, store containers.Store) error { var fieldpaths []string if req.UpdateMask != nil && len(req.UpdateMask.Paths) > 0 { - for _, path := range req.UpdateMask.Paths { - fieldpaths = append(fieldpaths, path) - } + fieldpaths = append(fieldpaths, req.UpdateMask.Paths...) } updated, err := store.Update(ctx, container, fieldpaths...) diff --git a/vendor/github.com/containerd/containerd/services/containers/service.go b/vendor/github.com/containerd/containerd/services/containers/service.go index 897964aca..77e844908 100644 --- a/vendor/github.com/containerd/containerd/services/containers/service.go +++ b/vendor/github.com/containerd/containerd/services/containers/service.go @@ -94,7 +94,6 @@ func (s *service) ListStream(req *api.ListContainersRequest, stream api.Containe } } } - return nil } func (s *service) Create(ctx context.Context, req *api.CreateContainerRequest) (*api.CreateContainerResponse, error) { diff --git a/vendor/github.com/containerd/containerd/services/images/local.go b/vendor/github.com/containerd/containerd/services/images/local.go index 116c4e432..ddd815a19 100644 --- a/vendor/github.com/containerd/containerd/services/images/local.go +++ b/vendor/github.com/containerd/containerd/services/images/local.go @@ -137,9 +137,7 @@ func (l *local) Update(ctx context.Context, req *imagesapi.UpdateImageRequest, _ ) if req.UpdateMask != nil && len(req.UpdateMask.Paths) > 0 { - for _, path := range req.UpdateMask.Paths { - fieldpaths = append(fieldpaths, path) - } + fieldpaths = append(fieldpaths, req.UpdateMask.Paths...) } updated, err := l.store.Update(ctx, image, fieldpaths...) diff --git a/vendor/github.com/containerd/containerd/services/server/config/config.go b/vendor/github.com/containerd/containerd/services/server/config/config.go index 2124d8671..27cebf579 100644 --- a/vendor/github.com/containerd/containerd/services/server/config/config.go +++ b/vendor/github.com/containerd/containerd/services/server/config/config.go @@ -83,6 +83,44 @@ type ProxyPlugin struct { Address string `toml:"address"` } +// BoltConfig defines the configuration values for the bolt plugin, which is +// loaded here, rather than back registered in the metadata package. +type BoltConfig struct { + // ContentSharingPolicy sets the sharing policy for content between + // namespaces. + // + // The default mode "shared" will make blobs available in all + // namespaces once it is pulled into any namespace. The blob will be pulled + // into the namespace if a writer is opened with the "Expected" digest that + // is already present in the backend. + // + // The alternative mode, "isolated" requires that clients prove they have + // access to the content by providing all of the content to the ingest + // before the blob is added to the namespace. + // + // Both modes share backing data, while "shared" will reduce total + // bandwidth across namespaces, at the cost of allowing access to any blob + // just by knowing its digest. + ContentSharingPolicy string `toml:"content_sharing_policy"` +} + +const ( + // SharingPolicyShared represents the "shared" sharing policy + SharingPolicyShared = "shared" + // SharingPolicyIsolated represents the "isolated" sharing policy + SharingPolicyIsolated = "isolated" +) + +// Validate validates if BoltConfig is valid +func (bc *BoltConfig) Validate() error { + switch bc.ContentSharingPolicy { + case SharingPolicyShared, SharingPolicyIsolated: + return nil + default: + return errors.Wrapf(errdefs.ErrInvalidArgument, "unknown policy: %s", bc.ContentSharingPolicy) + } +} + // Decode unmarshals a plugin specific configuration by plugin id func (c *Config) Decode(id string, v interface{}) (interface{}, error) { data, ok := c.Plugins[id] diff --git a/vendor/github.com/containerd/containerd/services/server/server.go b/vendor/github.com/containerd/containerd/services/server/server.go index 514bbdf69..6ed429146 100644 --- a/vendor/github.com/containerd/containerd/services/server/server.go +++ b/vendor/github.com/containerd/containerd/services/server/server.go @@ -238,6 +238,9 @@ func LoadPlugins(ctx context.Context, config *srvconfig.Config) ([]*plugin.Regis plugin.ContentPlugin, plugin.SnapshotPlugin, }, + Config: &srvconfig.BoltConfig{ + ContentSharingPolicy: srvconfig.SharingPolicyShared, + }, InitFn: func(ic *plugin.InitContext) (interface{}, error) { if err := os.MkdirAll(ic.Root, 0711); err != nil { return nil, err @@ -265,6 +268,22 @@ func LoadPlugins(ctx context.Context, config *srvconfig.Config) ([]*plugin.Regis snapshotters[name] = sn.(snapshots.Snapshotter) } + shared := true + ic.Meta.Exports["policy"] = srvconfig.SharingPolicyShared + if cfg, ok := ic.Config.(*srvconfig.BoltConfig); ok { + if cfg.ContentSharingPolicy != "" { + if err := cfg.Validate(); err != nil { + return nil, err + } + if cfg.ContentSharingPolicy == srvconfig.SharingPolicyIsolated { + ic.Meta.Exports["policy"] = srvconfig.SharingPolicyIsolated + shared = false + } + + log.L.WithField("policy", cfg.ContentSharingPolicy).Info("metadata content store policy set") + } + } + path := filepath.Join(ic.Root, "meta.db") ic.Meta.Exports["path"] = path @@ -272,7 +291,12 @@ func LoadPlugins(ctx context.Context, config *srvconfig.Config) ([]*plugin.Regis if err != nil { return nil, err } - mdb := metadata.NewDB(db, cs.(content.Store), snapshotters) + + var dbopts []metadata.DBOpt + if !shared { + dbopts = append(dbopts, metadata.WithPolicyIsolated) + } + mdb := metadata.NewDB(db, cs.(content.Store), snapshotters, dbopts...) if err := mdb.Init(ic.Context); err != nil { return nil, err } diff --git a/vendor/github.com/containerd/containerd/services/tasks/local.go b/vendor/github.com/containerd/containerd/services/tasks/local.go index 773feeb4f..ee7dc1bc9 100644 --- a/vendor/github.com/containerd/containerd/services/tasks/local.go +++ b/vendor/github.com/containerd/containerd/services/tasks/local.go @@ -41,7 +41,9 @@ import ( "github.com/containerd/containerd/mount" "github.com/containerd/containerd/plugin" "github.com/containerd/containerd/runtime" + "github.com/containerd/containerd/runtime/linux/runctypes" "github.com/containerd/containerd/runtime/v2" + "github.com/containerd/containerd/runtime/v2/runc/options" "github.com/containerd/containerd/services" "github.com/containerd/typeurl" ptypes "github.com/gogo/protobuf/types" @@ -123,11 +125,16 @@ type local struct { } func (l *local) Create(ctx context.Context, r *api.CreateTaskRequest, _ ...grpc.CallOption) (*api.CreateTaskResponse, error) { - var ( - checkpointPath string - err error - ) - if r.Checkpoint != nil { + container, err := l.getContainer(ctx, r.ContainerID) + if err != nil { + return nil, errdefs.ToGRPC(err) + } + checkpointPath, err := getRestorePath(container.Runtime.Name, r.Options) + if err != nil { + return nil, err + } + // jump get checkpointPath from checkpoint image + if checkpointPath != "" && r.Checkpoint != nil { checkpointPath, err = ioutil.TempDir(os.Getenv("XDG_RUNTIME_DIR"), "ctrd-checkpoint") if err != nil { return nil, err @@ -149,10 +156,6 @@ func (l *local) Create(ctx context.Context, r *api.CreateTaskRequest, _ ...grpc. return nil, err } } - container, err := l.getContainer(ctx, r.ContainerID) - if err != nil { - return nil, errdefs.ToGRPC(err) - } opts := runtime.CreateOpts{ Spec: container.Spec, IO: runtime.IO{ @@ -478,14 +481,27 @@ func (l *local) Checkpoint(ctx context.Context, r *api.CheckpointTaskRequest, _ if err != nil { return nil, err } - image, err := ioutil.TempDir(os.Getenv("XDG_RUNTIME_DIR"), "ctd-checkpoint") + image, err := getCheckpointPath(container.Runtime.Name, r.Options) if err != nil { - return nil, errdefs.ToGRPC(err) + return nil, err + } + checkpointImageExists := false + if image == "" { + checkpointImageExists = true + image, err = ioutil.TempDir(os.Getenv("XDG_RUNTIME_DIR"), "ctd-checkpoint") + if err != nil { + return nil, errdefs.ToGRPC(err) + } + defer os.RemoveAll(image) } - defer os.RemoveAll(image) if err := t.Checkpoint(ctx, image, r.Options); err != nil { return nil, errdefs.ToGRPC(err) } + // do not commit checkpoint image if checkpoint ImagePath is passed, + // return if checkpointImageExists is false + if !checkpointImageExists { + return &api.CheckpointTaskResponse{}, nil + } // write checkpoint to the content store tar := archive.Diff(ctx, "", image) cp, err := l.writeContent(ctx, images.MediaTypeContainerd1Checkpoint, image, tar) @@ -663,3 +679,71 @@ func (l *local) allRuntimes() (o []runtime.PlatformRuntime) { o = append(o, l.v2Runtime) return o } + +// getCheckpointPath only suitable for runc runtime now +func getCheckpointPath(runtime string, option *ptypes.Any) (string, error) { + if option == nil { + return "", nil + } + + var checkpointPath string + switch runtime { + case "io.containerd.runc.v1": + v, err := typeurl.UnmarshalAny(option) + if err != nil { + return "", err + } + opts, ok := v.(*options.CheckpointOptions) + if !ok { + return "", fmt.Errorf("invalid task checkpoint option for %s", runtime) + } + checkpointPath = opts.ImagePath + + case "io.containerd.runtime.v1.linux": + v, err := typeurl.UnmarshalAny(option) + if err != nil { + return "", err + } + opts, ok := v.(*runctypes.CheckpointOptions) + if !ok { + return "", fmt.Errorf("invalid task checkpoint option for %s", runtime) + } + checkpointPath = opts.ImagePath + } + + return checkpointPath, nil +} + +// getRestorePath only suitable for runc runtime now +func getRestorePath(runtime string, option *ptypes.Any) (string, error) { + if option == nil { + return "", nil + } + + var restorePath string + switch runtime { + case "io.containerd.runc.v1": + v, err := typeurl.UnmarshalAny(option) + if err != nil { + return "", err + } + opts, ok := v.(*options.Options) + if !ok { + return "", fmt.Errorf("invalid task create option for %s", runtime) + } + restorePath = opts.CriuImagePath + + case "io.containerd.runtime.v1.linux": + v, err := typeurl.UnmarshalAny(option) + if err != nil { + return "", err + } + opts, ok := v.(*runctypes.CreateOptions) + if !ok { + return "", fmt.Errorf("invalid task create option for %s", runtime) + } + restorePath = opts.CriuImagePath + } + + return restorePath, nil +} diff --git a/vendor/github.com/containerd/containerd/snapshots/overlay/overlay.go b/vendor/github.com/containerd/containerd/snapshots/overlay/overlay.go index 2c296adbe..9ad82c7f3 100644 --- a/vendor/github.com/containerd/containerd/snapshots/overlay/overlay.go +++ b/vendor/github.com/containerd/containerd/snapshots/overlay/overlay.go @@ -350,7 +350,7 @@ func (o *snapshotter) getCleanupDirectories(ctx context.Context, t storage.Trans return cleanup, nil } -func (o *snapshotter) createSnapshot(ctx context.Context, kind snapshots.Kind, key, parent string, opts []snapshots.Opt) ([]mount.Mount, error) { +func (o *snapshotter) createSnapshot(ctx context.Context, kind snapshots.Kind, key, parent string, opts []snapshots.Opt) (_ []mount.Mount, err error) { ctx, t, err := o.ms.TransactionContext(ctx, true) if err != nil { return nil, err @@ -426,7 +426,7 @@ func (o *snapshotter) createSnapshot(ctx context.Context, kind snapshots.Kind, k } func (o *snapshotter) prepareDirectory(ctx context.Context, snapshotDir string, kind snapshots.Kind) (string, error) { - td, err := ioutil.TempDir(filepath.Join(o.root, "snapshots"), "new-") + td, err := ioutil.TempDir(snapshotDir, "new-") if err != nil { return "", errors.Wrap(err, "failed to create temp dir") } diff --git a/vendor/github.com/containerd/containerd/snapshots/snapshotter.go b/vendor/github.com/containerd/containerd/snapshots/snapshotter.go index d11252d1e..68a807582 100644 --- a/vendor/github.com/containerd/containerd/snapshots/snapshotter.go +++ b/vendor/github.com/containerd/containerd/snapshots/snapshotter.go @@ -160,9 +160,13 @@ func (u *Usage) Add(other Usage) { // layerPath, tmpDir := getLayerPath(), mkTmpDir() // just a path to layer tar file. // // We start by using a Snapshotter to Prepare a new snapshot transaction, using a -// key and descending from the empty parent "": +// key and descending from the empty parent "". To prevent our layer from being +// garbage collected during unpacking, we add the `containerd.io/gc.root` label: // -// mounts, err := snapshotter.Prepare(ctx, key, "") +// noGcOpt := snapshotter.WithLabels(map[string]string{ +// "containerd.io/gc.root": time.Now().UTC().Format(time.RFC3339), +// }) +// mounts, err := snapshotter.Prepare(ctx, key, "", noGcOpt) // if err != nil { ... } // // We get back a list of mounts from Snapshotter.Prepare, with the key identifying @@ -191,15 +195,13 @@ func (u *Usage) Add(other Usage) { // // Now that we've verified and unpacked our layer, we commit the active // snapshot to a name. For this example, we are just going to use the layer -// digest, but in practice, this will probably be the ChainID: +// digest, but in practice, this will probably be the ChainID. This also removes +// the active snapshot: // -// if err := snapshotter.Commit(ctx, digest.String(), key); err != nil { ... } +// if err := snapshotter.Commit(ctx, digest.String(), key, noGcOpt); err != nil { ... } // // Now, we have a layer in the Snapshotter that can be accessed with the digest -// provided during commit. Once you have committed the snapshot, the active -// snapshot can be removed with the following: -// -// snapshotter.Remove(ctx, key) +// provided during commit. // // Importing the Next Layer // @@ -207,7 +209,7 @@ func (u *Usage) Add(other Usage) { // above except that the parent is provided as parent when calling // Manager.Prepare, assuming a clean, unique key identifier: // -// mounts, err := snapshotter.Prepare(ctx, key, parentDigest) +// mounts, err := snapshotter.Prepare(ctx, key, parentDigest, noGcOpt) // // We then mount, apply and commit, as we did above. The new snapshot will be // based on the content of the previous one. diff --git a/vendor/github.com/containerd/containerd/task.go b/vendor/github.com/containerd/containerd/task.go index 6806e1162..9deb66c7e 100644 --- a/vendor/github.com/containerd/containerd/task.go +++ b/vendor/github.com/containerd/containerd/task.go @@ -37,6 +37,8 @@ import ( "github.com/containerd/containerd/mount" "github.com/containerd/containerd/plugin" "github.com/containerd/containerd/rootfs" + "github.com/containerd/containerd/runtime/linux/runctypes" + "github.com/containerd/containerd/runtime/v2/runc/options" "github.com/containerd/typeurl" google_protobuf "github.com/gogo/protobuf/types" digest "github.com/opencontainers/go-digest" @@ -147,6 +149,8 @@ type Task interface { // OCI Index that can be push and pulled from a remote resource. // // Additional software like CRIU maybe required to checkpoint and restore tasks + // NOTE: Checkpoint supports to dump task information to a directory, in this way, + // an empty OCI Index will be returned. Checkpoint(context.Context, ...CheckpointTaskOpts) (Image, error) // Update modifies executing tasks with updated settings Update(context.Context, ...UpdateTaskOpts) error @@ -185,8 +189,10 @@ func (t *task) Start(ctx context.Context) error { ContainerID: t.id, }) if err != nil { - t.io.Cancel() - t.io.Close() + if t.io != nil { + t.io.Cancel() + t.io.Close() + } return errdefs.FromGRPC(err) } t.pid = r.Pid @@ -387,6 +393,8 @@ func (t *task) Resize(ctx context.Context, w, h uint32) error { return errdefs.FromGRPC(err) } +// NOTE: Checkpoint supports to dump task information to a directory, in this way, an empty +// OCI Index will be returned. func (t *task) Checkpoint(ctx context.Context, opts ...CheckpointTaskOpts) (Image, error) { ctx, done, err := t.client.WithLease(ctx) if err != nil { @@ -433,6 +441,12 @@ func (t *task) Checkpoint(ctx context.Context, opts ...CheckpointTaskOpts) (Imag if err := t.checkpointTask(ctx, &index, request); err != nil { return nil, err } + // if checkpoint image path passed, jump checkpoint image, + // return an empty image + if isCheckpointPathExist(cr.Runtime.Name, i.Options) { + return NewImage(t.client, images.Image{}), nil + } + if cr.Image != "" { if err := t.checkpointImage(ctx, &index, cr.Image); err != nil { return nil, err @@ -542,6 +556,7 @@ func (t *task) checkpointTask(ctx context.Context, index *v1.Index, request *tas if err != nil { return errdefs.FromGRPC(err) } + // NOTE: response.Descriptors can be an empty slice if checkpoint image is jumped // add the checkpoint descriptors to the index for _, d := range response.Descriptors { index.Manifests = append(index.Manifests, v1.Descriptor{ @@ -619,3 +634,24 @@ func writeContent(ctx context.Context, store content.Ingester, mediaType, ref st Size: size, }, nil } + +// isCheckpointPathExist only suitable for runc runtime now +func isCheckpointPathExist(runtime string, v interface{}) bool { + if v == nil { + return false + } + + switch runtime { + case "io.containerd.runc.v1": + if opts, ok := v.(*options.CheckpointOptions); ok && opts.ImagePath != "" { + return true + } + + case "io.containerd.runtime.v1.linux": + if opts, ok := v.(*runctypes.CheckpointOptions); ok && opts.ImagePath != "" { + return true + } + } + + return false +} diff --git a/vendor/github.com/containerd/containerd/task_opts.go b/vendor/github.com/containerd/containerd/task_opts.go index ce861ea51..714a152c5 100644 --- a/vendor/github.com/containerd/containerd/task_opts.go +++ b/vendor/github.com/containerd/containerd/task_opts.go @@ -27,11 +27,18 @@ import ( "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/images" "github.com/containerd/containerd/mount" + "github.com/containerd/containerd/runtime/linux/runctypes" + "github.com/containerd/containerd/runtime/v2/runc/options" imagespec "github.com/opencontainers/image-spec/specs-go/v1" "github.com/opencontainers/runtime-spec/specs-go" "github.com/pkg/errors" ) +const ( + v1runtime = "io.containerd.runtime.v1.linux" + v2runtime = "io.containerd.runc.v1" +) + // NewTaskOpts allows the caller to set options on a new task type NewTaskOpts func(context.Context, *Client, *TaskInfo) error @@ -89,6 +96,60 @@ func WithCheckpointName(name string) CheckpointTaskOpts { } } +// WithCheckpointImagePath sets image path for checkpoint option +func WithCheckpointImagePath(rt, path string) CheckpointTaskOpts { + return func(r *CheckpointTaskInfo) error { + switch rt { + case v1runtime: + if r.Options == nil { + r.Options = &runctypes.CheckpointOptions{} + } + opts, ok := r.Options.(*runctypes.CheckpointOptions) + if !ok { + return errors.New("invalid v1 checkpoint options format") + } + opts.ImagePath = path + case v2runtime: + if r.Options == nil { + r.Options = &options.CheckpointOptions{} + } + opts, ok := r.Options.(*options.CheckpointOptions) + if !ok { + return errors.New("invalid v2 checkpoint options format") + } + opts.ImagePath = path + } + return nil + } +} + +// WithRestoreImagePath sets image path for create option +func WithRestoreImagePath(rt, path string) NewTaskOpts { + return func(ctx context.Context, c *Client, ti *TaskInfo) error { + switch rt { + case v1runtime: + if ti.Options == nil { + ti.Options = &runctypes.CreateOptions{} + } + opts, ok := ti.Options.(*runctypes.CreateOptions) + if !ok { + return errors.New("invalid v1 create options format") + } + opts.CriuImagePath = path + case v2runtime: + if ti.Options == nil { + ti.Options = &options.Options{} + } + opts, ok := ti.Options.(*options.Options) + if !ok { + return errors.New("invalid v2 create options format") + } + opts.CriuImagePath = path + } + return nil + } +} + // ProcessDeleteOpts allows the caller to set options for the deletion of a task type ProcessDeleteOpts func(context.Context, Process) error diff --git a/vendor/github.com/containerd/containerd/vendor.conf b/vendor/github.com/containerd/containerd/vendor.conf index 8ebe63608..10f886342 100644 --- a/vendor/github.com/containerd/containerd/vendor.conf +++ b/vendor/github.com/containerd/containerd/vendor.conf @@ -1,6 +1,6 @@ github.com/containerd/go-runc 5a6d9f37cfa36b15efba46dc7ea349fa9b7143c3 github.com/containerd/console c12b1e7919c14469339a5d38f2f8ed9b64a9de23 -github.com/containerd/cgroups 5e610833b72089b37d0e615de9a92dfc043757c2 +github.com/containerd/cgroups 1152b960fcee041f50df15cdc67c29dbccf801ef github.com/containerd/typeurl a93fcdb778cd272c6e9b3028b2f42d813e785d40 github.com/containerd/fifo 3d5202aec260678c48179c56f40e6f38a095738c github.com/containerd/btrfs 2e1aa0ddf94f91fa282b6ed87c23bf0d64911244 @@ -20,7 +20,7 @@ github.com/gogo/protobuf v1.0.0 github.com/gogo/googleapis 08a7655d27152912db7aaf4f983275eaf8d128ef github.com/golang/protobuf v1.1.0 github.com/opencontainers/runtime-spec eba862dc2470385a233c7507392675cbeadf7353 # v1.0.1-45-geba862d -github.com/opencontainers/runc v1.0.0-rc6 +github.com/opencontainers/runc 12f6a991201fdb8f82579582d5e00e28fba06d0a github.com/sirupsen/logrus v1.0.3 github.com/urfave/cli 7bc6a0acffa589f415f88aca16cc1de5ffd66f9c golang.org/x/net b3756b4b77d7b13260a0a2ec658753cf48922eac @@ -29,21 +29,21 @@ github.com/pkg/errors v0.8.0 github.com/opencontainers/go-digest c9281466c8b2f606084ac71339773efd177436e7 golang.org/x/sys 1b2967e3c290b7c545b3db0deeda16e9be4f98a2 https://github.com/golang/sys github.com/opencontainers/image-spec v1.0.1 -golang.org/x/sync 450f422ab23cf9881c94e2db30cac0eb1b7cf80c +golang.org/x/sync 42b317875d0fa942474b76e1b46a6060d720ae6e github.com/BurntSushi/toml a368813c5e648fee92e5f6c30e3944ff9d5e8895 github.com/grpc-ecosystem/go-grpc-prometheus 6b7015e65d366bf3f19b2b2a000a831940f0f7e0 github.com/Microsoft/go-winio v0.4.11 -github.com/Microsoft/hcsshim v0.8.2 +github.com/Microsoft/hcsshim v0.8.5 google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944 golang.org/x/text 19e51611da83d6be54ddafce4a4af510cb3e9ea4 -github.com/containerd/ttrpc 2a805f71863501300ae1976d29f0454ae003e85a +github.com/containerd/ttrpc f02858b1457c5ca3aaec3a0803eb0d59f96e41d6 github.com/syndtr/gocapability db04d3cc01c8b54962a58ec7e491717d06cfcc16 gotest.tools v2.1.0 github.com/google/go-cmp v0.1.0 go.etcd.io/bbolt v1.3.1-etcd.8 # cri dependencies -github.com/containerd/cri f913714917d2456d7e65a0be84962b1ce8acb487 # release/1.2 branch +github.com/containerd/cri 4dd6735020f5596dd41738f8c4f5cb07fa804c5e # master github.com/containerd/go-cni 40bcf8ec8acd7372be1d77031d585d5d8e561c90 github.com/blang/semver v3.1.0 github.com/containernetworking/cni v0.6.0 @@ -53,8 +53,6 @@ github.com/docker/distribution b38e5838b7b2f2ad48e06ec4b500011976080621 github.com/docker/docker 86f080cff0914e9694068ed78d503701667c4c00 github.com/docker/spdystream 449fdfce4d962303d702fec724ef0ad181c92528 github.com/emicklei/go-restful v2.2.1 -github.com/ghodss/yaml v1.0.0 -github.com/golang/glog 44145f04b68cf362d9c4df2182967c2275eaefed github.com/google/gofuzz 44d81051d367757e1c7c6a5a86423ece9afcf63c github.com/hashicorp/errwrap 7554cd9344cec97297fa6649b055a8c98c2a1e55 github.com/hashicorp/go-multierror ed905158d87462226a13fe39ddf685ea65f1c11f @@ -73,12 +71,14 @@ golang.org/x/oauth2 a6bd8cefa1811bd24b86f8902872e4e8225f74c4 golang.org/x/time f51c12702a4d776e4c1fa9b0fabab841babae631 gopkg.in/inf.v0 3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4 gopkg.in/yaml.v2 v2.2.1 -k8s.io/api kubernetes-1.12.0 -k8s.io/apimachinery kubernetes-1.12.0 -k8s.io/apiserver kubernetes-1.12.0 -k8s.io/client-go kubernetes-1.12.0 -k8s.io/kubernetes v1.12.0 -k8s.io/utils cd34563cd63c2bd7c6fe88a73c4dcf34ed8a67cb +k8s.io/api kubernetes-1.13.0 +k8s.io/apimachinery kubernetes-1.13.0 +k8s.io/apiserver kubernetes-1.13.0 +k8s.io/client-go kubernetes-1.13.0 +k8s.io/klog 8139d8cb77af419532b33dfa7dd09fbc5f1d344f +k8s.io/kubernetes v1.13.0 +k8s.io/utils 0d26856f57b32ec3398579285e5c8a2bfe8c5243 +sigs.k8s.io/yaml v1.1.0 # zfs dependencies github.com/containerd/zfs 9f6ef3b1fe5144bd91fe5855b4eba81bc0d17d03 diff --git a/vendor/github.com/containerd/ttrpc/README.md b/vendor/github.com/containerd/ttrpc/README.md index d1eed6b12..c345c844e 100644 --- a/vendor/github.com/containerd/ttrpc/README.md +++ b/vendor/github.com/containerd/ttrpc/README.md @@ -50,3 +50,13 @@ TODO: - [ ] Document protocol layout - [ ] Add testing under concurrent load to ensure - [ ] Verify connection error handling + +# Project details + +ttrpc is a containerd sub-project, licensed under the [Apache 2.0 license](./LICENSE). +As a containerd sub-project, you will find the: + * [Project governance](https://github.com/containerd/project/blob/master/GOVERNANCE.md), + * [Maintainers](https://github.com/containerd/project/blob/master/MAINTAINERS), + * and [Contributing guidelines](https://github.com/containerd/project/blob/master/CONTRIBUTING.md) + +information in our [`containerd/project`](https://github.com/containerd/project) repository. diff --git a/vendor/github.com/containerd/ttrpc/client.go b/vendor/github.com/containerd/ttrpc/client.go index e40592dd7..a90608e8b 100644 --- a/vendor/github.com/containerd/ttrpc/client.go +++ b/vendor/github.com/containerd/ttrpc/client.go @@ -24,6 +24,7 @@ import ( "strings" "sync" "syscall" + "time" "github.com/gogo/protobuf/proto" "github.com/pkg/errors" @@ -86,6 +87,10 @@ func (c *Client) Call(ctx context.Context, service, method string, req, resp int cresp = &Response{} ) + if dl, ok := ctx.Deadline(); ok { + creq.TimeoutNano = dl.Sub(time.Now()).Nanoseconds() + } + if err := c.dispatch(ctx, creq, cresp); err != nil { return err } @@ -104,6 +109,7 @@ func (c *Client) Call(ctx context.Context, service, method string, req, resp int func (c *Client) dispatch(ctx context.Context, req *Request, resp *Response) error { errs := make(chan error, 1) call := &callRequest{ + ctx: ctx, req: req, resp: resp, errs: errs, diff --git a/vendor/github.com/containerd/ttrpc/server.go b/vendor/github.com/containerd/ttrpc/server.go index 263cb4583..40804eac0 100644 --- a/vendor/github.com/containerd/ttrpc/server.go +++ b/vendor/github.com/containerd/ttrpc/server.go @@ -414,6 +414,9 @@ func (c *serverConn) run(sctx context.Context) { case request := <-requests: active++ go func(id uint32) { + ctx, cancel := getRequestContext(ctx, request.req) + defer cancel() + p, status := c.server.services.call(ctx, request.req.Service, request.req.Method, request.req.Payload) resp := &Response{ Status: status.Proto(), @@ -454,3 +457,15 @@ func (c *serverConn) run(sctx context.Context) { } } } + +var noopFunc = func() {} + +func getRequestContext(ctx context.Context, req *Request) (retCtx context.Context, cancel func()) { + cancel = noopFunc + if req.TimeoutNano == 0 { + return ctx, cancel + } + + ctx, cancel = context.WithTimeout(ctx, time.Duration(req.TimeoutNano)) + return ctx, cancel +} diff --git a/vendor/github.com/containerd/ttrpc/types.go b/vendor/github.com/containerd/ttrpc/types.go index 1f7969e5c..a6b3b818e 100644 --- a/vendor/github.com/containerd/ttrpc/types.go +++ b/vendor/github.com/containerd/ttrpc/types.go @@ -23,9 +23,10 @@ import ( ) type Request struct { - Service string `protobuf:"bytes,1,opt,name=service,proto3"` - Method string `protobuf:"bytes,2,opt,name=method,proto3"` - Payload []byte `protobuf:"bytes,3,opt,name=payload,proto3"` + Service string `protobuf:"bytes,1,opt,name=service,proto3"` + Method string `protobuf:"bytes,2,opt,name=method,proto3"` + Payload []byte `protobuf:"bytes,3,opt,name=payload,proto3"` + TimeoutNano int64 `protobuf:"varint,4,opt,name=timeout_nano,proto3"` } func (r *Request) Reset() { *r = Request{} } diff --git a/vendor/github.com/opencontainers/runc/libcontainer/configs/intelrdt.go b/vendor/github.com/opencontainers/runc/libcontainer/configs/intelrdt.go index 6f47aac07..57e9f037d 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/configs/intelrdt.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/configs/intelrdt.go @@ -5,7 +5,9 @@ type IntelRdt struct { // Format: "L3:=;=;..." L3CacheSchema string `json:"l3_cache_schema,omitempty"` - // The schema of memory bandwidth percentage per L3 cache id + // The schema of memory bandwidth per L3 cache id // Format: "MB:=bandwidth0;=bandwidth1;..." + // The unit of memory bandwidth is specified in "percentages" by + // default, and in "MBps" if MBA Software Controller is enabled. MemBwSchema string `json:"memBwSchema,omitempty"` } diff --git a/vendor/golang.org/x/sync/README b/vendor/golang.org/x/sync/README deleted file mode 100644 index 59c9dcb49..000000000 --- a/vendor/golang.org/x/sync/README +++ /dev/null @@ -1,2 +0,0 @@ -This repository provides Go concurrency primitives in addition to the -ones provided by the language and "sync" and "sync/atomic" packages. diff --git a/vendor/golang.org/x/sync/README.md b/vendor/golang.org/x/sync/README.md new file mode 100644 index 000000000..1f8436cc9 --- /dev/null +++ b/vendor/golang.org/x/sync/README.md @@ -0,0 +1,18 @@ +# Go Sync + +This repository provides Go concurrency primitives in addition to the +ones provided by the language and "sync" and "sync/atomic" packages. + +## Download/Install + +The easiest way to install is to run `go get -u golang.org/x/sync`. You can +also manually git clone the repository to `$GOPATH/src/golang.org/x/sync`. + +## Report Issues / Send Patches + +This repository uses Gerrit for code changes. To learn how to submit changes to +this repository, see https://golang.org/doc/contribute.html. + +The main issue tracker for the sync repository is located at +https://github.com/golang/go/issues. Prefix your issue with "x/sync:" in the +subject line, so it is easy to find. diff --git a/vendor/golang.org/x/sync/errgroup/errgroup.go b/vendor/golang.org/x/sync/errgroup/errgroup.go index 533438d91..9857fe53d 100644 --- a/vendor/golang.org/x/sync/errgroup/errgroup.go +++ b/vendor/golang.org/x/sync/errgroup/errgroup.go @@ -7,9 +7,8 @@ package errgroup import ( + "context" "sync" - - "golang.org/x/net/context" ) // A Group is a collection of goroutines working on subtasks that are part of diff --git a/vendor/golang.org/x/sync/semaphore/semaphore.go b/vendor/golang.org/x/sync/semaphore/semaphore.go new file mode 100644 index 000000000..2096ca3a0 --- /dev/null +++ b/vendor/golang.org/x/sync/semaphore/semaphore.go @@ -0,0 +1,127 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package semaphore provides a weighted semaphore implementation. +package semaphore // import "golang.org/x/sync/semaphore" + +import ( + "container/list" + "context" + "sync" +) + +type waiter struct { + n int64 + ready chan<- struct{} // Closed when semaphore acquired. +} + +// NewWeighted creates a new weighted semaphore with the given +// maximum combined weight for concurrent access. +func NewWeighted(n int64) *Weighted { + w := &Weighted{size: n} + return w +} + +// Weighted provides a way to bound concurrent access to a resource. +// The callers can request access with a given weight. +type Weighted struct { + size int64 + cur int64 + mu sync.Mutex + waiters list.List +} + +// Acquire acquires the semaphore with a weight of n, blocking only until ctx +// is done. On success, returns nil. On failure, returns ctx.Err() and leaves +// the semaphore unchanged. +// +// If ctx is already done, Acquire may still succeed without blocking. +func (s *Weighted) Acquire(ctx context.Context, n int64) error { + s.mu.Lock() + if s.size-s.cur >= n && s.waiters.Len() == 0 { + s.cur += n + s.mu.Unlock() + return nil + } + + if n > s.size { + // Don't make other Acquire calls block on one that's doomed to fail. + s.mu.Unlock() + <-ctx.Done() + return ctx.Err() + } + + ready := make(chan struct{}) + w := waiter{n: n, ready: ready} + elem := s.waiters.PushBack(w) + s.mu.Unlock() + + select { + case <-ctx.Done(): + err := ctx.Err() + s.mu.Lock() + select { + case <-ready: + // Acquired the semaphore after we were canceled. Rather than trying to + // fix up the queue, just pretend we didn't notice the cancelation. + err = nil + default: + s.waiters.Remove(elem) + } + s.mu.Unlock() + return err + + case <-ready: + return nil + } +} + +// TryAcquire acquires the semaphore with a weight of n without blocking. +// On success, returns true. On failure, returns false and leaves the semaphore unchanged. +func (s *Weighted) TryAcquire(n int64) bool { + s.mu.Lock() + success := s.size-s.cur >= n && s.waiters.Len() == 0 + if success { + s.cur += n + } + s.mu.Unlock() + return success +} + +// Release releases the semaphore with a weight of n. +func (s *Weighted) Release(n int64) { + s.mu.Lock() + s.cur -= n + if s.cur < 0 { + s.mu.Unlock() + panic("semaphore: bad release") + } + for { + next := s.waiters.Front() + if next == nil { + break // No more waiters blocked. + } + + w := next.Value.(waiter) + if s.size-s.cur < w.n { + // Not enough tokens for the next waiter. We could keep going (to try to + // find a waiter with a smaller request), but under load that could cause + // starvation for large requests; instead, we leave all remaining waiters + // blocked. + // + // Consider a semaphore used as a read-write lock, with N tokens, N + // readers, and one writer. Each reader can Acquire(1) to obtain a read + // lock. The writer can Acquire(N) to obtain a write lock, excluding all + // of the readers. If we allow the readers to jump ahead in the queue, + // the writer will starve — there is always one token available for every + // reader. + break + } + + s.cur += w.n + s.waiters.Remove(next) + close(w.ready) + } + s.mu.Unlock() +}