func blockDumpAction(cmd *cobra.Command, args []string) error { if len(args) != 2 { return torus.ErrUsage } output, err := getWriterFromArg(args[1]) if err != nil { return fmt.Errorf("couldn't open output: %v", err) } srv := createServer() defer srv.Close() blockvol, err := block.OpenBlockVolume(srv, args[0]) if err != nil { return fmt.Errorf("couldn't open block volume %s: %v", args[0], err) } tempsnap := fmt.Sprintf("temp-dump-%d", os.Getpid()) err = blockvol.SaveSnapshot(tempsnap) if err != nil { return fmt.Errorf("couldn't snapshot: %v", err) } bf, err := blockvol.OpenSnapshot(tempsnap) if err != nil { return fmt.Errorf("couldn't open snapshot: %v", err) } size := int64(bf.Size()) if progress { pb := progressutil.NewCopyProgressPrinter() pb.AddCopy(bf, path.Base(args[0]), size, output) err := pb.PrintAndWait(os.Stderr, 500*time.Millisecond, nil) if err != nil { return fmt.Errorf("couldn't copy: %v", err) } } else { n, err := io.Copy(output, bf) if err != nil { return fmt.Errorf("couldn't copy: %v", err) } if n != size { return fmt.Errorf("short read of %q", args[0]) } } err = blockvol.DeleteSnapshot(tempsnap) if err != nil { return fmt.Errorf("couldn't delete snapshot: %v", err) } fmt.Printf("copied %d bytes\n", size) return nil }
func (rb *RepositoryBackend) buildACIV21(layerIDs []string, dockerURL *common.ParsedDockerURL, outputDir string, tmpBaseDir string, compression common.Compression) ([]string, []*schema.ImageManifest, error) { layerFiles := make([]*os.File, len(layerIDs)) layerDatas := make([]types.DockerImageData, len(layerIDs)) tmpParentDir, err := ioutil.TempDir(tmpBaseDir, "docker2aci-") if err != nil { return nil, nil, err } defer os.RemoveAll(tmpParentDir) copier := progressutil.NewCopyProgressPrinter() var errChannels []chan error closers := make([]io.ReadCloser, len(layerIDs)) var wg sync.WaitGroup for i, layerID := range layerIDs { if err := common.ValidateLayerId(layerID); err != nil { return nil, nil, err } wg.Add(1) errChan := make(chan error, 1) errChannels = append(errChannels, errChan) // https://github.com/golang/go/wiki/CommonMistakes i := i // golang-- layerID := layerID go func() { defer wg.Done() manifest := rb.imageManifests[*dockerURL] layerIndex, ok := rb.layersIndex[layerID] if !ok { errChan <- fmt.Errorf("layer not found in manifest: %s", layerID) return } if len(manifest.History) <= layerIndex { errChan <- fmt.Errorf("history not found for layer %s", layerID) return } layerDatas[i] = types.DockerImageData{} if err := json.Unmarshal([]byte(manifest.History[layerIndex].V1Compatibility), &layerDatas[i]); err != nil { errChan <- fmt.Errorf("error unmarshaling layer data: %v", err) return } tmpDir, err := ioutil.TempDir(tmpParentDir, "") if err != nil { errChan <- fmt.Errorf("error creating dir: %v", err) return } layerFiles[i], closers[i], err = rb.getLayerV2(layerID, dockerURL, tmpDir, copier) if err != nil { errChan <- fmt.Errorf("error getting the remote layer: %v", err) return } errChan <- nil }() } // Need to wait for all of the readers to be added to the copier (which happens during rb.getLayerV2) wg.Wait() err = copier.PrintAndWait(os.Stderr, 500*time.Millisecond, nil) if err != nil { return nil, nil, err } for _, closer := range closers { if closer != nil { closer.Close() } } for _, errChan := range errChannels { err := <-errChan if err != nil { return nil, nil, err } } for _, layerFile := range layerFiles { err := layerFile.Sync() if err != nil { return nil, nil, err } } var aciLayerPaths []string var aciManifests []*schema.ImageManifest var curPwl []string for i := len(layerIDs) - 1; i >= 0; i-- { rb.debug.Println("Generating layer ACI...") aciPath, aciManifest, err := internal.GenerateACI(i, layerDatas[i], dockerURL, outputDir, layerFiles[i], curPwl, compression, rb.debug) if err != nil { return nil, nil, fmt.Errorf("error generating ACI: %v", err) } aciLayerPaths = append(aciLayerPaths, aciPath) aciManifests = append(aciManifests, aciManifest) curPwl = aciManifest.PathWhitelist layerFiles[i].Close() } return aciLayerPaths, aciManifests, nil }
func blockLoadAction(cmd *cobra.Command, args []string) error { if len(args) != 2 && len(args) != 3 { return torus.ErrUsage } input, err := getReaderFromArg(args[0]) if err != nil { return fmt.Errorf("couldn't open input: %v", err) } srv := createServer() defer srv.Close() fi, err := input.Stat() if err != nil { return fmt.Errorf("couldn't stat input file: %v", err) } size := uint64(fi.Size()) if len(args) == 3 { expSize, err := humanize.ParseBytes(args[2]) if err != nil { return fmt.Errorf("error parsing size %s: %v", args[2], err) } if expSize < size { return fmt.Errorf("size must be larger than input file") } size = expSize } err = block.CreateBlockVolume(srv.MDS, args[1], size) if err != nil { return fmt.Errorf("couldn't create block volume %s: %v", args[1], err) } blockvol, err := block.OpenBlockVolume(srv, args[1]) if err != nil { return fmt.Errorf("couldn't open block volume %s: %v", args[1], err) } f, err := blockvol.OpenBlockFile() if err != nil { return fmt.Errorf("couldn't open blockfile %s: %v", args[1], err) } defer f.Close() if progress { pb := progressutil.NewCopyProgressPrinter() pb.AddCopy(input, path.Base(args[0]), fi.Size(), f) err := pb.PrintAndWait(os.Stderr, 500*time.Millisecond, nil) if err != nil { return fmt.Errorf("couldn't copy: %v", err) } } else { _, err := io.Copy(f, input) if err != nil { return fmt.Errorf("couldn't copy: %v", err) } } err = f.Sync() if err != nil { return fmt.Errorf("couldn't sync: %v", err) } fmt.Printf("copied %d bytes\n", fi.Size()) return nil }
func (rb *RepositoryBackend) buildACIV22(layerIDs []string, dockerURL *common.ParsedDockerURL, outputDir string, tmpBaseDir string, compression common.Compression) ([]string, []*schema.ImageManifest, error) { layerFiles := make([]*os.File, len(layerIDs)) tmpParentDir, err := ioutil.TempDir(tmpBaseDir, "docker2aci-") if err != nil { return nil, nil, err } defer os.RemoveAll(tmpParentDir) copier := progressutil.NewCopyProgressPrinter() resultChan := make(chan layer, len(layerIDs)) for i, layerID := range layerIDs { if err := common.ValidateLayerId(layerID); err != nil { return nil, nil, err } // https://github.com/golang/go/wiki/CommonMistakes i := i // golang-- layerID := layerID go func() { tmpDir, err := ioutil.TempDir(tmpParentDir, "") if err != nil { resultChan <- layer{ index: i, err: fmt.Errorf("error creating dir: %v", err), } return } layerFile, closer, err := rb.getLayerV2(layerID, dockerURL, tmpDir, copier) if err != nil { resultChan <- layer{ index: i, err: fmt.Errorf("error getting the remote layer: %v", err), } return } resultChan <- layer{ index: i, file: layerFile, closer: closer, err: nil, } }() } var errs []error for i := 0; i < len(layerIDs); i++ { res := <-resultChan if res.closer != nil { defer res.closer.Close() } if res.file != nil { defer res.file.Close() } if res.err != nil { errs = append(errs, res.err) } layerFiles[res.index] = res.file } if len(errs) > 0 { return nil, nil, errs[0] } err = copier.PrintAndWait(os.Stderr, 500*time.Millisecond, nil) if err != nil { return nil, nil, err } for _, layerFile := range layerFiles { err := layerFile.Sync() if err != nil { return nil, nil, err } } var aciLayerPaths []string var aciManifests []*schema.ImageManifest var curPwl []string var i int for i = 0; i < len(layerIDs)-1; i++ { rb.debug.Println("Generating layer ACI...") aciPath, aciManifest, err := internal.GenerateACI22LowerLayer(dockerURL, layerIDs[i], outputDir, layerFiles[i], curPwl, compression) if err != nil { return nil, nil, fmt.Errorf("error generating ACI: %v", err) } aciLayerPaths = append(aciLayerPaths, aciPath) aciManifests = append(aciManifests, aciManifest) curPwl = aciManifest.PathWhitelist } rb.debug.Println("Generating layer ACI...") aciPath, aciManifest, err := internal.GenerateACI22TopLayer(dockerURL, rb.imageConfigs[*dockerURL], layerIDs[i], outputDir, layerFiles[i], curPwl, compression, aciManifests, rb.debug) if err != nil { return nil, nil, fmt.Errorf("error generating ACI: %v", err) } aciLayerPaths = append(aciLayerPaths, aciPath) aciManifests = append(aciManifests, aciManifest) return aciLayerPaths, aciManifests, nil }