Skip to content

Commit

Permalink
Add HCS storage APIs
Browse files Browse the repository at this point in the history
* Add bindings for the HCS storage APIs from computestorage.dll

Signed-off-by: Daniel Canter <[email protected]>
  • Loading branch information
dcantah committed Oct 28, 2020
1 parent 0af9b9d commit 14e87c6
Show file tree
Hide file tree
Showing 11 changed files with 641 additions and 0 deletions.
38 changes: 38 additions & 0 deletions computestorage/attach.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package computestorage

import (
"context"
"encoding/json"
"fmt"

"github.com/Microsoft/hcsshim/internal/oc"
"go.opencensus.io/trace"
)

// AttachLayerStorageFilter sets up the layer storage filter on a writable
// container layer.
//
// `layerPath` is a path to a directory the writable layer is mounted. If the
// path does not end in a `\` the platform will append it automatically.
//
// `layerData` is the parent read-only layer data.
func AttachLayerStorageFilter(ctx context.Context, layerPath string, layerData LayerData) (err error) {
title := "hcsshim::AttachLayerStorageFilter"
ctx, span := trace.StartSpan(ctx, title)
defer span.End()
defer func() { oc.SetSpanStatus(span, err) }()
span.AddAttributes(
trace.StringAttribute("layerPath", layerPath),
)

bytes, err := json.Marshal(layerData)
if err != nil {
return err
}

err = hcsAttachLayerStorageFilter(layerPath, string(bytes))
if err != nil {
return fmt.Errorf("failed to attach layer storage filter: %s", err)
}
return nil
}
26 changes: 26 additions & 0 deletions computestorage/destroy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package computestorage

import (
"context"
"fmt"

"github.com/Microsoft/hcsshim/internal/oc"
"go.opencensus.io/trace"
)

// DestroyLayer deletes a container layer.
//
// `layerPath` is a path to a directory containing the layer to export.
func DestroyLayer(ctx context.Context, layerPath string) (err error) {
title := "hcsshim::DestroyLayer"
ctx, span := trace.StartSpan(ctx, title)
defer span.End()
defer func() { oc.SetSpanStatus(span, err) }()
span.AddAttributes(trace.StringAttribute("layerPath", layerPath))

err = hcsDestroyLayer(layerPath)
if err != nil {
return fmt.Errorf("failed to destroy layer: %s", err)
}
return nil
}
26 changes: 26 additions & 0 deletions computestorage/detach.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package computestorage

import (
"context"
"fmt"

"github.com/Microsoft/hcsshim/internal/oc"
"go.opencensus.io/trace"
)

// DetachLayerStorageFilter detaches the layer storage filter on a writable container layer.
//
// `layerPath` is a path to a directory containing the layer to export.
func DetachLayerStorageFilter(ctx context.Context, layerPath string) (err error) {
title := "hcsshim::DetachLayerStorageFilter"
ctx, span := trace.StartSpan(ctx, title)
defer span.End()
defer func() { oc.SetSpanStatus(span, err) }()
span.AddAttributes(trace.StringAttribute("layerPath", layerPath))

err = hcsDetachLayerStorageFilter(layerPath)
if err != nil {
return fmt.Errorf("failed to detach layer storage filter: %s", err)
}
return nil
}
46 changes: 46 additions & 0 deletions computestorage/export.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package computestorage

import (
"context"
"encoding/json"
"fmt"

"github.com/Microsoft/hcsshim/internal/oc"
"go.opencensus.io/trace"
)

// ExportLayer exports a container layer.
//
// `layerPath` is a path to a directory containing the layer to export.
//
// `exportFolderPath` is a pre-existing folder to export the layer to.
//
// `layerData` is the parent layer data.
//
// `options` are the export options applied to the exported layer.
func ExportLayer(ctx context.Context, layerPath, exportFolderPath string, layerData LayerData, options ExportLayerOptions) (err error) {
title := "hcsshim::ExportLayer"
ctx, span := trace.StartSpan(ctx, title)
defer span.End()
defer func() { oc.SetSpanStatus(span, err) }()
span.AddAttributes(
trace.StringAttribute("layerPath", layerPath),
trace.StringAttribute("exportFolderPath", exportFolderPath),
)

ldbytes, err := json.Marshal(layerData)
if err != nil {
return err
}

obytes, err := json.Marshal(options)
if err != nil {
return err
}

err = hcsExportLayer(layerPath, exportFolderPath, string(ldbytes), string(obytes))
if err != nil {
return fmt.Errorf("failed to export layer: %s", err)
}
return nil
}
26 changes: 26 additions & 0 deletions computestorage/format.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package computestorage

