[#114] Add remove-node IR control command

Signed-off-by: Alejandro Lopez <a.lopez@yadro.com>
This commit is contained in:
Alejandro Lopez 2023-05-03 16:19:46 +03:00 committed by Evgenii Stratonikov
parent ea10abb42a
commit 90799497d3
10 changed files with 676 additions and 54 deletions

View file

@ -10,6 +10,8 @@ var irCmd = &cobra.Command{
func initControlIRCmd() {
irCmd.AddCommand(tickEpochCmd)
irCmd.AddCommand(removeNodeCmd)
initControlIRTickEpochCmd()
initControlIRRemoveNodeCmd()
}

View file

@ -0,0 +1,58 @@
package control
import (
"encoding/hex"
"errors"
rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
ircontrol "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir"
ircontrolsrv "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir/server"
"github.com/spf13/cobra"
)
var removeNodeCmd = &cobra.Command{
Use: "remove-node",
Short: "Forces a node removal from netmap",
Long: "Forces a node removal from netmap via a notary request. It should be executed on other IR nodes as well.",
Run: removeNode,
}
func initControlIRRemoveNodeCmd() {
initControlFlags(removeNodeCmd)
flags := removeNodeCmd.Flags()
flags.String("node", "", "Node public key as a hex string")
_ = removeNodeCmd.MarkFlagRequired("node")
}
func removeNode(cmd *cobra.Command, _ []string) {
pk := key.Get(cmd)
c := getClient(cmd, pk)
nodeKeyStr, _ := cmd.Flags().GetString("node")
if len(nodeKeyStr) == 0 {
commonCmd.ExitOnErr(cmd, "parsing node public key: ", errors.New("key cannot be empty"))
}
nodeKey, err := hex.DecodeString(nodeKeyStr)
commonCmd.ExitOnErr(cmd, "can't decode node public key: %w", err)
req := new(ircontrol.RemoveNodeRequest)
req.SetBody(&ircontrol.RemoveNodeRequest_Body{
Key: nodeKey,
})
commonCmd.ExitOnErr(cmd, "could not sign request: %w", ircontrolsrv.SignMessage(pk, req))
var resp *ircontrol.RemoveNodeResponse
err = c.ExecRaw(func(client *rawclient.Client) error {
resp, err = ircontrol.RemoveNode(client, req)
return err
})
commonCmd.ExitOnErr(cmd, "rpc error: %w", err)
verifyResponse(cmd, resp.GetSignature(), resp.GetBody())
cmd.Println("Node removed")
}

View file

@ -41,3 +41,19 @@ func (c *Client) AddPeer(p AddPeerPrm) error {
}
return nil
}
// ForceRemovePeer marks the given peer as offline via a notary control transaction.
func (c *Client) ForceRemovePeer(nodeInfo netmap.NodeInfo) error {
if !c.client.WithNotary() {
return fmt.Errorf("peer can be forcefully removed only in notary environment")
}
prm := UpdatePeerPrm{}
prm.SetKey(nodeInfo.PublicKey())
prm.SetControlTX(true)
if err := c.UpdatePeerState(prm); err != nil {
return fmt.Errorf("updating peer state: %v", err)
}
return nil
}

View file

@ -11,6 +11,7 @@ const serviceName = "ircontrol.ControlService"
const (
rpcHealthCheck = "HealthCheck"
rpcTickEpoch = "TickEpoch"
rpcRemoveNode = "RemoveNode"
)
// HealthCheck executes ControlService.HealthCheck RPC.
@ -31,6 +32,14 @@ func TickEpoch(
return sendUnary[TickEpochRequest, TickEpochResponse](cli, rpcTickEpoch, req, opts...)
}
func RemoveNode(
cli *client.Client,
req *RemoveNodeRequest,
opts ...client.CallOption,
) (*RemoveNodeResponse, error) {
return sendUnary[RemoveNodeRequest, RemoveNodeResponse](cli, rpcRemoveNode, req, opts...)
}
func sendUnary[I, O grpc.Message](cli *client.Client, rpcName string, req *I, opts ...client.CallOption) (*O, error) {
var resp O
wResp := &responseWrapper[*O]{

View file

@ -1,9 +1,11 @@
package control
import (
"bytes"
"context"
"fmt"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap"
control "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
@ -57,3 +59,43 @@ func (s *Server) TickEpoch(_ context.Context, req *control.TickEpochRequest) (*c
return resp, nil
}
// RemoveNode forces a node removal.
//
// If request is not signed with a key from white list, permission error returns.
func (s *Server) RemoveNode(_ context.Context, req *control.RemoveNodeRequest) (*control.RemoveNodeResponse, error) {
if err := s.isValidRequest(req); err != nil {
return nil, status.Error(codes.PermissionDenied, err.Error())
}
resp := new(control.RemoveNodeResponse)
resp.SetBody(new(control.RemoveNodeResponse_Body))
nm, err := s.netmapClient.NetMap()
if err != nil {
return nil, fmt.Errorf("getting netmap: %w", err)
}
var nodeInfo netmap.NodeInfo
for _, info := range nm.Nodes() {
if bytes.Equal(info.PublicKey(), req.GetBody().GetKey()) {
nodeInfo = info
break
}
}
if len(nodeInfo.PublicKey()) == 0 {
return nil, status.Error(codes.NotFound, "no such node")
}
if nodeInfo.IsOffline() {
return nil, status.Error(codes.FailedPrecondition, "node is already offline")
}
if err := s.netmapClient.ForceRemovePeer(nodeInfo); err != nil {
return nil, fmt.Errorf("forcing node removal: %w", err)
}
if err := SignMessage(&s.prm.key.PrivateKey, resp); err != nil {
return nil, status.Error(codes.Internal, err.Error())
}
return resp, nil
}

View file

@ -32,3 +32,15 @@ func (x *TickEpochResponse) SetBody(v *TickEpochResponse_Body) {
x.Body = v
}
}
func (x *RemoveNodeRequest) SetBody(v *RemoveNodeRequest_Body) {
if x != nil {
x.Body = v
}
}
func (x *RemoveNodeResponse) SetBody(v *RemoveNodeResponse_Body) {
if x != nil {
x.Body = v
}
}

View file

@ -248,6 +248,116 @@ func (x *TickEpochResponse) GetSignature() *Signature {
return nil
}
type RemoveNodeRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Body *RemoveNodeRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"`
Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"`
}
func (x *RemoveNodeRequest) Reset() {
*x = RemoveNodeRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_pkg_services_control_ir_service_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *RemoveNodeRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*RemoveNodeRequest) ProtoMessage() {}
func (x *RemoveNodeRequest) ProtoReflect() protoreflect.Message {
mi := &file_pkg_services_control_ir_service_proto_msgTypes[4]
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 RemoveNodeRequest.ProtoReflect.Descriptor instead.
func (*RemoveNodeRequest) Descriptor() ([]byte, []int) {
return file_pkg_services_control_ir_service_proto_rawDescGZIP(), []int{4}
}
func (x *RemoveNodeRequest) GetBody() *RemoveNodeRequest_Body {
if x != nil {
return x.Body
}
return nil
}
func (x *RemoveNodeRequest) GetSignature() *Signature {
if x != nil {
return x.Signature
}
return nil
}
type RemoveNodeResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Body *RemoveNodeResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"`
Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"`
}
func (x *RemoveNodeResponse) Reset() {
*x = RemoveNodeResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_pkg_services_control_ir_service_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *RemoveNodeResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*RemoveNodeResponse) ProtoMessage() {}
func (x *RemoveNodeResponse) ProtoReflect() protoreflect.Message {
mi := &file_pkg_services_control_ir_service_proto_msgTypes[5]
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 RemoveNodeResponse.ProtoReflect.Descriptor instead.
func (*RemoveNodeResponse) Descriptor() ([]byte, []int) {
return file_pkg_services_control_ir_service_proto_rawDescGZIP(), []int{5}
}
func (x *RemoveNodeResponse) GetBody() *RemoveNodeResponse_Body {
if x != nil {
return x.Body
}
return nil
}
func (x *RemoveNodeResponse) GetSignature() *Signature {
if x != nil {
return x.Signature
}
return nil
}
// Health check request body.
type HealthCheckRequest_Body struct {
state protoimpl.MessageState
@ -258,7 +368,7 @@ type HealthCheckRequest_Body struct {
func (x *HealthCheckRequest_Body) Reset() {
*x = HealthCheckRequest_Body{}
if protoimpl.UnsafeEnabled {
mi := &file_pkg_services_control_ir_service_proto_msgTypes[4]
mi := &file_pkg_services_control_ir_service_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -271,7 +381,7 @@ func (x *HealthCheckRequest_Body) String() string {
func (*HealthCheckRequest_Body) ProtoMessage() {}
func (x *HealthCheckRequest_Body) ProtoReflect() protoreflect.Message {
mi := &file_pkg_services_control_ir_service_proto_msgTypes[4]
mi := &file_pkg_services_control_ir_service_proto_msgTypes[6]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -300,7 +410,7 @@ type HealthCheckResponse_Body struct {
func (x *HealthCheckResponse_Body) Reset() {
*x = HealthCheckResponse_Body{}
if protoimpl.UnsafeEnabled {
mi := &file_pkg_services_control_ir_service_proto_msgTypes[5]
mi := &file_pkg_services_control_ir_service_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -313,7 +423,7 @@ func (x *HealthCheckResponse_Body) String() string {
func (*HealthCheckResponse_Body) ProtoMessage() {}
func (x *HealthCheckResponse_Body) ProtoReflect() protoreflect.Message {
mi := &file_pkg_services_control_ir_service_proto_msgTypes[5]
mi := &file_pkg_services_control_ir_service_proto_msgTypes[7]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -345,7 +455,7 @@ type TickEpochRequest_Body struct {
func (x *TickEpochRequest_Body) Reset() {
*x = TickEpochRequest_Body{}
if protoimpl.UnsafeEnabled {
mi := &file_pkg_services_control_ir_service_proto_msgTypes[6]
mi := &file_pkg_services_control_ir_service_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -358,7 +468,7 @@ func (x *TickEpochRequest_Body) String() string {
func (*TickEpochRequest_Body) ProtoMessage() {}
func (x *TickEpochRequest_Body) ProtoReflect() protoreflect.Message {
mi := &file_pkg_services_control_ir_service_proto_msgTypes[6]
mi := &file_pkg_services_control_ir_service_proto_msgTypes[8]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -383,7 +493,7 @@ type TickEpochResponse_Body struct {
func (x *TickEpochResponse_Body) Reset() {
*x = TickEpochResponse_Body{}
if protoimpl.UnsafeEnabled {
mi := &file_pkg_services_control_ir_service_proto_msgTypes[7]
mi := &file_pkg_services_control_ir_service_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -396,7 +506,7 @@ func (x *TickEpochResponse_Body) String() string {
func (*TickEpochResponse_Body) ProtoMessage() {}
func (x *TickEpochResponse_Body) ProtoReflect() protoreflect.Message {
mi := &file_pkg_services_control_ir_service_proto_msgTypes[7]
mi := &file_pkg_services_control_ir_service_proto_msgTypes[9]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -412,6 +522,91 @@ func (*TickEpochResponse_Body) Descriptor() ([]byte, []int) {
return file_pkg_services_control_ir_service_proto_rawDescGZIP(), []int{3, 0}
}
type RemoveNodeRequest_Body struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
}
func (x *RemoveNodeRequest_Body) Reset() {
*x = RemoveNodeRequest_Body{}
if protoimpl.UnsafeEnabled {
mi := &file_pkg_services_control_ir_service_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *RemoveNodeRequest_Body) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*RemoveNodeRequest_Body) ProtoMessage() {}
func (x *RemoveNodeRequest_Body) ProtoReflect() protoreflect.Message {
mi := &file_pkg_services_control_ir_service_proto_msgTypes[10]
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 RemoveNodeRequest_Body.ProtoReflect.Descriptor instead.
func (*RemoveNodeRequest_Body) Descriptor() ([]byte, []int) {
return file_pkg_services_control_ir_service_proto_rawDescGZIP(), []int{4, 0}
}
func (x *RemoveNodeRequest_Body) GetKey() []byte {
if x != nil {
return x.Key
}
return nil
}
type RemoveNodeResponse_Body struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
}
func (x *RemoveNodeResponse_Body) Reset() {
*x = RemoveNodeResponse_Body{}
if protoimpl.UnsafeEnabled {
mi := &file_pkg_services_control_ir_service_proto_msgTypes[11]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *RemoveNodeResponse_Body) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*RemoveNodeResponse_Body) ProtoMessage() {}
func (x *RemoveNodeResponse_Body) ProtoReflect() protoreflect.Message {
mi := &file_pkg_services_control_ir_service_proto_msgTypes[11]
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 RemoveNodeResponse_Body.ProtoReflect.Descriptor instead.
func (*RemoveNodeResponse_Body) Descriptor() ([]byte, []int) {
return file_pkg_services_control_ir_service_proto_rawDescGZIP(), []int{5, 0}
}
var File_pkg_services_control_ir_service_proto protoreflect.FileDescriptor
var file_pkg_services_control_ir_service_proto_rawDesc = []byte{
@ -458,23 +653,46 @@ var file_pkg_services_control_ir_service_proto_rawDesc = []byte{
0x79, 0x12, 0x32, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e,
0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x32, 0xa6, 0x01,
0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
0x12, 0x4c, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12,
0x1d, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c,
0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e,
0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74,
0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x46,
0x0a, 0x09, 0x54, 0x69, 0x63, 0x6b, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x1b, 0x2e, 0x69, 0x72,
0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x54, 0x69, 0x63, 0x6b, 0x45, 0x70, 0x6f, 0x63,
0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e,
0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x54, 0x69, 0x63, 0x6b, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x44, 0x5a, 0x42, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72,
0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43,
0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d,
0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
0x73, 0x2f, 0x69, 0x72, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x62, 0x06, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x33,
0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0x98, 0x01,
0x0a, 0x11, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x21, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65,
0x6d, 0x6f, 0x76, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e,
0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x32, 0x0a, 0x09, 0x73, 0x69,
0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e,
0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74,
0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x18,
0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20,
0x01, 0x28, 0x0c, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x22, 0x88, 0x01, 0x0a, 0x12, 0x52, 0x65, 0x6d,
0x6f, 0x76, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
0x36, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e,
0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65,
0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64,
0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x32, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61,
0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x69, 0x72, 0x63,
0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65,
0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42,
0x6f, 0x64, 0x79, 0x32, 0xf1, 0x01, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x53,
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x4c, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68,
0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x1d, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f,
0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, 0x09, 0x54, 0x69, 0x63, 0x6b, 0x45, 0x70, 0x6f, 0x63,
0x68, 0x12, 0x1b, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x54, 0x69,
0x63, 0x6b, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c,
0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x54, 0x69, 0x63, 0x6b, 0x45,
0x70, 0x6f, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, 0x0a,
0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x1c, 0x2e, 0x69, 0x72, 0x63,
0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4e, 0x6f, 0x64,
0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e,
0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x44, 0x5a, 0x42, 0x67, 0x69, 0x74, 0x2e, 0x66,
0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65,
0x43, 0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73,
0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
0x65, 0x73, 0x2f, 0x69, 0x72, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x62, 0x06, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@ -489,38 +707,48 @@ func file_pkg_services_control_ir_service_proto_rawDescGZIP() []byte {
return file_pkg_services_control_ir_service_proto_rawDescData
}
var file_pkg_services_control_ir_service_proto_msgTypes = make([]protoimpl.MessageInfo, 8)
var file_pkg_services_control_ir_service_proto_msgTypes = make([]protoimpl.MessageInfo, 12)
var file_pkg_services_control_ir_service_proto_goTypes = []interface{}{
(*HealthCheckRequest)(nil), // 0: ircontrol.HealthCheckRequest
(*HealthCheckResponse)(nil), // 1: ircontrol.HealthCheckResponse
(*TickEpochRequest)(nil), // 2: ircontrol.TickEpochRequest
(*TickEpochResponse)(nil), // 3: ircontrol.TickEpochResponse
(*HealthCheckRequest_Body)(nil), // 4: ircontrol.HealthCheckRequest.Body
(*HealthCheckResponse_Body)(nil), // 5: ircontrol.HealthCheckResponse.Body
(*TickEpochRequest_Body)(nil), // 6: ircontrol.TickEpochRequest.Body
(*TickEpochResponse_Body)(nil), // 7: ircontrol.TickEpochResponse.Body
(*Signature)(nil), // 8: ircontrol.Signature
(HealthStatus)(0), // 9: ircontrol.HealthStatus
(*RemoveNodeRequest)(nil), // 4: ircontrol.RemoveNodeRequest
(*RemoveNodeResponse)(nil), // 5: ircontrol.RemoveNodeResponse
(*HealthCheckRequest_Body)(nil), // 6: ircontrol.HealthCheckRequest.Body
(*HealthCheckResponse_Body)(nil), // 7: ircontrol.HealthCheckResponse.Body
(*TickEpochRequest_Body)(nil), // 8: ircontrol.TickEpochRequest.Body
(*TickEpochResponse_Body)(nil), // 9: ircontrol.TickEpochResponse.Body
(*RemoveNodeRequest_Body)(nil), // 10: ircontrol.RemoveNodeRequest.Body
(*RemoveNodeResponse_Body)(nil), // 11: ircontrol.RemoveNodeResponse.Body
(*Signature)(nil), // 12: ircontrol.Signature
(HealthStatus)(0), // 13: ircontrol.HealthStatus
}
var file_pkg_services_control_ir_service_proto_depIdxs = []int32{
4, // 0: ircontrol.HealthCheckRequest.body:type_name -> ircontrol.HealthCheckRequest.Body
8, // 1: ircontrol.HealthCheckRequest.signature:type_name -> ircontrol.Signature
5, // 2: ircontrol.HealthCheckResponse.body:type_name -> ircontrol.HealthCheckResponse.Body
8, // 3: ircontrol.HealthCheckResponse.signature:type_name -> ircontrol.Signature
6, // 4: ircontrol.TickEpochRequest.body:type_name -> ircontrol.TickEpochRequest.Body
8, // 5: ircontrol.TickEpochRequest.signature:type_name -> ircontrol.Signature
7, // 6: ircontrol.TickEpochResponse.body:type_name -> ircontrol.TickEpochResponse.Body
8, // 7: ircontrol.TickEpochResponse.signature:type_name -> ircontrol.Signature
9, // 8: ircontrol.HealthCheckResponse.Body.health_status:type_name -> ircontrol.HealthStatus
0, // 9: ircontrol.ControlService.HealthCheck:input_type -> ircontrol.HealthCheckRequest
2, // 10: ircontrol.ControlService.TickEpoch:input_type -> ircontrol.TickEpochRequest
1, // 11: ircontrol.ControlService.HealthCheck:output_type -> ircontrol.HealthCheckResponse
3, // 12: ircontrol.ControlService.TickEpoch:output_type -> ircontrol.TickEpochResponse
11, // [11:13] is the sub-list for method output_type
9, // [9:11] is the sub-list for method input_type
9, // [9:9] is the sub-list for extension type_name
9, // [9:9] is the sub-list for extension extendee
0, // [0:9] is the sub-list for field type_name
6, // 0: ircontrol.HealthCheckRequest.body:type_name -> ircontrol.HealthCheckRequest.Body
12, // 1: ircontrol.HealthCheckRequest.signature:type_name -> ircontrol.Signature
7, // 2: ircontrol.HealthCheckResponse.body:type_name -> ircontrol.HealthCheckResponse.Body
12, // 3: ircontrol.HealthCheckResponse.signature:type_name -> ircontrol.Signature
8, // 4: ircontrol.TickEpochRequest.body:type_name -> ircontrol.TickEpochRequest.Body
12, // 5: ircontrol.TickEpochRequest.signature:type_name -> ircontrol.Signature
9, // 6: ircontrol.TickEpochResponse.body:type_name -> ircontrol.TickEpochResponse.Body
12, // 7: ircontrol.TickEpochResponse.signature:type_name -> ircontrol.Signature
10, // 8: ircontrol.RemoveNodeRequest.body:type_name -> ircontrol.RemoveNodeRequest.Body
12, // 9: ircontrol.RemoveNodeRequest.signature:type_name -> ircontrol.Signature
11, // 10: ircontrol.RemoveNodeResponse.body:type_name -> ircontrol.RemoveNodeResponse.Body
12, // 11: ircontrol.RemoveNodeResponse.signature:type_name -> ircontrol.Signature
13, // 12: ircontrol.HealthCheckResponse.Body.health_status:type_name -> ircontrol.HealthStatus
0, // 13: ircontrol.ControlService.HealthCheck:input_type -> ircontrol.HealthCheckRequest
2, // 14: ircontrol.ControlService.TickEpoch:input_type -> ircontrol.TickEpochRequest
4, // 15: ircontrol.ControlService.RemoveNode:input_type -> ircontrol.RemoveNodeRequest
1, // 16: ircontrol.ControlService.HealthCheck:output_type -> ircontrol.HealthCheckResponse
3, // 17: ircontrol.ControlService.TickEpoch:output_type -> ircontrol.TickEpochResponse
5, // 18: ircontrol.ControlService.RemoveNode:output_type -> ircontrol.RemoveNodeResponse
16, // [16:19] is the sub-list for method output_type
13, // [13:16] is the sub-list for method input_type
13, // [13:13] is the sub-list for extension type_name
13, // [13:13] is the sub-list for extension extendee
0, // [0:13] is the sub-list for field type_name
}
func init() { file_pkg_services_control_ir_service_proto_init() }
@ -579,7 +807,7 @@ func file_pkg_services_control_ir_service_proto_init() {
}
}
file_pkg_services_control_ir_service_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*HealthCheckRequest_Body); i {
switch v := v.(*RemoveNodeRequest); i {
case 0:
return &v.state
case 1:
@ -591,7 +819,7 @@ func file_pkg_services_control_ir_service_proto_init() {
}
}
file_pkg_services_control_ir_service_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*HealthCheckResponse_Body); i {
switch v := v.(*RemoveNodeResponse); i {
case 0:
return &v.state
case 1:
@ -603,7 +831,7 @@ func file_pkg_services_control_ir_service_proto_init() {
}
}
file_pkg_services_control_ir_service_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*TickEpochRequest_Body); i {
switch v := v.(*HealthCheckRequest_Body); i {
case 0:
return &v.state
case 1:
@ -615,6 +843,30 @@ func file_pkg_services_control_ir_service_proto_init() {
}
}
file_pkg_services_control_ir_service_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*HealthCheckResponse_Body); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_pkg_services_control_ir_service_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*TickEpochRequest_Body); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_pkg_services_control_ir_service_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*TickEpochResponse_Body); i {
case 0:
return &v.state
@ -626,6 +878,30 @@ func file_pkg_services_control_ir_service_proto_init() {
return nil
}
}
file_pkg_services_control_ir_service_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RemoveNodeRequest_Body); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_pkg_services_control_ir_service_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RemoveNodeResponse_Body); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
@ -633,7 +909,7 @@ func file_pkg_services_control_ir_service_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_pkg_services_control_ir_service_proto_rawDesc,
NumEnums: 0,
NumMessages: 8,
NumMessages: 12,
NumExtensions: 0,
NumServices: 1,
},

View file

@ -12,6 +12,8 @@ service ControlService {
rpc HealthCheck (HealthCheckRequest) returns (HealthCheckResponse);
// Forces a new epoch to be signaled by the IR node with high probability.
rpc TickEpoch (TickEpochRequest) returns (TickEpochResponse);
// Forces a node removal to be signaled by the IR node with high probability.
rpc RemoveNode (RemoveNodeRequest) returns (RemoveNodeResponse);
}
// Health check request.
@ -57,3 +59,19 @@ message TickEpochResponse {
Body body = 1;
Signature signature = 2;
}
message RemoveNodeRequest {
message Body{
bytes key = 1;
}
Body body = 1;
Signature signature = 2;
}
message RemoveNodeResponse {
message Body{}
Body body = 1;
Signature signature = 2;
}

View file

@ -296,3 +296,154 @@ func (x *TickEpochResponse) ReadSignedData(buf []byte) ([]byte, error) {
func (x *TickEpochResponse) SetSignature(sig *Signature) {
x.Signature = sig
}
// StableSize returns the size of x in protobuf format.
//
// Structures with the same field values have the same binary size.
func (x *RemoveNodeRequest_Body) StableSize() (size int) {
size += proto.BytesSize(1, x.Key)
return size
}
// StableMarshal marshals x in protobuf binary format with stable field order.
//
// If buffer length is less than x.StableSize(), new buffer is allocated.
//
// Returns any error encountered which did not allow writing the data completely.
// Otherwise, returns the buffer in which the data is written.
//
// Structures with the same field values have the same binary format.
func (x *RemoveNodeRequest_Body) StableMarshal(buf []byte) []byte {
if x == nil {
return []byte{}
}
if buf == nil {
buf = make([]byte, x.StableSize())
}
var offset int
offset += proto.BytesMarshal(1, buf[offset:], x.Key)
return buf
}
// StableSize returns the size of x in protobuf format.
//
// Structures with the same field values have the same binary size.
func (x *RemoveNodeRequest) StableSize() (size int) {
size += proto.NestedStructureSize(1, x.Body)
size += proto.NestedStructureSize(2, x.Signature)
return size
}
// StableMarshal marshals x in protobuf binary format with stable field order.
//
// If buffer length is less than x.StableSize(), new buffer is allocated.
//
// Returns any error encountered which did not allow writing the data completely.
// Otherwise, returns the buffer in which the data is written.
//
// Structures with the same field values have the same binary format.
func (x *RemoveNodeRequest) StableMarshal(buf []byte) []byte {
if x == nil {
return []byte{}
}
if buf == nil {
buf = make([]byte, x.StableSize())
}
var offset int
offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body)
offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature)
return buf
}
// ReadSignedData fills buf with signed data of x.
// If buffer length is less than x.SignedDataSize(), new buffer is allocated.
//
// Returns any error encountered which did not allow writing the data completely.
// Otherwise, returns the buffer in which the data is written.
//
// Structures with the same field values have the same signed data.
func (x *RemoveNodeRequest) SignedDataSize() int {
return x.GetBody().StableSize()
}
// SignedDataSize returns size of the request signed data in bytes.
//
// Structures with the same field values have the same signed data size.
func (x *RemoveNodeRequest) ReadSignedData(buf []byte) ([]byte, error) {
return x.GetBody().StableMarshal(buf), nil
}
func (x *RemoveNodeRequest) SetSignature(sig *Signature) {
x.Signature = sig
}
// StableSize returns the size of x in protobuf format.
//
// Structures with the same field values have the same binary size.
func (x *RemoveNodeResponse_Body) StableSize() (size int) {
return size
}
// StableMarshal marshals x in protobuf binary format with stable field order.
//
// If buffer length is less than x.StableSize(), new buffer is allocated.
//
// Returns any error encountered which did not allow writing the data completely.
// Otherwise, returns the buffer in which the data is written.
//
// Structures with the same field values have the same binary format.
func (x *RemoveNodeResponse_Body) StableMarshal(buf []byte) []byte {
return buf
}
// StableSize returns the size of x in protobuf format.
//
// Structures with the same field values have the same binary size.
func (x *RemoveNodeResponse) StableSize() (size int) {
size += proto.NestedStructureSize(1, x.Body)
size += proto.NestedStructureSize(2, x.Signature)
return size
}
// StableMarshal marshals x in protobuf binary format with stable field order.
//
// If buffer length is less than x.StableSize(), new buffer is allocated.
//
// Returns any error encountered which did not allow writing the data completely.
// Otherwise, returns the buffer in which the data is written.
//
// Structures with the same field values have the same binary format.
func (x *RemoveNodeResponse) StableMarshal(buf []byte) []byte {
if x == nil {
return []byte{}
}
if buf == nil {
buf = make([]byte, x.StableSize())
}
var offset int
offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body)
offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature)
return buf
}
// ReadSignedData fills buf with signed data of x.
// If buffer length is less than x.SignedDataSize(), new buffer is allocated.
//
// Returns any error encountered which did not allow writing the data completely.
// Otherwise, returns the buffer in which the data is written.
//
// Structures with the same field values have the same signed data.
func (x *RemoveNodeResponse) SignedDataSize() int {
return x.GetBody().StableSize()
}
// SignedDataSize returns size of the request signed data in bytes.
//
// Structures with the same field values have the same signed data size.
func (x *RemoveNodeResponse) ReadSignedData(buf []byte) ([]byte, error) {
return x.GetBody().StableMarshal(buf), nil
}
func (x *RemoveNodeResponse) SetSignature(sig *Signature) {
x.Signature = sig
}

View file

@ -26,6 +26,8 @@ type ControlServiceClient interface {
HealthCheck(ctx context.Context, in *HealthCheckRequest, opts ...grpc.CallOption) (*HealthCheckResponse, error)
// Forces a new epoch to be signaled by the IR node with high probability.
TickEpoch(ctx context.Context, in *TickEpochRequest, opts ...grpc.CallOption) (*TickEpochResponse, error)
// Forces a node removal to be signaled by the IR node with high probability.
RemoveNode(ctx context.Context, in *RemoveNodeRequest, opts ...grpc.CallOption) (*RemoveNodeResponse, error)
}
type controlServiceClient struct {
@ -54,6 +56,15 @@ func (c *controlServiceClient) TickEpoch(ctx context.Context, in *TickEpochReque
return out, nil
}
func (c *controlServiceClient) RemoveNode(ctx context.Context, in *RemoveNodeRequest, opts ...grpc.CallOption) (*RemoveNodeResponse, error) {
out := new(RemoveNodeResponse)
err := c.cc.Invoke(ctx, "/ircontrol.ControlService/RemoveNode", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// ControlServiceServer is the server API for ControlService service.
// All implementations should embed UnimplementedControlServiceServer
// for forward compatibility
@ -62,6 +73,8 @@ type ControlServiceServer interface {
HealthCheck(context.Context, *HealthCheckRequest) (*HealthCheckResponse, error)
// Forces a new epoch to be signaled by the IR node with high probability.
TickEpoch(context.Context, *TickEpochRequest) (*TickEpochResponse, error)
// Forces a node removal to be signaled by the IR node with high probability.
RemoveNode(context.Context, *RemoveNodeRequest) (*RemoveNodeResponse, error)
}
// UnimplementedControlServiceServer should be embedded to have forward compatible implementations.
@ -74,6 +87,9 @@ func (UnimplementedControlServiceServer) HealthCheck(context.Context, *HealthChe
func (UnimplementedControlServiceServer) TickEpoch(context.Context, *TickEpochRequest) (*TickEpochResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method TickEpoch not implemented")
}
func (UnimplementedControlServiceServer) RemoveNode(context.Context, *RemoveNodeRequest) (*RemoveNodeResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method RemoveNode not implemented")
}
// UnsafeControlServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to ControlServiceServer will
@ -122,6 +138,24 @@ func _ControlService_TickEpoch_Handler(srv interface{}, ctx context.Context, dec
return interceptor(ctx, in, info, handler)
}
func _ControlService_RemoveNode_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(RemoveNodeRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ControlServiceServer).RemoveNode(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/ircontrol.ControlService/RemoveNode",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ControlServiceServer).RemoveNode(ctx, req.(*RemoveNodeRequest))
}
return interceptor(ctx, in, info, handler)
}
// ControlService_ServiceDesc is the grpc.ServiceDesc for ControlService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
@ -137,6 +171,10 @@ var ControlService_ServiceDesc = grpc.ServiceDesc{
MethodName: "TickEpoch",
Handler: _ControlService_TickEpoch_Handler,
},
{
MethodName: "RemoveNode",
Handler: _ControlService_RemoveNode_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "pkg/services/control/ir/service.proto",