github.com/jandre/docker@v1.7.0/graph/load.go (about) 1 // +build linux windows 2 3 package graph 4 5 import ( 6 "encoding/json" 7 "io" 8 "io/ioutil" 9 "os" 10 "path/filepath" 11 12 "github.com/Sirupsen/logrus" 13 "github.com/docker/docker/image" 14 "github.com/docker/docker/pkg/archive" 15 "github.com/docker/docker/pkg/chrootarchive" 16 ) 17 18 // Loads a set of images into the repository. This is the complementary of ImageExport. 19 // The input stream is an uncompressed tar ball containing images and metadata. 20 func (s *TagStore) Load(inTar io.ReadCloser, outStream io.Writer) error { 21 tmpImageDir, err := ioutil.TempDir("", "docker-import-") 22 if err != nil { 23 return err 24 } 25 defer os.RemoveAll(tmpImageDir) 26 27 var ( 28 repoDir = filepath.Join(tmpImageDir, "repo") 29 ) 30 31 if err := os.Mkdir(repoDir, os.ModeDir); err != nil { 32 return err 33 } 34 images, err := s.graph.Map() 35 if err != nil { 36 return err 37 } 38 excludes := make([]string, len(images)) 39 i := 0 40 for k := range images { 41 excludes[i] = k 42 i++ 43 } 44 if err := chrootarchive.Untar(inTar, repoDir, &archive.TarOptions{ExcludePatterns: excludes}); err != nil { 45 return err 46 } 47 48 dirs, err := ioutil.ReadDir(repoDir) 49 if err != nil { 50 return err 51 } 52 53 for _, d := range dirs { 54 if d.IsDir() { 55 if err := s.recursiveLoad(d.Name(), tmpImageDir); err != nil { 56 return err 57 } 58 } 59 } 60 61 reposJSONFile, err := os.Open(filepath.Join(tmpImageDir, "repo", "repositories")) 62 if err != nil { 63 if !os.IsNotExist(err) { 64 return err 65 } 66 return nil 67 } 68 defer reposJSONFile.Close() 69 70 repositories := map[string]Repository{} 71 if err := json.NewDecoder(reposJSONFile).Decode(&repositories); err != nil { 72 return err 73 } 74 75 for imageName, tagMap := range repositories { 76 for tag, address := range tagMap { 77 if err := s.SetLoad(imageName, tag, address, true, outStream); err != nil { 78 return err 79 } 80 } 81 } 82 83 return nil 84 } 85 86 func (s *TagStore) recursiveLoad(address, tmpImageDir string) error { 87 if _, err := s.LookupImage(address); err != nil { 88 logrus.Debugf("Loading %s", address) 89 90 imageJson, err := ioutil.ReadFile(filepath.Join(tmpImageDir, "repo", address, "json")) 91 if err != nil { 92 logrus.Debugf("Error reading json", err) 93 return err 94 } 95 96 layer, err := os.Open(filepath.Join(tmpImageDir, "repo", address, "layer.tar")) 97 if err != nil { 98 logrus.Debugf("Error reading embedded tar", err) 99 return err 100 } 101 img, err := image.NewImgJSON(imageJson) 102 if err != nil { 103 logrus.Debugf("Error unmarshalling json", err) 104 return err 105 } 106 if err := image.ValidateID(img.ID); err != nil { 107 logrus.Debugf("Error validating ID: %s", err) 108 return err 109 } 110 111 // ensure no two downloads of the same layer happen at the same time 112 if c, err := s.poolAdd("pull", "layer:"+img.ID); err != nil { 113 if c != nil { 114 logrus.Debugf("Image (id: %s) load is already running, waiting: %v", img.ID, err) 115 <-c 116 return nil 117 } 118 119 return err 120 } 121 122 defer s.poolRemove("pull", "layer:"+img.ID) 123 124 if img.Parent != "" { 125 if !s.graph.Exists(img.Parent) { 126 if err := s.recursiveLoad(img.Parent, tmpImageDir); err != nil { 127 return err 128 } 129 } 130 } 131 if err := s.graph.Register(img, layer); err != nil { 132 return err 133 } 134 } 135 logrus.Debugf("Completed processing %s", address) 136 137 return nil 138 }