...

Source file src/github.com/Microsoft/hcsshim/internal/resources/resources.go

Documentation: github.com/Microsoft/hcsshim/internal/resources

     1  //go:build windows
     2  
     3  package resources
     4  
     5  import (
     6  	"context"
     7  	"errors"
     8  
     9  	"github.com/Microsoft/hcsshim/internal/credentials"
    10  	"github.com/Microsoft/hcsshim/internal/log"
    11  	"github.com/Microsoft/hcsshim/internal/uvm"
    12  )
    13  
    14  // NetNS returns the network namespace for the container
    15  func (r *Resources) NetNS() string {
    16  	return r.netNS
    17  }
    18  
    19  // SetNetNS updates the container resource's NetNS
    20  func (r *Resources) SetNetNS(netNS string) {
    21  	r.netNS = netNS
    22  }
    23  
    24  // SetCreatedNetNS updates the container resource's CreatedNetNS value
    25  func (r *Resources) SetCreatedNetNS(created bool) {
    26  	r.createdNetNS = true
    27  }
    28  
    29  // ContainerRootInUVM returns the containerRootInUVM for the container
    30  func (r *Resources) ContainerRootInUVM() string {
    31  	return r.containerRootInUVM
    32  }
    33  
    34  // SetContainerRootInUVM updates the container resource's containerRootInUVM value
    35  func (r *Resources) SetContainerRootInUVM(containerRootInUVM string) {
    36  	r.containerRootInUVM = containerRootInUVM
    37  }
    38  
    39  // SetAddedNetNSToVM updates the container resource's AddedNetNSToVM value
    40  func (r *Resources) SetAddedNetNSToVM(addedNetNSToVM bool) {
    41  	r.addedNetNSToVM = addedNetNSToVM
    42  }
    43  
    44  func (r *Resources) SetLcowScratchPath(scratchPath string) {
    45  	r.lcowScratchPath = scratchPath
    46  }
    47  
    48  func (r *Resources) LcowScratchPath() string {
    49  	return r.lcowScratchPath
    50  }
    51  
    52  // SetLayers updates the container resource's image layers
    53  func (r *Resources) SetLayers(l ResourceCloser) {
    54  	r.layers = l
    55  }
    56  
    57  // Add adds one or more resource closers to the resources struct to be
    58  // tracked for release later on
    59  func (r *Resources) Add(newResources ...ResourceCloser) {
    60  	r.resources = append(r.resources, newResources...)
    61  }
    62  
    63  // Resources is the structure returned as part of creating a container. It holds
    64  // nothing useful to clients, hence everything is lowercased. A client would use
    65  // it in a call to ReleaseResources to ensure everything is cleaned up when a
    66  // container exits.
    67  type Resources struct {
    68  	id string
    69  	// containerRootInUVM is the base path in a utility VM where elements relating
    70  	// to a container are exposed. For example, the mounted filesystem; the runtime
    71  	// spec (in the case of LCOW); overlay and scratch (in the case of LCOW).
    72  	//
    73  	// For WCOW, this will be under wcowRootInUVM. For LCOW, this will be under
    74  	// lcowRootInUVM, this will also be the "OCI Bundle Path".
    75  	containerRootInUVM string
    76  	// lcowScratchPath represents the path inside the UVM at which the LCOW scratch
    77  	// directory is present.  Usually, this is the path at which the container scratch
    78  	// VHD is mounted inside the UVM (`containerRootInUVM`). But in case of scratch
    79  	// sharing this is a directory under the UVM scratch directory.
    80  	lcowScratchPath string
    81  
    82  	netNS string
    83  	// createNetNS indicates if the network namespace has been created
    84  	createdNetNS bool
    85  	// addedNetNSToVM indicates if the network namespace has been added to the containers utility VM
    86  	addedNetNSToVM bool
    87  	// layers is a pointer to a struct of the layers paths of a container
    88  	layers ResourceCloser
    89  	// resources is a slice of the resources associated with a container
    90  	resources []ResourceCloser
    91  }
    92  
    93  // ResourceCloser is a generic interface for the releasing of a resource. If a resource implements
    94  // this interface(which they all should), freeing of that resource should entail one call to
    95  // <resourceName>.Release(ctx)
    96  type ResourceCloser interface {
    97  	Release(context.Context) error
    98  }
    99  
   100  // NewContainerResources returns a new empty container Resources struct with the
   101  // given container id
   102  func NewContainerResources(id string) *Resources {
   103  	return &Resources{
   104  		id: id,
   105  	}
   106  }
   107  
   108  // ReleaseResources releases/frees all of the resources associated with a container. This includes
   109  // Plan9 shares, vsmb mounts, pipe mounts, network endpoints, scsi mounts, vpci devices and layers.
   110  // TODO: make method on Resources struct.
   111  func ReleaseResources(ctx context.Context, r *Resources, vm *uvm.UtilityVM, all bool) error {
   112  	if vm != nil {
   113  		if r.addedNetNSToVM {
   114  			if err := vm.TearDownNetworking(ctx, r.netNS); err != nil {
   115  				log.G(ctx).Warn(err)
   116  			}
   117  			r.addedNetNSToVM = false
   118  		}
   119  	}
   120  
   121  	releaseErr := false
   122  	// Release resources in reverse order so that the most recently
   123  	// added are cleaned up first. We don't return an error right away
   124  	// so that other resources still get cleaned up in the case of one
   125  	// or more failing.
   126  	for i := len(r.resources) - 1; i >= 0; i-- {
   127  		switch r.resources[i].(type) {
   128  		case *uvm.NetworkEndpoints:
   129  			if r.createdNetNS {
   130  				if err := r.resources[i].Release(ctx); err != nil {
   131  					log.G(ctx).WithError(err).Error("failed to release container resource")
   132  					releaseErr = true
   133  				}
   134  				r.createdNetNS = false
   135  			}
   136  		case *credentials.CCGResource:
   137  			if err := r.resources[i].Release(ctx); err != nil {
   138  				log.G(ctx).WithError(err).Error("failed to release container resource")
   139  				releaseErr = true
   140  			}
   141  		default:
   142  			// Don't need to check if vm != nil here anymore as they wouldnt
   143  			// have been added in the first place. All resources have embedded
   144  			// vm they belong to.
   145  			if all {
   146  				if err := r.resources[i].Release(ctx); err != nil {
   147  					log.G(ctx).WithError(err).Error("failed to release container resource")
   148  					releaseErr = true
   149  				}
   150  			}
   151  		}
   152  	}
   153  	r.resources = nil
   154  	if releaseErr {
   155  		return errors.New("failed to release one or more container resources")
   156  	}
   157  
   158  	if r.layers != nil {
   159  		if err := r.layers.Release(ctx); err != nil {
   160  			return err
   161  		}
   162  	}
   163  	return nil
   164  }
   165  

View as plain text