Merge pull request #7452 from shykes/7370-on-7427

Cleanup: move image management and logging out of deprecated Server
This commit is contained in:
Solomon Hykes
2014-08-06 18:47:45 -07:00
33 changed files with 1170 additions and 1100 deletions

View File

@@ -168,6 +168,13 @@ func (container *Container) WriteHostConfig() error {
return ioutil.WriteFile(pth, data, 0666)
}
func (container *Container) LogEvent(action string) {
d := container.daemon
if err := d.eng.Job("log", action, container.ID, d.Repositories().ImageName(container.Image)).Run(); err != nil {
utils.Errorf("Error running container: %s", err)
}
}
func (container *Container) getResourcePath(path string) (string, error) {
cleanPath := filepath.Join("/", path)
return symlink.FollowSymlinkInScope(filepath.Join(container.basefs, cleanPath), container.basefs)
@@ -508,7 +515,7 @@ func (container *Container) monitor(callback execdriver.StartCallback) error {
container.stdin, container.stdinPipe = io.Pipe()
}
if container.daemon != nil && container.daemon.srv != nil {
container.daemon.srv.LogEvent("die", container.ID, container.daemon.repositories.ImageName(container.Image))
container.LogEvent("die")
}
if container.daemon != nil && container.daemon.srv != nil && container.daemon.srv.IsRunning() {
// FIXME: here is race condition between two RUN instructions in Dockerfile

View File

@@ -40,7 +40,7 @@ func (daemon *Daemon) ContainerCreate(job *engine.Job) engine.Status {
if !container.Config.NetworkDisabled && daemon.SystemConfig().IPv4ForwardingDisabled {
job.Errorf("IPv4 forwarding is disabled.\n")
}
job.Eng.Job("log", "create", container.ID, daemon.Repositories().ImageName(container.Image)).Run()
container.LogEvent("create")
// FIXME: this is necessary because daemon.Create might return a nil container
// with a non-nil error. This should not happen! Once it's fixed we
// can remove this workaround.

View File

@@ -107,6 +107,7 @@ type Daemon struct {
func (daemon *Daemon) Install(eng *engine.Engine) error {
// FIXME: rename "delete" to "rm" for consistency with the CLI command
// FIXME: rename ContainerDestroy to ContainerRm for consistency with the CLI command
// FIXME: remove ImageDelete's dependency on Daemon, then move to graph/
for name, method := range map[string]engine.Handler{
"attach": daemon.ContainerAttach,
"commit": daemon.ContainerCommit,
@@ -127,6 +128,7 @@ func (daemon *Daemon) Install(eng *engine.Engine) error {
"top": daemon.ContainerTop,
"unpause": daemon.ContainerUnpause,
"wait": daemon.ContainerWait,
"image_delete": daemon.ImageDelete, // FIXME: see above
} {
if err := eng.Register(name, method); err != nil {
return err

View File

@@ -70,7 +70,7 @@ func (daemon *Daemon) ContainerDestroy(job *engine.Job) engine.Status {
if err := daemon.Destroy(container); err != nil {
return job.Errorf("Cannot destroy container %s: %s", name, err)
}
job.Eng.Job("log", "destroy", container.ID, daemon.Repositories().ImageName(container.Image)).Run()
container.LogEvent("destroy")
if removeVolume {
var (

View File

@@ -23,7 +23,7 @@ func (daemon *Daemon) ContainerExport(job *engine.Job) engine.Status {
return job.Errorf("%s: %s", name, err)
}
// FIXME: factor job-specific LogEvent to engine.Job.Run()
job.Eng.Job("log", "export", container.ID, daemon.Repositories().ImageName(container.Image)).Run()
container.LogEvent("export")
return engine.StatusOK
}
return job.Errorf("No such container: %s", name)

156
daemon/image_delete.go Normal file
View File

@@ -0,0 +1,156 @@
package daemon
import (
"fmt"
"strings"
"github.com/docker/docker/engine"
"github.com/docker/docker/graph"
"github.com/docker/docker/image"
"github.com/docker/docker/pkg/parsers"
"github.com/docker/docker/utils"
)
func (daemon *Daemon) ImageDelete(job *engine.Job) engine.Status {
if n := len(job.Args); n != 1 {
return job.Errorf("Usage: %s IMAGE", job.Name)
}
imgs := engine.NewTable("", 0)
if err := daemon.DeleteImage(job.Eng, job.Args[0], imgs, true, job.GetenvBool("force"), job.GetenvBool("noprune")); err != nil {
return job.Error(err)
}
if len(imgs.Data) == 0 {
return job.Errorf("Conflict, %s wasn't deleted", job.Args[0])
}
if _, err := imgs.WriteListTo(job.Stdout); err != nil {
return job.Error(err)
}
return engine.StatusOK
}
// FIXME: make this private and use the job instead
func (daemon *Daemon) DeleteImage(eng *engine.Engine, name string, imgs *engine.Table, first, force, noprune bool) error {
var (
repoName, tag string
tags = []string{}
tagDeleted bool
)
// FIXME: please respect DRY and centralize repo+tag parsing in a single central place! -- shykes
repoName, tag = parsers.ParseRepositoryTag(name)
if tag == "" {
tag = graph.DEFAULTTAG
}
img, err := daemon.Repositories().LookupImage(name)
if err != nil {
if r, _ := daemon.Repositories().Get(repoName); r != nil {
return fmt.Errorf("No such image: %s:%s", repoName, tag)
}
return fmt.Errorf("No such image: %s", name)
}
if strings.Contains(img.ID, name) {
repoName = ""
tag = ""
}
byParents, err := daemon.Graph().ByParent()
if err != nil {
return err
}
//If delete by id, see if the id belong only to one repository
if repoName == "" {
for _, repoAndTag := range daemon.Repositories().ByID()[img.ID] {
parsedRepo, parsedTag := parsers.ParseRepositoryTag(repoAndTag)
if repoName == "" || repoName == parsedRepo {
repoName = parsedRepo
if parsedTag != "" {
tags = append(tags, parsedTag)
}
} else if repoName != parsedRepo && !force {
// the id belongs to multiple repos, like base:latest and user:test,
// in that case return conflict
return fmt.Errorf("Conflict, cannot delete image %s because it is tagged in multiple repositories, use -f to force", name)
}
}
} else {
tags = append(tags, tag)
}
if !first && len(tags) > 0 {
return nil
}
//Untag the current image
for _, tag := range tags {
tagDeleted, err = daemon.Repositories().Delete(repoName, tag)
if err != nil {
return err
}
if tagDeleted {
out := &engine.Env{}
out.Set("Untagged", repoName+":"+tag)
imgs.Add(out)
eng.Job("log", "untag", img.ID, "").Run()
}
}
tags = daemon.Repositories().ByID()[img.ID]
if (len(tags) <= 1 && repoName == "") || len(tags) == 0 {
if len(byParents[img.ID]) == 0 {
if err := daemon.canDeleteImage(img.ID, force, tagDeleted); err != nil {
return err
}
if err := daemon.Repositories().DeleteAll(img.ID); err != nil {
return err
}
if err := daemon.Graph().Delete(img.ID); err != nil {
return err
}
out := &engine.Env{}
out.Set("Deleted", img.ID)
imgs.Add(out)
eng.Job("log", "delete", img.ID, "").Run()
if img.Parent != "" && !noprune {
err := daemon.DeleteImage(eng, img.Parent, imgs, false, force, noprune)
if first {
return err
}
}
}
}
return nil
}
func (daemon *Daemon) canDeleteImage(imgID string, force, untagged bool) error {
var message string
if untagged {
message = " (docker untagged the image)"
}
for _, container := range daemon.List() {
parent, err := daemon.Repositories().LookupImage(container.Image)
if err != nil {
return err
}
if err := parent.WalkHistory(func(p *image.Image) error {
if imgID == p.ID {
if container.State.IsRunning() {
if force {
return fmt.Errorf("Conflict, cannot force delete %s because the running container %s is using it%s, stop it and retry", utils.TruncateID(imgID), utils.TruncateID(container.ID), message)
}
return fmt.Errorf("Conflict, cannot delete %s because the running container %s is using it%s, stop it and use -f to force", utils.TruncateID(imgID), utils.TruncateID(container.ID), message)
} else if !force {
return fmt.Errorf("Conflict, cannot delete %s because the container %s is using it%s, use -f to force", utils.TruncateID(imgID), utils.TruncateID(container.ID), message)
}
}
return nil
}); err != nil {
return err
}
}
return nil
}

View File

@@ -44,7 +44,7 @@ func (daemon *Daemon) ContainerKill(job *engine.Job) engine.Status {
if err := container.Kill(); err != nil {
return job.Errorf("Cannot kill container %s: %s", name, err)
}
job.Eng.Job("log", "kill", container.ID, daemon.Repositories().ImageName(container.Image)).Run()
container.LogEvent("kill")
} else {
// Otherwise, just send the requested signal
if err := container.KillSig(int(sig)); err != nil {

View File

@@ -16,7 +16,7 @@ func (daemon *Daemon) ContainerPause(job *engine.Job) engine.Status {
if err := container.Pause(); err != nil {
return job.Errorf("Cannot pause container %s: %s", name, err)
}
job.Eng.Job("log", "pause", container.ID, daemon.Repositories().ImageName(container.Image)).Run()
container.LogEvent("pause")
return engine.StatusOK
}
@@ -32,6 +32,6 @@ func (daemon *Daemon) ContainerUnpause(job *engine.Job) engine.Status {
if err := container.Unpause(); err != nil {
return job.Errorf("Cannot unpause container %s: %s", name, err)
}
job.Eng.Job("log", "unpause", container.ID, daemon.Repositories().ImageName(container.Image)).Run()
container.LogEvent("unpause")
return engine.StatusOK
}

View File

@@ -19,7 +19,7 @@ func (daemon *Daemon) ContainerRestart(job *engine.Job) engine.Status {
if err := container.Restart(int(t)); err != nil {
return job.Errorf("Cannot restart container %s: %s\n", name, err)
}
job.Eng.Job("log", "restart", container.ID, daemon.Repositories().ImageName(container.Image)).Run()
container.LogEvent("restart")
} else {
return job.Errorf("No such container: %s\n", name)
}

View File

@@ -1,10 +1,5 @@
package daemon
import (
"github.com/docker/docker/utils"
)
type Server interface {
LogEvent(action, id, from string) *utils.JSONMessage
IsRunning() bool // returns true if the server is currently in operation
}

View File

@@ -36,8 +36,7 @@ func (daemon *Daemon) ContainerStart(job *engine.Job) engine.Status {
if err := container.Start(); err != nil {
return job.Errorf("Cannot start container %s: %s", name, err)
}
job.Eng.Job("log", "start", container.ID, daemon.Repositories().ImageName(container.Image)).Run()
container.LogEvent("start")
return engine.StatusOK
}

View File

@@ -22,7 +22,7 @@ func (daemon *Daemon) ContainerStop(job *engine.Job) engine.Status {
if err := container.Stop(int(t)); err != nil {
return job.Errorf("Cannot stop container %s: %s\n", name, err)
}
job.Eng.Job("log", "stop", container.ID, daemon.Repositories().ImageName(container.Image)).Run()
container.LogEvent("stop")
} else {
return job.Errorf("No such container: %s\n", name)
}