binctr/vendor/github.com/Microsoft/hcsshim/functional/wcow_test.go
Jess Frazelle 94d1cfbfbf
update vendor
Signed-off-by: Jess Frazelle <acidburn@microsoft.com>
2018-09-25 12:27:46 -04:00

734 lines
23 KiB
Go

// +build functional wcow
package functional
import (
"bytes"
"os"
"path/filepath"
"strings"
"testing"
"github.com/Microsoft/hcsshim"
"github.com/Microsoft/hcsshim/functional/utilities"
"github.com/Microsoft/hcsshim/internal/hcs"
"github.com/Microsoft/hcsshim/internal/hcsoci"
"github.com/Microsoft/hcsshim/internal/osversion"
"github.com/Microsoft/hcsshim/internal/schema1"
"github.com/Microsoft/hcsshim/internal/schemaversion"
"github.com/Microsoft/hcsshim/internal/uvm"
"github.com/Microsoft/hcsshim/internal/uvmfolder"
"github.com/Microsoft/hcsshim/internal/wclayer"
"github.com/Microsoft/hcsshim/internal/wcow"
specs "github.com/opencontainers/runtime-spec/specs-go"
)
// Has testing for Windows containers using both the older hcsshim methods,
// and the newer hcsoci methods. Does the same thing in six different ways:
// - hcsshim/argon
// - hcsshim/xenon
// - hcsoci/argon v1
// - hcsoci/xenon v1
// - hcsoci/argon v2
// - hcsoci/xenon v2
//
// Sample v1 HCS document for Xenon (no networking):
//
//{
// "SystemType": "Container",
// "Name": "48347b95d0ad4f37de6d1979b986fb65912f973ad4549fbe716e848679dfa25c",
// "IgnoreFlushesDuringBoot": true,
// "LayerFolderPath": "C:\\layers\\48347b95d0ad4f37de6d1979b986fb65912f973ad4549fbe716e848679dfa25c",
// "Layers": [
// {
// "ID": "7095521e-b79e-50fc-bafb-958d85400362",
// "Path": "C:\\layers\\f9b22d909166dd54b870eb699d54f4cf36d99f035ffd7701aff1267230aefd1e"
// }
// ],
// "HvPartition": true,
// "HvRuntime": {
// "ImagePath": "C:\\layers\\f9b22d909166dd54b870eb699d54f4cf36d99f035ffd7701aff1267230aefd1e\\UtilityVM"
// }
//}
//
// Sample v1 HCS document for Argon (no networking):
//
//{
// "SystemType": "Container",
// "Name": "0a8bb9ec8366aa48a8e5f810274701d8d4452989bf268fc338570bfdecddf8df",
// "VolumePath": "\\\\?\\Volume{85da95c9-dda9-42e0-a066-40bd120c6f3c}",
// "IgnoreFlushesDuringBoot": true,
// "LayerFolderPath": "C:\\layers\\0a8bb9ec8366aa48a8e5f810274701d8d4452989bf268fc338570bfdecddf8df",
// "Layers": [
// {
// "ID": "7095521e-b79e-50fc-bafb-958d85400362",
// "Path": "C:\\layers\\f9b22d909166dd54b870eb699d54f4cf36d99f035ffd7701aff1267230aefd1e"
// }
// ],
// "HvPartition": false
//}
//
// Sample v2 HCS document for Argon (no networking):
//
//{
// "Owner": "sample",
// "SchemaVersion": {
// "Major": 2,
// "Minor": 0
// },
// "Container": {
// "Storage": {
// "Layers": [
// {
// "Id": "6ba9cac1-7086-5ee9-a197-c465d3f50ad7",
// "Path": "C:\\layers\\f30368666ce4457e86fe12867506e508071d89e7eae615fc389c64f2e37ce54e"
// },
// {
// "Id": "300b3ac0-b603-5367-9494-afec045dd369",
// "Path": "C:\\layers\\7a6ad2b849a9d29e6648d9950c1975b0f614a63b5fe2803009ce131745abcc62"
// },
// {
// "Id": "fa3057d9-0d4b-54c0-b2d5-34b7afc78f91",
// "Path": "C:\\layers\\5d1332fe416f7932c344ce9c536402a6fc6d0bfcdf7a74f67cc67b8cfc66ab41"
// },
// {
// "Id": "23284a2c-cdda-582a-a175-a196211b03cb",
// "Path": "C:\\layers\\b95977ad18f8fa04e517daa2e814f73d69bfff55c3ea68d56f2b0b8ae23a235d"
// },
// {
// "Id": "e0233918-d93f-5b08-839e-0cbeda79b68b",
// "Path": "C:\\layers\\b2a444ff0e984ef282d6a8e24fa0108e76b6807d943e111a0e878c1c53ed8246"
// },
// {
// "Id": "02740e08-d1d3-5715-9c08-c255eab4ca01",
// "Path": "C:\\layers\\de6b1a908240cca2aef34f49994e7d4e25a8e157a2cef3b6d6cf2d8e6400bfc2"
// }
// ],
// "Path": "\\\\?\\Volume{baac0fd5-16b7-405b-9621-112aa8e3d973}\\"
// }
// },
// "ShouldTerminateOnLastHandleClosed": true
//}
//
//
// Sample v2 HCS document for Xenon (no networking)
//
//{
// "Owner": "functional.test.exe",
// "SchemaVersion": {
// "Major": 2,
// "Minor": 0
// },
// "HostingSystemId": "xenonOci2UVM",
// "HostedSystem": {
// "SchemaVersion": {
// "Major": 2,
// "Minor": 0
// },
// "Container": {
// "Storage": {
// "Layers": [
// {
// "Id": "6ba9cac1-7086-5ee9-a197-c465d3f50ad7",
// "Path": "\\\\?\\VMSMB\\VSMB-{dcc079ae-60ba-4d07-847c-3493609c0870}\\s1"
// },
// {
// "Id": "300b3ac0-b603-5367-9494-afec045dd369",
// "Path": "\\\\?\\VMSMB\\VSMB-{dcc079ae-60ba-4d07-847c-3493609c0870}\\s2"
// },
// {
// "Id": "fa3057d9-0d4b-54c0-b2d5-34b7afc78f91",
// "Path": "\\\\?\\VMSMB\\VSMB-{dcc079ae-60ba-4d07-847c-3493609c0870}\\s3"
// },
// {
// "Id": "23284a2c-cdda-582a-a175-a196211b03cb",
// "Path": "\\\\?\\VMSMB\\VSMB-{dcc079ae-60ba-4d07-847c-3493609c0870}\\4"
// },
// {
// "Id": "e0233918-d93f-5b08-839e-0cbeda79b68b",
// "Path": "\\\\?\\VMSMB\\VSMB-{dcc079ae-60ba-4d07-847c-3493609c0870}\\s5"
// },
// {
// "Id": "02740e08-d1d3-5715-9c08-c255eab4ca01",
// "Path": "\\\\?\\VMSMB\\VSMB-{dcc079ae-60ba-4d07-847c-3493609c0870}\\s6"
// }
// ],
// "Path": "C:\\c\\1\\scratch"
// },
// "MappedDirectories": [
// {
// "HostPath": "\\\\?\\VMSMB\\VSMB-{dcc079ae-60ba-4d07-847c-3493609c0870}\\s7",
// "ContainerPath": "c:\\mappedro",
// "ReadOnly": true
// },
// {
// "HostPath": "\\\\?\\VMSMB\\VSMB-{dcc079ae-60ba-4d07-847c-3493609c0870}\\s8",
// "ContainerPath": "c:\\mappedrw"
// }
// ]
// }
// },
// "ShouldTerminateOnLastHandleClosed": true
//}
// Helper to start a container.
// Ones created through hcsoci methods will be of type *hcs.System.
// Ones created through hcsshim methods will be of type hcsshim.Container
func startContainer(t *testing.T, c interface{}) {
var err error
switch c.(type) {
case *hcs.System:
err = c.(*hcs.System).Start()
case hcsshim.Container:
err = c.(hcsshim.Container).Start()
default:
t.Fatal("unknown type")
}
if err != nil {
t.Fatalf("Failed start: %s", err)
}
}
// Helper to stop a container.
// Ones created through hcsoci methods will be of type *hcs.System.
// Ones created through hcsshim methods will be of type hcsshim.Container
func stopContainer(t *testing.T, c interface{}) {
switch c.(type) {
case *hcs.System:
if err := c.(*hcs.System).Shutdown(); err != nil {
if hcsshim.IsPending(err) {
if err := c.(*hcs.System).Wait(); err != nil {
t.Fatalf("Failed Wait shutdown: %s", err)
}
} else {
t.Fatalf("Failed shutdown: %s", err)
}
}
c.(*hcs.System).Terminate()
case hcsshim.Container:
if err := c.(hcsshim.Container).Shutdown(); err != nil {
if hcsshim.IsPending(err) {
if err := c.(hcsshim.Container).Wait(); err != nil {
t.Fatalf("Failed Wait shutdown: %s", err)
}
} else {
t.Fatalf("Failed shutdown: %s", err)
}
}
c.(hcsshim.Container).Terminate()
default:
t.Fatalf("unknown type")
}
}
// Helper to launch a process in a container created through the hcsshim methods.
// At the point of calling, the container must have been successfully created.
func runShimCommand(t *testing.T,
c hcsshim.Container,
command string,
workdir string,
expectedExitCode int,
expectedOutput string) {
if c == nil {
t.Fatalf("requested container to start is nil!")
}
p, err := c.CreateProcess(&hcsshim.ProcessConfig{
CommandLine: command,
WorkingDirectory: workdir,
CreateStdInPipe: true,
CreateStdOutPipe: true,
CreateStdErrPipe: true,
})
if err != nil {
t.Fatalf("Failed Create Process: %s", err)
}
defer p.Close()
if err := p.Wait(); err != nil {
t.Fatalf("Failed Wait Process: %s", err)
}
exitCode, err := p.ExitCode()
if err != nil {
t.Fatalf("Failed to obtain process exit code: %s", err)
}
if exitCode != expectedExitCode {
t.Fatalf("Exit code from %s wasn't %d (%d)", command, expectedExitCode, exitCode)
}
_, o, _, err := p.Stdio()
if err != nil {
t.Fatalf("Failed to get Stdio handles for process: %s", err)
}
buf := new(bytes.Buffer)
buf.ReadFrom(o)
out := strings.TrimSpace(buf.String())
if expectedOutput != "" {
if out != expectedOutput {
t.Fatalf("Failed to get %q from process: %q", expectedOutput, out)
}
}
}
func runShimCommands(t *testing.T, c hcsshim.Container) {
runShimCommand(t, c, `echo Hello`, `c:\`, 0, "Hello")
// Check that read-only doesn't allow deletion or creation
runShimCommand(t, c, `ls c:\mappedro\readonly`, `c:\`, 0, `c:\mappedro\readonly`)
runShimCommand(t, c, `rm c:\mappedro\readonly`, `c:\`, 1, "")
runShimCommand(t, c, `cp readonly fail`, `c:\mappedro`, 1, "")
runShimCommand(t, c, `ls`, `c:\mappedro`, 0, `readonly`)
// Check that read-write allows new file creation and removal
runShimCommand(t, c, `ls`, `c:\mappedrw`, 0, `readwrite`)
runShimCommand(t, c, `cp readwrite succeeds`, `c:\mappedrw`, 0, "")
runShimCommand(t, c, `ls`, `c:\mappedrw`, 0, "readwrite\nsucceeds")
runShimCommand(t, c, `rm succeeds`, `c:\mappedrw`, 0, "")
runShimCommand(t, c, `ls`, `c:\mappedrw`, 0, `readwrite`)
}
func runHcsCommands(t *testing.T, c *hcs.System) {
runHcsCommand(t, c, `echo Hello`, `c:\`, 0, "Hello")
// Check that read-only doesn't allow deletion or creation
runHcsCommand(t, c, `ls c:\mappedro\readonly`, `c:\`, 0, `c:\mappedro\readonly`)
runHcsCommand(t, c, `rm c:\mappedro\readonly`, `c:\`, 1, "")
runHcsCommand(t, c, `cp readonly fail`, `c:\mappedro`, 1, "")
runHcsCommand(t, c, `ls`, `c:\mappedro`, 0, `readonly`)
// Check that read-write allows new file creation and removal
runHcsCommand(t, c, `ls`, `c:\mappedrw`, 0, `readwrite`)
runHcsCommand(t, c, `cp readwrite succeeds`, `c:\mappedrw`, 0, "")
runHcsCommand(t, c, `ls`, `c:\mappedrw`, 0, "readwrite\nsucceeds")
runHcsCommand(t, c, `rm succeeds`, `c:\mappedrw`, 0, "")
runHcsCommand(t, c, `ls`, `c:\mappedrw`, 0, `readwrite`)
}
// Helper to launch a process in a container created through the hcsshim methods.
// At the point of calling, the container must have been successfully created.
func runHcsCommand(t *testing.T,
c *hcs.System,
command string,
workdir string,
expectedExitCode int,
expectedOutput string) {
if c == nil {
t.Fatalf("requested container to start is nil!")
}
p, err := c.CreateProcess(&hcsshim.ProcessConfig{
CommandLine: command,
WorkingDirectory: workdir,
CreateStdInPipe: true,
CreateStdOutPipe: true,
CreateStdErrPipe: true,
})
if err != nil {
t.Fatalf("Failed Create Process: %s", err)
}
defer p.Close()
if err := p.Wait(); err != nil {
t.Fatalf("Failed Wait Process: %s", err)
}
exitCode, err := p.ExitCode()
if err != nil {
t.Fatalf("Failed to obtain process exit code: %s", err)
}
if exitCode != expectedExitCode {
t.Fatalf("Exit code from %s wasn't %d (%d)", command, expectedExitCode, exitCode)
}
_, o, _, err := p.Stdio()
if err != nil {
t.Fatalf("Failed to get Stdio handles for process: %s", err)
}
buf := new(bytes.Buffer)
buf.ReadFrom(o)
out := strings.TrimSpace(buf.String())
if expectedOutput != "" {
if out != expectedOutput {
t.Fatalf("Failed to get %q from process: %q", expectedOutput, out)
}
}
}
// busybox is used as it has lots of layers. Exercises more code.
// Also the commands are more flexible for verification
const imageName = "busyboxw"
// Creates two temp folders used for the mounts/mapped directories
func createTestMounts(t *testing.T) (string, string) {
// Create two temp folders for mapped directories.
hostRWSharedDirectory := testutilities.CreateTempDir(t)
hostROSharedDirectory := testutilities.CreateTempDir(t)
fRW, _ := os.OpenFile(filepath.Join(hostRWSharedDirectory, "readwrite"), os.O_RDWR|os.O_CREATE, 0755)
fRO, _ := os.OpenFile(filepath.Join(hostROSharedDirectory, "readonly"), os.O_RDWR|os.O_CREATE, 0755)
fRW.Close()
fRO.Close()
return hostRWSharedDirectory, hostROSharedDirectory
}
// For calling hcsshim interface, need hcsshim.Layer built from an images layer folders
func generateShimLayersStruct(t *testing.T, imageLayers []string) []hcsshim.Layer {
var layers []hcsshim.Layer
for _, layerFolder := range imageLayers {
guid, _ := wclayer.NameToGuid(filepath.Base(layerFolder))
layers = append(layers, hcsshim.Layer{Path: layerFolder, ID: guid.String()})
}
return layers
}
// Argon through HCSShim interface (v1)
func TestWCOWArgonShim(t *testing.T) {
imageLayers := testutilities.LayerFolders(t, imageName)
argonShimMounted := false
argonShimScratchDir := testutilities.CreateTempDir(t)
defer os.RemoveAll(argonShimScratchDir)
if err := wclayer.CreateScratchLayer(argonShimScratchDir, imageLayers); err != nil {
t.Fatalf("failed to create argon scratch layer: %s", err)
}
hostRWSharedDirectory, hostROSharedDirectory := createTestMounts(t)
defer os.RemoveAll(hostRWSharedDirectory)
defer os.RemoveAll(hostROSharedDirectory)
layers := generateShimLayersStruct(t, imageLayers)
// For cleanup on failure
defer func() {
if argonShimMounted {
hcsoci.UnmountContainerLayers(append(imageLayers, argonShimScratchDir), "", nil, hcsoci.UnmountOperationAll)
}
}()
// This is a cheat but stops us re-writing exactly the same code just for test
argonShimLocalMountPath, err := hcsoci.MountContainerLayers(append(imageLayers, argonShimScratchDir), "", nil)
if err != nil {
t.Fatal(err)
}
argonShimMounted = true
argonShim, err := hcsshim.CreateContainer("argon", &hcsshim.ContainerConfig{
SystemType: "Container",
Name: "argonShim",
VolumePath: argonShimLocalMountPath.(string),
LayerFolderPath: argonShimScratchDir,
Layers: layers,
MappedDirectories: []schema1.MappedDir{
schema1.MappedDir{
HostPath: hostROSharedDirectory,
ContainerPath: `c:\mappedro`,
ReadOnly: true,
},
schema1.MappedDir{
HostPath: hostRWSharedDirectory,
ContainerPath: `c:\mappedrw`,
},
},
HvRuntime: nil,
})
if err != nil {
t.Fatal(err)
}
startContainer(t, argonShim)
runShimCommands(t, argonShim)
stopContainer(t, argonShim)
if err := hcsoci.UnmountContainerLayers(append(imageLayers, argonShimScratchDir), "", nil, hcsoci.UnmountOperationAll); err != nil {
t.Fatal(err)
}
argonShimMounted = false
}
// Xenon through HCSShim interface (v1)
func TestWCOWXenonShim(t *testing.T) {
imageLayers := testutilities.LayerFolders(t, imageName)
xenonShimScratchDir := testutilities.CreateTempDir(t)
defer os.RemoveAll(xenonShimScratchDir)
if err := wclayer.CreateScratchLayer(xenonShimScratchDir, imageLayers); err != nil {
t.Fatalf("failed to create xenon scratch layer: %s", err)
}
hostRWSharedDirectory, hostROSharedDirectory := createTestMounts(t)
defer os.RemoveAll(hostRWSharedDirectory)
defer os.RemoveAll(hostROSharedDirectory)
uvmImagePath, err := uvmfolder.LocateUVMFolder(imageLayers)
if err != nil {
t.Fatalf("LocateUVMFolder failed %s", err)
}
layers := generateShimLayersStruct(t, imageLayers)
xenonShim, err := hcsshim.CreateContainer("xenon", &hcsshim.ContainerConfig{
SystemType: "Container",
Name: "xenonShim",
LayerFolderPath: xenonShimScratchDir,
Layers: layers,
HvRuntime: &hcsshim.HvRuntime{ImagePath: filepath.Join(uvmImagePath, "UtilityVM")},
HvPartition: true,
MappedDirectories: []schema1.MappedDir{
schema1.MappedDir{
HostPath: hostROSharedDirectory,
ContainerPath: `c:\mappedro`,
ReadOnly: true,
},
schema1.MappedDir{
HostPath: hostRWSharedDirectory,
ContainerPath: `c:\mappedrw`,
},
},
})
if err != nil {
t.Fatal(err)
}
startContainer(t, xenonShim)
runShimCommands(t, xenonShim)
stopContainer(t, xenonShim)
}
func generateWCOWOciTestSpec(t *testing.T, imageLayers []string, scratchPath, hostRWSharedDirectory, hostROSharedDirectory string) *specs.Spec {
return &specs.Spec{
Windows: &specs.Windows{
LayerFolders: append(imageLayers, scratchPath),
},
Mounts: []specs.Mount{
specs.Mount{
Source: hostROSharedDirectory,
Destination: `c:\mappedro`,
Options: []string{"ro"},
},
specs.Mount{
Source: hostRWSharedDirectory,
Destination: `c:\mappedrw`,
},
},
}
}
// Argon through HCSOCI interface (v1)
func TestWCOWArgonOciV1(t *testing.T) {
imageLayers := testutilities.LayerFolders(t, imageName)
argonOci1Mounted := false
argonOci1ScratchDir := testutilities.CreateTempDir(t)
defer os.RemoveAll(argonOci1ScratchDir)
if err := wclayer.CreateScratchLayer(argonOci1ScratchDir, imageLayers); err != nil {
t.Fatalf("failed to create argon scratch layer: %s", err)
}
hostRWSharedDirectory, hostROSharedDirectory := createTestMounts(t)
defer os.RemoveAll(hostRWSharedDirectory)
defer os.RemoveAll(hostROSharedDirectory)
// For cleanup on failure
var argonOci1Resources *hcsoci.Resources
var argonOci1 *hcs.System
defer func() {
if argonOci1Mounted {
hcsoci.ReleaseResources(argonOci1Resources, nil, true)
}
}()
var err error
spec := generateWCOWOciTestSpec(t, imageLayers, argonOci1ScratchDir, hostRWSharedDirectory, hostROSharedDirectory)
argonOci1, argonOci1Resources, err = hcsoci.CreateContainer(
&hcsoci.CreateOptions{
ID: "argonOci1",
SchemaVersion: schemaversion.SchemaV10(),
Spec: spec,
})
if err != nil {
t.Fatal(err)
}
argonOci1Mounted = true
startContainer(t, argonOci1)
runHcsCommands(t, argonOci1)
stopContainer(t, argonOci1)
if err := hcsoci.ReleaseResources(argonOci1Resources, nil, true); err != nil {
t.Fatal(err)
}
argonOci1Mounted = false
}
// Xenon through HCSOCI interface (v1)
func TestWCOWXenonOciV1(t *testing.T) {
imageLayers := testutilities.LayerFolders(t, imageName)
xenonOci1Mounted := false
xenonOci1ScratchDir := testutilities.CreateTempDir(t)
defer os.RemoveAll(xenonOci1ScratchDir)
if err := wclayer.CreateScratchLayer(xenonOci1ScratchDir, imageLayers); err != nil {
t.Fatalf("failed to create xenon scratch layer: %s", err)
}
hostRWSharedDirectory, hostROSharedDirectory := createTestMounts(t)
defer os.RemoveAll(hostRWSharedDirectory)
defer os.RemoveAll(hostROSharedDirectory)
// TODO: This isn't currently used.
// uvmImagePath, err := uvmfolder.LocateUVMFolder(imageLayers)
// if err != nil {
// t.Fatalf("LocateUVMFolder failed %s", err)
// }
// For cleanup on failure
var xenonOci1Resources *hcsoci.Resources
var xenonOci1 *hcs.System
defer func() {
if xenonOci1Mounted {
hcsoci.ReleaseResources(xenonOci1Resources, nil, true)
}
}()
var err error
spec := generateWCOWOciTestSpec(t, imageLayers, xenonOci1ScratchDir, hostRWSharedDirectory, hostROSharedDirectory)
spec.Windows.HyperV = &specs.WindowsHyperV{}
xenonOci1, xenonOci1Resources, err = hcsoci.CreateContainer(
&hcsoci.CreateOptions{
ID: "xenonOci1",
SchemaVersion: schemaversion.SchemaV10(),
Spec: spec,
})
if err != nil {
t.Fatal(err)
}
xenonOci1Mounted = true
startContainer(t, xenonOci1)
runHcsCommands(t, xenonOci1)
stopContainer(t, xenonOci1)
if err := hcsoci.ReleaseResources(xenonOci1Resources, nil, true); err != nil {
t.Fatal(err)
}
xenonOci1Mounted = false
}
// Argon through HCSOCI interface (v2)
func TestWCOWArgonOciV2(t *testing.T) {
testutilities.RequiresBuild(t, osversion.RS5)
imageLayers := testutilities.LayerFolders(t, imageName)
argonOci2Mounted := false
argonOci2ScratchDir := testutilities.CreateTempDir(t)
defer os.RemoveAll(argonOci2ScratchDir)
if err := wclayer.CreateScratchLayer(argonOci2ScratchDir, imageLayers); err != nil {
t.Fatalf("failed to create argon scratch layer: %s", err)
}
hostRWSharedDirectory, hostROSharedDirectory := createTestMounts(t)
defer os.RemoveAll(hostRWSharedDirectory)
defer os.RemoveAll(hostROSharedDirectory)
// For cleanup on failure
var argonOci2Resources *hcsoci.Resources
var argonOci2 *hcs.System
defer func() {
if argonOci2Mounted {
hcsoci.ReleaseResources(argonOci2Resources, nil, true)
}
}()
var err error
spec := generateWCOWOciTestSpec(t, imageLayers, argonOci2ScratchDir, hostRWSharedDirectory, hostROSharedDirectory)
argonOci2, argonOci2Resources, err = hcsoci.CreateContainer(
&hcsoci.CreateOptions{
ID: "argonOci2",
SchemaVersion: schemaversion.SchemaV21(),
Spec: spec,
})
if err != nil {
t.Fatal(err)
}
argonOci2Mounted = true
startContainer(t, argonOci2)
runHcsCommands(t, argonOci2)
stopContainer(t, argonOci2)
if err := hcsoci.ReleaseResources(argonOci2Resources, nil, true); err != nil {
t.Fatal(err)
}
argonOci2Mounted = false
}
// Xenon through HCSOCI interface (v2)
func TestWCOWXenonOciV2(t *testing.T) {
testutilities.RequiresBuild(t, osversion.RS5)
imageLayers := testutilities.LayerFolders(t, imageName)
xenonOci2Mounted := false
xenonOci2UVMCreated := false
xenonOci2ScratchDir := testutilities.CreateTempDir(t)
defer os.RemoveAll(xenonOci2ScratchDir)
if err := wclayer.CreateScratchLayer(xenonOci2ScratchDir, imageLayers); err != nil {
t.Fatalf("failed to create xenon scratch layer: %s", err)
}
hostRWSharedDirectory, hostROSharedDirectory := createTestMounts(t)
defer os.RemoveAll(hostRWSharedDirectory)
defer os.RemoveAll(hostROSharedDirectory)
uvmImagePath, err := uvmfolder.LocateUVMFolder(imageLayers)
if err != nil {
t.Fatalf("LocateUVMFolder failed %s", err)
}
var xenonOci2Resources *hcsoci.Resources
var xenonOci2 *hcs.System
var xenonOci2UVM *uvm.UtilityVM
defer func() {
if xenonOci2Mounted {
hcsoci.ReleaseResources(xenonOci2Resources, xenonOci2UVM, true)
}
if xenonOci2UVMCreated {
xenonOci2UVM.Terminate()
}
}()
// Create the utility VM.
xenonOci2UVMId := "xenonOci2UVM"
xenonOci2UVMScratchDir := testutilities.CreateTempDir(t)
if err := wcow.CreateUVMScratch(uvmImagePath, xenonOci2UVMScratchDir, xenonOci2UVMId); err != nil {
t.Fatalf("failed to create scratch: %s", err)
}
xenonOci2UVM, err = uvm.Create(
&uvm.UVMOptions{
ID: xenonOci2UVMId,
OperatingSystem: "windows",
LayerFolders: append(imageLayers, xenonOci2UVMScratchDir),
})
if err != nil {
t.Fatalf("Failed create UVM: %s", err)
}
xenonOci2UVMCreated = true
if err := xenonOci2UVM.Start(); err != nil {
xenonOci2UVM.Terminate()
t.Fatalf("Failed start UVM: %s", err)
}
spec := generateWCOWOciTestSpec(t, imageLayers, xenonOci2ScratchDir, hostRWSharedDirectory, hostROSharedDirectory)
xenonOci2, xenonOci2Resources, err = hcsoci.CreateContainer(
&hcsoci.CreateOptions{
ID: "xenonOci2",
HostingSystem: xenonOci2UVM,
SchemaVersion: schemaversion.SchemaV21(),
Spec: spec,
})
if err != nil {
t.Fatal(err)
}
xenonOci2Mounted = true
startContainer(t, xenonOci2)
runHcsCommands(t, xenonOci2)
stopContainer(t, xenonOci2)
if err := hcsoci.ReleaseResources(xenonOci2Resources, xenonOci2UVM, true); err != nil {
t.Fatal(err)
}
xenonOci2Mounted = false
// Terminate the UVM
xenonOci2UVM.ComputeSystem().Terminate()
xenonOci2UVMCreated = false
}