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 }