// Get returns the rootfs path for the id. This will mount the dir at it's given path func (d *WindowsGraphDriver) Get(id, mountLabel string) (string, error) { var dir string d.Lock() defer d.Unlock() if d.active[id] == 0 { if err := hcsshim.ActivateLayer(d.info, id); err != nil { return "", err } } mountPath, err := hcsshim.GetLayerMountPath(d.info, id) if err != nil { return "", err } // If the layer has a mount path, use that. Otherwise, use the // folder path. if mountPath != "" { dir = mountPath } else { dir = d.dir(id) } d.active[id]++ return dir, nil }
// 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. // The layer should not be mounted when calling this function func (d *Driver) ApplyDiff(id, parent string, diff archive.Reader) (int64, error) { var layerChain []string if parent != "" { rPId, err := d.resolveID(parent) if err != nil { return 0, err } parentChain, err := d.getLayerChain(rPId) if err != nil { return 0, err } parentPath, err := hcsshim.GetLayerMountPath(d.info, rPId) if err != nil { return 0, err } layerChain = append(layerChain, parentPath) layerChain = append(layerChain, parentChain...) } size, err := d.importLayer(id, diff, layerChain) if err != nil { return 0, err } if err = d.setLayerChain(id, layerChain); err != nil { return 0, err } return size, 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 }
// Create creates a new layer with the given id. func (d *Driver) Create(id, parent, mountLabel string, storageOpt map[string]string) error { if len(storageOpt) != 0 { return fmt.Errorf("--storage-opt is not supported for windows") } rPId, err := d.resolveID(parent) if err != nil { return err } parentChain, err := d.getLayerChain(rPId) if err != nil { return err } var layerChain []string parentIsInit := strings.HasSuffix(rPId, "-init") if !parentIsInit && rPId != "" { parentPath, err := hcsshim.GetLayerMountPath(d.info, rPId) if err != nil { return err } layerChain = []string{parentPath} } layerChain = append(layerChain, parentChain...) if parentIsInit { if len(layerChain) == 0 { return fmt.Errorf("Cannot create a read/write layer without a parent layer.") } if err := hcsshim.CreateSandboxLayer(d.info, id, layerChain[0], layerChain); err != nil { return err } } else { if err := hcsshim.CreateLayer(d.info, id, rPId); err != nil { return err } } if _, err := os.Lstat(d.dir(parent)); err != nil { if err2 := hcsshim.DestroyLayer(d.info, id); err2 != nil { logrus.Warnf("Failed to DestroyLayer %s: %s", id, err2) } return fmt.Errorf("Cannot create layer with missing parent %s: %s", parent, err) } if err := d.setLayerChain(id, layerChain); err != nil { if err2 := hcsshim.DestroyLayer(d.info, id); err2 != nil { logrus.Warnf("Failed to DestroyLayer %s: %s", id, err2) } return err } return 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 }
// 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 }
// 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. // The layer should not be mounted when calling this function func (d *Driver) ApplyDiff(id, parent string, diff archive.Reader) (int64, error) { if d.info.Flavour == diffDriver { start := time.Now().UTC() logrus.Debugf("WindowsGraphDriver ApplyDiff: Start untar layer") destination := d.dir(id) destination = filepath.Dir(destination) size, err := chrootarchive.ApplyUncompressedLayer(destination, diff, nil) if err != nil { return 0, err } logrus.Debugf("WindowsGraphDriver ApplyDiff: Untar time: %vs", time.Now().UTC().Sub(start).Seconds()) return size, nil } var layerChain []string if parent != "" { rPId, err := d.resolveID(parent) if err != nil { return 0, err } parentChain, err := d.getLayerChain(rPId) if err != nil { return 0, err } parentPath, err := hcsshim.GetLayerMountPath(d.info, rPId) if err != nil { return 0, err } layerChain = append(layerChain, parentPath) layerChain = append(layerChain, parentChain...) } size, err := d.importLayer(id, diff, layerChain) if err != nil { return 0, err } if err = d.setLayerChain(id, layerChain); err != nil { return 0, err } return size, nil }
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 (d *Driver) create(id, parent, mountLabel string, readOnly bool, storageOpt map[string]string) error { if len(storageOpt) != 0 { return fmt.Errorf("--storage-opt is not supported for windows") } rPId, err := d.resolveID(parent) if err != nil { return err } parentChain, err := d.getLayerChain(rPId) if err != nil { return err } var layerChain []string if rPId != "" { parentPath, err := hcsshim.GetLayerMountPath(d.info, rPId) if err != nil { return err } if _, err := os.Stat(filepath.Join(parentPath, "Files")); err == nil { // This is a legitimate parent layer (not the empty "-init" layer), // so include it in the layer chain. layerChain = []string{parentPath} } } layerChain = append(layerChain, parentChain...) if readOnly { if err := hcsshim.CreateLayer(d.info, id, rPId); err != nil { return err } } else { var parentPath string if len(layerChain) != 0 { parentPath = layerChain[0] } if isTP5OrOlder() { // Pre-create the layer directory, providing an ACL to give the Hyper-V Virtual Machines // group access. This is necessary to ensure that Hyper-V containers can access the // virtual machine data. This is not necessary post-TP5. path, err := syscall.UTF16FromString(filepath.Join(d.info.HomeDir, id)) if err != nil { return err } // Give system and administrators full control, and VMs read, write, and execute. // Mark these ACEs as inherited. sd, err := winio.SddlToSecurityDescriptor("D:(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)(A;OICI;FRFWFX;;;S-1-5-83-0)") if err != nil { return err } err = syscall.CreateDirectory(&path[0], &syscall.SecurityAttributes{ Length: uint32(unsafe.Sizeof(syscall.SecurityAttributes{})), SecurityDescriptor: uintptr(unsafe.Pointer(&sd[0])), }) if err != nil { return err } } if err := hcsshim.CreateSandboxLayer(d.info, id, parentPath, layerChain); err != nil { return err } } if _, err := os.Lstat(d.dir(parent)); err != nil { if err2 := hcsshim.DestroyLayer(d.info, id); err2 != nil { logrus.Warnf("Failed to DestroyLayer %s: %s", id, err2) } return fmt.Errorf("Cannot create layer with missing parent %s: %s", parent, err) } if err := d.setLayerChain(id, layerChain); err != nil { if err2 := hcsshim.DestroyLayer(d.info, id); err2 != nil { logrus.Warnf("Failed to DestroyLayer %s: %s", id, err2) } return err } return nil }
func (d *Driver) create(id, parent, mountLabel string, readOnly bool, storageOpt map[string]string) error { rPId, err := d.resolveID(parent) if err != nil { return err } parentChain, err := d.getLayerChain(rPId) if err != nil { return err } var layerChain []string if rPId != "" { parentPath, err := hcsshim.GetLayerMountPath(d.info, rPId) if err != nil { return err } if _, err := os.Stat(filepath.Join(parentPath, "Files")); err == nil { // This is a legitimate parent layer (not the empty "-init" layer), // so include it in the layer chain. layerChain = []string{parentPath} } } layerChain = append(layerChain, parentChain...) if readOnly { if err := hcsshim.CreateLayer(d.info, id, rPId); err != nil { return err } } else { var parentPath string if len(layerChain) != 0 { parentPath = layerChain[0] } if err := hcsshim.CreateSandboxLayer(d.info, id, parentPath, layerChain); err != nil { return err } storageOptions, err := parseStorageOpt(storageOpt) if err != nil { return fmt.Errorf("Failed to parse storage options - %s", err) } if storageOptions.size != 0 { if err := hcsshim.ExpandSandboxSize(d.info, id, storageOptions.size); err != nil { return err } } } if _, err := os.Lstat(d.dir(parent)); err != nil { if err2 := hcsshim.DestroyLayer(d.info, id); err2 != nil { logrus.Warnf("Failed to DestroyLayer %s: %s", id, err2) } return fmt.Errorf("Cannot create layer with missing parent %s: %s", parent, err) } if err := d.setLayerChain(id, layerChain); err != nil { if err2 := hcsshim.DestroyLayer(d.info, id); err2 != nil { logrus.Warnf("Failed to DestroyLayer %s: %s", id, err2) } return err } return nil }
func (d *Driver) Create(id, parent string) error { rPId, err := d.resolveId(parent) if err != nil { return err } parentChain, err := d.getLayerChain(rPId) if err != nil { return err } var layerChain []string parentIsInit := strings.HasSuffix(rPId, "-init") if !parentIsInit && rPId != "" { parentPath, err := hcsshim.GetLayerMountPath(d.info, rPId) if err != nil { return err } layerChain = []string{parentPath} } layerChain = append(layerChain, parentChain...) if parentIsInit { if len(layerChain) == 0 { return fmt.Errorf("Cannot create a read/write layer without a parent layer.") } if err := hcsshim.CreateSandboxLayer(d.info, id, layerChain[0], layerChain); err != nil { return err } } else { if err := hcsshim.CreateLayer(d.info, id, rPId); err != nil { return err } } if _, err := os.Lstat(d.dir(parent)); err == nil { if err := d.setLayerChain(id, layerChain); err != nil { if err2 := hcsshim.DestroyLayer(d.info, id); err2 != nil { logrus.Warnf("Failed to DestroyLayer %s: %s", id, err) } return err } } else if os.IsNotExist(err) { // If the parent doesn't exist, this must be a special creation for an image // registered at an alternate location. Use the parent id as the alternate ID. if err := d.setId(id, parent); err != nil { if err2 := hcsshim.DestroyLayer(d.info, id); err2 != nil { logrus.Warnf("Failed to DestroyLayer %s: %s", id, err) } return err } } else { if err2 := hcsshim.DestroyLayer(d.info, id); err2 != nil { logrus.Warnf("Failed to DestroyLayer %s: %s", id, err) } return err } return 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) }
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) }