github.com/MerlinKodo/gvisor@v0.0.0-20231110090155-957f62ecf90e/pkg/sentry/control/state.go (about)

     1  // Copyright 2018 The gVisor Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package control
    16  
    17  import (
    18  	"errors"
    19  
    20  	"github.com/MerlinKodo/gvisor/pkg/abi/linux"
    21  	"github.com/MerlinKodo/gvisor/pkg/log"
    22  	"github.com/MerlinKodo/gvisor/pkg/sentry/kernel"
    23  	"github.com/MerlinKodo/gvisor/pkg/sentry/state"
    24  	"github.com/MerlinKodo/gvisor/pkg/sentry/watchdog"
    25  	"github.com/MerlinKodo/gvisor/pkg/urpc"
    26  )
    27  
    28  // ErrInvalidFiles is returned when the urpc call to Save does not include an
    29  // appropriate file payload (e.g. there is no output file!).
    30  var ErrInvalidFiles = errors.New("exactly one file must be provided")
    31  
    32  // State includes state-related functions.
    33  type State struct {
    34  	Kernel   *kernel.Kernel
    35  	Watchdog *watchdog.Watchdog
    36  }
    37  
    38  // SaveOpts contains options for the Save RPC call.
    39  type SaveOpts struct {
    40  	// Key is used for state integrity check.
    41  	Key []byte `json:"key"`
    42  
    43  	// Metadata is the set of metadata to prepend to the state file.
    44  	Metadata map[string]string `json:"metadata"`
    45  
    46  	// FilePayload contains the destination for the state.
    47  	urpc.FilePayload
    48  }
    49  
    50  // Save saves the running system.
    51  func (s *State) Save(o *SaveOpts, _ *struct{}) error {
    52  	// Create an output stream.
    53  	if len(o.FilePayload.Files) != 1 {
    54  		return ErrInvalidFiles
    55  	}
    56  	defer o.FilePayload.Files[0].Close()
    57  
    58  	// Save to the first provided stream.
    59  	saveOpts := state.SaveOpts{
    60  		Destination: o.FilePayload.Files[0],
    61  		Key:         o.Key,
    62  		Metadata:    o.Metadata,
    63  		Callback: func(err error) {
    64  			if err == nil {
    65  				log.Infof("Save succeeded: exiting...")
    66  				s.Kernel.SetSaveSuccess(false /* autosave */)
    67  			} else {
    68  				log.Warningf("Save failed: exiting...")
    69  				s.Kernel.SetSaveError(err)
    70  			}
    71  			s.Kernel.Kill(linux.WaitStatusExit(0))
    72  		},
    73  	}
    74  	return saveOpts.Save(s.Kernel.SupervisorContext(), s.Kernel, s.Watchdog)
    75  }