mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-19 09:52:49 +00:00
This tag of hcsshim brings in a couple welcome features/improvements. One being exposing a way to query for hns endpoint statistics (Packets received/sent etc.). This tag also contains some optimizations for querying whether a certain HCN feature is supported, which is a common workflow in kube-proxy on Windows. The first result from querying HCN is now cached so further calls can skip the hcn query as well as the version range parsing that was performed. This also gets rid of some redundant logs that used to hit everytime the version range parsing occurred. The Go-winio dep bump, and all of the ctrd deps are transitive only. Nothing new is needed/intended to be used. Signed-off-by: Daniel Canter <dcanter@microsoft.com>
224 lines
7.6 KiB
Go
224 lines
7.6 KiB
Go
package hcsshim
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/Microsoft/hcsshim/internal/hcs"
|
|
"github.com/Microsoft/hcsshim/internal/hcs/schema1"
|
|
"github.com/Microsoft/hcsshim/internal/mergemaps"
|
|
)
|
|
|
|
// ContainerProperties holds the properties for a container and the processes running in that container
|
|
type ContainerProperties = schema1.ContainerProperties
|
|
|
|
// MemoryStats holds the memory statistics for a container
|
|
type MemoryStats = schema1.MemoryStats
|
|
|
|
// ProcessorStats holds the processor statistics for a container
|
|
type ProcessorStats = schema1.ProcessorStats
|
|
|
|
// StorageStats holds the storage statistics for a container
|
|
type StorageStats = schema1.StorageStats
|
|
|
|
// NetworkStats holds the network statistics for a container
|
|
type NetworkStats = schema1.NetworkStats
|
|
|
|
// Statistics is the structure returned by a statistics call on a container
|
|
type Statistics = schema1.Statistics
|
|
|
|
// ProcessList is the structure of an item returned by a ProcessList call on a container
|
|
type ProcessListItem = schema1.ProcessListItem
|
|
|
|
// MappedVirtualDiskController is the structure of an item returned by a MappedVirtualDiskList call on a container
|
|
type MappedVirtualDiskController = schema1.MappedVirtualDiskController
|
|
|
|
// Type of Request Support in ModifySystem
|
|
type RequestType = schema1.RequestType
|
|
|
|
// Type of Resource Support in ModifySystem
|
|
type ResourceType = schema1.ResourceType
|
|
|
|
// RequestType const
|
|
const (
|
|
Add = schema1.Add
|
|
Remove = schema1.Remove
|
|
Network = schema1.Network
|
|
)
|
|
|
|
// ResourceModificationRequestResponse is the structure used to send request to the container to modify the system
|
|
// Supported resource types are Network and Request Types are Add/Remove
|
|
type ResourceModificationRequestResponse = schema1.ResourceModificationRequestResponse
|
|
|
|
type container struct {
|
|
system *hcs.System
|
|
waitOnce sync.Once
|
|
waitErr error
|
|
waitCh chan struct{}
|
|
}
|
|
|
|
// createComputeSystemAdditionalJSON is read from the environment at initialisation
|
|
// time. It allows an environment variable to define additional JSON which
|
|
// is merged in the CreateComputeSystem call to HCS.
|
|
var createContainerAdditionalJSON []byte
|
|
|
|
func init() {
|
|
createContainerAdditionalJSON = ([]byte)(os.Getenv("HCSSHIM_CREATECONTAINER_ADDITIONALJSON"))
|
|
}
|
|
|
|
// CreateContainer creates a new container with the given configuration but does not start it.
|
|
func CreateContainer(id string, c *ContainerConfig) (Container, error) {
|
|
fullConfig, err := mergemaps.MergeJSON(c, createContainerAdditionalJSON)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to merge additional JSON '%s': %s", createContainerAdditionalJSON, err)
|
|
}
|
|
|
|
system, err := hcs.CreateComputeSystem(context.Background(), id, fullConfig)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &container{system: system}, err
|
|
}
|
|
|
|
// OpenContainer opens an existing container by ID.
|
|
func OpenContainer(id string) (Container, error) {
|
|
system, err := hcs.OpenComputeSystem(context.Background(), id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &container{system: system}, err
|
|
}
|
|
|
|
// GetContainers gets a list of the containers on the system that match the query
|
|
func GetContainers(q ComputeSystemQuery) ([]ContainerProperties, error) {
|
|
return hcs.GetComputeSystems(context.Background(), q)
|
|
}
|
|
|
|
// Start synchronously starts the container.
|
|
func (container *container) Start() error {
|
|
return convertSystemError(container.system.Start(context.Background()), container)
|
|
}
|
|
|
|
// Shutdown requests a container shutdown, but it may not actually be shutdown until Wait() succeeds.
|
|
func (container *container) Shutdown() error {
|
|
err := container.system.Shutdown(context.Background())
|
|
if err != nil {
|
|
return convertSystemError(err, container)
|
|
}
|
|
return &ContainerError{Container: container, Err: ErrVmcomputeOperationPending, Operation: "hcsshim::ComputeSystem::Shutdown"}
|
|
}
|
|
|
|
// Terminate requests a container terminate, but it may not actually be terminated until Wait() succeeds.
|
|
func (container *container) Terminate() error {
|
|
err := container.system.Terminate(context.Background())
|
|
if err != nil {
|
|
return convertSystemError(err, container)
|
|
}
|
|
return &ContainerError{Container: container, Err: ErrVmcomputeOperationPending, Operation: "hcsshim::ComputeSystem::Terminate"}
|
|
}
|
|
|
|
// Waits synchronously waits for the container to shutdown or terminate.
|
|
func (container *container) Wait() error {
|
|
err := container.system.Wait()
|
|
if err == nil {
|
|
err = container.system.ExitError()
|
|
}
|
|
return convertSystemError(err, container)
|
|
}
|
|
|
|
// WaitTimeout synchronously waits for the container to terminate or the duration to elapse. It
|
|
// returns false if timeout occurs.
|
|
func (container *container) WaitTimeout(timeout time.Duration) error {
|
|
container.waitOnce.Do(func() {
|
|
container.waitCh = make(chan struct{})
|
|
go func() {
|
|
container.waitErr = container.Wait()
|
|
close(container.waitCh)
|
|
}()
|
|
})
|
|
t := time.NewTimer(timeout)
|
|
defer t.Stop()
|
|
select {
|
|
case <-t.C:
|
|
return &ContainerError{Container: container, Err: ErrTimeout, Operation: "hcsshim::ComputeSystem::Wait"}
|
|
case <-container.waitCh:
|
|
return container.waitErr
|
|
}
|
|
}
|
|
|
|
// Pause pauses the execution of a container.
|
|
func (container *container) Pause() error {
|
|
return convertSystemError(container.system.Pause(context.Background()), container)
|
|
}
|
|
|
|
// Resume resumes the execution of a container.
|
|
func (container *container) Resume() error {
|
|
return convertSystemError(container.system.Resume(context.Background()), container)
|
|
}
|
|
|
|
// HasPendingUpdates returns true if the container has updates pending to install
|
|
func (container *container) HasPendingUpdates() (bool, error) {
|
|
return false, nil
|
|
}
|
|
|
|
// Statistics returns statistics for the container. This is a legacy v1 call
|
|
func (container *container) Statistics() (Statistics, error) {
|
|
properties, err := container.system.Properties(context.Background(), schema1.PropertyTypeStatistics)
|
|
if err != nil {
|
|
return Statistics{}, convertSystemError(err, container)
|
|
}
|
|
|
|
return properties.Statistics, nil
|
|
}
|
|
|
|
// ProcessList returns an array of ProcessListItems for the container. This is a legacy v1 call
|
|
func (container *container) ProcessList() ([]ProcessListItem, error) {
|
|
properties, err := container.system.Properties(context.Background(), schema1.PropertyTypeProcessList)
|
|
if err != nil {
|
|
return nil, convertSystemError(err, container)
|
|
}
|
|
|
|
return properties.ProcessList, nil
|
|
}
|
|
|
|
// This is a legacy v1 call
|
|
func (container *container) MappedVirtualDisks() (map[int]MappedVirtualDiskController, error) {
|
|
properties, err := container.system.Properties(context.Background(), schema1.PropertyTypeMappedVirtualDisk)
|
|
if err != nil {
|
|
return nil, convertSystemError(err, container)
|
|
}
|
|
|
|
return properties.MappedVirtualDiskControllers, nil
|
|
}
|
|
|
|
// CreateProcess launches a new process within the container.
|
|
func (container *container) CreateProcess(c *ProcessConfig) (Process, error) {
|
|
p, err := container.system.CreateProcess(context.Background(), c)
|
|
if err != nil {
|
|
return nil, convertSystemError(err, container)
|
|
}
|
|
return &process{p: p.(*hcs.Process)}, nil
|
|
}
|
|
|
|
// OpenProcess gets an interface to an existing process within the container.
|
|
func (container *container) OpenProcess(pid int) (Process, error) {
|
|
p, err := container.system.OpenProcess(context.Background(), pid)
|
|
if err != nil {
|
|
return nil, convertSystemError(err, container)
|
|
}
|
|
return &process{p: p}, nil
|
|
}
|
|
|
|
// Close cleans up any state associated with the container but does not terminate or wait for it.
|
|
func (container *container) Close() error {
|
|
return convertSystemError(container.system.Close(), container)
|
|
}
|
|
|
|
// Modify the System
|
|
func (container *container) Modify(config *ResourceModificationRequestResponse) error {
|
|
return convertSystemError(container.system.Modify(context.Background(), config), container)
|
|
}
|