Skip to content
This repository was archived by the owner on Feb 8, 2021. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions containerd/api/grpc/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,17 @@ func (s *apiServer) State(ctx context.Context, r *types.StateRequest) (*types.St
}

func (s *apiServer) UpdateContainer(ctx context.Context, r *types.UpdateContainerRequest) (*types.UpdateContainerResponse, error) {
return nil, errors.New("UpdateContainer() not implemented yet")
glog.V(3).Infof("gRPC handle UpdateContainer")

if r.Status != supervisor.ContainerStateDeleted {
return nil, fmt.Errorf("UpdateContainer() status %s not supported", r.Status)
}

err := s.sv.DeleteContainer(r.Id)
if err != nil {
return nil, err
}
return &types.UpdateContainerResponse{}, nil
}

func (s *apiServer) UpdateProcess(ctx context.Context, r *types.UpdateProcessRequest) (*types.UpdateProcessResponse, error) {
Expand Down Expand Up @@ -230,7 +240,7 @@ func supervisorContainer2ApiContainer(c *supervisor.Container) *types.Container
return &types.Container{
Id: c.Id,
BundlePath: c.BundlePath,
Status: "running",
Status: c.Status,
Runtime: "runv",
}
}
Expand Down
4 changes: 2 additions & 2 deletions containerd/containerd.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,9 +189,9 @@ func namespaceShare(sv *supervisor.Supervisor, namespace, state string) {
events := sv.Events.Events(time.Time{})
containerCount := 0
for e := range events {
if e.Type == supervisor.EventContainerStart {
if e.Type == supervisor.EventContainerCreate {
containerCount++
} else if e.Type == supervisor.EventExit && e.PID == "init" {
} else if e.Type == supervisor.EventContainerDelete {
containerCount--
if containerCount == 0 {
syscall.Kill(0, syscall.SIGQUIT)
Expand Down
52 changes: 52 additions & 0 deletions delete.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package main

import (
"fmt"
"os"
"path/filepath"

"github.com/hyperhq/runv/containerd/api/grpc/types"
"github.com/hyperhq/runv/supervisor"
"github.com/urfave/cli"
netcontext "golang.org/x/net/context"
)

var deleteCommand = cli.Command{
Name: "delete",
Usage: "delete a stopped container",
ArgsUsage: `<container-id>`,
Action: func(context *cli.Context) error {
container := context.Args().First()
if container == "" {
return cli.NewExitError("container id cannot be empty", -1)
}

containerPath := filepath.Join(context.GlobalString("root"), container)

if dir, err := os.Stat(containerPath); err != nil || !dir.IsDir() {
return fmt.Errorf("container %s does not exist", container)
}

api, err := getClient(filepath.Join(containerPath, "namespace/namespaced.sock"))
if err != nil {
return fmt.Errorf("failed to get client: %v", err)
}

_, err = api.GetServerVersion(netcontext.Background(), nil)
if err != nil {
// if we can't connect to the api, runv was killed before it could clean up the stopped containers
err := os.RemoveAll(containerPath)
if err != nil {
return fmt.Errorf("delete stale container %s failed, %v", container, err)
}
return nil
}

_, err = api.UpdateContainer(netcontext.Background(), &types.UpdateContainerRequest{Id: container, Status: supervisor.ContainerStateDeleted})
if err != nil {
return fmt.Errorf("delete container %s failed, %v", container, err)
}

return nil
},
}
4 changes: 2 additions & 2 deletions integration-test/kill_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ func (s *RunVSuite) TestKillKILL(c *check.C) {

timeout := true
for count := 0; count < 10; count++ {
out, exitCode := s.runvCommand(c, "list")
out, exitCode := s.runvCommand(c, "state", ctrName)
c.Assert(exitCode, checker.Equals, 0)
if !strings.Contains(out, ctrName) {
if !strings.Contains(out, "running") {
timeout = false
break
}
Expand Down
10 changes: 9 additions & 1 deletion list.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"text/tabwriter"
"time"

"github.com/hyperhq/runv/supervisor"
"github.com/opencontainers/runtime-spec/specs-go"
"github.com/urfave/cli"
)
Expand Down Expand Up @@ -110,15 +111,22 @@ func getContainers(context *cli.Context) ([]containerState, error) {
if err != nil && !os.IsNotExist(err) {
return nil, fmt.Errorf("Stat file %s error: %s", stateFile, err.Error())
}

state, err := loadStateFile(stateFile)
if err != nil {
return nil, fmt.Errorf("Load state file %s failed: %s", stateFile, err.Error())
}

status := supervisor.ContainerStateStopped // if we can't connect to runv-containerd then the container is stopped
if c, err := getContainerApi(context, item.Name()); err == nil {
status = c.Status
}

// FIXME: refactor to get container state only via API
s = append(s, containerState{
ID: state.ID,
InitProcessPid: state.Pid,
Status: "running",
Status: status,
Bundle: state.Bundle,
Created: fi.ModTime(),
})
Expand Down
1 change: 1 addition & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ func main() {
pauseCommand,
resumeCommand,
containerd.ContainerdCommand,
deleteCommand,
}
if err := app.Run(os.Args); err != nil {
fmt.Fprintf(os.Stderr, "%v", err)
Expand Down
9 changes: 8 additions & 1 deletion state.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"path/filepath"
"time"

"github.com/hyperhq/runv/supervisor"
"github.com/urfave/cli"
)

Expand Down Expand Up @@ -79,11 +80,17 @@ func getContainer(context *cli.Context, name string) (*cState, error) {
return nil, fmt.Errorf("Load state file %s failed: %s", stateFile, err.Error())
}

status := supervisor.ContainerStateStopped // if we can't connect to runv-containerd then the container is stopped
if c, err := getContainerApi(context, name); err == nil {
status = c.Status
}

// FIXME: refactor to get container state only via API
s := &cState{
Version: state.Version,
ID: state.ID,
InitProcessPid: state.Pid,
Status: "running",
Status: status,
Bundle: state.Bundle,
Rootfs: filepath.Join(state.Bundle, "rootfs"),
Created: fi.ModTime(),
Expand Down
28 changes: 28 additions & 0 deletions supervisor/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,18 @@ import (
"github.com/opencontainers/runtime-spec/specs-go"
)

// container states
const (
ContainerStateCreating = "creating"
ContainerStateCreated = "created"
ContainerStateRunning = "running"
ContainerStateStopped = "stopped"
ContainerStateDeleted = "deleted" // special state that will lead to deleting the container resources
)

type Container struct {
Id string
Status string
BundlePath string
Spec *specs.Spec
Processes map[string]*Process
Expand Down Expand Up @@ -50,6 +60,7 @@ func (c *Container) start(p *Process) error {
}

go func() {
c.Status = ContainerStateRunning
e := Event{
ID: c.Id,
Type: EventContainerStart,
Expand All @@ -58,6 +69,7 @@ func (c *Container) start(p *Process) error {
c.ownerPod.sv.Events.notifySubscribers(e)

exit, err := c.wait(p, res)
c.Status = ContainerStateStopped
e = Event{
ID: c.Id,
Type: EventExit,
Expand All @@ -75,6 +87,7 @@ func (c *Container) start(p *Process) error {
}

func (c *Container) create() error {
c.Status = ContainerStateCreating
glog.V(3).Infof("prepare hypervisor info")
config := api.ContainerDescriptionFromOCF(c.Id, c.Spec)

Expand Down Expand Up @@ -182,6 +195,14 @@ func (c *Container) create() error {
return err
}

c.Status = ContainerStateCreated
e := Event{
ID: c.Id,
Type: EventContainerCreate,
Timestamp: time.Now(),
}
c.ownerPod.sv.Events.notifySubscribers(e)

return nil
}

Expand Down Expand Up @@ -354,6 +375,13 @@ func (c *Container) reap() {
utils.Umount(containerRoot)
os.RemoveAll(containerRoot)
os.RemoveAll(filepath.Join(c.ownerPod.sv.StateDir, c.Id))

e := Event{
ID: c.Id,
Type: EventContainerDelete,
Timestamp: time.Now(),
}
c.ownerPod.sv.Events.notifySubscribers(e)
}

func mountToRootfs(m *specs.Mount, rootfs, mountLabel string) error {
Expand Down
8 changes: 5 additions & 3 deletions supervisor/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ import (
)

const (
EventExit = "exit"
EventContainerStart = "start-container"
EventProcessStart = "start-process"
EventExit = "exit"
EventContainerCreate = "create-container"
EventContainerStart = "start-container"
EventContainerDelete = "delete-container"
EventProcessStart = "start-process"
)

var (
Expand Down
28 changes: 20 additions & 8 deletions supervisor/supervisor.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,26 @@ func (sv *Supervisor) StartContainer(container string, spec *specs.Spec) (c *Con
return nil, nil, fmt.Errorf("container %s is not found for StartContainer()", container)
}

func (sv *Supervisor) DeleteContainer(container string) error {
glog.Infof("delete container %s", container)
sv.Lock()
defer sv.Unlock()

if c, ok := sv.Containers[container]; ok {
c.reap()
delete(c.ownerPod.Containers, container)
delete(sv.Containers, container)

if len(c.ownerPod.Containers) == 0 {
c.ownerPod.reap()
}

return nil
}

return fmt.Errorf("Container %s not found", container)
}

func (sv *Supervisor) AddProcess(container, processId, stdin, stdout, stderr string, spec *specs.Process) (*Process, error) {
sv.Lock()
defer sv.Unlock()
Expand Down Expand Up @@ -164,14 +184,6 @@ func (sv *Supervisor) reap(container, processId string) {
// TODO: kill all the other existing processes in the same container
}
}
if len(c.Processes) == 0 {
c.reap()
delete(c.ownerPod.Containers, container)
delete(sv.Containers, container)
}
if len(c.ownerPod.Containers) == 0 {
c.ownerPod.reap()
}
}
}

Expand Down