123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197 |
- //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
- }
|