...

Source file src/github.com/Microsoft/hcsshim/container.go

Documentation: github.com/Microsoft/hcsshim

     1  //go:build windows
     2  
     3  package hcsshim
     4  
     5  import (
     6  	"context"
     7  	"fmt"
     8  	"os"
     9  	"sync"
    10  	"time"
    11  
    12  	"github.com/Microsoft/hcsshim/internal/hcs"
    13  	"github.com/Microsoft/hcsshim/internal/hcs/schema1"
    14  	"github.com/Microsoft/hcsshim/internal/mergemaps"
    15  )
    16  
    17  // ContainerProperties holds the properties for a container and the processes running in that container
    18  type ContainerProperties = schema1.ContainerProperties
    19  
    20  // MemoryStats holds the memory statistics for a container
    21  type MemoryStats = schema1.MemoryStats
    22  
    23  // ProcessorStats holds the processor statistics for a container
    24  type ProcessorStats = schema1.ProcessorStats
    25  
    26  // StorageStats holds the storage statistics for a container
    27  type StorageStats = schema1.StorageStats
    28  
    29  // NetworkStats holds the network statistics for a container
    30  type NetworkStats = schema1.NetworkStats
    31  
    32  // Statistics is the structure returned by a statistics call on a container
    33  type Statistics = schema1.Statistics
    34  
    35  // ProcessList is the structure of an item returned by a ProcessList call on a container
    36  type ProcessListItem = schema1.ProcessListItem
    37  
    38  // MappedVirtualDiskController is the structure of an item returned by a MappedVirtualDiskList call on a container
    39  type MappedVirtualDiskController = schema1.MappedVirtualDiskController
    40  
    41  // Type of Request Support in ModifySystem
    42  type RequestType = schema1.RequestType
    43  
    44  // Type of Resource Support in ModifySystem
    45  type ResourceType = schema1.ResourceType
    46  
    47  // RequestType const
    48  const (
    49  	Add     = schema1.Add
    50  	Remove  = schema1.Remove
    51  	Network = schema1.Network
    52  )
    53  
    54  // ResourceModificationRequestResponse is the structure used to send request to the container to modify the system
    55  // Supported resource types are Network and Request Types are Add/Remove
    56  type ResourceModificationRequestResponse = schema1.ResourceModificationRequestResponse
    57  
    58  type container struct {
    59  	system   *hcs.System
    60  	waitOnce sync.Once
    61  	waitErr  error
    62  	waitCh   chan struct{}
    63  }
    64  
    65  // createContainerAdditionalJSON is read from the environment at initialization
    66  // time. It allows an environment variable to define additional JSON which
    67  // is merged in the CreateComputeSystem call to HCS.
    68  var createContainerAdditionalJSON []byte
    69  
    70  func init() {
    71  	createContainerAdditionalJSON = ([]byte)(os.Getenv("HCSSHIM_CREATECONTAINER_ADDITIONALJSON"))
    72  }
    73  
    74  // CreateContainer creates a new container with the given configuration but does not start it.
    75  func CreateContainer(id string, c *ContainerConfig) (Container, error) {
    76  	fullConfig, err := mergemaps.MergeJSON(c, createContainerAdditionalJSON)
    77  	if err != nil {
    78  		return nil, fmt.Errorf("failed to merge additional JSON '%s': %s", createContainerAdditionalJSON, err)
    79  	}
    80  
    81  	system, err := hcs.CreateComputeSystem(context.Background(), id, fullConfig)
    82  	if err != nil {
    83  		return nil, err
    84  	}
    85  	return &container{system: system}, err
    86  }
    87  
    88  // OpenContainer opens an existing container by ID.
    89  func OpenContainer(id string) (Container, error) {
    90  	system, err := hcs.OpenComputeSystem(context.Background(), id)
    91  	if err != nil {
    92  		return nil, err
    93  	}
    94  	return &container{system: system}, err
    95  }
    96  
    97  // GetContainers gets a list of the containers on the system that match the query
    98  func GetContainers(q ComputeSystemQuery) ([]ContainerProperties, error) {
    99  	return hcs.GetComputeSystems(context.Background(), q)
   100  }
   101  
   102  // Start synchronously starts the container.
   103  func (container *container) Start() error {
   104  	return convertSystemError(container.system.Start(context.Background()), container)
   105  }
   106  
   107  // Shutdown requests a container shutdown, but it may not actually be shutdown until Wait() succeeds.
   108  func (container *container) Shutdown() error {
   109  	err := container.system.Shutdown(context.Background())
   110  	if err != nil {
   111  		return convertSystemError(err, container)
   112  	}
   113  	return &ContainerError{Container: container, Err: ErrVmcomputeOperationPending, Operation: "hcsshim::ComputeSystem::Shutdown"}
   114  }
   115  
   116  // Terminate requests a container terminate, but it may not actually be terminated until Wait() succeeds.
   117  func (container *container) Terminate() error {
   118  	err := container.system.Terminate(context.Background())
   119  	if err != nil {
   120  		return convertSystemError(err, container)
   121  	}
   122  	return &ContainerError{Container: container, Err: ErrVmcomputeOperationPending, Operation: "hcsshim::ComputeSystem::Terminate"}
   123  }
   124  
   125  // Waits synchronously waits for the container to shutdown or terminate.
   126  func (container *container) Wait() error {
   127  	err := container.system.Wait()
   128  	if err == nil {
   129  		err = container.system.ExitError()
   130  	}
   131  	return convertSystemError(err, container)
   132  }
   133  
   134  // WaitTimeout synchronously waits for the container to terminate or the duration to elapse. It
   135  // returns false if timeout occurs.
   136  func (container *container) WaitTimeout(timeout time.Duration) error {
   137  	container.waitOnce.Do(func() {
   138  		container.waitCh = make(chan struct{})
   139  		go func() {
   140  			container.waitErr = container.Wait()
   141  			close(container.waitCh)
   142  		}()
   143  	})
   144  	t := time.NewTimer(timeout)
   145  	defer t.Stop()
   146  	select {
   147  	case <-t.C:
   148  		return &ContainerError{Container: container, Err: ErrTimeout, Operation: "hcsshim::ComputeSystem::Wait"}
   149  	case <-container.waitCh:
   150  		return container.waitErr
   151  	}
   152  }
   153  
   154  // Pause pauses the execution of a container.
   155  func (container *container) Pause() error {
   156  	return convertSystemError(container.system.Pause(context.Background()), container)
   157  }
   158  
   159  // Resume resumes the execution of a container.
   160  func (container *container) Resume() error {
   161  	return convertSystemError(container.system.Resume(context.Background()), container)
   162  }
   163  
   164  // HasPendingUpdates returns true if the container has updates pending to install
   165  func (container *container) HasPendingUpdates() (bool, error) {
   166  	return false, nil
   167  }
   168  
   169  // Statistics returns statistics for the container. This is a legacy v1 call
   170  func (container *container) Statistics() (Statistics, error) {
   171  	properties, err := container.system.Properties(context.Background(), schema1.PropertyTypeStatistics)
   172  	if err != nil {
   173  		return Statistics{}, convertSystemError(err, container)
   174  	}
   175  
   176  	return properties.Statistics, nil
   177  }
   178  
   179  // ProcessList returns an array of ProcessListItems for the container. This is a legacy v1 call
   180  func (container *container) ProcessList() ([]ProcessListItem, error) {
   181  	properties, err := container.system.Properties(context.Background(), schema1.PropertyTypeProcessList)
   182  	if err != nil {
   183  		return nil, convertSystemError(err, container)
   184  	}
   185  
   186  	return properties.ProcessList, nil
   187  }
   188  
   189  // This is a legacy v1 call
   190  func (container *container) MappedVirtualDisks() (map[int]MappedVirtualDiskController, error) {
   191  	properties, err := container.system.Properties(context.Background(), schema1.PropertyTypeMappedVirtualDisk)
   192  	if err != nil {
   193  		return nil, convertSystemError(err, container)
   194  	}
   195  
   196  	return properties.MappedVirtualDiskControllers, nil
   197  }
   198  
   199  // CreateProcess launches a new process within the container.
   200  func (container *container) CreateProcess(c *ProcessConfig) (Process, error) {
   201  	p, err := container.system.CreateProcess(context.Background(), c)
   202  	if err != nil {
   203  		return nil, convertSystemError(err, container)
   204  	}
   205  	return &process{p: p.(*hcs.Process)}, nil
   206  }
   207  
   208  // OpenProcess gets an interface to an existing process within the container.
   209  func (container *container) OpenProcess(pid int) (Process, error) {
   210  	p, err := container.system.OpenProcess(context.Background(), pid)
   211  	if err != nil {
   212  		return nil, convertSystemError(err, container)
   213  	}
   214  	return &process{p: p}, nil
   215  }
   216  
   217  // Close cleans up any state associated with the container but does not terminate or wait for it.
   218  func (container *container) Close() error {
   219  	return convertSystemError(container.system.Close(), container)
   220  }
   221  
   222  // Modify the System
   223  func (container *container) Modify(config *ResourceModificationRequestResponse) error {
   224  	return convertSystemError(container.system.Modify(context.Background(), config), container)
   225  }
   226  

View as plain text