예제 #1
0
// 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
}
예제 #2
0
// 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
}
예제 #3
0
// 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
}
예제 #4
0
파일: windows.go 프로젝트: contiv/docker
// 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
}
예제 #5
0
// 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
}
예제 #6
0
파일: windows.go 프로젝트: ch3lo/docker
// 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
}
예제 #7
0
// 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)
}
예제 #8
0
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
}
예제 #9
0
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
}
예제 #10
0
파일: windows.go 프로젝트: contiv/docker
// 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
}