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  }