// 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 }
// importLayer adds a new layer to the tag and graph store based on the given data. func (d *Driver) importLayer(id string, layerData archive.Reader, parentLayerPaths []string) (size int64, err error) { layerFolder := d.dir(id) tempFolder := layerFolder + "-" + strconv.FormatUint(uint64(random.Rand.Uint32()), 10) if err = os.MkdirAll(tempFolder, 0755); err != nil { logrus.Errorf("Could not create %s %s", tempFolder, err) return } defer func() { _, folderName := filepath.Split(tempFolder) if err2 := hcsshim.DestroyLayer(d.info, folderName); err2 != nil { logrus.Warnf("Couldn't clean-up tempFolder: %s %s", tempFolder, err2) } }() start := time.Now().UTC() logrus.Debugf("Start untar layer") if size, err = chrootarchive.ApplyLayer(tempFolder, layerData); err != nil { return } logrus.Debugf("Untar time: %vs", time.Now().UTC().Sub(start).Seconds()) if err = hcsshim.ImportLayer(d.info, id, tempFolder, parentLayerPaths); err != nil { return } return }
// Remove unmounts and removes the dir information. func (d *Driver) Remove(id string) error { rID, err := d.resolveID(id) if err != nil { return err } os.RemoveAll(filepath.Join(d.info.HomeDir, "sysfile-backups", rID)) // ok to fail return hcsshim.DestroyLayer(d.info, rID) }
// Remove unmounts and removes the dir information. func (d *Driver) Remove(id string) error { rID, err := d.resolveID(id) if err != nil { return err } return hcsshim.DestroyLayer(d.info, rID) }
// DiffPath returns a directory that contains files needed to construct layer diff. func (d *Driver) DiffPath(id string) (path string, release func() error, err error) { id, err = d.resolveID(id) if err != nil { return } // Getting the layer paths must be done outside of the lock. layerChain, err := d.getLayerChain(id) if err != nil { return } layerFolder := d.dir(id) tempFolder := layerFolder + "-" + strconv.FormatUint(uint64(random.Rand.Uint32()), 10) if err = os.MkdirAll(tempFolder, 0755); err != nil { logrus.Errorf("Could not create %s %s", tempFolder, err) return } defer func() { if err != nil { _, folderName := filepath.Split(tempFolder) if err2 := hcsshim.DestroyLayer(d.info, folderName); err2 != nil { logrus.Warnf("Couldn't clean-up tempFolder: %s %s", tempFolder, err2) } } }() if err = hcsshim.ExportLayer(d.info, id, tempFolder, layerChain); err != nil { return } err = copySysFiles(filepath.Join(d.info.HomeDir, "sysfile-backups", id), tempFolder) if err != nil { return } return tempFolder, func() error { // TODO: activate layers and release here? _, folderName := filepath.Split(tempFolder) return hcsshim.DestroyLayer(d.info, folderName) }, nil }
// exportLayer generates an archive from a layer based on the given ID. func (d *Driver) exportLayer(id string, parentLayerPaths []string) (arch archive.Archive, err error) { layerFolder := d.dir(id) tempFolder := layerFolder + "-" + strconv.FormatUint(uint64(random.Rand.Uint32()), 10) if err = os.MkdirAll(tempFolder, 0755); err != nil { logrus.Errorf("Could not create %s %s", tempFolder, err) return } defer func() { if err != nil { _, folderName := filepath.Split(tempFolder) if err2 := hcsshim.DestroyLayer(d.info, folderName); err2 != nil { logrus.Warnf("Couldn't clean-up tempFolder: %s %s", tempFolder, err2) } } }() if err = hcsshim.ExportLayer(d.info, id, tempFolder, parentLayerPaths); err != nil { return } archive, err := archive.Tar(tempFolder, archive.Uncompressed) if err != nil { return } return ioutils.NewReadCloserWrapper(archive, func() error { err := archive.Close() d.Put(id) _, folderName := filepath.Split(tempFolder) if err2 := hcsshim.DestroyLayer(d.info, folderName); err2 != nil { logrus.Warnf("Couldn't clean-up tempFolder: %s %s", tempFolder, err2) } return err }), nil }
// Remove unmounts and removes the dir information. func (d *Driver) Remove(id string) error { rID, err := d.resolveID(id) if err != nil { return err } layerPath := filepath.Join(d.info.HomeDir, rID) tmpID := fmt.Sprintf("%s-removing", rID) tmpLayerPath := filepath.Join(d.info.HomeDir, tmpID) if err := os.Rename(layerPath, tmpLayerPath); err != nil && !os.IsNotExist(err) { return err } if err := hcsshim.DestroyLayer(d.info, tmpID); err != nil { logrus.Errorf("Failed to DestroyLayer %s: %s", id, err) } return 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 main() { var folder string flag.StringVar(&folder, "folder", "", "Folder to zap.") flag.Parse() if folder == "" { fmt.Println("Error: folder must be supplied") return } if folderexists(folder) { location, foldername := filepath.Split(folder) info := hcsshim.DriverInfo{ HomeDir: location, Flavour: 0, } if err := hcsshim.DestroyLayer(info, foldername); err != nil { fmt.Println("ERROR: ", err) } else { fmt.Println("INFO: Zapped successfully") } } else { fmt.Println("ERROR: Folder does not exist") } }
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 }
// Remove unmounts and removes the dir information. func (d *Driver) Remove(id string) error { rID, err := d.resolveID(id) if err != nil { return err } // This retry loop is due to a bug in Windows (Internal bug #9432268) // if GetContainers fails with ErrVmcomputeOperationInvalidState // it is a transient error. Retry until it succeeds. var computeSystems []hcsshim.ContainerProperties retryCount := 0 for { // Get and terminate any template VMs that are currently using the layer computeSystems, err = hcsshim.GetContainers(hcsshim.ComputeSystemQuery{}) if err != nil { if err == hcsshim.ErrVmcomputeOperationInvalidState { if retryCount >= 5 { // If we are unable to get the list of containers // go ahead and attempt to delete the layer anyway // as it will most likely work. break } retryCount++ time.Sleep(2 * time.Second) continue } return err } break } for _, computeSystem := range computeSystems { if strings.Contains(computeSystem.RuntimeImagePath, id) && computeSystem.IsRuntimeTemplate { container, err := hcsshim.OpenContainer(computeSystem.ID) if err != nil { return err } defer container.Close() err = container.Terminate() if hcsshim.IsPending(err) { err = container.Wait() } else if hcsshim.IsAlreadyStopped(err) { err = nil } if err != nil { return err } } } layerPath := filepath.Join(d.info.HomeDir, rID) tmpID := fmt.Sprintf("%s-removing", rID) tmpLayerPath := filepath.Join(d.info.HomeDir, tmpID) if err := os.Rename(layerPath, tmpLayerPath); err != nil && !os.IsNotExist(err) { return err } if err := hcsshim.DestroyLayer(d.info, tmpID); err != nil { logrus.Errorf("Failed to DestroyLayer %s: %s", id, 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) }
// Remove unmounts and removes the dir information func (d *WindowsGraphDriver) Remove(id string) error { return hcsshim.DestroyLayer(d.info, id) }
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) }