hcsshim tags v0.10.* is deprecated, so using the new v0.12.0-rc.* versioning for hcsshim tags on containerd/main Signed-off-by: Kirtana Ashok <kiashok@microsoft.com>
		
			
				
	
	
		
			200 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			200 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
//go:build windows
 | 
						|
 | 
						|
package computestorage
 | 
						|
 | 
						|
import (
 | 
						|
	"context"
 | 
						|
	"os"
 | 
						|
	"path/filepath"
 | 
						|
	"syscall"
 | 
						|
 | 
						|
	"github.com/Microsoft/go-winio/vhd"
 | 
						|
	"github.com/Microsoft/hcsshim/internal/memory"
 | 
						|
	"github.com/pkg/errors"
 | 
						|
	"golang.org/x/sys/windows"
 | 
						|
 | 
						|
	"github.com/Microsoft/hcsshim/internal/security"
 | 
						|
)
 | 
						|
 | 
						|
const (
 | 
						|
	defaultVHDXBlockSizeInMB = 1
 | 
						|
)
 | 
						|
 | 
						|
// SetupContainerBaseLayer is a helper to setup a containers scratch. It
 | 
						|
// will create and format the vhdx's inside and the size is configurable with the sizeInGB
 | 
						|
// parameter.
 | 
						|
//
 | 
						|
// `layerPath` is the path to the base container layer on disk.
 | 
						|
//
 | 
						|
// `baseVhdPath` is the path to where the base vhdx for the base layer should be created.
 | 
						|
//
 | 
						|
// `diffVhdPath` is the path where the differencing disk for the base layer should be created.
 | 
						|
//
 | 
						|
// `sizeInGB` is the size in gigabytes to make the base vhdx.
 | 
						|
