From f82b7e1ae3759f4cb15d2cca233b5a51fff3f91b Mon Sep 17 00:00:00 2001
From: Ekaterina Lebedeva <ekaterina.lebedeva@yadro.com>
Date: Thu, 15 Aug 2024 18:24:10 +0300
Subject: [PATCH] [#1135] ir: Add healthstatus RECONFIGURING

Signed-off-by: Ekaterina Lebedeva <ekaterina.lebedeva@yadro.com>
---
 cmd/frostfs-ir/config.go                   |  6 +++
 pkg/innerring/state.go                     | 12 ++++++
 pkg/services/control/ir/service_grpc.pb.go |  6 ++-
 pkg/services/control/ir/types.pb.go        | 18 ++++++---
 pkg/services/control/ir/types.proto        |  3 ++
 pkg/services/tree/service_grpc.pb.go       | 44 +++++++++-------------
 6 files changed, 54 insertions(+), 35 deletions(-)

diff --git a/cmd/frostfs-ir/config.go b/cmd/frostfs-ir/config.go
index 955195477..4eaac845c 100644
--- a/cmd/frostfs-ir/config.go
+++ b/cmd/frostfs-ir/config.go
@@ -7,6 +7,7 @@ import (
 
 	configViper "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/config"
 	"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
+	control "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir"
 	"github.com/spf13/viper"
 	"go.uber.org/zap"
 )
@@ -81,6 +82,10 @@ func watchForSignal(cancel func()) {
 				return
 			case <-sighupCh:
 				log.Info(logs.FrostFSNodeSIGHUPHasBeenReceivedRereadingConfiguration)
+				if !innerRing.CompareAndSwapHealthStatus(control.HealthStatus_READY, control.HealthStatus_RECONFIGURING) {
+					log.Info(logs.FrostFSNodeSIGHUPSkip)
+					break
+				}
 				err := reloadConfig()
 				if err != nil {
 					log.Error(logs.FrostFSNodeConfigurationReading, zap.Error(err))
@@ -92,6 +97,7 @@ func watchForSignal(cancel func()) {
 				if err != nil {
 					log.Error(logs.FrostFSNodeConfigurationReading, zap.Error(err))
 				}
+				innerRing.CompareAndSwapHealthStatus(control.HealthStatus_RECONFIGURING, control.HealthStatus_READY)
 				log.Info(logs.FrostFSNodeConfigurationHasBeenReloadedSuccessfully)
 			}
 		}
diff --git a/pkg/innerring/state.go b/pkg/innerring/state.go
index 1616dbb9f..d3071faad 100644
--- a/pkg/innerring/state.go
+++ b/pkg/innerring/state.go
@@ -161,6 +161,16 @@ func (s *Server) setHealthStatus(hs control.HealthStatus) {
 	}
 }
 
+func (s *Server) CompareAndSwapHealthStatus(oldSt, newSt control.HealthStatus) (swapped bool) {
+	if swapped = s.healthStatus.CompareAndSwap(int32(oldSt), int32(newSt)); swapped {
+		s.notifySystemd(newSt)
+		if s.irMetrics != nil {
+			s.irMetrics.SetHealth(int32(newSt))
+		}
+	}
+	return
+}
+
 // HealthStatus returns the current health status of the IR application.
 func (s *Server) HealthStatus() control.HealthStatus {
 	return control.HealthStatus(s.healthStatus.Load())
@@ -186,6 +196,8 @@ func (s *Server) notifySystemd(st control.HealthStatus) {
 		err = sdnotify.FlagAndStatus(sdnotify.ReadyEnabled)
 	case control.HealthStatus_SHUTTING_DOWN:
 		err = sdnotify.FlagAndStatus(sdnotify.StoppingEnabled)
+	case control.HealthStatus_RECONFIGURING:
+		err = sdnotify.FlagAndStatus(sdnotify.ReloadingEnabled)
 	default:
 		err = sdnotify.Status(fmt.Sprintf("%v", st))
 	}
diff --git a/pkg/services/control/ir/service_grpc.pb.go b/pkg/services/control/ir/service_grpc.pb.go
index 724149c44..336bf5f70 100644
--- a/pkg/services/control/ir/service_grpc.pb.go
+++ b/pkg/services/control/ir/service_grpc.pb.go
@@ -35,7 +35,8 @@ type ControlServiceClient interface {
 	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)
-	// Forces a container removal to be signaled by the IR node with high probability.
+	// Forces a container removal to be signaled by the IR node with high
+	// probability.
 	RemoveContainer(ctx context.Context, in *RemoveContainerRequest, opts ...grpc.CallOption) (*RemoveContainerResponse, error)
 }
 
@@ -93,7 +94,8 @@ type ControlServiceServer interface {
 	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)
-	// Forces a container removal to be signaled by the IR node with high probability.
+	// Forces a container removal to be signaled by the IR node with high
+	// probability.
 	RemoveContainer(context.Context, *RemoveContainerRequest) (*RemoveContainerResponse, error)
 }
 
