Checksum system overhaul

This commit is contained in:
shin- 2013-04-30 10:01:19 -07:00
parent e81a53eea9
commit 6e2ddf6f60
4 changed files with 60 additions and 37 deletions

View File

@ -529,9 +529,6 @@ func (srv *Server) CmdPush(stdin io.ReadCloser, stdout rcli.DockerConn, args ...
Debugf("Pushing [%s] to [%s]\n", local, remote)
// Try to get the image
// FIXME: Handle lookup
// FIXME: Also push the tags in case of ./docker push myrepo:mytag
// img, err := srv.runtime.LookupImage(cmd.Arg(0))
img, err := srv.runtime.graph.Get(local)
if err != nil {
Debugf("The push refers to a repository [%s] (len: %d)\n", local, len(srv.runtime.repositories.Repositories[local]))

View File

@ -81,13 +81,6 @@ func (graph *Graph) Get(name string) (*Image, error) {
return nil, fmt.Errorf("Image stored at '%s' has wrong id '%s'", id, img.Id)
}
img.graph = graph
if img.Checksum == "" {
err := img.FixChecksum()
if err != nil {
return nil, err
}
}
return img, nil
}
@ -105,17 +98,11 @@ func (graph *Graph) Create(layerData Archive, container *Container, comment, aut
img.Parent = container.Image
img.Container = container.Id
img.ContainerConfig = *container.Config
// FIXME: If an image is imported from a raw URL (not created from a container),
// its checksum will not be computed, which will cause a push to fail
checksum, err := container.RwChecksum()
if err != nil {
return nil, err
}
img.Checksum = checksum
}
if err := graph.Register(layerData, img); err != nil {
return nil, err
}
img.Checksum()
return img, nil
}
@ -309,7 +296,10 @@ func (graph *Graph) Checksums(repo Repository) ([]map[string]string, error) {
return nil, err
}
err = img.WalkHistory(func(image *Image) error {
checksums[image.Id] = image.Checksum
checksums[image.Id], err = image.Checksum()
if err != nil {
return err
}
return nil
})
if err != nil {

View File

@ -1,7 +1,9 @@
package docker
import (
"bytes"
"crypto/rand"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
@ -18,7 +20,6 @@ import (
type Image struct {
Id string `json:"id"`
Parent string `json:"parent,omitempty"`
Checksum string `json:"checksum,omitempty"`
Comment string `json:"comment,omitempty"`
Created time.Time `json:"created"`
Container string `json:"container,omitempty"`
@ -260,30 +261,57 @@ func (img *Image) layer() (string, error) {
return layerPath(root), nil
}
func (img *Image) FixChecksum() error {
func (img *Image) Checksum() (string, error) {
root, err := img.root()
if err != nil {
return "", err
}
checksumDictPth := path.Join(root, "..", "..", "checksums")
checksums := new(map[string]string)
if checksumDict, err := ioutil.ReadFile(checksumDictPth); err == nil {
if err := json.Unmarshal(checksumDict, checksums); err != nil {
return "", err
}
if checksum, ok := (*checksums)[img.Id]; ok {
return checksum, nil
}
}
layer, err := img.layer()
if err != nil {
return err
return "", err
}
layerData, err := Tar(layer, Xz)
if err != nil {
return err
return "", err
}
sum, err := HashData(layerData)
h := sha256.New()
if _, err := io.Copy(h, layerData); err != nil {
return "", err
}
jsonData, err := ioutil.ReadFile(jsonPath(root))
if err != nil {
return err
return "", err
}
img.Checksum = sum
jsonData, err := json.Marshal(img)
if _, err := io.Copy(h, bytes.NewBuffer(jsonData)); err != nil {
return "", err
}
hash := "sha256:"+hex.EncodeToString(h.Sum(nil))
if *checksums == nil {
*checksums = map[string]string{}
}
(*checksums)[img.Id] = hash
checksumJson, err := json.Marshal(checksums)
if err != nil {
return err
return hash, err
}
root, err := img.root()
if err != nil {
return err
if err := ioutil.WriteFile(checksumDictPth, checksumJson, 0600); err != nil {
return hash, err
}
if err := ioutil.WriteFile(jsonPath(root), jsonData, 0600); err != nil {
return err
}
return nil
return hash, nil
}

View File

@ -327,6 +327,12 @@ func pushImageRec(graph *Graph, stdout io.Writer, img *Image, registry string, t
}
req.Header.Add("Content-type", "application/json")
req.Header.Set("Authorization", "Token " + strings.Join(token, ","))
checksum, err := img.Checksum()
if err != nil {
return fmt.Errorf("Error while retrieving checksum for %s: %v", img.Id, err)
}
req.Header.Set("X-Docker-Checksum", checksum)
res, err := doWithCookies(client, req)
if err != nil {
return fmt.Errorf("Failed to upload metadata: %s", err)
@ -457,7 +463,7 @@ func (graph *Graph) PushRepository(stdout io.Writer, remote string, localRepo Re
return err
}
req, err := http.NewRequest("PUT", INDEX_ENDPOINT+"/repositories/"+remote, bytes.NewReader(imgListJson))
req, err := http.NewRequest("PUT", INDEX_ENDPOINT+"/repositories/"+remote+"/", bytes.NewReader(imgListJson))
if err != nil {
return err
}
@ -468,7 +474,7 @@ func (graph *Graph) PushRepository(stdout io.Writer, remote string, localRepo Re
if err != nil {
return err
}
res.Body.Close()
defer res.Body.Close()
for res.StatusCode >= 300 && res.StatusCode < 400 {
Debugf("Redirected to %s\n", res.Header.Get("Location"))
req, err = http.NewRequest("PUT", res.Header.Get("Location"), bytes.NewReader(imgListJson))
@ -482,10 +488,12 @@ func (graph *Graph) PushRepository(stdout io.Writer, remote string, localRepo Re
if err != nil {
return err
}
res.Body.Close()
defer res.Body.Close()
}
if res.StatusCode != 200 && res.StatusCode != 201 {
info, err := ioutil.ReadAll(res.Body)
Debugf("%v %v", err, string(info))
return fmt.Errorf("Error: Status %d trying to push repository %s", res.StatusCode, remote)
}