Skip to content

Commit

Permalink
Merge pull request #881 from dcantah/hcs-storage
Browse files Browse the repository at this point in the history
Add HCS storage APIs
  • Loading branch information
dcantah authored Nov 6, 2020
2 parents ff4402a + 04779e8 commit 1432f9c
Show file tree
Hide file tree
Showing 11 changed files with 712 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
}
75 changes: 75 additions & 0 deletions computestorage/setup.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package computestorage

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

"github.com/Microsoft/hcsshim/internal/oc"
"github.com/Microsoft/hcsshim/osversion"
"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
}

// SetupBaseOSVolume sets up a volume that contains a base OS for a container.
//
// `layerPath` is a path to a directory containing the layer.
//
// `volumePath` is the path to the volume to be used for setup.
//
// `options` are the options applied while processing the layer.
func SetupBaseOSVolume(ctx context.Context, layerPath, volumePath string, options OsLayerOptions) (err error) {
if osversion.Get().Build < 19645 {
return errors.New("SetupBaseOSVolume is not present on builds older than 19645")
}
title := "hcsshim.SetupBaseOSVolume"
ctx, span := trace.StartSpan(ctx, title)
defer span.End()
defer func() { oc.SetSpanStatus(span, err) }()
span.AddAttributes(
trace.StringAttribute("layerPath", layerPath),
trace.StringAttribute("volumePath", volumePath),
)

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

err = hcsSetupBaseOSVolume(layerPath, volumePath, string(bytes))
if err != nil {
return fmt.Errorf("failed to setup base OS layer: %s", err)
}
return nil
}
Loading

0 comments on commit 1432f9c

Please sign in to comment.