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