diff --git a/pkg/services/control/ir/types.pb.go b/pkg/services/control/ir/types.pb.go
index 828814b25..840e0be67 100644
--- a/pkg/services/control/ir/types.pb.go
+++ b/pkg/services/control/ir/types.pb.go
@@ -32,6 +32,8 @@ const (
 	HealthStatus_READY HealthStatus = 2
 	// IR application is shutting down.
 	HealthStatus_SHUTTING_DOWN HealthStatus = 3
+	// IR application is reconfiguring.
+	HealthStatus_RECONFIGURING HealthStatus = 4
 )
 
 // Enum value maps for HealthStatus.
@@ -41,12 +43,14 @@ var (
 		1: "STARTING",
 		2: "READY",
 		3: "SHUTTING_DOWN",
+		4: "RECONFIGURING",
 	}
 	HealthStatus_value = map[string]int32{
 		"HEALTH_STATUS_UNDEFINED": 0,
 		"STARTING":                1,
 		"READY":                   2,
 		"SHUTTING_DOWN":           3,
+		"RECONFIGURING":           4,
 	}
 )
 
@@ -144,17 +148,19 @@ var file_pkg_services_control_ir_types_proto_rawDesc = []byte{
 	0x22, 0x36, 0x0a, 0x09, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x10, 0x0a,
 	0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12,
 	0x17, 0x0a, 0x04, 0x73, 0x69, 0x67, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73,
-	0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x2a, 0x57, 0x0a, 0x0c, 0x48, 0x65, 0x61, 0x6c,
+	0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x2a, 0x6a, 0x0a, 0x0c, 0x48, 0x65, 0x61, 0x6c,
 	0x74, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1b, 0x0a, 0x17, 0x48, 0x45, 0x41, 0x4c,
 	0x54, 0x48, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x44, 0x45, 0x46, 0x49,
 	0x4e, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x53, 0x54, 0x41, 0x52, 0x54, 0x49, 0x4e,
 	0x47, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x52, 0x45, 0x41, 0x44, 0x59, 0x10, 0x02, 0x12, 0x11,
 	0x0a, 0x0d, 0x53, 0x48, 0x55, 0x54, 0x54, 0x49, 0x4e, 0x47, 0x5f, 0x44, 0x4f, 0x57, 0x4e, 0x10,
-	0x03, 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,
+	0x03, 0x12, 0x11, 0x0a, 0x0d, 0x52, 0x45, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x55, 0x52, 0x49,
+	0x4e, 0x47, 0x10, 0x04, 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 (
diff --git a/pkg/services/control/ir/types.proto b/pkg/services/control/ir/types.proto
index 9b6731cf8..901a55918 100644
--- a/pkg/services/control/ir/types.proto
+++ b/pkg/services/control/ir/types.proto
@@ -26,4 +26,7 @@ enum HealthStatus {
 
   // IR application is shutting down.
   SHUTTING_DOWN = 3;
+
+  // IR application is reconfiguring.
+  RECONFIGURING = 4;
 }
diff --git a/pkg/services/tree/service_grpc.pb.go b/pkg/services/tree/service_grpc.pb.go
index 4c293a4c0..63f96e11a 100644
--- a/pkg/services/tree/service_grpc.pb.go
+++ b/pkg/services/tree/service_grpc.pb.go
@@ -3,7 +3,7 @@
 
 // Code generated by protoc-gen-go-grpc. DO NOT EDIT.
 // versions:
-// - protoc-gen-go-grpc v1.4.0
+// - protoc-gen-go-grpc v1.3.0
 // - protoc             v4.25.0
 // source: pkg/services/tree/service.proto
 
@@ -18,8 +18,8 @@ import (
 
 // This is a compile-time assertion to ensure that this generated file
 // is compatible with the grpc package it is being compiled against.
-// Requires gRPC-Go v1.62.0 or later.
-const _ = grpc.SupportPackageIsVersion8
+// Requires gRPC-Go v1.32.0 or later.
+const _ = grpc.SupportPackageIsVersion7
 
 const (
 	TreeService_Add_FullMethodName           = "/tree.TreeService/Add"
@@ -70,9 +70,8 @@ func NewTreeServiceClient(cc grpc.ClientConnInterface) TreeServiceClient {
 }
 
 func (c *treeServiceClient) Add(ctx context.Context, in *AddRequest, opts ...grpc.CallOption) (*AddResponse, error) {
-	cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
 	out := new(AddResponse)
-	err := c.cc.Invoke(ctx, TreeService_Add_FullMethodName, in, out, cOpts...)
+	err := c.cc.Invoke(ctx, TreeService_Add_FullMethodName, in, out, opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -80,9 +79,8 @@ func (c *treeServiceClient) Add(ctx context.Context, in *AddRequest, opts ...grp
 }
 
 func (c *treeServiceClient) AddByPath(ctx context.Context, in *AddByPathRequest, opts ...grpc.CallOption) (*AddByPathResponse, error) {
-	cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
 	out := new(AddByPathResponse)
-	err := c.cc.Invoke(ctx, TreeService_AddByPath_FullMethodName, in, out, cOpts...)
+	err := c.cc.Invoke(ctx, TreeService_AddByPath_FullMethodName, in, out, opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -90,9 +88,8 @@ func (c *treeServiceClient) AddByPath(ctx context.Context, in *AddByPathRequest,
 }
 
 func (c *treeServiceClient) Remove(ctx context.Context, in *RemoveRequest, opts ...grpc.CallOption) (*RemoveResponse, error) {
-	cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
 	out := new(RemoveResponse)
-	err := c.cc.Invoke(ctx, TreeService_Remove_FullMethodName, in, out, cOpts...)
+	err := c.cc.Invoke(ctx, TreeService_Remove_FullMethodName, in, out, opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -100,9 +97,8 @@ func (c *treeServiceClient) Remove(ctx context.Context, in *RemoveRequest, opts
 }
 
 func (c *treeServiceClient) Move(ctx context.Context, in *MoveRequest, opts ...grpc.CallOption) (*MoveResponse, error) {
-	cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
 	out := new(MoveResponse)
-	err := c.cc.Invoke(ctx, TreeService_Move_FullMethodName, in, out, cOpts...)
+	err := c.cc.Invoke(ctx, TreeService_Move_FullMethodName, in, out, opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -110,9 +106,8 @@ func (c *treeServiceClient) Move(ctx context.Context, in *MoveRequest, opts ...g
 }
 
 func (c *treeServiceClient) GetNodeByPath(ctx context.Context, in *GetNodeByPathRequest, opts ...grpc.CallOption) (*GetNodeByPathResponse, error) {
-	cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
 	out := new(GetNodeByPathResponse)
-	err := c.cc.Invoke(ctx, TreeService_GetNodeByPath_FullMethodName, in, out, cOpts...)
+	err := c.cc.Invoke(ctx, TreeService_GetNodeByPath_FullMethodName, in, out, opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -120,12 +115,11 @@ func (c *treeServiceClient) GetNodeByPath(ctx context.Context, in *GetNodeByPath
 }
 
 func (c *treeServiceClient) GetSubTree(ctx context.Context, in *GetSubTreeRequest, opts ...grpc.CallOption) (TreeService_GetSubTreeClient, error) {
-	cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
-	stream, err := c.cc.NewStream(ctx, &TreeService_ServiceDesc.Streams[0], TreeService_GetSubTree_FullMethodName, cOpts...)
+	stream, err := c.cc.NewStream(ctx, &TreeService_ServiceDesc.Streams[0], TreeService_GetSubTree_FullMethodName, opts...)
 	if err != nil {
 		return nil, err
 	}
-	x := &treeServiceGetSubTreeClient{ClientStream: stream}
+	x := &treeServiceGetSubTreeClient{stream}
 	if err := x.ClientStream.SendMsg(in); err != nil {
 		return nil, err
 	}
@@ -153,9 +147,8 @@ func (x *treeServiceGetSubTreeClient) Recv() (*GetSubTreeResponse, error) {
 }
 
 func (c *treeServiceClient) TreeList(ctx context.Context, in *TreeListRequest, opts ...grpc.CallOption) (*TreeListResponse, error) {
-	cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
 	out := new(TreeListResponse)
-	err := c.cc.Invoke(ctx, TreeService_TreeList_FullMethodName, in, out, cOpts...)
+	err := c.cc.Invoke(ctx, TreeService_TreeList_FullMethodName, in, out, opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -163,9 +156,8 @@ func (c *treeServiceClient) TreeList(ctx context.Context, in *TreeListRequest, o
 }
 
 func (c *treeServiceClient) Apply(ctx context.Context, in *ApplyRequest, opts ...grpc.CallOption) (*ApplyResponse, error) {
-	cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
 	out := new(ApplyResponse)
-	err := c.cc.Invoke(ctx, TreeService_Apply_FullMethodName, in, out, cOpts...)
+	err := c.cc.Invoke(ctx, TreeService_Apply_FullMethodName, in, out, opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -173,12 +165,11 @@ func (c *treeServiceClient) Apply(ctx context.Context, in *ApplyRequest, opts ..
 }
 
 func (c *treeServiceClient) GetOpLog(ctx context.Context, in *GetOpLogRequest, opts ...grpc.CallOption) (TreeService_GetOpLogClient, error) {
-	cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
-	stream, err := c.cc.NewStream(ctx, &TreeService_ServiceDesc.Streams[1], TreeService_GetOpLog_FullMethodName, cOpts...)
+	stream, err := c.cc.NewStream(ctx, &TreeService_ServiceDesc.Streams[1], TreeService_GetOpLog_FullMethodName, opts...)
 	if err != nil {
 		return nil, err
 	}
-	x := &treeServiceGetOpLogClient{ClientStream: stream}
+	x := &treeServiceGetOpLogClient{stream}
 	if err := x.ClientStream.SendMsg(in); err != nil {
 		return nil, err
 	}
@@ -206,9 +197,8 @@ func (x *treeServiceGetOpLogClient) Recv() (*GetOpLogResponse, error) {
 }
 
 func (c *treeServiceClient) Healthcheck(ctx context.Context, in *HealthcheckRequest, opts ...grpc.CallOption) (*HealthcheckResponse, error) {
-	cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
 	out := new(HealthcheckResponse)
-	err := c.cc.Invoke(ctx, TreeService_Healthcheck_FullMethodName, in, out, cOpts...)
+	err := c.cc.Invoke(ctx, TreeService_Healthcheck_FullMethodName, in, out, opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -383,7 +373,7 @@ func _TreeService_GetSubTree_Handler(srv interface{}, stream grpc.ServerStream)
 	if err := stream.RecvMsg(m); err != nil {
 		return err
 	}
-	return srv.(TreeServiceServer).GetSubTree(m, &treeServiceGetSubTreeServer{ServerStream: stream})
+	return srv.(TreeServiceServer).GetSubTree(m, &treeServiceGetSubTreeServer{stream})
 }
 
 type TreeService_GetSubTreeServer interface {
@@ -440,7 +430,7 @@ func _TreeService_GetOpLog_Handler(srv interface{}, stream grpc.ServerStream) er
 	if err := stream.RecvMsg(m); err != nil {
 		return err
 	}
-	return srv.(TreeServiceServer).GetOpLog(m, &treeServiceGetOpLogServer{ServerStream: stream})
+	return srv.(TreeServiceServer).GetOpLog(m, &treeServiceGetOpLogServer{stream})
 }
 
 type TreeService_GetOpLogServer interface {