Ver Fonte

Move ImagePrune

Signed-off-by: Daniel Nephin <dnephin@docker.com>
Daniel Nephin há 7 anos atrás
pai
commit
9c25df0fa2
2 ficheiros alterados com 169 adições e 157 exclusões
  1. 168 0
      daemon/image_prune.go
  2. 1 157
      daemon/prune.go

+ 168 - 0
daemon/image_prune.go

@@ -0,0 +1,168 @@
+package daemon
+
+import (
+	"sync/atomic"
+
+	"github.com/docker/distribution/reference"
+	"github.com/docker/docker/api/types"
+	"github.com/docker/docker/api/types/filters"
+	"github.com/docker/docker/errdefs"
+	"github.com/docker/docker/image"
+	"github.com/docker/docker/layer"
+	digest "github.com/opencontainers/go-digest"
+	"github.com/sirupsen/logrus"
+	"golang.org/x/net/context"
+)
+
+var imagesAcceptedFilters = map[string]bool{
+	"dangling": true,
+	"label":    true,
+	"label!":   true,
+	"until":    true,
+}
+
+// ImagesPrune removes unused images
+func (daemon *Daemon) ImagesPrune(ctx context.Context, pruneFilters filters.Args) (*types.ImagesPruneReport, error) {
+	if !atomic.CompareAndSwapInt32(&daemon.pruneRunning, 0, 1) {
+		return nil, errPruneRunning
+	}
+	defer atomic.StoreInt32(&daemon.pruneRunning, 0)
+
+	// make sure that only accepted filters have been received
+	err := pruneFilters.Validate(imagesAcceptedFilters)
+	if err != nil {
+		return nil, err
+	}
+
+	rep := &types.ImagesPruneReport{}
+
+	danglingOnly := true
+	if pruneFilters.Contains("dangling") {
+		if pruneFilters.ExactMatch("dangling", "false") || pruneFilters.ExactMatch("dangling", "0") {
+			danglingOnly = false
+		} else if !pruneFilters.ExactMatch("dangling", "true") && !pruneFilters.ExactMatch("dangling", "1") {
+			return nil, invalidFilter{"dangling", pruneFilters.Get("dangling")}
+		}
+	}
+
+	until, err := getUntilFromPruneFilters(pruneFilters)
+	if err != nil {
+		return nil, err
+	}
+
+	var allImages map[image.ID]*image.Image
+	if danglingOnly {
+		allImages = daemon.imageStore.Heads()
+	} else {
+		allImages = daemon.imageStore.Map()
+	}
+
+	// Filter intermediary images and get their unique size
+	allLayers := make(map[layer.ChainID]layer.Layer)
+	for _, ls := range daemon.layerStores {
+		for k, v := range ls.Map() {
+			allLayers[k] = v
+		}
+	}
+	topImages := map[image.ID]*image.Image{}
+	for id, img := range allImages {
+		select {
+		case <-ctx.Done():
+			return nil, ctx.Err()
+		default:
+			dgst := digest.Digest(id)
+			if len(daemon.referenceStore.References(dgst)) == 0 && len(daemon.imageStore.Children(id)) != 0 {
+				continue
+			}
+			if !until.IsZero() && img.Created.After(until) {
+				continue
+			}
+			if img.Config != nil && !matchLabels(pruneFilters, img.Config.Labels) {
+				continue
+			}
+			topImages[id] = img
+		}
+	}
+
+	canceled := false
+deleteImagesLoop:
+	for id := range topImages {
+		select {
+		case <-ctx.Done():
+			// we still want to calculate freed size and return the data
+			canceled = true
+			break deleteImagesLoop
+		default:
+		}
+
+		deletedImages := []types.ImageDeleteResponseItem{}
+		refs := daemon.referenceStore.References(id.Digest())
+		if len(refs) > 0 {
+			shouldDelete := !danglingOnly
+			if !shouldDelete {
+				hasTag := false
+				for _, ref := range refs {
+					if _, ok := ref.(reference.NamedTagged); ok {
+						hasTag = true
+						break
+					}
+				}
+
+				// Only delete if it's untagged (i.e. repo:<none>)
+				shouldDelete = !hasTag
+			}
+
+			if shouldDelete {
+				for _, ref := range refs {
+					imgDel, err := daemon.ImageDelete(ref.String(), false, true)
+					if imageDeleteFailed(ref.String(), err) {
+						continue
+					}
+					deletedImages = append(deletedImages, imgDel...)
+				}
+			}
+		} else {
+			hex := id.Digest().Hex()
+			imgDel, err := daemon.ImageDelete(hex, false, true)
+			if imageDeleteFailed(hex, err) {
+				continue
+			}
+			deletedImages = append(deletedImages, imgDel...)
+		}
+
+		rep.ImagesDeleted = append(rep.ImagesDeleted, deletedImages...)
+	}
+
+	// Compute how much space was freed
+	for _, d := range rep.ImagesDeleted {
+		if d.Deleted != "" {
+			chid := layer.ChainID(d.Deleted)
+			if l, ok := allLayers[chid]; ok {
+				diffSize, err := l.DiffSize()
+				if err != nil {
+					logrus.Warnf("failed to get layer %s size: %v", chid, err)
+					continue
+				}
+				rep.SpaceReclaimed += uint64(diffSize)
+			}
+		}
+	}
+
+	if canceled {
+		logrus.Debugf("ImagesPrune operation cancelled: %#v", *rep)
+	}
+
+	return rep, nil
+}
+
+func imageDeleteFailed(ref string, err error) bool {
+	switch {
+	case err == nil:
+		return false
+	case errdefs.IsConflict(err):
+		return true
+	default:
+		logrus.Warnf("failed to prune image %s: %v", ref, err)
+		return true
+	}
+}