func SetupContainerBaseLayer(ctx context.Context, layerPath, baseVhdPath, diffVhdPath string, sizeInGB uint64) (err error) {
 | 
						|
	var (
 | 
						|
		hivesPath  = filepath.Join(layerPath, "Hives")
 | 
						|
		layoutPath = filepath.Join(layerPath, "Layout")
 | 
						|
	)
 | 
						|
 | 
						|
	// We need to remove the hives directory and layout file as `SetupBaseOSLayer` fails if these files
 | 
						|
	// already exist. `SetupBaseOSLayer` will create these files internally. We also remove the base and
 | 
						|
	// differencing disks if they exist in case we're asking for a different size.
 | 
						|
	if _, err := os.Stat(hivesPath); err == nil {
 | 
						|
		if err := os.RemoveAll(hivesPath); err != nil {
 | 
						|
			return errors.Wrap(err, "failed to remove prexisting hives directory")
 | 
						|
		}
 | 
						|
	}
 | 
						|
	if _, err := os.Stat(layoutPath); err == nil {
 | 
						|
		if err := os.RemoveAll(layoutPath); err != nil {
 | 
						|
			return errors.Wrap(err, "failed to remove prexisting layout file")
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if _, err := os.Stat(baseVhdPath); err == nil {
 | 
						|
		if err := os.RemoveAll(baseVhdPath); err != nil {
 | 
						|
			return errors.Wrap(err, "failed to remove base vhdx path")
 | 
						|
		}
 | 
						|
	}
 | 
						|
	if _, err := os.Stat(diffVhdPath); err == nil {
 | 
						|
		if err := os.RemoveAll(diffVhdPath); err != nil {
 | 
						|
			return errors.Wrap(err, "failed to remove differencing vhdx")
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	createParams := &vhd.CreateVirtualDiskParameters{
 | 
						|
		Version: 2,
 | 
						|
		Version2: vhd.CreateVersion2{
 | 
						|
			MaximumSize:      sizeInGB * memory.GiB,
 | 
						|
			BlockSizeInBytes: defaultVHDXBlockSizeInMB * memory.MiB,
 | 
						|
		},
 | 
						|
	}
 | 
						|
	handle, err := vhd.CreateVirtualDisk(baseVhdPath, vhd.VirtualDiskAccessNone, vhd.CreateVirtualDiskFlagNone, createParams)
 | 
						|
	if err != nil {
 | 
						|
		return errors.Wrap(err, "failed to create vhdx")
 | 
						|
	}
 | 
						|
 | 
						|
	defer func() {
 | 
						|
		if err != nil {
 | 
						|
			_ = syscall.CloseHandle(handle)
 | 
						|
			os.RemoveAll(baseVhdPath)
 | 
						|
			os.RemoveAll(diffVhdPath)
 | 
						|
		}
 | 
						|
	}()
 | 
						|
 | 
						|
	if err = FormatWritableLayerVhd(ctx, windows.Handle(handle)); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	// Base vhd handle must be closed before calling SetupBaseLayer in case of Container layer
 | 
						|
	if err = syscall.CloseHandle(handle); err != nil {
 | 
						|
		return errors.Wrap(err, "failed to close vhdx handle")
 | 
						|
	}
 | 
						|
 | 
						|
	options := OsLayerOptions{
 | 
						|
		Type: OsLayerTypeContainer,
 | 
						|
	}
 | 
						|
 | 
						|
	// SetupBaseOSLayer expects an empty vhd handle for a container layer and will
 | 
						|
	// error out otherwise.
 | 
						|
	if err = SetupBaseOSLayer(ctx, layerPath, 0, options); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	// Create the differencing disk that will be what's copied for the final rw layer
 | 
						|
	// for a container.
 | 
						|
	if err = vhd.CreateDiffVhd(diffVhdPath, baseVhdPath, defaultVHDXBlockSizeInMB); err != nil {
 | 
						|
		return errors.Wrap(err, "failed to create differencing disk")
 | 
						|
	}
 | 
						|
 | 
						|
	if err = security.GrantVmGroupAccess(baseVhdPath); err != nil {
 | 
						|
		return errors.Wrapf(err, "failed to grant vm group access to %s", baseVhdPath)
 | 
						|
	}
 | 
						|
	if err = security.GrantVmGroupAccess(diffVhdPath); err != nil {
 | 
						|
		return errors.Wrapf(err, "failed to grant vm group access to %s", diffVhdPath)
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
// SetupUtilityVMBaseLayer is a helper to setup a UVMs scratch space. It will create and format
 | 
						|
// the vhdx inside and the size is configurable by the sizeInGB parameter.
 | 
						|
//
 | 
						|
// `uvmPath` is the path to the UtilityVM filesystem.
 | 
						|
//
 | 
						|
// `baseVhdPath` is the path to where the base vhdx for the UVM should be created.
 | 
						|
//
 | 
						|
// `diffVhdPath` is the path where the differencing disk for the UVM should be created.
 | 
						|
//
 | 
						|
// `sizeInGB` specifies the size in gigabytes to make the base vhdx.
 | 
						|
func SetupUtilityVMBaseLayer(ctx context.Context, uvmPath, baseVhdPath, diffVhdPath string, sizeInGB uint64) (err error) {
 | 
						|
	// Remove the base and differencing disks if they exist in case we're asking for a different size.
 | 
						|
	if _, err := os.Stat(baseVhdPath); err == nil {
 | 
						|
		if err := os.RemoveAll(baseVhdPath); err != nil {
 | 
						|
			return errors.Wrap(err, "failed to remove base vhdx")
 | 
						|
		}
 | 
						|
	}
 | 
						|
	if _, err := os.Stat(diffVhdPath); err == nil {
 | 
						|
		if err := os.RemoveAll(diffVhdPath); err != nil {
 | 
						|
			return errors.Wrap(err, "failed to remove differencing vhdx")
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	// Just create the vhdx for utilityVM layer, no need to format it.
 | 
						|
	createParams := &vhd.CreateVirtualDiskParameters{
 | 
						|
		Version: 2,
 | 
						|
		Version2: vhd.CreateVersion2{
 | 
						|
			MaximumSize:      sizeInGB * memory.GiB,
 | 
						|
			BlockSizeInBytes: defaultVHDXBlockSizeInMB * memory.MiB,
 | 
						|
		},
 | 
						|
	}
 | 
						|
	handle, err := vhd.CreateVirtualDisk(baseVhdPath, vhd.VirtualDiskAccessNone, vhd.CreateVirtualDiskFlagNone, createParams)
 | 
						|
	if err != nil {
 | 
						|
		return errors.Wrap(err, "failed to create vhdx")
 | 
						|
	}
 | 
						|
 | 
						|
	defer func() {
 | 
						|
		if err != nil {
 | 
						|
			_ = syscall.CloseHandle(handle)
 | 
						|
			os.RemoveAll(baseVhdPath)
 | 
						|
			os.RemoveAll(diffVhdPath)
 | 
						|
		}
 | 
						|
	}()
 | 
						|
 | 
						|
	// If it is a UtilityVM layer then the base vhdx must be attached when calling
 | 
						|
	// `SetupBaseOSLayer`
 | 
						|
	attachParams := &vhd.AttachVirtualDiskParameters{
 | 
						|
		Version: 2,
 | 
						|
	}
 | 
						|
	if err := vhd.AttachVirtualDisk(handle, vhd.AttachVirtualDiskFlagNone, attachParams); err != nil {
 | 
						|
		return errors.Wrapf(err, "failed to attach virtual disk")
 | 
						|
	}
 | 
						|
 | 
						|
	options := OsLayerOptions{
 | 
						|
		Type: OsLayerTypeVM,
 | 
						|
	}
 | 
						|
	if err := SetupBaseOSLayer(ctx, uvmPath, windows.Handle(handle), options); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
 | 
						|
	// Detach and close the handle after setting up the layer as we don't need the handle
 | 
						|
	// for anything else and we no longer need to be attached either.
 | 
						|
	if err = vhd.DetachVirtualDisk(handle); err != nil {
 | 
						|
		return errors.Wrap(err, "failed to detach vhdx")
 | 
						|
	}
 | 
						|
	if err = syscall.CloseHandle(handle); err != nil {
 | 
						|
		return errors.Wrap(err, "failed to close vhdx handle")
 | 
						|
	}
 | 
						|
 | 
						|
	// Create the differencing disk that will be what's copied for the final rw layer
 | 
						|
	// for a container.
 | 
						|
	if err = vhd.CreateDiffVhd(diffVhdPath, baseVhdPath, defaultVHDXBlockSizeInMB); err != nil {
 | 
						|
		return errors.Wrap(err, "failed to create differencing disk")
 | 
						|
	}
 | 
						|
 | 
						|
	if err := security.GrantVmGroupAccess(baseVhdPath); err != nil {
 | 
						|
		return errors.Wrapf(err, "failed to grant vm group access to %s", baseVhdPath)
 | 
						|
	}
 | 
						|
	if err := security.GrantVmGroupAccess(diffVhdPath); err != nil {
 | 
						|
		return errors.Wrapf(err, "failed to grant vm group access to %s", diffVhdPath)
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 |