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  }