...

Source file src/github.com/Microsoft/hcsshim/internal/guest/prot/protocol.go

Documentation: github.com/Microsoft/hcsshim/internal/guest/prot

     1  // Package prot defines any structures used in the communication between the HCS
     2  // and the GCS. Some of these structures are also used outside the bridge as
     3  // good ways of packaging parameters to core calls.
     4  package prot
     5  
     6  import (
     7  	"encoding/json"
     8  	"strconv"
     9  
    10  	v1 "github.com/containerd/cgroups/stats/v1"
    11  	oci "github.com/opencontainers/runtime-spec/specs-go"
    12  	"github.com/pkg/errors"
    13  
    14  	"github.com/Microsoft/hcsshim/internal/guest/commonutils"
    15  	hcsschema "github.com/Microsoft/hcsshim/internal/hcs/schema2"
    16  	"github.com/Microsoft/hcsshim/internal/protocol/guestrequest"
    17  	"github.com/Microsoft/hcsshim/internal/protocol/guestresource"
    18  )
    19  
    20  //////////// Code for the Message Header ////////////
    21  // Message Identifiers as present in the message header are subdivided into
    22  // various pieces of information.
    23  //
    24  // +---+----+-----+----+
    25  // | T | CC | III | VV |
    26  // +---+----+-----+----+
    27  //
    28  // T   - 4 Bits    Type
    29  // CC  - 8 Bits    Category
    30  // III - 12 Bits   Message Id
    31  // VV  - 8 Bits    Version
    32  
    33  const (
    34  	messageTypeMask     = 0xF0000000
    35  	messageCategoryMask = 0x0FF00000
    36  	messageIDMask       = 0x000FFF00
    37  	messageVersionMask  = 0x000000FF
    38  	messageIDShift      = 8
    39  	messageVersionShift = 0
    40  )
    41  
    42  // MessageType is the type of the message.
    43  type MessageType uint32
    44  
    45  const (
    46  	// MtNone is the default MessageType.
    47  	MtNone = 0
    48  	// MtRequest is the MessageType when a request is received.
    49  	MtRequest = 0x10000000
    50  	// MtResponse is the MessageType used to send a response.
    51  	MtResponse = 0x20000000
    52  	// MtNotification is the MessageType used to send a notification not
    53  	// initiated by a request.
    54  	MtNotification = 0x30000000
    55  )
    56  
    57  // MessageCategory allows splitting the identifier namespace to easily route
    58  // similar messages for common processing.
    59  type MessageCategory uint32
    60  
    61  const (
    62  	// McNone is the default category.
    63  	McNone = 0
    64  	// McComputeSystem is the category to define message types for compute
    65  	// systems.
    66  	McComputeSystem = 0x00100000
    67  )
    68  
    69  // GetResponseIdentifier returns the response version of the given request
    70  // identifier. So, for example, an input of ComputeSystemCreateV1 would result
    71  // in an output of ComputeSystemResponseCreateV1.
    72  func GetResponseIdentifier(identifier MessageIdentifier) MessageIdentifier {
    73  	return MessageIdentifier(MtResponse | (uint32(identifier) & ^uint32(messageTypeMask)))
    74  }
    75  
    76  // MessageIdentifier describes the Type field of a MessageHeader struct.
    77  type MessageIdentifier uint32
    78  
    79  const (
    80  	// MiNone is the unknown identifier.
    81  	MiNone = 0
    82  
    83  	// ComputeSystemCreateV1 is the create container request.
    84  	ComputeSystemCreateV1 = 0x10100101
    85  	// ComputeSystemStartV1 is the start container request.
    86  	ComputeSystemStartV1 = 0x10100201
    87  	// ComputeSystemShutdownGracefulV1 is the graceful shutdown container
    88  	// request.
    89  	ComputeSystemShutdownGracefulV1 = 0x10100301
    90  	// ComputeSystemShutdownForcedV1 is the forceful shutdown container request.
    91  	ComputeSystemShutdownForcedV1 = 0x10100401
    92  	// ComputeSystemExecuteProcessV1 is the execute process request.
    93  	ComputeSystemExecuteProcessV1 = 0x10100501
    94  	// ComputeSystemWaitForProcessV1 is the wait for process exit request.
    95  	ComputeSystemWaitForProcessV1 = 0x10100601
    96  	// ComputeSystemSignalProcessV1 is the signal process request.
    97  	ComputeSystemSignalProcessV1 = 0x10100701
    98  	// ComputeSystemResizeConsoleV1 is the resize console tty request.
    99  	ComputeSystemResizeConsoleV1 = 0x10100801
   100  	// ComputeSystemGetPropertiesV1 is the list process properties request.
   101  	ComputeSystemGetPropertiesV1 = 0x10100901
   102  	// ComputeSystemModifySettingsV1 is the modify container request.
   103  	ComputeSystemModifySettingsV1 = 0x10100a01
   104  	// ComputeSystemNegotiateProtocolV1 is the protocol negotiation request.
   105  	ComputeSystemNegotiateProtocolV1 = 0x10100b01
   106  	// ComputeSystemDumpStacksV1 is the dump stack request
   107  	ComputeSystemDumpStacksV1 = 0x10100c01
   108  	// ComputeSystemDeleteContainerStateV1 is the delete container request.
   109  	ComputeSystemDeleteContainerStateV1 = 0x10100d01
   110  
   111  	// ComputeSystemResponseCreateV1 is the create container response.
   112  	ComputeSystemResponseCreateV1 = 0x20100101
   113  	// ComputeSystemResponseStartV1 is the start container response.
   114  	ComputeSystemResponseStartV1 = 0x20100201
   115  	// ComputeSystemResponseShutdownGracefulV1 is the graceful shutdown
   116  	// container response.
   117  	ComputeSystemResponseShutdownGracefulV1 = 0x20100301
   118  	// ComputeSystemResponseShutdownForcedV1 is the forceful shutdown container
   119  	// response.
   120  	ComputeSystemResponseShutdownForcedV1 = 0x20100401
   121  	// ComputeSystemResponseExecuteProcessV1 is the execute process response.
   122  	ComputeSystemResponseExecuteProcessV1 = 0x20100501
   123  	// ComputeSystemResponseWaitForProcessV1 is the wait for process exit
   124  	// response.
   125  	ComputeSystemResponseWaitForProcessV1 = 0x20100601
   126  	// ComputeSystemResponseSignalProcessV1 is the signal process response.
   127  	ComputeSystemResponseSignalProcessV1 = 0x20100701
   128  	// ComputeSystemResponseResizeConsoleV1 is the resize console tty response.
   129  	ComputeSystemResponseResizeConsoleV1 = 0x20100801
   130  	// ComputeSystemResponseGetPropertiesV1 is the list process properties
   131  	// response.
   132  	ComputeSystemResponseGetPropertiesV1 = 0x20100901
   133  	// ComputeSystemResponseModifySettingsV1 is the modify container response.
   134  	ComputeSystemResponseModifySettingsV1 = 0x20100a01
   135  	// ComputeSystemResponseNegotiateProtocolV1 is the protocol negotiation
   136  	// response.
   137  	ComputeSystemResponseNegotiateProtocolV1 = 0x20100b01
   138  	// ComputeSystemResponseDumpStacksV1 is the dump stack response
   139  	ComputeSystemResponseDumpStacksV1 = 0x20100c01
   140  
   141  	// ComputeSystemNotificationV1 is the notification identifier.
   142  	ComputeSystemNotificationV1 = 0x30100101
   143  )
   144  
   145  // String returns the string representation of the message identifier.
   146  func (mi MessageIdentifier) String() string {
   147  	switch mi {
   148  	case MiNone:
   149  		return "None"
   150  	case ComputeSystemCreateV1:
   151  		return "ComputeSystemCreateV1"
   152  	case ComputeSystemStartV1:
   153  		return "ComputeSystemStartV1"
   154  	case ComputeSystemShutdownGracefulV1:
   155  		return "ComputeSystemShutdownGracefulV1"
   156  	case ComputeSystemShutdownForcedV1:
   157  		return "ComputeSystemShutdownForcedV1"
   158  	case ComputeSystemExecuteProcessV1:
   159  		return "ComputeSystemExecuteProcessV1"
   160  	case ComputeSystemWaitForProcessV1:
   161  		return "ComputeSystemWaitForProcessV1"
   162  	case ComputeSystemSignalProcessV1:
   163  		return "ComputeSystemSignalProcessV1"
   164  	case ComputeSystemResizeConsoleV1:
   165  		return "ComputeSystemResizeConsoleV1"
   166  	case ComputeSystemGetPropertiesV1:
   167  		return "ComputeSystemGetPropertiesV1"
   168  	case ComputeSystemModifySettingsV1:
   169  		return "ComputeSystemModifySettingsV1"
   170  	case ComputeSystemNegotiateProtocolV1:
   171  		return "ComputeSystemNegotiateProtocolV1"
   172  	case ComputeSystemDumpStacksV1:
   173  		return "ComputeSystemDumpStacksV1"
   174  	case ComputeSystemDeleteContainerStateV1:
   175  		return "ComputeSystemDeleteContainerStateV1"
   176  	case ComputeSystemResponseCreateV1:
   177  		return "ComputeSystemResponseCreateV1"
   178  	case ComputeSystemResponseStartV1:
   179  		return "ComputeSystemResponseStartV1"
   180  	case ComputeSystemResponseShutdownGracefulV1:
   181  		return "ComputeSystemResponseShutdownGracefulV1"
   182  	case ComputeSystemResponseShutdownForcedV1:
   183  		return "ComputeSystemResponseShutdownForcedV1"
   184  	case ComputeSystemResponseExecuteProcessV1:
   185  		return "ComputeSystemResponseExecuteProcessV1"
   186  	case ComputeSystemResponseWaitForProcessV1:
   187  		return "ComputeSystemResponseWaitForProcessV1"
   188  	case ComputeSystemResponseSignalProcessV1:
   189  		return "ComputeSystemResponseSignalProcessV1"
   190  	case ComputeSystemResponseResizeConsoleV1:
   191  		return "ComputeSystemResponseResizeConsoleV1"
   192  	case ComputeSystemResponseGetPropertiesV1:
   193  		return "ComputeSystemResponseGetPropertiesV1"
   194  	case ComputeSystemResponseModifySettingsV1:
   195  		return "ComputeSystemResponseModifySettingsV1"
   196  	case ComputeSystemResponseNegotiateProtocolV1:
   197  		return "ComputeSystemResponseNegotiateProtocolV1"
   198  	case ComputeSystemResponseDumpStacksV1:
   199  		return "ComputeSystemResponseDumpStacksV1"
   200  	case ComputeSystemNotificationV1:
   201  		return "ComputeSystemNotificationV1"
   202  	default:
   203  		return strconv.FormatUint(uint64(mi), 10)
   204  	}
   205  }
   206  
   207  // SequenceID is used to correlate requests and responses.
   208  type SequenceID uint64
   209  
   210  // MessageHeader is the common header present in all communications messages.
   211  type MessageHeader struct {
   212  	Type MessageIdentifier
   213  	Size uint32
   214  	ID   SequenceID
   215  }
   216  
   217  // MessageHeaderSize is the size in bytes of the MessageHeader struct.
   218  const MessageHeaderSize = 16
   219  
   220  /////////////////////////////////////////////////////
   221  
   222  // ProtocolVersion is a type for the selected HCS<->GCS protocol version of
   223  // messages
   224  type ProtocolVersion uint32
   225  
   226  // Protocol versions.
   227  const (
   228  	PvInvalid ProtocolVersion = 0
   229  	PvV4      ProtocolVersion = 4
   230  	PvMax     ProtocolVersion = PvV4
   231  )
   232  
   233  // ProtocolSupport specifies the protocol versions to be used for HCS-GCS
   234  // communication.
   235  type ProtocolSupport struct {
   236  	MinimumVersion         string `json:",omitempty"`
   237  	MaximumVersion         string `json:",omitempty"`
   238  	MinimumProtocolVersion uint32
   239  	MaximumProtocolVersion uint32
   240  }
   241  
   242  // OsType defines the operating system type identifier of the guest hosting the
   243  // GCS.
   244  type OsType string
   245  
   246  // OsTypeLinux is the OS type the HCS expects for a Linux GCS
   247  const OsTypeLinux OsType = "Linux"
   248  
   249  // GcsCapabilities specifies the abilities and scenarios supported by this GCS.
   250  type GcsCapabilities struct {
   251  	// True if a create message should be sent for the hosting system itself.
   252  	SendHostCreateMessage bool `json:",omitempty"`
   253  	// True if a start message should be sent for the hosting system itself. If
   254  	// SendHostCreateMessage is false, a start message will not be sent either.
   255  	SendHostStartMessage bool `json:",omitempty"`
   256  	// True if an HVSocket ModifySettings request should be sent immediately
   257  	// after the create/start messages are sent (if they're sent at all). This
   258  	// ModifySettings request would be to configure the local and parent
   259  	// Hyper-V socket addresses of the VM, and would have a RequestType of
   260  	// Update.
   261  	HVSocketConfigOnStartup bool            `json:"HvSocketConfigOnStartup,omitempty"`
   262  	SupportedSchemaVersions []SchemaVersion `json:",omitempty"`
   263  	RuntimeOsType           OsType          `json:",omitempty"`
   264  	// GuestDefinedCapabilities define any JSON object that will be directly
   265  	// passed to a client of the HCS. This can be useful to pass runtime
   266  	// specific capabilities not tied to the platform itself.
   267  	GuestDefinedCapabilities GcsGuestCapabilities `json:",omitempty"`
   268  }
   269  
   270  // GcsGuestCapabilities represents the customized guest capabilities supported
   271  // by this GCS.
   272  type GcsGuestCapabilities struct {
   273  	NamespaceAddRequestSupported  bool `json:",omitempty"`
   274  	SignalProcessSupported        bool `json:",omitempty"`
   275  	DumpStacksSupported           bool `json:",omitempty"`
   276  	DeleteContainerStateSupported bool `json:",omitempty"`
   277  }
   278  
   279  // ocspancontext is the internal JSON representation of the OpenCensus
   280  // `trace.SpanContext` for fowarding to a GCS that supports it.
   281  type ocspancontext struct {
   282  	// TraceID is the `hex` encoded string of the OpenCensus
   283  	// `SpanContext.TraceID` to propagate to the guest.
   284  	TraceID string `json:",omitempty"`
   285  	// SpanID is the `hex` encoded string of the OpenCensus `SpanContext.SpanID`
   286  	// to propagate to the guest.
   287  	SpanID string `json:",omitempty"`
   288  
   289  	// TraceOptions is the OpenCensus `SpanContext.TraceOptions` passed through
   290  	// to propagate to the guest.
   291  	TraceOptions uint32 `json:",omitempty"`
   292  
   293  	// Tracestate is the `base64` encoded string of marshaling the OpenCensus
   294  	// `SpanContext.TraceState.Entries()` to JSON.
   295  	//
   296  	// If `SpanContext.Tracestate == nil ||
   297  	// len(SpanContext.Tracestate.Entries()) == 0` this will be `""`.
   298  	Tracestate string `json:",omitempty"`
   299  }
   300  
   301  // MessageBase is the base type embedded in all messages sent from the HCS to
   302  // the GCS, as well as ContainerNotification which is sent from GCS to HCS.
   303  type MessageBase struct {
   304  	ContainerID string `json:"ContainerId"`
   305  	ActivityID  string `json:"ActivityId"`
   306  
   307  	// OpenCensusSpanContext is the encoded OpenCensus `trace.SpanContext` if
   308  	// set when making the request.
   309  	//
   310  	// NOTE: This is not a part of the protocol but because its a JSON protocol
   311  	// adding fields is a non-breaking change. If the guest supports it this is
   312  	// just additive context.
   313  	OpenCensusSpanContext *ocspancontext `json:"ocsc,omitempty"`
   314  }
   315  
   316  // NegotiateProtocol is the message from the HCS used to determine the protocol
   317  // version that will be used for future communication.
   318  type NegotiateProtocol struct {
   319  	MessageBase
   320  	MinimumVersion uint32
   321  	MaximumVersion uint32
   322  }
   323  
   324  // ContainerCreate is the message from the HCS specifying to create a container
   325  // in the utility VM. This message won't actually create a Linux container
   326  // inside the utility VM, but will set up the infrustructure needed to start one
   327  // once the container's initial process is executed.
   328  type ContainerCreate struct {
   329  	MessageBase
   330  	ContainerConfig   string
   331  	SupportedVersions ProtocolSupport `json:",omitempty"`
   332  }
   333  
   334  // NotificationType defines a type of notification to be sent back to the HCS.
   335  type NotificationType string
   336  
   337  const (
   338  	// NtNone indicates nothing to be sent back to the HCS
   339  	NtNone = NotificationType("None")
   340  	// NtGracefulExit indicates a graceful exit notification to be sent back to
   341  	// the HCS
   342  	NtGracefulExit = NotificationType("GracefulExit")
   343  	// NtForcedExit indicates a forced exit notification to be sent back to the
   344  	// HCS
   345  	NtForcedExit = NotificationType("ForcedExit")
   346  	// NtUnexpectedExit indicates an unexpected exit notification to be sent
   347  	// back to the HCS
   348  	NtUnexpectedExit = NotificationType("UnexpectedExit")
   349  	// NtReboot indicates a reboot notification to be sent back to the HCS
   350  	NtReboot = NotificationType("Reboot")
   351  	// NtConstructed indicates a constructed notification to be sent back to the
   352  	// HCS
   353  	NtConstructed = NotificationType("Constructed")
   354  	// NtStarted indicates a started notification to be sent back to the HCS
   355  	NtStarted = NotificationType("Started")
   356  	// NtPaused indicates a paused notification to be sent back to the HCS
   357  	NtPaused = NotificationType("Paused")
   358  	// NtUnknown indicates an unknown notification to be sent back to the HCS
   359  	NtUnknown = NotificationType("Unknown")
   360  )
   361  
   362  // ActiveOperation defines an operation to be associated with a notification
   363  // sent back to the HCS.
   364  type ActiveOperation string
   365  
   366  const (
   367  	// AoNone indicates no active operation
   368  	AoNone = ActiveOperation("None")
   369  	// AoConstruct indicates a construct active operation
   370  	AoConstruct = ActiveOperation("Construct")
   371  	// AoStart indicates a start active operation
   372  	AoStart = ActiveOperation("Start")
   373  	// AoPause indicates a pause active operation
   374  	AoPause = ActiveOperation("Pause")
   375  	// AoResume indicates a resume active operation
   376  	AoResume = ActiveOperation("Resume")
   377  	// AoShutdown indicates a shutdown active operation
   378  	AoShutdown = ActiveOperation("Shutdown")
   379  	// AoTerminate indicates a terminate active operation
   380  	AoTerminate = ActiveOperation("Terminate")
   381  )
   382  
   383  // ContainerNotification is a message sent from the GCS to the HCS to indicate
   384  // some kind of event. At the moment, it is only used for container exit
   385  // notifications.
   386  type ContainerNotification struct {
   387  	MessageBase
   388  	Type       NotificationType
   389  	Operation  ActiveOperation
   390  	Result     int32
   391  	ResultInfo string `json:",omitempty"`
   392  }
   393  
   394  // ExecuteProcessVsockStdioRelaySettings defines the port numbers for each
   395  // stdio socket for a process.
   396  type ExecuteProcessVsockStdioRelaySettings struct {
   397  	StdIn  uint32 `json:",omitempty"`
   398  	StdOut uint32 `json:",omitempty"`
   399  	StdErr uint32 `json:",omitempty"`
   400  }
   401  
   402  // ExecuteProcessSettings defines the settings for a single process to be
   403  // executed either inside or outside the container namespace.
   404  type ExecuteProcessSettings struct {
   405  	ProcessParameters       string
   406  	VsockStdioRelaySettings ExecuteProcessVsockStdioRelaySettings
   407  }
   408  
   409  // ContainerExecuteProcess is the message from the HCS specifying to execute a
   410  // process either inside or outside the container namespace.
   411  type ContainerExecuteProcess struct {
   412  	MessageBase
   413  	Settings ExecuteProcessSettings
   414  }
   415  
   416  // ContainerResizeConsole is the message from the HCS specifying to change the
   417  // console size for the given process.
   418  type ContainerResizeConsole struct {
   419  	MessageBase
   420  	ProcessID uint32 `json:"ProcessId"`
   421  	Height    uint16
   422  	Width     uint16
   423  }
   424  
   425  // ContainerWaitForProcess is the message from the HCS specifying to wait until
   426  // the given process exits. After receiving this message, the corresponding
   427  // response should not be sent until the process has exited.
   428  type ContainerWaitForProcess struct {
   429  	MessageBase
   430  	ProcessID   uint32 `json:"ProcessId"`
   431  	TimeoutInMs uint32
   432  }
   433  
   434  // InfiniteWaitTimeout is the value for ContainerWaitForProcess.TimeoutInMs that
   435  // indicates that no timeout should be in effect.
   436  const InfiniteWaitTimeout = 0xffffffff
   437  
   438  // ContainerSignalProcess is the message from the HCS specifying to send a
   439  // signal to the given process.
   440  type ContainerSignalProcess struct {
   441  	MessageBase
   442  	ProcessID uint32               `json:"ProcessId"`
   443  	Options   SignalProcessOptions `json:",omitempty"`
   444  }
   445  
   446  // ContainerGetProperties is the message from the HCS requesting certain
   447  // properties of the container, such as a list of its processes.
   448  type ContainerGetProperties struct {
   449  	MessageBase
   450  	Query string
   451  }
   452  
   453  // PropertyType is the type of property, such as memory or virtual disk, which
   454  // is to be modified for the container.
   455  type PropertyType string
   456  
   457  const (
   458  	// PtMemory is the property type for memory
   459  	PtMemory = PropertyType("Memory")
   460  	// PtCPUGroup is the property type for CPU group
   461  	PtCPUGroup = PropertyType("CpuGroup")
   462  	// PtStatistics is the property type for statistics
   463  	PtStatistics = PropertyType("Statistics")
   464  	// PtProcessList is the property type for a process list
   465  	PtProcessList = PropertyType("ProcessList")
   466  	// PtPendingUpdates is the property type for determining if there are
   467  	// pending updates
   468  	PtPendingUpdates = PropertyType("PendingUpdates")
   469  	// PtTerminateOnLastHandleClosed is the property type for exiting when the
   470  	// last handle is closed
   471  	PtTerminateOnLastHandleClosed = PropertyType("TerminateOnLastHandleClosed")
   472  	// PtMappedDirectory is the property type for mapped directories
   473  	PtMappedDirectory = PropertyType("MappedDirectory")
   474  	// PtSystemGUID is the property type for the system GUID
   475  	PtSystemGUID = PropertyType("SystemGUID")
   476  	// PtNetwork is the property type for networking
   477  	PtNetwork = PropertyType("Network")
   478  	// PtMappedPipe is the property type for mapped pipes
   479  	PtMappedPipe = PropertyType("MappedPipe")
   480  	// PtMappedVirtualDisk is the property type for mapped virtual disks
   481  	PtMappedVirtualDisk = PropertyType("MappedVirtualDisk")
   482  )
   483  
   484  // RequestType is the type of operation to perform on a given property type.
   485  type RequestType string
   486  
   487  const (
   488  	// RtAdd is the "Add" request type of operation
   489  	RtAdd = RequestType("Add")
   490  	// RtRemove is the "Remove" request type of operation
   491  	RtRemove = RequestType("Remove")
   492  	// RtUpdate is the "Update" request type of operation
   493  	RtUpdate = RequestType("Update")
   494  )
   495  
   496  // ResourceModificationRequestResponse details a container resource which should
   497  // be modified, how, and with what parameters.
   498  type ResourceModificationRequestResponse struct {
   499  	ResourceType PropertyType
   500  	RequestType  RequestType `json:",omitempty"`
   501  	Settings     interface{} `json:",omitempty"`
   502  }
   503  
   504  // ContainerModifySettings is the message from the HCS specifying how a certain
   505  // container resource should be modified.
   506  type ContainerModifySettings struct {
   507  	MessageBase
   508  	Request interface{}
   509  }
   510  
   511  // UnmarshalContainerModifySettings unmarshals the given bytes into a
   512  // ContainerModifySettings message. This function is required because properties
   513  // such as `Settings` can be of many types identified by the `ResourceType` and
   514  // require dynamic unmarshalling.
   515  func UnmarshalContainerModifySettings(b []byte) (*ContainerModifySettings, error) {
   516  	// Unmarshal the message.
   517  	var request ContainerModifySettings
   518  	var requestRawSettings json.RawMessage
   519  	request.Request = &requestRawSettings
   520  	if err := commonutils.UnmarshalJSONWithHresult(b, &request); err != nil {
   521  		return nil, errors.Wrap(err, "failed to unmarshal ContainerModifySettings")
   522  	}
   523  
   524  	var msr guestrequest.ModificationRequest
   525  	var msrRawSettings json.RawMessage
   526  	msr.Settings = &msrRawSettings
   527  	if err := commonutils.UnmarshalJSONWithHresult(requestRawSettings, &msr); err != nil {
   528  		return &request, errors.Wrap(err, "failed to unmarshal request.Settings as ModifySettingRequest")
   529  	}
   530  
   531  	if msr.RequestType == "" {
   532  		msr.RequestType = guestrequest.RequestTypeAdd
   533  	}
   534  
   535  	// Fill in the ResourceType-specific fields.
   536  	switch msr.ResourceType {
   537  	case guestresource.ResourceTypeSCSIDevice:
   538  		msd := &guestresource.SCSIDevice{}
   539  		if err := commonutils.UnmarshalJSONWithHresult(msrRawSettings, msd); err != nil {
   540  			return &request, errors.Wrap(err, "failed to unmarshal settings as SCSIDevice")
   541  		}
   542  		msr.Settings = msd
   543  	case guestresource.ResourceTypeMappedVirtualDisk:
   544  		mvd := &guestresource.LCOWMappedVirtualDisk{}
   545  		if err := commonutils.UnmarshalJSONWithHresult(msrRawSettings, mvd); err != nil {
   546  			return &request, errors.Wrap(err, "failed to unmarshal settings as MappedVirtualDiskV2")
   547  		}
   548  		msr.Settings = mvd
   549  	case guestresource.ResourceTypeMappedDirectory:
   550  		md := &guestresource.LCOWMappedDirectory{}
   551  		if err := commonutils.UnmarshalJSONWithHresult(msrRawSettings, md); err != nil {
   552  			return &request, errors.Wrap(err, "failed to unmarshal settings as MappedDirectoryV2")
   553  		}
   554  		msr.Settings = md
   555  	case guestresource.ResourceTypeVPMemDevice:
   556  		vpd := &guestresource.LCOWMappedVPMemDevice{}
   557  		if err := commonutils.UnmarshalJSONWithHresult(msrRawSettings, vpd); err != nil {
   558  			return &request, errors.Wrap(err, "failed to unmarshal hosted settings as MappedVPMemDeviceV2")
   559  		}
   560  		msr.Settings = vpd
   561  	case guestresource.ResourceTypeCombinedLayers:
   562  		cl := &guestresource.LCOWCombinedLayers{}
   563  		if err := commonutils.UnmarshalJSONWithHresult(msrRawSettings, cl); err != nil {
   564  			return &request, errors.Wrap(err, "failed to unmarshal settings as CombinedLayersV2")
   565  		}
   566  		msr.Settings = cl
   567  	case guestresource.ResourceTypeNetwork:
   568  		na := &guestresource.LCOWNetworkAdapter{}
   569  		if err := commonutils.UnmarshalJSONWithHresult(msrRawSettings, na); err != nil {
   570  			return &request, errors.Wrap(err, "failed to unmarshal settings as NetworkAdapterV2")
   571  		}
   572  		msr.Settings = na
   573  	case guestresource.ResourceTypeVPCIDevice:
   574  		vd := &guestresource.LCOWMappedVPCIDevice{}
   575  		if err := commonutils.UnmarshalJSONWithHresult(msrRawSettings, vd); err != nil {
   576  			return &request, errors.Wrap(err, "failed to unmarshal settings as MappedVPCIDeviceV2")
   577  		}
   578  		msr.Settings = vd
   579  	case guestresource.ResourceTypeContainerConstraints:
   580  		cc := &guestresource.LCOWContainerConstraints{}
   581  		if err := commonutils.UnmarshalJSONWithHresult(msrRawSettings, cc); err != nil {
   582  			return &request, errors.Wrap(err, "failed to unmarshal settings as ContainerConstraintsV2")
   583  		}
   584  		msr.Settings = cc
   585  	case guestresource.ResourceTypeSecurityPolicy:
   586  		enforcer := &guestresource.LCOWConfidentialOptions{}
   587  		if err := commonutils.UnmarshalJSONWithHresult(msrRawSettings, enforcer); err != nil {
   588  			return &request, errors.Wrap(err, "failed to unmarshal settings as LCOWConfidentialOptions")
   589  		}
   590  		msr.Settings = enforcer
   591  	case guestresource.ResourceTypePolicyFragment:
   592  		fragment := &guestresource.LCOWSecurityPolicyFragment{}
   593  		if err := commonutils.UnmarshalJSONWithHresult(msrRawSettings, fragment); err != nil {
   594  			return &request, errors.Wrap(err, "failed to unmarshal settings as LCOWSecurityPolicyFragment")
   595  		}
   596  		msr.Settings = fragment
   597  	default:
   598  		return &request, errors.Errorf("invalid ResourceType '%s'", msr.ResourceType)
   599  	}
   600  	request.Request = &msr
   601  	return &request, nil
   602  }
   603  
   604  // ErrorRecord represents a single error to be reported back to the HCS. It
   605  // allows for specifying information about the source of the error, as well as
   606  // an error message and stack trace.
   607  type ErrorRecord struct {
   608  	Result       int32
   609  	Message      string
   610  	StackTrace   string `json:",omitempty"`
   611  	ModuleName   string
   612  	FileName     string
   613  	Line         uint32
   614  	FunctionName string `json:",omitempty"`
   615  }
   616  
   617  // MessageResponseBase is the base type embedded in all messages sent from the
   618  // GCS to the HCS except for ContainerNotification.
   619  type MessageResponseBase struct {
   620  	Result       int32
   621  	ActivityID   string        `json:"ActivityId,omitempty"`
   622  	ErrorMessage string        `json:",omitempty"` // Only used by hcsshim external bridge
   623  	ErrorRecords []ErrorRecord `json:",omitempty"`
   624  }
   625  
   626  // Base returns the response base by reference.
   627  func (mrp *MessageResponseBase) Base() *MessageResponseBase {
   628  	return mrp
   629  }
   630  
   631  // NegotiateProtocolResponse is the message to the HCS responding to a
   632  // NegotiateProtocol message. It specifies the preferred protocol version and
   633  // available capabilities of the GCS.
   634  type NegotiateProtocolResponse struct {
   635  	MessageResponseBase
   636  	Version      uint32
   637  	Capabilities GcsCapabilities
   638  }
   639  
   640  type DumpStacksResponse struct {
   641  	MessageResponseBase
   642  	GuestStacks string
   643  }
   644  
   645  // ContainerCreateResponse is the message to the HCS responding to a
   646  // ContainerCreate message. It serves a protocol negotiation function as well
   647  // for protocol versions 3 and lower, returning protocol version information to
   648  // the HCS.
   649  type ContainerCreateResponse struct {
   650  	MessageResponseBase
   651  	SelectedVersion         string `json:",omitempty"`
   652  	SelectedProtocolVersion uint32
   653  }
   654  
   655  // ContainerExecuteProcessResponse is the message to the HCS responding to a
   656  // ContainerExecuteProcess message. It provides back the process's pid.
   657  type ContainerExecuteProcessResponse struct {
   658  	MessageResponseBase
   659  	ProcessID uint32 `json:"ProcessId"`
   660  }
   661  
   662  // ContainerWaitForProcessResponse is the message to the HCS responding to a
   663  // ContainerWaitForProcess message. It is only sent when the process has exited.
   664  type ContainerWaitForProcessResponse struct {
   665  	MessageResponseBase
   666  	ExitCode uint32
   667  }
   668  
   669  // ContainerGetPropertiesResponse is the message to the HCS responding to a
   670  // ContainerGetProperties message. It contains a string representing the
   671  // properties requested.
   672  type ContainerGetPropertiesResponse struct {
   673  	MessageResponseBase
   674  	Properties string
   675  }
   676  
   677  /* types added on to the current official protocol types */
   678  
   679  // NetworkAdapter represents a network interface and its associated
   680  // configuration.
   681  type NetworkAdapter struct {
   682  	AdapterInstanceID    string `json:"AdapterInstanceId"`
   683  	FirewallEnabled      bool
   684  	NatEnabled           bool
   685  	MacAddress           string `json:",omitempty"`
   686  	AllocatedIPAddress   string `json:"AllocatedIpAddress,omitempty"`
   687  	HostIPAddress        string `json:"HostIpAddress,omitempty"`
   688  	HostIPPrefixLength   uint8  `json:"HostIpPrefixLength,omitempty"`
   689  	AllocatedIPv6Address string `json:"AllocatedIpv6Address,omitempty"`
   690  	HostIPv6Address      string `json:"HostIpv6Address,omitempty"`
   691  	HostIPv6PrefixLength uint8  `json:"HostIpv6PrefixLength,omitempty"`
   692  	HostDNSServerList    string `json:"HostDnsServerList,omitempty"`
   693  	HostDNSSuffix        string `json:"HostDnsSuffix,omitempty"`
   694  	EnableLowMetric      bool   `json:",omitempty"`
   695  	EncapOverhead        uint16 `json:",omitempty"`
   696  }
   697  
   698  // MappedVirtualDisk represents a disk on the host which is mapped into a
   699  // directory in the guest.
   700  type MappedVirtualDisk struct {
   701  	ContainerPath     string
   702  	Lun               uint8 `json:",omitempty"`
   703  	CreateInUtilityVM bool  `json:",omitempty"`
   704  	ReadOnly          bool  `json:",omitempty"`
   705  	AttachOnly        bool  `json:",omitempty"`
   706  }
   707  
   708  // MappedDirectory represents a directory on the host which is mapped to a
   709  // directory on the guest through a technology such as Plan9.
   710  type MappedDirectory struct {
   711  	ContainerPath     string
   712  	CreateInUtilityVM bool   `json:",omitempty"`
   713  	ReadOnly          bool   `json:",omitempty"`
   714  	Port              uint32 `json:",omitempty"`
   715  }
   716  
   717  // VMHostedContainerSettings is the set of settings used to specify the initial
   718  // configuration of a container.
   719  type VMHostedContainerSettings struct {
   720  	Layers []hcsschema.Layer
   721  	// SandboxDataPath is in this case the identifier (such as the SCSI number)
   722  	// of the sandbox device.
   723  	SandboxDataPath    string
   724  	MappedVirtualDisks []MappedVirtualDisk
   725  	MappedDirectories  []MappedDirectory
   726  	NetworkAdapters    []NetworkAdapter `json:",omitempty"`
   727  }
   728  
   729  // SchemaVersion defines the version of the schema that should be deserialized.
   730  type SchemaVersion struct {
   731  	Major uint32 `json:",omitempty"`
   732  	Minor uint32 `json:",omitempty"`
   733  }
   734  
   735  // Cmp compares s and v and returns:
   736  //
   737  //	-1 if s <  v
   738  //	0 if s == v
   739  //	1 if s >  v
   740  func (s *SchemaVersion) Cmp(v SchemaVersion) int {
   741  	if s.Major == v.Major {
   742  		if s.Minor == v.Minor {
   743  			return 0
   744  		} else if s.Minor < v.Minor {
   745  			return -1
   746  		}
   747  		return 1
   748  	} else if s.Major < v.Major {
   749  		return -1
   750  	}
   751  	return 1
   752  }
   753  
   754  // VMHostedContainerSettingsV2 defines the portion of the
   755  // ContainerCreate.ContainerConfig that is sent via a V2 call. This correlates
   756  // to the 'HostedSystem' on the HCS side but rather than sending the 'Container'
   757  // field the Linux GCS accepts an oci.Spec directly.
   758  type VMHostedContainerSettingsV2 struct {
   759  	SchemaVersion    SchemaVersion
   760  	OCIBundlePath    string    `json:"OciBundlePath,omitempty"`
   761  	OCISpecification *oci.Spec `json:"OciSpecification,omitempty"`
   762  	// ScratchDirPath represents the path inside the UVM at which the container scratch
   763  	// directory is present.  Usually, this is the path at which the container scratch
   764  	// VHD is mounted inside the UVM. But in case of scratch sharing this is a
   765  	// directory under the UVM scratch directory.
   766  	ScratchDirPath string
   767  }
   768  
   769  // ProcessParameters represents any process which may be started in the utility
   770  // VM. This covers three cases:
   771  // 1.) It is an external process, i.e. a process running inside the utility VM
   772  // but not inside any container. In this case, don't specify the
   773  // OCISpecification field, but specify all other fields.
   774  // 2.) It is the first process in a container. In this case, specify only the
   775  // OCISpecification field, and not the other fields.
   776  // 3.) It is a container process, but not the first process in that container.
   777  // In this case, don't specify the OCISpecification field, but specify all
   778  // other fields. This is the same as if it were an external process.
   779  type ProcessParameters struct {
   780  	// CommandLine is a space separated list of command line parameters. For
   781  	// example, the command which sleeps for 100 seconds would be represented by
   782  	// the CommandLine string "sleep 100".
   783  	CommandLine string `json:",omitempty"`
   784  	// CommandArgs is a list of strings representing the command to execute. If
   785  	// it is not empty, it will be used by the GCS. If it is empty, CommandLine
   786  	// will be used instead.
   787  	CommandArgs      []string          `json:",omitempty"`
   788  	WorkingDirectory string            `json:",omitempty"`
   789  	Environment      map[string]string `json:",omitempty"`
   790  	EmulateConsole   bool              `json:",omitempty"`
   791  	CreateStdInPipe  bool              `json:",omitempty"`
   792  	CreateStdOutPipe bool              `json:",omitempty"`
   793  	CreateStdErrPipe bool              `json:",omitempty"`
   794  	// If IsExternal is false, the process will be created inside a container.
   795  	// If true, it will be created external to any container. The latter is
   796  	// useful if, for example, you want to start up a shell in the utility VM
   797  	// for debugging/diagnostic purposes.
   798  	IsExternal bool `json:"CreateInUtilityVM,omitempty"`
   799  	// If this is the first process created for this container, this field must
   800  	// be specified. Otherwise, it must be left blank and the other fields must
   801  	// be specified.
   802  	OCISpecification *oci.Spec `json:"OciSpecification,omitempty"`
   803  
   804  	OCIProcess *oci.Process `json:"OciProcess,omitempty"`
   805  }
   806  
   807  // SignalProcessOptions represents the options for signaling a process.
   808  type SignalProcessOptions struct {
   809  	Signal int32
   810  }
   811  
   812  // ProcessDetails represents information about a given process.
   813  type ProcessDetails struct {
   814  	ProcessID uint32 `json:"ProcessId"`
   815  }
   816  
   817  // PropertyQuery is a query to specify which properties are requested.
   818  type PropertyQuery struct {
   819  	PropertyTypes []PropertyType `json:",omitempty"`
   820  }
   821  
   822  // Properties represents the properties of a compute system.
   823  type Properties struct {
   824  	ProcessList []ProcessDetails `json:",omitempty"`
   825  }
   826  
   827  type PropertiesV2 struct {
   828  	ProcessList []ProcessDetails `json:"ProcessList,omitempty"`
   829  	Metrics     *v1.Metrics      `json:"LCOWMetrics,omitempty"`
   830  }
   831  

View as plain text