github.com/kata-containers/runtime@v0.0.0-20210505125100-04f29832a923/virtcontainers/kata_agent_test.go (about)

     1  // Copyright (c) 2018 Intel Corporation
     2  //
     3  // SPDX-License-Identifier: Apache-2.0
     4  //
     5  
     6  package virtcontainers
     7  
     8  import (
     9  	"bufio"
    10  	"context"
    11  	"fmt"
    12  	"io/ioutil"
    13  	"net"
    14  	"os"
    15  	"path"
    16  	"path/filepath"
    17  	"reflect"
    18  	"strings"
    19  	"syscall"
    20  	"testing"
    21  
    22  	vcAnnotations "github.com/kata-containers/runtime/virtcontainers/pkg/annotations"
    23  
    24  	gpb "github.com/gogo/protobuf/types"
    25  	specs "github.com/opencontainers/runtime-spec/specs-go"
    26  	"github.com/stretchr/testify/assert"
    27  	"google.golang.org/grpc"
    28  
    29  	aTypes "github.com/kata-containers/agent/pkg/types"
    30  	pb "github.com/kata-containers/agent/protocols/grpc"
    31  	"github.com/kata-containers/runtime/virtcontainers/device/api"
    32  	"github.com/kata-containers/runtime/virtcontainers/device/config"
    33  	"github.com/kata-containers/runtime/virtcontainers/device/drivers"
    34  	"github.com/kata-containers/runtime/virtcontainers/device/manager"
    35  	"github.com/kata-containers/runtime/virtcontainers/persist"
    36  	"github.com/kata-containers/runtime/virtcontainers/pkg/mock"
    37  	"github.com/kata-containers/runtime/virtcontainers/pkg/rootless"
    38  	vcTypes "github.com/kata-containers/runtime/virtcontainers/pkg/types"
    39  	"github.com/kata-containers/runtime/virtcontainers/types"
    40  )
    41  
    42  var (
    43  	testKataProxyURLTempl  = "unix://%s/kata-proxy-test.sock"
    44  	testBlkDriveFormat     = "testBlkDriveFormat"
    45  	testBlockDeviceCtrPath = "testBlockDeviceCtrPath"
    46  	testDevNo              = "testDevNo"
    47  	testNvdimmID           = "testNvdimmID"
    48  	testPCIPath, _         = vcTypes.PciPathFromString("04/02")
    49  	testSCSIAddr           = "testSCSIAddr"
    50  	testVirtPath           = "testVirtPath"
    51  )
    52  
    53  func proxyHandlerDiscard(c net.Conn) {
    54  	buf := make([]byte, 1024)
    55  	c.Read(buf)
    56  }
    57  
    58  func testGenerateKataProxySockDir() (string, error) {
    59  	dir, err := ioutil.TempDir("", "kata-proxy-test")
    60  	if err != nil {
    61  		return "", err
    62  	}
    63  
    64  	return dir, nil
    65  }
    66  
    67  func TestKataAgentConnect(t *testing.T) {
    68  	assert := assert.New(t)
    69  	proxy := mock.ProxyUnixMock{
    70  		ClientHandler: proxyHandlerDiscard,
    71  	}
    72  
    73  	sockDir, err := testGenerateKataProxySockDir()
    74  	assert.NoError(err)
    75  	defer os.RemoveAll(sockDir)
    76  
    77  	testKataProxyURL := fmt.Sprintf(testKataProxyURLTempl, sockDir)
    78  	err = proxy.Start(testKataProxyURL)
    79  	assert.NoError(err)
    80  	defer proxy.Stop()
    81  
    82  	k := &kataAgent{
    83  		ctx: context.Background(),
    84  		state: KataAgentState{
    85  			URL: testKataProxyURL,
    86  		},
    87  	}
    88  
    89  	err = k.connect()
    90  	assert.NoError(err)
    91  	assert.NotNil(k.client)
    92  }
    93  
    94  func TestKataAgentDisconnect(t *testing.T) {
    95  	assert := assert.New(t)
    96  	proxy := mock.ProxyUnixMock{
    97  		ClientHandler: proxyHandlerDiscard,
    98  	}
    99  
   100  	sockDir, err := testGenerateKataProxySockDir()
   101  	assert.NoError(err)
   102  	defer os.RemoveAll(sockDir)
   103  
   104  	testKataProxyURL := fmt.Sprintf(testKataProxyURLTempl, sockDir)
   105  	err = proxy.Start(testKataProxyURL)
   106  	assert.NoError(err)
   107  	defer proxy.Stop()
   108  
   109  	k := &kataAgent{
   110  		ctx: context.Background(),
   111  		state: KataAgentState{
   112  			URL: testKataProxyURL,
   113  		},
   114  	}
   115  
   116  	assert.NoError(k.connect())
   117  	assert.NoError(k.disconnect())
   118  	assert.Nil(k.client)
   119  }
   120  
   121  type gRPCProxy struct{}
   122  
   123  var emptyResp = &gpb.Empty{}
   124  
   125  func (p *gRPCProxy) CreateContainer(ctx context.Context, req *pb.CreateContainerRequest) (*gpb.Empty, error) {
   126  	return emptyResp, nil
   127  }
   128  
   129  func (p *gRPCProxy) StartContainer(ctx context.Context, req *pb.StartContainerRequest) (*gpb.Empty, error) {
   130  	return emptyResp, nil
   131  }
   132  
   133  func (p *gRPCProxy) ExecProcess(ctx context.Context, req *pb.ExecProcessRequest) (*gpb.Empty, error) {
   134  	return emptyResp, nil
   135  }
   136  
   137  func (p *gRPCProxy) SignalProcess(ctx context.Context, req *pb.SignalProcessRequest) (*gpb.Empty, error) {
   138  	return emptyResp, nil
   139  }
   140  
   141  func (p *gRPCProxy) WaitProcess(ctx context.Context, req *pb.WaitProcessRequest) (*pb.WaitProcessResponse, error) {
   142  	return &pb.WaitProcessResponse{}, nil
   143  }
   144  
   145  func (p *gRPCProxy) ListProcesses(ctx context.Context, req *pb.ListProcessesRequest) (*pb.ListProcessesResponse, error) {
   146  	return &pb.ListProcessesResponse{}, nil
   147  }
   148  
   149  func (p *gRPCProxy) UpdateContainer(ctx context.Context, req *pb.UpdateContainerRequest) (*gpb.Empty, error) {
   150  	return emptyResp, nil
   151  }
   152  
   153  func (p *gRPCProxy) RemoveContainer(ctx context.Context, req *pb.RemoveContainerRequest) (*gpb.Empty, error) {
   154  	return emptyResp, nil
   155  }
   156  
   157  func (p *gRPCProxy) WriteStdin(ctx context.Context, req *pb.WriteStreamRequest) (*pb.WriteStreamResponse, error) {
   158  	return &pb.WriteStreamResponse{}, nil
   159  }
   160  
   161  func (p *gRPCProxy) ReadStdout(ctx context.Context, req *pb.ReadStreamRequest) (*pb.ReadStreamResponse, error) {
   162  	return &pb.ReadStreamResponse{}, nil
   163  }
   164  
   165  func (p *gRPCProxy) ReadStderr(ctx context.Context, req *pb.ReadStreamRequest) (*pb.ReadStreamResponse, error) {
   166  	return &pb.ReadStreamResponse{}, nil
   167  }
   168  
   169  func (p *gRPCProxy) CloseStdin(ctx context.Context, req *pb.CloseStdinRequest) (*gpb.Empty, error) {
   170  	return emptyResp, nil
   171  }
   172  
   173  func (p *gRPCProxy) TtyWinResize(ctx context.Context, req *pb.TtyWinResizeRequest) (*gpb.Empty, error) {
   174  	return emptyResp, nil
   175  }
   176  
   177  func (p *gRPCProxy) CreateSandbox(ctx context.Context, req *pb.CreateSandboxRequest) (*gpb.Empty, error) {
   178  	return emptyResp, nil
   179  }
   180  
   181  func (p *gRPCProxy) DestroySandbox(ctx context.Context, req *pb.DestroySandboxRequest) (*gpb.Empty, error) {
   182  	return emptyResp, nil
   183  }
   184  
   185  func (p *gRPCProxy) UpdateInterface(ctx context.Context, req *pb.UpdateInterfaceRequest) (*aTypes.Interface, error) {
   186  	return &aTypes.Interface{}, nil
   187  }
   188  
   189  func (p *gRPCProxy) UpdateRoutes(ctx context.Context, req *pb.UpdateRoutesRequest) (*pb.Routes, error) {
   190  	return &pb.Routes{}, nil
   191  }
   192  
   193  func (p *gRPCProxy) ListInterfaces(ctx context.Context, req *pb.ListInterfacesRequest) (*pb.Interfaces, error) {
   194  	return &pb.Interfaces{}, nil
   195  }
   196  
   197  func (p *gRPCProxy) ListRoutes(ctx context.Context, req *pb.ListRoutesRequest) (*pb.Routes, error) {
   198  	return &pb.Routes{}, nil
   199  }
   200  
   201  func (p *gRPCProxy) AddARPNeighbors(ctx context.Context, req *pb.AddARPNeighborsRequest) (*gpb.Empty, error) {
   202  	return emptyResp, nil
   203  }
   204  
   205  func (p *gRPCProxy) OnlineCPUMem(ctx context.Context, req *pb.OnlineCPUMemRequest) (*gpb.Empty, error) {
   206  	return emptyResp, nil
   207  }
   208  
   209  func (p *gRPCProxy) StatsContainer(ctx context.Context, req *pb.StatsContainerRequest) (*pb.StatsContainerResponse, error) {
   210  	return &pb.StatsContainerResponse{}, nil
   211  }
   212  
   213  func (p *gRPCProxy) Check(ctx context.Context, req *pb.CheckRequest) (*pb.HealthCheckResponse, error) {
   214  	return &pb.HealthCheckResponse{}, nil
   215  }
   216  
   217  func (p *gRPCProxy) Version(ctx context.Context, req *pb.CheckRequest) (*pb.VersionCheckResponse, error) {
   218  	return &pb.VersionCheckResponse{}, nil
   219  
   220  }
   221  
   222  func (p *gRPCProxy) PauseContainer(ctx context.Context, req *pb.PauseContainerRequest) (*gpb.Empty, error) {
   223  	return emptyResp, nil
   224  }
   225  
   226  func (p *gRPCProxy) ResumeContainer(ctx context.Context, req *pb.ResumeContainerRequest) (*gpb.Empty, error) {
   227  	return emptyResp, nil
   228  }
   229  
   230  func (p *gRPCProxy) ReseedRandomDev(ctx context.Context, req *pb.ReseedRandomDevRequest) (*gpb.Empty, error) {
   231  	return emptyResp, nil
   232  }
   233  
   234  func (p *gRPCProxy) GetGuestDetails(ctx context.Context, req *pb.GuestDetailsRequest) (*pb.GuestDetailsResponse, error) {
   235  	return &pb.GuestDetailsResponse{}, nil
   236  }
   237  
   238  func (p *gRPCProxy) SetGuestDateTime(ctx context.Context, req *pb.SetGuestDateTimeRequest) (*gpb.Empty, error) {
   239  	return &gpb.Empty{}, nil
   240  }
   241  
   242  func (p *gRPCProxy) CopyFile(ctx context.Context, req *pb.CopyFileRequest) (*gpb.Empty, error) {
   243  	return &gpb.Empty{}, nil
   244  }
   245  
   246  func (p *gRPCProxy) StartTracing(ctx context.Context, req *pb.StartTracingRequest) (*gpb.Empty, error) {
   247  	return &gpb.Empty{}, nil
   248  }
   249  
   250  func (p *gRPCProxy) StopTracing(ctx context.Context, req *pb.StopTracingRequest) (*gpb.Empty, error) {
   251  	return &gpb.Empty{}, nil
   252  }
   253  
   254  func (p *gRPCProxy) MemHotplugByProbe(ctx context.Context, req *pb.MemHotplugByProbeRequest) (*gpb.Empty, error) {
   255  	return &gpb.Empty{}, nil
   256  }
   257  
   258  func (p *gRPCProxy) GetOOMEvent(ctx context.Context, req *pb.GetOOMEventRequest) (*pb.OOMEvent, error) {
   259  	return &pb.OOMEvent{}, nil
   260  }
   261  
   262  func gRPCRegister(s *grpc.Server, srv interface{}) {
   263  	switch g := srv.(type) {
   264  	case *gRPCProxy:
   265  		pb.RegisterAgentServiceServer(s, g)
   266  		pb.RegisterHealthServer(s, g)
   267  	}
   268  }
   269  
   270  var reqList = []interface{}{
   271  	&pb.CreateSandboxRequest{},
   272  	&pb.DestroySandboxRequest{},
   273  	&pb.ExecProcessRequest{},
   274  	&pb.CreateContainerRequest{},
   275  	&pb.StartContainerRequest{},
   276  	&pb.RemoveContainerRequest{},
   277  	&pb.SignalProcessRequest{},
   278  	&pb.CheckRequest{},
   279  	&pb.WaitProcessRequest{},
   280  	&pb.StatsContainerRequest{},
   281  	&pb.SetGuestDateTimeRequest{},
   282  }
   283  
   284  func TestKataAgentSendReq(t *testing.T) {
   285  	assert := assert.New(t)
   286  
   287  	impl := &gRPCProxy{}
   288  
   289  	proxy := mock.ProxyGRPCMock{
   290  		GRPCImplementer: impl,
   291  		GRPCRegister:    gRPCRegister,
   292  	}
   293  
   294  	sockDir, err := testGenerateKataProxySockDir()
   295  	assert.Nil(err)
   296  	defer os.RemoveAll(sockDir)
   297  
   298  	testKataProxyURL := fmt.Sprintf(testKataProxyURLTempl, sockDir)
   299  	err = proxy.Start(testKataProxyURL)
   300  	assert.Nil(err)
   301  	defer proxy.Stop()
   302  
   303  	k := &kataAgent{
   304  		ctx: context.Background(),
   305  		state: KataAgentState{
   306  			URL: testKataProxyURL,
   307  		},
   308  	}
   309  
   310  	for _, req := range reqList {
   311  		_, err = k.sendReq(req)
   312  		assert.Nil(err)
   313  	}
   314  
   315  	sandbox := &Sandbox{}
   316  	container := &Container{}
   317  	execid := "processFooBar"
   318  
   319  	err = k.startContainer(sandbox, container)
   320  	assert.Nil(err)
   321  
   322  	err = k.signalProcess(container, execid, syscall.SIGKILL, true)
   323  	assert.Nil(err)
   324  
   325  	err = k.winsizeProcess(container, execid, 100, 200)
   326  	assert.Nil(err)
   327  
   328  	_, err = k.processListContainer(sandbox, Container{}, ProcessListOptions{})
   329  	assert.Nil(err)
   330  
   331  	err = k.updateContainer(sandbox, Container{}, specs.LinuxResources{})
   332  	assert.Nil(err)
   333  
   334  	err = k.pauseContainer(sandbox, Container{})
   335  	assert.Nil(err)
   336  
   337  	err = k.resumeContainer(sandbox, Container{})
   338  	assert.Nil(err)
   339  
   340  	err = k.onlineCPUMem(1, true)
   341  	assert.Nil(err)
   342  
   343  	_, err = k.statsContainer(sandbox, Container{})
   344  	assert.Nil(err)
   345  
   346  	err = k.check()
   347  	assert.Nil(err)
   348  
   349  	_, err = k.waitProcess(container, execid)
   350  	assert.Nil(err)
   351  
   352  	_, err = k.writeProcessStdin(container, execid, []byte{'c'})
   353  	assert.Nil(err)
   354  
   355  	err = k.closeProcessStdin(container, execid)
   356  	assert.Nil(err)
   357  
   358  	_, err = k.readProcessStdout(container, execid, []byte{})
   359  	assert.Nil(err)
   360  
   361  	_, err = k.readProcessStderr(container, execid, []byte{})
   362  	assert.Nil(err)
   363  
   364  	_, err = k.getOOMEvent()
   365  	assert.Nil(err)
   366  }
   367  
   368  func TestHandleEphemeralStorage(t *testing.T) {
   369  	k := kataAgent{}
   370  	var ociMounts []specs.Mount
   371  	mountSource := "/tmp/mountPoint"
   372  
   373  	mount := specs.Mount{
   374  		Type:   KataEphemeralDevType,
   375  		Source: mountSource,
   376  	}
   377  
   378  	ociMounts = append(ociMounts, mount)
   379  	epheStorages := k.handleEphemeralStorage(ociMounts)
   380  
   381  	epheMountPoint := epheStorages[0].GetMountPoint()
   382  	expected := filepath.Join(ephemeralPath(), filepath.Base(mountSource))
   383  	assert.Equal(t, epheMountPoint, expected,
   384  		"Ephemeral mount point didn't match: got %s, expecting %s", epheMountPoint, expected)
   385  }
   386  
   387  func TestHandleLocalStorage(t *testing.T) {
   388  	k := kataAgent{}
   389  	var ociMounts []specs.Mount
   390  	mountSource := "mountPoint"
   391  
   392  	mount := specs.Mount{
   393  		Type:   KataLocalDevType,
   394  		Source: mountSource,
   395  	}
   396  
   397  	sandboxID := "sandboxid"
   398  	rootfsSuffix := "rootfs"
   399  
   400  	ociMounts = append(ociMounts, mount)
   401  	localStorages := k.handleLocalStorage(ociMounts, sandboxID, rootfsSuffix)
   402  
   403  	assert.NotNil(t, localStorages)
   404  	assert.Equal(t, len(localStorages), 1)
   405  
   406  	localMountPoint := localStorages[0].GetMountPoint()
   407  	expected := filepath.Join(kataGuestSharedDir(), sandboxID, rootfsSuffix, KataLocalDevType, filepath.Base(mountSource))
   408  	assert.Equal(t, localMountPoint, expected)
   409  }
   410  
   411  func TestHandleHugepages(t *testing.T) {
   412  	if os.Getuid() != 0 {
   413  		t.Skip("Test disabled as requires root user")
   414  	}
   415  
   416  	assert := assert.New(t)
   417  
   418  	dir, err := ioutil.TempDir("", "hugepages-test")
   419  	assert.Nil(err)
   420  	defer os.RemoveAll(dir)
   421  
   422  	k := kataAgent{}
   423  	var mounts []specs.Mount
   424  	var hugepageLimits []specs.LinuxHugepageLimit
   425  
   426  	hugepageDirs := [2]string{"hugepages-1Gi", "hugepages-2Mi"}
   427  	options := [2]string{"pagesize=1024M", "pagesize=2M"}
   428  
   429  	for i := 0; i < 2; i++ {
   430  		target := path.Join(dir, hugepageDirs[i])
   431  		err := os.MkdirAll(target, 0777)
   432  		assert.NoError(err, "Unable to create dir %s", target)
   433  
   434  		err = syscall.Mount("nodev", target, "hugetlbfs", uintptr(0), options[i])
   435  		assert.NoError(err, "Unable to mount %s", target)
   436  
   437  		defer syscall.Unmount(target, 0)
   438  		defer os.RemoveAll(target)
   439  		mount := specs.Mount{
   440  			Type:   KataLocalDevType,
   441  			Source: target,
   442  		}
   443  		mounts = append(mounts, mount)
   444  
   445  	}
   446  
   447  	hugepageLimits = []specs.LinuxHugepageLimit{
   448  		{
   449  			Pagesize: "1GB",
   450  			Limit:    1073741824,
   451  		},
   452  		{
   453  			Pagesize: "2MB",
   454  			Limit:    134217728,
   455  		},
   456  	}
   457  
   458  	hugepages, err := k.handleHugepages(mounts, hugepageLimits)
   459  
   460  	assert.NoError(err, "Unable to handle hugepages %v", hugepageLimits)
   461  	assert.NotNil(hugepages)
   462  	assert.Equal(len(hugepages), 2)
   463  
   464  }
   465  
   466  func TestHandleDeviceBlockVolume(t *testing.T) {
   467  	k := kataAgent{}
   468  
   469  	tests := []struct {
   470  		BlockDeviceDriver string
   471  		inputMount        Mount
   472  		inputDev          *drivers.BlockDevice
   473  		resultVol         *pb.Storage
   474  	}{
   475  		{
   476  			inputDev: &drivers.BlockDevice{
   477  				BlockDrive: &config.BlockDrive{
   478  					Pmem:     true,
   479  					NvdimmID: testNvdimmID,
   480  					Format:   testBlkDriveFormat,
   481  				},
   482  			},
   483  			inputMount: Mount{},
   484  			resultVol: &pb.Storage{
   485  				Driver:  kataNvdimmDevType,
   486  				Source:  fmt.Sprintf("/dev/pmem%s", testNvdimmID),
   487  				Fstype:  testBlkDriveFormat,
   488  				Options: []string{"dax"},
   489  			},
   490  		},
   491  		{
   492  			BlockDeviceDriver: config.VirtioBlockCCW,
   493  			inputMount: Mount{
   494  				Type:    "bind",
   495  				Options: []string{"ro"},
   496  			},
   497  			inputDev: &drivers.BlockDevice{
   498  				BlockDrive: &config.BlockDrive{
   499  					DevNo: testDevNo,
   500  				},
   501  			},
   502  			resultVol: &pb.Storage{
   503  				Driver:  kataBlkCCWDevType,
   504  				Source:  testDevNo,
   505  				Fstype:  "bind",
   506  				Options: []string{"ro"},
   507  			},
   508  		},
   509  		{
   510  			BlockDeviceDriver: config.VirtioBlock,
   511  			inputMount:        Mount{},
   512  			inputDev: &drivers.BlockDevice{
   513  				BlockDrive: &config.BlockDrive{
   514  					PCIPath:  testPCIPath,
   515  					VirtPath: testVirtPath,
   516  				},
   517  			},
   518  			resultVol: &pb.Storage{
   519  				Driver: kataBlkDevType,
   520  				Source: testPCIPath.String(),
   521  			},
   522  		},
   523  		{
   524  			BlockDeviceDriver: config.VirtioBlock,
   525  			inputDev: &drivers.BlockDevice{
   526  				BlockDrive: &config.BlockDrive{
   527  					VirtPath: testVirtPath,
   528  				},
   529  			},
   530  			resultVol: &pb.Storage{
   531  				Driver: kataBlkDevType,
   532  				Source: testVirtPath,
   533  			},
   534  		},
   535  		{
   536  			BlockDeviceDriver: config.VirtioMmio,
   537  			inputDev: &drivers.BlockDevice{
   538  				BlockDrive: &config.BlockDrive{
   539  					VirtPath: testVirtPath,
   540  				},
   541  			},
   542  			resultVol: &pb.Storage{
   543  				Driver: kataMmioBlkDevType,
   544  				Source: testVirtPath,
   545  			},
   546  		},
   547  		{
   548  			BlockDeviceDriver: config.VirtioSCSI,
   549  			inputDev: &drivers.BlockDevice{
   550  				BlockDrive: &config.BlockDrive{
   551  					SCSIAddr: testSCSIAddr,
   552  				},
   553  			},
   554  			resultVol: &pb.Storage{
   555  				Driver: kataSCSIDevType,
   556  				Source: testSCSIAddr,
   557  			},
   558  		},
   559  	}
   560  
   561  	for _, test := range tests {
   562  		c := &Container{
   563  			sandbox: &Sandbox{
   564  				config: &SandboxConfig{
   565  					HypervisorConfig: HypervisorConfig{
   566  						BlockDeviceDriver: test.BlockDeviceDriver,
   567  					},
   568  				},
   569  			},
   570  		}
   571  
   572  		vol, _ := k.handleDeviceBlockVolume(c, test.inputMount, test.inputDev)
   573  		assert.True(t, reflect.DeepEqual(vol, test.resultVol),
   574  			"Volume didn't match: got %+v, expecting %+v",
   575  			vol, test.resultVol)
   576  	}
   577  }
   578  
   579  func TestHandleBlockVolume(t *testing.T) {
   580  	k := kataAgent{}
   581  
   582  	c := &Container{
   583  		id: "100",
   584  	}
   585  	containers := map[string]*Container{}
   586  	containers[c.id] = c
   587  
   588  	// Create a devices for VhostUserBlk, standard DeviceBlock and direct assigned Block device
   589  	vDevID := "MockVhostUserBlk"
   590  	bDevID := "MockDeviceBlock"
   591  	dDevID := "MockDeviceBlockDirect"
   592  	vDestination := "/VhostUserBlk/destination"
   593  	bDestination := "/DeviceBlock/destination"
   594  	dDestination := "/DeviceDirectBlock/destination"
   595  	vPCIPath, err := vcTypes.PciPathFromString("01/02")
   596  	assert.NoError(t, err)
   597  	bPCIPath, err := vcTypes.PciPathFromString("03/04")
   598  	assert.NoError(t, err)
   599  	dPCIPath, err := vcTypes.PciPathFromString("05/06")
   600  	assert.NoError(t, err)
   601  
   602  	vDev := drivers.NewVhostUserBlkDevice(&config.DeviceInfo{ID: vDevID})
   603  	bDev := drivers.NewBlockDevice(&config.DeviceInfo{ID: bDevID})
   604  	dDev := drivers.NewBlockDevice(&config.DeviceInfo{ID: dDevID})
   605  
   606  	vDev.VhostUserDeviceAttrs = &config.VhostUserDeviceAttrs{PCIPath: vPCIPath}
   607  	bDev.BlockDrive = &config.BlockDrive{PCIPath: bPCIPath}
   608  	dDev.BlockDrive = &config.BlockDrive{PCIPath: dPCIPath}
   609  
   610  	var devices []api.Device
   611  	devices = append(devices, vDev, bDev, dDev)
   612  
   613  	// Create a VhostUserBlk mount and a DeviceBlock mount
   614  	var mounts []Mount
   615  	vMount := Mount{
   616  		BlockDeviceID: vDevID,
   617  		Destination:   vDestination,
   618  	}
   619  	bMount := Mount{
   620  		BlockDeviceID: bDevID,
   621  		Destination:   bDestination,
   622  		Type:          "bind",
   623  		Options:       []string{"bind"},
   624  	}
   625  	dMount := Mount{
   626  		BlockDeviceID: dDevID,
   627  		Destination:   dDestination,
   628  		Type:          "ext4",
   629  		Options:       []string{"ro"},
   630  	}
   631  	mounts = append(mounts, vMount, bMount, dMount)
   632  
   633  	tmpDir := "/vhost/user/dir"
   634  	dm := manager.NewDeviceManager(manager.VirtioBlock, true, tmpDir, devices)
   635  
   636  	sConfig := SandboxConfig{}
   637  	sConfig.HypervisorConfig.BlockDeviceDriver = manager.VirtioBlock
   638  	sandbox := Sandbox{
   639  		id:         "100",
   640  		containers: containers,
   641  		hypervisor: &mockHypervisor{},
   642  		devManager: dm,
   643  		ctx:        context.Background(),
   644  		config:     &sConfig,
   645  	}
   646  	containers[c.id].sandbox = &sandbox
   647  	containers[c.id].mounts = mounts
   648  
   649  	volumeStorages, err := k.handleBlockVolumes(c)
   650  	assert.Nil(t, err, "Error while handling block volumes")
   651  
   652  	vStorage := &pb.Storage{
   653  		MountPoint: vDestination,
   654  		Fstype:     "bind",
   655  		Options:    []string{"bind"},
   656  		Driver:     kataBlkDevType,
   657  		Source:     vPCIPath.String(),
   658  	}
   659  	bStorage := &pb.Storage{
   660  		MountPoint: bDestination,
   661  		Fstype:     "bind",
   662  		Options:    []string{"bind"},
   663  		Driver:     kataBlkDevType,
   664  		Source:     bPCIPath.String(),
   665  	}
   666  	dStorage := &pb.Storage{
   667  		MountPoint: dDestination,
   668  		Fstype:     "ext4",
   669  		Options:    []string{"ro"},
   670  		Driver:     kataBlkDevType,
   671  		Source:     dPCIPath.String(),
   672  	}
   673  
   674  	assert.Equal(t, vStorage, volumeStorages[0], "Error while handle VhostUserBlk type block volume")
   675  	assert.Equal(t, bStorage, volumeStorages[1], "Error while handle BlockDevice type block volume")
   676  	assert.Equal(t, dStorage, volumeStorages[2], "Error while handle direct BlockDevice type block volume")
   677  }
   678  
   679  func TestAppendDevicesEmptyContainerDeviceList(t *testing.T) {
   680  	k := kataAgent{}
   681  
   682  	devList := []*pb.Device{}
   683  	expected := []*pb.Device{}
   684  	ctrDevices := []ContainerDevice{}
   685  
   686  	c := &Container{
   687  		sandbox: &Sandbox{
   688  			devManager: manager.NewDeviceManager("virtio-scsi", false, "", nil),
   689  		},
   690  		devices: ctrDevices,
   691  	}
   692  	updatedDevList := k.appendDevices(devList, c)
   693  	assert.True(t, reflect.DeepEqual(updatedDevList, expected),
   694  		"Device lists didn't match: got %+v, expecting %+v",
   695  		updatedDevList, expected)
   696  }
   697  
   698  func TestAppendDevices(t *testing.T) {
   699  	k := kataAgent{}
   700  
   701  	id := "test-append-block"
   702  	ctrDevices := []api.Device{
   703  		&drivers.BlockDevice{
   704  			GenericDevice: &drivers.GenericDevice{
   705  				ID: id,
   706  			},
   707  			BlockDrive: &config.BlockDrive{
   708  				PCIPath: testPCIPath,
   709  			},
   710  		},
   711  	}
   712  
   713  	sandboxConfig := &SandboxConfig{
   714  		HypervisorConfig: HypervisorConfig{
   715  			BlockDeviceDriver: config.VirtioBlock,
   716  		},
   717  	}
   718  
   719  	c := &Container{
   720  		sandbox: &Sandbox{
   721  			devManager: manager.NewDeviceManager("virtio-blk", false, "", ctrDevices),
   722  			config:     sandboxConfig,
   723  		},
   724  	}
   725  	c.devices = append(c.devices, ContainerDevice{
   726  		ID:            id,
   727  		ContainerPath: testBlockDeviceCtrPath,
   728  	})
   729  
   730  	devList := []*pb.Device{}
   731  	expected := []*pb.Device{
   732  		{
   733  			Type:          kataBlkDevType,
   734  			ContainerPath: testBlockDeviceCtrPath,
   735  			Id:            testPCIPath.String(),
   736  		},
   737  	}
   738  	updatedDevList := k.appendDevices(devList, c)
   739  	assert.True(t, reflect.DeepEqual(updatedDevList, expected),
   740  		"Device lists didn't match: got %+v, expecting %+v",
   741  		updatedDevList, expected)
   742  }
   743  
   744  func TestAppendVhostUserBlkDevices(t *testing.T) {
   745  	k := kataAgent{}
   746  
   747  	id := "test-append-vhost-user-blk"
   748  	ctrDevices := []api.Device{
   749  		&drivers.VhostUserBlkDevice{
   750  			GenericDevice: &drivers.GenericDevice{
   751  				ID: id,
   752  			},
   753  			VhostUserDeviceAttrs: &config.VhostUserDeviceAttrs{
   754  				Type:    config.VhostUserBlk,
   755  				PCIPath: testPCIPath,
   756  			},
   757  		},
   758  	}
   759  
   760  	sandboxConfig := &SandboxConfig{
   761  		HypervisorConfig: HypervisorConfig{
   762  			BlockDeviceDriver: config.VirtioBlock,
   763  		},
   764  	}
   765  
   766  	testVhostUserStorePath := "/test/vhost/user/store/path"
   767  	c := &Container{
   768  		sandbox: &Sandbox{
   769  			devManager: manager.NewDeviceManager("virtio-blk", true, testVhostUserStorePath, ctrDevices),
   770  			config:     sandboxConfig,
   771  		},
   772  	}
   773  	c.devices = append(c.devices, ContainerDevice{
   774  		ID:            id,
   775  		ContainerPath: testBlockDeviceCtrPath,
   776  	})
   777  
   778  	devList := []*pb.Device{}
   779  	expected := []*pb.Device{
   780  		{
   781  			Type:          kataBlkDevType,
   782  			ContainerPath: testBlockDeviceCtrPath,
   783  			Id:            testPCIPath.String(),
   784  		},
   785  	}
   786  	updatedDevList := k.appendDevices(devList, c)
   787  	assert.True(t, reflect.DeepEqual(updatedDevList, expected),
   788  		"Device lists didn't match: got %+v, expecting %+v",
   789  		updatedDevList, expected)
   790  }
   791  
   792  func TestConstraintGRPCSpec(t *testing.T) {
   793  	assert := assert.New(t)
   794  	expectedCgroupPath := "/foo/bar"
   795  
   796  	g := &pb.Spec{
   797  		Hooks: &pb.Hooks{},
   798  		Mounts: []pb.Mount{
   799  			{Destination: "/dev/shm"},
   800  		},
   801  		Linux: &pb.Linux{
   802  			Seccomp: &pb.LinuxSeccomp{},
   803  			Namespaces: []pb.LinuxNamespace{
   804  				{
   805  					Type: specs.NetworkNamespace,
   806  					Path: "/abc/123",
   807  				},
   808  				{
   809  					Type: specs.MountNamespace,
   810  					Path: "/abc/123",
   811  				},
   812  			},
   813  			Resources: &pb.LinuxResources{
   814  				Devices:        []pb.LinuxDeviceCgroup{},
   815  				Memory:         &pb.LinuxMemory{},
   816  				CPU:            &pb.LinuxCPU{},
   817  				Pids:           &pb.LinuxPids{},
   818  				BlockIO:        &pb.LinuxBlockIO{},
   819  				HugepageLimits: []pb.LinuxHugepageLimit{},
   820  				Network:        &pb.LinuxNetwork{},
   821  			},
   822  			CgroupsPath: "system.slice:foo:bar",
   823  			Devices: []pb.LinuxDevice{
   824  				{
   825  					Path: "/dev/vfio/1",
   826  					Type: "c",
   827  				},
   828  				{
   829  					Path: "/dev/vfio/2",
   830  					Type: "c",
   831  				},
   832  			},
   833  		},
   834  		Process: &pb.Process{
   835  			SelinuxLabel: "foo",
   836  		},
   837  	}
   838  
   839  	k := kataAgent{}
   840  	k.constraintGRPCSpec(g, true)
   841  
   842  	// check nil fields
   843  	assert.Nil(g.Hooks)
   844  	assert.NotNil(g.Linux.Seccomp)
   845  	assert.Nil(g.Linux.Resources.Devices)
   846  	assert.NotNil(g.Linux.Resources.Memory)
   847  	assert.Nil(g.Linux.Resources.Pids)
   848  	assert.Nil(g.Linux.Resources.BlockIO)
   849  	assert.Nil(g.Linux.Resources.HugepageLimits)
   850  	assert.Nil(g.Linux.Resources.Network)
   851  	assert.NotNil(g.Linux.Resources.CPU)
   852  	assert.Equal(g.Process.SelinuxLabel, "")
   853  
   854  	// check namespaces
   855  	assert.Len(g.Linux.Namespaces, 1)
   856  	assert.Empty(g.Linux.Namespaces[0].Path)
   857  
   858  	// check mounts
   859  	assert.Len(g.Mounts, 1)
   860  
   861  	// check cgroup path
   862  	assert.Equal(expectedCgroupPath, g.Linux.CgroupsPath)
   863  
   864  	// check Linux devices
   865  	assert.Empty(g.Linux.Devices)
   866  }
   867  
   868  func TestHandleShm(t *testing.T) {
   869  	assert := assert.New(t)
   870  	k := kataAgent{}
   871  	sandbox := &Sandbox{
   872  		shmSize: 8192,
   873  	}
   874  
   875  	var ociMounts []specs.Mount
   876  
   877  	mount := specs.Mount{
   878  		Type:        "bind",
   879  		Destination: "/dev/shm",
   880  	}
   881  
   882  	ociMounts = append(ociMounts, mount)
   883  	k.handleShm(ociMounts, sandbox)
   884  
   885  	assert.Len(ociMounts, 1)
   886  	assert.NotEmpty(ociMounts[0].Destination)
   887  	assert.Equal(ociMounts[0].Destination, "/dev/shm")
   888  	assert.Equal(ociMounts[0].Type, "bind")
   889  	assert.NotEmpty(ociMounts[0].Source, filepath.Join(kataGuestSharedDir(), shmDir))
   890  	assert.Equal(ociMounts[0].Options, []string{"rbind"})
   891  
   892  	sandbox.shmSize = 0
   893  	k.handleShm(ociMounts, sandbox)
   894  
   895  	assert.Len(ociMounts, 1)
   896  	assert.Equal(ociMounts[0].Destination, "/dev/shm")
   897  	assert.Equal(ociMounts[0].Type, "tmpfs")
   898  	assert.Equal(ociMounts[0].Source, "shm")
   899  	sizeOption := fmt.Sprintf("size=%d", DefaultShmSize)
   900  	assert.Equal(ociMounts[0].Options, []string{"noexec", "nosuid", "nodev", "mode=1777", sizeOption})
   901  
   902  	// In case the type of mount is ephemeral, the container mount is not
   903  	// shared with the sandbox shm.
   904  	ociMounts[0].Type = KataEphemeralDevType
   905  	mountSource := "/tmp/mountPoint"
   906  	ociMounts[0].Source = mountSource
   907  	k.handleShm(ociMounts, sandbox)
   908  
   909  	assert.Len(ociMounts, 1)
   910  	assert.Equal(ociMounts[0].Type, KataEphemeralDevType)
   911  	assert.NotEmpty(ociMounts[0].Source, mountSource)
   912  
   913  	epheStorages := k.handleEphemeralStorage(ociMounts)
   914  	epheMountPoint := epheStorages[0].GetMountPoint()
   915  	expected := filepath.Join(ephemeralPath(), filepath.Base(mountSource))
   916  	assert.Equal(epheMountPoint, expected,
   917  		"Ephemeral mount point didn't match: got %s, expecting %s", epheMountPoint, expected)
   918  
   919  }
   920  
   921  func testIsPidNamespacePresent(grpcSpec *pb.Spec) bool {
   922  	for _, ns := range grpcSpec.Linux.Namespaces {
   923  		if ns.Type == string(specs.PIDNamespace) {
   924  			return true
   925  		}
   926  	}
   927  
   928  	return false
   929  }
   930  
   931  func TestHandlePidNamespace(t *testing.T) {
   932  	assert := assert.New(t)
   933  
   934  	g := &pb.Spec{
   935  		Linux: &pb.Linux{
   936  			Namespaces: []pb.LinuxNamespace{
   937  				{
   938  					Type: specs.NetworkNamespace,
   939  					Path: "/abc/123",
   940  				},
   941  				{
   942  					Type: specs.MountNamespace,
   943  					Path: "/abc/123",
   944  				},
   945  			},
   946  		},
   947  	}
   948  
   949  	sandbox := &Sandbox{}
   950  
   951  	k := kataAgent{}
   952  
   953  	sharedPid := k.handlePidNamespace(g, sandbox)
   954  	assert.False(sharedPid)
   955  	assert.False(testIsPidNamespacePresent(g))
   956  
   957  	pidNs := pb.LinuxNamespace{
   958  		Type: string(specs.PIDNamespace),
   959  		Path: "",
   960  	}
   961  
   962  	utsNs := pb.LinuxNamespace{
   963  		Type: specs.UTSNamespace,
   964  		Path: "",
   965  	}
   966  
   967  	g.Linux.Namespaces = append(g.Linux.Namespaces, pidNs)
   968  	g.Linux.Namespaces = append(g.Linux.Namespaces, utsNs)
   969  
   970  	sharedPid = k.handlePidNamespace(g, sandbox)
   971  	assert.False(sharedPid)
   972  	assert.False(testIsPidNamespacePresent(g))
   973  
   974  	pidNs = pb.LinuxNamespace{
   975  		Type: string(specs.PIDNamespace),
   976  		Path: "/proc/112/ns/pid",
   977  	}
   978  	g.Linux.Namespaces = append(g.Linux.Namespaces, pidNs)
   979  
   980  	sharedPid = k.handlePidNamespace(g, sandbox)
   981  	assert.True(sharedPid)
   982  	assert.False(testIsPidNamespacePresent(g))
   983  }
   984  
   985  func TestAgentConfigure(t *testing.T) {
   986  	assert := assert.New(t)
   987  
   988  	dir, err := ioutil.TempDir("", "kata-agent-test")
   989  	assert.Nil(err)
   990  	defer os.RemoveAll(dir)
   991  
   992  	k := &kataAgent{}
   993  	h := &mockHypervisor{}
   994  	c := KataAgentConfig{}
   995  	id := "foobar"
   996  
   997  	err = k.configure(h, id, dir, true, c)
   998  	assert.Nil(err)
   999  
  1000  	err = k.configure(h, id, dir, true, c)
  1001  	assert.Nil(err)
  1002  	assert.Empty(k.state.URL)
  1003  
  1004  	err = k.configure(h, id, dir, false, c)
  1005  	assert.Nil(err)
  1006  }
  1007  
  1008  func TestCmdToKataProcess(t *testing.T) {
  1009  	assert := assert.New(t)
  1010  
  1011  	cmd := types.Cmd{
  1012  		Args:         strings.Split("foo", " "),
  1013  		Envs:         []types.EnvVar{},
  1014  		WorkDir:      "/",
  1015  		User:         "1000",
  1016  		PrimaryGroup: "1000",
  1017  	}
  1018  	_, err := cmdToKataProcess(cmd)
  1019  	assert.Nil(err)
  1020  
  1021  	cmd1 := cmd
  1022  	cmd1.User = "foobar"
  1023  	_, err = cmdToKataProcess(cmd1)
  1024  	assert.Error(err)
  1025  
  1026  	cmd1 = cmd
  1027  	cmd1.PrimaryGroup = "foobar"
  1028  	_, err = cmdToKataProcess(cmd1)
  1029  	assert.Error(err)
  1030  
  1031  	cmd1 = cmd
  1032  	cmd1.User = "foobar:1000"
  1033  	_, err = cmdToKataProcess(cmd1)
  1034  	assert.Error(err)
  1035  
  1036  	cmd1 = cmd
  1037  	cmd1.User = "1000:2000"
  1038  	_, err = cmdToKataProcess(cmd1)
  1039  	assert.Nil(err)
  1040  
  1041  	cmd1 = cmd
  1042  	cmd1.SupplementaryGroups = []string{"foo"}
  1043  	_, err = cmdToKataProcess(cmd1)
  1044  	assert.Error(err)
  1045  
  1046  	cmd1 = cmd
  1047  	cmd1.SupplementaryGroups = []string{"4000"}
  1048  	_, err = cmdToKataProcess(cmd1)
  1049  	assert.Nil(err)
  1050  }
  1051  
  1052  func TestAgentCreateContainer(t *testing.T) {
  1053  	assert := assert.New(t)
  1054  
  1055  	sandbox := &Sandbox{
  1056  		ctx: context.Background(),
  1057  		id:  "foobar",
  1058  		config: &SandboxConfig{
  1059  			ID:             "foobar",
  1060  			HypervisorType: MockHypervisor,
  1061  			HypervisorConfig: HypervisorConfig{
  1062  				KernelPath: "foo",
  1063  				ImagePath:  "bar",
  1064  			},
  1065  		},
  1066  		hypervisor: &mockHypervisor{},
  1067  	}
  1068  
  1069  	newStore, err := persist.GetDriver()
  1070  	assert.NoError(err)
  1071  	assert.NotNil(newStore)
  1072  	sandbox.newStore = newStore
  1073  
  1074  	container := &Container{
  1075  		ctx:       sandbox.ctx,
  1076  		id:        "barfoo",
  1077  		sandboxID: "foobar",
  1078  		sandbox:   sandbox,
  1079  		state: types.ContainerState{
  1080  			Fstype: "xfs",
  1081  		},
  1082  		config: &ContainerConfig{
  1083  			CustomSpec:  &specs.Spec{},
  1084  			Annotations: map[string]string{},
  1085  		},
  1086  	}
  1087  
  1088  	impl := &gRPCProxy{}
  1089  
  1090  	proxy := mock.ProxyGRPCMock{
  1091  		GRPCImplementer: impl,
  1092  		GRPCRegister:    gRPCRegister,
  1093  	}
  1094  
  1095  	sockDir, err := testGenerateKataProxySockDir()
  1096  	assert.Nil(err)
  1097  	defer os.RemoveAll(sockDir)
  1098  
  1099  	testKataProxyURL := fmt.Sprintf(testKataProxyURLTempl, sockDir)
  1100  	err = proxy.Start(testKataProxyURL)
  1101  	assert.Nil(err)
  1102  	defer proxy.Stop()
  1103  
  1104  	k := &kataAgent{
  1105  		ctx: context.Background(),
  1106  		state: KataAgentState{
  1107  			URL: testKataProxyURL,
  1108  		},
  1109  	}
  1110  
  1111  	dir, err := ioutil.TempDir("", "kata-agent-test")
  1112  	assert.Nil(err)
  1113  	defer os.RemoveAll(dir)
  1114  
  1115  	err = k.configure(&mockHypervisor{}, sandbox.id, dir, true, KataAgentConfig{})
  1116  	assert.Nil(err)
  1117  
  1118  	// We'll fail on container metadata file creation, but it helps increasing coverage...
  1119  	_, err = k.createContainer(sandbox, container)
  1120  	assert.Error(err)
  1121  }
  1122  
  1123  func TestAgentNetworkOperation(t *testing.T) {
  1124  	assert := assert.New(t)
  1125  
  1126  	impl := &gRPCProxy{}
  1127  
  1128  	proxy := mock.ProxyGRPCMock{
  1129  		GRPCImplementer: impl,
  1130  		GRPCRegister:    gRPCRegister,
  1131  	}
  1132  
  1133  	sockDir, err := testGenerateKataProxySockDir()
  1134  	assert.NoError(err)
  1135  	defer os.RemoveAll(sockDir)
  1136  
  1137  	testKataProxyURL := fmt.Sprintf(testKataProxyURLTempl, sockDir)
  1138  	assert.NoError(proxy.Start(testKataProxyURL))
  1139  	defer proxy.Stop()
  1140  
  1141  	k := &kataAgent{
  1142  		ctx: context.Background(),
  1143  		state: KataAgentState{
  1144  			URL: testKataProxyURL,
  1145  		},
  1146  	}
  1147  
  1148  	_, err = k.updateInterface(nil)
  1149  	assert.Nil(err)
  1150  
  1151  	_, err = k.listInterfaces()
  1152  	assert.Nil(err)
  1153  
  1154  	_, err = k.updateRoutes([]*vcTypes.Route{})
  1155  	assert.Nil(err)
  1156  
  1157  	_, err = k.listRoutes()
  1158  	assert.Nil(err)
  1159  
  1160  	err = k.addARPNeighbors(nil)
  1161  	assert.Nil(err)
  1162  }
  1163  
  1164  func TestKataAgentSetProxy(t *testing.T) {
  1165  	assert := assert.New(t)
  1166  
  1167  	k := &kataAgent{ctx: context.Background()}
  1168  	p := &kataBuiltInProxy{}
  1169  	s := &Sandbox{
  1170  		ctx: context.Background(),
  1171  		id:  "foobar",
  1172  	}
  1173  
  1174  	err := k.setProxy(s, p, 0, "")
  1175  	assert.Error(err)
  1176  }
  1177  
  1178  func TestKataGetAgentUrl(t *testing.T) {
  1179  	assert := assert.New(t)
  1180  	var err error
  1181  
  1182  	k := &kataAgent{vmSocket: types.Socket{HostPath: "/abc"}}
  1183  	assert.NoError(err)
  1184  	url, err := k.getAgentURL()
  1185  	assert.Nil(err)
  1186  	assert.NotEmpty(url)
  1187  
  1188  	k.vmSocket = types.VSock{}
  1189  	assert.NoError(err)
  1190  	url, err = k.getAgentURL()
  1191  	assert.Nil(err)
  1192  	assert.NotEmpty(url)
  1193  }
  1194  
  1195  func TestKataCopyFile(t *testing.T) {
  1196  	assert := assert.New(t)
  1197  
  1198  	impl := &gRPCProxy{}
  1199  
  1200  	proxy := mock.ProxyGRPCMock{
  1201  		GRPCImplementer: impl,
  1202  		GRPCRegister:    gRPCRegister,
  1203  	}
  1204  
  1205  	sockDir, err := testGenerateKataProxySockDir()
  1206  	assert.NoError(err)
  1207  	defer os.RemoveAll(sockDir)
  1208  
  1209  	testKataProxyURL := fmt.Sprintf(testKataProxyURLTempl, sockDir)
  1210  	err = proxy.Start(testKataProxyURL)
  1211  	assert.NoError(err)
  1212  	defer proxy.Stop()
  1213  
  1214  	k := &kataAgent{
  1215  		ctx: context.Background(),
  1216  		state: KataAgentState{
  1217  			URL: testKataProxyURL,
  1218  		},
  1219  	}
  1220  
  1221  	err = k.copyFile("/abc/xyz/123", "/tmp")
  1222  	assert.Error(err)
  1223  
  1224  	src, err := ioutil.TempFile("", "src")
  1225  	assert.NoError(err)
  1226  	defer os.Remove(src.Name())
  1227  
  1228  	data := []byte("abcdefghi123456789")
  1229  	_, err = src.Write(data)
  1230  	assert.NoError(err)
  1231  	assert.NoError(src.Close())
  1232  
  1233  	dst, err := ioutil.TempFile("", "dst")
  1234  	assert.NoError(err)
  1235  	assert.NoError(dst.Close())
  1236  	defer os.Remove(dst.Name())
  1237  
  1238  	orgGrpcMaxDataSize := grpcMaxDataSize
  1239  	grpcMaxDataSize = 1
  1240  	defer func() {
  1241  		grpcMaxDataSize = orgGrpcMaxDataSize
  1242  	}()
  1243  
  1244  	err = k.copyFile(src.Name(), dst.Name())
  1245  	assert.NoError(err)
  1246  }
  1247  
  1248  func TestKataCleanupSandbox(t *testing.T) {
  1249  	assert := assert.New(t)
  1250  
  1251  	kataHostSharedDirSaved := kataHostSharedDir
  1252  	kataHostSharedDir = func() string {
  1253  		td, _ := ioutil.TempDir("", "kata-cleanup")
  1254  		return td
  1255  	}
  1256  	defer func() {
  1257  		kataHostSharedDir = kataHostSharedDirSaved
  1258  	}()
  1259  
  1260  	s := Sandbox{
  1261  		id: "testFoo",
  1262  	}
  1263  
  1264  	dir := kataHostSharedDir()
  1265  	defer os.RemoveAll(dir)
  1266  	err := os.MkdirAll(path.Join(dir, s.id), 0777)
  1267  	assert.Nil(err)
  1268  
  1269  	k := &kataAgent{ctx: context.Background()}
  1270  	k.cleanup(&s)
  1271  
  1272  	_, err = os.Stat(dir)
  1273  	assert.False(os.IsExist(err))
  1274  }
  1275  
  1276  func TestKataAgentKernelParams(t *testing.T) {
  1277  	assert := assert.New(t)
  1278  
  1279  	type testData struct {
  1280  		debug             bool
  1281  		trace             bool
  1282  		containerPipeSize uint32
  1283  		traceMode         string
  1284  		traceType         string
  1285  		expectedParams    []Param
  1286  	}
  1287  
  1288  	debugParam := Param{Key: "agent.log", Value: "debug"}
  1289  
  1290  	traceIsolatedParam := Param{Key: "agent.trace", Value: "isolated"}
  1291  	traceCollatedParam := Param{Key: "agent.trace", Value: "collated"}
  1292  
  1293  	traceFooParam := Param{Key: "agent.trace", Value: "foo"}
  1294  
  1295  	containerPipeSizeParam := Param{Key: vcAnnotations.ContainerPipeSizeKernelParam, Value: "2097152"}
  1296  
  1297  	data := []testData{
  1298  		{false, false, 0, "", "", []Param{}},
  1299  		{true, false, 0, "", "", []Param{debugParam}},
  1300  
  1301  		{false, false, 0, "foo", "", []Param{}},
  1302  		{false, false, 0, "foo", "", []Param{}},
  1303  		{false, false, 0, "", "foo", []Param{}},
  1304  		{false, false, 0, "", "foo", []Param{}},
  1305  		{false, false, 0, "foo", "foo", []Param{}},
  1306  		{false, true, 0, "foo", "foo", []Param{}},
  1307  
  1308  		{false, false, 0, agentTraceModeDynamic, "", []Param{}},
  1309  		{false, false, 0, agentTraceModeStatic, "", []Param{}},
  1310  		{false, false, 0, "", agentTraceTypeIsolated, []Param{}},
  1311  		{false, false, 0, "", agentTraceTypeCollated, []Param{}},
  1312  		{false, false, 0, "foo", agentTraceTypeIsolated, []Param{}},
  1313  		{false, false, 0, "foo", agentTraceTypeCollated, []Param{}},
  1314  
  1315  		{false, false, 0, agentTraceModeDynamic, agentTraceTypeIsolated, []Param{}},
  1316  		{false, false, 0, agentTraceModeDynamic, agentTraceTypeCollated, []Param{}},
  1317  
  1318  		{false, false, 0, agentTraceModeStatic, agentTraceTypeCollated, []Param{}},
  1319  		{false, false, 0, agentTraceModeStatic, agentTraceTypeCollated, []Param{}},
  1320  
  1321  		{false, true, 0, agentTraceModeDynamic, agentTraceTypeIsolated, []Param{}},
  1322  		{false, true, 0, agentTraceModeDynamic, agentTraceTypeCollated, []Param{}},
  1323  		{true, true, 0, agentTraceModeDynamic, agentTraceTypeCollated, []Param{debugParam}},
  1324  
  1325  		{false, true, 0, "", agentTraceTypeIsolated, []Param{}},
  1326  		{false, true, 0, "", agentTraceTypeCollated, []Param{}},
  1327  		{true, true, 0, "", agentTraceTypeIsolated, []Param{debugParam}},
  1328  		{true, true, 0, "", agentTraceTypeCollated, []Param{debugParam}},
  1329  		{false, true, 0, "foo", agentTraceTypeIsolated, []Param{}},
  1330  		{false, true, 0, "foo", agentTraceTypeCollated, []Param{}},
  1331  		{true, true, 0, "foo", agentTraceTypeIsolated, []Param{debugParam}},
  1332  		{true, true, 0, "foo", agentTraceTypeCollated, []Param{debugParam}},
  1333  
  1334  		{false, true, 0, agentTraceModeStatic, agentTraceTypeIsolated, []Param{traceIsolatedParam}},
  1335  		{false, true, 0, agentTraceModeStatic, agentTraceTypeCollated, []Param{traceCollatedParam}},
  1336  		{true, true, 0, agentTraceModeStatic, agentTraceTypeIsolated, []Param{traceIsolatedParam, debugParam}},
  1337  		{true, true, 0, agentTraceModeStatic, agentTraceTypeCollated, []Param{traceCollatedParam, debugParam}},
  1338  
  1339  		{false, true, 0, agentTraceModeStatic, "foo", []Param{traceFooParam}},
  1340  		{true, true, 0, agentTraceModeStatic, "foo", []Param{debugParam, traceFooParam}},
  1341  
  1342  		{false, false, 0, "", "", []Param{}},
  1343  		{false, false, 2097152, "", "", []Param{containerPipeSizeParam}},
  1344  	}
  1345  
  1346  	for i, d := range data {
  1347  		config := KataAgentConfig{
  1348  			Debug:             d.debug,
  1349  			Trace:             d.trace,
  1350  			TraceMode:         d.traceMode,
  1351  			TraceType:         d.traceType,
  1352  			ContainerPipeSize: d.containerPipeSize,
  1353  		}
  1354  
  1355  		count := len(d.expectedParams)
  1356  
  1357  		params := KataAgentKernelParams(config)
  1358  
  1359  		if count == 0 {
  1360  			assert.Emptyf(params, "test %d (%+v)", i, d)
  1361  			continue
  1362  		}
  1363  
  1364  		assert.Len(params, count)
  1365  
  1366  		for _, p := range d.expectedParams {
  1367  			assert.Containsf(params, p, "test %d (%+v)", i, d)
  1368  		}
  1369  	}
  1370  }
  1371  
  1372  func TestKataAgentHandleTraceSettings(t *testing.T) {
  1373  	assert := assert.New(t)
  1374  
  1375  	type testData struct {
  1376  		traceMode               string
  1377  		trace                   bool
  1378  		expectDisableVMShutdown bool
  1379  		expectDynamicTracing    bool
  1380  	}
  1381  
  1382  	data := []testData{
  1383  		{"", false, false, false},
  1384  		{"", true, false, false},
  1385  		{agentTraceModeStatic, true, true, false},
  1386  		{agentTraceModeDynamic, true, false, true},
  1387  	}
  1388  
  1389  	for i, d := range data {
  1390  		k := &kataAgent{}
  1391  
  1392  		config := KataAgentConfig{
  1393  			Trace:     d.trace,
  1394  			TraceMode: d.traceMode,
  1395  		}
  1396  
  1397  		disableVMShutdown := k.handleTraceSettings(config)
  1398  
  1399  		if d.expectDisableVMShutdown {
  1400  			assert.Truef(disableVMShutdown, "test %d (%+v)", i, d)
  1401  		} else {
  1402  			assert.Falsef(disableVMShutdown, "test %d (%+v)", i, d)
  1403  		}
  1404  
  1405  		if d.expectDynamicTracing {
  1406  			assert.Truef(k.dynamicTracing, "test %d (%+v)", i, d)
  1407  		} else {
  1408  			assert.Falsef(k.dynamicTracing, "test %d (%+v)", i, d)
  1409  		}
  1410  	}
  1411  }
  1412  
  1413  func TestKataAgentSetDefaultTraceConfigOptions(t *testing.T) {
  1414  	assert := assert.New(t)
  1415  
  1416  	type testData struct {
  1417  		traceMode              string
  1418  		traceType              string
  1419  		trace                  bool
  1420  		expectDefaultTraceMode bool
  1421  		expectDefaultTraceType bool
  1422  		expectError            bool
  1423  	}
  1424  
  1425  	data := []testData{
  1426  		{"", "", false, false, false, false},
  1427  		{agentTraceModeDynamic, agentTraceTypeCollated, false, false, false, false},
  1428  		{agentTraceModeDynamic, agentTraceTypeIsolated, false, false, false, false},
  1429  		{agentTraceModeStatic, agentTraceTypeCollated, false, false, false, false},
  1430  		{agentTraceModeStatic, agentTraceTypeIsolated, false, false, false, false},
  1431  
  1432  		{agentTraceModeDynamic, agentTraceTypeCollated, true, false, false, false},
  1433  		{agentTraceModeDynamic, agentTraceTypeIsolated, true, false, false, false},
  1434  
  1435  		{agentTraceModeStatic, agentTraceTypeCollated, true, false, false, false},
  1436  		{agentTraceModeStatic, agentTraceTypeIsolated, true, false, false, false},
  1437  
  1438  		{agentTraceModeDynamic, "", true, false, true, false},
  1439  		{agentTraceModeDynamic, "invalid", true, false, false, true},
  1440  
  1441  		{agentTraceModeStatic, "", true, false, true, false},
  1442  		{agentTraceModeStatic, "invalid", true, false, false, true},
  1443  
  1444  		{"", agentTraceTypeIsolated, true, true, false, false},
  1445  		{"invalid", agentTraceTypeIsolated, true, false, false, true},
  1446  
  1447  		{"", agentTraceTypeCollated, true, true, false, false},
  1448  		{"invalid", agentTraceTypeCollated, true, false, false, true},
  1449  
  1450  		{"", "", true, true, true, false},
  1451  		{"invalid", "invalid", true, false, false, true},
  1452  	}
  1453  
  1454  	for i, d := range data {
  1455  		config := &KataAgentConfig{
  1456  			Trace:     d.trace,
  1457  			TraceMode: d.traceMode,
  1458  			TraceType: d.traceType,
  1459  		}
  1460  
  1461  		err := KataAgentSetDefaultTraceConfigOptions(config)
  1462  		if d.expectError {
  1463  			assert.Error(err, "test %d (%+v)", i, d)
  1464  			continue
  1465  		} else {
  1466  			assert.NoError(err, "test %d (%+v)", i, d)
  1467  		}
  1468  
  1469  		if d.expectDefaultTraceMode {
  1470  			assert.Equalf(config.TraceMode, defaultAgentTraceMode, "test %d (%+v)", i, d)
  1471  		}
  1472  
  1473  		if d.expectDefaultTraceType {
  1474  			assert.Equalf(config.TraceType, defaultAgentTraceType, "test %d (%+v)", i, d)
  1475  		}
  1476  	}
  1477  }
  1478  
  1479  func TestKataAgentDirs(t *testing.T) {
  1480  	assert := assert.New(t)
  1481  
  1482  	uidmapFile, err := os.OpenFile("/proc/self/uid_map", os.O_RDONLY, 0)
  1483  	assert.NoError(err)
  1484  
  1485  	line, err := bufio.NewReader(uidmapFile).ReadBytes('\n')
  1486  	assert.NoError(err)
  1487  
  1488  	uidmap := strings.Fields(string(line))
  1489  	expectedRootless := (uidmap[0] == "0" && uidmap[1] != "0")
  1490  	assert.Equal(expectedRootless, rootless.IsRootless())
  1491  
  1492  	if expectedRootless {
  1493  		assert.Equal(kataHostSharedDir(), os.Getenv("XDG_RUNTIME_DIR")+defaultKataHostSharedDir)
  1494  		assert.Equal(kataGuestSharedDir(), os.Getenv("XDG_RUNTIME_DIR")+defaultKataGuestSharedDir)
  1495  		assert.Equal(kataGuestSandboxDir(), os.Getenv("XDG_RUNTIME_DIR")+defaultKataGuestSandboxDir)
  1496  		assert.Equal(ephemeralPath(), os.Getenv("XDG_RUNTIME_DIR")+defaultEphemeralPath)
  1497  	} else {
  1498  		assert.Equal(kataHostSharedDir(), defaultKataHostSharedDir)
  1499  		assert.Equal(kataGuestSharedDir(), defaultKataGuestSharedDir)
  1500  		assert.Equal(kataGuestSandboxDir(), defaultKataGuestSandboxDir)
  1501  		assert.Equal(ephemeralPath(), defaultEphemeralPath)
  1502  	}
  1503  }