mirror of
https://github.com/kemko/nomad.git
synced 2026-01-01 16:05:42 +03:00
core: propagate remote task handles
Add a new driver capability: RemoteTasks. When a task is run by a driver with RemoteTasks set, its TaskHandle will be propagated to the server in its allocation's TaskState. If the task is replaced due to a down node or draining, its TaskHandle will be propagated to its replacement allocation. This allows tasks to be scheduled in remote systems whose lifecycles are disconnected from the Nomad node's lifecycle. See https://github.com/hashicorp/nomad-driver-ecs for an example ECS remote task driver.
This commit is contained in:
@@ -915,6 +915,15 @@ type TaskState struct {
|
||||
StartedAt time.Time
|
||||
FinishedAt time.Time
|
||||
Events []*TaskEvent
|
||||
|
||||
// Experimental - TaskHandle is based on drivers.TaskHandle and used
|
||||
// by remote task drivers to migrate task handles between allocations.
|
||||
TaskHandle *TaskHandle
|
||||
}
|
||||
|
||||
type TaskHandle struct {
|
||||
Version int
|
||||
DriverState []byte
|
||||
}
|
||||
|
||||
const (
|
||||
|
||||
@@ -13,20 +13,22 @@ import (
|
||||
// NewDriverHandle returns a handle for task operations on a specific task
|
||||
func NewDriverHandle(driver drivers.DriverPlugin, taskID string, task *structs.Task, net *drivers.DriverNetwork) *DriverHandle {
|
||||
return &DriverHandle{
|
||||
driver: driver,
|
||||
net: net,
|
||||
taskID: taskID,
|
||||
task: task,
|
||||
driver: driver,
|
||||
net: net,
|
||||
taskID: taskID,
|
||||
killSignal: task.KillSignal,
|
||||
killTimeout: task.KillTimeout,
|
||||
}
|
||||
}
|
||||
|
||||
// DriverHandle encapsulates a driver plugin client and task identifier and exposes
|
||||
// an api to perform driver operations on the task
|
||||
type DriverHandle struct {
|
||||
driver drivers.DriverPlugin
|
||||
net *drivers.DriverNetwork
|
||||
task *structs.Task
|
||||
taskID string
|
||||
driver drivers.DriverPlugin
|
||||
net *drivers.DriverNetwork
|
||||
taskID string
|
||||
killSignal string
|
||||
killTimeout time.Duration
|
||||
}
|
||||
|
||||
func (h *DriverHandle) ID() string {
|
||||
@@ -37,12 +39,13 @@ func (h *DriverHandle) WaitCh(ctx context.Context) (<-chan *drivers.ExitResult,
|
||||
return h.driver.WaitTask(ctx, h.taskID)
|
||||
}
|
||||
|
||||
func (h *DriverHandle) Update(task *structs.Task) error {
|
||||
return nil
|
||||
// SetKillSignal allows overriding the signal sent to kill the task.
|
||||
func (h *DriverHandle) SetKillSignal(signal string) {
|
||||
h.killSignal = signal
|
||||
}
|
||||
|
||||
func (h *DriverHandle) Kill() error {
|
||||
return h.driver.StopTask(h.taskID, h.task.KillTimeout, h.task.KillSignal)
|
||||
return h.driver.StopTask(h.taskID, h.killTimeout, h.killSignal)
|
||||
}
|
||||
|
||||
func (h *DriverHandle) Stats(ctx context.Context, interval time.Duration) (<-chan *cstructs.TaskResourceUsage, error) {
|
||||
|
||||
124
client/allocrunner/taskrunner/remotetask_hook.go
Normal file
124
client/allocrunner/taskrunner/remotetask_hook.go
Normal file
@@ -0,0 +1,124 @@
|
||||
package taskrunner
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
hclog "github.com/hashicorp/go-hclog"
|
||||
"github.com/hashicorp/nomad/client/allocrunner/interfaces"
|
||||
"github.com/hashicorp/nomad/nomad/structs"
|
||||
"github.com/hashicorp/nomad/plugins/drivers"
|
||||
)
|
||||
|
||||
var _ interfaces.TaskPrestartHook = (*remoteTaskHook)(nil)
|
||||
var _ interfaces.TaskPreKillHook = (*remoteTaskHook)(nil)
|
||||
|
||||
// remoteTaskHook reattaches to remotely executing tasks.
|
||||
type remoteTaskHook struct {
|
||||
tr *TaskRunner
|
||||
|
||||
logger hclog.Logger
|
||||
}
|
||||
|
||||
func newRemoteTaskHook(tr *TaskRunner, logger hclog.Logger) interfaces.TaskHook {
|
||||
h := &remoteTaskHook{
|
||||
tr: tr,
|
||||
}
|
||||
h.logger = logger.Named(h.Name())
|
||||
return h
|
||||
}
|
||||
|
||||
func (h *remoteTaskHook) Name() string {
|
||||
return "remote_task"
|
||||
}
|
||||
|
||||
// Prestart performs 2 remote task driver related tasks:
|
||||
// 1. If there is no local handle, see if there is a handle propagated from a
|
||||
// previous alloc to be restored.
|
||||
// 2. If the alloc is lost make sure the task signal is set to detach instead
|
||||
// of kill.
|
||||
func (h *remoteTaskHook) Prestart(ctx context.Context, req *interfaces.TaskPrestartRequest, resp *interfaces.TaskPrestartResponse) error {
|
||||
if h.tr.getDriverHandle() != nil {
|
||||
// Driver handle already exists so don't try to load remote
|
||||
// task handle
|
||||
return nil
|
||||
}
|
||||
|
||||
h.tr.stateLock.Lock()
|
||||
th := drivers.NewTaskHandleFromState(h.tr.state)
|
||||
h.tr.stateLock.Unlock()
|
||||
|
||||
// Task handle will be nil if there was no previous allocation or if
|
||||
// this is a destructive update
|
||||
if th == nil {
|
||||
resp.Done = true
|
||||
return nil
|
||||
}
|
||||
|
||||
// The task config is unique per invocation so recreate it here
|
||||
th.Config = h.tr.buildTaskConfig()
|
||||
|
||||
if err := h.tr.driver.RecoverTask(th); err != nil {
|
||||
// Soft error here to let a new instance get started instead of
|
||||
// failing the task since retrying is unlikely to help.
|
||||
h.logger.Error("error recovering task state", "error", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
taskInfo, err := h.tr.driver.InspectTask(th.Config.ID)
|
||||
if err != nil {
|
||||
// Soft error here to let a new instance get started instead of
|
||||
// failing the task since retrying is unlikely to help.
|
||||
h.logger.Error("error inspecting recovered task state", "error", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
h.tr.setDriverHandle(NewDriverHandle(h.tr.driver, th.Config.ID, h.tr.Task(), taskInfo.NetworkOverride))
|
||||
|
||||
h.tr.stateLock.Lock()
|
||||
h.tr.localState.TaskHandle = th
|
||||
h.tr.localState.DriverNetwork = taskInfo.NetworkOverride
|
||||
h.tr.stateLock.Unlock()
|
||||
|
||||
// Ensure the signal is set according to the allocation's state
|
||||
h.setSignal(h.tr.Alloc())
|
||||
|
||||
// Emit TaskStarted manually since the normal task runner logic will
|
||||
// treat this task like a restored task and skip emitting started.
|
||||
h.tr.UpdateState(structs.TaskStateRunning, structs.NewTaskEvent(structs.TaskStarted))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// PreKilling tells the remote task driver to detach a remote task instead of
|
||||
// stopping it.
|
||||
func (h *remoteTaskHook) PreKilling(ctx context.Context, req *interfaces.TaskPreKillRequest, resp *interfaces.TaskPreKillResponse) error {
|
||||
alloc := h.tr.Alloc()
|
||||
h.setSignal(alloc)
|
||||
return nil
|
||||
}
|
||||
|
||||
// setSignal to detach if the allocation is lost or draining. Safe to call
|
||||
// multiple times as it only transitions to using detach -- never back to kill.
|
||||
func (h *remoteTaskHook) setSignal(alloc *structs.Allocation) {
|
||||
driverHandle := h.tr.getDriverHandle()
|
||||
if driverHandle == nil {
|
||||
// Nothing to do exit early
|
||||
return
|
||||
}
|
||||
|
||||
switch {
|
||||
case alloc.ClientStatus == structs.AllocClientStatusLost:
|
||||
// Continue on; lost allocs should just detach
|
||||
h.logger.Debug("detaching from remote task since alloc was lost")
|
||||
case alloc.DesiredTransition.ShouldMigrate():
|
||||
// Continue on; migrating allocs should just detach
|
||||
h.logger.Debug("detaching from remote task since alloc was drained")
|
||||
default:
|
||||
// Nothing to do exit early
|
||||
return
|
||||
}
|
||||
|
||||
// Set DetachSignal to indicate to the remote task driver that it
|
||||
// should detach this remote task and ignore it.
|
||||
driverHandle.SetKillSignal(drivers.DetachSignal)
|
||||
}
|
||||
@@ -19,6 +19,7 @@ var _ interfaces.TaskPoststartHook = &serviceHook{}
|
||||
var _ interfaces.TaskPreKillHook = &serviceHook{}
|
||||
var _ interfaces.TaskExitedHook = &serviceHook{}
|
||||
var _ interfaces.TaskStopHook = &serviceHook{}
|
||||
var _ interfaces.TaskUpdateHook = &serviceHook{}
|
||||
|
||||
type serviceHookConfig struct {
|
||||
alloc *structs.Allocation
|
||||
|
||||
@@ -377,7 +377,8 @@ func NewTaskRunner(config *Config) (*TaskRunner, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Initialize the runners hooks.
|
||||
// Initialize the runners hooks. Must come after initDriver so hooks
|
||||
// can use tr.driverCapabilities
|
||||
tr.initHooks()
|
||||
|
||||
// Initialize base labels
|
||||
@@ -496,6 +497,7 @@ func (tr *TaskRunner) Run() {
|
||||
tr.logger.Info("task failed to restore; waiting to contact server before restarting")
|
||||
select {
|
||||
case <-tr.killCtx.Done():
|
||||
tr.logger.Info("task killed while waiting for server contact")
|
||||
case <-tr.shutdownCtx.Done():
|
||||
return
|
||||
case <-tr.serversContactedCh:
|
||||
@@ -637,11 +639,12 @@ MAIN:
|
||||
}
|
||||
|
||||
func (tr *TaskRunner) shouldShutdown() bool {
|
||||
if tr.alloc.ClientTerminalStatus() {
|
||||
alloc := tr.Alloc()
|
||||
if alloc.ClientTerminalStatus() {
|
||||
return true
|
||||
}
|
||||
|
||||
if !tr.IsPoststopTask() && tr.alloc.ServerTerminalStatus() {
|
||||
if !tr.IsPoststopTask() && alloc.ServerTerminalStatus() {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -1142,6 +1145,12 @@ func (tr *TaskRunner) UpdateState(state string, event *structs.TaskEvent) {
|
||||
tr.logger.Error("error persisting task state", "error", err, "event", event, "state", state)
|
||||
}
|
||||
|
||||
// Store task handle for remote tasks
|
||||
if tr.driverCapabilities != nil && tr.driverCapabilities.RemoteTasks {
|
||||
tr.logger.Trace("storing remote task handle state")
|
||||
tr.localState.TaskHandle.Store(tr.state)
|
||||
}
|
||||
|
||||
// Notify the alloc runner of the transition
|
||||
tr.stateUpdater.TaskStateUpdated()
|
||||
}
|
||||
|
||||
@@ -152,6 +152,12 @@ func (tr *TaskRunner) initHooks() {
|
||||
consul: tr.consulServiceClient,
|
||||
logger: hookLogger,
|
||||
}))
|
||||
|
||||
// If this task driver has remote capabilities, add the remote task
|
||||
// hook.
|
||||
if tr.driverCapabilities.RemoteTasks {
|
||||
tr.runnerHooks = append(tr.runnerHooks, newRemoteTaskHook(tr, hookLogger))
|
||||
}
|
||||
}
|
||||
|
||||
func (tr *TaskRunner) emitHookError(err error, hookName string) {
|
||||
|
||||
@@ -2239,7 +2239,6 @@ func (c *Client) runAllocs(update *allocUpdates) {
|
||||
|
||||
// Update the existing allocations
|
||||
for _, update := range diff.updated {
|
||||
c.logger.Trace("updating alloc", "alloc_id", update.ID, "index", update.AllocModifyIndex)
|
||||
c.updateAlloc(update)
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ import (
|
||||
_ "github.com/hashicorp/nomad/e2e/periodic"
|
||||
_ "github.com/hashicorp/nomad/e2e/podman"
|
||||
_ "github.com/hashicorp/nomad/e2e/quotas"
|
||||
_ "github.com/hashicorp/nomad/e2e/remotetasks"
|
||||
_ "github.com/hashicorp/nomad/e2e/rescheduling"
|
||||
_ "github.com/hashicorp/nomad/e2e/scaling"
|
||||
_ "github.com/hashicorp/nomad/e2e/scalingpolicies"
|
||||
|
||||
43
e2e/remotetasks/input/ecs.nomad
Normal file
43
e2e/remotetasks/input/ecs.nomad
Normal file
@@ -0,0 +1,43 @@
|
||||
variable "subnets" {
|
||||
type = list(string)
|
||||
description = "Subnet IDs task will run in."
|
||||
}
|
||||
|
||||
variable "security_groups" {
|
||||
type = list(string)
|
||||
description = "Security Group IDs task will run in."
|
||||
}
|
||||
|
||||
job "nomad-ecs-e2e" {
|
||||
datacenters = ["dc1"]
|
||||
|
||||
group "ecs-remote-task-e2e" {
|
||||
restart {
|
||||
attempts = 0
|
||||
mode = "fail"
|
||||
}
|
||||
|
||||
reschedule {
|
||||
delay = "5s"
|
||||
}
|
||||
|
||||
task "http-server" {
|
||||
driver = "ecs"
|
||||
kill_timeout = "1m" // increased from default to accomodate ECS.
|
||||
|
||||
config {
|
||||
task {
|
||||
launch_type = "FARGATE"
|
||||
task_definition = "nomad-rtd-e2e"
|
||||
network_configuration {
|
||||
aws_vpc_configuration {
|
||||
assign_public_ip = "ENABLED"
|
||||
security_groups = var.security_groups
|
||||
subnets = var.subnets
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
433
e2e/remotetasks/remotetasks.go
Normal file
433
e2e/remotetasks/remotetasks.go
Normal file
@@ -0,0 +1,433 @@
|
||||
package remotetasks
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/session"
|
||||
"github.com/aws/aws-sdk-go/service/ecs"
|
||||
"github.com/hashicorp/nomad/api"
|
||||
"github.com/hashicorp/nomad/e2e/e2eutil"
|
||||
"github.com/hashicorp/nomad/e2e/framework"
|
||||
"github.com/hashicorp/nomad/helper/uuid"
|
||||
"github.com/hashicorp/nomad/jobspec2"
|
||||
"github.com/hashicorp/nomad/plugins/base"
|
||||
"github.com/hashicorp/nomad/testutil"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
const (
|
||||
ecsTaskStatusDeactivating = "DEACTIVATING"
|
||||
ecsTaskStatusStopping = "STOPPING"
|
||||
ecsTaskStatusDeprovisioning = "DEPROVISIONING"
|
||||
ecsTaskStatusStopped = "STOPPED"
|
||||
ecsTaskStatusRunning = "RUNNING"
|
||||
)
|
||||
|
||||
type RemoteTasksTest struct {
|
||||
framework.TC
|
||||
jobIDs []string
|
||||
}
|
||||
|
||||
func init() {
|
||||
framework.AddSuites(&framework.TestSuite{
|
||||
Component: "RemoteTasks",
|
||||
CanRunLocal: true,
|
||||
Cases: []framework.TestCase{
|
||||
new(RemoteTasksTest),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func (tc *RemoteTasksTest) BeforeAll(f *framework.F) {
|
||||
e2eutil.WaitForLeader(f.T(), tc.Nomad())
|
||||
e2eutil.WaitForNodesReady(f.T(), tc.Nomad(), 2)
|
||||
}
|
||||
|
||||
func (tc *RemoteTasksTest) AfterEach(f *framework.F) {
|
||||
nomadClient := tc.Nomad()
|
||||
|
||||
// Mark all nodes eligible
|
||||
nodesAPI := tc.Nomad().Nodes()
|
||||
nodes, _, _ := nodesAPI.List(nil)
|
||||
for _, node := range nodes {
|
||||
nodesAPI.ToggleEligibility(node.ID, true, nil)
|
||||
}
|
||||
|
||||
jobs := nomadClient.Jobs()
|
||||
// Stop all jobs in test
|
||||
for _, id := range tc.jobIDs {
|
||||
jobs.Deregister(id, true, nil)
|
||||
}
|
||||
tc.jobIDs = []string{}
|
||||
|
||||
// Garbage collect
|
||||
nomadClient.System().GarbageCollect()
|
||||
}
|
||||
|
||||
// TestECSJob asserts an ECS job may be started and is cleaned up when stopped.
|
||||
func (tc *RemoteTasksTest) TestECSJob(f *framework.F) {
|
||||
t := f.T()
|
||||
|
||||
ecsClient := ecsOrSkip(t, tc.Nomad())
|
||||
|
||||
jobID := "ecsjob-" + uuid.Generate()[0:8]
|
||||
tc.jobIDs = append(tc.jobIDs, jobID)
|
||||
_, allocs := registerECSJobs(t, tc.Nomad(), jobID)
|
||||
require.Len(t, allocs, 1)
|
||||
allocID := allocs[0].ID
|
||||
e2eutil.WaitForAllocsRunning(t, tc.Nomad(), []string{allocID})
|
||||
|
||||
// We need to go from Allocation -> ECS ARN, so grab the updated
|
||||
// allocation's task state.
|
||||
arn := arnForAlloc(t, tc.Nomad().Allocations(), allocID)
|
||||
|
||||
// Use ARN to lookup status of ECS task in AWS
|
||||
ensureECSRunning(t, ecsClient, arn)
|
||||
|
||||
t.Logf("Task %s is running!", arn)
|
||||
|
||||
// Stop the job
|
||||
e2eutil.WaitForJobStopped(t, tc.Nomad(), jobID)
|
||||
|
||||
// Ensure it is stopped in ECS
|
||||
input := ecs.DescribeTasksInput{
|
||||
Cluster: aws.String("nomad-rtd-e2e"),
|
||||
Tasks: []*string{aws.String(arn)},
|
||||
}
|
||||
testutil.WaitForResult(func() (bool, error) {
|
||||
resp, err := ecsClient.DescribeTasks(&input)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
status := *resp.Tasks[0].LastStatus
|
||||
return status == ecsTaskStatusStopped, fmt.Errorf("ecs task is not stopped: %s", status)
|
||||
}, func(err error) {
|
||||
t.Fatalf("error retrieving ecs task status: %v", err)
|
||||
})
|
||||
}
|
||||
|
||||
// TestECSDrain asserts an ECS job may be started, drained from one node, and
|
||||
// is managed by a new node without stopping and restarting the remote task.
|
||||
func (tc *RemoteTasksTest) TestECSDrain(f *framework.F) {
|
||||
t := f.T()
|
||||
|
||||
ecsClient := ecsOrSkip(t, tc.Nomad())
|
||||
|
||||
jobID := "ecsjob-" + uuid.Generate()[0:8]
|
||||
tc.jobIDs = append(tc.jobIDs, jobID)
|
||||
_, allocs := registerECSJobs(t, tc.Nomad(), jobID)
|
||||
require.Len(t, allocs, 1)
|
||||
origNode := allocs[0].NodeID
|
||||
origAlloc := allocs[0].ID
|
||||
e2eutil.WaitForAllocsRunning(t, tc.Nomad(), []string{origAlloc})
|
||||
|
||||
arn := arnForAlloc(t, tc.Nomad().Allocations(), origAlloc)
|
||||
ensureECSRunning(t, ecsClient, arn)
|
||||
|
||||
t.Logf("Task %s is running! Now to drain the node.", arn)
|
||||
|
||||
// Drain the node
|
||||
_, err := tc.Nomad().Nodes().UpdateDrain(
|
||||
origNode,
|
||||
&api.DrainSpec{Deadline: 30 * time.Second},
|
||||
false,
|
||||
nil,
|
||||
)
|
||||
require.NoError(t, err, "error draining original node")
|
||||
|
||||
// Wait for new alloc to be running
|
||||
var newAlloc *api.AllocationListStub
|
||||
qopts := &api.QueryOptions{}
|
||||
testutil.WaitForResult(func() (bool, error) {
|
||||
allocs, resp, err := tc.Nomad().Jobs().Allocations(jobID, false, qopts)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("error retrieving allocations for job: %w", err)
|
||||
}
|
||||
|
||||
qopts.WaitIndex = resp.LastIndex
|
||||
|
||||
if len(allocs) > 2 {
|
||||
return false, fmt.Errorf("expected 1 or 2 allocs but found %d", len(allocs))
|
||||
}
|
||||
|
||||
for _, alloc := range allocs {
|
||||
if alloc.ID == origAlloc {
|
||||
// This is the old alloc, skip it
|
||||
continue
|
||||
}
|
||||
|
||||
newAlloc = alloc
|
||||
|
||||
if newAlloc.ClientStatus == "running" {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if newAlloc == nil {
|
||||
return false, fmt.Errorf("no new alloc found")
|
||||
}
|
||||
if newAlloc.ClientStatus != "running" {
|
||||
return false, fmt.Errorf("expected new alloc (%s) to be running but found: %s",
|
||||
newAlloc.ID, newAlloc.ClientStatus)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}, func(err error) {
|
||||
t.Fatalf("error waiting for new alloc to be running: %v", err)
|
||||
})
|
||||
|
||||
// Make sure the ARN hasn't changed by looking up the new alloc's ARN
|
||||
newARN := arnForAlloc(t, tc.Nomad().Allocations(), newAlloc.ID)
|
||||
|
||||
assert.Equal(t, arn, newARN, "unexpected new ARN")
|
||||
}
|
||||
|
||||
// TestECSDeployment asserts a new ECS task is started when an ECS job is
|
||||
// deployed.
|
||||
func (tc *RemoteTasksTest) TestECSDeployment(f *framework.F) {
|
||||
t := f.T()
|
||||
|
||||
ecsClient := ecsOrSkip(t, tc.Nomad())
|
||||
|
||||
jobID := "ecsjob-" + uuid.Generate()[0:8]
|
||||
tc.jobIDs = append(tc.jobIDs, jobID)
|
||||
job, origAllocs := registerECSJobs(t, tc.Nomad(), jobID)
|
||||
require.Len(t, origAllocs, 1)
|
||||
origAllocID := origAllocs[0].ID
|
||||
e2eutil.WaitForAllocsRunning(t, tc.Nomad(), []string{origAllocID})
|
||||
|
||||
// We need to go from Allocation -> ECS ARN, so grab the updated
|
||||
// allocation's task state.
|
||||
origARN := arnForAlloc(t, tc.Nomad().Allocations(), origAllocID)
|
||||
|
||||
// Use ARN to lookup status of ECS task in AWS
|
||||
ensureECSRunning(t, ecsClient, origARN)
|
||||
|
||||
t.Logf("Task %s is running! Updating...", origARN)
|
||||
|
||||
// Force a deployment by updating meta
|
||||
job.Meta = map[string]string{
|
||||
"updated": time.Now().Format(time.RFC3339Nano),
|
||||
}
|
||||
|
||||
// Register updated job
|
||||
resp, _, err := tc.Nomad().Jobs().Register(job, nil)
|
||||
require.NoError(t, err, "error registering updated job")
|
||||
require.NotEmpty(t, resp.EvalID, "no eval id created when registering updated job")
|
||||
|
||||
// Wait for new alloc to be running
|
||||
var newAlloc *api.AllocationListStub
|
||||
testutil.WaitForResult(func() (bool, error) {
|
||||
allocs, _, err := tc.Nomad().Jobs().Allocations(jobID, false, nil)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
for _, a := range allocs {
|
||||
if a.ID == origAllocID {
|
||||
if a.ClientStatus == "complete" {
|
||||
// Original alloc stopped as expected!
|
||||
continue
|
||||
}
|
||||
|
||||
// Original alloc is still running
|
||||
newAlloc = nil
|
||||
return false, fmt.Errorf("original alloc not yet terminal. "+
|
||||
"client status: %s; desired status: %s",
|
||||
a.ClientStatus, a.DesiredStatus)
|
||||
}
|
||||
|
||||
if a.ClientStatus != "running" {
|
||||
return false, fmt.Errorf("new alloc is not running: %s", a.ClientStatus)
|
||||
}
|
||||
|
||||
if newAlloc != nil {
|
||||
return false, fmt.Errorf("found 2 replacement allocs: %s and %s",
|
||||
a.ID, newAlloc.ID)
|
||||
}
|
||||
|
||||
newAlloc = a
|
||||
}
|
||||
|
||||
return newAlloc != nil, fmt.Errorf("no new alloc found for updated job")
|
||||
}, func(err error) {
|
||||
require.NoError(t, err, "error waiting for updated alloc")
|
||||
})
|
||||
|
||||
newARN := arnForAlloc(t, tc.Nomad().Allocations(), newAlloc.ID)
|
||||
t.Logf("Task %s is updated!", newARN)
|
||||
require.NotEqual(t, origARN, newARN, "expected new ARN")
|
||||
|
||||
// Ensure original ARN is stopped in ECS
|
||||
input := ecs.DescribeTasksInput{
|
||||
Cluster: aws.String("nomad-rtd-e2e"),
|
||||
Tasks: []*string{aws.String(origARN)},
|
||||
}
|
||||
testutil.WaitForResult(func() (bool, error) {
|
||||
resp, err := ecsClient.DescribeTasks(&input)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
status := *resp.Tasks[0].LastStatus
|
||||
return status == ecsTaskStatusStopped, fmt.Errorf("original ecs task is not stopped: %s", status)
|
||||
}, func(err error) {
|
||||
t.Fatalf("error retrieving ecs task status for original ARN: %v", err)
|
||||
})
|
||||
}
|
||||
|
||||
// ecsOrSkip returns an AWS ECS client or skips the test if ECS is unreachable
|
||||
// by the test runner or the ECS remote task driver isn't healthy.
|
||||
func ecsOrSkip(t *testing.T, nomadClient *api.Client) *ecs.ECS {
|
||||
awsSession := session.Must(session.NewSession())
|
||||
|
||||
ecsClient := ecs.New(awsSession, aws.NewConfig().WithRegion("us-east-1"))
|
||||
|
||||
_, err := ecsClient.ListClusters(&ecs.ListClustersInput{})
|
||||
if err != nil {
|
||||
t.Skipf("Skipping ECS Remote Task Driver Task. Error querying AWS ECS API: %v", err)
|
||||
}
|
||||
|
||||
testutil.WaitForResult(func() (bool, error) {
|
||||
nodes, _, err := nomadClient.Nodes().List(nil)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("error retrieving node listing: %w", err)
|
||||
}
|
||||
|
||||
notReady := 0
|
||||
notEligible := 0
|
||||
noECS := 0
|
||||
notHealthy := 0
|
||||
ready := 0
|
||||
for _, n := range nodes {
|
||||
if n.Status != "ready" {
|
||||
notReady++
|
||||
continue
|
||||
}
|
||||
if n.SchedulingEligibility != "eligible" {
|
||||
notEligible++
|
||||
continue
|
||||
}
|
||||
ecsDriver, ok := n.Drivers["ecs"]
|
||||
if !ok {
|
||||
noECS++
|
||||
continue
|
||||
}
|
||||
if !ecsDriver.Healthy {
|
||||
notHealthy++
|
||||
continue
|
||||
}
|
||||
ready++
|
||||
}
|
||||
|
||||
return ready > 1, fmt.Errorf("expected 2 nodes with healthy ecs drivers but found: "+
|
||||
"not_ready=%d ineligible=%d no_driver=%d unhealthy=%d ok=%d",
|
||||
notReady, notEligible, noECS, notHealthy, ready)
|
||||
}, func(err error) {
|
||||
if err != nil {
|
||||
t.Skipf("Skipping Remote Task Driver tests due to: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
return ecsClient
|
||||
}
|
||||
|
||||
// arnForAlloc retrieves the ARN for a running allocation.
|
||||
func arnForAlloc(t *testing.T, allocAPI *api.Allocations, allocID string) string {
|
||||
t.Logf("Retrieving ARN for alloc=%s", allocID)
|
||||
ecsState := struct {
|
||||
ARN string
|
||||
}{}
|
||||
testutil.WaitForResult(func() (bool, error) {
|
||||
alloc, _, err := allocAPI.Info(allocID, nil)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
state := alloc.TaskStates["http-server"]
|
||||
if state == nil {
|
||||
return false, fmt.Errorf("no task state for http-server (%d task states)", len(alloc.TaskStates))
|
||||
}
|
||||
if state.TaskHandle == nil {
|
||||
return false, fmt.Errorf("no task handle for http-server")
|
||||
}
|
||||
if len(state.TaskHandle.DriverState) == 0 {
|
||||
return false, fmt.Errorf("no driver state for task handle")
|
||||
}
|
||||
if err := base.MsgPackDecode(state.TaskHandle.DriverState, &ecsState); err != nil {
|
||||
return false, fmt.Errorf("error decoding driver state: %w", err)
|
||||
}
|
||||
if ecsState.ARN == "" {
|
||||
return false, fmt.Errorf("ARN is empty despite DriverState being %d bytes", len(state.TaskHandle.DriverState))
|
||||
}
|
||||
return true, nil
|
||||
}, func(err error) {
|
||||
t.Fatalf("error getting ARN: %v", err)
|
||||
})
|
||||
t.Logf("Retrieved ARN=%s for alloc=%s", ecsState.ARN, allocID)
|
||||
|
||||
return ecsState.ARN
|
||||
}
|
||||
|
||||
// ensureECSRunning asserts that the given ARN is a running ECS task.
|
||||
func ensureECSRunning(t *testing.T, ecsClient *ecs.ECS, arn string) {
|
||||
t.Logf("Ensuring ARN=%s is running", arn)
|
||||
input := ecs.DescribeTasksInput{
|
||||
Cluster: aws.String("nomad-rtd-e2e"),
|
||||
Tasks: []*string{aws.String(arn)},
|
||||
}
|
||||
testutil.WaitForResult(func() (bool, error) {
|
||||
resp, err := ecsClient.DescribeTasks(&input)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
status := *resp.Tasks[0].LastStatus
|
||||
return status == ecsTaskStatusRunning, fmt.Errorf("ecs task is not running: %s", status)
|
||||
}, func(err error) {
|
||||
t.Fatalf("error retrieving ecs task status: %v", err)
|
||||
})
|
||||
t.Logf("ARN=%s is running", arn)
|
||||
}
|
||||
|
||||
// registerECSJobs registers an ECS job and returns it and its allocation
|
||||
// stubs.
|
||||
func registerECSJobs(t *testing.T, nomadClient *api.Client, jobID string) (*api.Job, []*api.AllocationListStub) {
|
||||
const (
|
||||
jobPath = "remotetasks/input/ecs.nomad"
|
||||
varPath = "remotetasks/input/ecs.vars"
|
||||
)
|
||||
|
||||
jobBytes, err := os.ReadFile(jobPath)
|
||||
require.NoError(t, err, "error reading job file")
|
||||
|
||||
job, err := jobspec2.ParseWithConfig(&jobspec2.ParseConfig{
|
||||
Path: jobPath,
|
||||
Body: jobBytes,
|
||||
VarFiles: []string{varPath},
|
||||
Strict: true,
|
||||
})
|
||||
require.NoErrorf(t, err, "error parsing jobspec from %s with var file %s", jobPath, varPath)
|
||||
|
||||
job.ID = &jobID
|
||||
job.Name = &jobID
|
||||
|
||||
// Register job
|
||||
resp, _, err := nomadClient.Jobs().Register(job, nil)
|
||||
require.NoError(t, err, "error registering job")
|
||||
require.NotEmpty(t, resp.EvalID, "no eval id created when registering job")
|
||||
|
||||
var allocs []*api.AllocationListStub
|
||||
testutil.WaitForResult(func() (bool, error) {
|
||||
allocs, _, err = nomadClient.Jobs().Allocations(jobID, false, nil)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return len(allocs) > 0, fmt.Errorf("no allocs found")
|
||||
}, func(err error) {
|
||||
require.NoErrorf(t, err, "error retrieving allocations for %s", jobID)
|
||||
})
|
||||
return job, allocs
|
||||
}
|
||||
157
e2e/terraform/.terraform.lock.hcl
generated
157
e2e/terraform/.terraform.lock.hcl
generated
@@ -2,99 +2,98 @@
|
||||
# Manual edits may be lost in future updates.
|
||||
|
||||
provider "registry.terraform.io/hashicorp/aws" {
|
||||
version = "3.22.0"
|
||||
version = "3.37.0"
|
||||
hashes = [
|
||||
"h1:8aWXjFcmEi64P0TMHOCQXWws+/SmvJQrNvHlzdktKOM=",
|
||||
"h1:f/Tz8zv1Zb78ZaiyJkQ0MGIViZwbYrLuQk3kojPM91c=",
|
||||
"zh:4a9a66caf1964cdd3b61fb3ebb0da417195a5529cb8e496f266b0778335d11c8",
|
||||
"zh:514f2f006ae68db715d86781673faf9483292deab235c7402ff306e0e92ea11a",
|
||||
"zh:5277b61109fddb9011728f6650ef01a639a0590aeffe34ed7de7ba10d0c31803",
|
||||
"zh:67784dc8c8375ab37103eea1258c3334ee92be6de033c2b37e3a2a65d0005142",
|
||||
"zh:76d4c8be2ca4a3294fb51fb58de1fe03361d3bc403820270cc8e71a04c5fa806",
|
||||
"zh:8f90b1cfdcf6e8fb1a9d0382ecaa5056a3a84c94e313fbf9e92c89de271cdede",
|
||||
"zh:d0ac346519d0df124df89be2d803eb53f373434890f6ee3fb37112802f9eac59",
|
||||
"zh:d6256feedada82cbfb3b1dd6dd9ad02048f23120ab50e6146a541cb11a108cc1",
|
||||
"zh:db2fe0d2e77c02e9a74e1ed694aa352295a50283f9a1cf896e5be252af14e9f4",
|
||||
"zh:eda61e889b579bd90046939a5b40cf5dc9031fb5a819fc3e4667a78bd432bdb2",
|
||||
"h1:Tf6Os+utUxE8rEr/emCXLFEDdCb0Y6rsN4Ee84+aDCQ=",
|
||||
"zh:064c9b21bcd69be7a8631ccb3eccb8690c6a9955051145920803ef6ce6fc06bf",
|
||||
"zh:277dd05750187a41282cf6e066e882eac0dd0056e3211d125f94bf62c19c4b8b",
|
||||
"zh:47050211f72dcbf3d99c82147abd2eefbb7238efb94d5188979f60de66c8a3df",
|
||||
"zh:4a4e0d070399a050847545721dae925c192a2d6354802fdfbea73769077acca5",
|
||||
"zh:4cbc46f79239c85d69389f9e91ca9a9ebf6a8a937cfada026c5a037fd09130fb",
|
||||
"zh:6548dcb1ac4a388ed46034a5317fa74b3b0b0f68eec03393f2d4d09342683f95",
|
||||
"zh:75b4a82596aa525d95b0b2847fe648368c6e2b054059c4dc4dcdee01d374b592",
|
||||
"zh:75cf5cc674b61c82300667a82650f56722618b119ab0526b47b5ecbb4bbf49d0",
|
||||
"zh:93c896682359039960c38eb5a4b29d1cc06422f228db0572b90330427e2a21ec",
|
||||
"zh:c7256663aedbc9de121316b6d0623551386a476fc12b8eb77e88532ce15de354",
|
||||
"zh:e995c32f49c23b5938200386e08b2a3fd69cf5102b5299366c0608bbeac68429",
|
||||
]
|
||||
}
|
||||
|
||||
provider "registry.terraform.io/hashicorp/external" {
|
||||
version = "2.0.0"
|
||||
version = "2.1.0"
|
||||
hashes = [
|
||||
"h1:6S7hqjmUnoAZ5D/0F1VlJZKSJsUIBh7Ro0tLjGpKO0g=",
|
||||
"h1:Q5xqryWI3tCY8yr+fugq7dz4Qz+8g4GaW9ZS8dc6Ob8=",
|
||||
"zh:07949780dd6a1d43e7b46950f6e6976581d9724102cb5388d3411a1b6f476bde",
|
||||
"zh:0a4f4636ff93f0644affa8474465dd8c9252946437ad025b28fc9f6603534a24",
|
||||
"zh:0dd7e05a974c649950d1a21d7015d3753324ae52ebdd1744b144bc409ca4b3e8",
|
||||
"zh:2b881032b9aa9d227ac712f614056d050bcdcc67df0dc79e2b2cb76a197059ad",
|
||||
"zh:38feb4787b4570335459ca75a55389df1a7570bdca8cdf5df4c2876afe3c14b4",
|
||||
"zh:40f7e0aaef3b1f4c2ca2bb1189e3fe9af8c296da129423986d1d99ccc8cfb86c",
|
||||
"zh:56b361f64f0f0df5c4f958ae2f0e6f8ba192f35b720b9d3ae1be068fabcf73d9",
|
||||
"zh:5fadb5880cd31c2105f635ded92b9b16f918c1dd989627a4ce62c04939223909",
|
||||
"zh:61fa0be9c14c8c4109cfb7be8d54a80c56d35dbae49d3231cddb59831e7e5a4d",
|
||||
"zh:853774bf97fbc4a784d5af5a4ca0090848430781ae6cfc586adeb48f7c44af79",
|
||||
"h1:wbtDfLeawmv6xVT1W0w0fctRCb4ABlaD3JTxwb1jXag=",
|
||||
"zh:0d83ffb72fbd08986378204a7373d8c43b127049096eaf2765bfdd6b00ad9853",
|
||||
"zh:7577d6edc67b1e8c2cf62fe6501192df1231d74125d90e51d570d586d95269c5",
|
||||
"zh:9c669ded5d5affa4b2544952c4b6588dfed55260147d24ced02dca3a2829f328",
|
||||
"zh:a404d46f2831f90633947ab5d57e19dbfe35b3704104ba6ec80bcf50b058acfd",
|
||||
"zh:ae1caea1c936d459ceadf287bb5c5bd67b5e2a7819df6f5c4114b7305df7f822",
|
||||
"zh:afb4f805477694a4b9dde86b268d2c0821711c8aab1c6088f5f992228c4c06fb",
|
||||
"zh:b993b4a1de8a462643e78f4786789e44ce5064b332fee1cb0d6250ed085561b8",
|
||||
"zh:c84b2c13fa3ea2c0aa7291243006d560ce480a5591294b9001ce3742fc9c5791",
|
||||
"zh:c8966f69b7eccccb771704fd5335923692eccc9e0e90cb95d14538fe2e92a3b8",
|
||||
"zh:d5fe68850d449b811e633a300b114d0617df6d450305e8251643b4d143dc855b",
|
||||
"zh:ddebfd1e674ba336df09b1f27bbaa0e036c25b7a7087dc8081443f6e5954028b",
|
||||
]
|
||||
}
|
||||
|
||||
provider "registry.terraform.io/hashicorp/local" {
|
||||
version = "2.0.0"
|
||||
version = "2.1.0"
|
||||
hashes = [
|
||||
"h1:EC6eh7avwx1rF56h3RZcxgEp/14ihi7Sk/4J3Hn4nIE=",
|
||||
"h1:pO1ANXtOCRfecKsY9Hn4UsXoPBLv6LFiDIEiS1MZ09E=",
|
||||
"zh:34ce8b79493ace8333d094752b579ccc907fa9392a2c1d6933a6c95d0786d3f1",
|
||||
"zh:5c5a19c4f614a4ffb68bae0b0563f3860115cf7539b8adc21108324cfdc10092",
|
||||
"zh:67ddb1ca2cd3e1a8f948302597ceb967f19d2eeb2d125303493667388fe6330e",
|
||||
"zh:68e6b16f3a8e180fcba1a99754118deb2d82331b51f6cca39f04518339bfdfa6",
|
||||
"zh:8393a12eb11598b2799d51c9b0a922a3d9fadda5a626b94a1b4914086d53120e",
|
||||
"zh:90daea4b2010a86f2aca1e3a9590e0b3ddcab229c2bd3685fae76a832e9e836f",
|
||||
"zh:99308edc734a0ac9149b44f8e316ca879b2670a1cae387a8ae754c180b57cdb4",
|
||||
"zh:c76594db07a9d1a73372a073888b672df64adb455d483c2426cc220eda7e092e",
|
||||
"zh:dc09c1fb36c6a706bdac96cce338952888c8423978426a09f5df93031aa88b84",
|
||||
"zh:deda88134e9780319e8de91b3745520be48ead6ec38cb662694d09185c3dac70",
|
||||
"h1:EYZdckuGU3n6APs97nS2LxZm3dDtGqyM4qaIvsmac8o=",
|
||||
"zh:0f1ec65101fa35050978d483d6e8916664b7556800348456ff3d09454ac1eae2",
|
||||
"zh:36e42ac19f5d68467aacf07e6adcf83c7486f2e5b5f4339e9671f68525fc87ab",
|
||||
"zh:6db9db2a1819e77b1642ec3b5e95042b202aee8151a0256d289f2e141bf3ceb3",
|
||||
"zh:719dfd97bb9ddce99f7d741260b8ece2682b363735c764cac83303f02386075a",
|
||||
"zh:7598bb86e0378fd97eaa04638c1a4c75f960f62f69d3662e6d80ffa5a89847fe",
|
||||
"zh:ad0a188b52517fec9eca393f1e2c9daea362b33ae2eb38a857b6b09949a727c1",
|
||||
"zh:c46846c8df66a13fee6eff7dc5d528a7f868ae0dcf92d79deaac73cc297ed20c",
|
||||
"zh:dc1a20a2eec12095d04bf6da5321f535351a594a636912361db20eb2a707ccc4",
|
||||
"zh:e57ab4771a9d999401f6badd8b018558357d3cbdf3d33cc0c4f83e818ca8e94b",
|
||||
"zh:ebdcde208072b4b0f8d305ebf2bfdc62c926e0717599dcf8ec2fd8c5845031c3",
|
||||
"zh:ef34c52b68933bedd0868a13ccfd59ff1c820f299760b3c02e008dc95e2ece91",
|
||||
]
|
||||
}
|
||||
|
||||
provider "registry.terraform.io/hashicorp/null" {
|
||||
version = "3.0.0"
|
||||
version = "3.1.0"
|
||||
hashes = [
|
||||
"h1:V1tzrSG6t3e7zWvUwRbGbhsWU2Jd/anrJpOl9XM+R/8=",
|
||||
"h1:ysHGBhBNkIiJLEpthB/IVCLpA1Qoncp3KbCTFGFZTO0=",
|
||||
"zh:05fb7eab469324c97e9b73a61d2ece6f91de4e9b493e573bfeda0f2077bc3a4c",
|
||||
"zh:1688aa91885a395c4ae67636d411475d0b831e422e005dcf02eedacaafac3bb4",
|
||||
"zh:24a0b1292e3a474f57c483a7a4512d797e041bc9c2fbaac42fe12e86a7fb5a3c",
|
||||
"zh:2fc951bd0d1b9b23427acc93be09b6909d72871e464088171da60fbee4fdde03",
|
||||
"zh:6db825759425599a326385a68acc6be2d9ba0d7d6ef587191d0cdc6daef9ac63",
|
||||
"zh:85985763d02618993c32c294072cc6ec51f1692b803cb506fcfedca9d40eaec9",
|
||||
"zh:a53186599c57058be1509f904da512342cfdc5d808efdaf02dec15f0f3cb039a",
|
||||
"zh:c2e07b49b6efa676bdc7b00c06333ea1792a983a5720f9e2233db27323d2707c",
|
||||
"zh:cdc8fe1096103cf5374751e2e8408ec4abd2eb67d5a1c5151fe2c7ecfd525bef",
|
||||
"zh:dbdef21df0c012b0d08776f3d4f34eb0f2f229adfde07ff252a119e52c0f65b7",
|
||||
"h1:vpC6bgUQoJ0znqIKVFevOdq+YQw42bRq0u+H3nto8nA=",
|
||||
"zh:02a1675fd8de126a00460942aaae242e65ca3380b5bb192e8773ef3da9073fd2",
|
||||
"zh:53e30545ff8926a8e30ad30648991ca8b93b6fa496272cd23b26763c8ee84515",
|
||||
"zh:5f9200bf708913621d0f6514179d89700e9aa3097c77dac730e8ba6e5901d521",
|
||||
"zh:9ebf4d9704faba06b3ec7242c773c0fbfe12d62db7d00356d4f55385fc69bfb2",
|
||||
"zh:a6576c81adc70326e4e1c999c04ad9ca37113a6e925aefab4765e5a5198efa7e",
|
||||
"zh:a8a42d13346347aff6c63a37cda9b2c6aa5cc384a55b2fe6d6adfa390e609c53",
|
||||
"zh:c797744d08a5307d50210e0454f91ca4d1c7621c68740441cf4579390452321d",
|
||||
"zh:cecb6a304046df34c11229f20a80b24b1603960b794d68361a67c5efe58e62b8",
|
||||
"zh:e1371aa1e502000d9974cfaff5be4cfa02f47b17400005a16f14d2ef30dc2a70",
|
||||
"zh:fc39cc1fe71234a0b0369d5c5c7f876c71b956d23d7d6f518289737a001ba69b",
|
||||
"zh:fea4227271ebf7d9e2b61b89ce2328c7262acd9fd190e1fd6d15a591abfa848e",
|
||||
]
|
||||
}
|
||||
|
||||
provider "registry.terraform.io/hashicorp/random" {
|
||||
version = "3.0.0"
|
||||
version = "3.1.0"
|
||||
hashes = [
|
||||
"h1:grDzxfnOdFXi90FRIIwP/ZrCzirJ/SfsGBe6cE0Shg4=",
|
||||
"h1:yhHJpb4IfQQfuio7qjUXuUFTU/s+ensuEpm23A+VWz0=",
|
||||
"zh:0fcb00ff8b87dcac1b0ee10831e47e0203a6c46aafd76cb140ba2bab81f02c6b",
|
||||
"zh:123c984c0e04bad910c421028d18aa2ca4af25a153264aef747521f4e7c36a17",
|
||||
"zh:287443bc6fd7fa9a4341dec235589293cbcc6e467a042ae225fd5d161e4e68dc",
|
||||
"zh:2c1be5596dd3cca4859466885eaedf0345c8e7628503872610629e275d71b0d2",
|
||||
"zh:684a2ef6f415287944a3d966c4c8cee82c20e393e096e2f7cdcb4b2528407f6b",
|
||||
"zh:7625ccbc6ff17c2d5360ff2af7f9261c3f213765642dcd84e84ae02a3768fd51",
|
||||
"zh:9a60811ab9e6a5bfa6352fbb943bb530acb6198282a49373283a8fa3aa2b43fc",
|
||||
"zh:c73e0eaeea6c65b1cf5098b101d51a2789b054201ce7986a6d206a9e2dacaefd",
|
||||
"zh:e8f9ed41ac83dbe407de9f0206ef1148204a0d51ba240318af801ffb3ee5f578",
|
||||
"zh:fbdd0684e62563d3ac33425b0ac9439d543a3942465f4b26582bcfabcb149515",
|
||||
"h1:BZMEPucF+pbu9gsPk0G0BHx7YP04+tKdq2MrRDF1EDM=",
|
||||
"zh:2bbb3339f0643b5daa07480ef4397bd23a79963cc364cdfbb4e86354cb7725bc",
|
||||
"zh:3cd456047805bf639fbf2c761b1848880ea703a054f76db51852008b11008626",
|
||||
"zh:4f251b0eda5bb5e3dc26ea4400dba200018213654b69b4a5f96abee815b4f5ff",
|
||||
"zh:7011332745ea061e517fe1319bd6c75054a314155cb2c1199a5b01fe1889a7e2",
|
||||
"zh:738ed82858317ccc246691c8b85995bc125ac3b4143043219bd0437adc56c992",
|
||||
"zh:7dbe52fac7bb21227acd7529b487511c91f4107db9cc4414f50d04ffc3cab427",
|
||||
"zh:a3a9251fb15f93e4cfc1789800fc2d7414bbc18944ad4c5c98f466e6477c42bc",
|
||||
"zh:a543ec1a3a8c20635cf374110bd2f87c07374cf2c50617eee2c669b3ceeeaa9f",
|
||||
"zh:d9ab41d556a48bd7059f0810cf020500635bfc696c9fc3adab5ea8915c1d886b",
|
||||
"zh:d9e13427a7d011dbd654e591b0337e6074eef8c3b9bb11b2e39eaaf257044fd7",
|
||||
"zh:f7605bd1437752114baf601bdf6931debe6dc6bfe3006eb7e9bb9080931dca8a",
|
||||
]
|
||||
}
|
||||
|
||||
provider "registry.terraform.io/hashicorp/template" {
|
||||
version = "2.2.0"
|
||||
hashes = [
|
||||
"h1:0wlehNaxBX7GJQnPfQwTNvvAf38Jm0Nv7ssKGMaG6Og=",
|
||||
"h1:94qn780bi1qjrbC3uQtjJh3Wkfwd5+tTtJHOb7KTg9w=",
|
||||
"zh:01702196f0a0492ec07917db7aaa595843d8f171dc195f4c988d2ffca2a06386",
|
||||
"zh:09aae3da826ba3d7df69efeb25d146a1de0d03e951d35019a0f80e4f58c89b53",
|
||||
@@ -110,19 +109,19 @@ provider "registry.terraform.io/hashicorp/template" {
|
||||
}
|
||||
|
||||
provider "registry.terraform.io/hashicorp/tls" {
|
||||
version = "3.0.0"
|
||||
version = "3.1.0"
|
||||
hashes = [
|
||||
"h1:AcQGOAD5xa4KE9gYw5g7R6UU8a77Yn/afPvch4N86lQ=",
|
||||
"h1:LtCEW5v1E5Eo49+kQOsKHRYf9Hc8ZR0jTpK+mXszPHs=",
|
||||
"zh:05eac573a1fe53227bcc6b01daf6ddf0b73456f97f56f316f1b3114a4771e175",
|
||||
"zh:09390dad764c76f0fd59cae4dad296e3e39487e06de3a4bc0df73916c6bb2f17",
|
||||
"zh:142d0bc4722ab088b7ca124b0eb44206b9d100f51035c162d50ef552e09813d0",
|
||||
"zh:2c391743dd20f43329c0d0d49dec7827970d788115593c0e32a57050c0a85337",
|
||||
"zh:525b12fc87369c0e6d347afe6c77668aebf56cfa078bb0f1f01cc2ee01ac7016",
|
||||
"zh:5583d81b7a05c6d49a4c445e1ee62e82facb07bb9204998a836b7b522a51db8d",
|
||||
"zh:925e3acc70e18ed1cd296d337fc3e0ca43ac6f5bf2e660f24de750c7754f91aa",
|
||||
"zh:a291457d25b207fd28fb4fad9209ebb591e25cfc507ca1cb0fb8b2e255be1969",
|
||||
"zh:bbf9e2718752aebfbd7c6b8e196eb2e52730b66befed2ea1954f9ff1c199295e",
|
||||
"zh:f4b333c467ae02c1a238ac57465fe66405f6e2a6cfeb4eded9bc321c5652a1bf",
|
||||
"h1:fUJX8Zxx38e2kBln+zWr1Tl41X+OuiE++REjrEyiOM4=",
|
||||
"zh:3d46616b41fea215566f4a957b6d3a1aa43f1f75c26776d72a98bdba79439db6",
|
||||
"zh:623a203817a6dafa86f1b4141b645159e07ec418c82fe40acd4d2a27543cbaa2",
|
||||
"zh:668217e78b210a6572e7b0ecb4134a6781cc4d738f4f5d09eb756085b082592e",
|
||||
"zh:95354df03710691773c8f50a32e31fca25f124b7f3d6078265fdf3c4e1384dca",
|
||||
"zh:9f97ab190380430d57392303e3f36f4f7835c74ea83276baa98d6b9a997c3698",
|
||||
"zh:a16f0bab665f8d933e95ca055b9c8d5707f1a0dd8c8ecca6c13091f40dc1e99d",
|
||||
"zh:be274d5008c24dc0d6540c19e22dbb31ee6bfdd0b2cddd4d97f3cd8a8d657841",
|
||||
"zh:d5faa9dce0a5fc9d26b2463cea5be35f8586ab75030e7fa4d4920cd73ee26989",
|
||||
"zh:e9b672210b7fb410780e7b429975adcc76dd557738ecc7c890ea18942eb321a5",
|
||||
"zh:eb1f8368573d2370605d6dbf60f9aaa5b64e55741d96b5fb026dbfe91de67c0d",
|
||||
"zh:fc1e12b713837b85daf6c3bb703d7795eaf1c5177aebae1afcf811dd7009f4b0",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -27,6 +27,14 @@ plugin "nomad-driver-podman" {
|
||||
}
|
||||
}
|
||||
|
||||
plugin "nomad-driver-ecs" {
|
||||
config {
|
||||
enabled = true
|
||||
cluster = "nomad-rtd-e2e"
|
||||
region = "us-east-1"
|
||||
}
|
||||
}
|
||||
|
||||
vault {
|
||||
enabled = true
|
||||
address = "http://active.vault.service.consul:8200"
|
||||
|
||||
@@ -25,6 +25,14 @@ plugin "nomad-driver-podman" {
|
||||
}
|
||||
}
|
||||
|
||||
plugin "nomad-driver-ecs" {
|
||||
config {
|
||||
enabled = true
|
||||
cluster = "nomad-rtd-e2e"
|
||||
region = "us-east-1"
|
||||
}
|
||||
}
|
||||
|
||||
vault {
|
||||
enabled = true
|
||||
address = "http://active.vault.service.consul:8200"
|
||||
|
||||
@@ -20,6 +20,14 @@ plugin "nomad-driver-podman" {
|
||||
}
|
||||
}
|
||||
|
||||
plugin "nomad-driver-ecs" {
|
||||
config {
|
||||
enabled = true
|
||||
cluster = "nomad-rtd-e2e"
|
||||
region = "us-east-1"
|
||||
}
|
||||
}
|
||||
|
||||
vault {
|
||||
enabled = true
|
||||
address = "http://active.vault.service.consul:8200"
|
||||
|
||||
21
e2e/terraform/ecs-task.json
Normal file
21
e2e/terraform/ecs-task.json
Normal file
@@ -0,0 +1,21 @@
|
||||
[
|
||||
{
|
||||
"command": [
|
||||
"/bin/sh -c \"echo '<html> <head> <title>Amazon ECS Sample App</title> <style>body {margin-top: 40px; background-color: #333;} </style> </head><body> <div style=color:white;text-align:center> <h1>Amazon ECS Sample App</h1> <h2>Congratulations!</h2> <p>Your application is now running on a container in Amazon ECS.</p> </div></body></html>' > /usr/local/apache2/htdocs/index.html && httpd-foreground\""
|
||||
],
|
||||
"entryPoint": [
|
||||
"sh",
|
||||
"-c"
|
||||
],
|
||||
"essential": true,
|
||||
"image": "httpd:2.4",
|
||||
"name": "nomad-remote-driver-demo",
|
||||
"portMappings": [
|
||||
{
|
||||
"containerPort": 80,
|
||||
"hostPort": 80,
|
||||
"protocol": "tcp"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
29
e2e/terraform/ecs.tf
Normal file
29
e2e/terraform/ecs.tf
Normal file
@@ -0,0 +1,29 @@
|
||||
# Nomad ECS Remote Task Driver E2E
|
||||
resource "aws_ecs_cluster" "nomad_rtd_e2e" {
|
||||
name = "nomad-rtd-e2e"
|
||||
}
|
||||
|
||||
resource "aws_ecs_task_definition" "nomad_rtd_e2e" {
|
||||
family = "nomad-rtd-e2e"
|
||||
container_definitions = file("ecs-task.json")
|
||||
|
||||
# Don't need a network for e2e tests
|
||||
network_mode = "awsvpc"
|
||||
|
||||
requires_compatibilities = ["FARGATE"]
|
||||
cpu = 256
|
||||
memory = 512
|
||||
}
|
||||
|
||||
data "template_file" "ecs_vars_hcl" {
|
||||
template = <<EOT
|
||||
security_groups = ["${aws_security_group.primary.id}"]
|
||||
subnets = ["${data.aws_subnet.default.id}"]
|
||||
EOT
|
||||
}
|
||||
|
||||
resource "local_file" "ecs_vars_hcl" {
|
||||
content = data.template_file.ecs_vars_hcl.rendered
|
||||
filename = "${path.module}/../remotetasks/input/ecs.vars"
|
||||
file_permission = "0664"
|
||||
}
|
||||
@@ -131,6 +131,13 @@ sudo chmod +x "${NOMAD_PLUGIN_DIR}/nomad-driver-podman"
|
||||
sudo mv /tmp/linux/io.podman.service /etc/systemd/system/io.podman.service
|
||||
sudo mv /tmp/linux/io.podman.socket /etc/systemd/system/io.podman.socket
|
||||
|
||||
if [ -a "/tmp/linux/nomad-driver-ecs" ]; then
|
||||
echo "Installing nomad-driver-ecs"
|
||||
sudo install --mode=0755 --owner=ubuntu /tmp/linux/nomad-driver-ecs "$NOMAD_PLUGIN_DIR"
|
||||
else
|
||||
echo "nomad-driver-ecs not found: skipping install"
|
||||
fi
|
||||
|
||||
echo "Configuring dnsmasq"
|
||||
|
||||
# disable systemd-resolved and configure dnsmasq to forward local requests to
|
||||
|
||||
@@ -7406,6 +7406,34 @@ type AllocState struct {
|
||||
Time time.Time
|
||||
}
|
||||
|
||||
// TaskHandle is optional handle to a task propogated to the servers for use
|
||||
// by remote tasks. Since remote tasks are not implicitly lost when the node
|
||||
// they are assigned to is down, their state is migrated to the replacement
|
||||
// allocation.
|
||||
//
|
||||
// Minimal set of fields from plugins/drivers/task_handle.go:TaskHandle
|
||||
type TaskHandle struct {
|
||||
// Version of driver state. Used by the driver to gracefully handle
|
||||
// plugin upgrades.
|
||||
Version int
|
||||
|
||||
// Driver-specific state containing a handle to the remote task.
|
||||
DriverState []byte
|
||||
}
|
||||
|
||||
func (h *TaskHandle) Copy() *TaskHandle {
|
||||
if h == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
newTH := TaskHandle{
|
||||
Version: h.Version,
|
||||
DriverState: make([]byte, len(h.DriverState)),
|
||||
}
|
||||
copy(newTH.DriverState, h.DriverState)
|
||||
return &newTH
|
||||
}
|
||||
|
||||
// Set of possible states for a task.
|
||||
const (
|
||||
TaskStatePending = "pending" // The task is waiting to be run.
|
||||
@@ -7439,6 +7467,10 @@ type TaskState struct {
|
||||
|
||||
// Series of task events that transition the state of the task.
|
||||
Events []*TaskEvent
|
||||
|
||||
// Experimental - TaskHandle is based on drivers.TaskHandle and used
|
||||
// by remote task drivers to migrate task handles between allocations.
|
||||
TaskHandle *TaskHandle
|
||||
}
|
||||
|
||||
// NewTaskState returns a TaskState initialized in the Pending state.
|
||||
@@ -7460,16 +7492,18 @@ func (ts *TaskState) Copy() *TaskState {
|
||||
if ts == nil {
|
||||
return nil
|
||||
}
|
||||
copy := new(TaskState)
|
||||
*copy = *ts
|
||||
newTS := new(TaskState)
|
||||
*newTS = *ts
|
||||
|
||||
if ts.Events != nil {
|
||||
copy.Events = make([]*TaskEvent, len(ts.Events))
|
||||
newTS.Events = make([]*TaskEvent, len(ts.Events))
|
||||
for i, e := range ts.Events {
|
||||
copy.Events[i] = e.Copy()
|
||||
newTS.Events[i] = e.Copy()
|
||||
}
|
||||
}
|
||||
return copy
|
||||
|
||||
newTS.TaskHandle = ts.TaskHandle.Copy()
|
||||
return newTS
|
||||
}
|
||||
|
||||
// Successful returns whether a task finished successfully. This doesn't really
|
||||
|
||||
@@ -73,6 +73,7 @@ func (d *driverPluginClient) Capabilities() (*Capabilities, error) {
|
||||
}
|
||||
|
||||
caps.MountConfigs = MountConfigSupport(resp.Capabilities.MountConfigs)
|
||||
caps.RemoteTasks = resp.Capabilities.RemoteTasks
|
||||
}
|
||||
|
||||
return caps, nil
|
||||
|
||||
@@ -31,6 +31,13 @@ const (
|
||||
// handle is from a driver that existed before driver plugins (v0.9). The
|
||||
// driver should take appropriate action to handle the old driver state.
|
||||
Pre09TaskHandleVersion = 0
|
||||
|
||||
// DetachSignal is a special signal sent to remote task drivers when a
|
||||
// task should be detached instead of killed. This allows a remote task
|
||||
// to be left running and transferred to a replacement allocation in
|
||||
// cases like down or drained nodes causing the original allocation to
|
||||
// be terminal.
|
||||
DetachSignal = "DETACH"
|
||||
)
|
||||
|
||||
// DriverPlugin is the interface with drivers will implement. It is also
|
||||
@@ -158,6 +165,12 @@ type Capabilities struct {
|
||||
|
||||
// MountConfigs tells Nomad which mounting config options the driver supports.
|
||||
MountConfigs MountConfigSupport
|
||||
|
||||
// RemoteTasks indicates this driver runs tasks on remote systems
|
||||
// instead of locally. The Nomad client can use this information to
|
||||
// adjust behavior such as propogating task handles between allocations
|
||||
// to avoid downtime when a client is lost.
|
||||
RemoteTasks bool
|
||||
}
|
||||
|
||||
func (c *Capabilities) HasNetIsolationMode(m NetIsolationMode) bool {
|
||||
|
||||
@@ -1836,10 +1836,13 @@ type DriverCapabilities struct {
|
||||
NetworkIsolationModes []NetworkIsolationSpec_NetworkIsolationMode `protobuf:"varint,4,rep,packed,name=network_isolation_modes,json=networkIsolationModes,proto3,enum=hashicorp.nomad.plugins.drivers.proto.NetworkIsolationSpec_NetworkIsolationMode" json:"network_isolation_modes,omitempty"`
|
||||
MustCreateNetwork bool `protobuf:"varint,5,opt,name=must_create_network,json=mustCreateNetwork,proto3" json:"must_create_network,omitempty"`
|
||||
// MountConfigs indicates whether the driver supports mount configurations.
|
||||
MountConfigs DriverCapabilities_MountConfigs `protobuf:"varint,6,opt,name=mount_configs,json=mountConfigs,proto3,enum=hashicorp.nomad.plugins.drivers.proto.DriverCapabilities_MountConfigs" json:"mount_configs,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
MountConfigs DriverCapabilities_MountConfigs `protobuf:"varint,6,opt,name=mount_configs,json=mountConfigs,proto3,enum=hashicorp.nomad.plugins.drivers.proto.DriverCapabilities_MountConfigs" json:"mount_configs,omitempty"`
|
||||
// remote_tasks indicates whether the driver executes tasks remotely such
|
||||
// on cloud runtimes like AWS ECS.
|
||||
RemoteTasks bool `protobuf:"varint,7,opt,name=remote_tasks,json=remoteTasks,proto3" json:"remote_tasks,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *DriverCapabilities) Reset() { *m = DriverCapabilities{} }
|
||||
@@ -1909,6 +1912,13 @@ func (m *DriverCapabilities) GetMountConfigs() DriverCapabilities_MountConfigs {
|
||||
return DriverCapabilities_UNKNOWN_MOUNTS
|
||||
}
|
||||
|
||||
func (m *DriverCapabilities) GetRemoteTasks() bool {
|
||||
if m != nil {
|
||||
return m.RemoteTasks
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type NetworkIsolationSpec struct {
|
||||
Mode NetworkIsolationSpec_NetworkIsolationMode `protobuf:"varint,1,opt,name=mode,proto3,enum=hashicorp.nomad.plugins.drivers.proto.NetworkIsolationSpec_NetworkIsolationMode" json:"mode,omitempty"`
|
||||
Path string `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"`
|
||||
@@ -3607,239 +3617,240 @@ func init() {
|
||||
}
|
||||
|
||||
var fileDescriptor_4a8f45747846a74d = []byte{
|
||||
// 3707 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x5a, 0x4f, 0x6f, 0x1b, 0x49,
|
||||
0x76, 0x57, 0xf3, 0x9f, 0xc8, 0x47, 0x8a, 0x6a, 0x95, 0x65, 0x0f, 0xcd, 0x49, 0x32, 0xde, 0x0e,
|
||||
0x26, 0x10, 0x76, 0x67, 0xe8, 0x19, 0x2d, 0x32, 0x1e, 0xcf, 0x7a, 0xd6, 0xc3, 0xa1, 0x68, 0x4b,
|
||||
0x63, 0x89, 0x52, 0x8a, 0x14, 0xbc, 0x8e, 0xb3, 0xd3, 0x69, 0x75, 0x97, 0xc9, 0xb6, 0xd8, 0x7f,
|
||||
0xdc, 0x5d, 0x94, 0xa5, 0x0d, 0x82, 0x04, 0x1b, 0x20, 0xd8, 0x00, 0x09, 0x92, 0xcb, 0x64, 0x2f,
|
||||
0x39, 0x2d, 0x90, 0x53, 0xbe, 0x40, 0xb0, 0xc1, 0x9e, 0xf3, 0x05, 0x72, 0xcc, 0x25, 0xb7, 0x5c,
|
||||
0x02, 0x24, 0xdf, 0x20, 0xa8, 0x3f, 0xdd, 0xec, 0x26, 0xe9, 0x75, 0x93, 0xf2, 0xa9, 0xfb, 0xbd,
|
||||
0xaa, 0xfa, 0xd5, 0xeb, 0xf7, 0x5e, 0xd5, 0x7b, 0x55, 0xfd, 0x40, 0xf3, 0xc7, 0x93, 0xa1, 0xed,
|
||||
0x86, 0x77, 0xad, 0xc0, 0xbe, 0x20, 0x41, 0x78, 0xd7, 0x0f, 0x3c, 0xea, 0x49, 0xaa, 0xc5, 0x09,
|
||||
0xf4, 0xe1, 0xc8, 0x08, 0x47, 0xb6, 0xe9, 0x05, 0x7e, 0xcb, 0xf5, 0x1c, 0xc3, 0x6a, 0xc9, 0x31,
|
||||
0x2d, 0x39, 0x46, 0x74, 0x6b, 0xfe, 0xde, 0xd0, 0xf3, 0x86, 0x63, 0x22, 0x10, 0xce, 0x26, 0x2f,
|
||||
0xee, 0x5a, 0x93, 0xc0, 0xa0, 0xb6, 0xe7, 0xca, 0xf6, 0x0f, 0x66, 0xdb, 0xa9, 0xed, 0x90, 0x90,
|
||||
0x1a, 0x8e, 0x2f, 0x3b, 0x7c, 0x18, 0xc9, 0x12, 0x8e, 0x8c, 0x80, 0x58, 0x77, 0x47, 0xe6, 0x38,
|
||||
0xf4, 0x89, 0xc9, 0x9e, 0x3a, 0x7b, 0x91, 0xdd, 0x3e, 0x9a, 0xe9, 0x16, 0xd2, 0x60, 0x62, 0xd2,
|
||||
0x48, 0x72, 0x83, 0xd2, 0xc0, 0x3e, 0x9b, 0x50, 0x22, 0x7a, 0x6b, 0xb7, 0xe1, 0xbd, 0x81, 0x11,
|
||||
0x9e, 0x77, 0x3c, 0xf7, 0x85, 0x3d, 0xec, 0x9b, 0x23, 0xe2, 0x18, 0x98, 0xbc, 0x9a, 0x90, 0x90,
|
||||
0x6a, 0x7f, 0x02, 0x8d, 0xf9, 0xa6, 0xd0, 0xf7, 0xdc, 0x90, 0xa0, 0xaf, 0xa0, 0xc0, 0xa6, 0x6c,
|
||||
0x28, 0x77, 0x94, 0x9d, 0xea, 0xee, 0x47, 0xad, 0x37, 0xa9, 0x40, 0xc8, 0xd0, 0x92, 0xa2, 0xb6,
|
||||
0xfa, 0x3e, 0x31, 0x31, 0x1f, 0xa9, 0xdd, 0x84, 0x1b, 0x1d, 0xc3, 0x37, 0xce, 0xec, 0xb1, 0x4d,
|
||||
0x6d, 0x12, 0x46, 0x93, 0x4e, 0x60, 0x3b, 0xcd, 0x96, 0x13, 0xfe, 0x14, 0x6a, 0x66, 0x82, 0x2f,
|
||||
0x27, 0xbe, 0xdf, 0xca, 0xa4, 0xfb, 0xd6, 0x1e, 0xa7, 0x52, 0xc0, 0x29, 0x38, 0x6d, 0x1b, 0xd0,
|
||||
0x23, 0xdb, 0x1d, 0x92, 0xc0, 0x0f, 0x6c, 0x97, 0x46, 0xc2, 0xfc, 0x26, 0x0f, 0x37, 0x52, 0x6c,
|
||||
0x29, 0xcc, 0x4b, 0x80, 0x58, 0x8f, 0x4c, 0x94, 0xfc, 0x4e, 0x75, 0xf7, 0x9b, 0x8c, 0xa2, 0x2c,
|
||||
0xc0, 0x6b, 0xb5, 0x63, 0xb0, 0xae, 0x4b, 0x83, 0x2b, 0x9c, 0x40, 0x47, 0xdf, 0x42, 0x69, 0x44,
|
||||
0x8c, 0x31, 0x1d, 0x35, 0x72, 0x77, 0x94, 0x9d, 0xfa, 0xee, 0xa3, 0x6b, 0xcc, 0xb3, 0xcf, 0x81,
|
||||
0xfa, 0xd4, 0xa0, 0x04, 0x4b, 0x54, 0xf4, 0x31, 0x20, 0xf1, 0xa6, 0x5b, 0x24, 0x34, 0x03, 0xdb,
|
||||
0x67, 0x2e, 0xd9, 0xc8, 0xdf, 0x51, 0x76, 0x2a, 0x78, 0x4b, 0xb4, 0xec, 0x4d, 0x1b, 0x9a, 0x3e,
|
||||
0x6c, 0xce, 0x48, 0x8b, 0x54, 0xc8, 0x9f, 0x93, 0x2b, 0x6e, 0x91, 0x0a, 0x66, 0xaf, 0xe8, 0x31,
|
||||
0x14, 0x2f, 0x8c, 0xf1, 0x84, 0x70, 0x91, 0xab, 0xbb, 0x9f, 0xbe, 0xcd, 0x3d, 0xa4, 0x8b, 0x4e,
|
||||
0xf5, 0x80, 0xc5, 0xf8, 0x2f, 0x72, 0x9f, 0x2b, 0xda, 0x7d, 0xa8, 0x26, 0xe4, 0x46, 0x75, 0x80,
|
||||
0xd3, 0xde, 0x5e, 0x77, 0xd0, 0xed, 0x0c, 0xba, 0x7b, 0xea, 0x1a, 0xda, 0x80, 0xca, 0x69, 0x6f,
|
||||
0xbf, 0xdb, 0x3e, 0x1c, 0xec, 0x3f, 0x53, 0x15, 0x54, 0x85, 0xf5, 0x88, 0xc8, 0x69, 0x97, 0x80,
|
||||
0x30, 0x31, 0xbd, 0x0b, 0x12, 0x30, 0x47, 0x96, 0x56, 0x45, 0xef, 0xc1, 0x3a, 0x35, 0xc2, 0x73,
|
||||
0xdd, 0xb6, 0xa4, 0xcc, 0x25, 0x46, 0x1e, 0x58, 0xe8, 0x00, 0x4a, 0x23, 0xc3, 0xb5, 0xc6, 0x6f,
|
||||
0x97, 0x3b, 0xad, 0x6a, 0x06, 0xbe, 0xcf, 0x07, 0x62, 0x09, 0xc0, 0xbc, 0x3b, 0x35, 0xb3, 0x30,
|
||||
0x80, 0xf6, 0x0c, 0xd4, 0x3e, 0x35, 0x02, 0x9a, 0x14, 0xa7, 0x0b, 0x05, 0x36, 0xbf, 0xf4, 0xe8,
|
||||
0x65, 0xe6, 0x14, 0x2b, 0x13, 0xf3, 0xe1, 0xda, 0xff, 0xe5, 0x60, 0x2b, 0x81, 0x2d, 0x3d, 0xf5,
|
||||
0x29, 0x94, 0x02, 0x12, 0x4e, 0xc6, 0x94, 0xc3, 0xd7, 0x77, 0x1f, 0x66, 0x84, 0x9f, 0x43, 0x6a,
|
||||
0x61, 0x0e, 0x83, 0x25, 0x1c, 0xda, 0x01, 0x55, 0x8c, 0xd0, 0x49, 0x10, 0x78, 0x81, 0xee, 0x84,
|
||||
0x43, 0xae, 0xb5, 0x0a, 0xae, 0x0b, 0x7e, 0x97, 0xb1, 0x8f, 0xc2, 0x61, 0x42, 0xab, 0xf9, 0x6b,
|
||||
0x6a, 0x15, 0x19, 0xa0, 0xba, 0x84, 0xbe, 0xf6, 0x82, 0x73, 0x9d, 0xa9, 0x36, 0xb0, 0x2d, 0xd2,
|
||||
0x28, 0x70, 0xd0, 0xcf, 0x32, 0x82, 0xf6, 0xc4, 0xf0, 0x63, 0x39, 0x1a, 0x6f, 0xba, 0x69, 0x86,
|
||||
0xf6, 0x03, 0x28, 0x89, 0x2f, 0x65, 0x9e, 0xd4, 0x3f, 0xed, 0x74, 0xba, 0xfd, 0xbe, 0xba, 0x86,
|
||||
0x2a, 0x50, 0xc4, 0xdd, 0x01, 0x66, 0x1e, 0x56, 0x81, 0xe2, 0xa3, 0xf6, 0xa0, 0x7d, 0xa8, 0xe6,
|
||||
0xb4, 0xef, 0xc3, 0xe6, 0x53, 0xc3, 0xa6, 0x59, 0x9c, 0x4b, 0xf3, 0x40, 0x9d, 0xf6, 0x95, 0xd6,
|
||||
0x39, 0x48, 0x59, 0x27, 0xbb, 0x6a, 0xba, 0x97, 0x36, 0x9d, 0xb1, 0x87, 0x0a, 0x79, 0x12, 0x04,
|
||||
0xd2, 0x04, 0xec, 0x55, 0x7b, 0x0d, 0x9b, 0x7d, 0xea, 0xf9, 0x99, 0x3c, 0xff, 0x87, 0xb0, 0xce,
|
||||
0xa2, 0x8d, 0x37, 0xa1, 0xd2, 0xf5, 0x6f, 0xb7, 0x44, 0x34, 0x6a, 0x45, 0xd1, 0xa8, 0xb5, 0x27,
|
||||
0xa3, 0x15, 0x8e, 0x7a, 0xa2, 0x5b, 0x50, 0x0a, 0xed, 0xa1, 0x6b, 0x8c, 0xe5, 0x6e, 0x21, 0x29,
|
||||
0x0d, 0x31, 0x27, 0x8f, 0x26, 0x96, 0x8e, 0xdf, 0x01, 0xb4, 0x47, 0x42, 0x1a, 0x78, 0x57, 0x99,
|
||||
0xe4, 0xd9, 0x86, 0xe2, 0x0b, 0x2f, 0x30, 0xc5, 0x42, 0x2c, 0x63, 0x41, 0xb0, 0x45, 0x95, 0x02,
|
||||
0x91, 0xd8, 0x1f, 0x03, 0x3a, 0x70, 0x59, 0x4c, 0xc9, 0x66, 0x88, 0x7f, 0xc8, 0xc1, 0x8d, 0x54,
|
||||
0x7f, 0x69, 0x8c, 0xd5, 0xd7, 0x21, 0xdb, 0x98, 0x26, 0xa1, 0x58, 0x87, 0xe8, 0x18, 0x4a, 0xa2,
|
||||
0x87, 0xd4, 0xe4, 0xbd, 0x25, 0x80, 0x44, 0x98, 0x92, 0x70, 0x12, 0x66, 0xa1, 0xd3, 0xe7, 0xdf,
|
||||
0xad, 0xd3, 0xbf, 0x06, 0x35, 0xfa, 0x8e, 0xf0, 0xad, 0xb6, 0xf9, 0x06, 0x6e, 0x98, 0xde, 0x78,
|
||||
0x4c, 0x4c, 0xe6, 0x0d, 0xba, 0xed, 0x52, 0x12, 0x5c, 0x18, 0xe3, 0xb7, 0xfb, 0x0d, 0x9a, 0x8e,
|
||||
0x3a, 0x90, 0x83, 0xb4, 0xe7, 0xb0, 0x95, 0x98, 0x58, 0x1a, 0xe2, 0x11, 0x14, 0x43, 0xc6, 0x90,
|
||||
0x96, 0xf8, 0x64, 0x49, 0x4b, 0x84, 0x58, 0x0c, 0xd7, 0x6e, 0x08, 0xf0, 0xee, 0x05, 0x71, 0xe3,
|
||||
0xcf, 0xd2, 0xf6, 0x60, 0xab, 0xcf, 0xdd, 0x34, 0x93, 0x1f, 0x4e, 0x5d, 0x3c, 0x97, 0x72, 0xf1,
|
||||
0x6d, 0x40, 0x49, 0x14, 0xe9, 0x88, 0x57, 0xb0, 0xd9, 0xbd, 0x24, 0x66, 0x26, 0xe4, 0x06, 0xac,
|
||||
0x9b, 0x9e, 0xe3, 0x18, 0xae, 0xd5, 0xc8, 0xdd, 0xc9, 0xef, 0x54, 0x70, 0x44, 0x26, 0xd7, 0x62,
|
||||
0x3e, 0xeb, 0x5a, 0xd4, 0xfe, 0x4e, 0x01, 0x75, 0x3a, 0xb7, 0x54, 0x24, 0x93, 0x9e, 0x5a, 0x0c,
|
||||
0x88, 0xcd, 0x5d, 0xc3, 0x92, 0x92, 0xfc, 0x68, 0xbb, 0x10, 0x7c, 0x12, 0x04, 0x89, 0xed, 0x28,
|
||||
0x7f, 0xcd, 0xed, 0x48, 0xdb, 0x87, 0xdf, 0x89, 0xc4, 0xe9, 0xd3, 0x80, 0x18, 0x8e, 0xed, 0x0e,
|
||||
0x0f, 0x8e, 0x8f, 0x7d, 0x22, 0x04, 0x47, 0x08, 0x0a, 0x96, 0x41, 0x0d, 0x29, 0x18, 0x7f, 0x67,
|
||||
0x8b, 0xde, 0x1c, 0x7b, 0x61, 0xbc, 0xe8, 0x39, 0xa1, 0xfd, 0x7b, 0x1e, 0x1a, 0x73, 0x50, 0x91,
|
||||
0x7a, 0x9f, 0x43, 0x31, 0x24, 0x74, 0xe2, 0x4b, 0x57, 0xe9, 0x66, 0x16, 0x78, 0x31, 0x5e, 0xab,
|
||||
0xcf, 0xc0, 0xb0, 0xc0, 0x44, 0x43, 0x28, 0x53, 0x7a, 0xa5, 0x87, 0xf6, 0xcf, 0xa2, 0x84, 0xe0,
|
||||
0xf0, 0xba, 0xf8, 0x03, 0x12, 0x38, 0xb6, 0x6b, 0x8c, 0xfb, 0xf6, 0xcf, 0x08, 0x5e, 0xa7, 0xf4,
|
||||
0x8a, 0xbd, 0xa0, 0x67, 0xcc, 0xe1, 0x2d, 0xdb, 0x95, 0x6a, 0xef, 0xac, 0x3a, 0x4b, 0x42, 0xc1,
|
||||
0x58, 0x20, 0x36, 0x0f, 0xa1, 0xc8, 0xbf, 0x69, 0x15, 0x47, 0x54, 0x21, 0x4f, 0xe9, 0x15, 0x17,
|
||||
0xaa, 0x8c, 0xd9, 0x6b, 0xf3, 0x01, 0xd4, 0x92, 0x5f, 0xc0, 0x1c, 0x69, 0x44, 0xec, 0xe1, 0x48,
|
||||
0x38, 0x58, 0x11, 0x4b, 0x8a, 0x59, 0xf2, 0xb5, 0x6d, 0xc9, 0x94, 0xb5, 0x88, 0x05, 0xa1, 0xfd,
|
||||
0x6b, 0x0e, 0x6e, 0x2f, 0xd0, 0x8c, 0x74, 0xd6, 0xe7, 0x29, 0x67, 0x7d, 0x47, 0x5a, 0x88, 0x3c,
|
||||
0xfe, 0x79, 0xca, 0xe3, 0xdf, 0x21, 0x38, 0x5b, 0x36, 0xb7, 0xa0, 0x44, 0x2e, 0x6d, 0x4a, 0x2c,
|
||||
0xa9, 0x2a, 0x49, 0x25, 0x96, 0x53, 0xe1, 0xba, 0xcb, 0xe9, 0x53, 0xd8, 0xee, 0x04, 0xc4, 0xa0,
|
||||
0x44, 0x6e, 0xe5, 0x91, 0xff, 0xdf, 0x86, 0xb2, 0x31, 0x1e, 0x7b, 0xe6, 0xd4, 0xac, 0xeb, 0x9c,
|
||||
0x3e, 0xb0, 0xb4, 0xef, 0x14, 0xb8, 0x39, 0x33, 0x46, 0x6a, 0xfa, 0x0c, 0xea, 0x76, 0xe8, 0x8d,
|
||||
0xf9, 0x47, 0xe8, 0x89, 0x53, 0xdc, 0x8f, 0x96, 0x0b, 0x27, 0x07, 0x11, 0x06, 0x3f, 0xd4, 0x6d,
|
||||
0xd8, 0x49, 0x92, 0x7b, 0x15, 0x9f, 0xdc, 0x92, 0xab, 0x39, 0x22, 0xb5, 0x7f, 0x54, 0xe0, 0xa6,
|
||||
0x8c, 0xe2, 0x99, 0x3f, 0x66, 0x81, 0xc8, 0xb9, 0x77, 0x2d, 0xb2, 0xd6, 0x80, 0x5b, 0xb3, 0x72,
|
||||
0xc9, 0x7d, 0xfd, 0x3f, 0x0a, 0x80, 0xe6, 0x4f, 0x90, 0xe8, 0x7b, 0x50, 0x0b, 0x89, 0x6b, 0xe9,
|
||||
0x22, 0x26, 0x88, 0x70, 0x55, 0xc6, 0x55, 0xc6, 0x13, 0xc1, 0x21, 0x64, 0xdb, 0x1c, 0xb9, 0x94,
|
||||
0xd2, 0x96, 0x31, 0x7f, 0x47, 0x23, 0xa8, 0xbd, 0x08, 0xf5, 0x78, 0x6e, 0xee, 0x34, 0xf5, 0xcc,
|
||||
0x5b, 0xd7, 0xbc, 0x1c, 0xad, 0x47, 0xfd, 0xf8, 0xbb, 0x70, 0xf5, 0x45, 0x18, 0x13, 0xe8, 0x17,
|
||||
0x0a, 0xbc, 0x17, 0xa5, 0x0e, 0x53, 0xf5, 0x39, 0x9e, 0x45, 0xc2, 0x46, 0xe1, 0x4e, 0x7e, 0xa7,
|
||||
0xbe, 0x7b, 0x72, 0x0d, 0xfd, 0xcd, 0x31, 0x8f, 0x3c, 0x8b, 0xe0, 0x9b, 0xee, 0x02, 0x6e, 0x88,
|
||||
0x5a, 0x70, 0xc3, 0x99, 0x84, 0x54, 0x17, 0x5e, 0xa0, 0xcb, 0x4e, 0x8d, 0x22, 0xd7, 0xcb, 0x16,
|
||||
0x6b, 0x4a, 0xf9, 0x2a, 0x3a, 0x87, 0x0d, 0xc7, 0x9b, 0xb8, 0x54, 0x37, 0xf9, 0x19, 0x27, 0x6c,
|
||||
0x94, 0x96, 0x3a, 0xfc, 0x2e, 0xd0, 0xd2, 0x11, 0x83, 0x13, 0x27, 0xa6, 0x10, 0xd7, 0x9c, 0x04,
|
||||
0xa5, 0xb5, 0xa0, 0x9a, 0xd0, 0x21, 0x2a, 0x43, 0xa1, 0x77, 0xdc, 0xeb, 0xaa, 0x6b, 0x08, 0xa0,
|
||||
0xd4, 0xd9, 0xc7, 0xc7, 0xc7, 0x03, 0x91, 0xf6, 0x1f, 0x1c, 0xb5, 0x1f, 0x77, 0xd5, 0x9c, 0xd6,
|
||||
0x85, 0x5a, 0x12, 0x0d, 0x21, 0xa8, 0x9f, 0xf6, 0x9e, 0xf4, 0x8e, 0x9f, 0xf6, 0xf4, 0xa3, 0xe3,
|
||||
0xd3, 0xde, 0x80, 0x1d, 0x18, 0xea, 0x00, 0xed, 0xde, 0xb3, 0x29, 0xbd, 0x01, 0x95, 0xde, 0x71,
|
||||
0x44, 0x2a, 0xcd, 0x9c, 0xaa, 0x68, 0xff, 0x93, 0x83, 0xed, 0x45, 0x8a, 0x45, 0x16, 0x14, 0x98,
|
||||
0x91, 0xe4, 0x91, 0xed, 0xdd, 0xdb, 0x88, 0xa3, 0x33, 0xdf, 0xf4, 0x0d, 0xb9, 0x47, 0x57, 0x30,
|
||||
0x7f, 0x47, 0x3a, 0x94, 0xc6, 0xc6, 0x19, 0x19, 0x87, 0x8d, 0x3c, 0xbf, 0xd4, 0x78, 0x7c, 0x9d,
|
||||
0xb9, 0x0f, 0x39, 0x92, 0xb8, 0xd1, 0x90, 0xb0, 0xcd, 0xfb, 0x50, 0x4d, 0xb0, 0x17, 0x5c, 0x1d,
|
||||
0x6c, 0x27, 0xaf, 0x0e, 0x2a, 0xc9, 0x7b, 0x80, 0x87, 0xf3, 0xda, 0x62, 0x5f, 0xc3, 0xcc, 0xb5,
|
||||
0x7f, 0xdc, 0x1f, 0x88, 0x43, 0xda, 0x63, 0x7c, 0x7c, 0x7a, 0xa2, 0x2a, 0x8c, 0x39, 0x68, 0xf7,
|
||||
0x9f, 0xa8, 0xb9, 0xd8, 0x9a, 0x79, 0xed, 0x39, 0x54, 0xf6, 0x7a, 0x7d, 0x61, 0x34, 0xb6, 0x41,
|
||||
0x85, 0x24, 0x60, 0x9f, 0xc0, 0xef, 0x6f, 0x2a, 0x38, 0x22, 0x51, 0x13, 0xca, 0x21, 0x31, 0x02,
|
||||
0x73, 0x44, 0x42, 0x19, 0x11, 0x63, 0x9a, 0x8d, 0xf2, 0xf8, 0x3d, 0x88, 0x50, 0x50, 0x05, 0x47,
|
||||
0xa4, 0xf6, 0xbf, 0xeb, 0x00, 0xd3, 0x33, 0x39, 0xaa, 0x43, 0x2e, 0xde, 0xc5, 0x72, 0xb6, 0xc5,
|
||||
0x94, 0xed, 0x1a, 0x4e, 0xf4, 0x55, 0xfc, 0x1d, 0xed, 0xc2, 0x4d, 0x27, 0x1c, 0xfa, 0x86, 0x79,
|
||||
0xae, 0xcb, 0xa3, 0xb4, 0x70, 0x76, 0xbe, 0x23, 0xd4, 0xf0, 0x0d, 0xd9, 0x28, 0x7d, 0x59, 0xe0,
|
||||
0x1e, 0x42, 0x9e, 0xb8, 0x17, 0x7c, 0xf5, 0x56, 0x77, 0xbf, 0x58, 0xfa, 0xae, 0xa0, 0xd5, 0x75,
|
||||
0x2f, 0x84, 0x41, 0x18, 0x0c, 0xd2, 0x01, 0x2c, 0x72, 0x61, 0x9b, 0x44, 0x67, 0xa0, 0x45, 0x0e,
|
||||
0xfa, 0xd5, 0xf2, 0xa0, 0x7b, 0x1c, 0x23, 0x86, 0xae, 0x58, 0x11, 0x8d, 0x7a, 0x50, 0x09, 0x48,
|
||||
0xe8, 0x4d, 0x02, 0x93, 0x88, 0x25, 0x9c, 0x3d, 0x9d, 0xc7, 0xd1, 0x38, 0x3c, 0x85, 0x40, 0x7b,
|
||||
0x50, 0xe2, 0x2b, 0x37, 0x6c, 0xac, 0x73, 0x61, 0x3f, 0xca, 0x08, 0xc6, 0x97, 0x2b, 0x96, 0x63,
|
||||
0xd1, 0x63, 0x58, 0x17, 0x22, 0x86, 0x8d, 0x32, 0x87, 0xf9, 0x38, 0xeb, 0xb6, 0xc2, 0x47, 0xe1,
|
||||
0x68, 0x34, 0xb3, 0xea, 0x24, 0x24, 0x41, 0xa3, 0x22, 0xac, 0xca, 0xde, 0xd1, 0xfb, 0x50, 0x11,
|
||||
0x51, 0xcc, 0xb2, 0x83, 0x06, 0xf0, 0x06, 0x11, 0xd6, 0xf6, 0xec, 0x00, 0x7d, 0x00, 0x55, 0x91,
|
||||
0x91, 0xe8, 0x7c, 0xe9, 0x55, 0x79, 0x33, 0x08, 0xd6, 0x09, 0x5b, 0x80, 0xa2, 0x03, 0x09, 0x02,
|
||||
0xd1, 0xa1, 0x16, 0x77, 0x20, 0x41, 0xc0, 0x3b, 0xfc, 0x01, 0x6c, 0xf2, 0x3c, 0x6e, 0x18, 0x78,
|
||||
0x13, 0x5f, 0xe7, 0x3e, 0xb5, 0xc1, 0x3b, 0x6d, 0x30, 0xf6, 0x63, 0xc6, 0xed, 0x31, 0xe7, 0xba,
|
||||
0x0d, 0xe5, 0x97, 0xde, 0x99, 0xe8, 0x50, 0x17, 0xc1, 0xf4, 0xa5, 0x77, 0x16, 0x35, 0xc5, 0x71,
|
||||
0x76, 0x33, 0x1d, 0x67, 0x5f, 0xc1, 0xad, 0xf9, 0x80, 0xc1, 0xe3, 0xad, 0x7a, 0xfd, 0x78, 0xbb,
|
||||
0xed, 0x2e, 0xda, 0xec, 0xbe, 0x86, 0xbc, 0xe5, 0x86, 0x8d, 0xad, 0xa5, 0x9c, 0x23, 0x5e, 0xc7,
|
||||
0x98, 0x0d, 0x6e, 0x7e, 0x06, 0xe5, 0xc8, 0xfb, 0x96, 0xd9, 0x52, 0x9a, 0x0f, 0xa0, 0x9e, 0xf6,
|
||||
0xdd, 0xa5, 0x36, 0xa4, 0x7f, 0xce, 0x41, 0x25, 0xf6, 0x52, 0xe4, 0xc2, 0x0d, 0xae, 0x45, 0x96,
|
||||
0xe4, 0xe8, 0x53, 0xa7, 0x17, 0xa9, 0xd5, 0x97, 0x19, 0xbf, 0xab, 0x1d, 0x21, 0xc8, 0x73, 0x9c,
|
||||
0x5c, 0x01, 0x28, 0x46, 0x9e, 0xce, 0xf7, 0x2d, 0x6c, 0x8e, 0x6d, 0x77, 0x72, 0x99, 0x98, 0x4b,
|
||||
0xe4, 0x44, 0x7f, 0x98, 0x71, 0xae, 0x43, 0x36, 0x7a, 0x3a, 0x47, 0x7d, 0x9c, 0xa2, 0xd1, 0x3e,
|
||||
0x14, 0x7d, 0x2f, 0xa0, 0x51, 0x24, 0xd8, 0xcd, 0x88, 0x7a, 0xe2, 0x05, 0xf4, 0xc8, 0xf0, 0x7d,
|
||||
0x96, 0xda, 0x0b, 0x00, 0xed, 0xbb, 0x1c, 0xdc, 0x5a, 0xfc, 0x61, 0xa8, 0x07, 0x79, 0xd3, 0x9f,
|
||||
0x48, 0x25, 0x3d, 0x58, 0x56, 0x49, 0x1d, 0x7f, 0x32, 0x95, 0x9f, 0x01, 0xa1, 0xa7, 0x50, 0x72,
|
||||
0x88, 0xe3, 0x05, 0x57, 0x52, 0x17, 0x0f, 0x97, 0x85, 0x3c, 0xe2, 0xa3, 0xa7, 0xa8, 0x12, 0x0e,
|
||||
0x61, 0x28, 0x4b, 0xef, 0x0d, 0xe5, 0x3e, 0xb9, 0xe4, 0xe5, 0x4b, 0x04, 0x89, 0x63, 0x1c, 0xed,
|
||||
0x33, 0xb8, 0xb9, 0xf0, 0x53, 0xd0, 0xef, 0x02, 0x98, 0xfe, 0x44, 0xe7, 0x97, 0xe3, 0xc2, 0x83,
|
||||
0xf2, 0xb8, 0x62, 0xfa, 0x93, 0x3e, 0x67, 0x68, 0xcf, 0xa1, 0xf1, 0x26, 0x79, 0xd9, 0xee, 0x23,
|
||||
0x24, 0xd6, 0x9d, 0x33, 0xae, 0x83, 0x3c, 0x2e, 0x0b, 0xc6, 0xd1, 0x19, 0xd2, 0x60, 0x23, 0x6a,
|
||||
0x34, 0x2e, 0x59, 0x87, 0x3c, 0xef, 0x50, 0x95, 0x1d, 0x8c, 0xcb, 0xa3, 0x33, 0xed, 0x97, 0x39,
|
||||
0xd8, 0x9c, 0x11, 0x99, 0x1d, 0x70, 0xc4, 0x8e, 0x17, 0x1d, 0x1d, 0x05, 0xc5, 0xb6, 0x3f, 0xd3,
|
||||
0xb6, 0xa2, 0x4b, 0x47, 0xfe, 0xce, 0x03, 0x9f, 0x2f, 0x2f, 0x04, 0x73, 0xb6, 0xcf, 0x96, 0x8f,
|
||||
0x73, 0x66, 0xd3, 0x90, 0x9f, 0x81, 0x8a, 0x58, 0x10, 0xe8, 0x19, 0xd4, 0x03, 0xc2, 0x03, 0xae,
|
||||
0xa5, 0x0b, 0x2f, 0x2b, 0x2e, 0xe5, 0x65, 0x52, 0x42, 0xe6, 0x6c, 0x78, 0x23, 0x42, 0x62, 0x54,
|
||||
0x88, 0x9e, 0xc2, 0x86, 0x75, 0xe5, 0x1a, 0x8e, 0x6d, 0x4a, 0xe4, 0xd2, 0xca, 0xc8, 0x35, 0x09,
|
||||
0xc4, 0x81, 0xb5, 0xfb, 0x50, 0x4d, 0x34, 0xb2, 0x0f, 0xe3, 0x39, 0x8d, 0xd4, 0x89, 0x20, 0xd2,
|
||||
0xbb, 0x45, 0x51, 0xee, 0x16, 0xda, 0x19, 0x54, 0x13, 0xeb, 0x62, 0x99, 0xa1, 0x4c, 0x9f, 0xd4,
|
||||
0xe3, 0xfa, 0x2c, 0xe2, 0x1c, 0xf5, 0xd8, 0x39, 0x7e, 0xe4, 0x85, 0x54, 0xb7, 0x7d, 0xae, 0xd1,
|
||||
0x0a, 0x2e, 0x31, 0xf2, 0xc0, 0xd7, 0x7e, 0x9d, 0x83, 0x7a, 0x7a, 0x49, 0x47, 0x7e, 0xe4, 0x93,
|
||||
0xc0, 0xf6, 0xac, 0x84, 0x1f, 0x9d, 0x70, 0x06, 0xf3, 0x15, 0xd6, 0xfc, 0x6a, 0xe2, 0x51, 0x23,
|
||||
0xf2, 0x15, 0xd3, 0x9f, 0xfc, 0x11, 0xa3, 0x67, 0x7c, 0x30, 0x3f, 0xe3, 0x83, 0xe8, 0x23, 0x40,
|
||||
0xd2, 0x95, 0xc6, 0xb6, 0x63, 0x53, 0xfd, 0xec, 0x8a, 0x12, 0x61, 0xe3, 0x3c, 0x56, 0x45, 0xcb,
|
||||
0x21, 0x6b, 0xf8, 0x9a, 0xf1, 0x99, 0xe3, 0x79, 0x9e, 0xa3, 0x87, 0xa6, 0x17, 0x10, 0xdd, 0xb0,
|
||||
0x5e, 0xf2, 0xbc, 0x3f, 0x8f, 0xab, 0x9e, 0xe7, 0xf4, 0x19, 0xaf, 0x6d, 0xbd, 0x64, 0x91, 0xcf,
|
||||
0xf4, 0x27, 0x21, 0xa1, 0x3a, 0x7b, 0xf0, 0x64, 0xa1, 0x82, 0x41, 0xb0, 0x3a, 0xfe, 0x24, 0x44,
|
||||
0xbf, 0x0f, 0x1b, 0x51, 0x07, 0x1e, 0xfc, 0x64, 0xd4, 0xad, 0xc9, 0x2e, 0x9c, 0x87, 0x34, 0xa8,
|
||||
0x9d, 0x90, 0xc0, 0x24, 0x2e, 0x1d, 0xd8, 0xe6, 0x39, 0x8b, 0xef, 0xca, 0x8e, 0x82, 0x53, 0xbc,
|
||||
0x6f, 0x0a, 0xe5, 0x75, 0xb5, 0x8c, 0xa3, 0xd9, 0x1c, 0xe2, 0x84, 0xda, 0x4f, 0xa1, 0xc8, 0x53,
|
||||
0x04, 0xa6, 0x13, 0x1e, 0x5e, 0x79, 0xf4, 0x15, 0xe6, 0x29, 0x33, 0x06, 0x8f, 0xbd, 0xef, 0x43,
|
||||
0x85, 0xeb, 0x3e, 0x91, 0x36, 0x97, 0x19, 0x83, 0x37, 0x36, 0xa1, 0x1c, 0x10, 0xc3, 0xf2, 0xdc,
|
||||
0x71, 0x74, 0x65, 0x12, 0xd3, 0xda, 0x2b, 0x28, 0x89, 0x38, 0x73, 0x0d, 0xfc, 0x8f, 0x01, 0x89,
|
||||
0xef, 0x66, 0xf6, 0x74, 0xec, 0x30, 0x94, 0x59, 0x28, 0xff, 0x4f, 0x27, 0x5a, 0x4e, 0xa6, 0x0d,
|
||||
0xda, 0x7f, 0x2a, 0x22, 0x1f, 0x15, 0x7f, 0x50, 0x58, 0xe2, 0xca, 0x9c, 0x9c, 0x9d, 0x37, 0xc5,
|
||||
0x55, 0x4d, 0x44, 0xa2, 0x03, 0x28, 0xc9, 0xb4, 0x33, 0xb7, 0xea, 0x0f, 0x28, 0x09, 0x10, 0x5d,
|
||||
0xdc, 0x12, 0x79, 0xa4, 0x5d, 0xf6, 0xe2, 0x96, 0x88, 0x8b, 0x5b, 0xc2, 0x0e, 0xd6, 0x32, 0x21,
|
||||
0x16, 0x70, 0x05, 0x9e, 0x0f, 0x57, 0xad, 0xf8, 0x76, 0x9c, 0x68, 0xff, 0xad, 0xc4, 0xdb, 0x54,
|
||||
0x74, 0x8b, 0x8d, 0xbe, 0x85, 0x32, 0x5b, 0xf1, 0xba, 0x63, 0xf8, 0xf2, 0x9f, 0x6c, 0x67, 0xb5,
|
||||
0x0b, 0xf2, 0x28, 0x88, 0x89, 0x74, 0x76, 0xdd, 0x17, 0x14, 0xdb, 0xee, 0x0c, 0x6b, 0xba, 0xdd,
|
||||
0xb1, 0x77, 0xf4, 0x21, 0xd4, 0x8d, 0x09, 0xf5, 0x74, 0xc3, 0xba, 0x20, 0x01, 0xb5, 0x43, 0x22,
|
||||
0x6d, 0xbf, 0xc1, 0xb8, 0xed, 0x88, 0xd9, 0xfc, 0x02, 0x6a, 0x49, 0xcc, 0xb7, 0xa5, 0x19, 0xc5,
|
||||
0x64, 0x9a, 0xf1, 0xa7, 0x00, 0xd3, 0x1b, 0x21, 0xe6, 0x23, 0xe4, 0xd2, 0x66, 0xe7, 0x62, 0x79,
|
||||
0x40, 0x2c, 0xe2, 0x32, 0x63, 0x74, 0xd8, 0x51, 0x28, 0x7d, 0x5d, 0x5d, 0x8c, 0xae, 0xab, 0xd9,
|
||||
0x62, 0x66, 0xeb, 0xef, 0xdc, 0x1e, 0x8f, 0xe3, 0x5b, 0xaa, 0x8a, 0xe7, 0x39, 0x4f, 0x38, 0x43,
|
||||
0xfb, 0x4d, 0x4e, 0xf8, 0x8a, 0xf8, 0xf1, 0x90, 0xe9, 0xec, 0xf2, 0xae, 0x4c, 0x7d, 0x1f, 0x20,
|
||||
0xa4, 0x46, 0xc0, 0x72, 0x26, 0x23, 0xba, 0x27, 0x6b, 0xce, 0xdd, 0x77, 0x0f, 0xa2, 0x4a, 0x08,
|
||||
0x5c, 0x91, 0xbd, 0xdb, 0x14, 0x7d, 0x09, 0x35, 0xd3, 0x73, 0xfc, 0x31, 0x91, 0x83, 0x8b, 0x6f,
|
||||
0x1d, 0x5c, 0x8d, 0xfb, 0xb7, 0x69, 0xe2, 0x76, 0xae, 0x74, 0xdd, 0xdb, 0xb9, 0x5f, 0x2b, 0xe2,
|
||||
0xff, 0x49, 0xf2, 0xf7, 0x0d, 0x1a, 0x2e, 0xa8, 0x11, 0x78, 0xbc, 0xe2, 0xbf, 0xa0, 0xdf, 0x56,
|
||||
0x20, 0xd0, 0xfc, 0x32, 0xcb, 0x1f, 0xf9, 0x37, 0x67, 0xb1, 0xff, 0x96, 0x87, 0x4a, 0xfc, 0xeb,
|
||||
0x64, 0xce, 0xf6, 0x9f, 0x43, 0x25, 0x2e, 0x43, 0x91, 0x1b, 0xc4, 0x6f, 0x35, 0x4f, 0xdc, 0x19,
|
||||
0xbd, 0x00, 0x64, 0x0c, 0x87, 0x71, 0x76, 0xaa, 0x4f, 0x42, 0x63, 0x18, 0xfd, 0xb8, 0xfa, 0x7c,
|
||||
0x09, 0x3d, 0x44, 0xe1, 0xec, 0x94, 0x8d, 0xc7, 0xaa, 0x31, 0x1c, 0xa6, 0x38, 0xe8, 0xcf, 0xe0,
|
||||
0x66, 0x7a, 0x0e, 0xfd, 0xec, 0x4a, 0xf7, 0x6d, 0x4b, 0x9e, 0x91, 0xf7, 0x97, 0xfd, 0x7b, 0xd4,
|
||||
0x4a, 0xc1, 0x7f, 0x7d, 0x75, 0x62, 0x5b, 0x42, 0xe7, 0x28, 0x98, 0x6b, 0x68, 0xfe, 0x05, 0xbc,
|
||||
0xf7, 0x86, 0xee, 0x0b, 0x6c, 0xd0, 0x4b, 0x57, 0x45, 0xac, 0xae, 0x84, 0x84, 0xf5, 0x7e, 0xa5,
|
||||
0x88, 0x9f, 0x5c, 0x69, 0x9d, 0xb4, 0x93, 0x69, 0xf5, 0xdd, 0x8c, 0xf3, 0x74, 0x4e, 0x4e, 0x05,
|
||||
0x3c, 0xcf, 0xa4, 0xbf, 0x99, 0xc9, 0xa4, 0xb3, 0xe6, 0x4f, 0x22, 0x21, 0x15, 0x40, 0x12, 0x41,
|
||||
0xfb, 0x97, 0x3c, 0x94, 0x23, 0x74, 0x7e, 0xc2, 0xbd, 0x0a, 0x29, 0x71, 0xf4, 0xf8, 0x8e, 0x4b,
|
||||
0xc1, 0x20, 0x58, 0xfc, 0x3e, 0xe7, 0x7d, 0xa8, 0xb0, 0x83, 0xb4, 0x68, 0xce, 0xf1, 0xe6, 0x32,
|
||||
0x63, 0xf0, 0xc6, 0x0f, 0xa0, 0x4a, 0x3d, 0x6a, 0x8c, 0x75, 0xca, 0xc3, 0x7b, 0x5e, 0x8c, 0xe6,
|
||||
0x2c, 0x1e, 0xdc, 0xd1, 0x0f, 0x60, 0x8b, 0x8e, 0x02, 0x8f, 0xd2, 0x31, 0x4b, 0x2d, 0x79, 0xa2,
|
||||
0x23, 0xf2, 0x92, 0x02, 0x56, 0xe3, 0x06, 0x91, 0x00, 0x85, 0x6c, 0xf7, 0x9e, 0x76, 0x66, 0xae,
|
||||
0xcb, 0x37, 0x91, 0x02, 0xde, 0x88, 0xb9, 0xcc, 0xb5, 0x59, 0xf0, 0xf4, 0x45, 0x02, 0xc1, 0xf7,
|
||||
0x0a, 0x05, 0x47, 0x24, 0xd2, 0x61, 0xd3, 0x21, 0x46, 0x38, 0x09, 0x88, 0xa5, 0xbf, 0xb0, 0xc9,
|
||||
0xd8, 0x12, 0x17, 0x13, 0xf5, 0xcc, 0xa7, 0x83, 0x48, 0x2d, 0xad, 0x47, 0x7c, 0x34, 0xae, 0x47,
|
||||
0x70, 0x82, 0x66, 0x99, 0x83, 0x78, 0x43, 0x9b, 0x50, 0xed, 0x3f, 0xeb, 0x0f, 0xba, 0x47, 0xfa,
|
||||
0xd1, 0xf1, 0x5e, 0x57, 0x16, 0xbe, 0xf4, 0xbb, 0x58, 0x90, 0x0a, 0x6b, 0x1f, 0x1c, 0x0f, 0xda,
|
||||
0x87, 0xfa, 0xe0, 0xa0, 0xf3, 0xa4, 0xaf, 0xe6, 0xd0, 0x4d, 0xd8, 0x1a, 0xec, 0xe3, 0xe3, 0xc1,
|
||||
0xe0, 0xb0, 0xbb, 0xa7, 0x9f, 0x74, 0xf1, 0xc1, 0xf1, 0x5e, 0x5f, 0xcd, 0x23, 0x04, 0xf5, 0x29,
|
||||
0x7b, 0x70, 0x70, 0xd4, 0x55, 0x0b, 0xa8, 0x0a, 0xeb, 0x27, 0x5d, 0xdc, 0xe9, 0xf6, 0x06, 0x6a,
|
||||
0x51, 0xfb, 0x65, 0x1e, 0xaa, 0x09, 0x2b, 0x32, 0x47, 0x0e, 0x42, 0x71, 0x0c, 0x29, 0x60, 0xf6,
|
||||
0xca, 0x7f, 0xd4, 0x19, 0xe6, 0x48, 0x58, 0xa7, 0x80, 0x05, 0xc1, 0x8f, 0x1e, 0xc6, 0x65, 0x62,
|
||||
0x9d, 0x17, 0x70, 0xd9, 0x31, 0x2e, 0x05, 0xc8, 0xf7, 0xa0, 0x76, 0x4e, 0x02, 0x97, 0x8c, 0x65,
|
||||
0xbb, 0xb0, 0x48, 0x55, 0xf0, 0x44, 0x97, 0x1d, 0x50, 0x65, 0x97, 0x29, 0x8c, 0x30, 0x47, 0x5d,
|
||||
0xf0, 0x8f, 0x22, 0xb0, 0x6d, 0x28, 0x8a, 0xe6, 0x75, 0x31, 0x3f, 0x27, 0x58, 0x98, 0x0a, 0x5f,
|
||||
0x1b, 0x3e, 0x4f, 0xf9, 0x0a, 0x98, 0xbf, 0xa3, 0xb3, 0x79, 0xfb, 0x94, 0xb8, 0x7d, 0xee, 0x2f,
|
||||
0xef, 0xce, 0x6f, 0x32, 0xd1, 0x28, 0x36, 0xd1, 0x3a, 0xe4, 0x71, 0x54, 0x2d, 0xd2, 0x69, 0x77,
|
||||
0xf6, 0x99, 0x59, 0x36, 0xa0, 0x72, 0xd4, 0xfe, 0x89, 0x7e, 0xda, 0xe7, 0x57, 0xc7, 0x48, 0x85,
|
||||
0xda, 0x93, 0x2e, 0xee, 0x75, 0x0f, 0x25, 0x27, 0x8f, 0xb6, 0x41, 0x95, 0x9c, 0x69, 0xbf, 0x02,
|
||||
0x43, 0x10, 0xaf, 0x45, 0x54, 0x86, 0x42, 0xff, 0x69, 0xfb, 0x44, 0x2d, 0x69, 0xff, 0x95, 0x83,
|
||||
0x4d, 0x11, 0x16, 0xe2, 0xff, 0xda, 0x6f, 0xfe, 0xaf, 0x97, 0xbc, 0xe5, 0xc9, 0xa5, 0x6f, 0x79,
|
||||
0xa2, 0x24, 0x94, 0x47, 0xf5, 0xfc, 0x34, 0x09, 0xe5, 0xb7, 0x43, 0xa9, 0x1d, 0xbf, 0xb0, 0xcc,
|
||||
0x8e, 0xdf, 0x80, 0x75, 0x87, 0x84, 0xb1, 0xdd, 0x2a, 0x38, 0x22, 0x91, 0x0d, 0x55, 0xc3, 0x75,
|
||||
0x3d, 0x6a, 0x88, 0xab, 0xd3, 0xd2, 0x52, 0xc1, 0x70, 0xe6, 0x8b, 0x5b, 0xed, 0x29, 0x92, 0xd8,
|
||||
0x98, 0x93, 0xd8, 0xcd, 0x1f, 0x83, 0x3a, 0xdb, 0x61, 0x99, 0x70, 0xf8, 0xfd, 0x4f, 0xa7, 0xd1,
|
||||
0x90, 0xb0, 0x75, 0x21, 0x2f, 0xf6, 0xd5, 0x35, 0x46, 0xe0, 0xd3, 0x5e, 0xef, 0xa0, 0xf7, 0x58,
|
||||
0x55, 0x10, 0x40, 0xa9, 0xfb, 0x93, 0x83, 0x41, 0x77, 0x4f, 0xcd, 0xed, 0xfe, 0x6a, 0x0b, 0x4a,
|
||||
0x42, 0x48, 0xf4, 0x9d, 0xcc, 0x04, 0x92, 0x35, 0x93, 0xe8, 0xc7, 0x4b, 0x67, 0xd4, 0xa9, 0x3a,
|
||||
0xcc, 0xe6, 0xc3, 0x95, 0xc7, 0xcb, 0xff, 0x57, 0x6b, 0xe8, 0x6f, 0x14, 0xa8, 0xa5, 0xfe, 0x5d,
|
||||
0x65, 0xbd, 0x3a, 0x5e, 0x50, 0xa2, 0xd9, 0xfc, 0xd1, 0x4a, 0x63, 0x63, 0x59, 0x7e, 0xa1, 0x40,
|
||||
0x35, 0x51, 0x9c, 0x88, 0xee, 0xaf, 0x52, 0xd0, 0x28, 0x24, 0xf9, 0x62, 0xf5, 0x5a, 0x48, 0x6d,
|
||||
0xed, 0x13, 0x05, 0xfd, 0xb5, 0x02, 0xd5, 0x44, 0x99, 0x5e, 0x66, 0x51, 0xe6, 0x8b, 0x0a, 0x33,
|
||||
0x8b, 0xb2, 0xa8, 0x2a, 0x70, 0x0d, 0xfd, 0xa5, 0x02, 0x95, 0xb8, 0xe4, 0x0e, 0xdd, 0x5b, 0xbe,
|
||||
0x48, 0x4f, 0x08, 0xf1, 0xf9, 0xaa, 0xd5, 0x7d, 0xda, 0x1a, 0xfa, 0x73, 0x28, 0x47, 0xf5, 0x69,
|
||||
0x28, 0x6b, 0xf4, 0x9a, 0x29, 0x7e, 0x6b, 0xde, 0x5b, 0x7a, 0x5c, 0x72, 0xfa, 0xa8, 0x68, 0x2c,
|
||||
0xf3, 0xf4, 0x33, 0xe5, 0x6d, 0xcd, 0x7b, 0x4b, 0x8f, 0x8b, 0xa7, 0x67, 0x9e, 0x90, 0xa8, 0x2d,
|
||||
0xcb, 0xec, 0x09, 0xf3, 0x45, 0x6d, 0x99, 0x3d, 0x61, 0x51, 0x29, 0x9b, 0x10, 0x24, 0x51, 0x9d,
|
||||
0x96, 0x59, 0x90, 0xf9, 0x0a, 0xb8, 0xcc, 0x82, 0x2c, 0x28, 0x86, 0xd3, 0xd6, 0xd0, 0xcf, 0x95,
|
||||
0xe4, 0xb9, 0xe0, 0xde, 0xd2, 0x45, 0x58, 0x4b, 0xba, 0xe4, 0x5c, 0x19, 0x18, 0x5f, 0xa0, 0x3f,
|
||||
0x97, 0xb7, 0x18, 0xa2, 0x86, 0x0b, 0x2d, 0x03, 0x96, 0x2a, 0xfb, 0x6a, 0x7e, 0xb6, 0x5a, 0xb0,
|
||||
0xe1, 0x42, 0xfc, 0x95, 0x02, 0x30, 0xad, 0xf6, 0xca, 0x2c, 0xc4, 0x5c, 0x99, 0x59, 0xf3, 0xfe,
|
||||
0x0a, 0x23, 0x93, 0x0b, 0x24, 0xaa, 0x46, 0xc9, 0xbc, 0x40, 0x66, 0xaa, 0xd1, 0x32, 0x2f, 0x90,
|
||||
0xd9, 0x4a, 0x32, 0x6d, 0x0d, 0xfd, 0x93, 0x02, 0x5b, 0x73, 0xd5, 0x30, 0xe8, 0xe1, 0x35, 0x0b,
|
||||
0xa2, 0x9a, 0x5f, 0xad, 0x0e, 0x10, 0x89, 0xb6, 0xa3, 0x7c, 0xa2, 0xa0, 0xbf, 0x55, 0x60, 0x23,
|
||||
0x5d, 0x41, 0x90, 0x39, 0x4a, 0x2d, 0xa8, 0xab, 0x69, 0x3e, 0x58, 0x6d, 0x70, 0xac, 0xad, 0xbf,
|
||||
0x57, 0xa0, 0x9e, 0x2e, 0x26, 0x41, 0x0f, 0x96, 0xdb, 0x16, 0x66, 0x04, 0xfa, 0x72, 0xc5, 0xd1,
|
||||
0x91, 0x44, 0x5f, 0xaf, 0xff, 0x71, 0x51, 0x64, 0x6f, 0x25, 0xfe, 0xf8, 0xe1, 0xff, 0x07, 0x00,
|
||||
0x00, 0xff, 0xff, 0x47, 0xb7, 0xdf, 0xf9, 0xda, 0x32, 0x00, 0x00,
|
||||
// 3726 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x5a, 0xcd, 0x6f, 0x1b, 0x49,
|
||||
0x76, 0x57, 0xf3, 0x4b, 0xe4, 0xa3, 0x44, 0xb5, 0xca, 0xb2, 0x87, 0xe6, 0x24, 0x19, 0x6f, 0x07,
|
||||
0x13, 0x08, 0xbb, 0x33, 0xf4, 0x8c, 0x16, 0x19, 0x8f, 0x67, 0x3d, 0xeb, 0xe1, 0x50, 0xb4, 0xa5,
|
||||
0xb1, 0x44, 0x29, 0x45, 0x0a, 0x5e, 0xc7, 0xd9, 0xe9, 0xb4, 0xd8, 0x65, 0xaa, 0x2d, 0xf6, 0xc7,
|
||||
0x74, 0x15, 0x65, 0x69, 0x83, 0x20, 0xc1, 0x06, 0x08, 0x36, 0x40, 0x82, 0xe4, 0x32, 0xd9, 0x4b,
|
||||
0x4e, 0x0b, 0xe4, 0x94, 0x7f, 0x20, 0xd8, 0x60, 0xce, 0xf9, 0x27, 0x72, 0xc9, 0x2d, 0x97, 0x00,
|
||||
0xc9, 0x29, 0xd7, 0xa0, 0x3e, 0xba, 0xd9, 0x4d, 0xd2, 0xe3, 0x26, 0xe5, 0x53, 0xf7, 0x7b, 0x55,
|
||||
0xf5, 0xab, 0xd7, 0xef, 0xbd, 0xaa, 0xf7, 0xaa, 0xfa, 0x81, 0x11, 0x8c, 0xc6, 0x43, 0xc7, 0xa3,
|
||||
0x77, 0xed, 0xd0, 0xb9, 0x20, 0x21, 0xbd, 0x1b, 0x84, 0x3e, 0xf3, 0x15, 0xd5, 0x14, 0x04, 0x7a,
|
||||
0xff, 0xcc, 0xa2, 0x67, 0xce, 0xc0, 0x0f, 0x83, 0xa6, 0xe7, 0xbb, 0x96, 0xdd, 0x54, 0x63, 0x9a,
|
||||
0x6a, 0x8c, 0xec, 0xd6, 0xf8, 0xbd, 0xa1, 0xef, 0x0f, 0x47, 0x44, 0x22, 0x9c, 0x8e, 0x5f, 0xdc,
|
||||
0xb5, 0xc7, 0xa1, 0xc5, 0x1c, 0xdf, 0x53, 0xed, 0xef, 0x4d, 0xb7, 0x33, 0xc7, 0x25, 0x94, 0x59,
|
||||
0x6e, 0xa0, 0x3a, 0xbc, 0x1f, 0xc9, 0x42, 0xcf, 0xac, 0x90, 0xd8, 0x77, 0xcf, 0x06, 0x23, 0x1a,
|
||||
0x90, 0x01, 0x7f, 0x9a, 0xfc, 0x45, 0x75, 0xfb, 0x60, 0xaa, 0x1b, 0x65, 0xe1, 0x78, 0xc0, 0x22,
|
||||
0xc9, 0x2d, 0xc6, 0x42, 0xe7, 0x74, 0xcc, 0x88, 0xec, 0x6d, 0xdc, 0x86, 0x77, 0xfa, 0x16, 0x3d,
|
||||
0x6f, 0xfb, 0xde, 0x0b, 0x67, 0xd8, 0x1b, 0x9c, 0x11, 0xd7, 0xc2, 0xe4, 0x9b, 0x31, 0xa1, 0xcc,
|
||||
0xf8, 0x13, 0xa8, 0xcf, 0x36, 0xd1, 0xc0, 0xf7, 0x28, 0x41, 0x5f, 0x40, 0x81, 0x4f, 0x59, 0xd7,
|
||||
0xee, 0x68, 0xdb, 0xd5, 0x9d, 0x0f, 0x9a, 0xaf, 0x53, 0x81, 0x94, 0xa1, 0xa9, 0x44, 0x6d, 0xf6,
|
||||
0x02, 0x32, 0xc0, 0x62, 0xa4, 0x71, 0x13, 0x6e, 0xb4, 0xad, 0xc0, 0x3a, 0x75, 0x46, 0x0e, 0x73,
|
||||
0x08, 0x8d, 0x26, 0x1d, 0xc3, 0x56, 0x9a, 0xad, 0x26, 0xfc, 0x39, 0xac, 0x0d, 0x12, 0x7c, 0x35,
|
||||
0xf1, 0xfd, 0x66, 0x26, 0xdd, 0x37, 0x77, 0x05, 0x95, 0x02, 0x4e, 0xc1, 0x19, 0x5b, 0x80, 0x1e,
|
||||
0x39, 0xde, 0x90, 0x84, 0x41, 0xe8, 0x78, 0x2c, 0x12, 0xe6, 0xbb, 0x3c, 0xdc, 0x48, 0xb1, 0x95,
|
||||
0x30, 0x2f, 0x01, 0x62, 0x3d, 0x72, 0x51, 0xf2, 0xdb, 0xd5, 0x9d, 0xaf, 0x32, 0x8a, 0x32, 0x07,
|
||||
0xaf, 0xd9, 0x8a, 0xc1, 0x3a, 0x1e, 0x0b, 0xaf, 0x70, 0x02, 0x1d, 0x7d, 0x0d, 0xa5, 0x33, 0x62,
|
||||
0x8d, 0xd8, 0x59, 0x3d, 0x77, 0x47, 0xdb, 0xae, 0xed, 0x3c, 0xba, 0xc6, 0x3c, 0x7b, 0x02, 0xa8,
|
||||
0xc7, 0x2c, 0x46, 0xb0, 0x42, 0x45, 0x1f, 0x02, 0x92, 0x6f, 0xa6, 0x4d, 0xe8, 0x20, 0x74, 0x02,
|
||||
0xee, 0x92, 0xf5, 0xfc, 0x1d, 0x6d, 0xbb, 0x82, 0x37, 0x65, 0xcb, 0xee, 0xa4, 0xa1, 0x11, 0xc0,
|
||||
0xc6, 0x94, 0xb4, 0x48, 0x87, 0xfc, 0x39, 0xb9, 0x12, 0x16, 0xa9, 0x60, 0xfe, 0x8a, 0x1e, 0x43,
|
||||
0xf1, 0xc2, 0x1a, 0x8d, 0x89, 0x10, 0xb9, 0xba, 0xf3, 0xf1, 0x9b, 0xdc, 0x43, 0xb9, 0xe8, 0x44,
|
||||
0x0f, 0x58, 0x8e, 0xff, 0x2c, 0xf7, 0xa9, 0x66, 0xdc, 0x87, 0x6a, 0x42, 0x6e, 0x54, 0x03, 0x38,
|
||||
0xe9, 0xee, 0x76, 0xfa, 0x9d, 0x76, 0xbf, 0xb3, 0xab, 0xaf, 0xa0, 0x75, 0xa8, 0x9c, 0x74, 0xf7,
|
||||
0x3a, 0xad, 0x83, 0xfe, 0xde, 0x33, 0x5d, 0x43, 0x55, 0x58, 0x8d, 0x88, 0x9c, 0x71, 0x09, 0x08,
|
||||
0x93, 0x81, 0x7f, 0x41, 0x42, 0xee, 0xc8, 0xca, 0xaa, 0xe8, 0x1d, 0x58, 0x65, 0x16, 0x3d, 0x37,
|
||||
0x1d, 0x5b, 0xc9, 0x5c, 0xe2, 0xe4, 0xbe, 0x8d, 0xf6, 0xa1, 0x74, 0x66, 0x79, 0xf6, 0xe8, 0xcd,
|
||||
0x72, 0xa7, 0x55, 0xcd, 0xc1, 0xf7, 0xc4, 0x40, 0xac, 0x00, 0xb8, 0x77, 0xa7, 0x66, 0x96, 0x06,
|
||||
0x30, 0x9e, 0x81, 0xde, 0x63, 0x56, 0xc8, 0x92, 0xe2, 0x74, 0xa0, 0xc0, 0xe7, 0x57, 0x1e, 0xbd,
|
||||
0xc8, 0x9c, 0x72, 0x65, 0x62, 0x31, 0xdc, 0xf8, 0xdf, 0x1c, 0x6c, 0x26, 0xb0, 0x95, 0xa7, 0x3e,
|
||||
0x85, 0x52, 0x48, 0xe8, 0x78, 0xc4, 0x04, 0x7c, 0x6d, 0xe7, 0x61, 0x46, 0xf8, 0x19, 0xa4, 0x26,
|
||||
0x16, 0x30, 0x58, 0xc1, 0xa1, 0x6d, 0xd0, 0xe5, 0x08, 0x93, 0x84, 0xa1, 0x1f, 0x9a, 0x2e, 0x1d,
|
||||
0x0a, 0xad, 0x55, 0x70, 0x4d, 0xf2, 0x3b, 0x9c, 0x7d, 0x48, 0x87, 0x09, 0xad, 0xe6, 0xaf, 0xa9,
|
||||
0x55, 0x64, 0x81, 0xee, 0x11, 0xf6, 0xca, 0x0f, 0xcf, 0x4d, 0xae, 0xda, 0xd0, 0xb1, 0x49, 0xbd,
|
||||
0x20, 0x40, 0x3f, 0xc9, 0x08, 0xda, 0x95, 0xc3, 0x8f, 0xd4, 0x68, 0xbc, 0xe1, 0xa5, 0x19, 0xc6,
|
||||
0x8f, 0xa0, 0x24, 0xbf, 0x94, 0x7b, 0x52, 0xef, 0xa4, 0xdd, 0xee, 0xf4, 0x7a, 0xfa, 0x0a, 0xaa,
|
||||
0x40, 0x11, 0x77, 0xfa, 0x98, 0x7b, 0x58, 0x05, 0x8a, 0x8f, 0x5a, 0xfd, 0xd6, 0x81, 0x9e, 0x33,
|
||||
0x7e, 0x08, 0x1b, 0x4f, 0x2d, 0x87, 0x65, 0x71, 0x2e, 0xc3, 0x07, 0x7d, 0xd2, 0x57, 0x59, 0x67,
|
||||
0x3f, 0x65, 0x9d, 0xec, 0xaa, 0xe9, 0x5c, 0x3a, 0x6c, 0xca, 0x1e, 0x3a, 0xe4, 0x49, 0x18, 0x2a,
|
||||
0x13, 0xf0, 0x57, 0xe3, 0x15, 0x6c, 0xf4, 0x98, 0x1f, 0x64, 0xf2, 0xfc, 0x1f, 0xc3, 0x2a, 0x8f,
|
||||
0x36, 0xfe, 0x98, 0x29, 0xd7, 0xbf, 0xdd, 0x94, 0xd1, 0xa8, 0x19, 0x45, 0xa3, 0xe6, 0xae, 0x8a,
|
||||
0x56, 0x38, 0xea, 0x89, 0x6e, 0x41, 0x89, 0x3a, 0x43, 0xcf, 0x1a, 0xa9, 0xdd, 0x42, 0x51, 0x06,
|
||||
0xe2, 0x4e, 0x1e, 0x4d, 0xac, 0x1c, 0xbf, 0x0d, 0x68, 0x97, 0x50, 0x16, 0xfa, 0x57, 0x99, 0xe4,
|
||||
0xd9, 0x82, 0xe2, 0x0b, 0x3f, 0x1c, 0xc8, 0x85, 0x58, 0xc6, 0x92, 0xe0, 0x8b, 0x2a, 0x05, 0xa2,
|
||||
0xb0, 0x3f, 0x04, 0xb4, 0xef, 0xf1, 0x98, 0x92, 0xcd, 0x10, 0xff, 0x90, 0x83, 0x1b, 0xa9, 0xfe,
|
||||
0xca, 0x18, 0xcb, 0xaf, 0x43, 0xbe, 0x31, 0x8d, 0xa9, 0x5c, 0x87, 0xe8, 0x08, 0x4a, 0xb2, 0x87,
|
||||
0xd2, 0xe4, 0xbd, 0x05, 0x80, 0x64, 0x98, 0x52, 0x70, 0x0a, 0x66, 0xae, 0xd3, 0xe7, 0xdf, 0xae,
|
||||
0xd3, 0xbf, 0x02, 0x3d, 0xfa, 0x0e, 0xfa, 0x46, 0xdb, 0x7c, 0x05, 0x37, 0x06, 0xfe, 0x68, 0x44,
|
||||
0x06, 0xdc, 0x1b, 0x4c, 0xc7, 0x63, 0x24, 0xbc, 0xb0, 0x46, 0x6f, 0xf6, 0x1b, 0x34, 0x19, 0xb5,
|
||||
0xaf, 0x06, 0x19, 0xcf, 0x61, 0x33, 0x31, 0xb1, 0x32, 0xc4, 0x23, 0x28, 0x52, 0xce, 0x50, 0x96,
|
||||
0xf8, 0x68, 0x41, 0x4b, 0x50, 0x2c, 0x87, 0x1b, 0x37, 0x24, 0x78, 0xe7, 0x82, 0x78, 0xf1, 0x67,
|
||||
0x19, 0xbb, 0xb0, 0xd9, 0x13, 0x6e, 0x9a, 0xc9, 0x0f, 0x27, 0x2e, 0x9e, 0x4b, 0xb9, 0xf8, 0x16,
|
||||
0xa0, 0x24, 0x8a, 0x72, 0xc4, 0x2b, 0xd8, 0xe8, 0x5c, 0x92, 0x41, 0x26, 0xe4, 0x3a, 0xac, 0x0e,
|
||||
0x7c, 0xd7, 0xb5, 0x3c, 0xbb, 0x9e, 0xbb, 0x93, 0xdf, 0xae, 0xe0, 0x88, 0x4c, 0xae, 0xc5, 0x7c,
|
||||
0xd6, 0xb5, 0x68, 0xfc, 0x9d, 0x06, 0xfa, 0x64, 0x6e, 0xa5, 0x48, 0x2e, 0x3d, 0xb3, 0x39, 0x10,
|
||||
0x9f, 0x7b, 0x0d, 0x2b, 0x4a, 0xf1, 0xa3, 0xed, 0x42, 0xf2, 0x49, 0x18, 0x26, 0xb6, 0xa3, 0xfc,
|
||||
0x35, 0xb7, 0x23, 0x63, 0x0f, 0x7e, 0x27, 0x12, 0xa7, 0xc7, 0x42, 0x62, 0xb9, 0x8e, 0x37, 0xdc,
|
||||
0x3f, 0x3a, 0x0a, 0x88, 0x14, 0x1c, 0x21, 0x28, 0xd8, 0x16, 0xb3, 0x94, 0x60, 0xe2, 0x9d, 0x2f,
|
||||
0xfa, 0xc1, 0xc8, 0xa7, 0xf1, 0xa2, 0x17, 0x84, 0xf1, 0xef, 0x79, 0xa8, 0xcf, 0x40, 0x45, 0xea,
|
||||
0x7d, 0x0e, 0x45, 0x4a, 0xd8, 0x38, 0x50, 0xae, 0xd2, 0xc9, 0x2c, 0xf0, 0x7c, 0xbc, 0x66, 0x8f,
|
||||
0x83, 0x61, 0x89, 0x89, 0x86, 0x50, 0x66, 0xec, 0xca, 0xa4, 0xce, 0x2f, 0xa2, 0x84, 0xe0, 0xe0,
|
||||
0xba, 0xf8, 0x7d, 0x12, 0xba, 0x8e, 0x67, 0x8d, 0x7a, 0xce, 0x2f, 0x08, 0x5e, 0x65, 0xec, 0x8a,
|
||||
0xbf, 0xa0, 0x67, 0xdc, 0xe1, 0x6d, 0xc7, 0x53, 0x6a, 0x6f, 0x2f, 0x3b, 0x4b, 0x42, 0xc1, 0x58,
|
||||
0x22, 0x36, 0x0e, 0xa0, 0x28, 0xbe, 0x69, 0x19, 0x47, 0xd4, 0x21, 0xcf, 0xd8, 0x95, 0x10, 0xaa,
|
||||
0x8c, 0xf9, 0x6b, 0xe3, 0x01, 0xac, 0x25, 0xbf, 0x80, 0x3b, 0xd2, 0x19, 0x71, 0x86, 0x67, 0xd2,
|
||||
0xc1, 0x8a, 0x58, 0x51, 0xdc, 0x92, 0xaf, 0x1c, 0x5b, 0xa5, 0xac, 0x45, 0x2c, 0x09, 0xe3, 0x5f,
|
||||
0x73, 0x70, 0x7b, 0x8e, 0x66, 0x94, 0xb3, 0x3e, 0x4f, 0x39, 0xeb, 0x5b, 0xd2, 0x42, 0xe4, 0xf1,
|
||||
0xcf, 0x53, 0x1e, 0xff, 0x16, 0xc1, 0xf9, 0xb2, 0xb9, 0x05, 0x25, 0x72, 0xe9, 0x30, 0x62, 0x2b,
|
||||
0x55, 0x29, 0x2a, 0xb1, 0x9c, 0x0a, 0xd7, 0x5d, 0x4e, 0x1f, 0xc3, 0x56, 0x3b, 0x24, 0x16, 0x23,
|
||||
0x6a, 0x2b, 0x8f, 0xfc, 0xff, 0x36, 0x94, 0xad, 0xd1, 0xc8, 0x1f, 0x4c, 0xcc, 0xba, 0x2a, 0xe8,
|
||||
0x7d, 0xdb, 0xf8, 0x56, 0x83, 0x9b, 0x53, 0x63, 0x94, 0xa6, 0x4f, 0xa1, 0xe6, 0x50, 0x7f, 0x24,
|
||||
0x3e, 0xc2, 0x4c, 0x9c, 0xe2, 0x7e, 0xb2, 0x58, 0x38, 0xd9, 0x8f, 0x30, 0xc4, 0xa1, 0x6e, 0xdd,
|
||||
0x49, 0x92, 0xc2, 0xab, 0xc4, 0xe4, 0xb6, 0x5a, 0xcd, 0x11, 0x69, 0xfc, 0xa3, 0x06, 0x37, 0x55,
|
||||
0x14, 0xcf, 0xfc, 0x31, 0x73, 0x44, 0xce, 0xbd, 0x6d, 0x91, 0x8d, 0x3a, 0xdc, 0x9a, 0x96, 0x4b,
|
||||
0xed, 0xeb, 0xff, 0x57, 0x00, 0x34, 0x7b, 0x82, 0x44, 0x3f, 0x80, 0x35, 0x4a, 0x3c, 0xdb, 0x94,
|
||||
0x31, 0x41, 0x86, 0xab, 0x32, 0xae, 0x72, 0x9e, 0x0c, 0x0e, 0x94, 0x6f, 0x73, 0xe4, 0x52, 0x49,
|
||||
0x5b, 0xc6, 0xe2, 0x1d, 0x9d, 0xc1, 0xda, 0x0b, 0x6a, 0xc6, 0x73, 0x0b, 0xa7, 0xa9, 0x65, 0xde,
|
||||
0xba, 0x66, 0xe5, 0x68, 0x3e, 0xea, 0xc5, 0xdf, 0x85, 0xab, 0x2f, 0x68, 0x4c, 0xa0, 0x5f, 0x69,
|
||||
0xf0, 0x4e, 0x94, 0x3a, 0x4c, 0xd4, 0xe7, 0xfa, 0x36, 0xa1, 0xf5, 0xc2, 0x9d, 0xfc, 0x76, 0x6d,
|
||||
0xe7, 0xf8, 0x1a, 0xfa, 0x9b, 0x61, 0x1e, 0xfa, 0x36, 0xc1, 0x37, 0xbd, 0x39, 0x5c, 0x8a, 0x9a,
|
||||
0x70, 0xc3, 0x1d, 0x53, 0x66, 0x4a, 0x2f, 0x30, 0x55, 0xa7, 0x7a, 0x51, 0xe8, 0x65, 0x93, 0x37,
|
||||
0xa5, 0x7c, 0x15, 0x9d, 0xc3, 0xba, 0xeb, 0x8f, 0x3d, 0x66, 0x0e, 0xc4, 0x19, 0x87, 0xd6, 0x4b,
|
||||
0x0b, 0x1d, 0x7e, 0xe7, 0x68, 0xe9, 0x90, 0xc3, 0xc9, 0x13, 0x13, 0xc5, 0x6b, 0x6e, 0x82, 0xe2,
|
||||
0x86, 0x0c, 0x89, 0xeb, 0x33, 0x62, 0xf2, 0x3d, 0x91, 0xd6, 0x57, 0xa5, 0x21, 0x25, 0x8f, 0x2f,
|
||||
0x7f, 0x6a, 0x34, 0xa1, 0x9a, 0x50, 0x33, 0x2a, 0x43, 0xa1, 0x7b, 0xd4, 0xed, 0xe8, 0x2b, 0x08,
|
||||
0xa0, 0xd4, 0xde, 0xc3, 0x47, 0x47, 0x7d, 0x79, 0x32, 0xd8, 0x3f, 0x6c, 0x3d, 0xee, 0xe8, 0x39,
|
||||
0xa3, 0x03, 0x6b, 0xc9, 0x09, 0x11, 0x82, 0xda, 0x49, 0xf7, 0x49, 0xf7, 0xe8, 0x69, 0xd7, 0x3c,
|
||||
0x3c, 0x3a, 0xe9, 0xf6, 0xf9, 0x99, 0xa2, 0x06, 0xd0, 0xea, 0x3e, 0x9b, 0xd0, 0xeb, 0x50, 0xe9,
|
||||
0x1e, 0x45, 0xa4, 0xd6, 0xc8, 0xe9, 0x9a, 0xf1, 0xdf, 0x39, 0xd8, 0x9a, 0xa7, 0x7b, 0x64, 0x43,
|
||||
0x81, 0xdb, 0x51, 0x9d, 0xea, 0xde, 0xbe, 0x19, 0x05, 0x3a, 0x77, 0xdf, 0xc0, 0x52, 0xdb, 0x78,
|
||||
0x05, 0x8b, 0x77, 0x64, 0x42, 0x69, 0x64, 0x9d, 0x92, 0x11, 0xad, 0xe7, 0xc5, 0xbd, 0xc7, 0xe3,
|
||||
0xeb, 0xcc, 0x7d, 0x20, 0x90, 0xe4, 0xa5, 0x87, 0x82, 0x6d, 0xdc, 0x87, 0x6a, 0x82, 0x3d, 0xe7,
|
||||
0x76, 0x61, 0x2b, 0x79, 0xbb, 0x50, 0x49, 0x5e, 0x15, 0x3c, 0x9c, 0xd5, 0x16, 0xff, 0x1a, 0x6e,
|
||||
0xae, 0xbd, 0xa3, 0x5e, 0x5f, 0x9e, 0xe3, 0x1e, 0xe3, 0xa3, 0x93, 0x63, 0x5d, 0xe3, 0xcc, 0x7e,
|
||||
0xab, 0xf7, 0x44, 0xcf, 0xc5, 0xd6, 0xcc, 0x1b, 0xcf, 0xa1, 0xb2, 0xdb, 0xed, 0x49, 0xa3, 0xf1,
|
||||
0x3d, 0x8c, 0x92, 0x90, 0x7f, 0x82, 0xb8, 0xe2, 0xa9, 0xe0, 0x88, 0x44, 0x0d, 0x28, 0x53, 0x62,
|
||||
0x85, 0x83, 0x33, 0x42, 0x55, 0xd0, 0x8c, 0x69, 0x3e, 0xca, 0x17, 0x57, 0x25, 0x52, 0x41, 0x15,
|
||||
0x1c, 0x91, 0xc6, 0xff, 0xac, 0x02, 0x4c, 0x8e, 0xed, 0xa8, 0x06, 0xb9, 0x78, 0xa3, 0xcb, 0x39,
|
||||
0x36, 0x57, 0xb6, 0x67, 0xb9, 0xd1, 0x57, 0x89, 0x77, 0xb4, 0x03, 0x37, 0x5d, 0x3a, 0x0c, 0xac,
|
||||
0xc1, 0xb9, 0xa9, 0x4e, 0xdb, 0x72, 0x3d, 0x88, 0x4d, 0x63, 0x0d, 0xdf, 0x50, 0x8d, 0xca, 0xdd,
|
||||
0x25, 0xee, 0x01, 0xe4, 0x89, 0x77, 0x21, 0x16, 0x78, 0x75, 0xe7, 0xb3, 0x85, 0xaf, 0x13, 0x9a,
|
||||
0x1d, 0xef, 0x42, 0x1a, 0x84, 0xc3, 0x20, 0x13, 0xc0, 0x26, 0x17, 0xce, 0x80, 0x98, 0x1c, 0xb4,
|
||||
0x28, 0x40, 0xbf, 0x58, 0x1c, 0x74, 0x57, 0x60, 0xc4, 0xd0, 0x15, 0x3b, 0xa2, 0x51, 0x17, 0x2a,
|
||||
0x21, 0xa1, 0xfe, 0x38, 0x1c, 0x10, 0xb9, 0xca, 0xb3, 0x67, 0xfc, 0x38, 0x1a, 0x87, 0x27, 0x10,
|
||||
0x68, 0x17, 0x4a, 0x62, 0x71, 0xf3, 0x65, 0x9c, 0xff, 0xde, 0xbb, 0xc9, 0x34, 0x98, 0x58, 0xae,
|
||||
0x58, 0x8d, 0x45, 0x8f, 0x61, 0x55, 0x8a, 0x48, 0xeb, 0x65, 0x01, 0xf3, 0x61, 0xd6, 0x9d, 0x47,
|
||||
0x8c, 0xc2, 0xd1, 0x68, 0x6e, 0xd5, 0x31, 0x25, 0x61, 0xbd, 0x22, 0xad, 0xca, 0xdf, 0xd1, 0xbb,
|
||||
0x50, 0x91, 0x81, 0xce, 0x76, 0xc2, 0x3a, 0x88, 0x06, 0x19, 0xf9, 0x76, 0x9d, 0x10, 0xbd, 0x07,
|
||||
0x55, 0x99, 0xb4, 0x98, 0x62, 0xe9, 0x55, 0x45, 0x33, 0x48, 0xd6, 0x31, 0x5f, 0x80, 0xb2, 0x03,
|
||||
0x09, 0x43, 0xd9, 0x61, 0x2d, 0xee, 0x40, 0xc2, 0x50, 0x74, 0xf8, 0x03, 0xd8, 0x10, 0xa9, 0xde,
|
||||
0x30, 0xf4, 0xc7, 0x81, 0x29, 0x7c, 0x6a, 0x5d, 0x74, 0x5a, 0xe7, 0xec, 0xc7, 0x9c, 0xdb, 0xe5,
|
||||
0xce, 0x75, 0x1b, 0xca, 0x2f, 0xfd, 0x53, 0xd9, 0xa1, 0x26, 0xe3, 0xed, 0x4b, 0xff, 0x34, 0x6a,
|
||||
0x8a, 0x43, 0xf1, 0x46, 0x3a, 0x14, 0x7f, 0x03, 0xb7, 0x66, 0x63, 0x8a, 0x08, 0xc9, 0xfa, 0xf5,
|
||||
0x43, 0xf2, 0x96, 0x37, 0x6f, 0xb3, 0xfb, 0x12, 0xf2, 0xb6, 0x47, 0xeb, 0x9b, 0x0b, 0x39, 0x47,
|
||||
0xbc, 0x8e, 0x31, 0x1f, 0xdc, 0xf8, 0x04, 0xca, 0x91, 0xf7, 0x2d, 0xb2, 0xa5, 0x34, 0x1e, 0x40,
|
||||
0x2d, 0xed, 0xbb, 0x0b, 0x6d, 0x48, 0xff, 0x9c, 0x83, 0x4a, 0xec, 0xa5, 0xc8, 0x83, 0x1b, 0x42,
|
||||
0x8b, 0x3c, 0x0f, 0x32, 0x27, 0x4e, 0x2f, 0xb3, 0xaf, 0xcf, 0x33, 0x7e, 0x57, 0x2b, 0x42, 0x50,
|
||||
0x47, 0x3d, 0xb5, 0x02, 0x50, 0x8c, 0x3c, 0x99, 0xef, 0x6b, 0xd8, 0x18, 0x39, 0xde, 0xf8, 0x32,
|
||||
0x31, 0x97, 0x4c, 0x9b, 0xfe, 0x30, 0xe3, 0x5c, 0x07, 0x7c, 0xf4, 0x64, 0x8e, 0xda, 0x28, 0x45,
|
||||
0xa3, 0x3d, 0x28, 0x06, 0x7e, 0xc8, 0xa2, 0x48, 0xb0, 0x93, 0x11, 0xf5, 0xd8, 0x0f, 0xd9, 0xa1,
|
||||
0x15, 0x04, 0x3c, 0xfb, 0x97, 0x00, 0xc6, 0xb7, 0x39, 0xb8, 0x35, 0xff, 0xc3, 0x50, 0x17, 0xf2,
|
||||
0x83, 0x60, 0xac, 0x94, 0xf4, 0x60, 0x51, 0x25, 0xb5, 0x83, 0xf1, 0x44, 0x7e, 0x0e, 0x84, 0x9e,
|
||||
0x42, 0xc9, 0x25, 0xae, 0x1f, 0x5e, 0x29, 0x5d, 0x3c, 0x5c, 0x14, 0xf2, 0x50, 0x8c, 0x9e, 0xa0,
|
||||
0x2a, 0x38, 0x84, 0xa1, 0xac, 0xbc, 0x97, 0xaa, 0x7d, 0x72, 0xc1, 0xfb, 0x99, 0x08, 0x12, 0xc7,
|
||||
0x38, 0xc6, 0x27, 0x70, 0x73, 0xee, 0xa7, 0xa0, 0xdf, 0x05, 0x18, 0x04, 0x63, 0x53, 0xdc, 0x9f,
|
||||
0x4b, 0x0f, 0xca, 0xe3, 0xca, 0x20, 0x18, 0xf7, 0x04, 0xc3, 0x78, 0x0e, 0xf5, 0xd7, 0xc9, 0xcb,
|
||||
0x77, 0x1f, 0x29, 0xb1, 0xe9, 0x9e, 0x0a, 0x1d, 0xe4, 0x71, 0x59, 0x32, 0x0e, 0x4f, 0x91, 0x01,
|
||||
0xeb, 0x51, 0xa3, 0x75, 0xc9, 0x3b, 0xe4, 0x45, 0x87, 0xaa, 0xea, 0x60, 0x5d, 0x1e, 0x9e, 0x1a,
|
||||
0xbf, 0xce, 0xc1, 0xc6, 0x94, 0xc8, 0xfc, 0x0c, 0x24, 0x77, 0xbc, 0xe8, 0x74, 0x29, 0x29, 0xbe,
|
||||
0xfd, 0x0d, 0x1c, 0x3b, 0xba, 0x97, 0x14, 0xef, 0x22, 0xf0, 0x05, 0xea, 0xce, 0x30, 0xe7, 0x04,
|
||||
0x7c, 0xf9, 0xb8, 0xa7, 0x0e, 0xa3, 0xe2, 0x98, 0x54, 0xc4, 0x92, 0x40, 0xcf, 0xa0, 0x16, 0x12,
|
||||
0x11, 0x70, 0x6d, 0x53, 0x7a, 0x59, 0x71, 0x21, 0x2f, 0x53, 0x12, 0x72, 0x67, 0xc3, 0xeb, 0x11,
|
||||
0x12, 0xa7, 0x28, 0x7a, 0x0a, 0xeb, 0xf6, 0x95, 0x67, 0xb9, 0xce, 0x40, 0x21, 0x97, 0x96, 0x46,
|
||||
0x5e, 0x53, 0x40, 0x02, 0xd8, 0xb8, 0x0f, 0xd5, 0x44, 0x23, 0xff, 0x30, 0x91, 0xd3, 0x28, 0x9d,
|
||||
0x48, 0x22, 0xbd, 0x5b, 0x14, 0xd5, 0x6e, 0x61, 0x9c, 0x42, 0x35, 0xb1, 0x2e, 0x16, 0x19, 0xca,
|
||||
0xf5, 0xc9, 0x7c, 0xa1, 0xcf, 0x22, 0xce, 0x31, 0x9f, 0x1f, 0xf5, 0xcf, 0x7c, 0xca, 0x4c, 0x27,
|
||||
0x10, 0x1a, 0xad, 0xe0, 0x12, 0x27, 0xf7, 0x03, 0xe3, 0xb7, 0x39, 0xa8, 0xa5, 0x97, 0x74, 0xe4,
|
||||
0x47, 0x01, 0x09, 0x1d, 0xdf, 0x4e, 0xf8, 0xd1, 0xb1, 0x60, 0x70, 0x5f, 0xe1, 0xcd, 0xdf, 0x8c,
|
||||
0x7d, 0x66, 0x45, 0xbe, 0x32, 0x08, 0xc6, 0x7f, 0xc4, 0xe9, 0x29, 0x1f, 0xcc, 0x4f, 0xf9, 0x20,
|
||||
0xfa, 0x00, 0x90, 0x72, 0xa5, 0x91, 0xe3, 0x3a, 0xcc, 0x3c, 0xbd, 0x62, 0x44, 0xda, 0x38, 0x8f,
|
||||
0x75, 0xd9, 0x72, 0xc0, 0x1b, 0xbe, 0xe4, 0x7c, 0xee, 0x78, 0xbe, 0xef, 0x9a, 0x74, 0xe0, 0x87,
|
||||
0xc4, 0xb4, 0xec, 0x97, 0xe2, 0x68, 0x90, 0xc7, 0x55, 0xdf, 0x77, 0x7b, 0x9c, 0xd7, 0xb2, 0x5f,
|
||||
0xf2, 0xc8, 0x37, 0x08, 0xc6, 0x94, 0x30, 0x93, 0x3f, 0x44, 0xb2, 0x50, 0xc1, 0x20, 0x59, 0xed,
|
||||
0x60, 0x4c, 0xd1, 0xef, 0xc3, 0x7a, 0xd4, 0x41, 0x04, 0x3f, 0x15, 0x75, 0xd7, 0x54, 0x17, 0xc1,
|
||||
0x43, 0x06, 0xac, 0x1d, 0x93, 0x70, 0x40, 0x3c, 0xd6, 0x77, 0x06, 0xe7, 0x3c, 0xbe, 0x6b, 0xdb,
|
||||
0x1a, 0x4e, 0xf1, 0xbe, 0x2a, 0x94, 0x57, 0xf5, 0x32, 0x8e, 0x66, 0x73, 0x89, 0x4b, 0x8d, 0x9f,
|
||||
0x43, 0x51, 0xa4, 0x08, 0x5c, 0x27, 0x22, 0xbc, 0x8a, 0xe8, 0x2b, 0xcd, 0x53, 0xe6, 0x0c, 0x11,
|
||||
0x7b, 0xdf, 0x85, 0x8a, 0xd0, 0x7d, 0x22, 0x6d, 0x2e, 0x73, 0x86, 0x68, 0x6c, 0x40, 0x39, 0x24,
|
||||
0x96, 0xed, 0x7b, 0xa3, 0xe8, 0x56, 0x25, 0xa6, 0x8d, 0x6f, 0xa0, 0x24, 0xe3, 0xcc, 0x35, 0xf0,
|
||||
0x3f, 0x04, 0x24, 0xbf, 0x9b, 0xdb, 0xd3, 0x75, 0x28, 0x55, 0x59, 0xa8, 0xf8, 0x95, 0x27, 0x5b,
|
||||
0x8e, 0x27, 0x0d, 0xc6, 0x7f, 0x68, 0x32, 0x1f, 0x95, 0x3f, 0x59, 0x78, 0xe2, 0xca, 0x9d, 0x9c,
|
||||
0x1f, 0x49, 0xe5, 0x6d, 0x4e, 0x44, 0xa2, 0x7d, 0x28, 0xa9, 0xb4, 0x33, 0xb7, 0xec, 0x3f, 0x2a,
|
||||
0x05, 0x10, 0xdd, 0xed, 0x12, 0x75, 0xea, 0x5d, 0xf4, 0x6e, 0x97, 0xc8, 0xbb, 0x5d, 0xc2, 0x8f,
|
||||
0x6c, 0x2a, 0x21, 0x96, 0x70, 0x05, 0x91, 0x0f, 0x57, 0xed, 0xf8, 0x02, 0x9d, 0x18, 0xff, 0xa5,
|
||||
0xc5, 0xdb, 0x54, 0x74, 0xd1, 0x8d, 0xbe, 0x86, 0x32, 0x5f, 0xf1, 0xa6, 0x6b, 0x05, 0xea, 0xb7,
|
||||
0x6d, 0x7b, 0xb9, 0x3b, 0xf4, 0x28, 0x88, 0xc9, 0x74, 0x76, 0x35, 0x90, 0x14, 0xdf, 0xee, 0x2c,
|
||||
0x7b, 0xb2, 0xdd, 0xf1, 0x77, 0xf4, 0x3e, 0xd4, 0xac, 0x31, 0xf3, 0x4d, 0xcb, 0xbe, 0x20, 0x21,
|
||||
0x73, 0x28, 0x51, 0xb6, 0x5f, 0xe7, 0xdc, 0x56, 0xc4, 0x6c, 0x7c, 0x06, 0x6b, 0x49, 0xcc, 0x37,
|
||||
0xa5, 0x19, 0xc5, 0x64, 0x9a, 0xf1, 0xa7, 0x00, 0x93, 0x4b, 0x23, 0xee, 0x23, 0xe4, 0xd2, 0xe1,
|
||||
0x47, 0x67, 0x75, 0x40, 0x2c, 0xe2, 0x32, 0x67, 0xb4, 0xf9, 0x51, 0x28, 0x7d, 0xa3, 0x5d, 0x8c,
|
||||
0x6e, 0xb4, 0xf9, 0x62, 0xe6, 0xeb, 0xef, 0xdc, 0x19, 0x8d, 0xe2, 0x8b, 0xac, 0x8a, 0xef, 0xbb,
|
||||
0x4f, 0x04, 0xc3, 0xf8, 0x2e, 0x27, 0x7d, 0x45, 0xfe, 0x9b, 0xc8, 0x74, 0x76, 0x79, 0x5b, 0xa6,
|
||||
0xbe, 0x0f, 0x40, 0x99, 0x15, 0xf2, 0x9c, 0xc9, 0x8a, 0xae, 0xd2, 0x1a, 0x33, 0x57, 0xe2, 0xfd,
|
||||
0xa8, 0x58, 0x02, 0x57, 0x54, 0xef, 0x16, 0x43, 0x9f, 0xc3, 0xda, 0xc0, 0x77, 0x83, 0x11, 0x51,
|
||||
0x83, 0x8b, 0x6f, 0x1c, 0x5c, 0x8d, 0xfb, 0xb7, 0x58, 0xe2, 0x02, 0xaf, 0x74, 0xdd, 0x0b, 0xbc,
|
||||
0xdf, 0x6a, 0xf2, 0x17, 0x4b, 0xf2, 0x0f, 0x0f, 0x1a, 0xce, 0x29, 0x23, 0x78, 0xbc, 0xe4, 0xef,
|
||||
0xa2, 0xef, 0xab, 0x21, 0x68, 0x7c, 0x9e, 0xe5, 0xa7, 0xfd, 0xeb, 0xb3, 0xd8, 0x7f, 0xcb, 0x43,
|
||||
0x25, 0xfe, 0xbb, 0x32, 0x63, 0xfb, 0x4f, 0xa1, 0x12, 0x57, 0xaa, 0xa8, 0x0d, 0xe2, 0x7b, 0xcd,
|
||||
0x13, 0x77, 0x46, 0x2f, 0x00, 0x59, 0xc3, 0x61, 0x9c, 0x9d, 0x9a, 0x63, 0x6a, 0x0d, 0xa3, 0x7f,
|
||||
0x5b, 0x9f, 0x2e, 0xa0, 0x87, 0x28, 0x9c, 0x9d, 0xf0, 0xf1, 0x58, 0xb7, 0x86, 0xc3, 0x14, 0x07,
|
||||
0xfd, 0x19, 0xdc, 0x4c, 0xcf, 0x61, 0x9e, 0x5e, 0x99, 0x81, 0x63, 0xab, 0x33, 0xf2, 0xde, 0xa2,
|
||||
0x3f, 0x98, 0x9a, 0x29, 0xf8, 0x2f, 0xaf, 0x8e, 0x1d, 0x5b, 0xea, 0x1c, 0x85, 0x33, 0x0d, 0x8d,
|
||||
0xbf, 0x80, 0x77, 0x5e, 0xd3, 0x7d, 0x8e, 0x0d, 0xba, 0xe9, 0xc2, 0x89, 0xe5, 0x95, 0x90, 0xb0,
|
||||
0xde, 0x6f, 0x34, 0xf9, 0x1f, 0x2c, 0xad, 0x93, 0x56, 0x32, 0xad, 0xbe, 0x9b, 0x71, 0x9e, 0xf6,
|
||||
0xf1, 0x89, 0x84, 0x17, 0x99, 0xf4, 0x57, 0x53, 0x99, 0x74, 0xd6, 0xfc, 0x49, 0x26, 0xa4, 0x12,
|
||||
0x48, 0x21, 0x18, 0xff, 0x92, 0x87, 0x72, 0x84, 0x2e, 0x4e, 0xb8, 0x57, 0x94, 0x11, 0xd7, 0x8c,
|
||||
0xef, 0xb8, 0x34, 0x0c, 0x92, 0x25, 0xee, 0x73, 0xde, 0x85, 0x0a, 0x3f, 0x48, 0xcb, 0xe6, 0x9c,
|
||||
0x68, 0x2e, 0x73, 0x86, 0x68, 0x7c, 0x0f, 0xaa, 0xcc, 0x67, 0xd6, 0xc8, 0x64, 0x22, 0xbc, 0xe7,
|
||||
0xe5, 0x68, 0xc1, 0x12, 0xc1, 0x1d, 0xfd, 0x08, 0x36, 0xd9, 0x59, 0xe8, 0x33, 0x36, 0xe2, 0xa9,
|
||||
0xa5, 0x48, 0x74, 0x64, 0x5e, 0x52, 0xc0, 0x7a, 0xdc, 0x20, 0x13, 0x20, 0xca, 0x77, 0xef, 0x49,
|
||||
0x67, 0xee, 0xba, 0x62, 0x13, 0x29, 0xe0, 0xf5, 0x98, 0xcb, 0x5d, 0x9b, 0x07, 0xcf, 0x40, 0x26,
|
||||
0x10, 0x62, 0xaf, 0xd0, 0x70, 0x44, 0x22, 0x13, 0x36, 0x5c, 0x62, 0xd1, 0x71, 0x48, 0x6c, 0xf3,
|
||||
0x85, 0x43, 0x46, 0xb6, 0xbc, 0x98, 0xa8, 0x65, 0x3e, 0x1d, 0x44, 0x6a, 0x69, 0x3e, 0x12, 0xa3,
|
||||
0x71, 0x2d, 0x82, 0x93, 0x34, 0xcf, 0x1c, 0xe4, 0x1b, 0xda, 0x80, 0x6a, 0xef, 0x59, 0xaf, 0xdf,
|
||||
0x39, 0x34, 0x0f, 0x8f, 0x76, 0x3b, 0xaa, 0x36, 0xa6, 0xd7, 0xc1, 0x92, 0xd4, 0x78, 0x7b, 0xff,
|
||||
0xa8, 0xdf, 0x3a, 0x30, 0xfb, 0xfb, 0xed, 0x27, 0x3d, 0x3d, 0x87, 0x6e, 0xc2, 0x66, 0x7f, 0x0f,
|
||||
0x1f, 0xf5, 0xfb, 0x07, 0x9d, 0x5d, 0xf3, 0xb8, 0x83, 0xf7, 0x8f, 0x76, 0x7b, 0x7a, 0x1e, 0x21,
|
||||
0xa8, 0x4d, 0xd8, 0xfd, 0xfd, 0xc3, 0x8e, 0x5e, 0x40, 0x55, 0x58, 0x3d, 0xee, 0xe0, 0x76, 0xa7,
|
||||
0xdb, 0xd7, 0x8b, 0xc6, 0xaf, 0xf3, 0x50, 0x4d, 0x58, 0x91, 0x3b, 0x72, 0x48, 0xe5, 0x31, 0xa4,
|
||||
0x80, 0xf9, 0xab, 0xf8, 0x97, 0x67, 0x0d, 0xce, 0xa4, 0x75, 0x0a, 0x58, 0x12, 0xe2, 0xe8, 0x61,
|
||||
0x5d, 0x26, 0xd6, 0x79, 0x01, 0x97, 0x5d, 0xeb, 0x52, 0x82, 0xfc, 0x00, 0xd6, 0xce, 0x49, 0xe8,
|
||||
0x91, 0x91, 0x6a, 0x97, 0x16, 0xa9, 0x4a, 0x9e, 0xec, 0xb2, 0x0d, 0xba, 0xea, 0x32, 0x81, 0x91,
|
||||
0xe6, 0xa8, 0x49, 0xfe, 0x61, 0x04, 0xb6, 0x05, 0x45, 0xd9, 0xbc, 0x2a, 0xe7, 0x17, 0x04, 0x0f,
|
||||
0x53, 0xf4, 0x95, 0x15, 0x88, 0x94, 0xaf, 0x80, 0xc5, 0x3b, 0x3a, 0x9d, 0xb5, 0x4f, 0x49, 0xd8,
|
||||
0xe7, 0xfe, 0xe2, 0xee, 0xfc, 0x3a, 0x13, 0x9d, 0xc5, 0x26, 0x5a, 0x85, 0x3c, 0x8e, 0x0a, 0x4a,
|
||||
0xda, 0xad, 0xf6, 0x1e, 0x37, 0xcb, 0x3a, 0x54, 0x0e, 0x5b, 0x3f, 0x33, 0x4f, 0x7a, 0xe2, 0xea,
|
||||
0x18, 0xe9, 0xb0, 0xf6, 0xa4, 0x83, 0xbb, 0x9d, 0x03, 0xc5, 0xc9, 0xa3, 0x2d, 0xd0, 0x15, 0x67,
|
||||
0xd2, 0xaf, 0xc0, 0x11, 0xe4, 0x6b, 0x11, 0x95, 0xa1, 0xd0, 0x7b, 0xda, 0x3a, 0xd6, 0x4b, 0xc6,
|
||||
0x7f, 0xe6, 0x60, 0x43, 0x86, 0x85, 0xf8, 0xd7, 0xf7, 0xeb, 0x7f, 0xfd, 0x25, 0x6f, 0x79, 0x72,
|
||||
0xe9, 0x5b, 0x9e, 0x28, 0x09, 0x15, 0x51, 0x3d, 0x3f, 0x49, 0x42, 0xc5, 0xed, 0x50, 0x6a, 0xc7,
|
||||
0x2f, 0x2c, 0xb2, 0xe3, 0xd7, 0x61, 0xd5, 0x25, 0x34, 0xb6, 0x5b, 0x05, 0x47, 0x24, 0x72, 0xa0,
|
||||
0x6a, 0x79, 0x9e, 0xcf, 0x2c, 0x79, 0x75, 0x5a, 0x5a, 0x28, 0x18, 0x4e, 0x7d, 0x71, 0xb3, 0x35,
|
||||
0x41, 0x92, 0x1b, 0x73, 0x12, 0xbb, 0xf1, 0x53, 0xd0, 0xa7, 0x3b, 0x2c, 0x12, 0x0e, 0x7f, 0xf8,
|
||||
0xf1, 0x24, 0x1a, 0x12, 0xbe, 0x2e, 0xd4, 0xc5, 0xbe, 0xbe, 0xc2, 0x09, 0x7c, 0xd2, 0xed, 0xee,
|
||||
0x77, 0x1f, 0xeb, 0x1a, 0x02, 0x28, 0x75, 0x7e, 0xb6, 0xdf, 0xef, 0xec, 0xea, 0xb9, 0x9d, 0xdf,
|
||||
0x6c, 0x42, 0x49, 0x0a, 0x89, 0xbe, 0x55, 0x99, 0x40, 0xb2, 0xac, 0x12, 0xfd, 0x74, 0xe1, 0x8c,
|
||||
0x3a, 0x55, 0xaa, 0xd9, 0x78, 0xb8, 0xf4, 0x78, 0xf5, 0x8b, 0x6b, 0x05, 0xfd, 0x8d, 0x06, 0x6b,
|
||||
0xa9, 0xdf, 0x5b, 0x59, 0xaf, 0x8e, 0xe7, 0x54, 0x71, 0x36, 0x7e, 0xb2, 0xd4, 0xd8, 0x58, 0x96,
|
||||
0x5f, 0x69, 0x50, 0x4d, 0xd4, 0x2f, 0xa2, 0xfb, 0xcb, 0xd4, 0x3c, 0x4a, 0x49, 0x3e, 0x5b, 0xbe,
|
||||
0x5c, 0xd2, 0x58, 0xf9, 0x48, 0x43, 0x7f, 0xad, 0x41, 0x35, 0x51, 0xc9, 0x97, 0x59, 0x94, 0xd9,
|
||||
0xba, 0xc3, 0xcc, 0xa2, 0xcc, 0x2b, 0x1c, 0x5c, 0x41, 0x7f, 0xa9, 0x41, 0x25, 0xae, 0xca, 0x43,
|
||||
0xf7, 0x16, 0xaf, 0xe3, 0x93, 0x42, 0x7c, 0xba, 0x6c, 0x01, 0xa0, 0xb1, 0x82, 0xfe, 0x1c, 0xca,
|
||||
0x51, 0x09, 0x1b, 0xca, 0x1a, 0xbd, 0xa6, 0xea, 0xe3, 0x1a, 0xf7, 0x16, 0x1e, 0x97, 0x9c, 0x3e,
|
||||
0xaa, 0x2b, 0xcb, 0x3c, 0xfd, 0x54, 0x05, 0x5c, 0xe3, 0xde, 0xc2, 0xe3, 0xe2, 0xe9, 0xb9, 0x27,
|
||||
0x24, 0xca, 0xcf, 0x32, 0x7b, 0xc2, 0x6c, 0xdd, 0x5b, 0x66, 0x4f, 0x98, 0x57, 0xed, 0x26, 0x05,
|
||||
0x49, 0x14, 0xb0, 0x65, 0x16, 0x64, 0xb6, 0x48, 0x2e, 0xb3, 0x20, 0x73, 0xea, 0xe5, 0x8c, 0x15,
|
||||
0xf4, 0x4b, 0x2d, 0x79, 0x2e, 0xb8, 0xb7, 0x70, 0x9d, 0xd6, 0x82, 0x2e, 0x39, 0x53, 0x29, 0x26,
|
||||
0x16, 0xe8, 0x2f, 0xd5, 0x2d, 0x86, 0x2c, 0xf3, 0x42, 0x8b, 0x80, 0xa5, 0x2a, 0xc3, 0x1a, 0x9f,
|
||||
0x2c, 0x17, 0x6c, 0x84, 0x10, 0x7f, 0xa5, 0x01, 0x4c, 0x0a, 0xc2, 0x32, 0x0b, 0x31, 0x53, 0x89,
|
||||
0xd6, 0xb8, 0xbf, 0xc4, 0xc8, 0xe4, 0x02, 0x89, 0x0a, 0x56, 0x32, 0x2f, 0x90, 0xa9, 0x82, 0xb5,
|
||||
0xcc, 0x0b, 0x64, 0xba, 0xd8, 0xcc, 0x58, 0x41, 0xff, 0xa4, 0xc1, 0xe6, 0x4c, 0xc1, 0x0c, 0x7a,
|
||||
0x78, 0xcd, 0x9a, 0xa9, 0xc6, 0x17, 0xcb, 0x03, 0x44, 0xa2, 0x6d, 0x6b, 0x1f, 0x69, 0xe8, 0x6f,
|
||||
0x35, 0x58, 0x4f, 0x17, 0x19, 0x64, 0x8e, 0x52, 0x73, 0x4a, 0x6f, 0x1a, 0x0f, 0x96, 0x1b, 0x1c,
|
||||
0x6b, 0xeb, 0xef, 0x35, 0xa8, 0xa5, 0xeb, 0x4d, 0xd0, 0x83, 0xc5, 0xb6, 0x85, 0x29, 0x81, 0x3e,
|
||||
0x5f, 0x72, 0x74, 0x24, 0xd1, 0x97, 0xab, 0x7f, 0x5c, 0x94, 0xd9, 0x5b, 0x49, 0x3c, 0x7e, 0xfc,
|
||||
0xff, 0x01, 0x00, 0x00, 0xff, 0xff, 0x6e, 0xc4, 0x84, 0xf7, 0xfd, 0x32, 0x00, 0x00,
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
|
||||
@@ -382,6 +382,10 @@ message DriverCapabilities {
|
||||
}
|
||||
// MountConfigs indicates whether the driver supports mount configurations.
|
||||
MountConfigs mount_configs = 6;
|
||||
|
||||
// remote_tasks indicates whether the driver executes tasks remotely such
|
||||
// on cloud runtimes like AWS ECS.
|
||||
bool remote_tasks = 7;
|
||||
}
|
||||
|
||||
message NetworkIsolationSpec {
|
||||
|
||||
@@ -43,6 +43,7 @@ func (b *driverPluginServer) Capabilities(ctx context.Context, req *proto.Capabi
|
||||
Exec: caps.Exec,
|
||||
MustCreateNetwork: caps.MustInitiateNetwork,
|
||||
NetworkIsolationModes: []proto.NetworkIsolationSpec_NetworkIsolationMode{},
|
||||
RemoteTasks: caps.RemoteTasks,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package drivers
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/nomad/nomad/structs"
|
||||
"github.com/hashicorp/nomad/plugins/base"
|
||||
)
|
||||
|
||||
@@ -45,3 +46,34 @@ func (h *TaskHandle) Copy() *TaskHandle {
|
||||
copy(handle.DriverState, h.DriverState)
|
||||
return handle
|
||||
}
|
||||
|
||||
// Store this TaskHandle on the given TaskState.
|
||||
func (h *TaskHandle) Store(ts *structs.TaskState) {
|
||||
if h == nil || len(h.DriverState) == 0 {
|
||||
// No handle or state, clear existing state
|
||||
ts.TaskHandle = nil
|
||||
return
|
||||
}
|
||||
|
||||
ds := make([]byte, len(h.DriverState))
|
||||
copy(ds, h.DriverState)
|
||||
ts.TaskHandle = &structs.TaskHandle{
|
||||
Version: h.Version,
|
||||
DriverState: ds,
|
||||
}
|
||||
}
|
||||
|
||||
// NewTaskHandleFromState returns the TaskHandle stored in a TaskState or nil
|
||||
// if no handle was stored.
|
||||
func NewTaskHandleFromState(ts *structs.TaskState) *TaskHandle {
|
||||
if ts.TaskHandle == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
th := TaskHandle{
|
||||
Version: ts.TaskHandle.Version,
|
||||
DriverState: make([]byte, len(ts.TaskHandle.DriverState)),
|
||||
}
|
||||
copy(th.DriverState, ts.TaskHandle.DriverState)
|
||||
return &th
|
||||
}
|
||||
|
||||
@@ -606,6 +606,10 @@ func (s *GenericScheduler) computePlacements(destructive, place []placementResul
|
||||
if missing.IsRescheduling() {
|
||||
updateRescheduleTracker(alloc, prevAllocation, now)
|
||||
}
|
||||
|
||||
// If the allocation has task handles,
|
||||
// copy them to the new allocation
|
||||
propagateTaskState(alloc, prevAllocation, missing.PreviousLost())
|
||||
}
|
||||
|
||||
// If we are placing a canary and we found a match, add the canary
|
||||
@@ -643,6 +647,44 @@ func (s *GenericScheduler) computePlacements(destructive, place []placementResul
|
||||
return nil
|
||||
}
|
||||
|
||||
// propagateTaskState copies task handles from previous allocations to
|
||||
// replacement allocations when the previous allocation is being drained or was
|
||||
// lost. Remote task drivers rely on this to reconnect to remote tasks when the
|
||||
// allocation managing them changes due to a down or draining node.
|
||||
//
|
||||
// The previous allocation will be marked as lost as part of this plan, so its
|
||||
// ClientStatus is not yet lost.
|
||||
func propagateTaskState(newAlloc, prev *structs.Allocation, prevLost bool) {
|
||||
// Don't transfer state from client terminal allocs
|
||||
if prev.ClientTerminalStatus() {
|
||||
return
|
||||
}
|
||||
|
||||
// If previous allocation is not lost and not draining, do not copy
|
||||
// task handles.
|
||||
if !prevLost && !prev.DesiredTransition.ShouldMigrate() {
|
||||
return
|
||||
}
|
||||
|
||||
newAlloc.TaskStates = make(map[string]*structs.TaskState, len(newAlloc.AllocatedResources.Tasks))
|
||||
for taskName, prevState := range prev.TaskStates {
|
||||
if prevState.TaskHandle == nil {
|
||||
// No task handle, skip
|
||||
continue
|
||||
}
|
||||
|
||||
if _, ok := newAlloc.AllocatedResources.Tasks[taskName]; !ok {
|
||||
// Task dropped in update, skip
|
||||
continue
|
||||
}
|
||||
|
||||
// Copy state
|
||||
newState := structs.NewTaskState()
|
||||
newState.TaskHandle = prevState.TaskHandle.Copy()
|
||||
newAlloc.TaskStates[taskName] = newState
|
||||
}
|
||||
}
|
||||
|
||||
// getSelectOptions sets up preferred nodes and penalty nodes
|
||||
func getSelectOptions(prevAllocation *structs.Allocation, preferredNode *structs.Node) *SelectOptions {
|
||||
selectOptions := &SelectOptions{}
|
||||
|
||||
@@ -3327,6 +3327,98 @@ func TestServiceSched_NodeDrain_Queued_Allocations(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestServiceSched_NodeDrain_TaskHandle asserts that allocations with task
|
||||
// handles have them propagated to replacement allocations when drained.
|
||||
func TestServiceSched_NodeDrain_TaskHandle(t *testing.T) {
|
||||
h := NewHarness(t)
|
||||
|
||||
node := mock.Node()
|
||||
require.NoError(t, h.State.UpsertNode(structs.MsgTypeTestSetup, h.NextIndex(), node))
|
||||
|
||||
// Create some nodes
|
||||
for i := 0; i < 10; i++ {
|
||||
node := mock.Node()
|
||||
require.NoError(t, h.State.UpsertNode(structs.MsgTypeTestSetup, h.NextIndex(), node))
|
||||
}
|
||||
|
||||
// Generate a fake job with allocations and an update policy.
|
||||
job := mock.Job()
|
||||
require.NoError(t, h.State.UpsertJob(structs.MsgTypeTestSetup, h.NextIndex(), job))
|
||||
|
||||
var allocs []*structs.Allocation
|
||||
for i := 0; i < 10; i++ {
|
||||
alloc := mock.Alloc()
|
||||
alloc.Job = job
|
||||
alloc.JobID = job.ID
|
||||
alloc.NodeID = node.ID
|
||||
alloc.Name = fmt.Sprintf("my-job.web[%d]", i)
|
||||
alloc.DesiredTransition.Migrate = helper.BoolToPtr(true)
|
||||
alloc.TaskStates = map[string]*structs.TaskState{
|
||||
"web": &structs.TaskState{
|
||||
TaskHandle: &structs.TaskHandle{
|
||||
Version: 1,
|
||||
DriverState: []byte("test-driver-state"),
|
||||
},
|
||||
},
|
||||
}
|
||||
allocs = append(allocs, alloc)
|
||||
}
|
||||
require.NoError(t, h.State.UpsertAllocs(structs.MsgTypeTestSetup, h.NextIndex(), allocs))
|
||||
|
||||
node.DrainStrategy = mock.DrainNode().DrainStrategy
|
||||
require.NoError(t, h.State.UpsertNode(structs.MsgTypeTestSetup, h.NextIndex(), node))
|
||||
|
||||
// Create a mock evaluation to deal with drain
|
||||
eval := &structs.Evaluation{
|
||||
Namespace: structs.DefaultNamespace,
|
||||
ID: uuid.Generate(),
|
||||
Priority: 50,
|
||||
TriggeredBy: structs.EvalTriggerNodeUpdate,
|
||||
JobID: job.ID,
|
||||
NodeID: node.ID,
|
||||
Status: structs.EvalStatusPending,
|
||||
}
|
||||
require.NoError(t, h.State.UpsertEvals(structs.MsgTypeTestSetup, h.NextIndex(), []*structs.Evaluation{eval}))
|
||||
|
||||
// Process the evaluation
|
||||
err := h.Process(NewServiceScheduler, eval)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Ensure a single plan
|
||||
require.Len(t, h.Plans, 1)
|
||||
plan := h.Plans[0]
|
||||
|
||||
// Ensure the plan evicted all allocs
|
||||
require.Len(t, plan.NodeUpdate[node.ID], len(allocs))
|
||||
|
||||
// Ensure the plan allocated
|
||||
var planned []*structs.Allocation
|
||||
for _, allocList := range plan.NodeAllocation {
|
||||
planned = append(planned, allocList...)
|
||||
}
|
||||
require.Len(t, planned, len(allocs))
|
||||
|
||||
// Lookup the allocations by JobID
|
||||
ws := memdb.NewWatchSet()
|
||||
out, err := h.State.AllocsByJob(ws, job.Namespace, job.ID, false)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Ensure all allocations placed
|
||||
out, _ = structs.FilterTerminalAllocs(out)
|
||||
require.Len(t, out, len(allocs))
|
||||
|
||||
// Ensure task states were propagated
|
||||
for _, a := range out {
|
||||
require.NotEmpty(t, a.TaskStates)
|
||||
require.NotEmpty(t, a.TaskStates["web"])
|
||||
require.NotNil(t, a.TaskStates["web"].TaskHandle)
|
||||
assert.Equal(t, 1, a.TaskStates["web"].TaskHandle.Version)
|
||||
assert.Equal(t, []byte("test-driver-state"), a.TaskStates["web"].TaskHandle.DriverState)
|
||||
}
|
||||
|
||||
h.AssertEvalStatus(t, structs.EvalStatusComplete)
|
||||
}
|
||||
|
||||
func TestServiceSched_RetryLimit(t *testing.T) {
|
||||
h := NewHarness(t)
|
||||
h.Planner = &RejectPlan{h}
|
||||
@@ -6075,3 +6167,121 @@ func TestServiceSched_CSIVolumesPerAlloc(t *testing.T) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// TestPropagateTaskState asserts that propagateTaskState only copies state
|
||||
// when the previous allocation is lost or draining.
|
||||
func TestPropagateTaskState(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
const taskName = "web"
|
||||
taskHandle := &structs.TaskHandle{
|
||||
Version: 1,
|
||||
DriverState: []byte("driver-state"),
|
||||
}
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
prevAlloc *structs.Allocation
|
||||
prevLost bool
|
||||
copied bool
|
||||
}{
|
||||
{
|
||||
name: "LostWithState",
|
||||
prevAlloc: &structs.Allocation{
|
||||
ClientStatus: structs.AllocClientStatusRunning,
|
||||
DesiredTransition: structs.DesiredTransition{},
|
||||
TaskStates: map[string]*structs.TaskState{
|
||||
taskName: &structs.TaskState{
|
||||
TaskHandle: taskHandle,
|
||||
},
|
||||
},
|
||||
},
|
||||
prevLost: true,
|
||||
copied: true,
|
||||
},
|
||||
{
|
||||
name: "DrainedWithState",
|
||||
prevAlloc: &structs.Allocation{
|
||||
ClientStatus: structs.AllocClientStatusRunning,
|
||||
DesiredTransition: structs.DesiredTransition{
|
||||
Migrate: helper.BoolToPtr(true),
|
||||
},
|
||||
TaskStates: map[string]*structs.TaskState{
|
||||
taskName: &structs.TaskState{
|
||||
TaskHandle: taskHandle,
|
||||
},
|
||||
},
|
||||
},
|
||||
prevLost: false,
|
||||
copied: true,
|
||||
},
|
||||
{
|
||||
name: "LostWithoutState",
|
||||
prevAlloc: &structs.Allocation{
|
||||
ClientStatus: structs.AllocClientStatusRunning,
|
||||
DesiredTransition: structs.DesiredTransition{},
|
||||
TaskStates: map[string]*structs.TaskState{
|
||||
taskName: &structs.TaskState{},
|
||||
},
|
||||
},
|
||||
prevLost: true,
|
||||
copied: false,
|
||||
},
|
||||
{
|
||||
name: "DrainedWithoutState",
|
||||
prevAlloc: &structs.Allocation{
|
||||
ClientStatus: structs.AllocClientStatusRunning,
|
||||
DesiredTransition: structs.DesiredTransition{
|
||||
Migrate: helper.BoolToPtr(true),
|
||||
},
|
||||
TaskStates: map[string]*structs.TaskState{
|
||||
taskName: &structs.TaskState{},
|
||||
},
|
||||
},
|
||||
prevLost: false,
|
||||
copied: false,
|
||||
},
|
||||
{
|
||||
name: "TerminalWithState",
|
||||
prevAlloc: &structs.Allocation{
|
||||
ClientStatus: structs.AllocClientStatusComplete,
|
||||
DesiredTransition: structs.DesiredTransition{},
|
||||
TaskStates: map[string]*structs.TaskState{
|
||||
taskName: &structs.TaskState{
|
||||
TaskHandle: taskHandle,
|
||||
},
|
||||
},
|
||||
},
|
||||
prevLost: false,
|
||||
copied: false,
|
||||
},
|
||||
}
|
||||
|
||||
for i := range cases {
|
||||
tc := cases[i]
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
newAlloc := &structs.Allocation{
|
||||
// Required by propagateTaskState and populated
|
||||
// by the scheduler's node iterator.
|
||||
AllocatedResources: &structs.AllocatedResources{
|
||||
Tasks: map[string]*structs.AllocatedTaskResources{
|
||||
taskName: nil, // value isn't used
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
propagateTaskState(newAlloc, tc.prevAlloc, tc.prevLost)
|
||||
|
||||
if tc.copied {
|
||||
// Assert state was copied
|
||||
require.NotNil(t, newAlloc.TaskStates)
|
||||
require.Contains(t, newAlloc.TaskStates, taskName)
|
||||
require.Equal(t, taskHandle, newAlloc.TaskStates[taskName].TaskHandle)
|
||||
} else {
|
||||
// Assert state was *not* copied
|
||||
require.Empty(t, newAlloc.TaskStates,
|
||||
"expected task states not to be copied")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -396,12 +396,13 @@ func (a *allocReconciler) computeGroup(group string, all allocSet) bool {
|
||||
// reschedulable later and mark the allocations for in place updating
|
||||
a.handleDelayedReschedules(rescheduleLater, all, tg.Name)
|
||||
|
||||
// Create a structure for choosing names. Seed with the taken names which is
|
||||
// the union of untainted and migrating nodes (includes canaries)
|
||||
nameIndex := newAllocNameIndex(a.jobID, group, tg.Count, untainted.union(migrate, rescheduleNow))
|
||||
// Create a structure for choosing names. Seed with the taken names
|
||||
// which is the union of untainted, rescheduled, allocs on migrating
|
||||
// nodes, and allocs on down nodes (includes canaries)
|
||||
nameIndex := newAllocNameIndex(a.jobID, group, tg.Count, untainted.union(migrate, rescheduleNow, lost))
|
||||
|
||||
// Stop any unneeded allocations and update the untainted set to not
|
||||
// included stopped allocations.
|
||||
// include stopped allocations.
|
||||
canaryState := dstate != nil && dstate.DesiredCanaries != 0 && !dstate.Promoted
|
||||
stop := a.computeStop(tg, nameIndex, untainted, migrate, lost, canaries, canaryState, lostLaterEvals)
|
||||
desiredChanges.Stop += uint64(len(stop))
|
||||
@@ -452,9 +453,10 @@ func (a *allocReconciler) computeGroup(group string, all allocSet) bool {
|
||||
// * Not placing any canaries
|
||||
// * If there are any canaries that they have been promoted
|
||||
// * There is no delayed stop_after_client_disconnect alloc, which delays scheduling for the whole group
|
||||
// * An alloc was lost
|
||||
var place []allocPlaceResult
|
||||
if len(lostLater) == 0 {
|
||||
place = a.computePlacements(tg, nameIndex, untainted, migrate, rescheduleNow, canaryState)
|
||||
place = a.computePlacements(tg, nameIndex, untainted, migrate, rescheduleNow, canaryState, lost)
|
||||
if !existingDeployment {
|
||||
dstate.DesiredTotal += len(place)
|
||||
}
|
||||
@@ -705,8 +707,11 @@ func (a *allocReconciler) computeLimit(group *structs.TaskGroup, untainted, dest
|
||||
|
||||
// computePlacement returns the set of allocations to place given the group
|
||||
// definition, the set of untainted, migrating and reschedule allocations for the group.
|
||||
//
|
||||
// Placements will meet or exceed group count.
|
||||
func (a *allocReconciler) computePlacements(group *structs.TaskGroup,
|
||||
nameIndex *allocNameIndex, untainted, migrate allocSet, reschedule allocSet, canaryState bool) []allocPlaceResult {
|
||||
nameIndex *allocNameIndex, untainted, migrate allocSet, reschedule allocSet,
|
||||
canaryState bool, lost allocSet) []allocPlaceResult {
|
||||
|
||||
// Add rescheduled placement results
|
||||
var place []allocPlaceResult
|
||||
@@ -720,13 +725,31 @@ func (a *allocReconciler) computePlacements(group *structs.TaskGroup,
|
||||
|
||||
downgradeNonCanary: canaryState && !alloc.DeploymentStatus.IsCanary(),
|
||||
minJobVersion: alloc.Job.Version,
|
||||
lost: false,
|
||||
})
|
||||
}
|
||||
|
||||
// Hot path the nothing to do case
|
||||
// Add replacements for lost allocs up to group.Count
|
||||
existing := len(untainted) + len(migrate) + len(reschedule)
|
||||
if existing >= group.Count {
|
||||
return place
|
||||
|
||||
for _, alloc := range lost {
|
||||
if existing >= group.Count {
|
||||
// Reached desired count, do not replace remaining lost
|
||||
// allocs
|
||||
break
|
||||
}
|
||||
|
||||
existing++
|
||||
place = append(place, allocPlaceResult{
|
||||
name: alloc.Name,
|
||||
taskGroup: group,
|
||||
previousAlloc: alloc,
|
||||
reschedule: false,
|
||||
canary: alloc.DeploymentStatus.IsCanary(),
|
||||
downgradeNonCanary: canaryState && !alloc.DeploymentStatus.IsCanary(),
|
||||
minJobVersion: alloc.Job.Version,
|
||||
lost: true,
|
||||
})
|
||||
}
|
||||
|
||||
// Add remaining placement results
|
||||
@@ -749,8 +772,7 @@ func (a *allocReconciler) computePlacements(group *structs.TaskGroup,
|
||||
func (a *allocReconciler) computeStop(group *structs.TaskGroup, nameIndex *allocNameIndex,
|
||||
untainted, migrate, lost, canaries allocSet, canaryState bool, followupEvals map[string]string) allocSet {
|
||||
|
||||
// Mark all lost allocations for stop. Previous allocation doesn't matter
|
||||
// here since it is on a lost node
|
||||
// Mark all lost allocations for stop.
|
||||
var stop allocSet
|
||||
stop = stop.union(lost)
|
||||
a.markDelayed(lost, structs.AllocClientStatusLost, allocLost, followupEvals)
|
||||
|
||||
@@ -35,6 +35,9 @@ type placementResult interface {
|
||||
// stopped and if so the status description.
|
||||
StopPreviousAlloc() (bool, string)
|
||||
|
||||
// PreviousLost is true if the previous allocation was lost.
|
||||
PreviousLost() bool
|
||||
|
||||
// DowngradeNonCanary indicates that placement should use the latest stable job
|
||||
// with the MinJobVersion, rather than the current deployment version
|
||||
DowngradeNonCanary() bool
|
||||
@@ -58,6 +61,7 @@ type allocPlaceResult struct {
|
||||
taskGroup *structs.TaskGroup
|
||||
previousAlloc *structs.Allocation
|
||||
reschedule bool
|
||||
lost bool
|
||||
|
||||
downgradeNonCanary bool
|
||||
minJobVersion uint64
|
||||
@@ -71,6 +75,7 @@ func (a allocPlaceResult) IsRescheduling() bool { return a.re
|
||||
func (a allocPlaceResult) StopPreviousAlloc() (bool, string) { return false, "" }
|
||||
func (a allocPlaceResult) DowngradeNonCanary() bool { return a.downgradeNonCanary }
|
||||
func (a allocPlaceResult) MinJobVersion() uint64 { return a.minJobVersion }
|
||||
func (a allocPlaceResult) PreviousLost() bool { return a.lost }
|
||||
|
||||
// allocDestructiveResult contains the information required to do a destructive
|
||||
// update. Destructive changes should be applied atomically, as in the old alloc
|
||||
@@ -92,6 +97,7 @@ func (a allocDestructiveResult) StopPreviousAlloc() (bool, string) {
|
||||
}
|
||||
func (a allocDestructiveResult) DowngradeNonCanary() bool { return false }
|
||||
func (a allocDestructiveResult) MinJobVersion() uint64 { return 0 }
|
||||
func (a allocDestructiveResult) PreviousLost() bool { return false }
|
||||
|
||||
// allocMatrix is a mapping of task groups to their allocation set.
|
||||
type allocMatrix map[string]allocSet
|
||||
|
||||
Reference in New Issue
Block a user