func diff(id, parent string) (diff archive.Archive, err error) { // create pod // start or replace pod glog.Infof("Diff between %s and %s", id, parent) layerFs := "/tmp/test1" if parent == "" { archive, err := archive.Tar(layerFs, archive.Uncompressed) if err != nil { return nil, err } return ioutils.NewReadCloserWrapper(archive, func() error { err := archive.Close() return err }), nil } parentFs := "/tmp/test2" changes, err := archive.ChangesDirs(layerFs, parentFs) if err != nil { return nil, err } archive, err := archive.ExportChanges(layerFs, changes) if err != nil { return nil, err } return ioutils.NewReadCloserWrapper(archive, func() error { err := archive.Close() return err }), nil }
// Diff produces an archive of the changes between the specified // layer and its parent layer which may be "". func (gdw *naiveDiffDriver) Diff(id, parent string) (arch archive.Archive, err error) { glog.Error("Run the graphdriver Diff function") driver := gdw.ProtoDriver layerFs, err := driver.Get(id, "") if err != nil { return nil, err } defer func() { if err != nil { driver.Put(id) } }() if parent == "" { archive, err := archive.Tar(layerFs, archive.Uncompressed) if err != nil { return nil, err } return ioutils.NewReadCloserWrapper(archive, func() error { err := archive.Close() driver.Put(id) return err }), nil } parentFs, err := driver.Get(parent, "") if err != nil { return nil, err } defer driver.Put(parent) changes, err := archive.ChangesDirs(layerFs, parentFs) if err != nil { return nil, err } archive, err := archive.ExportChanges(layerFs, changes) if err != nil { return nil, err } return ioutils.NewReadCloserWrapper(archive, func() error { err := archive.Close() driver.Put(id) return err }), nil }
// NewReadCloserWrapper returns a wrapper which puts the bufio.Reader back // into the pool and closes the reader if it's an io.ReadCloser. func (bufPool *BufioReaderPool) NewReadCloserWrapper(buf *bufio.Reader, r io.Reader) io.ReadCloser { return ioutils.NewReadCloserWrapper(r, func() error { if readCloser, ok := r.(io.ReadCloser); ok { readCloser.Close() } bufPool.Put(buf) return nil }) }
func (container *Container) ExportRw() (archive.Archive, error) { if container.daemon == nil { return nil, fmt.Errorf("Can't load storage driver for unregistered container %s", container.ID) } glog.V(2).Infof("container address %p, daemon address %p", container, container.daemon) archive, err := container.daemon.Diff(container) // archive, err := diff("/tmp/test1/", "") if err != nil { return nil, err } return ioutils.NewReadCloserWrapper(archive, func() error { err := archive.Close() return err }), nil return nil, nil }
func (d *Driver) Diff(id, parent string) (diff archive.Archive, err error) { if d.daemon == nil { if err := d.Setup(); err != nil { return nil, err } } var ( podData string tgtDisk string = "" code int cause string ) srcDisk := fmt.Sprintf("%s/images/%s.vdi", d.RootPath(), id) if parent != "" { tgtDisk = fmt.Sprintf("%s/images/%s.vdi", d.RootPath(), parent) } outDir := path.Join(utils.HYPER_ROOT, "tar") if err := os.MkdirAll(outDir, 0755); err != nil { return nil, err } uuid, err := virtualbox.GetMediumUUID(srcDisk) if err == nil { srcDisk = uuid } // create pod podId := "diff-" + id[:10] podData, err = MakeDiffPod(podId, "puller:latest", id, srcDisk, tgtDisk, outDir) if err != nil { return nil, err } // start or replace pod vm, ok := d.daemon.VmList[d.pullVm] if !ok { return nil, fmt.Errorf("can not find VM(%s)", d.pullVm) } if vm.Status == types.S_VM_IDLE { code, cause, err = d.daemon.StartPod(podId, podData, d.pullVm, nil, false, true, types.VM_KEEP_AFTER_SHUTDOWN) if err != nil { glog.Errorf("Code is %d, Cause is %s, %s", code, cause, err.Error()) d.daemon.KillVm(d.pullVm) return nil, err } vm := d.daemon.VmList[d.pullVm] // wait for cmd finish _, _, ret3, err := vm.GetVmChan() if err != nil { glog.Error(err.Error()) return nil, err } subVmStatus := ret3.(chan *types.VmResponse) var vmResponse *types.VmResponse for { vmResponse = <-subVmStatus if vmResponse.VmId == d.pullVm { if vmResponse.Code == types.E_POD_FINISHED { glog.Infof("Got E_POD_FINISHED code response") break } } } d.daemon.PodList[podId].Vm = d.pullVm // release pod from VM code, cause, err = d.daemon.StopPod(podId, "no") if err != nil { glog.Errorf("Code is %d, Cause is %s, %s", code, cause, err.Error()) d.daemon.KillVm(d.pullVm) return nil, err } d.daemon.CleanPod(podId) } else { glog.Errorf("pull vm should not be associated") return nil, fmt.Errorf("pull vm is not idle") } tarFile := outDir + "/" + id + ".tar" if _, err := os.Stat(tarFile); err != nil { // If the parent is nil, the first layer is also nil. // So we may not got tar file if parent == "" { layerFs := fmt.Sprintf("%s/diff/%s", d.RootPath(), id) archive, err := archive.Tar(layerFs, archive.Uncompressed) if err != nil { return nil, err } return ioutils.NewReadCloserWrapper(archive, func() error { err := archive.Close() return err }), nil } else { return nil, fmt.Errorf("the out tar file is not exist") } } f, err := os.Open(tarFile) if err != nil { return nil, err } var archive io.ReadCloser archive = ioutil.NopCloser(f) glog.Infof("Diff between %s and %s", id, parent) return ioutils.NewReadCloserWrapper(archive, func() error { err := archive.Close() return err }), nil }