Skip to content
This repository was archived by the owner on Feb 8, 2021. It is now read-only.

Support for deleting container #371

Closed
wants to merge 3 commits into from
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
1 change: 1 addition & 0 deletions client/api/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ type APIInterface interface {
ContainerLogs(container, since string, timestamp, follow, stdout, stderr bool, tail string) (io.ReadCloser, string, error)
KillContainer(container string, sig int) error
StopContainer(container string) error
RemoveContainer(container string) error

GetPodInfo(podName string) (*types.PodInfo, error)
CreatePod(spec interface{}) (string, int, error)
Expand Down
10 changes: 10 additions & 0 deletions client/api/rm.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,13 @@ func (cli *Client) RmPod(id string) error {
}
return nil
}

func (cli *Client) RemoveContainer(id string) error {
v := url.Values{}
v.Set("container", id)
_, _, err := readBody(cli.call("DELETE", "/container?"+v.Encode(), nil, nil))
if err != nil {
return err
}
return nil
}
36 changes: 26 additions & 10 deletions client/rm.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@ import (
)

func (cli *HyperClient) HyperCmdRm(args ...string) error {
var parser = gflag.NewParser(nil, gflag.Default)
parser.Usage = "rm POD [POD...]\n\nRemove one or more pods"
var opts struct {
Container bool `short:"c" long:"container" default:"false" default-mask:"-" description:"rm container"`
}
var parser = gflag.NewParser(&opts, gflag.Default)
parser.Usage = "rm POD [POD...] | CONTAINER [CONTAINER...]\n\nRemove one or more pods | containers"
args, err := parser.ParseArgs(args)
if err != nil {
if !strings.Contains(err.Error(), "Usage") {
Expand All @@ -19,15 +22,28 @@ func (cli *HyperClient) HyperCmdRm(args ...string) error {
}
}
if len(args) == 0 {
return fmt.Errorf("\"rm\" requires a minimum of 1 argument, please provide POD ID.\n")
return fmt.Errorf("\"rm\" requires a minimum of 1 argument, please provide POD | CONTAINER ID.\n")
}
pods := args
for _, id := range pods {
err := cli.client.RmPod(id)
if err == nil {
fmt.Fprintf(cli.out, "Pod(%s) is successful to be deleted!\n", id)
} else {
fmt.Fprintf(cli.out, "%v\n", err)

if opts.Container {
containers := args
for _, id := range containers {
err := cli.client.RemoveContainer(id)
if err == nil {
fmt.Fprintf(cli.out, "Container(%s) is successful to be deleted!\n", id)
} else {
fmt.Fprintf(cli.out, "%v\n", err)
}
}
} else {
pods := args
for _, id := range pods {
err := cli.client.RmPod(id)
if err == nil {
fmt.Fprintf(cli.out, "Pod(%s) is successful to be deleted!\n", id)
} else {
fmt.Fprintf(cli.out, "%v\n", err)
}
}
}
return nil
Expand Down
79 changes: 79 additions & 0 deletions daemon/rm.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package daemon

import (
"encoding/json"
"fmt"
"os"
"path"
"strings"

"github.com/docker/docker/pkg/version"
dockertypes "github.com/docker/engine-api/types"
"github.com/golang/glog"
"github.com/hyperhq/hyperd/utils"
Expand Down Expand Up @@ -74,3 +77,79 @@ func (daemon *Daemon) RemovePodContainer(p *Pod) {
}
daemon.db.DeleteP2C(p.Id)
}

func (daemon *Daemon) RemoveContainer(containerId string) error {
pod, idx, ok := daemon.PodList.GetByContainerIdOrName(containerId)
if !ok {
return fmt.Errorf("can not find container %s", containerId)
}

if !pod.TransitionLock("rm") {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pod.TransitionLock("rmContainer")

glog.Errorf("Pod %s is under other operation", pod.Id)
return fmt.Errorf("Pod %s is under other operation", pod.Id)
}
defer pod.TransitionUnlock("rm")

if pod.PodStatus.Status == types.S_POD_RUNNING {
if pod.PodStatus.Containers[idx].Status == types.S_POD_RUNNING {
return fmt.Errorf("Container %s is still running, stop it first", containerId)
}
if err := pod.VM.RemoveContainer(containerId); err != nil {
return err
}
}

pod.Lock()
defer pod.Unlock()

pod.Status().DeleteContainer(containerId)

daemon.PodList.Put(pod)
if err := daemon.WritePodAndContainers(pod.Id); err != nil {
glog.Errorf("Found an error while saving the Containers info: %v", err)
return err
}

r, err := daemon.ContainerInspect(containerId, false, version.Version("1.21"))
if err != nil {
return err
}

if err := daemon.Daemon.ContainerRm(containerId, &dockertypes.ContainerRmConfig{}); err != nil {
return err
}

rsp, ok := r.(*dockertypes.ContainerJSON)
if !ok {
return fmt.Errorf("fail to unpack container json response for %s of %s", containerId, pod.Id)
}
name := strings.TrimLeft(rsp.Name, "/")
for i, c := range pod.Spec.Containers {
if name == c.Name {
pod.Spec.Containers = append(pod.Spec.Containers[:i], pod.Spec.Containers[i+1:]...)
break
}
}
podSpec, err := json.Marshal(pod.Spec)
if err != nil {
glog.Errorf("Marshal podspec %v failed: %v", pod.Spec, err)
return err
}
if err = daemon.db.UpdatePod(pod.Id, podSpec); err != nil {
glog.Errorf("Found an error while saving the POD file: %v", err)
return err
}

jsons, err := pod.TryLoadContainers(daemon)
if err != nil {
return err
}
if err = pod.ParseContainerJsons(daemon, jsons); err != nil {
glog.Errorf("Found an error while parsing the Containers json: %v", err)
return err
}

daemon.PodList.Put(pod)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need to put pod twice.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's necessary.The first time before "daemon.WritePodAndContainers(pod.Id)", we need put pod to update pod status.Then the spec of pod also being changed,so we need to update again to keep pod fresh.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

podlist.Put updates the containers array in podlist while daemon.WritePodAndContainers uses podstatus.Containers to updates the database, the podstatus.Containers was already updated.


return nil
}
10 changes: 10 additions & 0 deletions daemon/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,16 @@ func (daemon *Daemon) CmdExitCode(containerId, execId string) (int, error) {
return daemon.ExitCode(containerId, execId)
}

func (daemon *Daemon) CmdDeleteContainer(name string) (*engine.Env, error) {
err := daemon.RemoveContainer(name)
if err != nil {
glog.Errorf("fail to remove container %s: %v", name, err)
return nil, err
}
v := &engine.Env{}
return v, nil
}

func (daemon *Daemon) CmdSystemInfo() (*apitypes.InfoResponse, error) {
sys, err := daemon.Daemon.SystemInfo()
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions server/router/container/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ type Backend interface {
CmdCreateContainer(podId string, containerArgs []byte) (string, error)
CmdKillContainer(name string, sig int64) (*engine.Env, error)
CmdStopContainer(name string) (*engine.Env, error)
CmdDeleteContainer(name string) (*engine.Env, error)
CmdContainerRename(oldName, newName string) (*engine.Env, error)
CmdAttach(in io.ReadCloser, out io.WriteCloser, id string) error
CmdCommitImage(name string, cfg *types.ContainerCommitConfig) (*engine.Env, error)
Expand Down
1 change: 1 addition & 0 deletions server/router/container/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,6 @@ func (r *containerRouter) initRoutes() {
local.NewPostRoute("/tty/resize", r.postTtyResize),
// PUT
// DELETE
local.NewDeleteRoute("/container", r.deleteContainer),
}
}
14 changes: 14 additions & 0 deletions server/router/container/container_routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,20 @@ func (c *containerRouter) postContainerStop(ctx context.Context, w http.Response
return env.WriteJSON(w, http.StatusCreated)
}

func (c *containerRouter) deleteContainer(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if err := httputils.ParseForm(r); err != nil {
return err
}

cname := r.Form.Get("container")
env, err := c.backend.CmdDeleteContainer(cname)
if err != nil {
return err
}

return env.WriteJSON(w, http.StatusOK)
}

func (c *containerRouter) postContainerCommit(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if err := httputils.ParseForm(r); err != nil {
return err
Expand Down
13 changes: 13 additions & 0 deletions serverrpc/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,16 @@ func (s *ServerRPC) ContainerStop(c context.Context, req *types.ContainerStopReq

return &types.ContainerStopResponse{}, nil
}

// ContainerRemove deletes the specified container
func (s *ServerRPC) ContainerRemove(c context.Context, req *types.ContainerRemoveRequest) (*types.ContainerRemoveResponse, error) {
glog.V(3).Infof("ContainerRemove with request %v", req.String())

err := s.daemon.RemoveContainer(req.ContainerID)
if err != nil {
glog.Errorf("ContainerRemove error: %v", err)
return nil, err
}

return &types.ContainerRemoveResponse{}, nil
}
48 changes: 48 additions & 0 deletions types/types.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions types/types.proto
Original file line number Diff line number Diff line change
Expand Up @@ -707,6 +707,14 @@ message PodStatsResponse {
PodStats podStats = 1;
}

message ContainerRemoveRequest {
string containerID = 1;
}

message ContainerRemoveResponse {

}

// PublicAPI defines the public APIs which are handled over TCP sockets.
service PublicAPI {
// PodList gets a list of pods
Expand Down Expand Up @@ -763,6 +771,8 @@ service PublicAPI {
rpc ExecCreate(ExecCreateRequest) returns (ExecCreateResponse) {}
// ExecStart starts exec
rpc ExecStart(stream ExecStartRequest) returns (stream ExecStartResponse) {}
// ContainerRemove deletes the specified container
rpc ContainerRemove(ContainerRemoveRequest) returns (ContainerRemoveResponse) {}
// Attach attaches to the specified container
rpc Attach(stream AttachMessage) returns (stream AttachMessage) {}
// Wait gets the exit code of the specified container
Expand Down