// Diff produces an archive of the changes between the specified // layer and its parent layer which may be "". // The layer should be mounted when calling this function func (d *Driver) Diff(id, parent string) (_ archive.Archive, err error) { rID, err := d.resolveID(id) if err != nil { return } layerChain, err := d.getLayerChain(rID) if err != nil { return } // this is assuming that the layer is unmounted if err := hcsshim.UnprepareLayer(d.info, rID); err != nil { return nil, err } prepare := func() { if err := hcsshim.PrepareLayer(d.info, rID, layerChain); err != nil { logrus.Warnf("Failed to Deactivate %s: %s", rID, err) } } arch, err := d.exportLayer(rID, layerChain) if err != nil { prepare() return } return ioutils.NewReadCloserWrapper(arch, func() error { err := arch.Close() prepare() return err }), nil }
// Returns: LayerFolderPaht, VolumePath func CreateAndActivateContainerLayer(di hcsshim.DriverInfo, containerLayerId, parentLayerPath string) (string, string, error) { var err error parentLayerId := GetLayerId(parentLayerPath) log.Printf("Parent layer %v path has Id %v", parentLayerPath, parentLayerId) err = hcsshim.CreateSandboxLayer(di, containerLayerId, parentLayerPath, []string{parentLayerPath}) if err != nil { return "", "", err } err = hcsshim.ActivateLayer(di, containerLayerId) if err != nil { return "", "", err } err = hcsshim.PrepareLayer(di, containerLayerId, []string{parentLayerPath}) if err != nil { return "", "", err } volumeMountPath, err := hcsshim.GetLayerMountPath(di, containerLayerId) if err != nil { return "", "", err } log.Printf("Container layer volume path %v", volumeMountPath) return GetLayerPath(di, containerLayerId), volumeMountPath, nil }
// Get returns the rootfs path for the id. This will mount the dir at it's given path. func (d *Driver) Get(id, mountLabel string) (string, error) { logrus.Debugf("WindowsGraphDriver Get() id %s mountLabel %s", id, mountLabel) var dir string rID, err := d.resolveID(id) if err != nil { return "", err } if count := d.ctr.Increment(rID); count > 1 { return d.cache[rID], nil } // Getting the layer paths must be done outside of the lock. layerChain, err := d.getLayerChain(rID) if err != nil { d.ctr.Decrement(rID) return "", err } if err := hcsshim.ActivateLayer(d.info, rID); err != nil { d.ctr.Decrement(rID) return "", err } if err := hcsshim.PrepareLayer(d.info, rID, layerChain); err != nil { d.ctr.Decrement(rID) if err2 := hcsshim.DeactivateLayer(d.info, rID); err2 != nil { logrus.Warnf("Failed to Deactivate %s: %s", id, err) } return "", err } mountPath, err := hcsshim.GetLayerMountPath(d.info, rID) if err != nil { d.ctr.Decrement(rID) if err2 := hcsshim.DeactivateLayer(d.info, rID); err2 != nil { logrus.Warnf("Failed to Deactivate %s: %s", id, err) } return "", err } d.cacheMu.Lock() d.cache[rID] = mountPath d.cacheMu.Unlock() // If the layer has a mount path, use that. Otherwise, use the // folder path. if mountPath != "" { dir = mountPath } else { dir = d.dir(id) } return dir, nil }
// Diff produces an archive of the changes between the specified // layer and its parent layer which may be "". func (d *Driver) Diff(id, parent string) (_ archive.Archive, err error) { rID, err := d.resolveID(id) if err != nil { return } // Getting the layer paths must be done outside of the lock. layerChain, err := d.getLayerChain(rID) if err != nil { return } var undo func() d.Lock() // To support export, a layer must be activated but not prepared. if d.info.Flavour == filterDriver { if d.active[rID] == 0 { if err = hcsshim.ActivateLayer(d.info, rID); err != nil { d.Unlock() return } undo = func() { if err := hcsshim.DeactivateLayer(d.info, rID); err != nil { logrus.Warnf("Failed to Deactivate %s: %s", rID, err) } } } else { if err = hcsshim.UnprepareLayer(d.info, rID); err != nil { d.Unlock() return } undo = func() { if err := hcsshim.PrepareLayer(d.info, rID, layerChain); err != nil { logrus.Warnf("Failed to re-PrepareLayer %s: %s", rID, err) } } } } d.Unlock() arch, err := d.exportLayer(rID, layerChain) if err != nil { undo() return } return ioutils.NewReadCloserWrapper(arch, func() error { defer undo() return arch.Close() }), nil }
// Changes produces a list of changes between the specified layer // and its parent layer. If parent is "", then all changes will be ADD changes. // The layer should be mounted when calling this function func (d *Driver) Changes(id, parent string) ([]archive.Change, error) { rID, err := d.resolveID(id) if err != nil { return nil, err } parentChain, err := d.getLayerChain(rID) if err != nil { return nil, err } // this is assuming that the layer is unmounted if err := hcsshim.UnprepareLayer(d.info, rID); err != nil { return nil, err } defer func() { if err := hcsshim.PrepareLayer(d.info, rID, parentChain); err != nil { logrus.Warnf("Failed to Deactivate %s: %s", rID, err) } }() var changes []archive.Change err = winio.RunWithPrivilege(winio.SeBackupPrivilege, func() error { r, err := hcsshim.NewLayerReader(d.info, id, parentChain) if err != nil { return err } defer r.Close() for { name, _, fileInfo, err := r.Next() if err == io.EOF { return nil } if err != nil { return err } name = filepath.ToSlash(name) if fileInfo == nil { changes = append(changes, archive.Change{Path: name, Kind: archive.ChangeDelete}) } else { // Currently there is no way to tell between an add and a modify. changes = append(changes, archive.Change{Path: name, Kind: archive.ChangeModify}) } } }) if err != nil { return nil, err } return changes, nil }
// Get returns the rootfs path for the id. This will mount the dir at it's given path func (d *Driver) Get(id, mountLabel string) (string, error) { logrus.Debugf("WindowsGraphDriver Get() id %s mountLabel %s", id, mountLabel) var dir string d.Lock() defer d.Unlock() rId, err := d.resolveId(id) if err != nil { return "", err } // Getting the layer paths must be done outside of the lock. layerChain, err := d.getLayerChain(rId) if err != nil { return "", err } if d.active[rId] == 0 { if err := hcsshim.ActivateLayer(d.info, rId); err != nil { return "", err } if err := hcsshim.PrepareLayer(d.info, rId, layerChain); err != nil { if err2 := hcsshim.DeactivateLayer(d.info, rId); err2 != nil { logrus.Warnf("Failed to Deactivate %s: %s", id, err) } return "", err } } mountPath, err := hcsshim.GetLayerMountPath(d.info, rId) if err != nil { if err2 := hcsshim.DeactivateLayer(d.info, rId); err2 != nil { logrus.Warnf("Failed to Deactivate %s: %s", id, err) } return "", err } d.active[rId]++ // If the layer has a mount path, use that. Otherwise, use the // folder path. if mountPath != "" { dir = mountPath } else { dir = d.dir(id) } return dir, nil }
// Diff produces an archive of the changes between the specified // layer and its parent layer which may be "". func (d *Driver) Diff(id, parent string) (arch archive.Archive, err error) { rID, err := d.resolveID(id) if err != nil { return } // Getting the layer paths must be done outside of the lock. layerChain, err := d.getLayerChain(rID) if err != nil { return } d.Lock() // To support export, a layer must be activated but not prepared. if d.info.Flavour == filterDriver { if d.active[rID] == 0 { if err = hcsshim.ActivateLayer(d.info, rID); err != nil { d.Unlock() return } defer func() { if err := hcsshim.DeactivateLayer(d.info, rID); err != nil { logrus.Warnf("Failed to Deactivate %s: %s", rID, err) } }() } else { if err = hcsshim.UnprepareLayer(d.info, rID); err != nil { d.Unlock() return } defer func() { if err := hcsshim.PrepareLayer(d.info, rID, layerChain); err != nil { logrus.Warnf("Failed to re-PrepareLayer %s: %s", rID, err) } }() } } d.Unlock() return d.exportLayer(rID, layerChain) }
func GetLayerPath2(di hcsshim.DriverInfo, layerId, parentLayerPath string) (string, error) { parentLayerId := GetLayerId(parentLayerPath) err := hcsshim.CreateLayer(di, layerId, parentLayerId) if err != nil { return "", err } err = hcsshim.ActivateLayer(di, layerId) if err != nil { return "", err } err = hcsshim.PrepareLayer(di, layerId, []string{parentLayerPath}) if err != nil { return "", err } layerFolderPath, err := hcsshim.GetLayerMountPath(di, layerId) if err != nil { return "", err } log.Printf("Container layer folder path %v", layerFolderPath) err = hcsshim.UnprepareLayer(di, layerId) if err != nil { return "", err } err = hcsshim.DeactivateLayer(di, layerId) if err != nil { return "", err } err = hcsshim.DestroyLayer(di, layerId) if err != nil { return "", err } return layerFolderPath, nil }
func (container *Container) PrepareStorage() error { if wd, ok := container.daemon.driver.(*windows.WindowsGraphDriver); ok { // Get list of paths to parent layers. var ids []string if container.ImageID != "" { img, err := container.daemon.graph.Get(container.ImageID) if err != nil { return err } ids, err = container.daemon.graph.ParentLayerIds(img) if err != nil { return err } } if err := hcsshim.PrepareLayer(wd.Info(), container.ID, wd.LayerIdsToPaths(ids)); err != nil { return err } } return nil }
// Changes produces a list of changes between the specified layer // and its parent layer. If parent is "", then all changes will be ADD changes. func (d *Driver) Changes(id, parent string) ([]archive.Change, error) { rID, err := d.resolveID(id) if err != nil { return nil, err } parentChain, err := d.getLayerChain(rID) if err != nil { return nil, err } d.Lock() if d.info.Flavour == filterDriver { if d.active[rID] == 0 { if err = hcsshim.ActivateLayer(d.info, rID); err != nil { d.Unlock() return nil, err } defer func() { if err := hcsshim.DeactivateLayer(d.info, rID); err != nil { logrus.Warnf("Failed to Deactivate %s: %s", rID, err) } }() } else { if err = hcsshim.UnprepareLayer(d.info, rID); err != nil { d.Unlock() return nil, err } defer func() { if err := hcsshim.PrepareLayer(d.info, rID, parentChain); err != nil { logrus.Warnf("Failed to re-PrepareLayer %s: %s", rID, err) } }() } } d.Unlock() r, err := hcsshim.NewLayerReader(d.info, id, parentChain) if err != nil { return nil, err } defer r.Close() var changes []archive.Change for { name, _, fileInfo, err := r.Next() if err == io.EOF { break } if err != nil { return nil, err } name = filepath.ToSlash(name) if fileInfo == nil { changes = append(changes, archive.Change{name, archive.ChangeDelete}) } else { // Currently there is no way to tell between an add and a modify. changes = append(changes, archive.Change{name, archive.ChangeModify}) } } return changes, nil }