import (
"context"
"fmt"

"github.com/Microsoft/hcsshim/internal/oc"
"go.opencensus.io/trace"
"golang.org/x/sys/windows"
)

// FormatWritableLayerVhd formats a virtual disk for use as a writable container layer.
//
// If the VHD is not mounted it will be temporarily mounted.
func FormatWritableLayerVhd(ctx context.Context, vhdHandle windows.Handle) (err error) {
title := "hcsshim::FormatWritableLayerVhd"
ctx, span := trace.StartSpan(ctx, title)
defer span.End()
defer func() { oc.SetSpanStatus(span, err) }()

err = hcsFormatWritableLayerVhd(vhdHandle)
if err != nil {
return fmt.Errorf("failed to format writable layer vhd: %s", err)
}
return nil
}
41 changes: 41 additions & 0 deletions computestorage/import.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package computestorage

import (
"context"
"encoding/json"
"fmt"

"github.com/Microsoft/hcsshim/internal/oc"
"go.opencensus.io/trace"
)

// ImportLayer imports a container layer.
//
// `layerPath` is a path to a directory to import the layer to. If the directory
// does not exist it will be automatically created.
//
// `sourceFolderpath` is a pre-existing folder that contains the layer to
// import.
//
// `layerData` is the parent layer data.
func ImportLayer(ctx context.Context, layerPath, sourceFolderPath string, layerData LayerData) (err error) {
title := "hcsshim::ImportLayer"
ctx, span := trace.StartSpan(ctx, title)
defer span.End()
defer func() { oc.SetSpanStatus(span, err) }()
span.AddAttributes(
trace.StringAttribute("layerPath", layerPath),
trace.StringAttribute("sourceFolderPath", sourceFolderPath),
)

bytes, err := json.Marshal(layerData)
if err != nil {
return err
}

err = hcsImportLayer(layerPath, sourceFolderPath, string(bytes))
if err != nil {
return fmt.Errorf("failed to import layer: %s", err)
}
return nil
}
38 changes: 38 additions & 0 deletions computestorage/initialize.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package computestorage

import (
"context"
"encoding/json"
"fmt"

"github.com/Microsoft/hcsshim/internal/oc"
"go.opencensus.io/trace"
)

// InitializeWritableLayer initializes a writable layer for a container.
//
// `layerPath` is a path to a directory the layer is mounted. If the
// path does not end in a `\` the platform will append it automatically.
//
// `layerData` is the parent read-only layer data.
func InitializeWritableLayer(ctx context.Context, layerPath string, layerData LayerData) (err error) {
title := "hcsshim::InitializeWritableLayer"
ctx, span := trace.StartSpan(ctx, title)
defer span.End()
defer func() { oc.SetSpanStatus(span, err) }()
span.AddAttributes(
trace.StringAttribute("layerPath", layerPath),
)

bytes, err := json.Marshal(layerData)
if err != nil {
return err
}

// Options are not used in the platform as of RS5
err = hcsInitializeWritableLayer(layerPath, string(bytes), "")
if err != nil {
return fmt.Errorf("failed to intitialize container layer: %s", err)
}
return nil
}
27 changes: 27 additions & 0 deletions computestorage/mount.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package computestorage

import (
"context"
"fmt"

"github.com/Microsoft/hcsshim/internal/interop"
"github.com/Microsoft/hcsshim/internal/oc"
"go.opencensus.io/trace"
"golang.org/x/sys/windows"
)

// GetLayerVhdMountPath returns the volume path for a virtual disk of a writable container layer.
func GetLayerVhdMountPath(ctx context.Context, vhdHandle windows.Handle) (path string, err error) {
title := "hcsshim::GetLayerVhdMountPath"
ctx, span := trace.StartSpan(ctx, title)
defer span.End()
defer func() { oc.SetSpanStatus(span, err) }()

var mountPath *uint16
err = hcsGetLayerVhdMountPath(vhdHandle, &mountPath)
if err != nil {
return "", fmt.Errorf("failed to get vhd mount path: %s", err)
}
path = interop.ConvertAndFreeCoTaskMemString(mountPath)
return path, nil
}
41 changes: 41 additions & 0 deletions computestorage/setup.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package computestorage

