func (d *Driver) ApplyDiff(id, parent string, diff archive.ArchiveReader) (size int64, err error) { // Mount the root filesystem so we can apply the diff/layer. layerFs, err := d.Get(id, "") if err != nil { return 0, err } defer d.Put(id) start := time.Now().UTC() glog.V(1).Info("Start untar layer") if size, err = chrootarchive.ApplyLayer(layerFs, diff); err != nil { return 0, err } glog.V(1).Infof("Untar time: %vs", time.Now().UTC().Sub(start).Seconds()) root := path.Join(utils.HYPER_ROOT, "vbox") idDisk := fmt.Sprintf("%s/images/%s.vdi", root, id) if _, err = os.Stat(idDisk); err != nil { return 0, err } if err = d.VmMountLayer(id); err != nil { return 0, err } // XXX should remove the image/container's directory return size, err }
func (d *Driver) ApplyDiff(id string, parent string, diff archive.ArchiveReader) (size int64, err error) { dir := d.dir(id) if parent == "" { return 0, ErrApplyDiffFallback } parentRootDir := path.Join(d.dir(parent), "root") if _, err := os.Stat(parentRootDir); err != nil { return 0, ErrApplyDiffFallback } // We now know there is a parent, and it has a "root" directory containing // the full root filesystem. We can just hardlink it and apply the // layer. This relies on two things: // 1) ApplyDiff is only run once on a clean (no writes to upper layer) container // 2) ApplyDiff doesn't do any in-place writes to files (would break hardlinks) // These are all currently true and are not expected to break tmpRootDir, err := ioutil.TempDir(dir, "tmproot") if err != nil { return 0, err } defer func() { if err != nil { os.RemoveAll(tmpRootDir) } else { os.RemoveAll(path.Join(dir, "upper")) os.RemoveAll(path.Join(dir, "work")) os.RemoveAll(path.Join(dir, "merged")) os.RemoveAll(path.Join(dir, "lower-id")) } }() if err = copyDir(parentRootDir, tmpRootDir, CopyHardlink); err != nil { return 0, err } if size, err = chrootarchive.ApplyLayer(tmpRootDir, diff); err != nil { return 0, err } rootDir := path.Join(dir, "root") if err := os.Rename(tmpRootDir, rootDir); err != nil { return 0, err } return }
// ApplyDiff extracts the changeset from the given diff into the // layer with the specified id and parent, returning the size of the // new layer in bytes. func (gdw *naiveDiffDriver) ApplyDiff(id, parent string, diff archive.ArchiveReader) (size int64, err error) { driver := gdw.ProtoDriver // Mount the root filesystem so we can apply the diff/layer. layerFs, err := driver.Get(id, "") if err != nil { return } defer driver.Put(id) start := time.Now().UTC() glog.V(1).Info("Start untar layer") if size, err = chrootarchive.ApplyLayer(layerFs, diff); err != nil { return } glog.V(1).Infof("Untar time: %vs", time.Now().UTC().Sub(start).Seconds()) return }