github.com/kata-containers/runtime@v0.0.0-20210505125100-04f29832a923/virtcontainers/api.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 "os" 11 "runtime" 12 "syscall" 13 14 deviceApi "github.com/kata-containers/runtime/virtcontainers/device/api" 15 deviceConfig "github.com/kata-containers/runtime/virtcontainers/device/config" 16 "github.com/kata-containers/runtime/virtcontainers/persist" 17 "github.com/kata-containers/runtime/virtcontainers/pkg/cgroups" 18 "github.com/kata-containers/runtime/virtcontainers/pkg/compatoci" 19 vcTypes "github.com/kata-containers/runtime/virtcontainers/pkg/types" 20 "github.com/kata-containers/runtime/virtcontainers/store" 21 "github.com/kata-containers/runtime/virtcontainers/types" 22 specs "github.com/opencontainers/runtime-spec/specs-go" 23 opentracing "github.com/opentracing/opentracing-go" 24 "github.com/sirupsen/logrus" 25 ) 26 27 func init() { 28 runtime.LockOSThread() 29 } 30 31 var virtLog = logrus.WithField("source", "virtcontainers") 32 33 // trace creates a new tracing span based on the specified name and parent 34 // context. 35 func trace(parent context.Context, name string) (opentracing.Span, context.Context) { 36 span, ctx := opentracing.StartSpanFromContext(parent, name) 37 38 // Should not need to be changed (again). 39 span.SetTag("source", "virtcontainers") 40 span.SetTag("component", "virtcontainers") 41 42 // Should be reset as new subsystems are entered. 43 span.SetTag("subsystem", "api") 44 45 return span, ctx 46 } 47 48 // SetLogger sets the logger for virtcontainers package. 49 func SetLogger(ctx context.Context, logger *logrus.Entry) { 50 fields := virtLog.Data 51 virtLog = logger.WithFields(fields) 52 53 deviceApi.SetLogger(virtLog) 54 compatoci.SetLogger(virtLog) 55 store.SetLogger(virtLog) 56 deviceConfig.SetLogger(virtLog) 57 cgroups.SetLogger(virtLog) 58 } 59 60 // CreateSandbox is the virtcontainers sandbox creation entry point. 61 // CreateSandbox creates a sandbox and its containers. It does not start them. 62 func CreateSandbox(ctx context.Context, sandboxConfig SandboxConfig, factory Factory) (VCSandbox, error) { 63 span, ctx := trace(ctx, "CreateSandbox") 64 defer span.Finish() 65 66 s, err := createSandboxFromConfig(ctx, sandboxConfig, factory) 67 if err == nil { 68 s.releaseStatelessSandbox() 69 } 70 71 return s, err 72 } 73 74 func createSandboxFromConfig(ctx context.Context, sandboxConfig SandboxConfig, factory Factory) (_ *Sandbox, err error) { 75 span, ctx := trace(ctx, "createSandboxFromConfig") 76 defer span.Finish() 77 78 // Create the sandbox. 79 s, err := createSandbox(ctx, sandboxConfig, factory) 80 if err != nil { 81 return nil, err 82 } 83 84 // cleanup sandbox resources in case of any failure 85 defer func() { 86 if err != nil { 87 s.Delete() 88 } 89 }() 90 91 // Create the sandbox network 92 if err = s.createNetwork(); err != nil { 93 return nil, err 94 } 95 96 // network rollback 97 defer func() { 98 if err != nil { 99 s.removeNetwork() 100 } 101 }() 102 103 // Move runtime to sandbox cgroup so all process are created there. 104 if s.config.SandboxCgroupOnly { 105 if err := s.createCgroupManager(); err != nil { 106 return nil, err 107 } 108 109 if err := s.setupSandboxCgroup(); err != nil { 110 return nil, err 111 } 112 } 113 114 // Start the VM 115 if err = s.startVM(); err != nil { 116 return nil, err 117 } 118 119 // rollback to stop VM if error occurs 120 defer func() { 121 if err != nil { 122 s.stopVM() 123 } 124 }() 125 126 s.postCreatedNetwork() 127 128 if err = s.getAndStoreGuestDetails(); err != nil { 129 return nil, err 130 } 131 132 // Create Containers 133 if err = s.createContainers(); err != nil { 134 return nil, err 135 } 136 137 // The sandbox is completely created now, we can store it. 138 if err = s.storeSandbox(); err != nil { 139 return nil, err 140 } 141 142 return s, nil 143 } 144 145 // DeleteSandbox is the virtcontainers sandbox deletion entry point. 146 // DeleteSandbox will stop an already running container and then delete it. 147 func DeleteSandbox(ctx context.Context, sandboxID string) (VCSandbox, error) { 148 span, ctx := trace(ctx, "DeleteSandbox") 149 defer span.Finish() 150 151 if sandboxID == "" { 152 return nil, vcTypes.ErrNeedSandboxID 153 } 154 155 unlock, err := rwLockSandbox(sandboxID) 156 if err != nil { 157 return nil, err 158 } 159 defer unlock() 160 161 // Fetch the sandbox from storage and create it. 162 s, err := fetchSandbox(ctx, sandboxID) 163 if err != nil { 164 return nil, err 165 } 166 defer s.releaseStatelessSandbox() 167 168 // Delete it. 169 if err := s.Delete(); err != nil { 170 return nil, err 171 } 172 173 return s, nil 174 } 175 176 // FetchSandbox is the virtcontainers sandbox fetching entry point. 177 // FetchSandbox will find out and connect to an existing sandbox and 178 // return the sandbox structure. The caller is responsible of calling 179 // VCSandbox.Release() after done with it. 180 func FetchSandbox(ctx context.Context, sandboxID string) (VCSandbox, error) { 181 span, ctx := trace(ctx, "FetchSandbox") 182 defer span.Finish() 183 184 if sandboxID == "" { 185 return nil, vcTypes.ErrNeedSandboxID 186 } 187 188 unlock, err := rwLockSandbox(sandboxID) 189 if err != nil { 190 return nil, err 191 } 192 defer unlock() 193 194 // Fetch the sandbox from storage and create it. 195 s, err := fetchSandbox(ctx, sandboxID) 196 if err != nil { 197 return nil, err 198 } 199 200 // If the agent is long live connection, it needs to restart the proxy to 201 // watch the guest console if it hadn't been watched. 202 if s.agent.longLiveConn() { 203 err = s.startProxy() 204 if err != nil { 205 s.Release() 206 return nil, err 207 } 208 } 209 210 return s, nil 211 } 212 213 // StartSandbox is the virtcontainers sandbox starting entry point. 214 // StartSandbox will talk to the given hypervisor to start an existing 215 // sandbox and all its containers. 216 // It returns the sandbox ID. 217 func StartSandbox(ctx context.Context, sandboxID string) (VCSandbox, error) { 218 span, ctx := trace(ctx, "StartSandbox") 219 defer span.Finish() 220 221 if sandboxID == "" { 222 return nil, vcTypes.ErrNeedSandboxID 223 } 224 225 unlock, err := rwLockSandbox(sandboxID) 226 if err != nil { 227 return nil, err 228 } 229 defer unlock() 230 231 // Fetch the sandbox from storage and create it. 232 s, err := fetchSandbox(ctx, sandboxID) 233 if err != nil { 234 return nil, err 235 } 236 defer s.releaseStatelessSandbox() 237 238 // Start it 239 err = s.Start() 240 if err != nil { 241 return nil, err 242 } 243 244 if err = s.storeSandbox(); err != nil { 245 return nil, err 246 } 247 248 return s, nil 249 } 250 251 // StopSandbox is the virtcontainers sandbox stopping entry point. 252 // StopSandbox will talk to the given agent to stop an existing sandbox and destroy all containers within that sandbox. 253 func StopSandbox(ctx context.Context, sandboxID string, force bool) (VCSandbox, error) { 254 span, ctx := trace(ctx, "StopSandbox") 255 defer span.Finish() 256 257 if sandboxID == "" { 258 return nil, vcTypes.ErrNeedSandbox 259 } 260 261 unlock, err := rwLockSandbox(sandboxID) 262 if err != nil { 263 return nil, err 264 } 265 defer unlock() 266 267 // Fetch the sandbox from storage and create it. 268 s, err := fetchSandbox(ctx, sandboxID) 269 if err != nil { 270 return nil, err 271 } 272 defer s.releaseStatelessSandbox() 273 274 // Stop it. 275 err = s.Stop(force) 276 if err != nil { 277 return nil, err 278 } 279 280 if err = s.storeSandbox(); err != nil { 281 return nil, err 282 } 283 284 return s, nil 285 } 286 287 // RunSandbox is the virtcontainers sandbox running entry point. 288 // RunSandbox creates a sandbox and its containers and then it starts them. 289 func RunSandbox(ctx context.Context, sandboxConfig SandboxConfig, factory Factory) (VCSandbox, error) { 290 span, ctx := trace(ctx, "RunSandbox") 291 defer span.Finish() 292 293 // Create the sandbox 294 s, err := createSandboxFromConfig(ctx, sandboxConfig, factory) 295 if err != nil { 296 return nil, err 297 } 298 defer s.releaseStatelessSandbox() 299 300 unlock, err := rwLockSandbox(s.id) 301 if err != nil { 302 return nil, err 303 } 304 defer unlock() 305 306 // Start the sandbox 307 err = s.Start() 308 if err != nil { 309 return nil, err 310 } 311 312 return s, nil 313 } 314 315 // ListSandbox is the virtcontainers sandbox listing entry point. 316 func ListSandbox(ctx context.Context) ([]SandboxStatus, error) { 317 span, ctx := trace(ctx, "ListSandbox") 318 defer span.Finish() 319 320 store, err := persist.GetDriver() 321 if err != nil { 322 return []SandboxStatus{}, err 323 } 324 325 dir, err := os.Open(store.RunStoragePath()) 326 if err != nil { 327 if os.IsNotExist(err) { 328 // No sandbox directory is not an error 329 return []SandboxStatus{}, nil 330 } 331 return []SandboxStatus{}, err 332 } 333 334 defer dir.Close() 335 336 sandboxesID, err := dir.Readdirnames(0) 337 if err != nil { 338 return []SandboxStatus{}, err 339 } 340 341 var sandboxStatusList []SandboxStatus 342 343 for _, sandboxID := range sandboxesID { 344 sandboxStatus, err := StatusSandbox(ctx, sandboxID) 345 if err != nil { 346 continue 347 } 348 349 sandboxStatusList = append(sandboxStatusList, sandboxStatus) 350 } 351 352 return sandboxStatusList, nil 353 } 354 355 // StatusSandbox is the virtcontainers sandbox status entry point. 356 func StatusSandbox(ctx context.Context, sandboxID string) (SandboxStatus, error) { 357 span, ctx := trace(ctx, "StatusSandbox") 358 defer span.Finish() 359 360 if sandboxID == "" { 361 return SandboxStatus{}, vcTypes.ErrNeedSandboxID 362 } 363 364 unlock, err := rwLockSandbox(sandboxID) 365 if err != nil { 366 return SandboxStatus{}, err 367 } 368 defer unlock() 369 370 s, err := fetchSandbox(ctx, sandboxID) 371 if err != nil { 372 return SandboxStatus{}, err 373 } 374 defer s.releaseStatelessSandbox() 375 376 var contStatusList []ContainerStatus 377 for _, container := range s.containers { 378 contStatus, err := statusContainer(s, container.id) 379 if err != nil { 380 return SandboxStatus{}, err 381 } 382 383 contStatusList = append(contStatusList, contStatus) 384 } 385 386 sandboxStatus := SandboxStatus{ 387 ID: s.id, 388 State: s.state, 389 Hypervisor: s.config.HypervisorType, 390 HypervisorConfig: s.config.HypervisorConfig, 391 Agent: s.config.AgentType, 392 ContainersStatus: contStatusList, 393 Annotations: s.config.Annotations, 394 } 395 396 return sandboxStatus, nil 397 } 398 399 // CreateContainer is the virtcontainers container creation entry point. 400 // CreateContainer creates a container on a given sandbox. 401 func CreateContainer(ctx context.Context, sandboxID string, containerConfig ContainerConfig) (VCSandbox, VCContainer, error) { 402 span, ctx := trace(ctx, "CreateContainer") 403 defer span.Finish() 404 405 if sandboxID == "" { 406 return nil, nil, vcTypes.ErrNeedSandboxID 407 } 408 409 unlock, err := rwLockSandbox(sandboxID) 410 if err != nil { 411 return nil, nil, err 412 } 413 defer unlock() 414 415 s, err := fetchSandbox(ctx, sandboxID) 416 if err != nil { 417 return nil, nil, err 418 } 419 defer s.releaseStatelessSandbox() 420 421 c, err := s.CreateContainer(containerConfig) 422 if err != nil { 423 return nil, nil, err 424 } 425 426 if err = s.storeSandbox(); err != nil { 427 return nil, nil, err 428 } 429 430 return s, c, nil 431 } 432 433 // DeleteContainer is the virtcontainers container deletion entry point. 434 // DeleteContainer deletes a Container from a Sandbox. If the container is running, 435 // it needs to be stopped first. 436 func DeleteContainer(ctx context.Context, sandboxID, containerID string) (VCContainer, error) { 437 span, ctx := trace(ctx, "DeleteContainer") 438 defer span.Finish() 439 440 if sandboxID == "" { 441 return nil, vcTypes.ErrNeedSandboxID 442 } 443 444 if containerID == "" { 445 return nil, vcTypes.ErrNeedContainerID 446 } 447 448 unlock, err := rwLockSandbox(sandboxID) 449 if err != nil { 450 return nil, err 451 } 452 defer unlock() 453 454 s, err := fetchSandbox(ctx, sandboxID) 455 if err != nil { 456 return nil, err 457 } 458 defer s.releaseStatelessSandbox() 459 460 return s.DeleteContainer(containerID) 461 } 462 463 // StartContainer is the virtcontainers container starting entry point. 464 // StartContainer starts an already created container. 465 func StartContainer(ctx context.Context, sandboxID, containerID string) (VCContainer, error) { 466 span, ctx := trace(ctx, "StartContainer") 467 defer span.Finish() 468 469 if sandboxID == "" { 470 return nil, vcTypes.ErrNeedSandboxID 471 } 472 473 if containerID == "" { 474 return nil, vcTypes.ErrNeedContainerID 475 } 476 477 unlock, err := rwLockSandbox(sandboxID) 478 if err != nil { 479 return nil, err 480 } 481 defer unlock() 482 483 s, err := fetchSandbox(ctx, sandboxID) 484 if err != nil { 485 return nil, err 486 } 487 defer s.releaseStatelessSandbox() 488 489 return s.StartContainer(containerID) 490 } 491 492 // StopContainer is the virtcontainers container stopping entry point. 493 // StopContainer stops an already running container. 494 func StopContainer(ctx context.Context, sandboxID, containerID string) (VCContainer, error) { 495 span, ctx := trace(ctx, "StopContainer") 496 defer span.Finish() 497 498 if sandboxID == "" { 499 return nil, vcTypes.ErrNeedSandboxID 500 } 501 502 if containerID == "" { 503 return nil, vcTypes.ErrNeedContainerID 504 } 505 506 unlock, err := rwLockSandbox(sandboxID) 507 if err != nil { 508 return nil, err 509 } 510 defer unlock() 511 512 s, err := fetchSandbox(ctx, sandboxID) 513 if err != nil { 514 return nil, err 515 } 516 defer s.releaseStatelessSandbox() 517 518 return s.StopContainer(containerID, false) 519 } 520 521 // EnterContainer is the virtcontainers container command execution entry point. 522 // EnterContainer enters an already running container and runs a given command. 523 func EnterContainer(ctx context.Context, sandboxID, containerID string, cmd types.Cmd) (VCSandbox, VCContainer, *Process, error) { 524 span, ctx := trace(ctx, "EnterContainer") 525 defer span.Finish() 526 527 if sandboxID == "" { 528 return nil, nil, nil, vcTypes.ErrNeedSandboxID 529 } 530 531 if containerID == "" { 532 return nil, nil, nil, vcTypes.ErrNeedContainerID 533 } 534 535 unlock, err := rLockSandbox(sandboxID) 536 if err != nil { 537 return nil, nil, nil, err 538 } 539 defer unlock() 540 541 s, err := fetchSandbox(ctx, sandboxID) 542 if err != nil { 543 return nil, nil, nil, err 544 } 545 defer s.releaseStatelessSandbox() 546 547 c, process, err := s.EnterContainer(containerID, cmd) 548 if err != nil { 549 return nil, nil, nil, err 550 } 551 552 return s, c, process, nil 553 } 554 555 // StatusContainer is the virtcontainers container status entry point. 556 // StatusContainer returns a detailed container status. 557 func StatusContainer(ctx context.Context, sandboxID, containerID string) (ContainerStatus, error) { 558 span, ctx := trace(ctx, "StatusContainer") 559 defer span.Finish() 560 561 if sandboxID == "" { 562 return ContainerStatus{}, vcTypes.ErrNeedSandboxID 563 } 564 565 if containerID == "" { 566 return ContainerStatus{}, vcTypes.ErrNeedContainerID 567 } 568 569 unlock, err := rwLockSandbox(sandboxID) 570 if err != nil { 571 return ContainerStatus{}, err 572 } 573 defer unlock() 574 575 s, err := fetchSandbox(ctx, sandboxID) 576 if err != nil { 577 return ContainerStatus{}, err 578 } 579 defer s.releaseStatelessSandbox() 580 581 return statusContainer(s, containerID) 582 } 583 584 // This function might have to stop the container if it realizes the shim 585 // process is not running anymore. This might be caused by two different 586 // reasons, either the process inside the VM exited and the shim terminated 587 // accordingly, or the shim has been killed directly and we need to make sure 588 // that we properly stop the container process inside the VM. 589 // 590 // When a container needs to be stopped because of those reasons, we want this 591 // to happen atomically from a sandbox perspective. That's why we cannot afford 592 // to take a read or read/write lock based on the situation, as it would break 593 // the initial locking from the caller. Instead, a read/write lock has to be 594 // taken from the caller, even if we simply return the container status without 595 // taking any action regarding the container. 596 func statusContainer(sandbox *Sandbox, containerID string) (ContainerStatus, error) { 597 if container, ok := sandbox.containers[containerID]; ok { 598 // We have to check for the process state to make sure 599 // we update the status in case the process is supposed 600 // to be running but has been killed or terminated. 601 if (container.state.State == types.StateReady || 602 container.state.State == types.StateRunning || 603 container.state.State == types.StatePaused) && 604 container.process.Pid > 0 { 605 606 running, err := isShimRunning(container.process.Pid) 607 if err != nil { 608 return ContainerStatus{}, err 609 } 610 611 if !running { 612 virtLog.WithFields(logrus.Fields{ 613 "state": container.state.State, 614 "pid": container.process.Pid}). 615 Info("container isn't running") 616 if err := container.stop(true); err != nil { 617 return ContainerStatus{}, err 618 } 619 } 620 } 621 622 return ContainerStatus{ 623 ID: container.id, 624 State: container.state, 625 PID: container.process.Pid, 626 StartTime: container.process.StartTime, 627 RootFs: container.config.RootFs.Target, 628 Spec: container.GetPatchedOCISpec(), 629 Annotations: container.config.Annotations, 630 }, nil 631 } 632 633 // No matching containers in the sandbox 634 return ContainerStatus{}, nil 635 } 636 637 // KillContainer is the virtcontainers entry point to send a signal 638 // to a container running inside a sandbox. If all is true, all processes in 639 // the container will be sent the signal. 640 func KillContainer(ctx context.Context, sandboxID, containerID string, signal syscall.Signal, all bool) error { 641 span, ctx := trace(ctx, "KillContainer") 642 defer span.Finish() 643 644 if sandboxID == "" { 645 return vcTypes.ErrNeedSandboxID 646 } 647 648 if containerID == "" { 649 return vcTypes.ErrNeedContainerID 650 } 651 652 unlock, err := rwLockSandbox(sandboxID) 653 if err != nil { 654 return err 655 } 656 defer unlock() 657 658 s, err := fetchSandbox(ctx, sandboxID) 659 if err != nil { 660 return err 661 } 662 defer s.releaseStatelessSandbox() 663 664 return s.KillContainer(containerID, signal, all) 665 } 666 667 // ProcessListContainer is the virtcontainers entry point to list 668 // processes running inside a container 669 func ProcessListContainer(ctx context.Context, sandboxID, containerID string, options ProcessListOptions) (ProcessList, error) { 670 span, ctx := trace(ctx, "ProcessListContainer") 671 defer span.Finish() 672 673 if sandboxID == "" { 674 return nil, vcTypes.ErrNeedSandboxID 675 } 676 677 if containerID == "" { 678 return nil, vcTypes.ErrNeedContainerID 679 } 680 681 unlock, err := rLockSandbox(sandboxID) 682 if err != nil { 683 return nil, err 684 } 685 defer unlock() 686 687 s, err := fetchSandbox(ctx, sandboxID) 688 if err != nil { 689 return nil, err 690 } 691 defer s.releaseStatelessSandbox() 692 693 return s.ProcessListContainer(containerID, options) 694 } 695 696 // UpdateContainer is the virtcontainers entry point to update 697 // container's resources. 698 func UpdateContainer(ctx context.Context, sandboxID, containerID string, resources specs.LinuxResources) error { 699 span, ctx := trace(ctx, "UpdateContainer") 700 defer span.Finish() 701 702 if sandboxID == "" { 703 return vcTypes.ErrNeedSandboxID 704 } 705 706 if containerID == "" { 707 return vcTypes.ErrNeedContainerID 708 } 709 710 unlock, err := rwLockSandbox(sandboxID) 711 if err != nil { 712 return err 713 } 714 defer unlock() 715 716 s, err := fetchSandbox(ctx, sandboxID) 717 if err != nil { 718 return err 719 } 720 defer s.releaseStatelessSandbox() 721 722 return s.UpdateContainer(containerID, resources) 723 } 724 725 // StatsContainer is the virtcontainers container stats entry point. 726 // StatsContainer returns a detailed container stats. 727 func StatsContainer(ctx context.Context, sandboxID, containerID string) (ContainerStats, error) { 728 span, ctx := trace(ctx, "StatsContainer") 729 defer span.Finish() 730 731 if sandboxID == "" { 732 return ContainerStats{}, vcTypes.ErrNeedSandboxID 733 } 734 735 if containerID == "" { 736 return ContainerStats{}, vcTypes.ErrNeedContainerID 737 } 738 739 unlock, err := rLockSandbox(sandboxID) 740 if err != nil { 741 return ContainerStats{}, err 742 } 743 defer unlock() 744 745 s, err := fetchSandbox(ctx, sandboxID) 746 if err != nil { 747 return ContainerStats{}, err 748 } 749 defer s.releaseStatelessSandbox() 750 751 return s.StatsContainer(containerID) 752 } 753 754 // StatsSandbox is the virtcontainers sandbox stats entry point. 755 // StatsSandbox returns a detailed sandbox stats. 756 func StatsSandbox(ctx context.Context, sandboxID string) (SandboxStats, []ContainerStats, error) { 757 span, ctx := trace(ctx, "StatsSandbox") 758 defer span.Finish() 759 760 if sandboxID == "" { 761 return SandboxStats{}, []ContainerStats{}, vcTypes.ErrNeedSandboxID 762 } 763 764 unlock, err := rLockSandbox(sandboxID) 765 if err != nil { 766 return SandboxStats{}, []ContainerStats{}, err 767 } 768 defer unlock() 769 770 s, err := fetchSandbox(ctx, sandboxID) 771 if err != nil { 772 return SandboxStats{}, []ContainerStats{}, err 773 } 774 defer s.releaseStatelessSandbox() 775 776 sandboxStats, err := s.Stats() 777 if err != nil { 778 return SandboxStats{}, []ContainerStats{}, err 779 } 780 781 containerStats := []ContainerStats{} 782 for _, c := range s.containers { 783 cstats, err := s.StatsContainer(c.id) 784 if err != nil { 785 return SandboxStats{}, []ContainerStats{}, err 786 } 787 containerStats = append(containerStats, cstats) 788 } 789 790 return sandboxStats, containerStats, nil 791 } 792 793 func togglePauseContainer(ctx context.Context, sandboxID, containerID string, pause bool) error { 794 if sandboxID == "" { 795 return vcTypes.ErrNeedSandboxID 796 } 797 798 if containerID == "" { 799 return vcTypes.ErrNeedContainerID 800 } 801 802 unlock, err := rwLockSandbox(sandboxID) 803 if err != nil { 804 return err 805 } 806 defer unlock() 807 808 s, err := fetchSandbox(ctx, sandboxID) 809 if err != nil { 810 return err 811 } 812 defer s.releaseStatelessSandbox() 813 814 if pause { 815 return s.PauseContainer(containerID) 816 } 817 818 return s.ResumeContainer(containerID) 819 } 820 821 // PauseContainer is the virtcontainers container pause entry point. 822 func PauseContainer(ctx context.Context, sandboxID, containerID string) error { 823 span, ctx := trace(ctx, "PauseContainer") 824 defer span.Finish() 825 826 return togglePauseContainer(ctx, sandboxID, containerID, true) 827 } 828 829 // ResumeContainer is the virtcontainers container resume entry point. 830 func ResumeContainer(ctx context.Context, sandboxID, containerID string) error { 831 span, ctx := trace(ctx, "ResumeContainer") 832 defer span.Finish() 833 834 return togglePauseContainer(ctx, sandboxID, containerID, false) 835 } 836 837 // AddDevice will add a device to sandbox 838 func AddDevice(ctx context.Context, sandboxID string, info deviceConfig.DeviceInfo) (deviceApi.Device, error) { 839 span, ctx := trace(ctx, "AddDevice") 840 defer span.Finish() 841 842 if sandboxID == "" { 843 return nil, vcTypes.ErrNeedSandboxID 844 } 845 846 unlock, err := rwLockSandbox(sandboxID) 847 if err != nil { 848 return nil, err 849 } 850 defer unlock() 851 852 s, err := fetchSandbox(ctx, sandboxID) 853 if err != nil { 854 return nil, err 855 } 856 defer s.releaseStatelessSandbox() 857 858 return s.AddDevice(info) 859 } 860 861 func toggleInterface(ctx context.Context, sandboxID string, inf *vcTypes.Interface, add bool) (*vcTypes.Interface, error) { 862 if sandboxID == "" { 863 return nil, vcTypes.ErrNeedSandboxID 864 } 865 866 unlock, err := rwLockSandbox(sandboxID) 867 if err != nil { 868 return nil, err 869 } 870 defer unlock() 871 872 s, err := fetchSandbox(ctx, sandboxID) 873 if err != nil { 874 return nil, err 875 } 876 defer s.releaseStatelessSandbox() 877 878 if add { 879 return s.AddInterface(inf) 880 } 881 882 return s.RemoveInterface(inf) 883 } 884 885 // AddInterface is the virtcontainers add interface entry point. 886 func AddInterface(ctx context.Context, sandboxID string, inf *vcTypes.Interface) (*vcTypes.Interface, error) { 887 span, ctx := trace(ctx, "AddInterface") 888 defer span.Finish() 889 890 return toggleInterface(ctx, sandboxID, inf, true) 891 } 892 893 // RemoveInterface is the virtcontainers remove interface entry point. 894 func RemoveInterface(ctx context.Context, sandboxID string, inf *vcTypes.Interface) (*vcTypes.Interface, error) { 895 span, ctx := trace(ctx, "RemoveInterface") 896 defer span.Finish() 897 898 return toggleInterface(ctx, sandboxID, inf, false) 899 } 900 901 // ListInterfaces is the virtcontainers list interfaces entry point. 902 func ListInterfaces(ctx context.Context, sandboxID string) ([]*vcTypes.Interface, error) { 903 span, ctx := trace(ctx, "ListInterfaces") 904 defer span.Finish() 905 906 if sandboxID == "" { 907 return nil, vcTypes.ErrNeedSandboxID 908 } 909 910 unlock, err := rLockSandbox(sandboxID) 911 if err != nil { 912 return nil, err 913 } 914 defer unlock() 915 916 s, err := fetchSandbox(ctx, sandboxID) 917 if err != nil { 918 return nil, err 919 } 920 defer s.releaseStatelessSandbox() 921 922 return s.ListInterfaces() 923 } 924 925 // UpdateRoutes is the virtcontainers update routes entry point. 926 func UpdateRoutes(ctx context.Context, sandboxID string, routes []*vcTypes.Route) ([]*vcTypes.Route, error) { 927 span, ctx := trace(ctx, "UpdateRoutes") 928 defer span.Finish() 929 930 if sandboxID == "" { 931 return nil, vcTypes.ErrNeedSandboxID 932 } 933 934 unlock, err := rwLockSandbox(sandboxID) 935 if err != nil { 936 return nil, err 937 } 938 defer unlock() 939 940 s, err := fetchSandbox(ctx, sandboxID) 941 if err != nil { 942 return nil, err 943 } 944 defer s.releaseStatelessSandbox() 945 946 return s.UpdateRoutes(routes) 947 } 948 949 // ListRoutes is the virtcontainers list routes entry point. 950 func ListRoutes(ctx context.Context, sandboxID string) ([]*vcTypes.Route, error) { 951 span, ctx := trace(ctx, "ListRoutes") 952 defer span.Finish() 953 954 if sandboxID == "" { 955 return nil, vcTypes.ErrNeedSandboxID 956 } 957 958 unlock, err := rLockSandbox(sandboxID) 959 if err != nil { 960 return nil, err 961 } 962 defer unlock() 963 964 s, err := fetchSandbox(ctx, sandboxID) 965 if err != nil { 966 return nil, err 967 } 968 defer s.releaseStatelessSandbox() 969 970 return s.ListRoutes() 971 } 972 973 // CleanupContaienr is used by shimv2 to stop and delete a container exclusively, once there is no container 974 // in the sandbox left, do stop the sandbox and delete it. Those serial operations will be done exclusively by 975 // locking the sandbox. 976 func CleanupContainer(ctx context.Context, sandboxID, containerID string, force bool) error { 977 span, ctx := trace(ctx, "CleanupContainer") 978 defer span.Finish() 979 980 if sandboxID == "" { 981 return vcTypes.ErrNeedSandboxID 982 } 983 984 if containerID == "" { 985 return vcTypes.ErrNeedContainerID 986 } 987 988 unlock, err := rwLockSandbox(sandboxID) 989 if err != nil { 990 return err 991 } 992 defer unlock() 993 994 s, err := fetchSandbox(ctx, sandboxID) 995 if err != nil { 996 return err 997 } 998 999 defer s.Release() 1000 1001 _, err = s.StopContainer(containerID, force) 1002 if err != nil && !force { 1003 return err 1004 } 1005 1006 _, err = s.DeleteContainer(containerID) 1007 if err != nil && !force { 1008 return err 1009 } 1010 1011 if len(s.GetAllContainers()) > 0 { 1012 return nil 1013 } 1014 1015 if err = s.Stop(force); err != nil && !force { 1016 return err 1017 } 1018 1019 if err = s.Delete(); err != nil { 1020 return err 1021 } 1022 1023 return nil 1024 }