forked from buildbarn/bb-remote-execution
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Mount special filesystems in chroot runners
This can be used to mount special filesystems like '/proc' and '/sys' in the input root of actions if 'chroot' is enabled. The filesystems are required for many tools to work. Solves: buildbarn#115
- Loading branch information
1 parent
a56ecc6
commit b60b67b
Showing
6 changed files
with
355 additions
and
29 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
package runner | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/buildbarn/bb-remote-execution/pkg/proto/configuration/bb_runner" | ||
runner_pb "github.com/buildbarn/bb-remote-execution/pkg/proto/runner" | ||
"github.com/buildbarn/bb-storage/pkg/filesystem" | ||
"github.com/buildbarn/bb-storage/pkg/filesystem/path" | ||
"github.com/buildbarn/bb-storage/pkg/util" | ||
"google.golang.org/grpc/codes" | ||
"google.golang.org/grpc/status" | ||
"google.golang.org/protobuf/types/known/emptypb" | ||
) | ||
|
||
type mountingRunner struct { | ||
base runner_pb.RunnerServer | ||
buildDirectory filesystem.Directory | ||
mount *bb_runner.InputMountOptions | ||
} | ||
|
||
// NewMountingRunner is a decorator for Runner | ||
// that mounts `mount` before running a build action. | ||
// | ||
// This decorator can be used for chroot runners | ||
// that must mount special filesystems into the input root. | ||
func NewMountingRunner(base runner_pb.RunnerServer, buildDirectory filesystem.Directory, mount *bb_runner.InputMountOptions) runner_pb.RunnerServer { | ||
return &mountingRunner{ | ||
buildDirectory: buildDirectory, | ||
mount: mount, | ||
base: base, | ||
} | ||
} | ||
|
||
func (r *mountingRunner) Run(ctx context.Context, request *runner_pb.RunRequest) (response *runner_pb.RunResponse, err error) { | ||
rootResolver := buildDirectoryPathResolver{ | ||
stack: util.NewNonEmptyStack(filesystem.NopDirectoryCloser(r.buildDirectory)), | ||
} | ||
defer rootResolver.closeAll() | ||
if err := path.Resolve(request.InputRootDirectory, path.NewRelativeScopeWalker(&rootResolver)); err != nil { | ||
return nil, util.StatusWrap(err, "Invalid input root.") | ||
} | ||
|
||
if rootResolver.TerminalName != nil { | ||
return nil, status.Errorf(codes.InvalidArgument, "Path resolves to a file, must be directory: %#v", request.InputRootDirectory) | ||
} | ||
inputRoot := rootResolver.stack.Peek() | ||
defer inputRoot.Close() | ||
|
||
mountResolver := buildDirectoryPathResolver{ | ||
stack: util.NewNonEmptyStack(filesystem.NopDirectoryCloser(inputRoot)), | ||
} | ||
defer mountResolver.closeAll() | ||
if err := path.Resolve(r.mount.Mountpoint, path.NewRelativeScopeWalker(&mountResolver)); err != nil { | ||
return nil, util.StatusWrap(err, "Invalid mountpoint directory path.") | ||
} | ||
|
||
mountDir := mountResolver.stack.Peek() | ||
defer mountDir.Close() | ||
if mountResolver.TerminalName == nil { | ||
return nil, status.Errorf(codes.InvalidArgument, "Could not resolve mountpoint basename: %#v", r.mount.Mountpoint) | ||
} | ||
|
||
mountname := *mountResolver.TerminalName | ||
if err := mountDir.Mount(mountname, r.mount.Source, r.mount.FilesystemType); err != nil { | ||
return nil, util.StatusWrapf(err, "Failed to mount %#v in the input root", r.mount) | ||
} | ||
|
||
response, err = r.base.Run(ctx, request) | ||
if err != nil { | ||
return nil, err | ||
} | ||
if err2 := mountDir.Unmount(mountname); err2 != nil { | ||
err = util.StatusFromMultiple([]error{ | ||
err, | ||
util.StatusWrapf(err2, "Failed to unmount %#v in the input root", r.mount.Mountpoint), | ||
}) | ||
} | ||
|
||
return response, nil | ||
} | ||
|
||
func (r *mountingRunner) CheckReadiness(ctx context.Context, request *runner_pb.CheckReadinessRequest) (*emptypb.Empty, error) { | ||
return r.base.CheckReadiness(ctx, request) | ||
} |
Oops, something went wrong.