import (
"context"
"encoding/json"
"fmt"

"github.com/Microsoft/hcsshim/internal/oc"
"go.opencensus.io/trace"
"golang.org/x/sys/windows"
)

// SetupBaseOSLayer sets up a layer that contains a base OS for a container.
//
// `layerPath` is a path to a directory containing the layer.
//
// `vhdHandle` is an empty file handle of `options.Type == OsLayerTypeContainer`
// or else it is a file handle to the 'SystemTemplateBase.vhdx' if `options.Type
// == OsLayerTypeVm`.
//
// `options` are the options applied while processing the layer.
func SetupBaseOSLayer(ctx context.Context, layerPath string, vhdHandle windows.Handle, options OsLayerOptions) (err error) {
title := "hcsshim::SetupBaseOSLayer"
ctx, span := trace.StartSpan(ctx, title)
defer span.End()
defer func() { oc.SetSpanStatus(span, err) }()
span.AddAttributes(
trace.StringAttribute("layerPath", layerPath),
)

bytes, err := json.Marshal(options)
if err != nil {
return err
}

err = hcsSetupBaseOSLayer(layerPath, vhdHandle, string(bytes))
if err != nil {
return fmt.Errorf("failed to setup base OS layer: %s", err)
}
return nil
}
47 changes: 47 additions & 0 deletions computestorage/storage.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Package computestorage is a wrapper around the HCS storage APIs. These are new storage APIs introduced
// separate from the original graphdriver calls intended to give more freedom around creating
// and managing container layers and scratch spaces.
package computestorage

import (
hcsschema "github.com/Microsoft/hcsshim/internal/schema2"
)

//go:generate go run ../mksyscall_windows.go -output zsyscall_windows.go storage.go

//sys hcsImportLayer(layerPath string, sourceFolderPath string, layerData string) (hr error) = computestorage.HcsImportLayer?
//sys hcsExportLayer(layerPath string, exportFolderPath string, layerData string, options string) (hr error) = computestorage.HcsExportLayer?
//sys hcsDestroyLayer(layerPath string) (hr error) = computestorage.HcsDestoryLayer?
//sys hcsSetupBaseOSLayer(layerPath string, handle windows.Handle, options string) (hr error) = computestorage.HcsSetupBaseOSLayer?
//sys hcsInitializeWritableLayer(writableLayerPath string, layerData string, options string) (hr error) = computestorage.HcsInitializeWritableLayer?
//sys hcsAttachLayerStorageFilter(layerPath string, layerData string) (hr error) = computestorage.HcsAttachLayerStorageFilter?
//sys hcsDetachLayerStorageFilter(layerPath string) (hr error) = computestorage.HcsDetachLayerStorageFilter?
//sys hcsFormatWritableLayerVhd(handle windows.Handle) (hr error) = computestorage.HcsFormatWritableLayerVhd?
//sys hcsGetLayerVhdMountPath(vhdHandle windows.Handle, mountPath **uint16) (hr error) = computestorage.hcsGetLayerVhdMountPath?

// LayerData is the data used to describe parent layer information.
type LayerData struct {
SchemaVersion hcsschema.Version `json:"SchemaVersion,omitempty"`
Layers []hcsschema.Layer `json:"Layers,omitempty"`
}

// ExportLayerOptions are the set of options that are used with the `computestorage.HcsExportLayer` syscall.
type ExportLayerOptions struct {
IsWritableLayer bool `json:"IsWritableLayer,omitempty"`
}

// OsLayerType is the type of layer being operated on.
type OsLayerType string

const (
// OsLayerTypeContainer is a container layer.
OsLayerTypeContainer OsLayerType = "Container"
// OsLayerTypeVM is a virtual machine layer.
OsLayerTypeVM OsLayerType = "Vm"
)

// OsLayerOptions are the set of options that are used with the `computestorage.HcsSetupBaseOSLayer` syscall.
type OsLayerOptions struct {
Type OsLayerType `json:"Type,omitempty"`
DisableCiCacheOptimization bool `json:"DisableCiCacheOptimization,omitempty"`
}
Loading

0 comments on commit 14e87c6

Please sign in to comment.