+ 1 - 157
daemon/prune.go

@@ -6,18 +6,13 @@ import (
 	"sync/atomic"
 	"sync/atomic"
 	"time"
 	"time"
 
 
-	"github.com/docker/distribution/reference"
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types/filters"
 	"github.com/docker/docker/api/types/filters"
 	timetypes "github.com/docker/docker/api/types/time"
 	timetypes "github.com/docker/docker/api/types/time"
-	"github.com/docker/docker/errdefs"
-	"github.com/docker/docker/image"
-	"github.com/docker/docker/layer"
 	"github.com/docker/docker/pkg/directory"
 	"github.com/docker/docker/pkg/directory"
 	"github.com/docker/docker/runconfig"
 	"github.com/docker/docker/runconfig"
 	"github.com/docker/docker/volume"
 	"github.com/docker/docker/volume"
 	"github.com/docker/libnetwork"
 	"github.com/docker/libnetwork"
-	digest "github.com/opencontainers/go-digest"
 	"github.com/sirupsen/logrus"
 	"github.com/sirupsen/logrus"
 	"golang.org/x/net/context"
 	"golang.org/x/net/context"
 )
 )
@@ -36,12 +31,7 @@ var (
 		"label":  true,
 		"label":  true,
 		"label!": true,
 		"label!": true,
 	}
 	}
