github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/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/SagerNet/gvisor/pkg/log"
    21  	"github.com/SagerNet/gvisor/pkg/sentry/kernel"
    22  	"github.com/SagerNet/gvisor/pkg/sentry/state"
    23  	"github.com/SagerNet/gvisor/pkg/sentry/watchdog"
    24  	"github.com/SagerNet/gvisor/pkg/urpc"
    25  )
    26  
    27  // ErrInvalidFiles is returned when the urpc call to Save does not include an
    28  // appropriate file payload (e.g. there is no output file!).
    29  var ErrInvalidFiles = errors.New("exactly one file must be provided")
    30  
    31  // State includes state-related functions.
    32  type State struct {
    33  	Kernel   *kernel.Kernel
    34  	Watchdog *watchdog.Watchdog
    35  }
    36  
    37  // SaveOpts contains options for the Save RPC call.
    38  type SaveOpts struct {
    39  	// Key is used for state integrity check.
    40  	Key []byte `json:"key"`
    41  
    42  	// Metadata is the set of metadata to prepend to the state file.
    43  	Metadata map[string]string `json:"metadata"`
    44  
    45  	// FilePayload contains the destination for the state.
    46  	urpc.FilePayload
    47  }
    48  
    49  // Save saves the running system.
    50  func (s *State) Save(o *SaveOpts, _ *struct{}) error {
    51  	// Create an output stream.
    52  	if len(o.FilePayload.Files) != 1 {
    53  		return ErrInvalidFiles
    54  	}
    55  	defer o.FilePayload.Files[0].Close()
    56  
    57  	// Save to the first provided stream.
    58  	saveOpts := state.SaveOpts{
    59  		Destination: o.FilePayload.Files[0],
    60  		Key:         o.Key,
    61  		Metadata:    o.Metadata,
    62  		Callback: func(err error) {
    63  			if err == nil {
    64  				log.Infof("Save succeeded: exiting...")
    65  				s.Kernel.SetSaveSuccess(false /* autosave */)
    66  			} else {
    67  				log.Warningf("Save failed: exiting...")
    68  				s.Kernel.SetSaveError(err)
    69  			}
    70  			s.Kernel.Kill(kernel.ExitStatus{})
    71  		},
    72  	}
    73  	return saveOpts.Save(s.Kernel.SupervisorContext(), s.Kernel, s.Watchdog)
    74  }