diff --git a/Makefile b/Makefile index ecbc198..e8c1a6b 100644 --- a/Makefile +++ b/Makefile @@ -79,6 +79,10 @@ test: tidy ## Runs unit tests server: ## Runs uncompiled version of the server go run cmd/server/server.go --global-token rainbow +.PHONY: server-verbose +server-verbose: ## Runs uncompiled version of the server + go run cmd/server/server.go --loglevel 6 --global-token rainbow + .PHONY: stream stream: ## Runs the interface client go run cmd/stream/stream.go @@ -88,9 +92,13 @@ register: ## Run mock registration go run cmd/rainbow/rainbow.go register cluster --cluster-name keebler --nodes-json ./docs/examples/scheduler/cluster-nodes.json --config-path ./docs/examples/scheduler/rainbow-config.yaml --save .PHONY: subsystem -subsystem: ## Run mock registration +subsystem: ## Register subsystem go run cmd/rainbow/rainbow.go register subsystem --subsystem io --nodes-json ./docs/examples/scheduler/cluster-io-subsystem.json --config-path ./docs/examples/scheduler/rainbow-config.yaml +.PHONY: update-state +update-state: ## Update state + go run cmd/rainbow/rainbow.go update state --state-file ./docs/examples/scheduler/cluster-state.json --config-path ./docs/examples/scheduler/rainbow-config.yaml + .PHONY: tag tag: ## Creates release tag git tag -s -m "version bump to $(VERSION)" $(VERSION) diff --git a/api/v1/rainbow.proto b/api/v1/rainbow.proto index a8b7575..a02dc41 100644 --- a/api/v1/rainbow.proto +++ b/api/v1/rainbow.proto @@ -18,6 +18,10 @@ service RainbowScheduler { // Job Submission - request for submitting a job to a named cluster rpc SubmitJob(SubmitJobRequest) returns (SubmitJobResponse); + // Update State - allow a cluster to provide state metadata + // This is intended for use by a selection algorithm + rpc UpdateState(UpdateStateRequest) returns (UpdateStateResponse); + // Request Job - ask the rainbow scheduler for up to max jobs rpc ReceiveJobs(ReceiveJobsRequest) returns (ReceiveJobsResponse); @@ -37,6 +41,29 @@ message RegisterRequest { google.protobuf.Timestamp sent = 5; } +// UpdateStateRequests allows a cluster to set arbitrary metadata +// for its state. State metadata is used for selection algorithms +message UpdateStateRequest { + string cluster = 1; + string secret = 2; + + // We are generous that the payload can be a flat + // set of key value pairs, and will be parsed into + // types within the graph database + string payload = 3; +} + +message UpdateStateResponse { + enum ResultType { + UPDATE_STATE_UNSPECIFIED = 0; + UPDATE_STATE_PARTIAL = 1; + UPDATE_STATE_SUCCESS = 2; + UPDATE_STATE_ERROR = 3; + } + ResultType status = 1; +} + + // SubmitJobRequest takes a job name, cluster name // and requires the cluster token. Since we want to be generic, // we currently accept nodes, tasks, and the command diff --git a/cmd/rainbow/rainbow.go b/cmd/rainbow/rainbow.go index 0d07d2c..e1e0ce7 100644 --- a/cmd/rainbow/rainbow.go +++ b/cmd/rainbow/rainbow.go @@ -10,6 +10,7 @@ import ( "github.com/converged-computing/rainbow/cmd/rainbow/receive" "github.com/converged-computing/rainbow/cmd/rainbow/register" "github.com/converged-computing/rainbow/cmd/rainbow/submit" + "github.com/converged-computing/rainbow/cmd/rainbow/update" "github.com/converged-computing/rainbow/pkg/types" // Register database backends and selection algorithms @@ -41,6 +42,7 @@ func main() { submitCmd := parser.NewCommand("submit", "Submit a job to a rainbow scheduler") receiveCmd := parser.NewCommand("receive", "Receive and accept jobs") registerClusterCmd := registerCmd.NewCommand("cluster", "Register a new cluster") + updateCmd := parser.NewCommand("update", "Update a cluster") // Configuration configCmd := parser.NewCommand("config", "Interact with rainbow configs") @@ -69,6 +71,10 @@ func main() { // Register subsystem (requires config file for authentication) subsysCmd := registerCmd.NewCommand("subsystem", "Register a new subsystem") + // Update subcommands - currently just supported are state + stateCmd := updateCmd.NewCommand("state", "Update the state for a known cluster") + stateFile := stateCmd.String("", "state-file", &argparse.Options{Help: "JSON file with key, value attributes for the cluster"}) + // Submit (note that command for now needs to be in quotes to get the whole thing) token := submitCmd.String("", "token", &argparse.Options{Default: defaultSecret, Help: "Client token to submit jobs with."}) nodes := submitCmd.Int("n", "nodes", &argparse.Options{Default: 1, Help: "Number of nodes to request"}) @@ -91,6 +97,17 @@ func main() { log.Fatalf("Issue with config: %s\n", err) } + } else if stateCmd.Happened() { + err := update.UpdateState( + *host, + *clusterName, + *stateFile, + *cfg, + ) + if err != nil { + log.Fatalf("Issue with register subsystem: %s\n", err) + } + } else if registerCmd.Happened() { if subsysCmd.Happened() { diff --git a/cmd/rainbow/update/state.go b/cmd/rainbow/update/state.go new file mode 100644 index 0000000..db357db --- /dev/null +++ b/cmd/rainbow/update/state.go @@ -0,0 +1,51 @@ +package update + +import ( + "context" + "fmt" + "log" + + "github.com/converged-computing/rainbow/pkg/client" + "github.com/converged-computing/rainbow/pkg/config" +) + +// UpdateState updates state for a cluster +func UpdateState( + host, + clusterName, + stateFile, + cfgFile string, +) error { + + c, err := client.NewClient(host) + if err != nil { + return err + } + + // A config file is required here + if cfgFile == "" { + return fmt.Errorf("an existing configuration file is required to update an existing cluster") + } + if stateFile == "" { + return fmt.Errorf("a state file (json with key value pairs) is required to update state") + } + // Read in the config, if provided, command line takes preference + cfg, err := config.NewRainbowClientConfig(cfgFile, "", "", "", "", "") + if err != nil { + return err + } + + log.Printf("updating state for cluster: %s", cfg.Scheduler.Name) + + // Last argument is subsystem name, which we can derive from graph + response, err := c.UpdateState( + context.Background(), + cfg.Cluster.Name, + cfg.Cluster.Secret, + stateFile, + ) + // If we get here, success! Dump all the stuff. + log.Printf("%s", response) + return err + +} diff --git a/docs/commands.md b/docs/commands.md index 667589f..a39ac01 100644 --- a/docs/commands.md +++ b/docs/commands.md @@ -7,7 +7,11 @@ The following commands are currently supported. For Python, see the [README](htt You can run the server (with defaults) as follows: ```bash +# Regular logging make server + +# Verbose logging +make server-verbose ``` ```console go run cmd/server/server.go --global-token rainbow @@ -180,6 +184,40 @@ the following reasons: In Computer Science I think they are used interchangeably. For next steps we will be updating the memory graph database to be a little more meaty (adding proper metadata and likely a summary of resources at the top as a quick "does it satisfy" heuristic) and then working on the next interaction, the client submit command, which is going to hit the `Satisfies` endpoint. I will write up more about the database and submit design after that. +## Update State + +A cluster state is intended to be a superficial view of the cluster status. It's not considered a subsystem because (for the time being) we are only considering a flat listing of key value pairs that describe a cluster. The data is also intended to be small so it can be provided via this update endpoint more frequently. As an example, an update payload may look like the following: + +```json +{ + "cost-per-node": 12, + "nodes-free": 100 +} +``` + +While the above would not be suited for a real-world deployment (for example, there are many more costs than per node, and occupancy goes beyond nodes free) +but this will be appropriate for small tests and simulations. The metadata above will be provided, on a cluster level, for a final selection algorithm (to use or not). So after you've created your cluster, let's update the state. + +```bash +make update-state +``` +```console +Adding edge from socket -contains-> core +Adding edge from socket -contains-> core +2024/04/05 18:38:13 We have made an in memory graph (subsystem cluster) with 45 vertices! +Metrics for subsystem cluster{ + "cluster": 1, + "core": 36, + "node": 3, + "rack": 1, + "socket": 3 +} +2024/04/05 18:38:16 📝️ received state update: keebler +Updating state cost-per-node to 12 +Updating state max-jobs to 100 +``` +In debug logging mode (`make server-debug`) you will see the values updated, as shown above. They are also in blue, which you can't see! Note that this state metadata is provided to a selection algorithm, and we will be added more interesting ones soon for experiments! + ## Register Subsystem Adding a subsystem means adding another graph that has nodes with edges that connect (in some meaningful way) to the dominant subsystem. diff --git a/docs/examples/scheduler/cluster-state.json b/docs/examples/scheduler/cluster-state.json new file mode 100644 index 0000000..3c8932c --- /dev/null +++ b/docs/examples/scheduler/cluster-state.json @@ -0,0 +1,4 @@ +{ + "cost-per-node": 12, + "max-jobs": 100 +} \ No newline at end of file diff --git a/docs/examples/scheduler/rainbow-config.yaml b/docs/examples/scheduler/rainbow-config.yaml index 316602f..c0493ee 100644 --- a/docs/examples/scheduler/rainbow-config.yaml +++ b/docs/examples/scheduler/rainbow-config.yaml @@ -8,7 +8,7 @@ scheduler: name: match cluster: name: keebler - secret: 79643f8e-6408-4cd1-bd1a-76aa499d5864 + secret: 76948f58-8655-48c1-aaab-fccedf2bb383 graphdatabase: name: memory host: 127.0.0.1:50051 diff --git a/pkg/api/v1/rainbow.pb.go b/pkg/api/v1/rainbow.pb.go index daf7f9c..25be690 100644 --- a/pkg/api/v1/rainbow.pb.go +++ b/pkg/api/v1/rainbow.pb.go @@ -21,6 +21,58 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) +type UpdateStateResponse_ResultType int32 + +const ( + UpdateStateResponse_UPDATE_STATE_UNSPECIFIED UpdateStateResponse_ResultType = 0 + UpdateStateResponse_UPDATE_STATE_PARTIAL UpdateStateResponse_ResultType = 1 + UpdateStateResponse_UPDATE_STATE_SUCCESS UpdateStateResponse_ResultType = 2 + UpdateStateResponse_UPDATE_STATE_ERROR UpdateStateResponse_ResultType = 3 +) + +// Enum value maps for UpdateStateResponse_ResultType. +var ( + UpdateStateResponse_ResultType_name = map[int32]string{ + 0: "UPDATE_STATE_UNSPECIFIED", + 1: "UPDATE_STATE_PARTIAL", + 2: "UPDATE_STATE_SUCCESS", + 3: "UPDATE_STATE_ERROR", + } + UpdateStateResponse_ResultType_value = map[string]int32{ + "UPDATE_STATE_UNSPECIFIED": 0, + "UPDATE_STATE_PARTIAL": 1, + "UPDATE_STATE_SUCCESS": 2, + "UPDATE_STATE_ERROR": 3, + } +) + +func (x UpdateStateResponse_ResultType) Enum() *UpdateStateResponse_ResultType { + p := new(UpdateStateResponse_ResultType) + *p = x + return p +} + +func (x UpdateStateResponse_ResultType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (UpdateStateResponse_ResultType) Descriptor() protoreflect.EnumDescriptor { + return file_rainbow_proto_enumTypes[0].Descriptor() +} + +func (UpdateStateResponse_ResultType) Type() protoreflect.EnumType { + return &file_rainbow_proto_enumTypes[0] +} + +func (x UpdateStateResponse_ResultType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use UpdateStateResponse_ResultType.Descriptor instead. +func (UpdateStateResponse_ResultType) EnumDescriptor() ([]byte, []int) { + return file_rainbow_proto_rawDescGZIP(), []int{2, 0} +} + // Registration statuses type RegisterResponse_ResultType int32 @@ -61,11 +113,11 @@ func (x RegisterResponse_ResultType) String() string { } func (RegisterResponse_ResultType) Descriptor() protoreflect.EnumDescriptor { - return file_rainbow_proto_enumTypes[0].Descriptor() + return file_rainbow_proto_enumTypes[1].Descriptor() } func (RegisterResponse_ResultType) Type() protoreflect.EnumType { - return &file_rainbow_proto_enumTypes[0] + return &file_rainbow_proto_enumTypes[1] } func (x RegisterResponse_ResultType) Number() protoreflect.EnumNumber { @@ -74,7 +126,7 @@ func (x RegisterResponse_ResultType) Number() protoreflect.EnumNumber { // Deprecated: Use RegisterResponse_ResultType.Descriptor instead. func (RegisterResponse_ResultType) EnumDescriptor() ([]byte, []int) { - return file_rainbow_proto_rawDescGZIP(), []int{4, 0} + return file_rainbow_proto_rawDescGZIP(), []int{6, 0} } // Enum to represent the result types of the operation. @@ -114,11 +166,11 @@ func (x SubmitJobResponse_ResultType) String() string { } func (SubmitJobResponse_ResultType) Descriptor() protoreflect.EnumDescriptor { - return file_rainbow_proto_enumTypes[1].Descriptor() + return file_rainbow_proto_enumTypes[2].Descriptor() } func (SubmitJobResponse_ResultType) Type() protoreflect.EnumType { - return &file_rainbow_proto_enumTypes[1] + return &file_rainbow_proto_enumTypes[2] } func (x SubmitJobResponse_ResultType) Number() protoreflect.EnumNumber { @@ -127,7 +179,7 @@ func (x SubmitJobResponse_ResultType) Number() protoreflect.EnumNumber { // Deprecated: Use SubmitJobResponse_ResultType.Descriptor instead. func (SubmitJobResponse_ResultType) EnumDescriptor() ([]byte, []int) { - return file_rainbow_proto_rawDescGZIP(), []int{5, 0} + return file_rainbow_proto_rawDescGZIP(), []int{7, 0} } // Enum to represent the result types of the operation. @@ -167,11 +219,11 @@ func (x ReceiveJobsResponse_ResultType) String() string { } func (ReceiveJobsResponse_ResultType) Descriptor() protoreflect.EnumDescriptor { - return file_rainbow_proto_enumTypes[2].Descriptor() + return file_rainbow_proto_enumTypes[3].Descriptor() } func (ReceiveJobsResponse_ResultType) Type() protoreflect.EnumType { - return &file_rainbow_proto_enumTypes[2] + return &file_rainbow_proto_enumTypes[3] } func (x ReceiveJobsResponse_ResultType) Number() protoreflect.EnumNumber { @@ -180,7 +232,7 @@ func (x ReceiveJobsResponse_ResultType) Number() protoreflect.EnumNumber { // Deprecated: Use ReceiveJobsResponse_ResultType.Descriptor instead. func (ReceiveJobsResponse_ResultType) EnumDescriptor() ([]byte, []int) { - return file_rainbow_proto_rawDescGZIP(), []int{6, 0} + return file_rainbow_proto_rawDescGZIP(), []int{8, 0} } type AcceptJobsResponse_ResultType int32 @@ -219,11 +271,11 @@ func (x AcceptJobsResponse_ResultType) String() string { } func (AcceptJobsResponse_ResultType) Descriptor() protoreflect.EnumDescriptor { - return file_rainbow_proto_enumTypes[3].Descriptor() + return file_rainbow_proto_enumTypes[4].Descriptor() } func (AcceptJobsResponse_ResultType) Type() protoreflect.EnumType { - return &file_rainbow_proto_enumTypes[3] + return &file_rainbow_proto_enumTypes[4] } func (x AcceptJobsResponse_ResultType) Number() protoreflect.EnumNumber { @@ -232,7 +284,7 @@ func (x AcceptJobsResponse_ResultType) Number() protoreflect.EnumNumber { // Deprecated: Use AcceptJobsResponse_ResultType.Descriptor instead. func (AcceptJobsResponse_ResultType) EnumDescriptor() ([]byte, []int) { - return file_rainbow_proto_rawDescGZIP(), []int{7, 0} + return file_rainbow_proto_rawDescGZIP(), []int{9, 0} } // RegisterRequest registers a cluster to the scheduler service @@ -317,6 +369,121 @@ func (x *RegisterRequest) GetSent() *timestamppb.Timestamp { return nil } +// UpdateStateRequests allows a cluster to set arbitrary metadata +// for its state. State metadata is used for selection algorithms +type UpdateStateRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Cluster string `protobuf:"bytes,1,opt,name=cluster,proto3" json:"cluster,omitempty"` + Secret string `protobuf:"bytes,2,opt,name=secret,proto3" json:"secret,omitempty"` + // We are generous that the payload can be a flat + // set of key value pairs, and will be parsed into + // types within the graph database + Payload string `protobuf:"bytes,3,opt,name=payload,proto3" json:"payload,omitempty"` +} + +func (x *UpdateStateRequest) Reset() { + *x = UpdateStateRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_rainbow_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UpdateStateRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateStateRequest) ProtoMessage() {} + +func (x *UpdateStateRequest) ProtoReflect() protoreflect.Message { + mi := &file_rainbow_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UpdateStateRequest.ProtoReflect.Descriptor instead. +func (*UpdateStateRequest) Descriptor() ([]byte, []int) { + return file_rainbow_proto_rawDescGZIP(), []int{1} +} + +func (x *UpdateStateRequest) GetCluster() string { + if x != nil { + return x.Cluster + } + return "" +} + +func (x *UpdateStateRequest) GetSecret() string { + if x != nil { + return x.Secret + } + return "" +} + +func (x *UpdateStateRequest) GetPayload() string { + if x != nil { + return x.Payload + } + return "" +} + +type UpdateStateResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Status UpdateStateResponse_ResultType `protobuf:"varint,1,opt,name=status,proto3,enum=convergedcomputing.org.grpc.v1.UpdateStateResponse_ResultType" json:"status,omitempty"` +} + +func (x *UpdateStateResponse) Reset() { + *x = UpdateStateResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_rainbow_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UpdateStateResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateStateResponse) ProtoMessage() {} + +func (x *UpdateStateResponse) ProtoReflect() protoreflect.Message { + mi := &file_rainbow_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UpdateStateResponse.ProtoReflect.Descriptor instead. +func (*UpdateStateResponse) Descriptor() ([]byte, []int) { + return file_rainbow_proto_rawDescGZIP(), []int{2} +} + +func (x *UpdateStateResponse) GetStatus() UpdateStateResponse_ResultType { + if x != nil { + return x.Status + } + return UpdateStateResponse_UPDATE_STATE_UNSPECIFIED +} + // SubmitJobRequest takes a job name, cluster name // and requires the cluster token. Since we want to be generic, // we currently accept nodes, tasks, and the command @@ -334,7 +501,7 @@ type SubmitJobRequest struct { func (x *SubmitJobRequest) Reset() { *x = SubmitJobRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rainbow_proto_msgTypes[1] + mi := &file_rainbow_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -347,7 +514,7 @@ func (x *SubmitJobRequest) String() string { func (*SubmitJobRequest) ProtoMessage() {} func (x *SubmitJobRequest) ProtoReflect() protoreflect.Message { - mi := &file_rainbow_proto_msgTypes[1] + mi := &file_rainbow_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -360,7 +527,7 @@ func (x *SubmitJobRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SubmitJobRequest.ProtoReflect.Descriptor instead. func (*SubmitJobRequest) Descriptor() ([]byte, []int) { - return file_rainbow_proto_rawDescGZIP(), []int{1} + return file_rainbow_proto_rawDescGZIP(), []int{3} } func (x *SubmitJobRequest) GetName() string { @@ -412,7 +579,7 @@ type ReceiveJobsRequest struct { func (x *ReceiveJobsRequest) Reset() { *x = ReceiveJobsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rainbow_proto_msgTypes[2] + mi := &file_rainbow_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -425,7 +592,7 @@ func (x *ReceiveJobsRequest) String() string { func (*ReceiveJobsRequest) ProtoMessage() {} func (x *ReceiveJobsRequest) ProtoReflect() protoreflect.Message { - mi := &file_rainbow_proto_msgTypes[2] + mi := &file_rainbow_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -438,7 +605,7 @@ func (x *ReceiveJobsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ReceiveJobsRequest.ProtoReflect.Descriptor instead. func (*ReceiveJobsRequest) Descriptor() ([]byte, []int) { - return file_rainbow_proto_rawDescGZIP(), []int{2} + return file_rainbow_proto_rawDescGZIP(), []int{4} } func (x *ReceiveJobsRequest) GetCluster() string { @@ -484,7 +651,7 @@ type AcceptJobsRequest struct { func (x *AcceptJobsRequest) Reset() { *x = AcceptJobsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rainbow_proto_msgTypes[3] + mi := &file_rainbow_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -497,7 +664,7 @@ func (x *AcceptJobsRequest) String() string { func (*AcceptJobsRequest) ProtoMessage() {} func (x *AcceptJobsRequest) ProtoReflect() protoreflect.Message { - mi := &file_rainbow_proto_msgTypes[3] + mi := &file_rainbow_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -510,7 +677,7 @@ func (x *AcceptJobsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use AcceptJobsRequest.ProtoReflect.Descriptor instead. func (*AcceptJobsRequest) Descriptor() ([]byte, []int) { - return file_rainbow_proto_rawDescGZIP(), []int{3} + return file_rainbow_proto_rawDescGZIP(), []int{5} } func (x *AcceptJobsRequest) GetCluster() string { @@ -559,7 +726,7 @@ type RegisterResponse struct { func (x *RegisterResponse) Reset() { *x = RegisterResponse{} if protoimpl.UnsafeEnabled { - mi := &file_rainbow_proto_msgTypes[4] + mi := &file_rainbow_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -572,7 +739,7 @@ func (x *RegisterResponse) String() string { func (*RegisterResponse) ProtoMessage() {} func (x *RegisterResponse) ProtoReflect() protoreflect.Message { - mi := &file_rainbow_proto_msgTypes[4] + mi := &file_rainbow_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -585,7 +752,7 @@ func (x *RegisterResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RegisterResponse.ProtoReflect.Descriptor instead. func (*RegisterResponse) Descriptor() ([]byte, []int) { - return file_rainbow_proto_rawDescGZIP(), []int{4} + return file_rainbow_proto_rawDescGZIP(), []int{6} } func (x *RegisterResponse) GetRequestId() string { @@ -631,7 +798,7 @@ type SubmitJobResponse struct { func (x *SubmitJobResponse) Reset() { *x = SubmitJobResponse{} if protoimpl.UnsafeEnabled { - mi := &file_rainbow_proto_msgTypes[5] + mi := &file_rainbow_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -644,7 +811,7 @@ func (x *SubmitJobResponse) String() string { func (*SubmitJobResponse) ProtoMessage() {} func (x *SubmitJobResponse) ProtoReflect() protoreflect.Message { - mi := &file_rainbow_proto_msgTypes[5] + mi := &file_rainbow_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -657,7 +824,7 @@ func (x *SubmitJobResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SubmitJobResponse.ProtoReflect.Descriptor instead. func (*SubmitJobResponse) Descriptor() ([]byte, []int) { - return file_rainbow_proto_rawDescGZIP(), []int{5} + return file_rainbow_proto_rawDescGZIP(), []int{7} } func (x *SubmitJobResponse) GetRequestId() string { @@ -703,7 +870,7 @@ type ReceiveJobsResponse struct { func (x *ReceiveJobsResponse) Reset() { *x = ReceiveJobsResponse{} if protoimpl.UnsafeEnabled { - mi := &file_rainbow_proto_msgTypes[6] + mi := &file_rainbow_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -716,7 +883,7 @@ func (x *ReceiveJobsResponse) String() string { func (*ReceiveJobsResponse) ProtoMessage() {} func (x *ReceiveJobsResponse) ProtoReflect() protoreflect.Message { - mi := &file_rainbow_proto_msgTypes[6] + mi := &file_rainbow_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -729,7 +896,7 @@ func (x *ReceiveJobsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ReceiveJobsResponse.ProtoReflect.Descriptor instead. func (*ReceiveJobsResponse) Descriptor() ([]byte, []int) { - return file_rainbow_proto_rawDescGZIP(), []int{6} + return file_rainbow_proto_rawDescGZIP(), []int{8} } func (x *ReceiveJobsResponse) GetRequestId() string { @@ -765,7 +932,7 @@ type AcceptJobsResponse struct { func (x *AcceptJobsResponse) Reset() { *x = AcceptJobsResponse{} if protoimpl.UnsafeEnabled { - mi := &file_rainbow_proto_msgTypes[7] + mi := &file_rainbow_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -778,7 +945,7 @@ func (x *AcceptJobsResponse) String() string { func (*AcceptJobsResponse) ProtoMessage() {} func (x *AcceptJobsResponse) ProtoReflect() protoreflect.Message { - mi := &file_rainbow_proto_msgTypes[7] + mi := &file_rainbow_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -791,7 +958,7 @@ func (x *AcceptJobsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use AcceptJobsResponse.ProtoReflect.Descriptor instead. func (*AcceptJobsResponse) Descriptor() ([]byte, []int) { - return file_rainbow_proto_rawDescGZIP(), []int{7} + return file_rainbow_proto_rawDescGZIP(), []int{9} } func (x *AcceptJobsResponse) GetStatus() AcceptJobsResponse_ResultType { @@ -813,7 +980,7 @@ type SubmitJobRequest_Cluster struct { func (x *SubmitJobRequest_Cluster) Reset() { *x = SubmitJobRequest_Cluster{} if protoimpl.UnsafeEnabled { - mi := &file_rainbow_proto_msgTypes[8] + mi := &file_rainbow_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -826,7 +993,7 @@ func (x *SubmitJobRequest_Cluster) String() string { func (*SubmitJobRequest_Cluster) ProtoMessage() {} func (x *SubmitJobRequest_Cluster) ProtoReflect() protoreflect.Message { - mi := &file_rainbow_proto_msgTypes[8] + mi := &file_rainbow_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -839,7 +1006,7 @@ func (x *SubmitJobRequest_Cluster) ProtoReflect() protoreflect.Message { // Deprecated: Use SubmitJobRequest_Cluster.ProtoReflect.Descriptor instead. func (*SubmitJobRequest_Cluster) Descriptor() ([]byte, []int) { - return file_rainbow_proto_rawDescGZIP(), []int{1, 0} + return file_rainbow_proto_rawDescGZIP(), []int{3, 0} } func (x *SubmitJobRequest_Cluster) GetName() string { @@ -874,158 +1041,186 @@ var file_rainbow_proto_rawDesc = []byte{ 0x73, 0x74, 0x65, 0x6d, 0x12, 0x2e, 0x0a, 0x04, 0x73, 0x65, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x04, - 0x73, 0x65, 0x6e, 0x74, 0x22, 0xfb, 0x01, 0x0a, 0x10, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x4a, - 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x54, 0x0a, - 0x08, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x38, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x67, 0x65, 0x64, 0x63, 0x6f, 0x6d, 0x70, 0x75, - 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x76, 0x31, - 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x08, 0x63, 0x6c, 0x75, 0x73, 0x74, - 0x65, 0x72, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6a, 0x6f, 0x62, 0x73, 0x70, 0x65, 0x63, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6a, 0x6f, 0x62, 0x73, 0x70, 0x65, 0x63, 0x12, 0x2e, 0x0a, - 0x04, 0x73, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, - 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x04, 0x73, 0x65, 0x6e, 0x74, 0x1a, 0x33, 0x0a, - 0x07, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, - 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x6b, - 0x65, 0x6e, 0x22, 0x90, 0x01, 0x0a, 0x12, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x4a, 0x6f, - 0x62, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6c, 0x75, - 0x73, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6c, 0x75, 0x73, - 0x74, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x6d, - 0x61, 0x78, 0x4a, 0x6f, 0x62, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x6d, 0x61, - 0x78, 0x4a, 0x6f, 0x62, 0x73, 0x12, 0x2e, 0x0a, 0x04, 0x73, 0x65, 0x6e, 0x74, 0x18, 0x07, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, - 0x04, 0x73, 0x65, 0x6e, 0x74, 0x22, 0x8d, 0x01, 0x0a, 0x11, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, - 0x4a, 0x6f, 0x62, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x63, - 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6c, - 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x16, 0x0a, - 0x06, 0x6a, 0x6f, 0x62, 0x69, 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x05, 0x52, 0x06, 0x6a, - 0x6f, 0x62, 0x69, 0x64, 0x73, 0x12, 0x2e, 0x0a, 0x04, 0x73, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, - 0x04, 0x73, 0x65, 0x6e, 0x74, 0x22, 0xb0, 0x02, 0x0a, 0x10, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, - 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, - 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x6b, - 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x12, - 0x16, 0x0a, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x53, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3b, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, - 0x67, 0x65, 0x64, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, - 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, - 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, - 0x54, 0x79, 0x70, 0x65, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x7a, 0x0a, 0x0a, - 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x14, 0x52, 0x45, - 0x47, 0x49, 0x53, 0x54, 0x45, 0x52, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, - 0x45, 0x44, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x45, 0x52, - 0x5f, 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, 0x53, 0x10, 0x01, 0x12, 0x12, 0x0a, 0x0e, 0x52, 0x45, - 0x47, 0x49, 0x53, 0x54, 0x45, 0x52, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x12, 0x13, - 0x0a, 0x0f, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x45, 0x52, 0x5f, 0x44, 0x45, 0x4e, 0x49, 0x45, - 0x44, 0x10, 0x03, 0x12, 0x13, 0x0a, 0x0f, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x45, 0x52, 0x5f, - 0x45, 0x58, 0x49, 0x53, 0x54, 0x53, 0x10, 0x04, 0x22, 0x97, 0x02, 0x0a, 0x11, 0x53, 0x75, 0x62, - 0x6d, 0x69, 0x74, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, - 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x14, 0x0a, - 0x05, 0x6a, 0x6f, 0x62, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6a, 0x6f, - 0x62, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x54, 0x0a, - 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3c, 0x2e, - 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x67, 0x65, 0x64, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x69, - 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x53, - 0x75, 0x62, 0x6d, 0x69, 0x74, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x06, 0x73, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x22, 0x5d, 0x0a, 0x0a, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x54, 0x79, 0x70, - 0x65, 0x12, 0x16, 0x0a, 0x12, 0x53, 0x55, 0x42, 0x4d, 0x49, 0x54, 0x5f, 0x55, 0x4e, 0x53, 0x50, - 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x53, 0x55, 0x42, - 0x4d, 0x49, 0x54, 0x5f, 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, 0x53, 0x10, 0x01, 0x12, 0x10, 0x0a, - 0x0c, 0x53, 0x55, 0x42, 0x4d, 0x49, 0x54, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x12, - 0x11, 0x0a, 0x0d, 0x53, 0x55, 0x42, 0x4d, 0x49, 0x54, 0x5f, 0x44, 0x45, 0x4e, 0x49, 0x45, 0x44, - 0x10, 0x03, 0x22, 0x8d, 0x03, 0x0a, 0x13, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x4a, 0x6f, - 0x62, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, - 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x51, 0x0a, 0x04, 0x6a, 0x6f, 0x62, - 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3d, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, - 0x67, 0x65, 0x64, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, - 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, - 0x4a, 0x6f, 0x62, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4a, 0x6f, 0x62, - 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x6a, 0x6f, 0x62, 0x73, 0x12, 0x56, 0x0a, 0x06, - 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3e, 0x2e, 0x63, - 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x67, 0x65, 0x64, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x69, 0x6e, - 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, - 0x63, 0x65, 0x69, 0x76, 0x65, 0x4a, 0x6f, 0x62, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x06, 0x73, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x1a, 0x37, 0x0a, 0x09, 0x4a, 0x6f, 0x62, 0x73, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, - 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x73, 0x0a, - 0x0a, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x16, 0x52, - 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x5f, 0x4a, 0x4f, 0x42, 0x53, 0x5f, 0x4e, 0x4f, 0x52, 0x45, - 0x53, 0x55, 0x4c, 0x54, 0x53, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x52, 0x45, 0x51, 0x55, 0x45, - 0x53, 0x54, 0x5f, 0x4a, 0x4f, 0x42, 0x53, 0x5f, 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, 0x53, 0x10, - 0x01, 0x12, 0x16, 0x0a, 0x12, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x5f, 0x4a, 0x4f, 0x42, - 0x53, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x12, 0x17, 0x0a, 0x13, 0x52, 0x45, 0x51, - 0x55, 0x45, 0x53, 0x54, 0x5f, 0x4a, 0x4f, 0x42, 0x53, 0x5f, 0x44, 0x45, 0x4e, 0x49, 0x45, 0x44, - 0x10, 0x03, 0x22, 0xdf, 0x01, 0x0a, 0x12, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x4a, 0x6f, 0x62, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x55, 0x0a, 0x06, 0x73, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3d, 0x2e, 0x63, 0x6f, 0x6e, 0x76, - 0x65, 0x72, 0x67, 0x65, 0x64, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x6f, - 0x72, 0x67, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x70, - 0x74, 0x4a, 0x6f, 0x62, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, - 0x73, 0x75, 0x6c, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x22, 0x72, 0x0a, 0x0a, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1b, - 0x0a, 0x17, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, - 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x52, - 0x45, 0x53, 0x55, 0x4c, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, 0x41, 0x52, 0x54, 0x49, - 0x41, 0x4c, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x5f, 0x54, - 0x59, 0x50, 0x45, 0x5f, 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, 0x53, 0x10, 0x02, 0x12, 0x15, 0x0a, - 0x11, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, 0x52, 0x52, - 0x4f, 0x52, 0x10, 0x03, 0x32, 0xd8, 0x04, 0x0a, 0x10, 0x52, 0x61, 0x69, 0x6e, 0x62, 0x6f, 0x77, - 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x12, 0x6d, 0x0a, 0x08, 0x52, 0x65, 0x67, - 0x69, 0x73, 0x74, 0x65, 0x72, 0x12, 0x2f, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x67, 0x65, - 0x64, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2e, 0x67, - 0x72, 0x70, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x67, - 0x65, 0x64, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2e, - 0x67, 0x72, 0x70, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x76, 0x0a, 0x11, 0x52, 0x65, 0x67, 0x69, - 0x73, 0x74, 0x65, 0x72, 0x53, 0x75, 0x62, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x2f, 0x2e, - 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x67, 0x65, 0x64, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x69, - 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x52, - 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, + 0x73, 0x65, 0x6e, 0x74, 0x22, 0x60, 0x0a, 0x12, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, + 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6c, + 0x75, 0x73, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6c, 0x75, + 0x73, 0x74, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x18, 0x0a, 0x07, + 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, + 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0xe5, 0x01, 0x0a, 0x13, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, + 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3e, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x67, 0x65, 0x64, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x76, 0x31, 0x2e, - 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x70, 0x0a, 0x09, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x4a, 0x6f, 0x62, 0x12, 0x30, 0x2e, - 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x67, 0x65, 0x64, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x69, - 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x53, - 0x75, 0x62, 0x6d, 0x69, 0x74, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x67, 0x65, 0x64, 0x63, 0x6f, 0x6d, 0x70, 0x75, - 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x76, 0x31, - 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x76, 0x0a, 0x0b, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x4a, 0x6f, 0x62, - 0x73, 0x12, 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x67, 0x65, 0x64, 0x63, 0x6f, 0x6d, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x06, + 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x76, 0x0a, 0x0a, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, + 0x54, 0x79, 0x70, 0x65, 0x12, 0x1c, 0x0a, 0x18, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x53, + 0x54, 0x41, 0x54, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, + 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x53, 0x54, 0x41, + 0x54, 0x45, 0x5f, 0x50, 0x41, 0x52, 0x54, 0x49, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, + 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x53, 0x55, 0x43, + 0x43, 0x45, 0x53, 0x53, 0x10, 0x02, 0x12, 0x16, 0x0a, 0x12, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, + 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x03, 0x22, 0xfb, + 0x01, 0x0a, 0x10, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x54, 0x0a, 0x08, 0x63, 0x6c, 0x75, 0x73, 0x74, + 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x63, 0x6f, 0x6e, 0x76, + 0x65, 0x72, 0x67, 0x65, 0x64, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x6f, + 0x72, 0x67, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, + 0x74, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x43, 0x6c, 0x75, 0x73, + 0x74, 0x65, 0x72, 0x52, 0x08, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x12, 0x18, 0x0a, + 0x07, 0x6a, 0x6f, 0x62, 0x73, 0x70, 0x65, 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, + 0x6a, 0x6f, 0x62, 0x73, 0x70, 0x65, 0x63, 0x12, 0x2e, 0x0a, 0x04, 0x73, 0x65, 0x6e, 0x74, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, + 0x70, 0x52, 0x04, 0x73, 0x65, 0x6e, 0x74, 0x1a, 0x33, 0x0a, 0x07, 0x43, 0x6c, 0x75, 0x73, 0x74, + 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x90, 0x01, 0x0a, + 0x12, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x4a, 0x6f, 0x62, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x16, 0x0a, + 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, + 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x61, 0x78, 0x4a, 0x6f, 0x62, 0x73, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x6d, 0x61, 0x78, 0x4a, 0x6f, 0x62, 0x73, 0x12, + 0x2e, 0x0a, 0x04, 0x73, 0x65, 0x6e, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x04, 0x73, 0x65, 0x6e, 0x74, 0x22, + 0x8d, 0x01, 0x0a, 0x11, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x4a, 0x6f, 0x62, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, + 0x16, 0x0a, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6a, 0x6f, 0x62, 0x69, 0x64, + 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x05, 0x52, 0x06, 0x6a, 0x6f, 0x62, 0x69, 0x64, 0x73, 0x12, + 0x2e, 0x0a, 0x04, 0x73, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x04, 0x73, 0x65, 0x6e, 0x74, 0x22, + 0xb0, 0x02, 0x0a, 0x10, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x65, 0x63, + 0x72, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, + 0x74, 0x12, 0x53, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x0e, 0x32, 0x3b, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x67, 0x65, 0x64, 0x63, 0x6f, 0x6d, + 0x70, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, + 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x06, + 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x7a, 0x0a, 0x0a, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, + 0x54, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x14, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x45, 0x52, + 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x14, + 0x0a, 0x10, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x45, 0x52, 0x5f, 0x53, 0x55, 0x43, 0x43, 0x45, + 0x53, 0x53, 0x10, 0x01, 0x12, 0x12, 0x0a, 0x0e, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x45, 0x52, + 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x12, 0x13, 0x0a, 0x0f, 0x52, 0x45, 0x47, 0x49, + 0x53, 0x54, 0x45, 0x52, 0x5f, 0x44, 0x45, 0x4e, 0x49, 0x45, 0x44, 0x10, 0x03, 0x12, 0x13, 0x0a, + 0x0f, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x45, 0x52, 0x5f, 0x45, 0x58, 0x49, 0x53, 0x54, 0x53, + 0x10, 0x04, 0x22, 0x97, 0x02, 0x0a, 0x11, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x4a, 0x6f, 0x62, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6a, 0x6f, 0x62, 0x69, 0x64, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6a, 0x6f, 0x62, 0x69, 0x64, 0x12, 0x18, 0x0a, + 0x07, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, + 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x54, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3c, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, + 0x67, 0x65, 0x64, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, + 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x4a, + 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, + 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x5d, 0x0a, + 0x0a, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x12, 0x53, + 0x55, 0x42, 0x4d, 0x49, 0x54, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, + 0x44, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x53, 0x55, 0x42, 0x4d, 0x49, 0x54, 0x5f, 0x53, 0x55, + 0x43, 0x43, 0x45, 0x53, 0x53, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x53, 0x55, 0x42, 0x4d, 0x49, + 0x54, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x12, 0x11, 0x0a, 0x0d, 0x53, 0x55, 0x42, + 0x4d, 0x49, 0x54, 0x5f, 0x44, 0x45, 0x4e, 0x49, 0x45, 0x44, 0x10, 0x03, 0x22, 0x8d, 0x03, 0x0a, + 0x13, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x4a, 0x6f, 0x62, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x49, 0x64, 0x12, 0x51, 0x0a, 0x04, 0x6a, 0x6f, 0x62, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x3d, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x67, 0x65, 0x64, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x4a, 0x6f, 0x62, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x67, 0x65, - 0x64, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2e, 0x67, - 0x72, 0x70, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x4a, 0x6f, - 0x62, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x73, 0x0a, 0x0a, 0x41, 0x63, - 0x63, 0x65, 0x70, 0x74, 0x4a, 0x6f, 0x62, 0x73, 0x12, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4a, 0x6f, 0x62, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x52, 0x04, 0x6a, 0x6f, 0x62, 0x73, 0x12, 0x56, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3e, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x67, + 0x65, 0x64, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2e, + 0x67, 0x72, 0x70, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x4a, + 0x6f, 0x62, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x75, + 0x6c, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x1a, 0x37, + 0x0a, 0x09, 0x4a, 0x6f, 0x62, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, + 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x73, 0x0a, 0x0a, 0x52, 0x65, 0x73, 0x75, 0x6c, + 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x16, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, + 0x5f, 0x4a, 0x4f, 0x42, 0x53, 0x5f, 0x4e, 0x4f, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x53, 0x10, + 0x00, 0x12, 0x18, 0x0a, 0x14, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x5f, 0x4a, 0x4f, 0x42, + 0x53, 0x5f, 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, 0x53, 0x10, 0x01, 0x12, 0x16, 0x0a, 0x12, 0x52, + 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x5f, 0x4a, 0x4f, 0x42, 0x53, 0x5f, 0x45, 0x52, 0x52, 0x4f, + 0x52, 0x10, 0x02, 0x12, 0x17, 0x0a, 0x13, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x5f, 0x4a, + 0x4f, 0x42, 0x53, 0x5f, 0x44, 0x45, 0x4e, 0x49, 0x45, 0x44, 0x10, 0x03, 0x22, 0xdf, 0x01, 0x0a, + 0x12, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x4a, 0x6f, 0x62, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x55, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0e, 0x32, 0x3d, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x67, 0x65, 0x64, 0x63, + 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2e, 0x67, 0x72, 0x70, + 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x4a, 0x6f, 0x62, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x54, 0x79, + 0x70, 0x65, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x72, 0x0a, 0x0a, 0x52, 0x65, + 0x73, 0x75, 0x6c, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x17, 0x52, 0x45, 0x53, 0x55, + 0x4c, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, + 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x5f, + 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, 0x41, 0x52, 0x54, 0x49, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x17, + 0x0a, 0x13, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x55, + 0x43, 0x43, 0x45, 0x53, 0x53, 0x10, 0x02, 0x12, 0x15, 0x0a, 0x11, 0x52, 0x45, 0x53, 0x55, 0x4c, + 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x03, 0x32, 0xd0, + 0x05, 0x0a, 0x10, 0x52, 0x61, 0x69, 0x6e, 0x62, 0x6f, 0x77, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, + 0x6c, 0x65, 0x72, 0x12, 0x6d, 0x0a, 0x08, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x12, + 0x2f, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x67, 0x65, 0x64, 0x63, 0x6f, 0x6d, 0x70, 0x75, + 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x76, 0x31, + 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x30, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x67, 0x65, 0x64, 0x63, 0x6f, 0x6d, 0x70, + 0x75, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x76, + 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x76, 0x0a, 0x11, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x53, 0x75, + 0x62, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x2f, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, + 0x67, 0x65, 0x64, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, + 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, + 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x67, 0x65, 0x64, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x6f, 0x72, - 0x67, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, - 0x4a, 0x6f, 0x62, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x63, 0x6f, + 0x67, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, + 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x70, 0x0a, 0x09, 0x53, 0x75, + 0x62, 0x6d, 0x69, 0x74, 0x4a, 0x6f, 0x62, 0x12, 0x30, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, + 0x67, 0x65, 0x64, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, + 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x4a, + 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x76, + 0x65, 0x72, 0x67, 0x65, 0x64, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x6f, + 0x72, 0x67, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, + 0x74, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x76, 0x0a, 0x0b, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x67, 0x65, 0x64, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x69, 0x6e, 0x67, - 0x2e, 0x6f, 0x72, 0x67, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x63, 0x63, - 0x65, 0x70, 0x74, 0x4a, 0x6f, 0x62, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, - 0x33, 0x5a, 0x31, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, - 0x6e, 0x76, 0x65, 0x72, 0x67, 0x65, 0x64, 0x2d, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x69, 0x6e, - 0x67, 0x2f, 0x72, 0x61, 0x69, 0x6e, 0x62, 0x6f, 0x77, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x61, 0x70, - 0x69, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x2e, 0x6f, 0x72, 0x67, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x33, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x67, 0x65, 0x64, 0x63, 0x6f, 0x6d, 0x70, 0x75, + 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x76, 0x31, + 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x76, 0x0a, 0x0b, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x4a, + 0x6f, 0x62, 0x73, 0x12, 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x67, 0x65, 0x64, 0x63, + 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2e, 0x67, 0x72, 0x70, + 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x4a, 0x6f, 0x62, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, + 0x67, 0x65, 0x64, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, + 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, + 0x4a, 0x6f, 0x62, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x73, 0x0a, 0x0a, + 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x4a, 0x6f, 0x62, 0x73, 0x12, 0x31, 0x2e, 0x63, 0x6f, 0x6e, + 0x76, 0x65, 0x72, 0x67, 0x65, 0x64, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x2e, + 0x6f, 0x72, 0x67, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x63, 0x63, 0x65, + 0x70, 0x74, 0x4a, 0x6f, 0x62, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, + 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x67, 0x65, 0x64, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x69, + 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x41, + 0x63, 0x63, 0x65, 0x70, 0x74, 0x4a, 0x6f, 0x62, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x42, 0x33, 0x5a, 0x31, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, + 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x67, 0x65, 0x64, 0x2d, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, + 0x69, 0x6e, 0x67, 0x2f, 0x72, 0x61, 0x69, 0x6e, 0x62, 0x6f, 0x77, 0x2f, 0x70, 0x6b, 0x67, 0x2f, + 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1040,51 +1235,57 @@ func file_rainbow_proto_rawDescGZIP() []byte { return file_rainbow_proto_rawDescData } -var file_rainbow_proto_enumTypes = make([]protoimpl.EnumInfo, 4) -var file_rainbow_proto_msgTypes = make([]protoimpl.MessageInfo, 10) +var file_rainbow_proto_enumTypes = make([]protoimpl.EnumInfo, 5) +var file_rainbow_proto_msgTypes = make([]protoimpl.MessageInfo, 12) var file_rainbow_proto_goTypes = []interface{}{ - (RegisterResponse_ResultType)(0), // 0: convergedcomputing.org.grpc.v1.RegisterResponse.ResultType - (SubmitJobResponse_ResultType)(0), // 1: convergedcomputing.org.grpc.v1.SubmitJobResponse.ResultType - (ReceiveJobsResponse_ResultType)(0), // 2: convergedcomputing.org.grpc.v1.ReceiveJobsResponse.ResultType - (AcceptJobsResponse_ResultType)(0), // 3: convergedcomputing.org.grpc.v1.AcceptJobsResponse.ResultType - (*RegisterRequest)(nil), // 4: convergedcomputing.org.grpc.v1.RegisterRequest - (*SubmitJobRequest)(nil), // 5: convergedcomputing.org.grpc.v1.SubmitJobRequest - (*ReceiveJobsRequest)(nil), // 6: convergedcomputing.org.grpc.v1.ReceiveJobsRequest - (*AcceptJobsRequest)(nil), // 7: convergedcomputing.org.grpc.v1.AcceptJobsRequest - (*RegisterResponse)(nil), // 8: convergedcomputing.org.grpc.v1.RegisterResponse - (*SubmitJobResponse)(nil), // 9: convergedcomputing.org.grpc.v1.SubmitJobResponse - (*ReceiveJobsResponse)(nil), // 10: convergedcomputing.org.grpc.v1.ReceiveJobsResponse - (*AcceptJobsResponse)(nil), // 11: convergedcomputing.org.grpc.v1.AcceptJobsResponse - (*SubmitJobRequest_Cluster)(nil), // 12: convergedcomputing.org.grpc.v1.SubmitJobRequest.Cluster - nil, // 13: convergedcomputing.org.grpc.v1.ReceiveJobsResponse.JobsEntry - (*timestamppb.Timestamp)(nil), // 14: google.protobuf.Timestamp + (UpdateStateResponse_ResultType)(0), // 0: convergedcomputing.org.grpc.v1.UpdateStateResponse.ResultType + (RegisterResponse_ResultType)(0), // 1: convergedcomputing.org.grpc.v1.RegisterResponse.ResultType + (SubmitJobResponse_ResultType)(0), // 2: convergedcomputing.org.grpc.v1.SubmitJobResponse.ResultType + (ReceiveJobsResponse_ResultType)(0), // 3: convergedcomputing.org.grpc.v1.ReceiveJobsResponse.ResultType + (AcceptJobsResponse_ResultType)(0), // 4: convergedcomputing.org.grpc.v1.AcceptJobsResponse.ResultType + (*RegisterRequest)(nil), // 5: convergedcomputing.org.grpc.v1.RegisterRequest + (*UpdateStateRequest)(nil), // 6: convergedcomputing.org.grpc.v1.UpdateStateRequest + (*UpdateStateResponse)(nil), // 7: convergedcomputing.org.grpc.v1.UpdateStateResponse + (*SubmitJobRequest)(nil), // 8: convergedcomputing.org.grpc.v1.SubmitJobRequest + (*ReceiveJobsRequest)(nil), // 9: convergedcomputing.org.grpc.v1.ReceiveJobsRequest + (*AcceptJobsRequest)(nil), // 10: convergedcomputing.org.grpc.v1.AcceptJobsRequest + (*RegisterResponse)(nil), // 11: convergedcomputing.org.grpc.v1.RegisterResponse + (*SubmitJobResponse)(nil), // 12: convergedcomputing.org.grpc.v1.SubmitJobResponse + (*ReceiveJobsResponse)(nil), // 13: convergedcomputing.org.grpc.v1.ReceiveJobsResponse + (*AcceptJobsResponse)(nil), // 14: convergedcomputing.org.grpc.v1.AcceptJobsResponse + (*SubmitJobRequest_Cluster)(nil), // 15: convergedcomputing.org.grpc.v1.SubmitJobRequest.Cluster + nil, // 16: convergedcomputing.org.grpc.v1.ReceiveJobsResponse.JobsEntry + (*timestamppb.Timestamp)(nil), // 17: google.protobuf.Timestamp } var file_rainbow_proto_depIdxs = []int32{ - 14, // 0: convergedcomputing.org.grpc.v1.RegisterRequest.sent:type_name -> google.protobuf.Timestamp - 12, // 1: convergedcomputing.org.grpc.v1.SubmitJobRequest.clusters:type_name -> convergedcomputing.org.grpc.v1.SubmitJobRequest.Cluster - 14, // 2: convergedcomputing.org.grpc.v1.SubmitJobRequest.sent:type_name -> google.protobuf.Timestamp - 14, // 3: convergedcomputing.org.grpc.v1.ReceiveJobsRequest.sent:type_name -> google.protobuf.Timestamp - 14, // 4: convergedcomputing.org.grpc.v1.AcceptJobsRequest.sent:type_name -> google.protobuf.Timestamp - 0, // 5: convergedcomputing.org.grpc.v1.RegisterResponse.status:type_name -> convergedcomputing.org.grpc.v1.RegisterResponse.ResultType - 1, // 6: convergedcomputing.org.grpc.v1.SubmitJobResponse.status:type_name -> convergedcomputing.org.grpc.v1.SubmitJobResponse.ResultType - 13, // 7: convergedcomputing.org.grpc.v1.ReceiveJobsResponse.jobs:type_name -> convergedcomputing.org.grpc.v1.ReceiveJobsResponse.JobsEntry - 2, // 8: convergedcomputing.org.grpc.v1.ReceiveJobsResponse.status:type_name -> convergedcomputing.org.grpc.v1.ReceiveJobsResponse.ResultType - 3, // 9: convergedcomputing.org.grpc.v1.AcceptJobsResponse.status:type_name -> convergedcomputing.org.grpc.v1.AcceptJobsResponse.ResultType - 4, // 10: convergedcomputing.org.grpc.v1.RainbowScheduler.Register:input_type -> convergedcomputing.org.grpc.v1.RegisterRequest - 4, // 11: convergedcomputing.org.grpc.v1.RainbowScheduler.RegisterSubsystem:input_type -> convergedcomputing.org.grpc.v1.RegisterRequest - 5, // 12: convergedcomputing.org.grpc.v1.RainbowScheduler.SubmitJob:input_type -> convergedcomputing.org.grpc.v1.SubmitJobRequest - 6, // 13: convergedcomputing.org.grpc.v1.RainbowScheduler.ReceiveJobs:input_type -> convergedcomputing.org.grpc.v1.ReceiveJobsRequest - 7, // 14: convergedcomputing.org.grpc.v1.RainbowScheduler.AcceptJobs:input_type -> convergedcomputing.org.grpc.v1.AcceptJobsRequest - 8, // 15: convergedcomputing.org.grpc.v1.RainbowScheduler.Register:output_type -> convergedcomputing.org.grpc.v1.RegisterResponse - 8, // 16: convergedcomputing.org.grpc.v1.RainbowScheduler.RegisterSubsystem:output_type -> convergedcomputing.org.grpc.v1.RegisterResponse - 9, // 17: convergedcomputing.org.grpc.v1.RainbowScheduler.SubmitJob:output_type -> convergedcomputing.org.grpc.v1.SubmitJobResponse - 10, // 18: convergedcomputing.org.grpc.v1.RainbowScheduler.ReceiveJobs:output_type -> convergedcomputing.org.grpc.v1.ReceiveJobsResponse - 11, // 19: convergedcomputing.org.grpc.v1.RainbowScheduler.AcceptJobs:output_type -> convergedcomputing.org.grpc.v1.AcceptJobsResponse - 15, // [15:20] is the sub-list for method output_type - 10, // [10:15] is the sub-list for method input_type - 10, // [10:10] is the sub-list for extension type_name - 10, // [10:10] is the sub-list for extension extendee - 0, // [0:10] is the sub-list for field type_name + 17, // 0: convergedcomputing.org.grpc.v1.RegisterRequest.sent:type_name -> google.protobuf.Timestamp + 0, // 1: convergedcomputing.org.grpc.v1.UpdateStateResponse.status:type_name -> convergedcomputing.org.grpc.v1.UpdateStateResponse.ResultType + 15, // 2: convergedcomputing.org.grpc.v1.SubmitJobRequest.clusters:type_name -> convergedcomputing.org.grpc.v1.SubmitJobRequest.Cluster + 17, // 3: convergedcomputing.org.grpc.v1.SubmitJobRequest.sent:type_name -> google.protobuf.Timestamp + 17, // 4: convergedcomputing.org.grpc.v1.ReceiveJobsRequest.sent:type_name -> google.protobuf.Timestamp + 17, // 5: convergedcomputing.org.grpc.v1.AcceptJobsRequest.sent:type_name -> google.protobuf.Timestamp + 1, // 6: convergedcomputing.org.grpc.v1.RegisterResponse.status:type_name -> convergedcomputing.org.grpc.v1.RegisterResponse.ResultType + 2, // 7: convergedcomputing.org.grpc.v1.SubmitJobResponse.status:type_name -> convergedcomputing.org.grpc.v1.SubmitJobResponse.ResultType + 16, // 8: convergedcomputing.org.grpc.v1.ReceiveJobsResponse.jobs:type_name -> convergedcomputing.org.grpc.v1.ReceiveJobsResponse.JobsEntry + 3, // 9: convergedcomputing.org.grpc.v1.ReceiveJobsResponse.status:type_name -> convergedcomputing.org.grpc.v1.ReceiveJobsResponse.ResultType + 4, // 10: convergedcomputing.org.grpc.v1.AcceptJobsResponse.status:type_name -> convergedcomputing.org.grpc.v1.AcceptJobsResponse.ResultType + 5, // 11: convergedcomputing.org.grpc.v1.RainbowScheduler.Register:input_type -> convergedcomputing.org.grpc.v1.RegisterRequest + 5, // 12: convergedcomputing.org.grpc.v1.RainbowScheduler.RegisterSubsystem:input_type -> convergedcomputing.org.grpc.v1.RegisterRequest + 8, // 13: convergedcomputing.org.grpc.v1.RainbowScheduler.SubmitJob:input_type -> convergedcomputing.org.grpc.v1.SubmitJobRequest + 6, // 14: convergedcomputing.org.grpc.v1.RainbowScheduler.UpdateState:input_type -> convergedcomputing.org.grpc.v1.UpdateStateRequest + 9, // 15: convergedcomputing.org.grpc.v1.RainbowScheduler.ReceiveJobs:input_type -> convergedcomputing.org.grpc.v1.ReceiveJobsRequest + 10, // 16: convergedcomputing.org.grpc.v1.RainbowScheduler.AcceptJobs:input_type -> convergedcomputing.org.grpc.v1.AcceptJobsRequest + 11, // 17: convergedcomputing.org.grpc.v1.RainbowScheduler.Register:output_type -> convergedcomputing.org.grpc.v1.RegisterResponse + 11, // 18: convergedcomputing.org.grpc.v1.RainbowScheduler.RegisterSubsystem:output_type -> convergedcomputing.org.grpc.v1.RegisterResponse + 12, // 19: convergedcomputing.org.grpc.v1.RainbowScheduler.SubmitJob:output_type -> convergedcomputing.org.grpc.v1.SubmitJobResponse + 7, // 20: convergedcomputing.org.grpc.v1.RainbowScheduler.UpdateState:output_type -> convergedcomputing.org.grpc.v1.UpdateStateResponse + 13, // 21: convergedcomputing.org.grpc.v1.RainbowScheduler.ReceiveJobs:output_type -> convergedcomputing.org.grpc.v1.ReceiveJobsResponse + 14, // 22: convergedcomputing.org.grpc.v1.RainbowScheduler.AcceptJobs:output_type -> convergedcomputing.org.grpc.v1.AcceptJobsResponse + 17, // [17:23] is the sub-list for method output_type + 11, // [11:17] is the sub-list for method input_type + 11, // [11:11] is the sub-list for extension type_name + 11, // [11:11] is the sub-list for extension extendee + 0, // [0:11] is the sub-list for field type_name } func init() { file_rainbow_proto_init() } @@ -1106,7 +1307,7 @@ func file_rainbow_proto_init() { } } file_rainbow_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SubmitJobRequest); i { + switch v := v.(*UpdateStateRequest); i { case 0: return &v.state case 1: @@ -1118,7 +1319,7 @@ func file_rainbow_proto_init() { } } file_rainbow_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ReceiveJobsRequest); i { + switch v := v.(*UpdateStateResponse); i { case 0: return &v.state case 1: @@ -1130,7 +1331,7 @@ func file_rainbow_proto_init() { } } file_rainbow_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AcceptJobsRequest); i { + switch v := v.(*SubmitJobRequest); i { case 0: return &v.state case 1: @@ -1142,7 +1343,7 @@ func file_rainbow_proto_init() { } } file_rainbow_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RegisterResponse); i { + switch v := v.(*ReceiveJobsRequest); i { case 0: return &v.state case 1: @@ -1154,7 +1355,7 @@ func file_rainbow_proto_init() { } } file_rainbow_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SubmitJobResponse); i { + switch v := v.(*AcceptJobsRequest); i { case 0: return &v.state case 1: @@ -1166,7 +1367,7 @@ func file_rainbow_proto_init() { } } file_rainbow_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ReceiveJobsResponse); i { + switch v := v.(*RegisterResponse); i { case 0: return &v.state case 1: @@ -1178,7 +1379,7 @@ func file_rainbow_proto_init() { } } file_rainbow_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AcceptJobsResponse); i { + switch v := v.(*SubmitJobResponse); i { case 0: return &v.state case 1: @@ -1190,6 +1391,30 @@ func file_rainbow_proto_init() { } } file_rainbow_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ReceiveJobsResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_rainbow_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AcceptJobsResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_rainbow_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SubmitJobRequest_Cluster); i { case 0: return &v.state @@ -1207,8 +1432,8 @@ func file_rainbow_proto_init() { File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_rainbow_proto_rawDesc, - NumEnums: 4, - NumMessages: 10, + NumEnums: 5, + NumMessages: 12, NumExtensions: 0, NumServices: 1, }, diff --git a/pkg/api/v1/rainbow_grpc.pb.go b/pkg/api/v1/rainbow_grpc.pb.go index b671cc6..427208a 100644 --- a/pkg/api/v1/rainbow_grpc.pb.go +++ b/pkg/api/v1/rainbow_grpc.pb.go @@ -28,6 +28,9 @@ type RainbowSchedulerClient interface { RegisterSubsystem(ctx context.Context, in *RegisterRequest, opts ...grpc.CallOption) (*RegisterResponse, error) // Job Submission - request for submitting a job to a named cluster SubmitJob(ctx context.Context, in *SubmitJobRequest, opts ...grpc.CallOption) (*SubmitJobResponse, error) + // Update State - allow a cluster to provide state metadata + // This is intended for use by a selection algorithm + UpdateState(ctx context.Context, in *UpdateStateRequest, opts ...grpc.CallOption) (*UpdateStateResponse, error) // Request Job - ask the rainbow scheduler for up to max jobs ReceiveJobs(ctx context.Context, in *ReceiveJobsRequest, opts ...grpc.CallOption) (*ReceiveJobsResponse, error) // Accept Jobs - accept some number of jobs @@ -69,6 +72,15 @@ func (c *rainbowSchedulerClient) SubmitJob(ctx context.Context, in *SubmitJobReq return out, nil } +func (c *rainbowSchedulerClient) UpdateState(ctx context.Context, in *UpdateStateRequest, opts ...grpc.CallOption) (*UpdateStateResponse, error) { + out := new(UpdateStateResponse) + err := c.cc.Invoke(ctx, "/convergedcomputing.org.grpc.v1.RainbowScheduler/UpdateState", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *rainbowSchedulerClient) ReceiveJobs(ctx context.Context, in *ReceiveJobsRequest, opts ...grpc.CallOption) (*ReceiveJobsResponse, error) { out := new(ReceiveJobsResponse) err := c.cc.Invoke(ctx, "/convergedcomputing.org.grpc.v1.RainbowScheduler/ReceiveJobs", in, out, opts...) @@ -97,6 +109,9 @@ type RainbowSchedulerServer interface { RegisterSubsystem(context.Context, *RegisterRequest) (*RegisterResponse, error) // Job Submission - request for submitting a job to a named cluster SubmitJob(context.Context, *SubmitJobRequest) (*SubmitJobResponse, error) + // Update State - allow a cluster to provide state metadata + // This is intended for use by a selection algorithm + UpdateState(context.Context, *UpdateStateRequest) (*UpdateStateResponse, error) // Request Job - ask the rainbow scheduler for up to max jobs ReceiveJobs(context.Context, *ReceiveJobsRequest) (*ReceiveJobsResponse, error) // Accept Jobs - accept some number of jobs @@ -117,6 +132,9 @@ func (UnimplementedRainbowSchedulerServer) RegisterSubsystem(context.Context, *R func (UnimplementedRainbowSchedulerServer) SubmitJob(context.Context, *SubmitJobRequest) (*SubmitJobResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method SubmitJob not implemented") } +func (UnimplementedRainbowSchedulerServer) UpdateState(context.Context, *UpdateStateRequest) (*UpdateStateResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method UpdateState not implemented") +} func (UnimplementedRainbowSchedulerServer) ReceiveJobs(context.Context, *ReceiveJobsRequest) (*ReceiveJobsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ReceiveJobs not implemented") } @@ -190,6 +208,24 @@ func _RainbowScheduler_SubmitJob_Handler(srv interface{}, ctx context.Context, d return interceptor(ctx, in, info, handler) } +func _RainbowScheduler_UpdateState_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UpdateStateRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(RainbowSchedulerServer).UpdateState(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/convergedcomputing.org.grpc.v1.RainbowScheduler/UpdateState", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RainbowSchedulerServer).UpdateState(ctx, req.(*UpdateStateRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _RainbowScheduler_ReceiveJobs_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(ReceiveJobsRequest) if err := dec(in); err != nil { @@ -245,6 +281,10 @@ var RainbowScheduler_ServiceDesc = grpc.ServiceDesc{ MethodName: "SubmitJob", Handler: _RainbowScheduler_SubmitJob_Handler, }, + { + MethodName: "UpdateState", + Handler: _RainbowScheduler_UpdateState_Handler, + }, { MethodName: "ReceiveJobs", Handler: _RainbowScheduler_ReceiveJobs_Handler, diff --git a/pkg/client/client.go b/pkg/client/client.go index 98ea78b..71b4cc2 100644 --- a/pkg/client/client.go +++ b/pkg/client/client.go @@ -30,6 +30,9 @@ type Client interface { Register(ctx context.Context, clusterName, secret, clusterNodes, subsystem string) (*pb.RegisterResponse, error) RegisterSubsystem(ctx context.Context, clusterName, secret, subsystemNodes, subsystem string) (*pb.RegisterResponse, error) + // Update + UpdateState(ctx context.Context, clusterName, secret, stateFile string) (*pb.UpdateStateResponse, error) + // Job Client Interactions AcceptJobs(ctx context.Context, cluster, secret string, jobids []int32) (*pb.AcceptJobsResponse, error) SubmitJob(ctx context.Context, job *js.Jobspec, cfg *config.RainbowConfig) (*pb.SubmitJobResponse, error) diff --git a/pkg/client/endpoint.go b/pkg/client/endpoint.go index 1065a8e..a77c63c 100644 --- a/pkg/client/endpoint.go +++ b/pkg/client/endpoint.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "log" + "os" "time" js "github.com/compspec/jobspec-go/pkg/jobspec/experimental" @@ -220,6 +221,56 @@ func (c *RainbowClient) Register( return response, nil } +// UpdateState of an existing cluster +func (c *RainbowClient) UpdateState( + ctx context.Context, + cluster string, + secret string, + stateFile string, +) (*pb.UpdateStateResponse, error) { + + response := &pb.UpdateStateResponse{} + + // Unlike register, this is the cluster to add the subsytem for. + if cluster == "" { + return response, errors.New("cluster is required") + } + if secret == "" { + return response, errors.New("secret is required") + } + if !c.Connected() { + return response, errors.New("client is not connected") + } + if stateFile == "" { + return response, fmt.Errorf("a state file must be provided with --state-file") + } + _, err := utils.PathExists(stateFile) + if err != nil { + return response, errors.New(fmt.Sprintf("state file %s does not exist: %s", stateFile, err)) + } + + // Read stateFile into payload + states, err := os.ReadFile(stateFile) + if err != nil { + return response, err + } + + // Contact the server and print out its response. + ctx, cancel := context.WithTimeout(ctx, time.Second) + defer cancel() + + // Hit the register subsystem endpoint + response, err = c.service.UpdateState(ctx, &pb.UpdateStateRequest{ + Cluster: cluster, + Secret: secret, + Payload: string(states), + }) + if err != nil { + return response, errors.Wrap(err, "could not update endpoint") + } + return response, nil +} + // Register makes a request to register a new cluster func (c *RainbowClient) RegisterSubsystem( ctx context.Context, diff --git a/pkg/graph/backend/backend.go b/pkg/graph/backend/backend.go index 34124e3..39bcbf3 100644 --- a/pkg/graph/backend/backend.go +++ b/pkg/graph/backend/backend.go @@ -8,6 +8,7 @@ import ( "github.com/converged-computing/jsongraph-go/jsongraph/v2/graph" "github.com/converged-computing/rainbow/pkg/graph/algorithm" + "github.com/converged-computing/rainbow/pkg/types" "google.golang.org/grpc" ) @@ -41,6 +42,13 @@ type GraphBackend interface { // Add a subsystem to the graph AddSubsystem(name string, nodes *graph.JsonGraph, subsystem string) error + + // Update state of a cluster in the graph + UpdateState(name, payload string) error + + // GetStates for a final set of clusters, these states + // go to selection algorithms + GetStates([]string) (map[string]types.ClusterState, error) } // List returns known backends diff --git a/pkg/graph/selection/selection.go b/pkg/graph/selection/selection.go index 89a0fab..6e66006 100644 --- a/pkg/graph/selection/selection.go +++ b/pkg/graph/selection/selection.go @@ -3,6 +3,8 @@ package selection import ( "fmt" "log" + + "github.com/converged-computing/rainbow/pkg/types" ) // Lookup of Algorthms @@ -18,7 +20,8 @@ type SelectionAlgorithm interface { Init(map[string]string) error // Take a list of contenders and select based on algorithm - Select([]string) (string, error) + // The algorithm can optionally use cluster states from the graph + Select([]string, map[string]types.ClusterState) (string, error) } // List returns known backends diff --git a/pkg/server/endpoint.go b/pkg/server/endpoint.go index 5672414..20e1b27 100644 --- a/pkg/server/endpoint.go +++ b/pkg/server/endpoint.go @@ -47,6 +47,30 @@ func (s *Server) Register(_ context.Context, in *pb.RegisterRequest) (*pb.Regist return response, err } +// UpdateState sends state metadata to the graph for the selection step +// This could eventually be used in other parts of the graph search but +// right now makes sense to be used with algorithms +func (s *Server) UpdateState(_ context.Context, in *pb.UpdateStateRequest) (*pb.UpdateStateResponse, error) { + if in == nil { + return nil, errors.New("request is required") + } + if in.Cluster == "" || in.Secret == "" || in.Payload == "" { + return nil, errors.New("cluster, name, secret, and state file payload are required") + } + _, err := s.db.ValidateClusterSecret(in.Cluster, in.Secret) + if err != nil { + return nil, errors.New("request denied") + } + // A subsystem just needs to be added to the graph + log.Printf("📝️ received state update: %s", in.Cluster) + response := pb.UpdateStateResponse{Status: pb.UpdateStateResponse_UPDATE_STATE_SUCCESS} + err = s.graph.UpdateState(in.Cluster, in.Payload) + if err != nil { + response.Status = pb.UpdateStateResponse_UPDATE_STATE_ERROR + } + return &response, err +} + // Register a subsystem with the server func (s *Server) RegisterSubsystem(_ context.Context, in *pb.RegisterRequest) (*pb.RegisterResponse, error) { if in == nil { @@ -119,8 +143,15 @@ func (s *Server) SubmitJob(_ context.Context, in *pb.SubmitJobRequest) (*pb.Subm log.Printf("📝️ received job %s for %d contender clusters", in.Name, len(clusters)) - // Use the algorithm to select a final cluster - selected, err := s.selectionAlgorithm.Select(clusters) + // Get state for clusters. Note that we allow clusters that are missing + // state data - given that the algorithm needs it, they are not included + states, err := s.graph.GetStates(clusters) + if err != nil { + return nil, err + } + + // Use the algorithm to select a final cluster, providing states + selected, err := s.selectionAlgorithm.Select(clusters, states) if err != nil { return nil, err } diff --git a/pkg/types/backend.go b/pkg/types/backend.go index 9dc14aa..d4f80f9 100644 --- a/pkg/types/backend.go +++ b/pkg/types/backend.go @@ -14,6 +14,10 @@ type Resource struct { Metadata metadata.Metadata } +// A Cluster state is a key value interface. +// The algorithms are required to know what they are looking for +type ClusterState map[string]interface{} + // A vertex is defined by an identifier. We use an int // instead of a string because it's faster. Edges are other // vertices (and their identifiers) it's connected to. diff --git a/plugins/backends/memory/cluster.go b/plugins/backends/memory/cluster.go index d03ac09..9149c30 100644 --- a/plugins/backends/memory/cluster.go +++ b/plugins/backends/memory/cluster.go @@ -7,6 +7,7 @@ import ( jgf "github.com/converged-computing/jsongraph-go/jsongraph/v2/graph" rlog "github.com/converged-computing/rainbow/pkg/logger" + "github.com/converged-computing/rainbow/pkg/types" ) var ( @@ -19,6 +20,7 @@ var ( type ClusterGraph struct { subsystem map[string]*Subsystem lock sync.RWMutex + State map[string]interface{} // Courtesy holder for name Name string @@ -28,6 +30,14 @@ type ClusterGraph struct { dominantSubsystem string } +// GetState of the cluster +// We could expose this as a public variable, but I'm leaving +// like this in case we want to do additional processing +// (for example, maybe some attributes are private) +func (c *ClusterGraph) GetState() types.ClusterState { + return c.State +} + // Dominant subsystem gets the dominant subsystem func (c *ClusterGraph) DominantSubsystem() *Subsystem { return c.subsystem[c.dominantSubsystem] @@ -113,6 +123,7 @@ func NewClusterGraph(name string, domSubsystem string) *ClusterGraph { Name: name, subsystem: subsystems, dominantSubsystem: defaultDominantSubsystem, + State: types.ClusterState{}, } return g } diff --git a/plugins/backends/memory/graph.go b/plugins/backends/memory/graph.go index 199c710..34bc689 100644 --- a/plugins/backends/memory/graph.go +++ b/plugins/backends/memory/graph.go @@ -16,6 +16,7 @@ import ( "github.com/converged-computing/rainbow/pkg/graph" "github.com/converged-computing/rainbow/pkg/graph/algorithm" rlog "github.com/converged-computing/rainbow/pkg/logger" + "github.com/converged-computing/rainbow/pkg/types" "github.com/converged-computing/rainbow/pkg/utils" "github.com/converged-computing/rainbow/plugins/backends/memory/service" ) @@ -30,6 +31,35 @@ type Graph struct { dominantSubsystem string } +// GetStates for clusters in the graph +func (g *Graph) GetStates(names []string) (map[string]types.ClusterState, error) { + states := map[string]types.ClusterState{} + for _, name := range names { + + // Only error if the cluster isn't known + cluster, ok := g.Clusters[name] + if !ok { + return states, fmt.Errorf("cluster %s does not exist", name) + } + states[name] = cluster.GetState() + } + return states, nil +} + +// UpdateState updates the state of a known cluster in the graph +func (g *Graph) UpdateState(name string, state *types.ClusterState) error { + cluster, ok := g.Clusters[name] + if !ok { + return fmt.Errorf("cluster %s does not exist", name) + } + // We always update old values + for key, value := range *state { + rlog.Debugf("Updating state %s to %v\n", key, value) + cluster.State[key] = value + } + return nil +} + // NewGraph creates a structure that holds one or more graphs func NewGraph() *Graph { diff --git a/plugins/backends/memory/memory.go b/plugins/backends/memory/memory.go index 1017ba8..f4509f2 100644 --- a/plugins/backends/memory/memory.go +++ b/plugins/backends/memory/memory.go @@ -12,6 +12,7 @@ import ( "github.com/converged-computing/rainbow/pkg/graph/algorithm" "github.com/converged-computing/rainbow/pkg/graph/backend" + "github.com/converged-computing/rainbow/pkg/types" "github.com/converged-computing/rainbow/plugins/backends/memory/service" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" @@ -53,6 +54,26 @@ func (m MemoryGraph) AddCluster( } // Add subsystem adds a new subsystem to the graph! +func (m MemoryGraph) UpdateState( + name string, + payload string, +) error { + // Load state into interface + state := types.ClusterState{} + err := json.Unmarshal([]byte(payload), &state) + if err != nil { + return err + } + return graphClient.UpdateState(name, &state) +} + +// GetStates for a list of clusters +func (m MemoryGraph) GetStates(names []string) (map[string]types.ClusterState, error) { + return graphClient.GetStates(names) +} + +// UpdateState of a cluster in the graph. +// This is used for selection algorithms func (m MemoryGraph) AddSubsystem( name string, nodes *jgf.JsonGraph, diff --git a/plugins/selection/random/random.go b/plugins/selection/random/random.go index 0f36a58..3357caa 100644 --- a/plugins/selection/random/random.go +++ b/plugins/selection/random/random.go @@ -4,6 +4,7 @@ import ( "math/rand" "github.com/converged-computing/rainbow/pkg/graph/selection" + "github.com/converged-computing/rainbow/pkg/types" ) // Random selection of a cluster @@ -26,7 +27,10 @@ func (s RandomSelection) Description() string { // Select randomly chooses a cluster from the set // This should not receive an empty list, but we check anyway -func (s RandomSelection) Select(contenders []string) (string, error) { +func (s RandomSelection) Select( + contenders []string, + states map[string]types.ClusterState, +) (string, error) { if len(contenders) == 0 { return "", nil } diff --git a/python/v1/README.md b/python/v1/README.md index 8fcc897..84b2e57 100644 --- a/python/v1/README.md +++ b/python/v1/README.md @@ -100,6 +100,38 @@ In the server window you'll see the subsystem added: } ``` +### Update State + +While we likely will have clusters sending back state when they accept jobs, for now we have a separate endpoint to do a one-off request to update the state. You can test that here. + +```bash +python ./examples/flux/update-state.py keebler --config-path ./rainbow-config.yaml +``` +```console +status: UPDATE_STATE_SUCCESS +``` + +In the server terminal (depending on your level of logging) you'll see the state update. + +```console +2024/04/05 18:45:16 We have made an in memory graph (subsystem io) with 7 vertices, with 15 connections to the dominant! +Metrics for subsystem io{ + "io": 1, + "mtl1unit": 1, + "mtl2unit": 1, + "mtl3unit": 1, + "nvme": 1, + "shm": 1 +} +2024/04/05 18:47:18 📝️ received state update: keebler +Updating state cost-per-node to 12 +Updating state max-jobs to 100 +``` + +Note that the path to the state metadata file is provided as a default to make the demo simple. +This state metadata will be provided to the selection algorithm to use as needed to make choice for +a final cluster. + ### Submit Job (Simple) Now let's submit a job to our faux cluster. We need to provide the token we received above. Remember that this is a two stage process: diff --git a/python/v1/examples/flux/update-state.py b/python/v1/examples/flux/update-state.py new file mode 100644 index 0000000..ea28bb3 --- /dev/null +++ b/python/v1/examples/flux/update-state.py @@ -0,0 +1,50 @@ +import argparse +import os + +from rainbow.protos import rainbow_pb2 +from rainbow.client import RainbowClient +import rainbow.config as config + +# Config file from a few directories up +here = os.path.abspath(os.path.dirname(__file__)) +root = here + +# rainbow root directory +for iter in range(4): + root = os.path.dirname(root) + + +def get_parser(): + parser = argparse.ArgumentParser(description="🌈️ Rainbow scheduler update state") + parser.add_argument("--cluster", help="cluster name to register", default="keebler") + parser.add_argument("--host", help="host of rainbow cluster", default="localhost:50051") + parser.add_argument( + "--config-path", + help="Path to rainbow configuration file to write or use", + ) + parser.add_argument( + "--state-file", + help="Json file with key/value metadata pairs to update", + default=os.path.join(root, "docs", "examples", "scheduler", "cluster-state.json"), + ) + return parser + + +def main(): + parser = get_parser() + args, _ = parser.parse_known_args() + cli = RainbowClient(host=args.host) + + # Do we want to write or update a config file? + if not args.config_path or not os.path.exists(args.config_path): + cfg = config.new_rainbow_config(args.host, args.cluster, args.secret) + else: + cfg = config.RainbowConfig(args.config_path) + + # The secret we need is from the cluster config + secret = cfg._cfg["cluster"]["secret"] + response = cli.update_state(args.cluster, state_file=args.state_file, secret=secret) + print(response) + +if __name__ == "__main__": + main() diff --git a/python/v1/rainbow/client.py b/python/v1/rainbow/client.py index d2ffc22..0e2e9dc 100644 --- a/python/v1/rainbow/client.py +++ b/python/v1/rainbow/client.py @@ -104,6 +104,30 @@ def register(self, cluster, secret, cluster_nodes): response = stub.Register(registerRequest) return response + def update_state(self, cluster, state_file, secret): + """ + Update a cluster state + """ + if not cluster: + raise ValueError("A cluster name is required to register") + if not secret: + raise ValueError("A secret is required to register") + if not os.path.exists(state_file): + raise ValueError(f"State metadata file {state_file} does not exist.") + + payload = utils.read_file(state_file) + + # These are the variables for our cluster - name for now + request = rainbow_pb2.UpdateStateRequest( + cluster=cluster, + secret=secret, + payload=payload, + ) + with grpc.insecure_channel(self.host) as channel: + stub = rainbow_pb2_grpc.RainbowSchedulerStub(channel) + response = stub.UpdateState(request) + return response + def register_subsystem(self, cluster, subsystem, secret, nodes): """ Register subsystem nodes to rainbow diff --git a/python/v1/rainbow/protos/rainbow_pb2.py b/python/v1/rainbow/protos/rainbow_pb2.py index 3e66da7..0cda9fc 100644 --- a/python/v1/rainbow/protos/rainbow_pb2.py +++ b/python/v1/rainbow/protos/rainbow_pb2.py @@ -16,7 +16,7 @@ from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n\rrainbow.proto\x12\x1e\x63onvergedcomputing.org.grpc.v1\x1a\x1fgoogle/protobuf/timestamp.proto"{\n\x0fRegisterRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0e\n\x06secret\x18\x02 \x01(\t\x12\r\n\x05nodes\x18\x03 \x01(\t\x12\x11\n\tsubsystem\x18\x04 \x01(\t\x12(\n\x04sent\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xcf\x01\n\x10SubmitJobRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12J\n\x08\x63lusters\x18\x02 \x03(\x0b\x32\x38.convergedcomputing.org.grpc.v1.SubmitJobRequest.Cluster\x12\x0f\n\x07jobspec\x18\x03 \x01(\t\x12(\n\x04sent\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x1a&\n\x07\x43luster\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05token\x18\x02 \x01(\t"p\n\x12ReceiveJobsRequest\x12\x0f\n\x07\x63luster\x18\x01 \x01(\t\x12\x0e\n\x06secret\x18\x02 \x01(\t\x12\x0f\n\x07maxJobs\x18\x03 \x01(\x05\x12(\n\x04sent\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"n\n\x11\x41\x63\x63\x65ptJobsRequest\x12\x0f\n\x07\x63luster\x18\x01 \x01(\t\x12\x0e\n\x06secret\x18\x02 \x01(\t\x12\x0e\n\x06jobids\x18\x03 \x03(\x05\x12(\n\x04sent\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\x8e\x02\n\x10RegisterResponse\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12\r\n\x05token\x18\x02 \x01(\t\x12\x0e\n\x06secret\x18\x03 \x01(\t\x12K\n\x06status\x18\x04 \x01(\x0e\x32;.convergedcomputing.org.grpc.v1.RegisterResponse.ResultType"z\n\nResultType\x12\x18\n\x14REGISTER_UNSPECIFIED\x10\x00\x12\x14\n\x10REGISTER_SUCCESS\x10\x01\x12\x12\n\x0eREGISTER_ERROR\x10\x02\x12\x13\n\x0fREGISTER_DENIED\x10\x03\x12\x13\n\x0fREGISTER_EXISTS\x10\x04"\xf4\x01\n\x11SubmitJobResponse\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12\r\n\x05jobid\x18\x02 \x01(\x05\x12\x0f\n\x07\x63luster\x18\x03 \x01(\t\x12L\n\x06status\x18\x04 \x01(\x0e\x32<.convergedcomputing.org.grpc.v1.SubmitJobResponse.ResultType"]\n\nResultType\x12\x16\n\x12SUBMIT_UNSPECIFIED\x10\x00\x12\x12\n\x0eSUBMIT_SUCCESS\x10\x01\x12\x10\n\x0cSUBMIT_ERROR\x10\x02\x12\x11\n\rSUBMIT_DENIED\x10\x03"\xe8\x02\n\x13ReceiveJobsResponse\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12K\n\x04jobs\x18\x02 \x03(\x0b\x32=.convergedcomputing.org.grpc.v1.ReceiveJobsResponse.JobsEntry\x12N\n\x06status\x18\x03 \x01(\x0e\x32>.convergedcomputing.org.grpc.v1.ReceiveJobsResponse.ResultType\x1a+\n\tJobsEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"s\n\nResultType\x12\x1a\n\x16REQUEST_JOBS_NORESULTS\x10\x00\x12\x18\n\x14REQUEST_JOBS_SUCCESS\x10\x01\x12\x16\n\x12REQUEST_JOBS_ERROR\x10\x02\x12\x17\n\x13REQUEST_JOBS_DENIED\x10\x03"\xd7\x01\n\x12\x41\x63\x63\x65ptJobsResponse\x12M\n\x06status\x18\x01 \x01(\x0e\x32=.convergedcomputing.org.grpc.v1.AcceptJobsResponse.ResultType"r\n\nResultType\x12\x1b\n\x17RESULT_TYPE_UNSPECIFIED\x10\x00\x12\x17\n\x13RESULT_TYPE_PARTIAL\x10\x01\x12\x17\n\x13RESULT_TYPE_SUCCESS\x10\x02\x12\x15\n\x11RESULT_TYPE_ERROR\x10\x03\x32\xd8\x04\n\x10RainbowScheduler\x12m\n\x08Register\x12/.convergedcomputing.org.grpc.v1.RegisterRequest\x1a\x30.convergedcomputing.org.grpc.v1.RegisterResponse\x12v\n\x11RegisterSubsystem\x12/.convergedcomputing.org.grpc.v1.RegisterRequest\x1a\x30.convergedcomputing.org.grpc.v1.RegisterResponse\x12p\n\tSubmitJob\x12\x30.convergedcomputing.org.grpc.v1.SubmitJobRequest\x1a\x31.convergedcomputing.org.grpc.v1.SubmitJobResponse\x12v\n\x0bReceiveJobs\x12\x32.convergedcomputing.org.grpc.v1.ReceiveJobsRequest\x1a\x33.convergedcomputing.org.grpc.v1.ReceiveJobsResponse\x12s\n\nAcceptJobs\x12\x31.convergedcomputing.org.grpc.v1.AcceptJobsRequest\x1a\x32.convergedcomputing.org.grpc.v1.AcceptJobsResponseB3Z1github.com/converged-computing/rainbow/pkg/api/v1b\x06proto3' + b'\n\rrainbow.proto\x12\x1e\x63onvergedcomputing.org.grpc.v1\x1a\x1fgoogle/protobuf/timestamp.proto"{\n\x0fRegisterRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0e\n\x06secret\x18\x02 \x01(\t\x12\r\n\x05nodes\x18\x03 \x01(\t\x12\x11\n\tsubsystem\x18\x04 \x01(\t\x12(\n\x04sent\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"F\n\x12UpdateStateRequest\x12\x0f\n\x07\x63luster\x18\x01 \x01(\t\x12\x0e\n\x06secret\x18\x02 \x01(\t\x12\x0f\n\x07payload\x18\x03 \x01(\t"\xdd\x01\n\x13UpdateStateResponse\x12N\n\x06status\x18\x01 \x01(\x0e\x32>.convergedcomputing.org.grpc.v1.UpdateStateResponse.ResultType"v\n\nResultType\x12\x1c\n\x18UPDATE_STATE_UNSPECIFIED\x10\x00\x12\x18\n\x14UPDATE_STATE_PARTIAL\x10\x01\x12\x18\n\x14UPDATE_STATE_SUCCESS\x10\x02\x12\x16\n\x12UPDATE_STATE_ERROR\x10\x03"\xcf\x01\n\x10SubmitJobRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12J\n\x08\x63lusters\x18\x02 \x03(\x0b\x32\x38.convergedcomputing.org.grpc.v1.SubmitJobRequest.Cluster\x12\x0f\n\x07jobspec\x18\x03 \x01(\t\x12(\n\x04sent\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x1a&\n\x07\x43luster\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05token\x18\x02 \x01(\t"p\n\x12ReceiveJobsRequest\x12\x0f\n\x07\x63luster\x18\x01 \x01(\t\x12\x0e\n\x06secret\x18\x02 \x01(\t\x12\x0f\n\x07maxJobs\x18\x03 \x01(\x05\x12(\n\x04sent\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"n\n\x11\x41\x63\x63\x65ptJobsRequest\x12\x0f\n\x07\x63luster\x18\x01 \x01(\t\x12\x0e\n\x06secret\x18\x02 \x01(\t\x12\x0e\n\x06jobids\x18\x03 \x03(\x05\x12(\n\x04sent\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\x8e\x02\n\x10RegisterResponse\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12\r\n\x05token\x18\x02 \x01(\t\x12\x0e\n\x06secret\x18\x03 \x01(\t\x12K\n\x06status\x18\x04 \x01(\x0e\x32;.convergedcomputing.org.grpc.v1.RegisterResponse.ResultType"z\n\nResultType\x12\x18\n\x14REGISTER_UNSPECIFIED\x10\x00\x12\x14\n\x10REGISTER_SUCCESS\x10\x01\x12\x12\n\x0eREGISTER_ERROR\x10\x02\x12\x13\n\x0fREGISTER_DENIED\x10\x03\x12\x13\n\x0fREGISTER_EXISTS\x10\x04"\xf4\x01\n\x11SubmitJobResponse\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12\r\n\x05jobid\x18\x02 \x01(\x05\x12\x0f\n\x07\x63luster\x18\x03 \x01(\t\x12L\n\x06status\x18\x04 \x01(\x0e\x32<.convergedcomputing.org.grpc.v1.SubmitJobResponse.ResultType"]\n\nResultType\x12\x16\n\x12SUBMIT_UNSPECIFIED\x10\x00\x12\x12\n\x0eSUBMIT_SUCCESS\x10\x01\x12\x10\n\x0cSUBMIT_ERROR\x10\x02\x12\x11\n\rSUBMIT_DENIED\x10\x03"\xe8\x02\n\x13ReceiveJobsResponse\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12K\n\x04jobs\x18\x02 \x03(\x0b\x32=.convergedcomputing.org.grpc.v1.ReceiveJobsResponse.JobsEntry\x12N\n\x06status\x18\x03 \x01(\x0e\x32>.convergedcomputing.org.grpc.v1.ReceiveJobsResponse.ResultType\x1a+\n\tJobsEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"s\n\nResultType\x12\x1a\n\x16REQUEST_JOBS_NORESULTS\x10\x00\x12\x18\n\x14REQUEST_JOBS_SUCCESS\x10\x01\x12\x16\n\x12REQUEST_JOBS_ERROR\x10\x02\x12\x17\n\x13REQUEST_JOBS_DENIED\x10\x03"\xd7\x01\n\x12\x41\x63\x63\x65ptJobsResponse\x12M\n\x06status\x18\x01 \x01(\x0e\x32=.convergedcomputing.org.grpc.v1.AcceptJobsResponse.ResultType"r\n\nResultType\x12\x1b\n\x17RESULT_TYPE_UNSPECIFIED\x10\x00\x12\x17\n\x13RESULT_TYPE_PARTIAL\x10\x01\x12\x17\n\x13RESULT_TYPE_SUCCESS\x10\x02\x12\x15\n\x11RESULT_TYPE_ERROR\x10\x03\x32\xd0\x05\n\x10RainbowScheduler\x12m\n\x08Register\x12/.convergedcomputing.org.grpc.v1.RegisterRequest\x1a\x30.convergedcomputing.org.grpc.v1.RegisterResponse\x12v\n\x11RegisterSubsystem\x12/.convergedcomputing.org.grpc.v1.RegisterRequest\x1a\x30.convergedcomputing.org.grpc.v1.RegisterResponse\x12p\n\tSubmitJob\x12\x30.convergedcomputing.org.grpc.v1.SubmitJobRequest\x1a\x31.convergedcomputing.org.grpc.v1.SubmitJobResponse\x12v\n\x0bUpdateState\x12\x32.convergedcomputing.org.grpc.v1.UpdateStateRequest\x1a\x33.convergedcomputing.org.grpc.v1.UpdateStateResponse\x12v\n\x0bReceiveJobs\x12\x32.convergedcomputing.org.grpc.v1.ReceiveJobsRequest\x1a\x33.convergedcomputing.org.grpc.v1.ReceiveJobsResponse\x12s\n\nAcceptJobs\x12\x31.convergedcomputing.org.grpc.v1.AcceptJobsRequest\x1a\x32.convergedcomputing.org.grpc.v1.AcceptJobsResponseB3Z1github.com/converged-computing/rainbow/pkg/api/v1b\x06proto3' ) _globals = globals() @@ -31,32 +31,38 @@ _globals["_RECEIVEJOBSRESPONSE_JOBSENTRY"]._serialized_options = b"8\001" _globals["_REGISTERREQUEST"]._serialized_start = 82 _globals["_REGISTERREQUEST"]._serialized_end = 205 - _globals["_SUBMITJOBREQUEST"]._serialized_start = 208 - _globals["_SUBMITJOBREQUEST"]._serialized_end = 415 - _globals["_SUBMITJOBREQUEST_CLUSTER"]._serialized_start = 377 - _globals["_SUBMITJOBREQUEST_CLUSTER"]._serialized_end = 415 - _globals["_RECEIVEJOBSREQUEST"]._serialized_start = 417 - _globals["_RECEIVEJOBSREQUEST"]._serialized_end = 529 - _globals["_ACCEPTJOBSREQUEST"]._serialized_start = 531 - _globals["_ACCEPTJOBSREQUEST"]._serialized_end = 641 - _globals["_REGISTERRESPONSE"]._serialized_start = 644 - _globals["_REGISTERRESPONSE"]._serialized_end = 914 - _globals["_REGISTERRESPONSE_RESULTTYPE"]._serialized_start = 792 - _globals["_REGISTERRESPONSE_RESULTTYPE"]._serialized_end = 914 - _globals["_SUBMITJOBRESPONSE"]._serialized_start = 917 - _globals["_SUBMITJOBRESPONSE"]._serialized_end = 1161 - _globals["_SUBMITJOBRESPONSE_RESULTTYPE"]._serialized_start = 1068 - _globals["_SUBMITJOBRESPONSE_RESULTTYPE"]._serialized_end = 1161 - _globals["_RECEIVEJOBSRESPONSE"]._serialized_start = 1164 - _globals["_RECEIVEJOBSRESPONSE"]._serialized_end = 1524 - _globals["_RECEIVEJOBSRESPONSE_JOBSENTRY"]._serialized_start = 1364 - _globals["_RECEIVEJOBSRESPONSE_JOBSENTRY"]._serialized_end = 1407 - _globals["_RECEIVEJOBSRESPONSE_RESULTTYPE"]._serialized_start = 1409 - _globals["_RECEIVEJOBSRESPONSE_RESULTTYPE"]._serialized_end = 1524 - _globals["_ACCEPTJOBSRESPONSE"]._serialized_start = 1527 - _globals["_ACCEPTJOBSRESPONSE"]._serialized_end = 1742 - _globals["_ACCEPTJOBSRESPONSE_RESULTTYPE"]._serialized_start = 1628 - _globals["_ACCEPTJOBSRESPONSE_RESULTTYPE"]._serialized_end = 1742 - _globals["_RAINBOWSCHEDULER"]._serialized_start = 1745 - _globals["_RAINBOWSCHEDULER"]._serialized_end = 2345 + _globals["_UPDATESTATEREQUEST"]._serialized_start = 207 + _globals["_UPDATESTATEREQUEST"]._serialized_end = 277 + _globals["_UPDATESTATERESPONSE"]._serialized_start = 280 + _globals["_UPDATESTATERESPONSE"]._serialized_end = 501 + _globals["_UPDATESTATERESPONSE_RESULTTYPE"]._serialized_start = 383 + _globals["_UPDATESTATERESPONSE_RESULTTYPE"]._serialized_end = 501 + _globals["_SUBMITJOBREQUEST"]._serialized_start = 504 + _globals["_SUBMITJOBREQUEST"]._serialized_end = 711 + _globals["_SUBMITJOBREQUEST_CLUSTER"]._serialized_start = 673 + _globals["_SUBMITJOBREQUEST_CLUSTER"]._serialized_end = 711 + _globals["_RECEIVEJOBSREQUEST"]._serialized_start = 713 + _globals["_RECEIVEJOBSREQUEST"]._serialized_end = 825 + _globals["_ACCEPTJOBSREQUEST"]._serialized_start = 827 + _globals["_ACCEPTJOBSREQUEST"]._serialized_end = 937 + _globals["_REGISTERRESPONSE"]._serialized_start = 940 + _globals["_REGISTERRESPONSE"]._serialized_end = 1210 + _globals["_REGISTERRESPONSE_RESULTTYPE"]._serialized_start = 1088 + _globals["_REGISTERRESPONSE_RESULTTYPE"]._serialized_end = 1210 + _globals["_SUBMITJOBRESPONSE"]._serialized_start = 1213 + _globals["_SUBMITJOBRESPONSE"]._serialized_end = 1457 + _globals["_SUBMITJOBRESPONSE_RESULTTYPE"]._serialized_start = 1364 + _globals["_SUBMITJOBRESPONSE_RESULTTYPE"]._serialized_end = 1457 + _globals["_RECEIVEJOBSRESPONSE"]._serialized_start = 1460 + _globals["_RECEIVEJOBSRESPONSE"]._serialized_end = 1820 + _globals["_RECEIVEJOBSRESPONSE_JOBSENTRY"]._serialized_start = 1660 + _globals["_RECEIVEJOBSRESPONSE_JOBSENTRY"]._serialized_end = 1703 + _globals["_RECEIVEJOBSRESPONSE_RESULTTYPE"]._serialized_start = 1705 + _globals["_RECEIVEJOBSRESPONSE_RESULTTYPE"]._serialized_end = 1820 + _globals["_ACCEPTJOBSRESPONSE"]._serialized_start = 1823 + _globals["_ACCEPTJOBSRESPONSE"]._serialized_end = 2038 + _globals["_ACCEPTJOBSRESPONSE_RESULTTYPE"]._serialized_start = 1924 + _globals["_ACCEPTJOBSRESPONSE_RESULTTYPE"]._serialized_end = 2038 + _globals["_RAINBOWSCHEDULER"]._serialized_start = 2041 + _globals["_RAINBOWSCHEDULER"]._serialized_end = 2761 # @@protoc_insertion_point(module_scope) diff --git a/python/v1/rainbow/protos/rainbow_pb2.pyi b/python/v1/rainbow/protos/rainbow_pb2.pyi index d038642..2ca4aff 100644 --- a/python/v1/rainbow/protos/rainbow_pb2.pyi +++ b/python/v1/rainbow/protos/rainbow_pb2.pyi @@ -21,6 +21,32 @@ class RegisterRequest(_message.Message): sent: _timestamp_pb2.Timestamp def __init__(self, name: _Optional[str] = ..., secret: _Optional[str] = ..., nodes: _Optional[str] = ..., subsystem: _Optional[str] = ..., sent: _Optional[_Union[_timestamp_pb2.Timestamp, _Mapping]] = ...) -> None: ... +class UpdateStateRequest(_message.Message): + __slots__ = ("cluster", "secret", "payload") + CLUSTER_FIELD_NUMBER: _ClassVar[int] + SECRET_FIELD_NUMBER: _ClassVar[int] + PAYLOAD_FIELD_NUMBER: _ClassVar[int] + cluster: str + secret: str + payload: str + def __init__(self, cluster: _Optional[str] = ..., secret: _Optional[str] = ..., payload: _Optional[str] = ...) -> None: ... + +class UpdateStateResponse(_message.Message): + __slots__ = ("status",) + class ResultType(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + UPDATE_STATE_UNSPECIFIED: _ClassVar[UpdateStateResponse.ResultType] + UPDATE_STATE_PARTIAL: _ClassVar[UpdateStateResponse.ResultType] + UPDATE_STATE_SUCCESS: _ClassVar[UpdateStateResponse.ResultType] + UPDATE_STATE_ERROR: _ClassVar[UpdateStateResponse.ResultType] + UPDATE_STATE_UNSPECIFIED: UpdateStateResponse.ResultType + UPDATE_STATE_PARTIAL: UpdateStateResponse.ResultType + UPDATE_STATE_SUCCESS: UpdateStateResponse.ResultType + UPDATE_STATE_ERROR: UpdateStateResponse.ResultType + STATUS_FIELD_NUMBER: _ClassVar[int] + status: UpdateStateResponse.ResultType + def __init__(self, status: _Optional[_Union[UpdateStateResponse.ResultType, str]] = ...) -> None: ... + class SubmitJobRequest(_message.Message): __slots__ = ("name", "clusters", "jobspec", "sent") class Cluster(_message.Message): diff --git a/python/v1/rainbow/protos/rainbow_pb2_grpc.py b/python/v1/rainbow/protos/rainbow_pb2_grpc.py index 581d9ea..2211f2e 100644 --- a/python/v1/rainbow/protos/rainbow_pb2_grpc.py +++ b/python/v1/rainbow/protos/rainbow_pb2_grpc.py @@ -29,6 +29,11 @@ def __init__(self, channel): request_serializer=rainbow__pb2.SubmitJobRequest.SerializeToString, response_deserializer=rainbow__pb2.SubmitJobResponse.FromString, ) + self.UpdateState = channel.unary_unary( + "/convergedcomputing.org.grpc.v1.RainbowScheduler/UpdateState", + request_serializer=rainbow__pb2.UpdateStateRequest.SerializeToString, + response_deserializer=rainbow__pb2.UpdateStateResponse.FromString, + ) self.ReceiveJobs = channel.unary_unary( "/convergedcomputing.org.grpc.v1.RainbowScheduler/ReceiveJobs", request_serializer=rainbow__pb2.ReceiveJobsRequest.SerializeToString, @@ -62,6 +67,14 @@ def SubmitJob(self, request, context): context.set_details("Method not implemented!") raise NotImplementedError("Method not implemented!") + def UpdateState(self, request, context): + """Update State - allow a cluster to provide state metadata + This is intended for use by a selection algorithm + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details("Method not implemented!") + raise NotImplementedError("Method not implemented!") + def ReceiveJobs(self, request, context): """Request Job - ask the rainbow scheduler for up to max jobs""" context.set_code(grpc.StatusCode.UNIMPLEMENTED) @@ -92,6 +105,11 @@ def add_RainbowSchedulerServicer_to_server(servicer, server): request_deserializer=rainbow__pb2.SubmitJobRequest.FromString, response_serializer=rainbow__pb2.SubmitJobResponse.SerializeToString, ), + "UpdateState": grpc.unary_unary_rpc_method_handler( + servicer.UpdateState, + request_deserializer=rainbow__pb2.UpdateStateRequest.FromString, + response_serializer=rainbow__pb2.UpdateStateResponse.SerializeToString, + ), "ReceiveJobs": grpc.unary_unary_rpc_method_handler( servicer.ReceiveJobs, request_deserializer=rainbow__pb2.ReceiveJobsRequest.FromString, @@ -200,6 +218,35 @@ def SubmitJob( metadata, ) + @staticmethod + def UpdateState( + request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None, + ): + return grpc.experimental.unary_unary( + request, + target, + "/convergedcomputing.org.grpc.v1.RainbowScheduler/UpdateState", + rainbow__pb2.UpdateStateRequest.SerializeToString, + rainbow__pb2.UpdateStateResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + ) + @staticmethod def ReceiveJobs( request, diff --git a/python/v1/setup.py b/python/v1/setup.py index 9e91888..22b1e37 100644 --- a/python/v1/setup.py +++ b/python/v1/setup.py @@ -18,7 +18,7 @@ if __name__ == "__main__": setup( name="rainbow-scheduler", - version="0.0.14", + version="0.0.15", author="Vanessasaurus", author_email="vsoch@users.noreply.github.com", maintainer="Vanessasaurus",