Browse code

Compute TarSum on storage of image layer content

Now, newly created/imported layers will have the checksum of
the layer diff computed and stored in the image json file.

For now, it is not an error if the computed checksum does not
match an existing checksum, only a warning message is logged. The
eventual goal is to use the checksums in the image JSON to verify
the integrity of the layer contents when doing `docker load` or
`docker pull`, and error out if it does not match.

Docker-DCO-1.1-Signed-off-by: Josh Hawn <josh.hawn@docker.com> (github: jlhawn)

Josh Hawn authored on 2014/11/05 08:23:21
Showing 2 changed files
... ...
@@ -150,6 +150,7 @@ func (s *TagStore) CmdLookup(job *engine.Job) engine.Status {
150 150
 		out.Set("Os", image.OS)
151 151
 		out.SetInt64("Size", image.Size)
152 152
 		out.SetInt64("VirtualSize", image.GetParentsSize(0)+image.Size)
153
+		out.Set("Checksum", image.Checksum)
153 154
 		if _, err = out.WriteTo(job.Stdout); err != nil {
154 155
 			return job.Error(err)
155 156
 		}
... ...
@@ -11,6 +11,7 @@ import (
11 11
 
12 12
 	log "github.com/Sirupsen/logrus"
13 13
 	"github.com/docker/docker/pkg/archive"
14
+	"github.com/docker/docker/pkg/tarsum"
14 15
 	"github.com/docker/docker/runconfig"
15 16
 	"github.com/docker/docker/utils"
16 17
 )
... ...
@@ -32,6 +33,7 @@ type Image struct {
32 32
 	Config          *runconfig.Config `json:"config,omitempty"`
33 33
 	Architecture    string            `json:"architecture,omitempty"`
34 34
 	OS              string            `json:"os,omitempty"`
35
+	Checksum        string            `json:"checksum"`
35 36
 	Size            int64
36 37
 
37 38
 	graph Graph
... ...
@@ -74,19 +76,43 @@ func LoadImage(root string) (*Image, error) {
74 74
 	return img, nil
75 75
 }
76 76
 
77
+// StoreImage stores file system layer data for the given image to the
78
+// image's registered storage driver. Image metadata is stored in a file
79
+// at the specified root directory. This function also computes the TarSum
80
+// of `layerData` (currently using tarsum.dev).
77 81
 func StoreImage(img *Image, layerData archive.ArchiveReader, root string) error {
78 82
 	// Store the layer
79 83
 	var (
80
-		size   int64
81
-		err    error
82
-		driver = img.graph.Driver()
84
+		size        int64
85
+		err         error
86
+		driver      = img.graph.Driver()
87
+		layerTarSum tarsum.TarSum
83 88
 	)
84 89
 
85 90
 	// If layerData is not nil, unpack it into the new layer
86 91
 	if layerData != nil {
87
-		if size, err = driver.ApplyDiff(img.ID, img.Parent, layerData); err != nil {
92
+		layerDataDecompressed, err := archive.DecompressStream(layerData)
93
+		if err != nil {
88 94
 			return err
89 95
 		}
96
+
97
+		defer layerDataDecompressed.Close()
98
+
99
+		if layerTarSum, err = tarsum.NewTarSum(layerDataDecompressed, true, tarsum.VersionDev); err != nil {
100
+			return err
101
+		}
102
+
103
+		if size, err = driver.ApplyDiff(img.ID, img.Parent, layerTarSum); err != nil {
104
+			return err
105
+		}
106
+
107
+		checksum := layerTarSum.Sum(nil)
108
+
109
+		if img.Checksum != "" && img.Checksum != checksum {
110
+			log.Warn("image layer checksum mismatch: computed %q, expected %q", checksum, img.Checksum)
111
+		}
112
+
113
+		img.Checksum = checksum
90 114
 	}
91 115
 
92 116
 	img.Size = size