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