gitee.com/leisunstar/runtime@v0.0.0-20200521203717-5cef3e7b53f9/virtcontainers/sandbox_test.go (about)

     1  // Copyright (c) 2016 Intel Corporation
     2  //
     3  // SPDX-License-Identifier: Apache-2.0
     4  //
     5  
     6  package virtcontainers
     7  
     8  import (
     9  	"context"
    10  	"fmt"
    11  	"io/ioutil"
    12  	"os"
    13  	"os/exec"
    14  	"path"
    15  	"path/filepath"
    16  	"sync"
    17  	"syscall"
    18  	"testing"
    19  
    20  	ktu "github.com/kata-containers/runtime/pkg/katatestutils"
    21  	"github.com/kata-containers/runtime/virtcontainers/device/config"
    22  	"github.com/kata-containers/runtime/virtcontainers/device/drivers"
    23  	"github.com/kata-containers/runtime/virtcontainers/device/manager"
    24  	exp "github.com/kata-containers/runtime/virtcontainers/experimental"
    25  	"github.com/kata-containers/runtime/virtcontainers/persist/fs"
    26  	"github.com/kata-containers/runtime/virtcontainers/pkg/annotations"
    27  	"github.com/kata-containers/runtime/virtcontainers/types"
    28  	specs "github.com/opencontainers/runtime-spec/specs-go"
    29  	"github.com/stretchr/testify/assert"
    30  	"golang.org/x/sys/unix"
    31  )
    32  
    33  // dirMode is the permission bits used for creating a directory
    34  const dirMode = os.FileMode(0750) | os.ModeDir
    35  
    36  func newHypervisorConfig(kernelParams []Param, hParams []Param) HypervisorConfig {
    37  	return HypervisorConfig{
    38  		KernelPath:       filepath.Join(testDir, testKernel),
    39  		ImagePath:        filepath.Join(testDir, testImage),
    40  		HypervisorPath:   filepath.Join(testDir, testHypervisor),
    41  		KernelParams:     kernelParams,
    42  		HypervisorParams: hParams,
    43  	}
    44  
    45  }
    46  
    47  func testCreateSandbox(t *testing.T, id string,
    48  	htype HypervisorType, hconfig HypervisorConfig, atype AgentType,
    49  	nconfig NetworkConfig, containers []ContainerConfig,
    50  	volumes []types.Volume) (*Sandbox, error) {
    51  
    52  	sconfig := SandboxConfig{
    53  		ID:               id,
    54  		HypervisorType:   htype,
    55  		HypervisorConfig: hconfig,
    56  		AgentType:        atype,
    57  		NetworkConfig:    nconfig,
    58  		Volumes:          volumes,
    59  		Containers:       containers,
    60  		Annotations:      sandboxAnnotations,
    61  	}
    62  
    63  	sandbox, err := createSandbox(context.Background(), sconfig, nil)
    64  	if err != nil {
    65  		return nil, fmt.Errorf("Could not create sandbox: %s", err)
    66  	}
    67  
    68  	if err := sandbox.agent.startSandbox(sandbox); err != nil {
    69  		return nil, err
    70  	}
    71  
    72  	if err := sandbox.createContainers(); err != nil {
    73  		return nil, err
    74  	}
    75  
    76  	if sandbox.id == "" {
    77  		return sandbox, fmt.Errorf("Invalid empty sandbox ID")
    78  	}
    79  
    80  	if id != "" && sandbox.id != id {
    81  		return sandbox, fmt.Errorf("Invalid ID %s vs %s", id, sandbox.id)
    82  	}
    83  
    84  	return sandbox, nil
    85  }
    86  
    87  func TestCreateEmptySandbox(t *testing.T) {
    88  	_, err := testCreateSandbox(t, testSandboxID, MockHypervisor, HypervisorConfig{}, NoopAgentType, NetworkConfig{}, nil, nil)
    89  	assert.Error(t, err)
    90  	defer cleanUp()
    91  }
    92  
    93  func TestCreateEmptyHypervisorSandbox(t *testing.T) {
    94  	_, err := testCreateSandbox(t, testSandboxID, QemuHypervisor, HypervisorConfig{}, NoopAgentType, NetworkConfig{}, nil, nil)
    95  	assert.Error(t, err)
    96  	defer cleanUp()
    97  }
    98  
    99  func TestCreateMockSandbox(t *testing.T) {
   100  	hConfig := newHypervisorConfig(nil, nil)
   101  	_, err := testCreateSandbox(t, testSandboxID, MockHypervisor, hConfig, NoopAgentType, NetworkConfig{}, nil, nil)
   102  	assert.NoError(t, err)
   103  	defer cleanUp()
   104  }
   105  
   106  func TestCalculateSandboxCPUs(t *testing.T) {
   107  	sandbox := &Sandbox{}
   108  	sandbox.config = &SandboxConfig{}
   109  	unconstrained := newTestContainerConfigNoop("cont-00001")
   110  	constrained := newTestContainerConfigNoop("cont-00001")
   111  	quota := int64(4000)
   112  	period := uint64(1000)
   113  	constrained.Resources.CPU = &specs.LinuxCPU{Period: &period, Quota: &quota}
   114  
   115  	tests := []struct {
   116  		name       string
   117  		containers []ContainerConfig
   118  		want       uint32
   119  	}{
   120  		{"1-unconstrained", []ContainerConfig{unconstrained}, 0},
   121  		{"2-unconstrained", []ContainerConfig{unconstrained, unconstrained}, 0},
   122  		{"1-constrained", []ContainerConfig{constrained}, 4},
   123  		{"2-constrained", []ContainerConfig{constrained, constrained}, 8},
   124  		{"3-mix-constraints", []ContainerConfig{unconstrained, constrained, constrained}, 8},
   125  		{"3-constrained", []ContainerConfig{constrained, constrained, constrained}, 12},
   126  	}
   127  	for _, tt := range tests {
   128  		t.Run(tt.name, func(t *testing.T) {
   129  			sandbox.config.Containers = tt.containers
   130  			got := sandbox.calculateSandboxCPUs()
   131  			assert.Equal(t, got, tt.want)
   132  		})
   133  	}
   134  }
   135  
   136  func TestCalculateSandboxMem(t *testing.T) {
   137  	sandbox := &Sandbox{}
   138  	sandbox.config = &SandboxConfig{}
   139  	unconstrained := newTestContainerConfigNoop("cont-00001")
   140  	constrained := newTestContainerConfigNoop("cont-00001")
   141  	limit := int64(4000)
   142  	constrained.Resources.Memory = &specs.LinuxMemory{Limit: &limit}
   143  
   144  	tests := []struct {
   145  		name       string
   146  		containers []ContainerConfig
   147  		want       int64
   148  	}{
   149  		{"1-unconstrained", []ContainerConfig{unconstrained}, 0},
   150  		{"2-unconstrained", []ContainerConfig{unconstrained, unconstrained}, 0},
   151  		{"1-constrained", []ContainerConfig{constrained}, limit},
   152  		{"2-constrained", []ContainerConfig{constrained, constrained}, limit * 2},
   153  		{"3-mix-constraints", []ContainerConfig{unconstrained, constrained, constrained}, limit * 2},
   154  		{"3-constrained", []ContainerConfig{constrained, constrained, constrained}, limit * 3},
   155  	}
   156  	for _, tt := range tests {
   157  		t.Run(tt.name, func(t *testing.T) {
   158  			sandbox.config.Containers = tt.containers
   159  			got := sandbox.calculateSandboxMemory()
   160  			assert.Equal(t, got, tt.want)
   161  		})
   162  	}
   163  }
   164  
   165  func TestCreateSandboxEmptyID(t *testing.T) {
   166  	hConfig := newHypervisorConfig(nil, nil)
   167  	_, err := testCreateSandbox(t, "", MockHypervisor, hConfig, NoopAgentType, NetworkConfig{}, nil, nil)
   168  	assert.Error(t, err)
   169  	defer cleanUp()
   170  }
   171  
   172  func testSandboxStateTransition(t *testing.T, state types.StateString, newState types.StateString) error {
   173  	hConfig := newHypervisorConfig(nil, nil)
   174  
   175  	p, err := testCreateSandbox(t, testSandboxID, MockHypervisor, hConfig, NoopAgentType, NetworkConfig{}, nil, nil)
   176  	assert.NoError(t, err)
   177  	defer cleanUp()
   178  
   179  	p.state = types.SandboxState{
   180  		State: state,
   181  	}
   182  
   183  	return p.state.ValidTransition(state, newState)
   184  }
   185  
   186  func TestSandboxStateReadyRunning(t *testing.T) {
   187  	err := testSandboxStateTransition(t, types.StateReady, types.StateRunning)
   188  	assert.NoError(t, err)
   189  }
   190  
   191  func TestSandboxStateRunningPaused(t *testing.T) {
   192  	err := testSandboxStateTransition(t, types.StateRunning, types.StatePaused)
   193  	assert.NoError(t, err)
   194  }
   195  
   196  func TestSandboxStatePausedRunning(t *testing.T) {
   197  	err := testSandboxStateTransition(t, types.StatePaused, types.StateRunning)
   198  	assert.NoError(t, err)
   199  }
   200  
   201  func TestSandboxStatePausedStopped(t *testing.T) {
   202  	err := testSandboxStateTransition(t, types.StatePaused, types.StateStopped)
   203  	assert.NoError(t, err)
   204  }
   205  
   206  func TestSandboxStateRunningStopped(t *testing.T) {
   207  	err := testSandboxStateTransition(t, types.StateRunning, types.StateStopped)
   208  	assert.NoError(t, err)
   209  }
   210  
   211  func TestSandboxStateReadyPaused(t *testing.T) {
   212  	err := testSandboxStateTransition(t, types.StateReady, types.StateStopped)
   213  	assert.NoError(t, err)
   214  }
   215  
   216  func TestSandboxStatePausedReady(t *testing.T) {
   217  	err := testSandboxStateTransition(t, types.StateStopped, types.StateReady)
   218  	assert.Error(t, err)
   219  }
   220  
   221  func testStateValid(t *testing.T, stateStr types.StateString, expected bool) {
   222  	state := &types.SandboxState{
   223  		State: stateStr,
   224  	}
   225  
   226  	ok := state.Valid()
   227  	assert.Equal(t, ok, expected)
   228  }
   229  
   230  func TestStateValidSuccessful(t *testing.T) {
   231  	testStateValid(t, types.StateReady, true)
   232  	testStateValid(t, types.StateRunning, true)
   233  	testStateValid(t, types.StatePaused, true)
   234  	testStateValid(t, types.StateStopped, true)
   235  }
   236  
   237  func TestStateValidFailing(t *testing.T) {
   238  	testStateValid(t, "", false)
   239  }
   240  
   241  func TestValidTransitionFailingOldStateMismatch(t *testing.T) {
   242  	state := &types.SandboxState{
   243  		State: types.StateReady,
   244  	}
   245  
   246  	err := state.ValidTransition(types.StateRunning, types.StateStopped)
   247  	assert.Error(t, err)
   248  }
   249  
   250  func TestVolumesSetSuccessful(t *testing.T) {
   251  	volumes := &types.Volumes{}
   252  
   253  	volStr := "mountTag1:hostPath1 mountTag2:hostPath2"
   254  
   255  	expected := types.Volumes{
   256  		{
   257  			MountTag: "mountTag1",
   258  			HostPath: "hostPath1",
   259  		},
   260  		{
   261  			MountTag: "mountTag2",
   262  			HostPath: "hostPath2",
   263  		},
   264  	}
   265  
   266  	err := volumes.Set(volStr)
   267  	assert.NoError(t, err)
   268  	assert.Exactly(t, *volumes, expected)
   269  }
   270  
   271  func TestVolumesSetFailingTooFewArguments(t *testing.T) {
   272  	volumes := &types.Volumes{}
   273  
   274  	volStr := "mountTag1 mountTag2"
   275  
   276  	err := volumes.Set(volStr)
   277  	assert.Error(t, err)
   278  }
   279  
   280  func TestVolumesSetFailingTooManyArguments(t *testing.T) {
   281  	volumes := &types.Volumes{}
   282  
   283  	volStr := "mountTag1:hostPath1:Foo1 mountTag2:hostPath2:Foo2"
   284  
   285  	err := volumes.Set(volStr)
   286  	assert.Error(t, err)
   287  }
   288  
   289  func TestVolumesSetFailingVoidArguments(t *testing.T) {
   290  	volumes := &types.Volumes{}
   291  
   292  	volStr := ": : :"
   293  
   294  	err := volumes.Set(volStr)
   295  	assert.Error(t, err)
   296  }
   297  
   298  func TestVolumesStringSuccessful(t *testing.T) {
   299  	volumes := &types.Volumes{
   300  		{
   301  			MountTag: "mountTag1",
   302  			HostPath: "hostPath1",
   303  		},
   304  		{
   305  			MountTag: "mountTag2",
   306  			HostPath: "hostPath2",
   307  		},
   308  	}
   309  
   310  	expected := "mountTag1:hostPath1 mountTag2:hostPath2"
   311  
   312  	result := volumes.String()
   313  	assert.Equal(t, result, expected)
   314  }
   315  
   316  func TestSocketsSetSuccessful(t *testing.T) {
   317  	sockets := &types.Sockets{}
   318  
   319  	sockStr := "devID1:id1:hostPath1:Name1 devID2:id2:hostPath2:Name2"
   320  
   321  	expected := types.Sockets{
   322  		{
   323  			DeviceID: "devID1",
   324  			ID:       "id1",
   325  			HostPath: "hostPath1",
   326  			Name:     "Name1",
   327  		},
   328  		{
   329  			DeviceID: "devID2",
   330  			ID:       "id2",
   331  			HostPath: "hostPath2",
   332  			Name:     "Name2",
   333  		},
   334  	}
   335  
   336  	err := sockets.Set(sockStr)
   337  	assert.NoError(t, err)
   338  	assert.Exactly(t, *sockets, expected)
   339  }
   340  
   341  func TestSocketsSetFailingWrongArgsAmount(t *testing.T) {
   342  	sockets := &types.Sockets{}
   343  
   344  	sockStr := "devID1:id1:hostPath1"
   345  
   346  	err := sockets.Set(sockStr)
   347  	assert.Error(t, err)
   348  }
   349  
   350  func TestSocketsSetFailingVoidArguments(t *testing.T) {
   351  	sockets := &types.Sockets{}
   352  
   353  	sockStr := ":::"
   354  
   355  	err := sockets.Set(sockStr)
   356  	assert.Error(t, err)
   357  }
   358  
   359  func TestSocketsStringSuccessful(t *testing.T) {
   360  	sockets := &types.Sockets{
   361  		{
   362  			DeviceID: "devID1",
   363  			ID:       "id1",
   364  			HostPath: "hostPath1",
   365  			Name:     "Name1",
   366  		},
   367  		{
   368  			DeviceID: "devID2",
   369  			ID:       "id2",
   370  			HostPath: "hostPath2",
   371  			Name:     "Name2",
   372  		},
   373  	}
   374  
   375  	expected := "devID1:id1:hostPath1:Name1 devID2:id2:hostPath2:Name2"
   376  
   377  	result := sockets.String()
   378  	assert.Equal(t, result, expected)
   379  }
   380  
   381  func TestSandboxListSuccessful(t *testing.T) {
   382  	sandbox := &Sandbox{}
   383  
   384  	sandboxList, err := sandbox.list()
   385  	assert.NoError(t, err)
   386  	assert.Nil(t, sandboxList)
   387  }
   388  
   389  func TestSandboxEnterSuccessful(t *testing.T) {
   390  	sandbox := &Sandbox{}
   391  
   392  	err := sandbox.enter([]string{})
   393  	assert.NoError(t, err)
   394  }
   395  
   396  func testCheckInitSandboxAndContainerStates(p *Sandbox, initialSandboxState types.SandboxState, c *Container, initialContainerState types.ContainerState) error {
   397  	if p.state.State != initialSandboxState.State {
   398  		return fmt.Errorf("Expected sandbox state %v, got %v", initialSandboxState.State, p.state.State)
   399  	}
   400  
   401  	if c.state.State != initialContainerState.State {
   402  		return fmt.Errorf("Expected container state %v, got %v", initialContainerState.State, c.state.State)
   403  	}
   404  
   405  	return nil
   406  }
   407  
   408  func testForceSandboxStateChangeAndCheck(t *testing.T, p *Sandbox, newSandboxState types.SandboxState) error {
   409  	// force sandbox state change
   410  	err := p.setSandboxState(newSandboxState.State)
   411  	assert.NoError(t, err)
   412  	// check the in-memory state is correct
   413  	if p.state.State != newSandboxState.State {
   414  		return fmt.Errorf("Expected state %v, got %v", newSandboxState.State, p.state.State)
   415  	}
   416  
   417  	return nil
   418  }
   419  
   420  func testForceContainerStateChangeAndCheck(t *testing.T, p *Sandbox, c *Container, newContainerState types.ContainerState) error {
   421  	// force container state change
   422  	err := c.setContainerState(newContainerState.State)
   423  	assert.NoError(t, err)
   424  
   425  	// check the in-memory state is correct
   426  	if c.state.State != newContainerState.State {
   427  		return fmt.Errorf("Expected state %v, got %v", newContainerState.State, c.state.State)
   428  	}
   429  
   430  	return nil
   431  }
   432  
   433  func testCheckSandboxOnDiskState(p *Sandbox, sandboxState types.SandboxState) error {
   434  	// check on-disk state is correct
   435  	if p.state.State != sandboxState.State {
   436  		return fmt.Errorf("Expected state %v, got %v", sandboxState.State, p.state.State)
   437  	}
   438  
   439  	return nil
   440  }
   441  
   442  func testCheckContainerOnDiskState(c *Container, containerState types.ContainerState) error {
   443  	// check on-disk state is correct
   444  	if c.state.State != containerState.State {
   445  		return fmt.Errorf("Expected state %v, got %v", containerState.State, c.state.State)
   446  	}
   447  
   448  	return nil
   449  }
   450  
   451  func TestSandboxSetSandboxAndContainerState(t *testing.T) {
   452  	contID := "505"
   453  	contConfig := newTestContainerConfigNoop(contID)
   454  	hConfig := newHypervisorConfig(nil, nil)
   455  	assert := assert.New(t)
   456  
   457  	// create a sandbox
   458  	p, err := testCreateSandbox(t, testSandboxID, MockHypervisor, hConfig, NoopAgentType, NetworkConfig{}, []ContainerConfig{contConfig}, nil)
   459  	assert.NoError(err)
   460  	defer cleanUp()
   461  
   462  	l := len(p.GetAllContainers())
   463  	assert.Equal(l, 1)
   464  
   465  	initialSandboxState := types.SandboxState{
   466  		State: types.StateReady,
   467  	}
   468  
   469  	// After a sandbox creation, a container has a READY state
   470  	initialContainerState := types.ContainerState{
   471  		State: types.StateReady,
   472  	}
   473  
   474  	c, err := p.findContainer(contID)
   475  	assert.NoError(err)
   476  
   477  	// check initial sandbox and container states
   478  	if err := testCheckInitSandboxAndContainerStates(p, initialSandboxState, c, initialContainerState); err != nil {
   479  		t.Error(err)
   480  	}
   481  
   482  	// persist to disk
   483  	err = p.storeSandbox()
   484  	assert.NoError(err)
   485  
   486  	newSandboxState := types.SandboxState{
   487  		State: types.StateRunning,
   488  	}
   489  
   490  	if err := testForceSandboxStateChangeAndCheck(t, p, newSandboxState); err != nil {
   491  		t.Error(err)
   492  	}
   493  
   494  	newContainerState := types.ContainerState{
   495  		State: types.StateStopped,
   496  	}
   497  
   498  	if err := testForceContainerStateChangeAndCheck(t, p, c, newContainerState); err != nil {
   499  		t.Error(err)
   500  	}
   501  
   502  	// force state to be read from disk
   503  	p2, err := fetchSandbox(context.Background(), p.ID())
   504  	assert.NoError(err)
   505  
   506  	if err := testCheckSandboxOnDiskState(p2, newSandboxState); err != nil {
   507  		t.Error(err)
   508  	}
   509  
   510  	c2, err := p2.findContainer(contID)
   511  	assert.NoError(err)
   512  
   513  	if err := testCheckContainerOnDiskState(c2, newContainerState); err != nil {
   514  		t.Error(err)
   515  	}
   516  
   517  	// revert sandbox state to allow it to be deleted
   518  	err = p.setSandboxState(initialSandboxState.State)
   519  	assert.NoError(err)
   520  
   521  	// clean up
   522  	err = p.Delete()
   523  	assert.NoError(err)
   524  }
   525  
   526  func TestGetContainer(t *testing.T) {
   527  	containerIDs := []string{"abc", "123", "xyz", "rgb"}
   528  	containers := map[string]*Container{}
   529  
   530  	for _, id := range containerIDs {
   531  		c := Container{id: id}
   532  		containers[id] = &c
   533  	}
   534  
   535  	sandbox := Sandbox{
   536  		containers: containers,
   537  	}
   538  
   539  	c := sandbox.GetContainer("noid")
   540  	assert.Nil(t, c)
   541  
   542  	for _, id := range containerIDs {
   543  		c = sandbox.GetContainer(id)
   544  		assert.NotNil(t, c)
   545  	}
   546  }
   547  
   548  func TestGetAllContainers(t *testing.T) {
   549  	containerIDs := []string{"abc", "123", "xyz", "rgb"}
   550  	containers := map[string]*Container{}
   551  
   552  	for _, id := range containerIDs {
   553  		c := &Container{id: id}
   554  		containers[id] = c
   555  	}
   556  
   557  	sandbox := Sandbox{
   558  		containers: containers,
   559  	}
   560  
   561  	list := sandbox.GetAllContainers()
   562  
   563  	for _, c := range list {
   564  		assert.NotNil(t, containers[c.ID()], nil)
   565  	}
   566  }
   567  
   568  func TestSetAnnotations(t *testing.T) {
   569  	assert := assert.New(t)
   570  	sandbox := Sandbox{
   571  		ctx:             context.Background(),
   572  		id:              "abcxyz123",
   573  		annotationsLock: &sync.RWMutex{},
   574  		config: &SandboxConfig{
   575  			Annotations: map[string]string{
   576  				"annotation1": "abc",
   577  			},
   578  		},
   579  	}
   580  
   581  	keyAnnotation := "annotation2"
   582  	valueAnnotation := "xyz"
   583  	newAnnotations := map[string]string{
   584  		keyAnnotation: valueAnnotation,
   585  	}
   586  
   587  	// Add a new annotation
   588  	sandbox.SetAnnotations(newAnnotations)
   589  
   590  	v, err := sandbox.Annotations(keyAnnotation)
   591  	assert.NoError(err)
   592  	assert.Equal(v, valueAnnotation)
   593  
   594  	//Change the value of an annotation
   595  	valueAnnotation = "123"
   596  	newAnnotations[keyAnnotation] = valueAnnotation
   597  
   598  	sandbox.SetAnnotations(newAnnotations)
   599  
   600  	v, err = sandbox.Annotations(keyAnnotation)
   601  	assert.NoError(err)
   602  	assert.Equal(v, valueAnnotation)
   603  }
   604  
   605  func TestSandboxGetContainer(t *testing.T) {
   606  	assert := assert.New(t)
   607  
   608  	emptySandbox := Sandbox{}
   609  	_, err := emptySandbox.findContainer("")
   610  	assert.Error(err)
   611  
   612  	_, err = emptySandbox.findContainer("foo")
   613  	assert.Error(err)
   614  
   615  	hConfig := newHypervisorConfig(nil, nil)
   616  	p, err := testCreateSandbox(t, testSandboxID, MockHypervisor, hConfig, NoopAgentType, NetworkConfig{}, nil, nil)
   617  	assert.NoError(err)
   618  	defer cleanUp()
   619  
   620  	contID := "999"
   621  	contConfig := newTestContainerConfigNoop(contID)
   622  	nc, err := newContainer(p, &contConfig)
   623  	assert.NoError(err)
   624  
   625  	err = p.addContainer(nc)
   626  	assert.NoError(err)
   627  
   628  	got := false
   629  	for _, c := range p.GetAllContainers() {
   630  		c2, err := p.findContainer(c.ID())
   631  		assert.NoError(err)
   632  		assert.Equal(c2.ID(), c.ID())
   633  
   634  		if c2.ID() == contID {
   635  			got = true
   636  		}
   637  	}
   638  
   639  	assert.True(got)
   640  }
   641  
   642  func TestContainerStateSetFstype(t *testing.T) {
   643  	var err error
   644  	assert := assert.New(t)
   645  
   646  	containers := []ContainerConfig{
   647  		{
   648  			ID:          "100",
   649  			Annotations: containerAnnotations,
   650  			CustomSpec:  newEmptySpec(),
   651  		},
   652  	}
   653  
   654  	hConfig := newHypervisorConfig(nil, nil)
   655  	sandbox, err := testCreateSandbox(t, testSandboxID, MockHypervisor, hConfig, NoopAgentType, NetworkConfig{}, containers, nil)
   656  	assert.Nil(err)
   657  	defer cleanUp()
   658  
   659  	c := sandbox.GetContainer("100")
   660  	assert.NotNil(c)
   661  
   662  	cImpl, ok := c.(*Container)
   663  	assert.True(ok)
   664  
   665  	state := types.ContainerState{
   666  		State:  "ready",
   667  		Fstype: "vfs",
   668  	}
   669  
   670  	cImpl.state = state
   671  
   672  	newFstype := "ext4"
   673  	err = cImpl.setStateFstype(newFstype)
   674  	assert.NoError(err)
   675  	assert.Equal(cImpl.state.Fstype, newFstype)
   676  }
   677  
   678  func TestSandboxAttachDevicesVFIO(t *testing.T) {
   679  	tmpDir, err := ioutil.TempDir("", "")
   680  	assert.Nil(t, err)
   681  	os.RemoveAll(tmpDir)
   682  
   683  	testFDIOGroup := "2"
   684  	testDeviceBDFPath := "0000:00:1c.0"
   685  
   686  	devicesDir := filepath.Join(tmpDir, testFDIOGroup, "devices")
   687  	err = os.MkdirAll(devicesDir, DirMode)
   688  	assert.Nil(t, err)
   689  
   690  	deviceFile := filepath.Join(devicesDir, testDeviceBDFPath)
   691  	_, err = os.Create(deviceFile)
   692  	assert.Nil(t, err)
   693  
   694  	savedIOMMUPath := config.SysIOMMUPath
   695  	config.SysIOMMUPath = tmpDir
   696  
   697  	defer func() {
   698  		config.SysIOMMUPath = savedIOMMUPath
   699  	}()
   700  
   701  	dm := manager.NewDeviceManager(manager.VirtioSCSI, false, "", nil)
   702  	path := filepath.Join(vfioPath, testFDIOGroup)
   703  	deviceInfo := config.DeviceInfo{
   704  		HostPath:      path,
   705  		ContainerPath: path,
   706  		DevType:       "c",
   707  	}
   708  	dev, err := dm.NewDevice(deviceInfo)
   709  	assert.Nil(t, err, "deviceManager.NewDevice return error: %v", err)
   710  
   711  	c := &Container{
   712  		id: "100",
   713  		devices: []ContainerDevice{
   714  			{
   715  				ID:            dev.DeviceID(),
   716  				ContainerPath: path,
   717  			},
   718  		},
   719  	}
   720  
   721  	containers := map[string]*Container{}
   722  	containers[c.id] = c
   723  
   724  	sandbox := Sandbox{
   725  		id:         "100",
   726  		containers: containers,
   727  		hypervisor: &mockHypervisor{},
   728  		devManager: dm,
   729  		ctx:        context.Background(),
   730  		config:     &SandboxConfig{},
   731  	}
   732  
   733  	containers[c.id].sandbox = &sandbox
   734  
   735  	err = containers[c.id].attachDevices(c.devices)
   736  	assert.Nil(t, err, "Error while attaching devices %s", err)
   737  
   738  	err = containers[c.id].detachDevices()
   739  	assert.Nil(t, err, "Error while detaching devices %s", err)
   740  }
   741  
   742  func TestSandboxAttachDevicesVhostUserBlk(t *testing.T) {
   743  	rootEnabled := true
   744  	tc := ktu.NewTestConstraint(false)
   745  	if tc.NotValid(ktu.NeedRoot()) {
   746  		rootEnabled = false
   747  	}
   748  
   749  	tmpDir, err := ioutil.TempDir("", "")
   750  	assert.Nil(t, err)
   751  	os.RemoveAll(tmpDir)
   752  	dm := manager.NewDeviceManager(manager.VirtioSCSI, true, tmpDir, nil)
   753  
   754  	vhostUserDevNodePath := filepath.Join(tmpDir, "/block/devices/")
   755  	vhostUserSockPath := filepath.Join(tmpDir, "/block/sockets/")
   756  	deviceNodePath := filepath.Join(vhostUserDevNodePath, "vhostblk0")
   757  	deviceSockPath := filepath.Join(vhostUserSockPath, "vhostblk0")
   758  
   759  	err = os.MkdirAll(vhostUserDevNodePath, dirMode)
   760  	assert.Nil(t, err)
   761  	err = os.MkdirAll(vhostUserSockPath, dirMode)
   762  	assert.Nil(t, err)
   763  	_, err = os.Create(deviceSockPath)
   764  	assert.Nil(t, err)
   765  
   766  	// mknod requires root privilege, call mock function for non-root to
   767  	// get VhostUserBlk device type.
   768  	if rootEnabled == true {
   769  		err = unix.Mknod(deviceNodePath, unix.S_IFBLK, int(unix.Mkdev(config.VhostUserBlkMajor, 0)))
   770  		assert.Nil(t, err)
   771  	} else {
   772  		savedFunc := config.GetVhostUserNodeStatFunc
   773  
   774  		_, err = os.Create(deviceNodePath)
   775  		assert.Nil(t, err)
   776  
   777  		config.GetVhostUserNodeStatFunc = func(devNodePath string,
   778  			devNodeStat *unix.Stat_t) error {
   779  			if deviceNodePath != devNodePath {
   780  				return fmt.Errorf("mock GetVhostUserNodeStatFunc error")
   781  			}
   782  
   783  			devNodeStat.Rdev = unix.Mkdev(config.VhostUserBlkMajor, 0)
   784  			return nil
   785  		}
   786  
   787  		defer func() {
   788  			config.GetVhostUserNodeStatFunc = savedFunc
   789  		}()
   790  	}
   791  
   792  	path := "/dev/vda"
   793  	deviceInfo := config.DeviceInfo{
   794  		HostPath:      deviceNodePath,
   795  		ContainerPath: path,
   796  		DevType:       "b",
   797  		Major:         config.VhostUserBlkMajor,
   798  		Minor:         0,
   799  	}
   800  
   801  	device, err := dm.NewDevice(deviceInfo)
   802  	assert.Nil(t, err)
   803  	_, ok := device.(*drivers.VhostUserBlkDevice)
   804  	assert.True(t, ok)
   805  
   806  	c := &Container{
   807  		id: "100",
   808  		devices: []ContainerDevice{
   809  			{
   810  				ID:            device.DeviceID(),
   811  				ContainerPath: path,
   812  			},
   813  		},
   814  	}
   815  
   816  	containers := map[string]*Container{}
   817  	containers[c.id] = c
   818  
   819  	sandbox := Sandbox{
   820  		id:         "100",
   821  		containers: containers,
   822  		hypervisor: &mockHypervisor{},
   823  		devManager: dm,
   824  		ctx:        context.Background(),
   825  		config:     &SandboxConfig{},
   826  	}
   827  
   828  	containers[c.id].sandbox = &sandbox
   829  
   830  	err = containers[c.id].attachDevices(c.devices)
   831  	assert.Nil(t, err, "Error while attaching vhost-user-blk devices %s", err)
   832  
   833  	err = containers[c.id].detachDevices()
   834  	assert.Nil(t, err, "Error while detaching vhost-user-blk devices %s", err)
   835  }
   836  
   837  var assetContent = []byte("FakeAsset fake asset FAKE ASSET")
   838  var assetContentHash = "92549f8d2018a95a294d28a65e795ed7d1a9d150009a28cea108ae10101178676f04ab82a6950d0099e4924f9c5e41dcba8ece56b75fc8b4e0a7492cb2a8c880"
   839  var assetContentWrongHash = "92549f8d2018a95a294d28a65e795ed7d1a9d150009a28cea108ae10101178676f04ab82a6950d0099e4924f9c5e41dcba8ece56b75fc8b4e0a7492cb2a8c881"
   840  
   841  func TestSandboxCreateAssets(t *testing.T) {
   842  	assert := assert.New(t)
   843  
   844  	tmpfile, err := ioutil.TempFile("", "virtcontainers-test-")
   845  	assert.Nil(err)
   846  
   847  	defer func() {
   848  		tmpfile.Close()
   849  		os.Remove(tmpfile.Name()) // clean up
   850  	}()
   851  
   852  	_, err = tmpfile.Write(assetContent)
   853  	assert.Nil(err)
   854  
   855  	originalKernelPath := filepath.Join(testDir, testKernel)
   856  
   857  	hc := HypervisorConfig{
   858  		KernelPath: originalKernelPath,
   859  		ImagePath:  filepath.Join(testDir, testImage),
   860  	}
   861  
   862  	p := &SandboxConfig{
   863  		Annotations: map[string]string{
   864  			annotations.KernelPath: tmpfile.Name(),
   865  			annotations.KernelHash: assetContentHash,
   866  		},
   867  
   868  		HypervisorConfig: hc,
   869  	}
   870  
   871  	err = createAssets(context.Background(), p)
   872  	assert.Nil(err)
   873  
   874  	a, ok := p.HypervisorConfig.customAssets[types.KernelAsset]
   875  	assert.True(ok)
   876  	assert.Equal(a.Path(), tmpfile.Name())
   877  
   878  	p = &SandboxConfig{
   879  		Annotations: map[string]string{
   880  			annotations.KernelPath: tmpfile.Name(),
   881  			annotations.KernelHash: assetContentWrongHash,
   882  		},
   883  
   884  		HypervisorConfig: hc,
   885  	}
   886  
   887  	err = createAssets(context.Background(), p)
   888  	assert.NotNil(err)
   889  }
   890  
   891  func testFindContainerFailure(t *testing.T, sandbox *Sandbox, cid string) {
   892  	c, err := sandbox.findContainer(cid)
   893  	assert.Nil(t, c, "Container pointer should be nil")
   894  	assert.NotNil(t, err, "Should have returned an error")
   895  }
   896  
   897  func TestFindContainerSandboxNilFailure(t *testing.T) {
   898  	testFindContainerFailure(t, nil, testContainerID)
   899  }
   900  
   901  func TestFindContainerContainerIDEmptyFailure(t *testing.T) {
   902  	sandbox := &Sandbox{}
   903  	testFindContainerFailure(t, sandbox, "")
   904  }
   905  
   906  func TestFindContainerNoContainerMatchFailure(t *testing.T) {
   907  	sandbox := &Sandbox{}
   908  	testFindContainerFailure(t, sandbox, testContainerID)
   909  }
   910  
   911  func TestFindContainerSuccess(t *testing.T) {
   912  	sandbox := &Sandbox{
   913  		containers: map[string]*Container{
   914  			testContainerID: {id: testContainerID},
   915  		},
   916  	}
   917  	c, err := sandbox.findContainer(testContainerID)
   918  	assert.NotNil(t, c, "Container pointer should not be nil")
   919  	assert.Nil(t, err, "Should not have returned an error: %v", err)
   920  
   921  	assert.True(t, c == sandbox.containers[testContainerID], "Container pointers should point to the same address")
   922  }
   923  
   924  func TestRemoveContainerSandboxNilFailure(t *testing.T) {
   925  	testFindContainerFailure(t, nil, testContainerID)
   926  }
   927  
   928  func TestRemoveContainerContainerIDEmptyFailure(t *testing.T) {
   929  	sandbox := &Sandbox{}
   930  	testFindContainerFailure(t, sandbox, "")
   931  }
   932  
   933  func TestRemoveContainerNoContainerMatchFailure(t *testing.T) {
   934  	sandbox := &Sandbox{}
   935  	testFindContainerFailure(t, sandbox, testContainerID)
   936  }
   937  
   938  func TestRemoveContainerSuccess(t *testing.T) {
   939  	sandbox := &Sandbox{
   940  		containers: map[string]*Container{
   941  			testContainerID: {id: testContainerID},
   942  		},
   943  	}
   944  	err := sandbox.removeContainer(testContainerID)
   945  	assert.Nil(t, err, "Should not have returned an error: %v", err)
   946  
   947  	assert.Equal(t, len(sandbox.containers), 0, "Containers list from sandbox structure should be empty")
   948  }
   949  
   950  func TestCreateContainer(t *testing.T) {
   951  	s, err := testCreateSandbox(t, testSandboxID, MockHypervisor, newHypervisorConfig(nil, nil), NoopAgentType, NetworkConfig{}, nil, nil)
   952  	assert.Nil(t, err, "VirtContainers should not allow empty sandboxes")
   953  	defer cleanUp()
   954  
   955  	contID := "999"
   956  	contConfig := newTestContainerConfigNoop(contID)
   957  	_, err = s.CreateContainer(contConfig)
   958  	assert.Nil(t, err, "Failed to create container %+v in sandbox %+v: %v", contConfig, s, err)
   959  
   960  	assert.Equal(t, len(s.config.Containers), 1, "Container config list length from sandbox structure should be 1")
   961  
   962  	_, err = s.CreateContainer(contConfig)
   963  	assert.NotNil(t, err, "Should failed to create a duplicated container")
   964  	assert.Equal(t, len(s.config.Containers), 1, "Container config list length from sandbox structure should be 1")
   965  }
   966  
   967  func TestDeleteContainer(t *testing.T) {
   968  	s, err := testCreateSandbox(t, testSandboxID, MockHypervisor, newHypervisorConfig(nil, nil), NoopAgentType, NetworkConfig{}, nil, nil)
   969  	assert.Nil(t, err, "VirtContainers should not allow empty sandboxes")
   970  	defer cleanUp()
   971  
   972  	contID := "999"
   973  	_, err = s.DeleteContainer(contID)
   974  	assert.NotNil(t, err, "Deletng non-existing container should fail")
   975  
   976  	contConfig := newTestContainerConfigNoop(contID)
   977  	_, err = s.CreateContainer(contConfig)
   978  	assert.Nil(t, err, "Failed to create container %+v in sandbox %+v: %v", contConfig, s, err)
   979  
   980  	_, err = s.DeleteContainer(contID)
   981  	assert.Nil(t, err, "Failed to delete container %s in sandbox %s: %v", contID, s.ID(), err)
   982  }
   983  
   984  func TestStartContainer(t *testing.T) {
   985  	s, err := testCreateSandbox(t, testSandboxID, MockHypervisor, newHypervisorConfig(nil, nil), NoopAgentType, NetworkConfig{}, nil, nil)
   986  	assert.Nil(t, err, "VirtContainers should not allow empty sandboxes")
   987  	defer cleanUp()
   988  
   989  	contID := "999"
   990  	_, err = s.StartContainer(contID)
   991  	assert.NotNil(t, err, "Starting non-existing container should fail")
   992  
   993  	err = s.Start()
   994  	assert.Nil(t, err, "Failed to start sandbox: %v", err)
   995  
   996  	contConfig := newTestContainerConfigNoop(contID)
   997  	_, err = s.CreateContainer(contConfig)
   998  	assert.Nil(t, err, "Failed to create container %+v in sandbox %+v: %v", contConfig, s, err)
   999  
  1000  	_, err = s.StartContainer(contID)
  1001  	assert.Nil(t, err, "Start container failed: %v", err)
  1002  }
  1003  
  1004  func TestStatusContainer(t *testing.T) {
  1005  	s, err := testCreateSandbox(t, testSandboxID, MockHypervisor, newHypervisorConfig(nil, nil), NoopAgentType, NetworkConfig{}, nil, nil)
  1006  	assert.Nil(t, err, "VirtContainers should not allow empty sandboxes")
  1007  	defer cleanUp()
  1008  
  1009  	contID := "999"
  1010  	_, err = s.StatusContainer(contID)
  1011  	assert.NotNil(t, err, "Status non-existing container should fail")
  1012  
  1013  	contConfig := newTestContainerConfigNoop(contID)
  1014  	_, err = s.CreateContainer(contConfig)
  1015  	assert.Nil(t, err, "Failed to create container %+v in sandbox %+v: %v", contConfig, s, err)
  1016  
  1017  	_, err = s.StatusContainer(contID)
  1018  	assert.Nil(t, err, "Status container failed: %v", err)
  1019  
  1020  	_, err = s.DeleteContainer(contID)
  1021  	assert.Nil(t, err, "Failed to delete container %s in sandbox %s: %v", contID, s.ID(), err)
  1022  }
  1023  
  1024  func TestStatusSandbox(t *testing.T) {
  1025  	s, err := testCreateSandbox(t, testSandboxID, MockHypervisor, newHypervisorConfig(nil, nil), NoopAgentType, NetworkConfig{}, nil, nil)
  1026  	assert.Nil(t, err, "VirtContainers should not allow empty sandboxes")
  1027  	defer cleanUp()
  1028  
  1029  	s.Status()
  1030  }
  1031  
  1032  func TestEnterContainer(t *testing.T) {
  1033  	s, err := testCreateSandbox(t, testSandboxID, MockHypervisor, newHypervisorConfig(nil, nil), NoopAgentType, NetworkConfig{}, nil, nil)
  1034  	assert.Nil(t, err, "VirtContainers should not allow empty sandboxes")
  1035  	defer cleanUp()
  1036  
  1037  	contID := "999"
  1038  	cmd := types.Cmd{}
  1039  	_, _, err = s.EnterContainer(contID, cmd)
  1040  	assert.NotNil(t, err, "Entering non-existing container should fail")
  1041  
  1042  	contConfig := newTestContainerConfigNoop(contID)
  1043  	_, err = s.CreateContainer(contConfig)
  1044  	assert.Nil(t, err, "Failed to create container %+v in sandbox %+v: %v", contConfig, s, err)
  1045  
  1046  	_, _, err = s.EnterContainer(contID, cmd)
  1047  	assert.NotNil(t, err, "Entering non-running container should fail")
  1048  
  1049  	err = s.Start()
  1050  	assert.Nil(t, err, "Failed to start sandbox: %v", err)
  1051  
  1052  	_, _, err = s.EnterContainer(contID, cmd)
  1053  	assert.Nil(t, err, "Enter container failed: %v", err)
  1054  }
  1055  
  1056  func TestDeleteStoreWhenCreateContainerFail(t *testing.T) {
  1057  	hypervisorConfig := newHypervisorConfig(nil, nil)
  1058  	s, err := testCreateSandbox(t, testSandboxID, MockHypervisor, hypervisorConfig, NoopAgentType, NetworkConfig{}, nil, nil)
  1059  	if err != nil {
  1060  		t.Fatal(err)
  1061  	}
  1062  	defer cleanUp()
  1063  
  1064  	contID := "999"
  1065  	contConfig := newTestContainerConfigNoop(contID)
  1066  	contConfig.RootFs = RootFs{Target: "", Mounted: true}
  1067  	s.state.CgroupPath = filepath.Join(testDir, "bad-cgroup")
  1068  	_, err = s.CreateContainer(contConfig)
  1069  	assert.NotNil(t, err, "Should fail to create container due to wrong cgroup")
  1070  }
  1071  
  1072  func TestDeleteStoreWhenNewContainerFail(t *testing.T) {
  1073  	hConfig := newHypervisorConfig(nil, nil)
  1074  	p, err := testCreateSandbox(t, testSandboxID, MockHypervisor, hConfig, NoopAgentType, NetworkConfig{}, nil, nil)
  1075  	if err != nil {
  1076  		t.Fatal(err)
  1077  	}
  1078  	defer cleanUp()
  1079  
  1080  	contID := "999"
  1081  	contConfig := newTestContainerConfigNoop(contID)
  1082  	contConfig.DeviceInfos = []config.DeviceInfo{
  1083  		{
  1084  			ContainerPath: "",
  1085  			DevType:       "",
  1086  		},
  1087  	}
  1088  	_, err = newContainer(p, &contConfig)
  1089  	assert.NotNil(t, err, "New container with invalid device info should fail")
  1090  	storePath := filepath.Join(p.newStore.RunStoragePath(), testSandboxID, contID)
  1091  	_, err = os.Stat(storePath)
  1092  	assert.NotNil(t, err, "Should delete configuration root after failed to create a container")
  1093  }
  1094  
  1095  func TestMonitor(t *testing.T) {
  1096  	s, err := testCreateSandbox(t, testSandboxID, MockHypervisor, newHypervisorConfig(nil, nil), NoopAgentType, NetworkConfig{}, nil, nil)
  1097  	assert.Nil(t, err, "VirtContainers should not allow empty sandboxes")
  1098  	defer cleanUp()
  1099  
  1100  	_, err = s.Monitor()
  1101  	assert.NotNil(t, err, "Monitoring non-running container should fail")
  1102  
  1103  	err = s.Start()
  1104  	assert.Nil(t, err, "Failed to start sandbox: %v", err)
  1105  
  1106  	_, err = s.Monitor()
  1107  	assert.Nil(t, err, "Monitor sandbox failed: %v", err)
  1108  
  1109  	_, err = s.Monitor()
  1110  	assert.Nil(t, err, "Monitor sandbox again failed: %v", err)
  1111  
  1112  	s.monitor.stop()
  1113  }
  1114  
  1115  func TestWaitProcess(t *testing.T) {
  1116  	s, err := testCreateSandbox(t, testSandboxID, MockHypervisor, newHypervisorConfig(nil, nil), NoopAgentType, NetworkConfig{}, nil, nil)
  1117  	assert.Nil(t, err, "VirtContainers should not allow empty sandboxes")
  1118  	defer cleanUp()
  1119  
  1120  	contID := "foo"
  1121  	execID := "bar"
  1122  	_, err = s.WaitProcess(contID, execID)
  1123  	assert.NotNil(t, err, "Wait process in stopped sandbox should fail")
  1124  
  1125  	err = s.Start()
  1126  	assert.Nil(t, err, "Failed to start sandbox: %v", err)
  1127  
  1128  	_, err = s.WaitProcess(contID, execID)
  1129  	assert.NotNil(t, err, "Wait process in non-existing container should fail")
  1130  
  1131  	contConfig := newTestContainerConfigNoop(contID)
  1132  	_, err = s.CreateContainer(contConfig)
  1133  	assert.Nil(t, err, "Failed to create container %+v in sandbox %+v: %v", contConfig, s, err)
  1134  
  1135  	_, err = s.WaitProcess(contID, execID)
  1136  	assert.Nil(t, err, "Wait process in ready container failed: %v", err)
  1137  
  1138  	_, err = s.StartContainer(contID)
  1139  	assert.Nil(t, err, "Start container failed: %v", err)
  1140  
  1141  	_, err = s.WaitProcess(contID, execID)
  1142  	assert.Nil(t, err, "Wait process failed: %v", err)
  1143  }
  1144  
  1145  func TestSignalProcess(t *testing.T) {
  1146  	s, err := testCreateSandbox(t, testSandboxID, MockHypervisor, newHypervisorConfig(nil, nil), NoopAgentType, NetworkConfig{}, nil, nil)
  1147  	assert.Nil(t, err, "VirtContainers should not allow empty sandboxes")
  1148  	defer cleanUp()
  1149  
  1150  	contID := "foo"
  1151  	execID := "bar"
  1152  	err = s.SignalProcess(contID, execID, syscall.SIGKILL, true)
  1153  	assert.NotNil(t, err, "Wait process in stopped sandbox should fail")
  1154  
  1155  	err = s.Start()
  1156  	assert.Nil(t, err, "Failed to start sandbox: %v", err)
  1157  
  1158  	err = s.SignalProcess(contID, execID, syscall.SIGKILL, false)
  1159  	assert.NotNil(t, err, "Wait process in non-existing container should fail")
  1160  
  1161  	contConfig := newTestContainerConfigNoop(contID)
  1162  	_, err = s.CreateContainer(contConfig)
  1163  	assert.Nil(t, err, "Failed to create container %+v in sandbox %+v: %v", contConfig, s, err)
  1164  
  1165  	err = s.SignalProcess(contID, execID, syscall.SIGKILL, true)
  1166  	assert.Nil(t, err, "Wait process in ready container failed: %v", err)
  1167  
  1168  	_, err = s.StartContainer(contID)
  1169  	assert.Nil(t, err, "Start container failed: %v", err)
  1170  
  1171  	err = s.SignalProcess(contID, execID, syscall.SIGKILL, false)
  1172  	assert.Nil(t, err, "Wait process failed: %v", err)
  1173  }
  1174  
  1175  func TestWinsizeProcess(t *testing.T) {
  1176  	s, err := testCreateSandbox(t, testSandboxID, MockHypervisor, newHypervisorConfig(nil, nil), NoopAgentType, NetworkConfig{}, nil, nil)
  1177  	assert.Nil(t, err, "VirtContainers should not allow empty sandboxes")
  1178  	defer cleanUp()
  1179  
  1180  	contID := "foo"
  1181  	execID := "bar"
  1182  	err = s.WinsizeProcess(contID, execID, 100, 200)
  1183  	assert.NotNil(t, err, "Winsize process in stopped sandbox should fail")
  1184  
  1185  	err = s.Start()
  1186  	assert.Nil(t, err, "Failed to start sandbox: %v", err)
  1187  
  1188  	err = s.WinsizeProcess(contID, execID, 100, 200)
  1189  	assert.NotNil(t, err, "Winsize process in non-existing container should fail")
  1190  
  1191  	contConfig := newTestContainerConfigNoop(contID)
  1192  	_, err = s.CreateContainer(contConfig)
  1193  	assert.Nil(t, err, "Failed to create container %+v in sandbox %+v: %v", contConfig, s, err)
  1194  
  1195  	err = s.WinsizeProcess(contID, execID, 100, 200)
  1196  	assert.Nil(t, err, "Winsize process in ready container failed: %v", err)
  1197  
  1198  	_, err = s.StartContainer(contID)
  1199  	assert.Nil(t, err, "Start container failed: %v", err)
  1200  
  1201  	err = s.WinsizeProcess(contID, execID, 100, 200)
  1202  	assert.Nil(t, err, "Winsize process failed: %v", err)
  1203  }
  1204  
  1205  func TestContainerProcessIOStream(t *testing.T) {
  1206  	s, err := testCreateSandbox(t, testSandboxID, MockHypervisor, newHypervisorConfig(nil, nil), NoopAgentType, NetworkConfig{}, nil, nil)
  1207  	assert.Nil(t, err, "VirtContainers should not allow empty sandboxes")
  1208  	defer cleanUp()
  1209  
  1210  	contID := "foo"
  1211  	execID := "bar"
  1212  	_, _, _, err = s.IOStream(contID, execID)
  1213  	assert.NotNil(t, err, "Winsize process in stopped sandbox should fail")
  1214  
  1215  	err = s.Start()
  1216  	assert.Nil(t, err, "Failed to start sandbox: %v", err)
  1217  
  1218  	_, _, _, err = s.IOStream(contID, execID)
  1219  	assert.NotNil(t, err, "Winsize process in non-existing container should fail")
  1220  
  1221  	contConfig := newTestContainerConfigNoop(contID)
  1222  	_, err = s.CreateContainer(contConfig)
  1223  	assert.Nil(t, err, "Failed to create container %+v in sandbox %+v: %v", contConfig, s, err)
  1224  
  1225  	_, _, _, err = s.IOStream(contID, execID)
  1226  	assert.Nil(t, err, "Winsize process in ready container failed: %v", err)
  1227  
  1228  	_, err = s.StartContainer(contID)
  1229  	assert.Nil(t, err, "Start container failed: %v", err)
  1230  
  1231  	_, _, _, err = s.IOStream(contID, execID)
  1232  	assert.Nil(t, err, "Winsize process failed: %v", err)
  1233  }
  1234  
  1235  func TestAttachBlockDevice(t *testing.T) {
  1236  	hypervisor := &mockHypervisor{}
  1237  
  1238  	hConfig := HypervisorConfig{
  1239  		BlockDeviceDriver: config.VirtioBlock,
  1240  	}
  1241  
  1242  	sconfig := &SandboxConfig{
  1243  		HypervisorConfig: hConfig,
  1244  	}
  1245  
  1246  	sandbox := &Sandbox{
  1247  		id:         testSandboxID,
  1248  		hypervisor: hypervisor,
  1249  		config:     sconfig,
  1250  		ctx:        context.Background(),
  1251  		state:      types.SandboxState{BlockIndexMap: make(map[int]struct{})},
  1252  	}
  1253  
  1254  	contID := "100"
  1255  	container := Container{
  1256  		sandbox: sandbox,
  1257  		id:      contID,
  1258  	}
  1259  
  1260  	// create state file
  1261  	path := filepath.Join(fs.MockRunStoragePath(), testSandboxID, container.ID())
  1262  	err := os.MkdirAll(path, DirMode)
  1263  	assert.NoError(t, err)
  1264  
  1265  	defer os.RemoveAll(path)
  1266  
  1267  	path = "/dev/hda"
  1268  	deviceInfo := config.DeviceInfo{
  1269  		HostPath:      path,
  1270  		ContainerPath: path,
  1271  		DevType:       "b",
  1272  	}
  1273  
  1274  	dm := manager.NewDeviceManager(config.VirtioBlock, false, "", nil)
  1275  	device, err := dm.NewDevice(deviceInfo)
  1276  	assert.Nil(t, err)
  1277  	_, ok := device.(*drivers.BlockDevice)
  1278  	assert.True(t, ok)
  1279  
  1280  	container.state.State = ""
  1281  	index, err := sandbox.getAndSetSandboxBlockIndex()
  1282  	assert.Nil(t, err)
  1283  	assert.Equal(t, index, 0)
  1284  
  1285  	err = device.Attach(sandbox)
  1286  	assert.Nil(t, err)
  1287  	index, err = sandbox.getAndSetSandboxBlockIndex()
  1288  	assert.Nil(t, err)
  1289  	assert.Equal(t, index, 2)
  1290  
  1291  	err = device.Detach(sandbox)
  1292  	assert.Nil(t, err)
  1293  	index, err = sandbox.getAndSetSandboxBlockIndex()
  1294  	assert.Nil(t, err)
  1295  	assert.Equal(t, index, 1)
  1296  
  1297  	container.state.State = types.StateReady
  1298  	err = device.Attach(sandbox)
  1299  	assert.Nil(t, err)
  1300  
  1301  	err = device.Detach(sandbox)
  1302  	assert.Nil(t, err)
  1303  
  1304  	container.sandbox.config.HypervisorConfig.BlockDeviceDriver = config.VirtioSCSI
  1305  	err = device.Attach(sandbox)
  1306  	assert.Nil(t, err)
  1307  
  1308  	err = device.Detach(sandbox)
  1309  	assert.Nil(t, err)
  1310  
  1311  	container.state.State = types.StateReady
  1312  	err = device.Attach(sandbox)
  1313  	assert.Nil(t, err)
  1314  
  1315  	err = device.Detach(sandbox)
  1316  	assert.Nil(t, err)
  1317  }
  1318  
  1319  func TestPreAddDevice(t *testing.T) {
  1320  	hypervisor := &mockHypervisor{}
  1321  
  1322  	hConfig := HypervisorConfig{
  1323  		BlockDeviceDriver: config.VirtioBlock,
  1324  	}
  1325  
  1326  	sconfig := &SandboxConfig{
  1327  		HypervisorConfig: hConfig,
  1328  	}
  1329  
  1330  	dm := manager.NewDeviceManager(config.VirtioBlock, false, "", nil)
  1331  	// create a sandbox first
  1332  	sandbox := &Sandbox{
  1333  		id:         testSandboxID,
  1334  		hypervisor: hypervisor,
  1335  		config:     sconfig,
  1336  		devManager: dm,
  1337  		ctx:        context.Background(),
  1338  		state:      types.SandboxState{BlockIndexMap: make(map[int]struct{})},
  1339  	}
  1340  
  1341  	contID := "100"
  1342  	container := Container{
  1343  		sandbox:   sandbox,
  1344  		id:        contID,
  1345  		sandboxID: testSandboxID,
  1346  	}
  1347  	container.state.State = types.StateReady
  1348  
  1349  	// create state file
  1350  	path := filepath.Join(fs.MockRunStoragePath(), testSandboxID, container.ID())
  1351  	err := os.MkdirAll(path, DirMode)
  1352  	assert.NoError(t, err)
  1353  
  1354  	defer os.RemoveAll(path)
  1355  
  1356  	path = "/dev/hda"
  1357  	deviceInfo := config.DeviceInfo{
  1358  		HostPath:      path,
  1359  		ContainerPath: path,
  1360  		DevType:       "b",
  1361  	}
  1362  
  1363  	// Add a mount device for a mountpoint before container's creation
  1364  	dev, err := sandbox.AddDevice(deviceInfo)
  1365  	assert.Nil(t, err)
  1366  
  1367  	// in Frakti use case, here we will create and start the container
  1368  	// which will attach same device twice
  1369  	container.mounts = []Mount{
  1370  		{
  1371  			Destination:   path,
  1372  			Source:        path,
  1373  			Type:          "bind",
  1374  			BlockDeviceID: dev.DeviceID(),
  1375  		},
  1376  	}
  1377  
  1378  	mounts, ignoreMounts, err := container.mountSharedDirMounts("", "")
  1379  	assert.Nil(t, err)
  1380  	assert.Equal(t, len(mounts), 0,
  1381  		"mounts should contain nothing because it only contains a block device")
  1382  	assert.Equal(t, len(ignoreMounts), 0,
  1383  		"ignoreMounts should contain nothing because it only contains a block device")
  1384  }
  1385  
  1386  func TestGetNetNs(t *testing.T) {
  1387  	s := Sandbox{}
  1388  
  1389  	expected := ""
  1390  	netNs := s.GetNetNs()
  1391  	assert.Equal(t, netNs, expected)
  1392  
  1393  	expected = "/foo/bar/ns/net"
  1394  	s.networkNS = NetworkNamespace{
  1395  		NetNsPath: expected,
  1396  	}
  1397  
  1398  	netNs = s.GetNetNs()
  1399  	assert.Equal(t, netNs, expected)
  1400  }
  1401  
  1402  func TestStartNetworkMonitor(t *testing.T) {
  1403  	if os.Getuid() != 0 {
  1404  		t.Skip("Test disabled as requires root user")
  1405  	}
  1406  	trueBinPath, err := exec.LookPath("true")
  1407  	assert.Nil(t, err)
  1408  	assert.NotEmpty(t, trueBinPath)
  1409  
  1410  	s := &Sandbox{
  1411  		id: testSandboxID,
  1412  		config: &SandboxConfig{
  1413  			NetworkConfig: NetworkConfig{
  1414  				NetmonConfig: NetmonConfig{
  1415  					Path: trueBinPath,
  1416  				},
  1417  			},
  1418  		},
  1419  		networkNS: NetworkNamespace{
  1420  			NetNsPath: fmt.Sprintf("/proc/%d/task/%d/ns/net", os.Getpid(), unix.Gettid()),
  1421  		},
  1422  		ctx: context.Background(),
  1423  	}
  1424  
  1425  	err = s.startNetworkMonitor()
  1426  	assert.Nil(t, err)
  1427  }
  1428  
  1429  func TestSandboxStopStopped(t *testing.T) {
  1430  	s := &Sandbox{
  1431  		ctx:   context.Background(),
  1432  		state: types.SandboxState{State: types.StateStopped},
  1433  	}
  1434  	err := s.Stop(false)
  1435  
  1436  	assert.Nil(t, err)
  1437  }
  1438  
  1439  func checkDirNotExist(path string) error {
  1440  	if _, err := os.Stat(path); os.IsExist(err) {
  1441  		return fmt.Errorf("%s is still exists", path)
  1442  	}
  1443  	return nil
  1444  }
  1445  
  1446  func checkSandboxRemains() error {
  1447  	var err error
  1448  	if err = checkDirNotExist(sandboxDirState); err != nil {
  1449  		return fmt.Errorf("%s still exists", sandboxDirState)
  1450  	}
  1451  	if err = checkDirNotExist(path.Join(kataHostSharedDir(), testSandboxID)); err != nil {
  1452  		return fmt.Errorf("%s still exists", path.Join(kataHostSharedDir(), testSandboxID))
  1453  	}
  1454  	if _, err = globalSandboxList.lookupSandbox(testSandboxID); err == nil {
  1455  		return fmt.Errorf("globalSandboxList for %s stil exists", testSandboxID)
  1456  	}
  1457  
  1458  	return nil
  1459  }
  1460  
  1461  func TestSandboxCreationFromConfigRollbackFromCreateSandbox(t *testing.T) {
  1462  	defer cleanUp()
  1463  	assert := assert.New(t)
  1464  	ctx := context.Background()
  1465  	hConf := newHypervisorConfig(nil, nil)
  1466  	sConf := SandboxConfig{
  1467  		ID:               testSandboxID,
  1468  		HypervisorType:   QemuHypervisor,
  1469  		HypervisorConfig: hConf,
  1470  		AgentType:        KataContainersAgent,
  1471  		NetworkConfig:    NetworkConfig{},
  1472  		Volumes:          nil,
  1473  		Containers:       nil,
  1474  	}
  1475  
  1476  	// Ensure hypervisor doesn't exist
  1477  	assert.NoError(os.Remove(hConf.HypervisorPath))
  1478  
  1479  	_, err := createSandboxFromConfig(ctx, sConf, nil)
  1480  	// Fail at createSandbox: QEMU path does not exist, it is expected. Then rollback is called
  1481  	assert.Error(err)
  1482  
  1483  	// check dirs
  1484  	err = checkSandboxRemains()
  1485  	assert.NoError(err)
  1486  }
  1487  
  1488  func TestSandboxUpdateResources(t *testing.T) {
  1489  	contConfig1 := newTestContainerConfigNoop("cont-00001")
  1490  	contConfig2 := newTestContainerConfigNoop("cont-00002")
  1491  	hConfig := newHypervisorConfig(nil, nil)
  1492  
  1493  	defer cleanUp()
  1494  	// create a sandbox
  1495  	s, err := testCreateSandbox(t,
  1496  		testSandboxID,
  1497  		MockHypervisor,
  1498  		hConfig,
  1499  		NoopAgentType,
  1500  		NetworkConfig{},
  1501  		[]ContainerConfig{contConfig1, contConfig2},
  1502  		nil)
  1503  
  1504  	assert.NoError(t, err)
  1505  	err = s.updateResources()
  1506  	assert.NoError(t, err)
  1507  
  1508  	containerMemLimit := int64(1000)
  1509  	containerCPUPeriod := uint64(1000)
  1510  	containerCPUQouta := int64(5)
  1511  	for _, c := range s.config.Containers {
  1512  		c.Resources.Memory = &specs.LinuxMemory{
  1513  			Limit: new(int64),
  1514  		}
  1515  		c.Resources.CPU = &specs.LinuxCPU{
  1516  			Period: new(uint64),
  1517  			Quota:  new(int64),
  1518  		}
  1519  		c.Resources.Memory.Limit = &containerMemLimit
  1520  		c.Resources.CPU.Period = &containerCPUPeriod
  1521  		c.Resources.CPU.Quota = &containerCPUQouta
  1522  	}
  1523  	err = s.updateResources()
  1524  	assert.NoError(t, err)
  1525  }
  1526  
  1527  func TestSandboxExperimentalFeature(t *testing.T) {
  1528  	testFeature := exp.Feature{
  1529  		Name:        "mock",
  1530  		Description: "exp feature for test",
  1531  		ExpRelease:  "1.8.0",
  1532  	}
  1533  	sconfig := SandboxConfig{
  1534  		ID:           testSandboxID,
  1535  		Experimental: []exp.Feature{testFeature},
  1536  	}
  1537  
  1538  	assert.Nil(t, exp.Get(testFeature.Name))
  1539  	assert.False(t, sconfig.valid())
  1540  
  1541  	exp.Register(testFeature)
  1542  	assert.NotNil(t, exp.Get(testFeature.Name))
  1543  	assert.True(t, sconfig.valid())
  1544  }
  1545  
  1546  func TestSandbox_SetupSandboxCgroup(t *testing.T) {
  1547  	sandboxContainer := ContainerConfig{}
  1548  	sandboxContainer.Annotations = make(map[string]string)
  1549  	sandboxContainer.Annotations[annotations.ContainerTypeKey] = string(PodSandbox)
  1550  
  1551  	emptyJSONLinux := ContainerConfig{
  1552  		CustomSpec: newEmptySpec(),
  1553  	}
  1554  	emptyJSONLinux.Annotations = make(map[string]string)
  1555  	emptyJSONLinux.Annotations[annotations.ContainerTypeKey] = string(PodSandbox)
  1556  
  1557  	cloneSpec1 := newEmptySpec()
  1558  	cloneSpec1.Linux.CgroupsPath = "/myRuntime/myContainer"
  1559  	successfulContainer := ContainerConfig{
  1560  		CustomSpec: cloneSpec1,
  1561  	}
  1562  	successfulContainer.Annotations = make(map[string]string)
  1563  	successfulContainer.Annotations[annotations.ContainerTypeKey] = string(PodSandbox)
  1564  
  1565  	tests := []struct {
  1566  		name     string
  1567  		s        *Sandbox
  1568  		wantErr  bool
  1569  		needRoot bool
  1570  	}{
  1571  		{
  1572  			"New sandbox",
  1573  			&Sandbox{},
  1574  			true,
  1575  			false,
  1576  		},
  1577  		{
  1578  			"New sandbox, new config",
  1579  			&Sandbox{config: &SandboxConfig{}},
  1580  			true,
  1581  			false,
  1582  		},
  1583  		{
  1584  			"sandbox, container no sandbox type",
  1585  			&Sandbox{
  1586  				config: &SandboxConfig{Containers: []ContainerConfig{
  1587  					{},
  1588  				}}},
  1589  			true,
  1590  			false,
  1591  		},
  1592  		{
  1593  			"sandbox, container sandbox type",
  1594  			&Sandbox{
  1595  				config: &SandboxConfig{Containers: []ContainerConfig{
  1596  					sandboxContainer,
  1597  				}}},
  1598  			true,
  1599  			false,
  1600  		},
  1601  		{
  1602  			"sandbox, empty linux json",
  1603  			&Sandbox{
  1604  				config: &SandboxConfig{Containers: []ContainerConfig{
  1605  					emptyJSONLinux,
  1606  				}}},
  1607  			false,
  1608  			true,
  1609  		},
  1610  		{
  1611  			"sandbox, successful config",
  1612  			&Sandbox{
  1613  				config: &SandboxConfig{Containers: []ContainerConfig{
  1614  					successfulContainer,
  1615  				}}},
  1616  			false,
  1617  			true,
  1618  		},
  1619  	}
  1620  	for _, tt := range tests {
  1621  		if tt.needRoot && os.Getuid() != 0 {
  1622  			t.Skip(tt.name + "needs root")
  1623  		}
  1624  
  1625  		t.Run(tt.name, func(t *testing.T) {
  1626  			tt.s.createCgroupManager()
  1627  			if err := tt.s.setupSandboxCgroup(); (err != nil) != tt.wantErr {
  1628  				t.Errorf("Sandbox.SetupSandboxCgroupOnly() error = %v, wantErr %v", err, tt.wantErr)
  1629  			}
  1630  		})
  1631  	}
  1632  }