diff --git a/src/runtime/virtcontainers/api.go b/src/runtime/virtcontainers/api.go index 7ebe35b653..9efdff3c72 100644 --- a/src/runtime/virtcontainers/api.go +++ b/src/runtime/virtcontainers/api.go @@ -7,19 +7,13 @@ package virtcontainers import ( "context" - "os" "runtime" - "syscall" deviceApi "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/device/api" deviceConfig "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/device/config" - "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/persist" - pbTypes "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/agent/protocols" "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/cgroups" "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/compatoci" vcTypes "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/types" - "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/types" - specs "github.com/opencontainers/runtime-spec/specs-go" opentracing "github.com/opentracing/opentracing-go" "github.com/sirupsen/logrus" ) @@ -138,766 +132,7 @@ func createSandboxFromConfig(ctx context.Context, sandboxConfig SandboxConfig, f return s, nil } -// DeleteSandbox is the virtcontainers sandbox deletion entry point. -// DeleteSandbox will stop an already running container and then delete it. -func DeleteSandbox(ctx context.Context, sandboxID string) (VCSandbox, error) { - span, ctx := trace(ctx, "DeleteSandbox") - defer span.Finish() - - if sandboxID == "" { - return nil, vcTypes.ErrNeedSandboxID - } - - unlock, err := rwLockSandbox(sandboxID) - if err != nil { - return nil, err - } - defer unlock() - - // Fetch the sandbox from storage and create it. - s, err := fetchSandbox(ctx, sandboxID) - if err != nil { - return nil, err - } - - // Delete it. - if err := s.Delete(); err != nil { - return nil, err - } - - return s, nil -} - -// FetchSandbox is the virtcontainers sandbox fetching entry point. -// FetchSandbox will find out and connect to an existing sandbox and -// return the sandbox structure. The caller is responsible of calling -// VCSandbox.Release() after done with it. -func FetchSandbox(ctx context.Context, sandboxID string) (VCSandbox, error) { - span, ctx := trace(ctx, "FetchSandbox") - defer span.Finish() - - if sandboxID == "" { - return nil, vcTypes.ErrNeedSandboxID - } - - unlock, err := rwLockSandbox(sandboxID) - if err != nil { - return nil, err - } - defer unlock() - - // Fetch the sandbox from storage and create it. - s, err := fetchSandbox(ctx, sandboxID) - if err != nil { - return nil, err - } - - return s, nil -} - -// StartSandbox is the virtcontainers sandbox starting entry point. -// StartSandbox will talk to the given hypervisor to start an existing -// sandbox and all its containers. -// It returns the sandbox ID. -func StartSandbox(ctx context.Context, sandboxID string) (VCSandbox, error) { - span, ctx := trace(ctx, "StartSandbox") - defer span.Finish() - - if sandboxID == "" { - return nil, vcTypes.ErrNeedSandboxID - } - - unlock, err := rwLockSandbox(sandboxID) - if err != nil { - return nil, err - } - defer unlock() - - // Fetch the sandbox from storage and create it. - s, err := fetchSandbox(ctx, sandboxID) - if err != nil { - return nil, err - } - - // Start it - err = s.Start() - if err != nil { - return nil, err - } - - if err = s.storeSandbox(); err != nil { - return nil, err - } - - return s, nil -} - -// StopSandbox is the virtcontainers sandbox stopping entry point. -// StopSandbox will talk to the given agent to stop an existing sandbox and destroy all containers within that sandbox. -func StopSandbox(ctx context.Context, sandboxID string, force bool) (VCSandbox, error) { - span, ctx := trace(ctx, "StopSandbox") - defer span.Finish() - - if sandboxID == "" { - return nil, vcTypes.ErrNeedSandbox - } - - unlock, err := rwLockSandbox(sandboxID) - if err != nil { - return nil, err - } - defer unlock() - - // Fetch the sandbox from storage and create it. - s, err := fetchSandbox(ctx, sandboxID) - if err != nil { - return nil, err - } - - // Stop it. - err = s.Stop(force) - if err != nil { - return nil, err - } - - if err = s.storeSandbox(); err != nil { - return nil, err - } - - return s, nil -} - -// RunSandbox is the virtcontainers sandbox running entry point. -// RunSandbox creates a sandbox and its containers and then it starts them. -func RunSandbox(ctx context.Context, sandboxConfig SandboxConfig, factory Factory) (VCSandbox, error) { - span, ctx := trace(ctx, "RunSandbox") - defer span.Finish() - - // Create the sandbox - s, err := createSandboxFromConfig(ctx, sandboxConfig, factory) - if err != nil { - return nil, err - } - - unlock, err := rwLockSandbox(s.id) - if err != nil { - return nil, err - } - defer unlock() - - // Start the sandbox - err = s.Start() - if err != nil { - return nil, err - } - - return s, nil -} - -// ListSandbox is the virtcontainers sandbox listing entry point. -func ListSandbox(ctx context.Context) ([]SandboxStatus, error) { - span, ctx := trace(ctx, "ListSandbox") - defer span.Finish() - - store, err := persist.GetDriver() - if err != nil { - return []SandboxStatus{}, err - } - - dir, err := os.Open(store.RunStoragePath()) - if err != nil { - if os.IsNotExist(err) { - // No sandbox directory is not an error - return []SandboxStatus{}, nil - } - return []SandboxStatus{}, err - } - - defer dir.Close() - - sandboxesID, err := dir.Readdirnames(0) - if err != nil { - return []SandboxStatus{}, err - } - - var sandboxStatusList []SandboxStatus - - for _, sandboxID := range sandboxesID { - sandboxStatus, err := StatusSandbox(ctx, sandboxID) - if err != nil { - continue - } - - sandboxStatusList = append(sandboxStatusList, sandboxStatus) - } - - return sandboxStatusList, nil -} - -// StatusSandbox is the virtcontainers sandbox status entry point. -func StatusSandbox(ctx context.Context, sandboxID string) (SandboxStatus, error) { - span, ctx := trace(ctx, "StatusSandbox") - defer span.Finish() - - if sandboxID == "" { - return SandboxStatus{}, vcTypes.ErrNeedSandboxID - } - - unlock, err := rwLockSandbox(sandboxID) - if err != nil { - return SandboxStatus{}, err - } - defer unlock() - - s, err := fetchSandbox(ctx, sandboxID) - if err != nil { - return SandboxStatus{}, err - } - - var contStatusList []ContainerStatus - for _, container := range s.containers { - contStatus, err := statusContainer(s, container.id) - if err != nil { - return SandboxStatus{}, err - } - - contStatusList = append(contStatusList, contStatus) - } - - sandboxStatus := SandboxStatus{ - ID: s.id, - State: s.state, - Hypervisor: s.config.HypervisorType, - HypervisorConfig: s.config.HypervisorConfig, - ContainersStatus: contStatusList, - Annotations: s.config.Annotations, - } - - return sandboxStatus, nil -} - -// CreateContainer is the virtcontainers container creation entry point. -// CreateContainer creates a container on a given sandbox. -func CreateContainer(ctx context.Context, sandboxID string, containerConfig ContainerConfig) (VCSandbox, VCContainer, error) { - span, ctx := trace(ctx, "CreateContainer") - defer span.Finish() - - if sandboxID == "" { - return nil, nil, vcTypes.ErrNeedSandboxID - } - - unlock, err := rwLockSandbox(sandboxID) - if err != nil { - return nil, nil, err - } - defer unlock() - - s, err := fetchSandbox(ctx, sandboxID) - if err != nil { - return nil, nil, err - } - - c, err := s.CreateContainer(containerConfig) - if err != nil { - return nil, nil, err - } - - if err = s.storeSandbox(); err != nil { - return nil, nil, err - } - - return s, c, nil -} - -// DeleteContainer is the virtcontainers container deletion entry point. -// DeleteContainer deletes a Container from a Sandbox. If the container is running, -// it needs to be stopped first. -func DeleteContainer(ctx context.Context, sandboxID, containerID string) (VCContainer, error) { - span, ctx := trace(ctx, "DeleteContainer") - defer span.Finish() - - if sandboxID == "" { - return nil, vcTypes.ErrNeedSandboxID - } - - if containerID == "" { - return nil, vcTypes.ErrNeedContainerID - } - - unlock, err := rwLockSandbox(sandboxID) - if err != nil { - return nil, err - } - defer unlock() - - s, err := fetchSandbox(ctx, sandboxID) - if err != nil { - return nil, err - } - - return s.DeleteContainer(containerID) -} - -// StartContainer is the virtcontainers container starting entry point. -// StartContainer starts an already created container. -func StartContainer(ctx context.Context, sandboxID, containerID string) (VCContainer, error) { - span, ctx := trace(ctx, "StartContainer") - defer span.Finish() - - if sandboxID == "" { - return nil, vcTypes.ErrNeedSandboxID - } - - if containerID == "" { - return nil, vcTypes.ErrNeedContainerID - } - - unlock, err := rwLockSandbox(sandboxID) - if err != nil { - return nil, err - } - defer unlock() - - s, err := fetchSandbox(ctx, sandboxID) - if err != nil { - return nil, err - } - - return s.StartContainer(containerID) -} - -// StopContainer is the virtcontainers container stopping entry point. -// StopContainer stops an already running container. -func StopContainer(ctx context.Context, sandboxID, containerID string) (VCContainer, error) { - span, ctx := trace(ctx, "StopContainer") - defer span.Finish() - - if sandboxID == "" { - return nil, vcTypes.ErrNeedSandboxID - } - - if containerID == "" { - return nil, vcTypes.ErrNeedContainerID - } - - unlock, err := rwLockSandbox(sandboxID) - if err != nil { - return nil, err - } - defer unlock() - - s, err := fetchSandbox(ctx, sandboxID) - if err != nil { - return nil, err - } - - return s.StopContainer(containerID, false) -} - -// EnterContainer is the virtcontainers container command execution entry point. -// EnterContainer enters an already running container and runs a given command. -func EnterContainer(ctx context.Context, sandboxID, containerID string, cmd types.Cmd) (VCSandbox, VCContainer, *Process, error) { - span, ctx := trace(ctx, "EnterContainer") - defer span.Finish() - - if sandboxID == "" { - return nil, nil, nil, vcTypes.ErrNeedSandboxID - } - - if containerID == "" { - return nil, nil, nil, vcTypes.ErrNeedContainerID - } - - unlock, err := rLockSandbox(sandboxID) - if err != nil { - return nil, nil, nil, err - } - defer unlock() - - s, err := fetchSandbox(ctx, sandboxID) - if err != nil { - return nil, nil, nil, err - } - - c, process, err := s.EnterContainer(containerID, cmd) - if err != nil { - return nil, nil, nil, err - } - - return s, c, process, nil -} - -// StatusContainer is the virtcontainers container status entry point. -// StatusContainer returns a detailed container status. -func StatusContainer(ctx context.Context, sandboxID, containerID string) (ContainerStatus, error) { - span, ctx := trace(ctx, "StatusContainer") - defer span.Finish() - - if sandboxID == "" { - return ContainerStatus{}, vcTypes.ErrNeedSandboxID - } - - if containerID == "" { - return ContainerStatus{}, vcTypes.ErrNeedContainerID - } - - unlock, err := rwLockSandbox(sandboxID) - if err != nil { - return ContainerStatus{}, err - } - defer unlock() - - s, err := fetchSandbox(ctx, sandboxID) - if err != nil { - return ContainerStatus{}, err - } - - return statusContainer(s, containerID) -} - -func statusContainer(sandbox *Sandbox, containerID string) (ContainerStatus, error) { - if container, ok := sandbox.containers[containerID]; ok { - return ContainerStatus{ - ID: container.id, - State: container.state, - PID: container.process.Pid, - StartTime: container.process.StartTime, - RootFs: container.config.RootFs.Target, - Spec: container.GetPatchedOCISpec(), - Annotations: container.config.Annotations, - }, nil - } - - // No matching containers in the sandbox - return ContainerStatus{}, nil -} - -// KillContainer is the virtcontainers entry point to send a signal -// to a container running inside a sandbox. If all is true, all processes in -// the container will be sent the signal. -func KillContainer(ctx context.Context, sandboxID, containerID string, signal syscall.Signal, all bool) error { - span, ctx := trace(ctx, "KillContainer") - defer span.Finish() - - if sandboxID == "" { - return vcTypes.ErrNeedSandboxID - } - - if containerID == "" { - return vcTypes.ErrNeedContainerID - } - - unlock, err := rwLockSandbox(sandboxID) - if err != nil { - return err - } - defer unlock() - - s, err := fetchSandbox(ctx, sandboxID) - if err != nil { - return err - } - - return s.KillContainer(containerID, signal, all) -} - -// ProcessListContainer is the virtcontainers entry point to list -// processes running inside a container -func ProcessListContainer(ctx context.Context, sandboxID, containerID string, options ProcessListOptions) (ProcessList, error) { - span, ctx := trace(ctx, "ProcessListContainer") - defer span.Finish() - - if sandboxID == "" { - return nil, vcTypes.ErrNeedSandboxID - } - - if containerID == "" { - return nil, vcTypes.ErrNeedContainerID - } - - unlock, err := rLockSandbox(sandboxID) - if err != nil { - return nil, err - } - defer unlock() - - s, err := fetchSandbox(ctx, sandboxID) - if err != nil { - return nil, err - } - - return s.ProcessListContainer(containerID, options) -} - -// UpdateContainer is the virtcontainers entry point to update -// container's resources. -func UpdateContainer(ctx context.Context, sandboxID, containerID string, resources specs.LinuxResources) error { - span, ctx := trace(ctx, "UpdateContainer") - defer span.Finish() - - if sandboxID == "" { - return vcTypes.ErrNeedSandboxID - } - - if containerID == "" { - return vcTypes.ErrNeedContainerID - } - - unlock, err := rwLockSandbox(sandboxID) - if err != nil { - return err - } - defer unlock() - - s, err := fetchSandbox(ctx, sandboxID) - if err != nil { - return err - } - - return s.UpdateContainer(containerID, resources) -} - -// StatsContainer is the virtcontainers container stats entry point. -// StatsContainer returns a detailed container stats. -func StatsContainer(ctx context.Context, sandboxID, containerID string) (ContainerStats, error) { - span, ctx := trace(ctx, "StatsContainer") - defer span.Finish() - - if sandboxID == "" { - return ContainerStats{}, vcTypes.ErrNeedSandboxID - } - - if containerID == "" { - return ContainerStats{}, vcTypes.ErrNeedContainerID - } - - unlock, err := rLockSandbox(sandboxID) - if err != nil { - return ContainerStats{}, err - } - defer unlock() - - s, err := fetchSandbox(ctx, sandboxID) - if err != nil { - return ContainerStats{}, err - } - - return s.StatsContainer(containerID) -} - -// StatsSandbox is the virtcontainers sandbox stats entry point. -// StatsSandbox returns a detailed sandbox stats. -func StatsSandbox(ctx context.Context, sandboxID string) (SandboxStats, []ContainerStats, error) { - span, ctx := trace(ctx, "StatsSandbox") - defer span.Finish() - - if sandboxID == "" { - return SandboxStats{}, []ContainerStats{}, vcTypes.ErrNeedSandboxID - } - - unlock, err := rLockSandbox(sandboxID) - if err != nil { - return SandboxStats{}, []ContainerStats{}, err - } - defer unlock() - - s, err := fetchSandbox(ctx, sandboxID) - if err != nil { - return SandboxStats{}, []ContainerStats{}, err - } - - sandboxStats, err := s.Stats() - if err != nil { - return SandboxStats{}, []ContainerStats{}, err - } - - containerStats := []ContainerStats{} - for _, c := range s.containers { - cstats, err := s.StatsContainer(c.id) - if err != nil { - return SandboxStats{}, []ContainerStats{}, err - } - containerStats = append(containerStats, cstats) - } - - return sandboxStats, containerStats, nil -} - -func togglePauseContainer(ctx context.Context, sandboxID, containerID string, pause bool) error { - if sandboxID == "" { - return vcTypes.ErrNeedSandboxID - } - - if containerID == "" { - return vcTypes.ErrNeedContainerID - } - - unlock, err := rwLockSandbox(sandboxID) - if err != nil { - return err - } - defer unlock() - - s, err := fetchSandbox(ctx, sandboxID) - if err != nil { - return err - } - - if pause { - return s.PauseContainer(containerID) - } - - return s.ResumeContainer(containerID) -} - -// PauseContainer is the virtcontainers container pause entry point. -func PauseContainer(ctx context.Context, sandboxID, containerID string) error { - span, ctx := trace(ctx, "PauseContainer") - defer span.Finish() - - return togglePauseContainer(ctx, sandboxID, containerID, true) -} - -// ResumeContainer is the virtcontainers container resume entry point. -func ResumeContainer(ctx context.Context, sandboxID, containerID string) error { - span, ctx := trace(ctx, "ResumeContainer") - defer span.Finish() - - return togglePauseContainer(ctx, sandboxID, containerID, false) -} - -// AddDevice will add a device to sandbox -func AddDevice(ctx context.Context, sandboxID string, info deviceConfig.DeviceInfo) (deviceApi.Device, error) { - span, ctx := trace(ctx, "AddDevice") - defer span.Finish() - - if sandboxID == "" { - return nil, vcTypes.ErrNeedSandboxID - } - - unlock, err := rwLockSandbox(sandboxID) - if err != nil { - return nil, err - } - defer unlock() - - s, err := fetchSandbox(ctx, sandboxID) - if err != nil { - return nil, err - } - - return s.AddDevice(info) -} - -func toggleInterface(ctx context.Context, sandboxID string, inf *pbTypes.Interface, add bool) (*pbTypes.Interface, error) { - if sandboxID == "" { - return nil, vcTypes.ErrNeedSandboxID - } - - unlock, err := rwLockSandbox(sandboxID) - if err != nil { - return nil, err - } - defer unlock() - - s, err := fetchSandbox(ctx, sandboxID) - if err != nil { - return nil, err - } - - if add { - return s.AddInterface(inf) - } - - return s.RemoveInterface(inf) -} - -// AddInterface is the virtcontainers add interface entry point. -func AddInterface(ctx context.Context, sandboxID string, inf *pbTypes.Interface) (*pbTypes.Interface, error) { - span, ctx := trace(ctx, "AddInterface") - defer span.Finish() - - return toggleInterface(ctx, sandboxID, inf, true) -} - -// RemoveInterface is the virtcontainers remove interface entry point. -func RemoveInterface(ctx context.Context, sandboxID string, inf *pbTypes.Interface) (*pbTypes.Interface, error) { - span, ctx := trace(ctx, "RemoveInterface") - defer span.Finish() - - return toggleInterface(ctx, sandboxID, inf, false) -} - -// ListInterfaces is the virtcontainers list interfaces entry point. -func ListInterfaces(ctx context.Context, sandboxID string) ([]*pbTypes.Interface, error) { - span, ctx := trace(ctx, "ListInterfaces") - defer span.Finish() - - if sandboxID == "" { - return nil, vcTypes.ErrNeedSandboxID - } - - unlock, err := rLockSandbox(sandboxID) - if err != nil { - return nil, err - } - defer unlock() - - s, err := fetchSandbox(ctx, sandboxID) - if err != nil { - return nil, err - } - - return s.ListInterfaces() -} - -// UpdateRoutes is the virtcontainers update routes entry point. -func UpdateRoutes(ctx context.Context, sandboxID string, routes []*pbTypes.Route) ([]*pbTypes.Route, error) { - span, ctx := trace(ctx, "UpdateRoutes") - defer span.Finish() - - if sandboxID == "" { - return nil, vcTypes.ErrNeedSandboxID - } - - unlock, err := rwLockSandbox(sandboxID) - if err != nil { - return nil, err - } - defer unlock() - - s, err := fetchSandbox(ctx, sandboxID) - if err != nil { - return nil, err - } - - return s.UpdateRoutes(routes) -} - -// ListRoutes is the virtcontainers list routes entry point. -func ListRoutes(ctx context.Context, sandboxID string) ([]*pbTypes.Route, error) { - span, ctx := trace(ctx, "ListRoutes") - defer span.Finish() - - if sandboxID == "" { - return nil, vcTypes.ErrNeedSandboxID - } - - unlock, err := rLockSandbox(sandboxID) - if err != nil { - return nil, err - } - defer unlock() - - s, err := fetchSandbox(ctx, sandboxID) - if err != nil { - return nil, err - } - - return s.ListRoutes() -} - -// CleanupContaienr is used by shimv2 to stop and delete a container exclusively, once there is no container +// CleanupContainer is used by shimv2 to stop and delete a container exclusively, once there is no container // in the sandbox left, do stop the sandbox and delete it. Those serial operations will be done exclusively by // locking the sandbox. func CleanupContainer(ctx context.Context, sandboxID, containerID string, force bool) error { diff --git a/src/runtime/virtcontainers/implementation.go b/src/runtime/virtcontainers/implementation.go index dc2ee0aaa5..177797ebd2 100644 --- a/src/runtime/virtcontainers/implementation.go +++ b/src/runtime/virtcontainers/implementation.go @@ -35,7 +35,7 @@ func (impl *VCImpl) CreateSandbox(ctx context.Context, sandboxConfig SandboxConf return CreateSandbox(ctx, sandboxConfig, impl.factory) } -// CleanupContaienr is used by shimv2 to stop and delete a container exclusively, once there is no container +// CleanupContainer is used by shimv2 to stop and delete a container exclusively, once there is no container // in the sandbox left, do stop the sandbox and delete it. Those serial operations will be done exclusively by // locking the sandbox. func (impl *VCImpl) CleanupContainer(ctx context.Context, sandboxID, containerID string, force bool) error {