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