drivers/raw_exec: enable setting cgroup override values (#20481)

* drivers/raw_exec: enable setting cgroup override values

This PR enables configuration of cgroup override values on the `raw_exec`
task driver. WARNING: setting cgroup override values eliminates any
gauruntee Nomad can make about resource availability for *any* task on
the client node.

For cgroup v2 systems, set a single unified cgroup path using `cgroup_v2_override`.
The path may be either absolute or relative to the cgroup root.

config {
  cgroup_v2_override = "custom.slice/app.scope"
}

or

config {
  cgroup_v2_override = "/sys/fs/cgroup/custom.slice/app.scope"
}

For cgroup v1 systems, set a per-controller path for each controller using
`cgroup_v1_override`. The path(s) may be either absolute or relative to
the controller root.

config {
  cgroup_v1_override = {
    "pids": "custom/app",
    "cpuset": "custom/app",
  }
}

or

config {
  cgroup_v1_override = {
    "pids": "/sys/fs/cgroup/pids/custom/app",
    "cpuset": "/sys/fs/cgroup/cpuset/custom/app",
  }
}

* drivers/rawexec: ensure only one of v1/v2 cgroup override is set

* drivers/raw_exec: executor should error if setting cgroup does not work

* drivers/raw_exec: create cgroups in raw_exec tests

* drivers/raw_exec: ensure we fail to start if custom cgroup set and non-root

* move custom cgroup func into shared file

---------

Co-authored-by: Michael Schurter <mschurter@hashicorp.com>
This commit is contained in:
Seth Hoenig
2024-05-07 19:46:27 -04:00
committed by GitHub
parent 5041460043
commit 14a022cbc0
16 changed files with 430 additions and 84 deletions

3
.changelog/20481.txt Normal file
View File

@@ -0,0 +1,3 @@
```release-note:improvement
driver/rawexec: Allow specifying custom cgroups
```

View File

@@ -27,6 +27,7 @@ import (
"github.com/hashicorp/nomad/client/config"
consulclient "github.com/hashicorp/nomad/client/consul"
"github.com/hashicorp/nomad/client/devicemanager"
"github.com/hashicorp/nomad/client/lib/cgroupslib"
"github.com/hashicorp/nomad/client/lib/proclib"
"github.com/hashicorp/nomad/client/pluginmanager/drivermanager"
regMock "github.com/hashicorp/nomad/client/serviceregistration/mock"
@@ -107,7 +108,15 @@ func testTaskRunnerConfig(t *testing.T, alloc *structs.Allocation, taskName stri
}
taskDir := allocDir.NewTaskDir(taskName)
// Create cgroup
f := cgroupslib.Factory(alloc.ID, taskName, false)
must.NoError(t, f.Setup())
trCleanup := func() {
// destroy and remove the cgroup
_ = f.Kill()
_ = f.Teardown()
// destroy the alloc dir
if err := allocDir.Destroy(); err != nil {
t.Logf("error destroying alloc dir: %v", err)
}
@@ -189,6 +198,7 @@ func runTestTaskRunner(t *testing.T, alloc *structs.Allocation, taskName string)
}
tr, err := NewTaskRunner(config)
require.NoError(t, err)
go tr.Run()

View File

@@ -10,6 +10,7 @@ import (
"fmt"
"os"
"path/filepath"
"strings"
"github.com/hashicorp/go-hclog"
)
@@ -286,3 +287,23 @@ func LinuxResourcesPath(allocID, task string, reserveCores bool) string {
return filepath.Join(root, NomadCgroupParent, partition, scopeCG2(allocID, task))
}
}
// CustomPathCG1 returns the absolute directory path of the cgroup directory of
// the given controller. If path is already absolute (starts with /), that
// value is used without modification.
func CustomPathCG1(controller, path string) string {
if strings.HasPrefix(path, "/") {
return path
}
return filepath.Join(root, controller, path)
}
// CustomPathCG2 returns the absolute directory path of the given cgroup path.
// If the path is already absolute (starts with /), that value is used without
// modification.
func CustomPathCG2(path string) string {
if strings.HasPrefix(path, "/") || path == "" {
return path
}
return filepath.Join(root, path)
}

View File

@@ -9,3 +9,13 @@ package cgroupslib
func PathCG1(allocID, taskName, iface string) string {
return ""
}
// CustomPathCG1 returns empty string on non-Linux systems
func CustomPathCG1(controller, path string) string {
return ""
}
// CustomPathCG2 returns empty string on non-Linux systems
func CustomPathCG2(path string) string {
return ""
}

View File

@@ -0,0 +1,45 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
//go:build linux
package cgroupslib
import (
"testing"
"github.com/shoenig/test/must"
)
func TestCustomPathCG1(t *testing.T) {
exp := "/sys/fs/cgroup/pids/custom/path"
t.Run("absolute", func(t *testing.T) {
result := CustomPathCG1("pids", "/sys/fs/cgroup/pids/custom/path")
must.Eq(t, result, exp)
})
t.Run("relative", func(t *testing.T) {
result := CustomPathCG1("pids", "custom/path")
must.Eq(t, result, exp)
})
}
func TestCustomPathCG2(t *testing.T) {
exp := "/sys/fs/cgroup/custom.slice/path.scope"
t.Run("unset", func(t *testing.T) {
result := CustomPathCG2("")
must.Eq(t, result, "")
})
t.Run("absolute", func(t *testing.T) {
result := CustomPathCG2("/sys/fs/cgroup/custom.slice/path.scope")
must.Eq(t, result, exp)
})
t.Run("relative", func(t *testing.T) {
result := CustomPathCG2("custom.slice/path.scope")
must.Eq(t, result, exp)
})
}

View File

@@ -5,6 +5,7 @@ package rawexec
import (
"context"
"errors"
"fmt"
"os"
"path/filepath"
@@ -13,9 +14,11 @@ import (
"github.com/hashicorp/consul-template/signals"
"github.com/hashicorp/go-hclog"
"github.com/hashicorp/nomad/client/lib/cgroupslib"
"github.com/hashicorp/nomad/client/lib/cpustats"
"github.com/hashicorp/nomad/drivers/shared/eventer"
"github.com/hashicorp/nomad/drivers/shared/executor"
"github.com/hashicorp/nomad/helper/pluginutils/hclutils"
"github.com/hashicorp/nomad/helper/pluginutils/loader"
"github.com/hashicorp/nomad/plugins/base"
"github.com/hashicorp/nomad/plugins/drivers"
@@ -83,8 +86,10 @@ var (
// taskConfigSpec is the hcl specification for the driver config section of
// a task within a job. It is returned in the TaskConfigSchema RPC
taskConfigSpec = hclspec.NewObject(map[string]*hclspec.Spec{
"command": hclspec.NewAttr("command", "string", true),
"args": hclspec.NewAttr("args", "list(string)", false),
"command": hclspec.NewAttr("command", "string", true),
"args": hclspec.NewAttr("args", "list(string)", false),
"cgroup_v2_override": hclspec.NewAttr("cgroup_v2_override", "string", false),
"cgroup_v1_override": hclspec.NewAttr("cgroup_v1_override", "list(map(string))", false),
})
// capabilities is returned by the Capabilities RPC and indicates what
@@ -139,6 +144,18 @@ type Config struct {
type TaskConfig struct {
Command string `codec:"command"`
Args []string `codec:"args"`
// OverrideCgroupV2 allows overriding the unified cgroup the task will be
// become a member of.
//
// * All resource isolation guarantees are lost FOR ALL TASKS if set *
OverrideCgroupV2 string `codec:"cgroup_v2_override"`
// OverrideCgroupV1 allows overriding per-controller cgroups the task will
// become a member of.
//
// * All resource isolation guarantees are lost FOR ALL TASKS if set *
OverrideCgroupV1 hclutils.MapStrStr `codec:"cgroup_v1_override"`
}
// TaskState is the state which is encoded in the handle returned in
@@ -334,6 +351,15 @@ func (d *Driver) StartTask(cfg *drivers.TaskConfig) (*drivers.TaskHandle, *drive
StderrPath: cfg.StderrPath,
NetworkIsolation: cfg.NetworkIsolation,
Resources: cfg.Resources.Copy(),
OverrideCgroupV2: cgroupslib.CustomPathCG2(driverConfig.OverrideCgroupV2),
OverrideCgroupV1: driverConfig.OverrideCgroupV1,
}
// ensure only one of cgroups_v1_override and cgroups_v2_override have been
// configured; must check here because task config validation cannot happen
// on the server.
if len(execCmd.OverrideCgroupV1) > 0 && execCmd.OverrideCgroupV2 != "" {
return nil, nil, errors.New("only one of cgroups_v1_override and cgroups_v2_override may be set")
}
ps, err := exec.Launch(execCmd)

View File

@@ -26,6 +26,7 @@ import (
"github.com/hashicorp/nomad/plugins/drivers"
dtestutil "github.com/hashicorp/nomad/plugins/drivers/testutils"
"github.com/hashicorp/nomad/testutil"
"github.com/shoenig/test/must"
"github.com/stretchr/testify/require"
"golang.org/x/sys/unix"
)
@@ -60,6 +61,38 @@ func TestRawExecDriver_User(t *testing.T) {
require.Contains(err.Error(), msg)
}
func TestRawExecDriver_ValidateCgroupOverrides(t *testing.T) {
ci.Parallel(t)
clienttestutil.RequireLinux(t)
d := newEnabledRawExecDriver(t)
harness := dtestutil.NewDriverHarness(t, d)
task := &drivers.TaskConfig{
ID: uuid.Generate(),
Name: "sleep",
User: "nobody",
}
cleanup := harness.MkAllocDir(task, false)
defer cleanup()
tc := &TaskConfig{
Command: "sleep",
Args: []string{"infinity"},
OverrideCgroupV2: "custom.slice/app.scope",
OverrideCgroupV1: map[string]string{
"pids": "custom/path",
},
}
must.NoError(t, task.EncodeConcreteDriverConfig(&tc))
testtask.SetTaskConfigEnv(task)
_, _, err := harness.StartTask(task)
must.ErrorContains(t, err, "only one of cgroups_v1_override and cgroups_v2_override may be set")
}
func TestRawExecDriver_Signal(t *testing.T) {
ci.Parallel(t)
clienttestutil.RequireLinux(t)

View File

@@ -151,6 +151,35 @@ type ExecCommand struct {
// Capabilities are the linux capabilities to be enabled by the task driver.
Capabilities []string
// OverrideCgroupV2 allows overriding the unified cgroup the task will be
// become a member of.
//
// * All resource isolation guarantees are lost FOR ALL TASKS if set *
OverrideCgroupV2 string
// OverrideCgroupV1 allows overriding per-controller cgroups the task will
// become a member of.
//
// * All resource isolation guarantees are lost FOR ALL TASKS if set *
OverrideCgroupV1 map[string]string
}
func (c *ExecCommand) getCgroupOr(controller, fallback string) string {
switch cgroupslib.GetMode() {
case cgroupslib.OFF:
return ""
case cgroupslib.CG2:
if c.OverrideCgroupV2 != "" {
return c.OverrideCgroupV2
}
case cgroupslib.CG1:
path, exists := c.OverrideCgroupV1[controller]
if exists {
return cgroupslib.CustomPathCG1(controller, path)
}
}
return fallback
}
// CpusetCgroup returns the path to the cgroup in which the Nomad client will
@@ -166,7 +195,10 @@ func (c *ExecCommand) CpusetCgroup() string {
if c == nil || c.Resources == nil || c.Resources.LinuxResources == nil {
return ""
}
return c.Resources.LinuxResources.CpusetCgroupPath
// lookup the custom cgroup (cpuset controller on cgroups v1) or use the
// predetermined fallback
return c.getCgroupOr("cpuset", c.Resources.LinuxResources.CpusetCgroupPath)
}
// StatsCgroup returns the path to the cgroup Nomad client will use to inspect
@@ -181,14 +213,19 @@ func (c *ExecCommand) StatsCgroup() string {
if c == nil || c.Resources == nil || c.Resources.LinuxResources == nil {
return ""
}
switch cgroupslib.GetMode() {
case cgroupslib.CG1:
// figure out the freezer cgroup path nomad created for use as fallback
// (in cgroups v2 its just the unified cgroup)
fallback := c.Resources.LinuxResources.CpusetCgroupPath
if cgroupslib.GetMode() == cgroupslib.CG1 {
taskName := filepath.Base(c.TaskDir)
allocID := filepath.Base(filepath.Dir(c.TaskDir))
return cgroupslib.PathCG1(allocID, taskName, "freezer")
default:
return c.CpusetCgroup()
fallback = cgroupslib.PathCG1(allocID, taskName, "freezer")
}
// lookup the custom cgroup (pids controller on cgroups v1) or use
// the predetermined fallback
return c.getCgroupOr("pids", fallback)
}
// SetWriters sets the writer for the process stdout and stderr. This should
@@ -331,8 +368,12 @@ func (e *UniversalExecutor) Launch(command *ExecCommand) (*ProcessState, error)
// setup containment (i.e. cgroups on linux)
if cleanup, err := e.configureResourceContainer(command, os.Getpid()); err != nil {
// keep going; some folks run nomad as non-root and expect this driver to still work
e.logger.Warn("failed to configure container, process isolation will not work", "error", err)
e.logger.Error("failed to configure container, process isolation will not work", "error", err)
if os.Geteuid() == 0 || e.usesCustomCgroup() {
return nil, fmt.Errorf("unable to configure cgroups: %w", err)
}
// keep going if we are not root; some folks run nomad as non-root and
// expect this driver to still work
} else {
defer cleanup()
}
@@ -667,6 +708,11 @@ func (e *UniversalExecutor) handleStats(ch chan *cstructs.TaskResourceUsage, ctx
}
}
// usesCustomCgroup whether cgroup_v1_override or cgroup_v2_override is set
func (e *UniversalExecutor) usesCustomCgroup() bool {
return len(e.command.OverrideCgroupV1) > 0 || e.command.OverrideCgroupV2 != ""
}
// lookupBin looks for path to the binary to run by looking for the binary in
// the following locations, in-order:
// task/local/, task/, on the host file system, in host $PATH

View File

@@ -793,3 +793,66 @@ func TestExecutor_cmdMounts(t *testing.T) {
require.EqualValues(t, expected, cmdMounts(input))
}
func TestExecCommand_getCgroupOr_off(t *testing.T) {
ci.Parallel(t)
if cgroupslib.GetMode() != cgroupslib.OFF {
t.Skip("test only runs with no cgroups")
}
ec := new(ExecCommand)
result := ec.getCgroupOr("cpuset", "/sys/fs/cgroup/cpuset/nomad/abc123")
must.Eq(t, "", result)
}
func TestExecCommand_getCgroupOr_v1_absolute(t *testing.T) {
ci.Parallel(t)
if cgroupslib.GetMode() != cgroupslib.CG1 {
t.Skip("test only runs on cgroups v1")
}
t.Run("unset", func(t *testing.T) {
ec := &ExecCommand{
OverrideCgroupV1: nil,
}
result := ec.getCgroupOr("pids", "/sys/fs/cgroup/pids/nomad/abc123")
must.Eq(t, result, "/sys/fs/cgroup/pids/nomad/abc123")
result2 := ec.getCgroupOr("cpuset", "/sys/fs/cgroup/cpuset/nomad/abc123")
must.Eq(t, result2, "/sys/fs/cgroup/cpuset/nomad/abc123")
})
t.Run("set", func(t *testing.T) {
ec := &ExecCommand{
OverrideCgroupV1: map[string]string{
"pids": "/sys/fs/cgroup/pids/custom/path",
"cpuset": "/sys/fs/cgroup/cpuset/custom/path",
},
}
result := ec.getCgroupOr("pids", "/sys/fs/cgroup/pids/nomad/abc123")
must.Eq(t, result, "/sys/fs/cgroup/pids/custom/path")
result2 := ec.getCgroupOr("cpuset", "/sys/fs/cgroup/cpuset/nomad/abc123")
must.Eq(t, result2, "/sys/fs/cgroup/cpuset/custom/path")
})
}
func TestExecCommand_getCgroupOr_v1_relative(t *testing.T) {
ci.Parallel(t)
if cgroupslib.GetMode() != cgroupslib.CG1 {
t.Skip("test only runs on cgroups v1")
}
ec := &ExecCommand{
OverrideCgroupV1: map[string]string{
"pids": "custom/path",
"cpuset": "custom/path",
},
}
result := ec.getCgroupOr("pids", "/sys/fs/cgroup/pids/nomad/abc123")
must.Eq(t, result, "/sys/fs/cgroup/pids/custom/path")
result2 := ec.getCgroupOr("cpuset", "/sys/fs/cgroup/cpuset/nomad/abc123")
must.Eq(t, result2, "/sys/fs/cgroup/cpuset/custom/path")
}

View File

@@ -134,7 +134,9 @@ func (e *UniversalExecutor) configureResourceContainer(command *ExecCommand, pid
// manually configure cgroup for cpu / memory constraints
switch cgroupslib.GetMode() {
case cgroupslib.CG1:
e.configureCG1(cgroup, command)
if err := e.configureCG1(cgroup, command); err != nil {
return nil, err
}
cgCleanup = e.enterCG1(cgroup, command.CpusetCgroup())
default:
e.configureCG2(cgroup, command)
@@ -189,11 +191,26 @@ func (e *UniversalExecutor) enterCG1(statsCgroup, cpusetCgroup string) func() {
}
}
func (e *UniversalExecutor) configureCG1(cgroup string, command *ExecCommand) {
func (e *UniversalExecutor) configureCG1(cgroup string, command *ExecCommand) error {
// some drivers like qemu entirely own resource management
if command.Resources == nil || command.Resources.LinuxResources == nil {
return
return nil
}
// if custom cgroups are set join those instead of configuring the /nomad
// cgroups we are not going to use
if len(e.command.OverrideCgroupV1) > 0 {
pid := unix.Getpid()
for controller, path := range e.command.OverrideCgroupV1 {
absPath := cgroupslib.CustomPathCG1(controller, path)
ed := cgroupslib.OpenPath(absPath)
err := ed.Write("cgroup.procs", strconv.Itoa(pid))
if err != nil {
e.logger.Error("unable to write to custom cgroup", "error", err)
return fmt.Errorf("unable to write to custom cgroup: %v", err)
}
}
return nil
}
// write memory limits
@@ -222,10 +239,11 @@ func (e *UniversalExecutor) configureCG1(cgroup string, command *ExecCommand) {
ed = cgroupslib.OpenPath(cpusetPath)
_ = ed.Write("cpuset.cpus", cpuSet)
}
return nil
}
func (e *UniversalExecutor) configureCG2(cgroup string, command *ExecCommand) {
// some drivers like qemu entirely own resource management
if command.Resources == nil || command.Resources.LinuxResources == nil {
return

View File

@@ -9,6 +9,10 @@ import (
"fmt"
"testing"
"github.com/hashicorp/nomad/ci"
"github.com/hashicorp/nomad/client/lib/cgroupslib"
"github.com/hashicorp/nomad/client/testutil"
"github.com/hashicorp/nomad/helper/testlog"
"github.com/hashicorp/nomad/nomad/structs"
"github.com/hashicorp/nomad/plugins/drivers"
"github.com/shoenig/test/must"
@@ -66,3 +70,32 @@ func Test_computeMemory(t *testing.T) {
})
}
}
func TestExecutor_InvalidCgroup(t *testing.T) {
ci.Parallel(t)
testutil.CgroupsCompatible(t)
factory := universalFactory
testExecCmd := testExecutorCommand(t)
execCmd, allocDir := testExecCmd.command, testExecCmd.allocDir
execCmd.Cmd = "sleep"
execCmd.Args = []string{"infinity"}
switch cgroupslib.GetMode() {
case cgroupslib.CG1:
execCmd.OverrideCgroupV1 = map[string]string{
"pid": "custom/path",
}
case cgroupslib.CG2:
execCmd.OverrideCgroupV2 = "custom.slice/test.scope"
}
factory.configureExecCmd(t, execCmd)
defer allocDir.Destroy()
executor := factory.new(testlog.HCLogger(t), compute)
defer executor.Shutdown("", 0)
_, err := executor.Launch(execCmd)
must.ErrorContains(t, err, "unable to configure cgroups: no such file or directory")
}

View File

@@ -52,6 +52,8 @@ func (c *grpcExecutorClient) Launch(cmd *ExecCommand) (*ProcessState, error) {
DefaultPidMode: cmd.ModePID,
DefaultIpcMode: cmd.ModeIPC,
Capabilities: cmd.Capabilities,
CgroupV2Override: cmd.OverrideCgroupV2,
CgroupV1Override: cmd.OverrideCgroupV1,
}
resp, err := c.client.Launch(ctx, req)
if err != nil {

View File

@@ -41,6 +41,8 @@ func (s *grpcExecutorServer) Launch(ctx context.Context, req *proto.LaunchReques
ModePID: req.DefaultPidMode,
ModeIPC: req.DefaultIpcMode,
Capabilities: req.Capabilities,
OverrideCgroupV2: req.CgroupV2Override,
OverrideCgroupV1: req.CgroupV1Override,
})
if err != nil {

View File

@@ -46,6 +46,8 @@ type LaunchRequest struct {
CpusetCgroup string `protobuf:"bytes,17,opt,name=cpuset_cgroup,json=cpusetCgroup,proto3" json:"cpuset_cgroup,omitempty"`
AllowCaps []string `protobuf:"bytes,18,rep,name=allow_caps,json=allowCaps,proto3" json:"allow_caps,omitempty"`
Capabilities []string `protobuf:"bytes,19,rep,name=capabilities,proto3" json:"capabilities,omitempty"`
CgroupV2Override string `protobuf:"bytes,20,opt,name=cgroup_v2_override,json=cgroupV2Override,proto3" json:"cgroup_v2_override,omitempty"`
CgroupV1Override map[string]string `protobuf:"bytes,21,rep,name=cgroup_v1_override,json=cgroupV1Override,proto3" json:"cgroup_v1_override,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
@@ -210,6 +212,20 @@ func (m *LaunchRequest) GetCapabilities() []string {
return nil
}
func (m *LaunchRequest) GetCgroupV2Override() string {
if m != nil {
return m.CgroupV2Override
}
return ""
}
func (m *LaunchRequest) GetCgroupV1Override() map[string]string {
if m != nil {
return m.CgroupV1Override
}
return nil
}
type LaunchResponse struct {
Process *ProcessState `protobuf:"bytes,1,opt,name=process,proto3" json:"process,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
@@ -860,6 +876,7 @@ func (m *ProcessState) GetOomKilled() bool {
func init() {
proto.RegisterType((*LaunchRequest)(nil), "hashicorp.nomad.plugins.executor.proto.LaunchRequest")
proto.RegisterMapType((map[string]string)(nil), "hashicorp.nomad.plugins.executor.proto.LaunchRequest.CgroupV1OverrideEntry")
proto.RegisterType((*LaunchResponse)(nil), "hashicorp.nomad.plugins.executor.proto.LaunchResponse")
proto.RegisterType((*WaitRequest)(nil), "hashicorp.nomad.plugins.executor.proto.WaitRequest")
proto.RegisterType((*WaitResponse)(nil), "hashicorp.nomad.plugins.executor.proto.WaitResponse")
@@ -883,75 +900,80 @@ func init() {
}
var fileDescriptor_66b85426380683f3 = []byte{
// 1083 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x55, 0xff, 0x6e, 0x1b, 0x45,
0x10, 0xee, 0xc5, 0x89, 0x7f, 0x8c, 0xed, 0xc4, 0x5d, 0x50, 0xb8, 0x1a, 0xa1, 0x9a, 0x43, 0xa2,
0x16, 0x94, 0x4b, 0x94, 0xa6, 0x2d, 0x12, 0x12, 0x45, 0x4d, 0x0a, 0xaa, 0x48, 0xa3, 0xe8, 0x52,
0xa8, 0xc4, 0x1f, 0x1c, 0x9b, 0xbb, 0xad, 0xbd, 0xca, 0xf9, 0xf6, 0xd8, 0xdd, 0x73, 0x82, 0x84,
0xc4, 0x4b, 0x80, 0xc4, 0x03, 0xf0, 0x20, 0x3c, 0x1a, 0xda, 0x5f, 0x17, 0x3b, 0x2d, 0xd5, 0xb9,
0x88, 0xbf, 0x7c, 0x3b, 0xfe, 0xbe, 0x99, 0xd9, 0x9d, 0x99, 0x6f, 0xe0, 0x6e, 0xca, 0xe9, 0x9c,
0x70, 0xb1, 0x23, 0xa6, 0x98, 0x93, 0x74, 0x87, 0x5c, 0x92, 0xa4, 0x94, 0x8c, 0xef, 0x14, 0x9c,
0x49, 0x56, 0x1d, 0x43, 0x7d, 0x44, 0x1f, 0x4f, 0xb1, 0x98, 0xd2, 0x84, 0xf1, 0x22, 0xcc, 0xd9,
0x0c, 0xa7, 0x61, 0x91, 0x95, 0x13, 0x9a, 0x8b, 0x70, 0x19, 0x37, 0xbc, 0x3d, 0x61, 0x6c, 0x92,
0x11, 0xe3, 0xe4, 0xac, 0x7c, 0xb9, 0x23, 0xe9, 0x8c, 0x08, 0x89, 0x67, 0x85, 0x05, 0x04, 0x96,
0xb8, 0xe3, 0xc2, 0x9b, 0x70, 0xe6, 0x64, 0x30, 0xc1, 0xdf, 0x4d, 0xe8, 0x1f, 0xe1, 0x32, 0x4f,
0xa6, 0x11, 0xf9, 0xb9, 0x24, 0x42, 0xa2, 0x01, 0x34, 0x92, 0x59, 0xea, 0x7b, 0x23, 0x6f, 0xdc,
0x89, 0xd4, 0x27, 0x42, 0xb0, 0x8e, 0xf9, 0x44, 0xf8, 0x6b, 0xa3, 0xc6, 0xb8, 0x13, 0xe9, 0x6f,
0x74, 0x0c, 0x1d, 0x4e, 0x04, 0x2b, 0x79, 0x42, 0x84, 0xdf, 0x18, 0x79, 0xe3, 0xee, 0xde, 0x6e,
0xf8, 0x6f, 0x89, 0xdb, 0xf8, 0x26, 0x64, 0x18, 0x39, 0x5e, 0x74, 0xe5, 0x02, 0xdd, 0x86, 0xae,
0x90, 0x29, 0x2b, 0x65, 0x5c, 0x60, 0x39, 0xf5, 0xd7, 0x75, 0x74, 0x30, 0xa6, 0x13, 0x2c, 0xa7,
0x16, 0x40, 0x38, 0x37, 0x80, 0x8d, 0x0a, 0x40, 0x38, 0xd7, 0x80, 0x01, 0x34, 0x48, 0x3e, 0xf7,
0x9b, 0x3a, 0x49, 0xf5, 0xa9, 0xf2, 0x2e, 0x05, 0xe1, 0x7e, 0x4b, 0x63, 0xf5, 0x37, 0xba, 0x05,
0x6d, 0x89, 0xc5, 0x79, 0x9c, 0x52, 0xee, 0xb7, 0xb5, 0xbd, 0xa5, 0xce, 0x87, 0x94, 0xa3, 0x3b,
0xb0, 0xe5, 0xf2, 0x89, 0x33, 0x3a, 0xa3, 0x52, 0xf8, 0x9d, 0x91, 0x37, 0x6e, 0x47, 0x9b, 0xce,
0x7c, 0xa4, 0xad, 0x68, 0x1f, 0xde, 0x3d, 0xc3, 0x82, 0x26, 0x71, 0xc1, 0x59, 0x42, 0x84, 0x88,
0x93, 0x09, 0x67, 0x65, 0xe1, 0x83, 0x42, 0x3f, 0x5e, 0xf3, 0xbd, 0x08, 0xe9, 0xff, 0x4f, 0xcc,
0xdf, 0x07, 0xfa, 0x5f, 0x74, 0x08, 0xcd, 0x19, 0x2b, 0x73, 0x29, 0xfc, 0xee, 0xa8, 0x31, 0xee,
0xee, 0xdd, 0xad, 0xf9, 0x5c, 0xcf, 0x14, 0x29, 0xb2, 0x5c, 0xf4, 0x0d, 0xb4, 0x52, 0x32, 0xa7,
0xea, 0xd5, 0x7b, 0xda, 0xcd, 0x67, 0x35, 0xdd, 0x1c, 0x6a, 0x56, 0xe4, 0xd8, 0x68, 0x0a, 0x37,
0x73, 0x22, 0x2f, 0x18, 0x3f, 0x8f, 0xa9, 0x60, 0x19, 0x96, 0x94, 0xe5, 0x7e, 0x5f, 0x17, 0xf2,
0x8b, 0x9a, 0x2e, 0x8f, 0x0d, 0xff, 0xa9, 0xa3, 0x9f, 0x16, 0x24, 0x89, 0x06, 0xf9, 0x35, 0x2b,
0x0a, 0xa0, 0x9f, 0xb3, 0xb8, 0xa0, 0x73, 0x26, 0x63, 0xce, 0x98, 0xf4, 0x37, 0xf5, 0xab, 0x76,
0x73, 0x76, 0xa2, 0x6c, 0x11, 0x63, 0x12, 0x8d, 0x61, 0x90, 0x92, 0x97, 0xb8, 0xcc, 0x64, 0x5c,
0xd0, 0x34, 0x9e, 0xb1, 0x94, 0xf8, 0x5b, 0xba, 0x3c, 0x9b, 0xd6, 0x7e, 0x42, 0xd3, 0x67, 0x2c,
0x25, 0x8b, 0x48, 0x5a, 0x24, 0x06, 0x39, 0x58, 0x42, 0x3e, 0x2d, 0x12, 0x8d, 0xfc, 0x08, 0xfa,
0x49, 0x51, 0x0a, 0x22, 0x5d, 0x7d, 0x6e, 0x6a, 0x58, 0xcf, 0x18, 0x6d, 0x55, 0x3e, 0x00, 0xc0,
0x59, 0xc6, 0x2e, 0xe2, 0x04, 0x17, 0xc2, 0x47, 0xba, 0x79, 0x3a, 0xda, 0x72, 0x80, 0x0b, 0x81,
0x02, 0xe8, 0x25, 0xb8, 0xc0, 0x67, 0x34, 0xa3, 0x92, 0x12, 0xe1, 0xbf, 0xa3, 0x01, 0x4b, 0xb6,
0xe0, 0x27, 0xd8, 0x74, 0x13, 0x24, 0x0a, 0x96, 0x0b, 0x82, 0x8e, 0xa1, 0x65, 0x5b, 0x43, 0x8f,
0x51, 0x77, 0x6f, 0x3f, 0xac, 0x37, 0xd3, 0xa1, 0x6d, 0x99, 0x53, 0x89, 0x25, 0x89, 0x9c, 0x93,
0xa0, 0x0f, 0xdd, 0x17, 0x98, 0x4a, 0x3b, 0xa1, 0xc1, 0x8f, 0xd0, 0x33, 0xc7, 0xff, 0x29, 0xdc,
0x11, 0x6c, 0x9d, 0x4e, 0x4b, 0x99, 0xb2, 0x8b, 0xdc, 0x89, 0xc2, 0x36, 0x34, 0x05, 0x9d, 0xe4,
0x38, 0xb3, 0xba, 0x60, 0x4f, 0xe8, 0x43, 0xe8, 0x4d, 0x38, 0x4e, 0x48, 0x5c, 0x10, 0x4e, 0x59,
0xea, 0xaf, 0x8d, 0xbc, 0x71, 0x23, 0xea, 0x6a, 0xdb, 0x89, 0x36, 0x05, 0x08, 0x06, 0x57, 0xde,
0x4c, 0xc6, 0xc1, 0x14, 0xb6, 0xbf, 0x2b, 0x52, 0x15, 0xb4, 0xd2, 0x02, 0x1b, 0x68, 0x49, 0x57,
0xbc, 0xff, 0xac, 0x2b, 0xc1, 0x2d, 0x78, 0xef, 0x95, 0x48, 0x36, 0x89, 0x01, 0x6c, 0x7e, 0x4f,
0xb8, 0xa0, 0xcc, 0xdd, 0x32, 0xf8, 0x14, 0xb6, 0x2a, 0x8b, 0x7d, 0x5b, 0x1f, 0x5a, 0x73, 0x63,
0xb2, 0x37, 0x77, 0xc7, 0xe0, 0x13, 0xe8, 0xa9, 0x77, 0xab, 0x32, 0x1f, 0x42, 0x9b, 0xe6, 0x92,
0xf0, 0xb9, 0x7d, 0xa4, 0x46, 0x54, 0x9d, 0x83, 0x17, 0xd0, 0xb7, 0x58, 0xeb, 0xf6, 0x6b, 0xd8,
0x10, 0xca, 0xb0, 0xe2, 0x15, 0x9f, 0x63, 0x71, 0x6e, 0x1c, 0x19, 0x7a, 0x70, 0x07, 0xfa, 0xa7,
0xba, 0x12, 0xaf, 0x2f, 0xd4, 0x86, 0x2b, 0x94, 0xba, 0xac, 0x03, 0xda, 0xeb, 0x9f, 0x43, 0xf7,
0xc9, 0x25, 0x49, 0x1c, 0xf1, 0x01, 0xb4, 0x53, 0x82, 0xd3, 0x8c, 0xe6, 0xc4, 0x26, 0x35, 0x0c,
0xcd, 0x82, 0x09, 0xdd, 0x82, 0x09, 0x9f, 0xbb, 0x05, 0x13, 0x55, 0x58, 0xb7, 0x2e, 0xd6, 0x5e,
0x5d, 0x17, 0x8d, 0xab, 0x75, 0x11, 0x1c, 0x40, 0xcf, 0x04, 0xb3, 0xf7, 0xdf, 0x86, 0x26, 0x2b,
0x65, 0x51, 0x4a, 0x1d, 0xab, 0x17, 0xd9, 0x13, 0x7a, 0x1f, 0x3a, 0xe4, 0x92, 0xca, 0x38, 0x51,
0x63, 0xbd, 0xa6, 0x6f, 0xd0, 0x56, 0x86, 0x03, 0x96, 0x92, 0xe0, 0x2f, 0x0f, 0x7a, 0x8b, 0x1d,
0xab, 0x62, 0x17, 0x34, 0xb5, 0x37, 0x55, 0x9f, 0x6f, 0xe4, 0x2f, 0xbc, 0x4d, 0x63, 0xf1, 0x6d,
0x50, 0x08, 0xeb, 0x6a, 0x75, 0xea, 0xa5, 0xf3, 0xe6, 0x6b, 0x6b, 0x9c, 0xd2, 0x0c, 0xc6, 0x66,
0xf1, 0x39, 0xcd, 0x32, 0x92, 0xea, 0x4d, 0xd4, 0x8e, 0x3a, 0x8c, 0xcd, 0xbe, 0xd5, 0x86, 0xbd,
0x3f, 0x3a, 0xd0, 0x7e, 0x62, 0xe7, 0x0c, 0xfd, 0x02, 0x4d, 0x23, 0x0e, 0xe8, 0x7e, 0xdd, 0xa1,
0x5c, 0x5a, 0xc7, 0xc3, 0x07, 0xab, 0xd2, 0x6c, 0x79, 0x6f, 0x20, 0x01, 0xeb, 0x4a, 0x26, 0xd0,
0xbd, 0xba, 0x1e, 0x16, 0x34, 0x66, 0xb8, 0xbf, 0x1a, 0xa9, 0x0a, 0xfa, 0x1b, 0xb4, 0xdd, 0xb4,
0xa3, 0x87, 0x75, 0x7d, 0x5c, 0x53, 0x9b, 0xe1, 0xe7, 0xab, 0x13, 0xab, 0x04, 0x7e, 0xf7, 0x60,
0xeb, 0xda, 0xc4, 0xa3, 0x2f, 0xeb, 0xfa, 0x7b, 0xbd, 0x28, 0x0d, 0x1f, 0xbd, 0x35, 0xbf, 0x4a,
0xeb, 0x57, 0x68, 0x59, 0x69, 0x41, 0xb5, 0x2b, 0xba, 0xac, 0x4e, 0xc3, 0x87, 0x2b, 0xf3, 0xaa,
0xe8, 0x97, 0xb0, 0xa1, 0x65, 0x03, 0xd5, 0x2e, 0xeb, 0xa2, 0xb4, 0x0d, 0xef, 0xaf, 0xc8, 0x72,
0x71, 0x77, 0x3d, 0xd5, 0xff, 0x46, 0x77, 0xea, 0xf7, 0xff, 0x92, 0xa0, 0xd5, 0xef, 0xff, 0x6b,
0xf2, 0xa6, 0xfb, 0x5f, 0x8d, 0x61, 0xfd, 0xfe, 0x5f, 0x90, 0xc3, 0xfa, 0xfd, 0xbf, 0x28, 0x6b,
0xc1, 0x0d, 0xf4, 0xa7, 0x07, 0x7d, 0x65, 0x3a, 0x95, 0x9c, 0xe0, 0x19, 0xcd, 0x27, 0xe8, 0x51,
0x4d, 0x6d, 0x57, 0x2c, 0xa3, 0xef, 0x96, 0xe9, 0x52, 0xf9, 0xea, 0xed, 0x1d, 0xb8, 0xb4, 0xc6,
0xde, 0xae, 0xf7, 0xb8, 0xf5, 0xc3, 0x86, 0x91, 0xb4, 0xa6, 0xfe, 0xb9, 0xf7, 0x4f, 0x00, 0x00,
0x00, 0xff, 0xff, 0x2d, 0xae, 0x48, 0x7d, 0x97, 0x0c, 0x00, 0x00,
// 1163 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x56, 0x6b, 0x8f, 0xdb, 0x44,
0x17, 0xae, 0x37, 0xbb, 0xb9, 0x9c, 0x24, 0xbb, 0xe9, 0xbc, 0x6d, 0x5f, 0x37, 0x08, 0x75, 0x31,
0x12, 0x8d, 0xa0, 0x78, 0xdb, 0xf4, 0x2a, 0x90, 0x28, 0xea, 0xb6, 0xa0, 0xaa, 0x17, 0x56, 0xde,
0xd2, 0x4a, 0x7c, 0xc0, 0x4c, 0xed, 0x69, 0x32, 0x8a, 0xe3, 0x31, 0x33, 0xe3, 0x74, 0x57, 0x42,
0xe2, 0x4f, 0x80, 0xc4, 0x0f, 0xe0, 0x33, 0xbf, 0x11, 0xcd, 0xcd, 0x9b, 0x6c, 0x4b, 0xe5, 0x14,
0xf1, 0x29, 0x33, 0x8f, 0x9f, 0x73, 0x9b, 0x33, 0xe7, 0x99, 0xc0, 0x95, 0x94, 0xd3, 0x05, 0xe1,
0x62, 0x4f, 0x4c, 0x31, 0x27, 0xe9, 0x1e, 0x39, 0x22, 0x49, 0x29, 0x19, 0xdf, 0x2b, 0x38, 0x93,
0xac, 0xda, 0x86, 0x7a, 0x8b, 0x3e, 0x99, 0x62, 0x31, 0xa5, 0x09, 0xe3, 0x45, 0x98, 0xb3, 0x39,
0x4e, 0xc3, 0x22, 0x2b, 0x27, 0x34, 0x17, 0xe1, 0x2a, 0x6f, 0x78, 0x69, 0xc2, 0xd8, 0x24, 0x23,
0xc6, 0xc9, 0xcb, 0xf2, 0xd5, 0x9e, 0xa4, 0x73, 0x22, 0x24, 0x9e, 0x17, 0x96, 0x10, 0x58, 0xc3,
0x3d, 0x17, 0xde, 0x84, 0x33, 0x3b, 0xc3, 0x09, 0xfe, 0x6a, 0x43, 0xff, 0x31, 0x2e, 0xf3, 0x64,
0x1a, 0x91, 0x9f, 0x4b, 0x22, 0x24, 0x1a, 0x40, 0x23, 0x99, 0xa7, 0xbe, 0xb7, 0xeb, 0x8d, 0x3a,
0x91, 0x5a, 0x22, 0x04, 0x9b, 0x98, 0x4f, 0x84, 0xbf, 0xb1, 0xdb, 0x18, 0x75, 0x22, 0xbd, 0x46,
0x4f, 0xa1, 0xc3, 0x89, 0x60, 0x25, 0x4f, 0x88, 0xf0, 0x1b, 0xbb, 0xde, 0xa8, 0x3b, 0xbe, 0x1a,
0xfe, 0x53, 0xe2, 0x36, 0xbe, 0x09, 0x19, 0x46, 0xce, 0x2e, 0x3a, 0x71, 0x81, 0x2e, 0x41, 0x57,
0xc8, 0x94, 0x95, 0x32, 0x2e, 0xb0, 0x9c, 0xfa, 0x9b, 0x3a, 0x3a, 0x18, 0xe8, 0x00, 0xcb, 0xa9,
0x25, 0x10, 0xce, 0x0d, 0x61, 0xab, 0x22, 0x10, 0xce, 0x35, 0x61, 0x00, 0x0d, 0x92, 0x2f, 0xfc,
0xa6, 0x4e, 0x52, 0x2d, 0x55, 0xde, 0xa5, 0x20, 0xdc, 0x6f, 0x69, 0xae, 0x5e, 0xa3, 0x8b, 0xd0,
0x96, 0x58, 0xcc, 0xe2, 0x94, 0x72, 0xbf, 0xad, 0xf1, 0x96, 0xda, 0xdf, 0xa7, 0x1c, 0x5d, 0x86,
0x1d, 0x97, 0x4f, 0x9c, 0xd1, 0x39, 0x95, 0xc2, 0xef, 0xec, 0x7a, 0xa3, 0x76, 0xb4, 0xed, 0xe0,
0xc7, 0x1a, 0x45, 0x37, 0xe0, 0xdc, 0x4b, 0x2c, 0x68, 0x12, 0x17, 0x9c, 0x25, 0x44, 0x88, 0x38,
0x99, 0x70, 0x56, 0x16, 0x3e, 0x28, 0xf6, 0xbd, 0x0d, 0xdf, 0x8b, 0x90, 0xfe, 0x7e, 0x60, 0x3e,
0xef, 0xeb, 0xaf, 0xe8, 0x3e, 0x34, 0xe7, 0xac, 0xcc, 0xa5, 0xf0, 0xbb, 0xbb, 0x8d, 0x51, 0x77,
0x7c, 0xa5, 0xe6, 0x71, 0x3d, 0x51, 0x46, 0x91, 0xb5, 0x45, 0xdf, 0x42, 0x2b, 0x25, 0x0b, 0xaa,
0x4e, 0xbd, 0xa7, 0xdd, 0x7c, 0x5e, 0xd3, 0xcd, 0x7d, 0x6d, 0x15, 0x39, 0x6b, 0x34, 0x85, 0xb3,
0x39, 0x91, 0xaf, 0x19, 0x9f, 0xc5, 0x54, 0xb0, 0x0c, 0x4b, 0xca, 0x72, 0xbf, 0xaf, 0x1b, 0xf9,
0x65, 0x4d, 0x97, 0x4f, 0x8d, 0xfd, 0x43, 0x67, 0x7e, 0x58, 0x90, 0x24, 0x1a, 0xe4, 0xa7, 0x50,
0x14, 0x40, 0x3f, 0x67, 0x71, 0x41, 0x17, 0x4c, 0xc6, 0x9c, 0x31, 0xe9, 0x6f, 0xeb, 0x53, 0xed,
0xe6, 0xec, 0x40, 0x61, 0x11, 0x63, 0x12, 0x8d, 0x60, 0x90, 0x92, 0x57, 0xb8, 0xcc, 0x64, 0x5c,
0xd0, 0x34, 0x9e, 0xb3, 0x94, 0xf8, 0x3b, 0xba, 0x3d, 0xdb, 0x16, 0x3f, 0xa0, 0xe9, 0x13, 0x96,
0x92, 0x65, 0x26, 0x2d, 0x12, 0xc3, 0x1c, 0xac, 0x30, 0x1f, 0x16, 0x89, 0x66, 0x7e, 0x0c, 0xfd,
0xa4, 0x28, 0x05, 0x91, 0xae, 0x3f, 0x67, 0x35, 0xad, 0x67, 0x40, 0xdb, 0x95, 0x0f, 0x01, 0x70,
0x96, 0xb1, 0xd7, 0x71, 0x82, 0x0b, 0xe1, 0x23, 0x7d, 0x79, 0x3a, 0x1a, 0xd9, 0xc7, 0x85, 0x40,
0x01, 0xf4, 0x12, 0x5c, 0xe0, 0x97, 0x34, 0xa3, 0x92, 0x12, 0xe1, 0xff, 0x4f, 0x13, 0x56, 0x30,
0x74, 0x05, 0x90, 0x09, 0x10, 0x2f, 0xc6, 0x31, 0x5b, 0x10, 0xce, 0x69, 0x4a, 0xfc, 0x73, 0x3a,
0xd8, 0xc0, 0x7c, 0x79, 0x3e, 0xfe, 0xce, 0xe2, 0xe8, 0xf8, 0x84, 0x7d, 0xed, 0x84, 0x7d, 0x5e,
0xf7, 0xf2, 0x51, 0x58, 0x6f, 0xf4, 0xc3, 0x95, 0x89, 0x0d, 0x4d, 0x29, 0xcf, 0xaf, 0xb9, 0x18,
0x0f, 0x72, 0xc9, 0x8f, 0xab, 0xd0, 0x15, 0x3c, 0xdc, 0x87, 0xf3, 0x6f, 0xa5, 0xaa, 0xd1, 0x99,
0x91, 0x63, 0x37, 0xf2, 0x33, 0x72, 0x8c, 0xce, 0xc1, 0xd6, 0x02, 0x67, 0x25, 0xf1, 0x37, 0x34,
0x66, 0x36, 0x5f, 0x6c, 0xdc, 0xf1, 0x82, 0x9f, 0x60, 0xdb, 0x45, 0x17, 0x05, 0xcb, 0x05, 0x41,
0x4f, 0xa1, 0x65, 0x07, 0x41, 0x7b, 0xe8, 0x8e, 0x6f, 0xd4, 0x2d, 0xc3, 0x0e, 0xc8, 0xa1, 0xc4,
0x92, 0x44, 0xce, 0x49, 0xd0, 0x87, 0xee, 0x0b, 0x4c, 0xa5, 0xad, 0x2e, 0xf8, 0x11, 0x7a, 0x66,
0xfb, 0x1f, 0x85, 0x7b, 0x0c, 0x3b, 0x87, 0xd3, 0x52, 0xa6, 0xec, 0x75, 0xee, 0x24, 0xf0, 0x02,
0x34, 0x05, 0x9d, 0xe4, 0x38, 0xb3, 0x47, 0x62, 0x77, 0xe8, 0x23, 0xe8, 0x4d, 0x38, 0x4e, 0x48,
0x5c, 0x10, 0x4e, 0x59, 0xaa, 0x0f, 0xa7, 0x11, 0x75, 0x35, 0x76, 0xa0, 0xa1, 0x00, 0xc1, 0xe0,
0xc4, 0x9b, 0xc9, 0x38, 0x98, 0xc2, 0x85, 0xef, 0x8b, 0x54, 0x05, 0xad, 0x94, 0xcf, 0x06, 0x5a,
0x51, 0x51, 0xef, 0x5f, 0xab, 0x68, 0x70, 0x11, 0xfe, 0xff, 0x46, 0x24, 0x9b, 0xc4, 0x00, 0xb6,
0x9f, 0x13, 0x2e, 0x28, 0x73, 0x55, 0x06, 0x9f, 0xc1, 0x4e, 0x85, 0xd8, 0xb3, 0xf5, 0xa1, 0xb5,
0x30, 0x90, 0xad, 0xdc, 0x6d, 0x83, 0x4f, 0xa1, 0xa7, 0xce, 0xad, 0xca, 0x7c, 0x08, 0x6d, 0x9a,
0x4b, 0xc2, 0x17, 0xf6, 0x90, 0x1a, 0x51, 0xb5, 0x0f, 0x5e, 0x40, 0xdf, 0x72, 0xad, 0xdb, 0x6f,
0x60, 0x4b, 0x28, 0x60, 0xcd, 0x12, 0x9f, 0x61, 0x31, 0x33, 0x8e, 0x8c, 0x79, 0x70, 0x19, 0xfa,
0x87, 0xba, 0x13, 0x6f, 0x6f, 0xd4, 0x96, 0x6b, 0x94, 0x2a, 0xd6, 0x11, 0x6d, 0xf9, 0x33, 0xe8,
0x3e, 0x38, 0x22, 0x89, 0x33, 0xbc, 0x05, 0xed, 0x94, 0xe0, 0x34, 0xa3, 0x39, 0xb1, 0x49, 0x0d,
0x43, 0xf3, 0x9c, 0x86, 0xee, 0x39, 0x0d, 0x9f, 0xb9, 0xe7, 0x34, 0xaa, 0xb8, 0xee, 0x71, 0xdc,
0x78, 0xf3, 0x71, 0x6c, 0x9c, 0x3c, 0x8e, 0xc1, 0x3e, 0xf4, 0x4c, 0x30, 0x5b, 0xff, 0x05, 0x68,
0xb2, 0x52, 0x16, 0xa5, 0xd4, 0xb1, 0x7a, 0x91, 0xdd, 0xa1, 0x0f, 0xa0, 0x43, 0x8e, 0xa8, 0x8c,
0x13, 0x25, 0x62, 0x1b, 0xba, 0x82, 0xb6, 0x02, 0xf6, 0x59, 0x4a, 0x82, 0x3f, 0x3d, 0xe8, 0x2d,
0xdf, 0x58, 0x15, 0xbb, 0xa0, 0xa9, 0xad, 0x54, 0x2d, 0xdf, 0x69, 0xbf, 0x74, 0x36, 0x8d, 0xe5,
0xb3, 0x41, 0x21, 0x6c, 0xaa, 0x3f, 0x0a, 0xfa, 0x89, 0x7d, 0x77, 0xd9, 0x9a, 0xa7, 0x14, 0x92,
0xb1, 0x79, 0x3c, 0xa3, 0x59, 0x46, 0x52, 0xfd, 0xee, 0xb6, 0xa3, 0x0e, 0x63, 0xf3, 0x47, 0x1a,
0x18, 0xff, 0xde, 0x81, 0xf6, 0x03, 0x3b, 0x67, 0xe8, 0x18, 0x9a, 0x46, 0x1c, 0xd0, 0xcd, 0xf7,
0x92, 0xb2, 0xe1, 0xad, 0x75, 0xcd, 0x6c, 0x7b, 0xcf, 0x20, 0x01, 0x9b, 0x4a, 0x26, 0xd0, 0xf5,
0xba, 0x1e, 0x96, 0x34, 0x66, 0x78, 0x63, 0x3d, 0xa3, 0x2a, 0xe8, 0xaf, 0xd0, 0x76, 0xd3, 0x8e,
0x6e, 0xd7, 0xf5, 0x71, 0x4a, 0x6d, 0x86, 0x77, 0xd6, 0x37, 0xac, 0x12, 0xf8, 0xcd, 0x83, 0x9d,
0x53, 0x13, 0x8f, 0xbe, 0xaa, 0xeb, 0xef, 0xed, 0xa2, 0x34, 0xbc, 0xfb, 0xde, 0xf6, 0x55, 0x5a,
0xbf, 0x40, 0xcb, 0x4a, 0x0b, 0xaa, 0xdd, 0xd1, 0x55, 0x75, 0x1a, 0xde, 0x5e, 0xdb, 0xae, 0x8a,
0x7e, 0x04, 0x5b, 0x5a, 0x36, 0x50, 0xed, 0xb6, 0x2e, 0x4b, 0xdb, 0xf0, 0xe6, 0x9a, 0x56, 0x2e,
0xee, 0x55, 0x4f, 0xdd, 0x7f, 0xa3, 0x3b, 0xf5, 0xef, 0xff, 0x8a, 0xa0, 0xd5, 0xbf, 0xff, 0xa7,
0xe4, 0x4d, 0xdf, 0x7f, 0x35, 0x86, 0xf5, 0xef, 0xff, 0x92, 0x1c, 0xd6, 0xbf, 0xff, 0xcb, 0xb2,
0x16, 0x9c, 0x41, 0x7f, 0x78, 0xd0, 0x57, 0xd0, 0xa1, 0xe4, 0x04, 0xcf, 0x69, 0x3e, 0x41, 0x77,
0x6b, 0x6a, 0xbb, 0xb2, 0x32, 0xfa, 0x6e, 0x2d, 0x5d, 0x2a, 0x5f, 0xbf, 0xbf, 0x03, 0x97, 0xd6,
0xc8, 0xbb, 0xea, 0xdd, 0x6b, 0xfd, 0xb0, 0x65, 0x24, 0xad, 0xa9, 0x7f, 0xae, 0xff, 0x1d, 0x00,
0x00, 0xff, 0xff, 0x86, 0x06, 0x47, 0x8b, 0x85, 0x0d, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.

View File

@@ -50,6 +50,8 @@ message LaunchRequest {
string cpuset_cgroup = 17;
repeated string allow_caps = 18;
repeated string capabilities = 19;
string cgroup_v2_override = 20;
map<string,string> cgroup_v1_override = 21;
}
message LaunchResponse {

View File

@@ -37,6 +37,16 @@ The `raw_exec` driver supports the following configuration in the job spec:
variables](/nomad/docs/runtime/interpolation) will be interpreted before
launching the task.
- `cgroup_v1_override` - (Optional) A map of controller names to paths. The
task will be added to these cgroups. The task will fail if these cgroups do
not exist. **WARNING:** May conflict with other Nomad driver's cgroups and
have unintended side effects.
- `cgroup_v2_override` - (Optional) Adds the task to a unified cgroup path.
Paths may be relative to the cgroupfs root or absolute. **WARNING:** May
conflict with other Nomad driver's cgroups and have unintended side
effects.
~> The `task.user` field cannot be set on a Task using the `raw_exec` driver if
the Nomad client has been hardened according to the [production][hardening] guide.