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  }