load.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. // +build linux
  2. package graph
  3. import (
  4. "encoding/json"
  5. "io"
  6. "io/ioutil"
  7. "os"
  8. "path"
  9. log "github.com/Sirupsen/logrus"
  10. "github.com/docker/docker/engine"
  11. "github.com/docker/docker/image"
  12. "github.com/docker/docker/pkg/archive"
  13. "github.com/docker/docker/pkg/chrootarchive"
  14. "github.com/docker/docker/utils"
  15. )
  16. // Loads a set of images into the repository. This is the complementary of ImageExport.
  17. // The input stream is an uncompressed tar ball containing images and metadata.
  18. func (s *TagStore) CmdLoad(job *engine.Job) engine.Status {
  19. tmpImageDir, err := ioutil.TempDir("", "docker-import-")
  20. if err != nil {
  21. return job.Error(err)
  22. }
  23. defer os.RemoveAll(tmpImageDir)
  24. var (
  25. repoTarFile = path.Join(tmpImageDir, "repo.tar")
  26. repoDir = path.Join(tmpImageDir, "repo")
  27. )
  28. tarFile, err := os.Create(repoTarFile)
  29. if err != nil {
  30. return job.Error(err)
  31. }
  32. if _, err := io.Copy(tarFile, job.Stdin); err != nil {
  33. return job.Error(err)
  34. }
  35. tarFile.Close()
  36. repoFile, err := os.Open(repoTarFile)
  37. if err != nil {
  38. return job.Error(err)
  39. }
  40. if err := os.Mkdir(repoDir, os.ModeDir); err != nil {
  41. return job.Error(err)
  42. }
  43. images, err := s.graph.Map()
  44. if err != nil {
  45. return job.Error(err)
  46. }
  47. excludes := make([]string, len(images))
  48. i := 0
  49. for k := range images {
  50. excludes[i] = k
  51. i++
  52. }
  53. if err := chrootarchive.Untar(repoFile, repoDir, &archive.TarOptions{ExcludePatterns: excludes}); err != nil {
  54. return job.Error(err)
  55. }
  56. dirs, err := ioutil.ReadDir(repoDir)
  57. if err != nil {
  58. return job.Error(err)
  59. }
  60. for _, d := range dirs {
  61. if d.IsDir() {
  62. if err := s.recursiveLoad(job.Eng, d.Name(), tmpImageDir); err != nil {
  63. return job.Error(err)
  64. }
  65. }
  66. }
  67. repositoriesJson, err := ioutil.ReadFile(path.Join(tmpImageDir, "repo", "repositories"))
  68. if err == nil {
  69. repositories := map[string]Repository{}
  70. if err := json.Unmarshal(repositoriesJson, &repositories); err != nil {
  71. return job.Error(err)
  72. }
  73. for imageName, tagMap := range repositories {
  74. for tag, address := range tagMap {
  75. if err := s.Set(imageName, tag, address, true); err != nil {
  76. return job.Error(err)
  77. }
  78. }
  79. }
  80. } else if !os.IsNotExist(err) {
  81. return job.Error(err)
  82. }
  83. return engine.StatusOK
  84. }
  85. func (s *TagStore) recursiveLoad(eng *engine.Engine, address, tmpImageDir string) error {
  86. if err := eng.Job("image_get", address).Run(); err != nil {
  87. log.Debugf("Loading %s", address)
  88. imageJson, err := ioutil.ReadFile(path.Join(tmpImageDir, "repo", address, "json"))
  89. if err != nil {
  90. log.Debugf("Error reading json", err)
  91. return err
  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. if img.Parent != "" {
  108. if !s.graph.Exists(img.Parent) {
  109. if err := s.recursiveLoad(eng, img.Parent, tmpImageDir); err != nil {
  110. return err
  111. }
  112. }
  113. }
  114. if err := s.graph.Register(img, layer); err != nil {
  115. return err
  116. }
  117. }
  118. log.Debugf("Completed processing %s", address)
  119. return nil
  120. }