summaryrefslogtreecommitdiffhomepage
path: root/runsc/fsgofer/control.go
diff options
context:
space:
mode:
Diffstat (limited to 'runsc/fsgofer/control.go')
-rw-r--r--runsc/fsgofer/control.go204
1 files changed, 0 insertions, 204 deletions
diff --git a/runsc/fsgofer/control.go b/runsc/fsgofer/control.go
deleted file mode 100644
index 8cb2f67ac..000000000
--- a/runsc/fsgofer/control.go
+++ /dev/null
@@ -1,204 +0,0 @@
-// Copyright 2018 Google Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package fsgofer
-
-import (
- "fmt"
- "os"
- "path/filepath"
- "sync"
-
- "gvisor.googlesource.com/gvisor/pkg/control/server"
- "gvisor.googlesource.com/gvisor/pkg/log"
- "gvisor.googlesource.com/gvisor/pkg/p9"
- "gvisor.googlesource.com/gvisor/pkg/unet"
- "gvisor.googlesource.com/gvisor/pkg/urpc"
-)
-
-// Controller manages the fsgofer's control server.
-type Controller struct {
- // api holds the control server's URPC endpoints.
- api api
-
- // srv is the control server.
- srv *server.Server
-}
-
-// NewController creates a new Controller and starts it listenting
-func NewController(fd int, rootBundleDir string) (*Controller, error) {
- if !filepath.IsAbs(rootBundleDir) {
- return nil, fmt.Errorf("NewController should receive an absolute bundle dir path, but got %q", rootBundleDir)
- }
-
- srv, err := server.CreateFromFD(fd)
- if err != nil {
- return nil, err
- }
-
- cr := &Controller{srv: srv}
- cr.api.rootBundleDir = rootBundleDir
- cr.api.bundleDirs = make(map[string]string)
- srv.Register(&cr.api)
-
- if err := srv.StartServing(); err != nil {
- return nil, err
- }
-
- return cr, nil
-}
-
-// Wait waits for all the p9 servers to finish, then shuts down the control
-// server.
-func (cr *Controller) Wait() {
- cr.api.p9wg.Wait()
- cr.srv.Stop()
- log.Infof("All 9P servers exited.")
-}
-
-// Serve starts serving each Attacher in ats via its corresponding file
-// descriptor in ioFDs. This takes ownership of the FDs in ioFDs.
-func (cr *Controller) Serve(ats []p9.Attacher, ioFDs []int) error {
- if len(ats) != len(ioFDs) {
- return fmt.Errorf("number of attach points does not match the number of IO FDs (%d and %d)", len(ats), len(ioFDs))
- }
- for i, _ := range ats {
- cr.api.serve(ats[i], os.NewFile(uintptr(ioFDs[i]), "io fd"))
- }
- return nil
-}
-
-// api URPC methods.
-const (
- // AddBundleDirs readies the gofer to serve from a new bundle
- // directory. It should be called during runsc create.
- AddBundleDirs = "api.AddBundleDirs"
-
- // ServeDirectory serves a new directory via the fsgofer. It should be
- // called during runsc start.
- ServeDirectory = "api.ServeDirectory"
-)
-
-// API defines and implements the URPC endpoints for the gofer.
-type api struct {
- // p9wg waits for all the goroutines serving the sentry via p9. When its
- // counter is 0, the gofer is out of work and exits.
- p9wg sync.WaitGroup
-
- // bundleDirs maps from container ID to bundle directory for each
- // container.
- bundleDirs map[string]string
-
- // rootBundleDir is the bundle directory of the root container.
- rootBundleDir string
-}
-
-// AddBundleDirsRequest is the URPC argument to AddBundleDirs.
-type AddBundleDirsRequest struct {
- // BundleDirs is a map of container IDs to bundle directories to add to
- // the gofer.
- BundleDirs map[string]string
-}
-
-// AddBundleDirsRequest adds bundle directories that for the gofer to serve.
-func (api *api) AddBundleDirs(req *AddBundleDirsRequest, _ *struct{}) error {
- log.Debugf("fsgofer.AddBundleDirs")
- for cid, bd := range req.BundleDirs {
- if _, ok := api.bundleDirs[cid]; ok {
- return fmt.Errorf("fsgofer already has a bundleDir for container %q", cid)
- }
- api.bundleDirs[cid] = bd
- }
- return nil
-}
-
-// ServeDirectoryRequest is the URPC argument to ServeDirectory.
-type ServeDirectoryRequest struct {
- // Dir is the absolute path to a directory to be served to the sentry.
- Dir string
-
- // IsReadOnly specifies whether the directory should be served in
- // read-only mode.
- IsReadOnly bool
-
- // CID is the container ID of the container that needs to serve a
- // directory.
- CID string
-
- // FilePayload contains the socket over which the sentry will request
- // files from Dir.
- urpc.FilePayload
-}
-
-// ServeDirectory begins serving a directory via a file descriptor for the
-// sentry. Directories must be added via AddBundleDirsRequest before
-// ServeDirectory is called.
-func (api *api) ServeDirectory(req *ServeDirectoryRequest, _ *struct{}) error {
- log.Debugf("fsgofer.ServeDirectory: %+v", req)
-
- if req.Dir == "" {
- return fmt.Errorf("ServeDirectory should receive a directory argument, but was empty")
- }
- if req.CID == "" {
- return fmt.Errorf("ServeDirectory should receive a CID argument, but was empty")
- }
- // Prevent CIDs containing ".." from confusing the sentry when creating
- // /containers/<cid> directory.
- // TODO: Once we have multiple independant roots, this
- // check won't be necessary.
- if filepath.Clean(req.CID) != req.CID {
- return fmt.Errorf("container ID shouldn't contain directory traversals such as \"..\": %q", req.CID)
- }
- if nFiles := len(req.FilePayload.Files); nFiles != 1 {
- return fmt.Errorf("ServeDirectory should receive 1 file descriptor, but got %d", nFiles)
- }
-
- bd, ok := api.bundleDirs[req.CID]
- if !ok {
- // If there's no entry in bundleDirs for the container ID, this
- // is the root container.
- bd = api.rootBundleDir
- }
-
- // Relative paths are served relative to the bundle directory.
- absDir := req.Dir
- if !filepath.IsAbs(absDir) {
- absDir = filepath.Join(bd, req.Dir)
- }
-
- // Create the attach point and start serving.
- at := NewAttachPoint(absDir, Config{
- ROMount: req.IsReadOnly,
- LazyOpenForWrite: true,
- })
- api.serve(at, req.FilePayload.Files[0])
-
- return nil
-}
-
-// serve begins serving a directory via a file descriptor.
-func (api *api) serve(at p9.Attacher, ioFile *os.File) {
- api.p9wg.Add(1)
- go func() {
- socket, err := unet.NewSocket(int(ioFile.Fd()))
- if err != nil {
- panic(fmt.Sprintf("err creating server on FD %d: %v", ioFile.Fd(), err))
- }
- s := p9.NewServer(at)
- if err := s.Handle(socket); err != nil {
- panic(fmt.Sprintf("P9 server returned error. Gofer is shutting down. FD: %d, err: %v", ioFile.Fd(), err))
- }
- api.p9wg.Done()
- }()
-}