// 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 }
// 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 }
// Put adds a new layer to the driver. func (d *Driver) Put(id string) error { logrus.Debugf("WindowsGraphDriver Put() id %s", id) rID, err := d.resolveID(id) if err != nil { return err } d.Lock() defer d.Unlock() if d.active[rID] > 1 { d.active[rID]-- } else if d.active[rID] == 1 { if err := hcsshim.UnprepareLayer(d.info, rID); err != nil { return err } if err := hcsshim.DeactivateLayer(d.info, rID); err != nil { return err } delete(d.active, rID) } return 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 }
// Put adds a new layer to the driver. func (d *Driver) Put(id string) error { logrus.Debugf("WindowsGraphDriver Put() id %s", id) rID, err := d.resolveID(id) if err != nil { return err } if err := hcsshim.UnprepareLayer(d.info, rID); err != nil { return err } return hcsshim.DeactivateLayer(d.info, rID) }
// 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 not 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 } if err := hcsshim.ActivateLayer(d.info, rID); err != nil { return nil, err } defer func() { if err2 := hcsshim.DeactivateLayer(d.info, rID); err2 != nil { logrus.Errorf("changes() failed to DeactivateLayer %s %s: %s", id, rID, err2) } }() 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 }
func (d *WindowsGraphDriver) Put(id string) error { logrus.Debugf("WindowsGraphDriver Put() id %s", id) d.Lock() defer d.Unlock() if d.active[id] > 1 { d.active[id]-- } else if d.active[id] == 1 { if err := hcsshim.DeactivateLayer(d.info, id); err != nil { return err } delete(d.active, id) } return nil }
func (d *WindowsGraphDriver) CopyDiff(sourceId, id string, parentLayerPaths []string) error { d.Lock() defer d.Unlock() if d.info.Flavour == filterDriver && d.active[sourceId] == 0 { if err := hcsshim.ActivateLayer(d.info, sourceId); err != nil { return err } defer func() { err := hcsshim.DeactivateLayer(d.info, sourceId) if err != nil { logrus.Warnf("Failed to Deactivate %s: %s", sourceId, err) } }() } return hcsshim.CopyLayer(d.info, sourceId, id, parentLayerPaths) }
// 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) }
// Put adds a new layer to the driver. func (d *Driver) Put(id string) error { logrus.Debugf("WindowsGraphDriver Put() id %s", id) rID, err := d.resolveID(id) if err != nil { return err } if count := d.ctr.Decrement(rID); count > 0 { return nil } d.cacheMu.Lock() delete(d.cache, rID) d.cacheMu.Unlock() if err := hcsshim.UnprepareLayer(d.info, rID); err != nil { return err } return hcsshim.DeactivateLayer(d.info, rID) }
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 main() { if len(os.Args) != 2 { fmt.Print(` This sample create a new container runs ping and then destroys the container. Usage: sample.exe <base container Id> To get the base container id for "microsoft/windowsservercore" use the following PS snippet: Split-Path -Leaf (docker inspect microsoft/windowsservercore | ConvertFrom-Json).GraphDriver.Data.Dir `) os.Exit(1) } windowsbaseId := os.Args[1] di := hcsshim.DriverInfo{ HomeDir: homeDir, Flavour: filterDriver, } imgData, err := hcsshim.GetSharedBaseImages() panicIf(err) fmt.Println(imgData) hcsNets, err := hcsshim.HNSListNetworkRequest("GET", "", "") panicIf(err) fmt.Println(hcsNets) virtualNetworkId := "" for _, n := range hcsNets { if n.Name == "nat" { virtualNetworkId = n.Id } } // https://github.com/docker/libnetwork/blob/f9a1590164b878e668eabf889dd79fb6af8eaced/drivers/windows/windows.go#L284 endpointRequest := hcsshim.HNSEndpoint{ VirtualNetwork: virtualNetworkId, } endpointRequestJson, err := json.Marshal(endpointRequest) panicIf(err) endpoint, err := hcsshim.HNSEndpointRequest("POST", "", string(endpointRequestJson)) panicIf(err) fmt.Println(*endpoint) windowsservercorePath, err := hcsshim.GetLayerMountPath(di, windowsbaseId) panicIf(err) fmt.Println(windowsservercorePath) layerChain, err := GetLayerChain(windowsservercorePath) panicIf(err) fmt.Println(layerChain) newContainerId := stringid.GenerateNonCryptoID() layerFolderPath, volumeMountPath, err := CreateAndActivateContainerLayer(di, newContainerId, windowsservercorePath) panicIf(err) containerConfig := hcsshim.ContainerConfig{ SystemType: "Container", Name: newContainerId, Owner: "Garden", LayerFolderPath: layerFolderPath, VolumePath: volumeMountPath, IgnoreFlushesDuringBoot: true, EndpointList: []string{endpoint.Id}, } // https://github.com/docker/docker/blob/cf58eb437c4229e876f2d952a228b603a074e584/libcontainerd/client_windows.go#L111-L121 for _, layerPath := range layerChain { id, err := hcsshim.NameToGuid(GetLayerId(layerPath)) panicIf(err) containerConfig.Layers = append(containerConfig.Layers, hcsshim.Layer{ Path: layerPath, ID: id.ToString(), }) } c, err := hcsshim.CreateContainer(newContainerId, &containerConfig) panicIf(err) fmt.Println(c) err = c.Start() panicIf(err) stats, err := c.Statistics() panicIf(err) fmt.Println(stats) processConfig := hcsshim.ProcessConfig{ CommandLine: "ping 127.0.0.1", WorkingDirectory: "C:\\", //CreateStdErrPipe: true, //CreateStdInPipe: true, //CreateStdOutPipe: true, } p, err := c.CreateProcess(&processConfig) panicIf(err) fmt.Println(p) err = p.Wait() panicIf(err) err = c.Shutdown() warnIf(err) err = c.Terminate() warnIf(err) endpoint, err = hcsshim.HNSEndpointRequest("DELETE", endpoint.Id, "") warnIf(err) err = hcsshim.UnprepareLayer(di, newContainerId) warnIf(err) err = hcsshim.DeactivateLayer(di, newContainerId) warnIf(err) err = hcsshim.DestroyLayer(di, newContainerId) warnIf(err) }
// 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 }
func main() { if len(os.Args) != 2 { fmt.Print(` This sample create a new container runs ping and then destroys the container. Usage: sample.exe <base container Id> To get the base container id for "microsoft/windowsservercore" use the following PS snippet: Split-Path -Leaf (docker inspect microsoft/windowsservercore | ConvertFrom-Json).GraphDriver.Data.Dir `) os.Exit(1) } windowsbaseId := os.Args[1] guid, err := hcsshim.NameToGuid(windowsbaseId) panicIf(err) windowsbaseGuid := guid.ToString() di := hcsshim.DriverInfo{ HomeDir: homeDir, Flavour: filterDriver, } imgData, err := hcsshim.GetSharedBaseImages() panicIf(err) fmt.Println(imgData) windowsservercorePath, err := hcsshim.GetLayerMountPath(di, windowsbaseId) panicIf(err) fmt.Println(windowsservercorePath) newContainerId := stringid.GenerateNonCryptoID() layerFolderPath, volumeMountPath, err := CreateAndActivateContainerLayer(di, newContainerId, windowsservercorePath) panicIf(err) containerConfig := hcsshim.ContainerConfig{ SystemType: "Container", Name: newContainerId, Owner: "Garden", LayerFolderPath: layerFolderPath, VolumePath: volumeMountPath, Layers: []hcsshim.Layer{ hcsshim.Layer{Path: windowsservercorePath, ID: windowsbaseGuid}, }, IgnoreFlushesDuringBoot: true, } c, err := hcsshim.CreateContainer(newContainerId, &containerConfig) panicIf(err) fmt.Println(c) err = c.Start() panicIf(err) stats, err := c.Statistics() panicIf(err) fmt.Println(stats) processConfig := hcsshim.ProcessConfig{ CommandLine: "ping 127.0.0.1", WorkingDirectory: "C:\\", //CreateStdErrPipe: true, //CreateStdInPipe: true, //CreateStdOutPipe: true, } p, err := c.CreateProcess(&processConfig) panicIf(err) fmt.Println(p) err = p.Wait() panicIf(err) err = c.Shutdown() warnIf(err) err = c.Terminate() warnIf(err) err = hcsshim.UnprepareLayer(di, newContainerId) warnIf(err) err = hcsshim.DeactivateLayer(di, newContainerId) warnIf(err) err = hcsshim.DestroyLayer(di, newContainerId) warnIf(err) }