-	imagesAcceptedFilters = map[string]bool{
-		"dangling": true,
-		"label":    true,
-		"label!":   true,
-		"until":    true,
-	}
+
 	networksAcceptedFilters = map[string]bool{
 	networksAcceptedFilters = map[string]bool{
 		"label":  true,
 		"label":  true,
 		"label!": true,
 		"label!": true,
@@ -159,152 +149,6 @@ func (daemon *Daemon) VolumesPrune(ctx context.Context, pruneFilters filters.Arg
 	return rep, err
 	return rep, err
 }
 }
 
 
-// ImagesPrune removes unused images
-func (daemon *Daemon) ImagesPrune(ctx context.Context, pruneFilters filters.Args) (*types.ImagesPruneReport, error) {
-	if !atomic.CompareAndSwapInt32(&daemon.pruneRunning, 0, 1) {
-		return nil, errPruneRunning
-	}
-	defer atomic.StoreInt32(&daemon.pruneRunning, 0)
-
-	// make sure that only accepted filters have been received
-	err := pruneFilters.Validate(imagesAcceptedFilters)
-	if err != nil {
-		return nil, err
-	}
-
-	rep := &types.ImagesPruneReport{}
-
-	danglingOnly := true
-	if pruneFilters.Contains("dangling") {
-		if pruneFilters.ExactMatch("dangling", "false") || pruneFilters.ExactMatch("dangling", "0") {
-			danglingOnly = false
-		} else if !pruneFilters.ExactMatch("dangling", "true") && !pruneFilters.ExactMatch("dangling", "1") {
-			return nil, invalidFilter{"dangling", pruneFilters.Get("dangling")}
-		}
-	}
-
-	until, err := getUntilFromPruneFilters(pruneFilters)
-	if err != nil {
-		return nil, err
-	}
-
-	var allImages map[image.ID]*image.Image
-	if danglingOnly {
-		allImages = daemon.imageStore.Heads()
-	} else {
-		allImages = daemon.imageStore.Map()
-	}
-
-	// Filter intermediary images and get their unique size
-	allLayers := make(map[layer.ChainID]layer.Layer)
-	for _, ls := range daemon.layerStores {
-		for k, v := range ls.Map() {
-			allLayers[k] = v
-		}
-	}
-	topImages := map[image.ID]*image.Image{}
-	for id, img := range allImages {
-		select {
-		case <-ctx.Done():
-			return nil, ctx.Err()
-		default:
-			dgst := digest.Digest(id)
-			if len(daemon.referenceStore.References(dgst)) == 0 && len(daemon.imageStore.Children(id)) != 0 {
-				continue
-			}
-			if !until.IsZero() && img.Created.After(until) {
-				continue
-			}
-			if img.Config != nil && !matchLabels(pruneFilters, img.Config.Labels) {
-				continue
-			}
-			topImages[id] = img
-		}
-	}
-
-	canceled := false
-deleteImagesLoop:
-	for id := range topImages {
-		select {
-		case <-ctx.Done():
-			// we still want to calculate freed size and return the data
-			canceled = true
-			break deleteImagesLoop
-		default:
-		}
-
-		deletedImages := []types.ImageDeleteResponseItem{}
-		refs := daemon.referenceStore.References(id.Digest())
-		if len(refs) > 0 {
-			shouldDelete := !danglingOnly
-			if !shouldDelete {
-				hasTag := false
-				for _, ref := range refs {
-					if _, ok := ref.(reference.NamedTagged); ok {
-						hasTag = true
-						break
-					}
-				}
-
-				// Only delete if it's untagged (i.e. repo:<none>)
-				shouldDelete = !hasTag
-			}
-
-			if shouldDelete {
-				for _, ref := range refs {
-					imgDel, err := daemon.ImageDelete(ref.String(), false, true)
-					if imageDeleteFailed(ref.String(), err) {
-						continue
-					}
-					deletedImages = append(deletedImages, imgDel...)
-				}
-			}
-		} else {
-			hex := id.Digest().Hex()
-			imgDel, err := daemon.ImageDelete(hex, false, true)
-			if imageDeleteFailed(hex, err) {
-				continue
-			}
-			deletedImages = append(deletedImages, imgDel...)
-		}
-
-		rep.ImagesDeleted = append(rep.ImagesDeleted, deletedImages...)
-	}
-
-	// Compute how much space was freed
-	for _, d := range rep.ImagesDeleted {
-		if d.Deleted != "" {
-			chid := layer.ChainID(d.Deleted)
-			if l, ok := allLayers[chid]; ok {
-				diffSize, err := l.DiffSize()
-				if err != nil {
-					logrus.Warnf("failed to get layer %s size: %v", chid, err)
-					continue
-				}
-				rep.SpaceReclaimed += uint64(diffSize)
-			}
-		}
-	}
-
-	if canceled {
-		logrus.Debugf("ImagesPrune operation cancelled: %#v", *rep)
-	}
-
-	return rep, nil
-}
-
-func imageDeleteFailed(ref string, err error) bool {
-	switch {
-	case err == nil:
-		return false
-	case errdefs.IsConflict(err):
-		return true
-	default:
-		logrus.Warnf("failed to prune image %s: %v", ref, err)
-		return true
-	}
-}
-
 // localNetworksPrune removes unused local networks
 // localNetworksPrune removes unused local networks
 func (daemon *Daemon) localNetworksPrune(ctx context.Context, pruneFilters filters.Args) *types.NetworksPruneReport {
 func (daemon *Daemon) localNetworksPrune(ctx context.Context, pruneFilters filters.Args) *types.NetworksPruneReport {
 	rep := &types.NetworksPruneReport{}
 	rep := &types.NetworksPruneReport{}