mirror of
https://github.com/k3s-io/k3s.git
synced 2024-06-07 19:41:36 +00:00
b352d73511
Signed-off-by: Brad Davidson <brad.davidson@rancher.com>
194 lines
6.6 KiB
Go
194 lines
6.6 KiB
Go
package computestorage
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"path/filepath"
|
|
"syscall"
|
|
|
|
"github.com/Microsoft/go-winio/pkg/security"
|
|
"github.com/Microsoft/go-winio/vhd"
|
|
"github.com/pkg/errors"
|
|
"golang.org/x/sys/windows"
|
|
)
|
|
|
|
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 * 1024 * 1024 * 1024,
|
|
BlockSizeInBytes: defaultVHDXBlockSizeInMB * 1024 * 1024,
|
|
},
|
|
}
|
|
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 * 1024 * 1024 * 1024,
|
|
BlockSizeInBytes: defaultVHDXBlockSizeInMB * 1024 * 1024,
|
|
},
|
|
}
|
|
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
|
|
}
|