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

227 lines
7.1 KiB
Go

// +build functional lcow
package functional
import (
"bytes"
"os"
"os/exec"
"path/filepath"
"strings"
"testing"
"time"
"github.com/Microsoft/hcsshim/functional/utilities"
"github.com/Microsoft/hcsshim/internal/hcs"
"github.com/Microsoft/hcsshim/internal/hcsoci"
"github.com/Microsoft/hcsshim/internal/lcow"
"github.com/Microsoft/hcsshim/internal/osversion"
"github.com/Microsoft/hcsshim/internal/uvm"
)
// TestLCOWUVMNoSCSINoVPMemInitrd starts an LCOW utility VM without a SCSI controller and
// no VPMem device. Uses initrd.
func TestLCOWUVMNoSCSINoVPMemInitrd(t *testing.T) {
scsiCount := 0
var vpmemCount int32 = 0
opts := &uvm.UVMOptions{
OperatingSystem: "linux",
ID: "uvm",
VPMemDeviceCount: &vpmemCount,
SCSIControllerCount: &scsiCount,
}
testLCOWUVMNoSCSISingleVPMem(t, opts, `Command line: initrd=/initrd.img`)
}
// TestLCOWUVMNoSCSISingleVPMemVHD starts an LCOW utility VM without a SCSI controller and
// only a single VPMem device. Uses VPMEM VHD
func TestLCOWUVMNoSCSISingleVPMemVHD(t *testing.T) {
scsiCount := 0
var vpmemCount int32 = 1
var prfst uvm.PreferredRootFSType = uvm.PreferredRootFSTypeVHD
opts := &uvm.UVMOptions{
OperatingSystem: "linux",
ID: "uvm",
VPMemDeviceCount: &vpmemCount,
SCSIControllerCount: &scsiCount,
PreferredRootFSType: &prfst,
//ConsolePipe: `\\.\pipe\vmpipe`,
}
testLCOWUVMNoSCSISingleVPMem(t, opts, `Command line: root=/dev/pmem0 init=/init`)
}
func testLCOWUVMNoSCSISingleVPMem(t *testing.T, opts *uvm.UVMOptions, expected string) {
testutilities.RequiresBuild(t, osversion.RS5)
lcowUVM, err := uvm.Create(opts)
if err != nil {
t.Fatal(err)
}
if err := lcowUVM.Start(); err != nil {
t.Fatal(err)
}
defer lcowUVM.Terminate()
out, err := exec.Command(`hcsdiag`, `exec`, `-uvm`, lcowUVM.ID(), `dmesg`).Output() // TODO: Move the CreateProcess.
if err != nil {
t.Fatal(string(err.(*exec.ExitError).Stderr))
}
if !strings.Contains(string(out), expected) {
t.Fatalf("Expected dmesg output to have %q: %s", expected, string(out))
}
}
// TestLCOWTimeUVMStartVHD starts/terminates a utility VM booting from VPMem-
// attached root filesystem a number of times.
func TestLCOWTimeUVMStartVHD(t *testing.T) {
testLCOWTimeUVMStart(t, uvm.PreferredRootFSTypeVHD)
}
// TestLCOWTimeUVMStartInitRD starts/terminates a utility VM booting from initrd-
// attached root file system a number of times.
func TestLCOWTimeUVMStartInitRD(t *testing.T) {
testLCOWTimeUVMStart(t, uvm.PreferredRootFSTypeInitRd)
}
func testLCOWTimeUVMStart(t *testing.T, rfsType uvm.PreferredRootFSType) {
testutilities.RequiresBuild(t, osversion.RS5)
var vpmemCount int32 = 32
for i := 0; i < 3; i++ {
opts := &uvm.UVMOptions{
OperatingSystem: "linux",
ID: "uvm",
VPMemDeviceCount: &vpmemCount,
PreferredRootFSType: &rfsType,
}
lcowUVM, err := uvm.Create(opts)
if err != nil {
t.Fatal(err)
}
if err := lcowUVM.Start(); err != nil {
t.Fatal(err)
}
lcowUVM.Terminate()
}
}
func TestLCOWSimplePodScenario(t *testing.T) {
t.Skip("Doesn't work quite yet")
testutilities.RequiresBuild(t, osversion.RS5)
alpineLayers := testutilities.LayerFolders(t, "alpine")
cacheDir := testutilities.CreateTempDir(t)
defer os.RemoveAll(cacheDir)
cacheFile := filepath.Join(cacheDir, "cache.vhdx")
// This is what gets mounted into /tmp/scratch
uvmScratchDir := testutilities.CreateTempDir(t)
defer os.RemoveAll(uvmScratchDir)
uvmScratchFile := filepath.Join(uvmScratchDir, "uvmscratch.vhdx")
// Scratch for the first container
c1ScratchDir := testutilities.CreateTempDir(t)
defer os.RemoveAll(c1ScratchDir)
c1ScratchFile := filepath.Join(c1ScratchDir, "sandbox.vhdx")
// Scratch for the second container
c2ScratchDir := testutilities.CreateTempDir(t)
defer os.RemoveAll(c2ScratchDir)
c2ScratchFile := filepath.Join(c2ScratchDir, "sandbox.vhdx")
opts := &uvm.UVMOptions{
OperatingSystem: "linux",
ID: "uvm",
}
lcowUVM, err := uvm.Create(opts)
if err != nil {
t.Fatal(err)
}
if err := lcowUVM.Start(); err != nil {
t.Fatal(err)
}
defer lcowUVM.Terminate()
// Populate the cache and generate the scratch file for /tmp/scratch
if err := lcow.CreateScratch(lcowUVM, uvmScratchFile, lcow.DefaultScratchSizeGB, cacheFile, ""); err != nil {
t.Fatal(err)
}
if _, _, err := lcowUVM.AddSCSI(uvmScratchFile, `/tmp/scratch`); err != nil {
t.Fatal(err)
}
// Now create the first containers sandbox, populate a spec
if err := lcow.CreateScratch(lcowUVM, c1ScratchFile, lcow.DefaultScratchSizeGB, cacheFile, ""); err != nil {
t.Fatal(err)
}
c1Spec := testutilities.GetDefaultLinuxSpec(t)
c1Folders := append(alpineLayers, c1ScratchDir)
c1Spec.Windows.LayerFolders = c1Folders
c1Spec.Process.Args = []string{"echo", "hello", "lcow", "container", "one"}
c1Opts := &hcsoci.CreateOptions{
Spec: c1Spec,
HostingSystem: lcowUVM,
}
// Now create the second containers sandbox, populate a spec
if err := lcow.CreateScratch(lcowUVM, c2ScratchFile, lcow.DefaultScratchSizeGB, cacheFile, ""); err != nil {
t.Fatal(err)
}
c2Spec := testutilities.GetDefaultLinuxSpec(t)
c2Folders := append(alpineLayers, c2ScratchDir)
c2Spec.Windows.LayerFolders = c2Folders
c2Spec.Process.Args = []string{"echo", "hello", "lcow", "container", "two"}
c2Opts := &hcsoci.CreateOptions{
Spec: c2Spec,
HostingSystem: lcowUVM,
}
// Create the two containers
c1hcsSystem, c1Resources, err := CreateContainerTestWrapper(c1Opts)
if err != nil {
t.Fatal(err)
}
c2hcsSystem, c2Resources, err := CreateContainerTestWrapper(c2Opts)
if err != nil {
t.Fatal(err)
}
// Start them. In the UVM, they'll be in the created state from runc's perspective after this.eg
/// # runc list
//ID PID STATUS BUNDLE CREATED OWNER
//3a724c2b-f389-5c71-0555-ebc6f5379b30 138 running /run/gcs/c/1 2018-06-04T21:23:39.1253911Z root
//7a8229a0-eb60-b515-55e7-d2dd63ffae75 158 created /run/gcs/c/2 2018-06-04T21:23:39.4249048Z root
if err := c1hcsSystem.Start(); err != nil {
t.Fatal(err)
}
defer hcsoci.ReleaseResources(c1Resources, lcowUVM, true)
if err := c2hcsSystem.Start(); err != nil {
t.Fatal(err)
}
defer hcsoci.ReleaseResources(c2Resources, lcowUVM, true)
// Start the init process in each container and grab it's stdout comparing to expected
runInitProcess(t, c1hcsSystem, "hello lcow container one")
runInitProcess(t, c2hcsSystem, "hello lcow container two")
}
// Helper to run the init process in an LCOW container; verify it exits with exit
// code 0; verify stderr is empty; check output is as expected.
func runInitProcess(t *testing.T, s *hcs.System, expected string) {
var outB, errB bytes.Buffer
p, bc, err := lcow.CreateProcess(&lcow.ProcessOptions{
HCSSystem: s,
Stdout: &outB,
Stderr: &errB,
CopyTimeout: 30 * time.Second,
})
if err != nil {
t.Fatal(err)
}
defer p.Close()
if bc.Err != 0 {
t.Fatalf("got %d bytes on stderr: %s", bc.Err, errB.String())
}
if strings.TrimSpace(outB.String()) != expected {
t.Fatalf("got %q (%d) expecting %q", outB.String(), bc.Out, expected)
}
}