From 9ac1093805a6f65ff77bab1b0a4c38750440cc23 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 5 Oct 2022 14:40:37 +0300 Subject: [PATCH 1/5] [#1840] neofs-node: Allow to use `mode: disabled` in config Currently, when removing shard special care must be taken with respect to shard numbering. `mode: disabled` allows to leave shard configuration in place while also ignoring it during initialization. This makes disk replacement much more convenient. Signed-off-by: Evgenii Stratonikov --- CHANGELOG.md | 1 + cmd/neofs-node/config/engine/config.go | 9 ++++++++- cmd/neofs-node/config/engine/shard/config.go | 2 ++ pkg/local_object_storage/shard/mode/mode.go | 9 +++++++++ 4 files changed, 20 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 13fe707c3b1..ce889b1ba5b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ Changelog for NeoFS Node - `flush-cache` control service command to flush write-cache (#1806) - `wallet-address` flag in `neofs-adm morph refill-gas` command (#1820) - Validate policy before container creation (#1704) +- Shards can be marked with `mode: disabled` to be ignored by node (#1840) ### Changed - Allow to evacuate shard data with `EvacuateShard` control RPC (#1800) diff --git a/cmd/neofs-node/config/engine/config.go b/cmd/neofs-node/config/engine/config.go index 0fc9e01ebac..86f6b70c4a4 100644 --- a/cmd/neofs-node/config/engine/config.go +++ b/cmd/neofs-node/config/engine/config.go @@ -6,6 +6,7 @@ import ( "github.com/nspcc-dev/neofs-node/cmd/neofs-node/config" shardconfig "github.com/nspcc-dev/neofs-node/cmd/neofs-node/config/engine/shard" + "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/shard/mode" ) const ( @@ -31,6 +32,7 @@ func IterateShards(c *config.Config, required bool, f func(*shardconfig.Config) c = c.Sub("shard") def := c.Sub("default") + alive := 0 i := uint64(0) for ; ; i++ { si := strconv.FormatUint(i, 10) @@ -48,11 +50,16 @@ func IterateShards(c *config.Config, required bool, f func(*shardconfig.Config) } (*config.Config)(sc).SetDefault(def) + if sc.Mode() == mode.Disabled { + continue + } + if err := f(sc); err != nil { return err } + alive++ } - if i == 0 && required { + if alive == 0 && required { return ErrNoShardConfigured } return nil diff --git a/cmd/neofs-node/config/engine/shard/config.go b/cmd/neofs-node/config/engine/shard/config.go index ab1641ae236..610ebdf1ed9 100644 --- a/cmd/neofs-node/config/engine/shard/config.go +++ b/cmd/neofs-node/config/engine/shard/config.go @@ -128,6 +128,8 @@ func (x *Config) Mode() (m mode.Mode) { m = mode.Degraded case "degraded-read-only": m = mode.DegradedReadOnly + case "disabled": + m = mode.Disabled default: panic(fmt.Sprintf("unknown shard mode: %s", s)) } diff --git a/pkg/local_object_storage/shard/mode/mode.go b/pkg/local_object_storage/shard/mode/mode.go index b06920d2e7c..65b2b5c8950 100644 --- a/pkg/local_object_storage/shard/mode/mode.go +++ b/pkg/local_object_storage/shard/mode/mode.go @@ -1,5 +1,7 @@ package mode +import "math" + // Mode represents enumeration of Shard work modes. type Mode uint32 @@ -12,6 +14,11 @@ const ( // after a certain number of errors is encountered. It is the same as // `mode.Degraded` but also is read-only. DegradedReadOnly = Degraded | ReadOnly + + // Disabled mode is a mode where a shard is disabled. + // An existing shard can't have this mode, but it can be used in + // the configuration or control service commands. + Disabled = math.MaxUint32 ) const ( @@ -36,6 +43,8 @@ func (m Mode) String() string { return "DEGRADED_READ_WRITE" case DegradedReadOnly: return "DEGRADED_READ_ONLY" + case Disabled: + return "DISABLED" } } From 2ecee9f2ccbe9b29135bcf98149dfe1bc2595c2e Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 5 Oct 2022 15:11:12 +0300 Subject: [PATCH 2/5] [#1840] blobstor: Return `Path` from components Signed-off-by: Evgenii Stratonikov --- .../blobstor/blobovniczatree/blobovnicza.go | 5 +++++ pkg/local_object_storage/blobstor/common/storage.go | 1 + pkg/local_object_storage/blobstor/fstree/fstree.go | 5 +++++ 3 files changed, 11 insertions(+) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go b/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go index 0e7806d16be..e70ed06ae33 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go @@ -237,6 +237,11 @@ func (b *Blobovniczas) Type() string { return Type } +// Path implements common.Storage. +func (b *Blobovniczas) Path() string { + return b.rootPath +} + // SetCompressor implements common.Storage. func (b *Blobovniczas) SetCompressor(cc *compression.Config) { b.compression = cc diff --git a/pkg/local_object_storage/blobstor/common/storage.go b/pkg/local_object_storage/blobstor/common/storage.go index d6bea47a2de..85f8039a396 100644 --- a/pkg/local_object_storage/blobstor/common/storage.go +++ b/pkg/local_object_storage/blobstor/common/storage.go @@ -10,6 +10,7 @@ type Storage interface { Close() error Type() string + Path() string SetCompressor(cc *compression.Config) Get(GetPrm) (GetRes, error) diff --git a/pkg/local_object_storage/blobstor/fstree/fstree.go b/pkg/local_object_storage/blobstor/fstree/fstree.go index a2ab55c459d..601d772aecf 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree.go @@ -347,6 +347,11 @@ func (*FSTree) Type() string { return Type } +// Path implements common.Storage. +func (t *FSTree) Path() string { + return t.RootPath +} + // SetCompressor implements common.Storage. func (t *FSTree) SetCompressor(cc *compression.Config) { t.Config = cc From 56321b8c6bca1671a5d2ff35a103d6c1b817a79f Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 5 Oct 2022 15:18:01 +0300 Subject: [PATCH 3/5] [#1840] blobstor/test: Add tests for auxiliary functions Signed-off-by: Evgenii Stratonikov --- .../blobstor/blobovniczatree/generic_test.go | 17 ++++++++++++++--- .../blobstor/fstree/generic_test.go | 17 ++++++++++++++--- .../blobstor/internal/blobstortest/common.go | 6 ++++++ 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/generic_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/generic_test.go index b62c85774bd..5b60270ffc2 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/generic_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/generic_test.go @@ -16,9 +16,7 @@ func TestGeneric(t *testing.T) { defer func() { _ = os.RemoveAll(t.Name()) }() - var n int - newTree := func(t *testing.T) common.Storage { - dir := filepath.Join(t.Name(), strconv.Itoa(n)) + helper := func(t *testing.T, dir string) common.Storage { return NewBlobovniczaTree( WithLogger(zaptest.NewLogger(t)), WithObjectSizeLimit(maxObjectSize), @@ -28,7 +26,20 @@ func TestGeneric(t *testing.T) { WithBlobovniczaSize(1<<20)) } + var n int + newTree := func(t *testing.T) common.Storage { + dir := filepath.Join(t.Name(), strconv.Itoa(n)) + return helper(t, dir) + } + blobstortest.TestAll(t, newTree, 1024, maxObjectSize) + + t.Run("info", func(t *testing.T) { + dir := filepath.Join(t.Name(), "info") + blobstortest.TestInfo(t, func(t *testing.T) common.Storage { + return helper(t, dir) + }, Type, dir) + }) } func TestControl(t *testing.T) { diff --git a/pkg/local_object_storage/blobstor/fstree/generic_test.go b/pkg/local_object_storage/blobstor/fstree/generic_test.go index 173611cc46d..eae12d2892a 100644 --- a/pkg/local_object_storage/blobstor/fstree/generic_test.go +++ b/pkg/local_object_storage/blobstor/fstree/generic_test.go @@ -13,16 +13,27 @@ import ( func TestGeneric(t *testing.T) { defer func() { _ = os.RemoveAll(t.Name()) }() - var n int - newTree := func(t *testing.T) common.Storage { - dir := filepath.Join(t.Name(), strconv.Itoa(n)) + helper := func(t *testing.T, dir string) common.Storage { return New( WithPath(dir), WithDepth(2), WithDirNameLen(2)) } + var n int + newTree := func(t *testing.T) common.Storage { + dir := filepath.Join(t.Name(), strconv.Itoa(n)) + return helper(t, dir) + } + blobstortest.TestAll(t, newTree, 2048, 16*1024) + + t.Run("info", func(t *testing.T) { + dir := filepath.Join(t.Name(), "info") + blobstortest.TestInfo(t, func(t *testing.T) common.Storage { + return helper(t, dir) + }, Type, dir) + }) } func TestControl(t *testing.T) { diff --git a/pkg/local_object_storage/blobstor/internal/blobstortest/common.go b/pkg/local_object_storage/blobstor/internal/blobstortest/common.go index 7e858d3b93b..0d3a79e8e05 100644 --- a/pkg/local_object_storage/blobstor/internal/blobstortest/common.go +++ b/pkg/local_object_storage/blobstor/internal/blobstortest/common.go @@ -43,6 +43,12 @@ func TestAll(t *testing.T, cons Constructor, min, max uint64) { }) } +func TestInfo(t *testing.T, cons Constructor, expectedType string, expectedPath string) { + s := cons(t) + require.Equal(t, expectedType, s.Type()) + require.Equal(t, expectedPath, s.Path()) +} + func prepare(t *testing.T, count int, s common.Storage, min, max uint64) []objectDesc { objects := make([]objectDesc, count) From 5e20a5b4e277089a5f18de46b76416f46c474239 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 5 Oct 2022 15:41:36 +0300 Subject: [PATCH 4/5] [#1840] blobstor: Return info about all components Signed-off-by: Evgenii Stratonikov --- cmd/neofs-cli/modules/control/shards_list.go | 12 +- pkg/local_object_storage/blobstor/blobstor.go | 12 +- pkg/local_object_storage/blobstor/info.go | 15 +- pkg/local_object_storage/engine/error_test.go | 4 +- .../shard/control_test.go | 16 +- pkg/services/control/server/list_shards.go | 14 +- pkg/services/control/service_test.go | 19 +- pkg/services/control/types.go | 5 - pkg/services/control/types.pb.go | 181 +++++++++++++----- pkg/services/control/types.proto | 12 +- pkg/services/control/types_neofs.pb.go | 38 +++- pkg/services/control/types_test.go | 6 +- 12 files changed, 246 insertions(+), 88 deletions(-) diff --git a/cmd/neofs-cli/modules/control/shards_list.go b/cmd/neofs-cli/modules/control/shards_list.go index 4d4eef63a7a..879b712b018 100644 --- a/cmd/neofs-cli/modules/control/shards_list.go +++ b/cmd/neofs-cli/modules/control/shards_list.go @@ -4,6 +4,7 @@ import ( "bytes" "encoding/json" "fmt" + "strings" "github.com/mr-tron/base58" rawclient "github.com/nspcc-dev/neofs-api-go/v2/rpc/client" @@ -65,7 +66,7 @@ func prettyPrintShardsJSON(cmd *cobra.Command, ii []*control.ShardInfo) { "shard_id": base58.Encode(i.Shard_ID), "mode": shardModeToString(i.GetMode()), "metabase": i.GetMetabasePath(), - "blobstor": i.GetBlobstorPath(), + "blobstor": i.GetBlobstor(), "writecache": i.GetWritecachePath(), "error_count": i.GetErrorCount(), }) @@ -89,9 +90,16 @@ func prettyPrintShards(cmd *cobra.Command, ii []*control.ShardInfo) { return fmt.Sprintf("%s: %s\n", name, path) } + var sb strings.Builder + sb.WriteString("Blobstor:\n") + for j, info := range i.GetBlobstor() { + sb.WriteString(fmt.Sprintf("\tPath %d: %s\n\tType %d: %s\n", + j, info.GetPath(), j, info.GetType())) + } + cmd.Printf("Shard %s:\nMode: %s\n"+ pathPrinter("Metabase", i.GetMetabasePath())+ - pathPrinter("Blobstor", i.GetBlobstorPath())+ + sb.String()+ pathPrinter("Write-cache", i.GetWritecachePath())+ pathPrinter("Pilorama", i.GetPiloramaPath())+ fmt.Sprintf("Error count: %d\n", i.GetErrorCount()), diff --git a/pkg/local_object_storage/blobstor/blobstor.go b/pkg/local_object_storage/blobstor/blobstor.go index 4d8bd94f93c..0480db0d297 100644 --- a/pkg/local_object_storage/blobstor/blobstor.go +++ b/pkg/local_object_storage/blobstor/blobstor.go @@ -5,7 +5,6 @@ import ( "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/common" "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/compression" - "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/fstree" "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/shard/mode" "github.com/nspcc-dev/neofs-node/pkg/util/logger" objectSDK "github.com/nspcc-dev/neofs-sdk-go/object" @@ -26,7 +25,16 @@ type BlobStor struct { mode mode.Mode } -type Info = fstree.Info +// Info contains information about blobstor. +type Info struct { + SubStorages []SubStorageInfo +} + +// SubStorageInfo contains information about blobstor storage component. +type SubStorageInfo struct { + Type string + Path string +} // Option represents BlobStor's constructor option. type Option func(*cfg) diff --git a/pkg/local_object_storage/blobstor/info.go b/pkg/local_object_storage/blobstor/info.go index 60a143ce18b..e3e790ebc8a 100644 --- a/pkg/local_object_storage/blobstor/info.go +++ b/pkg/local_object_storage/blobstor/info.go @@ -1,13 +1,14 @@ package blobstor -import "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/fstree" - // DumpInfo returns information about blob stor. -func (b *BlobStor) DumpInfo() fstree.Info { +func (b *BlobStor) DumpInfo() Info { + sub := make([]SubStorageInfo, len(b.storage)) for i := range b.storage { - if b.storage[i].Storage.Type() == "fstree" { - return b.storage[i].Storage.(*fstree.FSTree).Info - } + sub[i].Path = b.storage[i].Storage.Path() + sub[i].Type = b.storage[i].Storage.Type() + } + + return Info{ + SubStorages: sub, } - return fstree.Info{} } diff --git a/pkg/local_object_storage/engine/error_test.go b/pkg/local_object_storage/engine/error_test.go index 2439d667b94..ccbe8c04ef3 100644 --- a/pkg/local_object_storage/engine/error_test.go +++ b/pkg/local_object_storage/engine/error_test.go @@ -167,8 +167,8 @@ func TestBlobstorFailback(t *testing.T) { checkShardState(t, e, id[0], 0, mode.ReadWrite) require.NoError(t, e.Close()) - p1 := e.shards[id[0].String()].Shard.DumpInfo().BlobStorInfo.RootPath - p2 := e.shards[id[1].String()].Shard.DumpInfo().BlobStorInfo.RootPath + p1 := e.shards[id[0].String()].Shard.DumpInfo().BlobStorInfo.SubStorages[1].Path + p2 := e.shards[id[1].String()].Shard.DumpInfo().BlobStorInfo.SubStorages[1].Path tmp := filepath.Join(dir, "tmp") require.NoError(t, os.Rename(p1, tmp)) require.NoError(t, os.Rename(p2, p1)) diff --git a/pkg/local_object_storage/shard/control_test.go b/pkg/local_object_storage/shard/control_test.go index 01aa3f67f5f..eb9d2a3ff31 100644 --- a/pkg/local_object_storage/shard/control_test.go +++ b/pkg/local_object_storage/shard/control_test.go @@ -82,13 +82,14 @@ func TestShardOpen(t *testing.T) { func TestRefillMetabaseCorrupted(t *testing.T) { dir := t.TempDir() + fsTree := fstree.New( + fstree.WithDirNameLen(2), + fstree.WithPath(filepath.Join(dir, "blob")), + fstree.WithDepth(1)) blobOpts := []blobstor.Option{ blobstor.WithStorages([]blobstor.SubStorage{ { - Storage: fstree.New( - fstree.WithDirNameLen(2), - fstree.WithPath(filepath.Join(dir, "blob")), - fstree.WithDepth(1)), + Storage: fsTree, }, }), } @@ -111,12 +112,7 @@ func TestRefillMetabaseCorrupted(t *testing.T) { require.NoError(t, sh.Close()) addr := object.AddressOf(obj) - fs := fstree.FSTree{ - DirNameLen: 2, - Depth: 1, - Info: sh.blobStor.DumpInfo(), - } - _, err = fs.Put(common.PutPrm{Address: addr, RawData: []byte("not an object")}) + _, err = fsTree.Put(common.PutPrm{Address: addr, RawData: []byte("not an object")}) require.NoError(t, err) sh = New( diff --git a/pkg/services/control/server/list_shards.go b/pkg/services/control/server/list_shards.go index 11a66dcd5db..0e21d90282b 100644 --- a/pkg/services/control/server/list_shards.go +++ b/pkg/services/control/server/list_shards.go @@ -3,6 +3,7 @@ package control import ( "context" + "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor" "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/shard/mode" "github.com/nspcc-dev/neofs-node/pkg/services/control" "google.golang.org/grpc/codes" @@ -30,7 +31,7 @@ func (s *Server) ListShards(_ context.Context, req *control.ListShardsRequest) ( si.SetID(*sh.ID) si.SetMetabasePath(sh.MetaBaseInfo.Path) - si.SetBlobstorPath(sh.BlobStorInfo.RootPath) + si.Blobstor = blobstorInfoToProto(sh.BlobStorInfo) si.SetWriteCachePath(sh.WriteCacheInfo.Path) si.SetPiloramaPath(sh.PiloramaInfo.Path) @@ -64,3 +65,14 @@ func (s *Server) ListShards(_ context.Context, req *control.ListShardsRequest) ( return resp, nil } + +func blobstorInfoToProto(info blobstor.Info) []*control.BlobstorInfo { + res := make([]*control.BlobstorInfo, len(info.SubStorages)) + for i := range info.SubStorages { + res[i] = &control.BlobstorInfo{ + Path: info.SubStorages[i].Path, + Type: info.SubStorages[i].Type, + } + } + return res +} diff --git a/pkg/services/control/service_test.go b/pkg/services/control/service_test.go index b64e67d7b72..8c5f3279ce1 100644 --- a/pkg/services/control/service_test.go +++ b/pkg/services/control/service_test.go @@ -77,18 +77,21 @@ func equalListShardResponseBodies(b1, b2 *control.ListShardsResponse_Body) bool for i := range b1.Shards { if b1.Shards[i].GetMetabasePath() != b2.Shards[i].GetMetabasePath() || - b1.Shards[i].GetBlobstorPath() != b2.Shards[i].GetBlobstorPath() || b1.Shards[i].GetWritecachePath() != b2.Shards[i].GetWritecachePath() || b1.Shards[i].GetPiloramaPath() != b2.Shards[i].GetPiloramaPath() || !bytes.Equal(b1.Shards[i].GetShard_ID(), b2.Shards[i].GetShard_ID()) { return false } + + info1 := b1.Shards[i].GetBlobstor() + info2 := b2.Shards[i].GetBlobstor() + return compareBlobstorInfo(info1, info2) } for i := range b1.Shards { for j := i + 1; j < len(b1.Shards); j++ { if b1.Shards[i].GetMetabasePath() == b2.Shards[j].GetMetabasePath() || - b1.Shards[i].GetBlobstorPath() == b2.Shards[j].GetBlobstorPath() || + !compareBlobstorInfo(b1.Shards[i].Blobstor, b2.Shards[i].Blobstor) || b1.Shards[i].GetWritecachePath() == b2.Shards[j].GetWritecachePath() || bytes.Equal(b1.Shards[i].GetShard_ID(), b2.Shards[j].GetShard_ID()) { return false @@ -98,6 +101,18 @@ func equalListShardResponseBodies(b1, b2 *control.ListShardsResponse_Body) bool return true } +func compareBlobstorInfo(a, b []*control.BlobstorInfo) bool { + if len(a) != len(b) { + return false + } + for i := range a { + if a[i].Type != b[i].Type || + a[i].Path != b[i].Path { + return false + } + } + return true +} func generateListShardsResponseBody() *control.ListShardsResponse_Body { body := new(control.ListShardsResponse_Body) diff --git a/pkg/services/control/types.go b/pkg/services/control/types.go index 406a1896af3..13bd87ed56b 100644 --- a/pkg/services/control/types.go +++ b/pkg/services/control/types.go @@ -97,11 +97,6 @@ func (x *ShardInfo) SetMetabasePath(v string) { x.MetabasePath = v } -// SetBlobstorPath sets path to shard's blobstor. -func (x *ShardInfo) SetBlobstorPath(v string) { - x.BlobstorPath = v -} - // SetWriteCachePath sets path to shard's write-cache. func (x *ShardInfo) SetWriteCachePath(v string) { x.WritecachePath = v diff --git a/pkg/services/control/types.pb.go b/pkg/services/control/types.pb.go index 7056a225f38..0f40deb509f 100644 --- a/pkg/services/control/types.pb.go +++ b/pkg/services/control/types.pb.go @@ -400,8 +400,8 @@ type ShardInfo struct { Shard_ID []byte `protobuf:"bytes,1,opt,name=shard_ID,json=shardID,proto3" json:"shard_ID,omitempty"` // Path to shard's metabase. MetabasePath string `protobuf:"bytes,2,opt,name=metabase_path,json=metabasePath,proto3" json:"metabase_path,omitempty"` - // Path to shard's blobstor. - BlobstorPath string `protobuf:"bytes,3,opt,name=blobstor_path,json=blobstorPath,proto3" json:"blobstor_path,omitempty"` + // Shard's blobstor info. + Blobstor []*BlobstorInfo `protobuf:"bytes,3,rep,name=blobstor,proto3" json:"blobstor,omitempty"` // Path to shard's write-cache, empty if disabled. WritecachePath string `protobuf:"bytes,4,opt,name=writecache_path,json=writecachePath,proto3" json:"writecache_path,omitempty"` // Work mode of the shard. @@ -458,11 +458,11 @@ func (x *ShardInfo) GetMetabasePath() string { return "" } -func (x *ShardInfo) GetBlobstorPath() string { +func (x *ShardInfo) GetBlobstor() []*BlobstorInfo { if x != nil { - return x.BlobstorPath + return x.Blobstor } - return "" + return nil } func (x *ShardInfo) GetWritecachePath() string { @@ -493,6 +493,64 @@ func (x *ShardInfo) GetPiloramaPath() string { return "" } +// Blobstor component description. +type BlobstorInfo struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Path to the root. + Path string `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"` + // Component type. + Type string `protobuf:"bytes,2,opt,name=type,proto3" json:"type,omitempty"` +} + +func (x *BlobstorInfo) Reset() { + *x = BlobstorInfo{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_control_types_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *BlobstorInfo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BlobstorInfo) ProtoMessage() {} + +func (x *BlobstorInfo) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_control_types_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 BlobstorInfo.ProtoReflect.Descriptor instead. +func (*BlobstorInfo) Descriptor() ([]byte, []int) { + return file_pkg_services_control_types_proto_rawDescGZIP(), []int{4} +} + +func (x *BlobstorInfo) GetPath() string { + if x != nil { + return x.Path + } + return "" +} + +func (x *BlobstorInfo) GetType() string { + if x != nil { + return x.Type + } + return "" +} + // Administrator-defined Attributes of the NeoFS Storage Node. // // `Attribute` is a Key-Value metadata pair. Key name must be a valid UTF-8 @@ -549,7 +607,7 @@ type NodeInfo_Attribute struct { func (x *NodeInfo_Attribute) Reset() { *x = NodeInfo_Attribute{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_types_proto_msgTypes[4] + mi := &file_pkg_services_control_types_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -562,7 +620,7 @@ func (x *NodeInfo_Attribute) String() string { func (*NodeInfo_Attribute) ProtoMessage() {} func (x *NodeInfo_Attribute) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_types_proto_msgTypes[4] + mi := &file_pkg_services_control_types_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -629,44 +687,49 @@ var file_pkg_services_control_types_proto_rawDesc = []byte{ 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x27, 0x0a, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, - 0x86, 0x02, 0x0a, 0x09, 0x53, 0x68, 0x61, 0x72, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x19, 0x0a, + 0x94, 0x02, 0x0a, 0x09, 0x53, 0x68, 0x61, 0x72, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x65, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0c, 0x6d, 0x65, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x23, 0x0a, - 0x0d, 0x62, 0x6c, 0x6f, 0x62, 0x73, 0x74, 0x6f, 0x72, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x62, 0x6c, 0x6f, 0x62, 0x73, 0x74, 0x6f, 0x72, 0x50, 0x61, - 0x74, 0x68, 0x12, 0x27, 0x0a, 0x0f, 0x77, 0x72, 0x69, 0x74, 0x65, 0x63, 0x61, 0x63, 0x68, 0x65, - 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x77, 0x72, 0x69, - 0x74, 0x65, 0x63, 0x61, 0x63, 0x68, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x26, 0x0a, 0x04, 0x6d, - 0x6f, 0x64, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x6d, - 0x6f, 0x64, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x75, 0x6e, - 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, - 0x75, 0x6e, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x69, 0x6c, 0x6f, 0x72, 0x61, 0x6d, 0x61, 0x5f, - 0x70, 0x61, 0x74, 0x68, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x69, 0x6c, 0x6f, - 0x72, 0x61, 0x6d, 0x61, 0x50, 0x61, 0x74, 0x68, 0x2a, 0x4e, 0x0a, 0x0c, 0x4e, 0x65, 0x74, 0x6d, - 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x14, 0x0a, 0x10, 0x53, 0x54, 0x41, 0x54, - 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x44, 0x45, 0x46, 0x49, 0x4e, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0a, - 0x0a, 0x06, 0x4f, 0x4e, 0x4c, 0x49, 0x4e, 0x45, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x4f, 0x46, - 0x46, 0x4c, 0x49, 0x4e, 0x45, 0x10, 0x02, 0x12, 0x0f, 0x0a, 0x0b, 0x4d, 0x41, 0x49, 0x4e, 0x54, - 0x45, 0x4e, 0x41, 0x4e, 0x43, 0x45, 0x10, 0x03, 0x2a, 0x57, 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, 0x2a, 0x6a, 0x0a, 0x09, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x18, - 0x0a, 0x14, 0x53, 0x48, 0x41, 0x52, 0x44, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x44, - 0x45, 0x46, 0x49, 0x4e, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x52, 0x45, 0x41, 0x44, - 0x5f, 0x57, 0x52, 0x49, 0x54, 0x45, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x52, 0x45, 0x41, 0x44, - 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x02, 0x12, 0x0c, 0x0a, 0x08, 0x44, 0x45, 0x47, 0x52, 0x41, - 0x44, 0x45, 0x44, 0x10, 0x03, 0x12, 0x16, 0x0a, 0x12, 0x44, 0x45, 0x47, 0x52, 0x41, 0x44, 0x45, - 0x44, 0x5f, 0x52, 0x45, 0x41, 0x44, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x04, 0x42, 0x36, 0x5a, - 0x34, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6e, 0x73, 0x70, 0x63, - 0x63, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x6e, 0x65, 0x6f, 0x66, 0x73, 0x2d, 0x6e, 0x6f, 0x64, 0x65, - 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x0c, 0x6d, 0x65, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x31, 0x0a, + 0x08, 0x62, 0x6c, 0x6f, 0x62, 0x73, 0x74, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x15, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x42, 0x6c, 0x6f, 0x62, 0x73, 0x74, + 0x6f, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x08, 0x62, 0x6c, 0x6f, 0x62, 0x73, 0x74, 0x6f, 0x72, + 0x12, 0x27, 0x0a, 0x0f, 0x77, 0x72, 0x69, 0x74, 0x65, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x70, + 0x61, 0x74, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x77, 0x72, 0x69, 0x74, 0x65, + 0x63, 0x61, 0x63, 0x68, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x26, 0x0a, 0x04, 0x6d, 0x6f, 0x64, + 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2e, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x6d, 0x6f, 0x64, + 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x75, 0x6e, + 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x69, 0x6c, 0x6f, 0x72, 0x61, 0x6d, 0x61, 0x5f, 0x70, 0x61, + 0x74, 0x68, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x69, 0x6c, 0x6f, 0x72, 0x61, + 0x6d, 0x61, 0x50, 0x61, 0x74, 0x68, 0x22, 0x36, 0x0a, 0x0c, 0x42, 0x6c, 0x6f, 0x62, 0x73, 0x74, + 0x6f, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, + 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x2a, 0x4e, + 0x0a, 0x0c, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x14, + 0x0a, 0x10, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x44, 0x45, 0x46, 0x49, 0x4e, + 0x45, 0x44, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x4f, 0x4e, 0x4c, 0x49, 0x4e, 0x45, 0x10, 0x01, + 0x12, 0x0b, 0x0a, 0x07, 0x4f, 0x46, 0x46, 0x4c, 0x49, 0x4e, 0x45, 0x10, 0x02, 0x12, 0x0f, 0x0a, + 0x0b, 0x4d, 0x41, 0x49, 0x4e, 0x54, 0x45, 0x4e, 0x41, 0x4e, 0x43, 0x45, 0x10, 0x03, 0x2a, 0x57, + 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, 0x2a, 0x6a, 0x0a, 0x09, 0x53, 0x68, 0x61, 0x72, 0x64, + 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x14, 0x53, 0x48, 0x41, 0x52, 0x44, 0x5f, 0x4d, 0x4f, + 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x44, 0x45, 0x46, 0x49, 0x4e, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0e, + 0x0a, 0x0a, 0x52, 0x45, 0x41, 0x44, 0x5f, 0x57, 0x52, 0x49, 0x54, 0x45, 0x10, 0x01, 0x12, 0x0d, + 0x0a, 0x09, 0x52, 0x45, 0x41, 0x44, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x02, 0x12, 0x0c, 0x0a, + 0x08, 0x44, 0x45, 0x47, 0x52, 0x41, 0x44, 0x45, 0x44, 0x10, 0x03, 0x12, 0x16, 0x0a, 0x12, 0x44, + 0x45, 0x47, 0x52, 0x41, 0x44, 0x45, 0x44, 0x5f, 0x52, 0x45, 0x41, 0x44, 0x5f, 0x4f, 0x4e, 0x4c, + 0x59, 0x10, 0x04, 0x42, 0x36, 0x5a, 0x34, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, + 0x6d, 0x2f, 0x6e, 0x73, 0x70, 0x63, 0x63, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x6e, 0x65, 0x6f, 0x66, + 0x73, 0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x33, } var ( @@ -682,7 +745,7 @@ func file_pkg_services_control_types_proto_rawDescGZIP() []byte { } var file_pkg_services_control_types_proto_enumTypes = make([]protoimpl.EnumInfo, 3) -var file_pkg_services_control_types_proto_msgTypes = make([]protoimpl.MessageInfo, 5) +var file_pkg_services_control_types_proto_msgTypes = make([]protoimpl.MessageInfo, 6) var file_pkg_services_control_types_proto_goTypes = []interface{}{ (NetmapStatus)(0), // 0: control.NetmapStatus (HealthStatus)(0), // 1: control.HealthStatus @@ -691,18 +754,20 @@ var file_pkg_services_control_types_proto_goTypes = []interface{}{ (*NodeInfo)(nil), // 4: control.NodeInfo (*Netmap)(nil), // 5: control.Netmap (*ShardInfo)(nil), // 6: control.ShardInfo - (*NodeInfo_Attribute)(nil), // 7: control.NodeInfo.Attribute + (*BlobstorInfo)(nil), // 7: control.BlobstorInfo + (*NodeInfo_Attribute)(nil), // 8: control.NodeInfo.Attribute } var file_pkg_services_control_types_proto_depIdxs = []int32{ - 7, // 0: control.NodeInfo.attributes:type_name -> control.NodeInfo.Attribute + 8, // 0: control.NodeInfo.attributes:type_name -> control.NodeInfo.Attribute 0, // 1: control.NodeInfo.state:type_name -> control.NetmapStatus 4, // 2: control.Netmap.nodes:type_name -> control.NodeInfo - 2, // 3: control.ShardInfo.mode:type_name -> control.ShardMode - 4, // [4:4] is the sub-list for method output_type - 4, // [4:4] is the sub-list for method input_type - 4, // [4:4] is the sub-list for extension type_name - 4, // [4:4] is the sub-list for extension extendee - 0, // [0:4] is the sub-list for field type_name + 7, // 3: control.ShardInfo.blobstor:type_name -> control.BlobstorInfo + 2, // 4: control.ShardInfo.mode:type_name -> control.ShardMode + 5, // [5:5] is the sub-list for method output_type + 5, // [5:5] is the sub-list for method input_type + 5, // [5:5] is the sub-list for extension type_name + 5, // [5:5] is the sub-list for extension extendee + 0, // [0:5] is the sub-list for field type_name } func init() { file_pkg_services_control_types_proto_init() } @@ -760,6 +825,18 @@ func file_pkg_services_control_types_proto_init() { } } file_pkg_services_control_types_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*BlobstorInfo); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_control_types_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*NodeInfo_Attribute); i { case 0: return &v.state @@ -778,7 +855,7 @@ func file_pkg_services_control_types_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_pkg_services_control_types_proto_rawDesc, NumEnums: 3, - NumMessages: 5, + NumMessages: 6, NumExtensions: 0, NumServices: 0, }, diff --git a/pkg/services/control/types.proto b/pkg/services/control/types.proto index 0729e4ebb88..1994e24489f 100644 --- a/pkg/services/control/types.proto +++ b/pkg/services/control/types.proto @@ -128,8 +128,8 @@ message ShardInfo { // Path to shard's metabase. string metabase_path = 2 [json_name = "metabasePath"]; - // Path to shard's blobstor. - string blobstor_path = 3 [json_name = "blobstorPath"]; + // Shard's blobstor info. + repeated BlobstorInfo blobstor = 3 [json_name = "blobstor"]; // Path to shard's write-cache, empty if disabled. string writecache_path = 4 [json_name = "writecachePath"]; @@ -144,6 +144,14 @@ message ShardInfo { string pilorama_path = 7 [json_name = "piloramaPath"]; } +// Blobstor component description. +message BlobstorInfo { + // Path to the root. + string path = 1 [json_name = "path"]; + // Component type. + string type = 2 [json_name = "type"]; +} + // Work mode of the shard. enum ShardMode { // Undefined mode, default value. diff --git a/pkg/services/control/types_neofs.pb.go b/pkg/services/control/types_neofs.pb.go index 8dd46362eb5..148f1869c10 100644 --- a/pkg/services/control/types_neofs.pb.go +++ b/pkg/services/control/types_neofs.pb.go @@ -144,7 +144,9 @@ func (x *Netmap) StableMarshal(buf []byte) []byte { func (x *ShardInfo) StableSize() (size int) { size += proto.BytesSize(1, x.Shard_ID) size += proto.StringSize(2, x.MetabasePath) - size += proto.StringSize(3, x.BlobstorPath) + for i := range x.Blobstor { + size += proto.NestedStructureSize(3, x.Blobstor[i]) + } size += proto.StringSize(4, x.WritecachePath) size += proto.EnumSize(5, int32(x.Mode)) size += proto.UInt32Size(6, x.ErrorCount) @@ -170,10 +172,42 @@ func (x *ShardInfo) StableMarshal(buf []byte) []byte { var offset int offset += proto.BytesMarshal(1, buf[offset:], x.Shard_ID) offset += proto.StringMarshal(2, buf[offset:], x.MetabasePath) - offset += proto.StringMarshal(3, buf[offset:], x.BlobstorPath) + for i := range x.Blobstor { + offset += proto.NestedStructureMarshal(3, buf[offset:], x.Blobstor[i]) + } offset += proto.StringMarshal(4, buf[offset:], x.WritecachePath) offset += proto.EnumMarshal(5, buf[offset:], int32(x.Mode)) offset += proto.UInt32Marshal(6, buf[offset:], x.ErrorCount) offset += proto.StringMarshal(7, buf[offset:], x.PiloramaPath) return buf } + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *BlobstorInfo) StableSize() (size int) { + size += proto.StringSize(1, x.Path) + size += proto.StringSize(2, x.Type) + 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 *BlobstorInfo) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + if buf == nil { + buf = make([]byte, x.StableSize()) + } + var offset int + offset += proto.StringMarshal(1, buf[offset:], x.Path) + offset += proto.StringMarshal(2, buf[offset:], x.Type) + return buf +} diff --git a/pkg/services/control/types_test.go b/pkg/services/control/types_test.go index 40a0d17a90f..79b6da8e638 100644 --- a/pkg/services/control/types_test.go +++ b/pkg/services/control/types_test.go @@ -7,6 +7,8 @@ import ( "testing" "github.com/google/uuid" + "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/blobovniczatree" + "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/fstree" "github.com/nspcc-dev/neofs-node/pkg/services/control" ) @@ -138,7 +140,9 @@ func generateShardInfo(id int) *control.ShardInfo { si.SetID(bin) si.SetMode(control.ShardMode_READ_WRITE) si.SetMetabasePath(filepath.Join(path, "meta")) - si.SetBlobstorPath(filepath.Join(path, "blobstor")) + si.Blobstor = []*control.BlobstorInfo{ + {Type: fstree.Type, Path: filepath.Join(path, "fstree")}, + {Type: blobovniczatree.Type, Path: filepath.Join(path, "blobtree")}} si.SetWriteCachePath(filepath.Join(path, "writecache")) si.SetPiloramaPath(filepath.Join(path, "pilorama")) From 96f35f79194db74d27881528de8c26f5a8baaab0 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 5 Oct 2022 15:53:42 +0300 Subject: [PATCH 5/5] [#1840] neofs-node: Use blobstor paths to identify shard Signed-off-by: Evgenii Stratonikov --- cmd/neofs-node/config.go | 30 +++++++++++---- pkg/local_object_storage/engine/control.go | 38 +++++++++++++------ .../engine/control_test.go | 9 ++--- 3 files changed, 52 insertions(+), 25 deletions(-) diff --git a/cmd/neofs-node/config.go b/cmd/neofs-node/config.go index e2effd6a529..99d96d6751c 100644 --- a/cmd/neofs-node/config.go +++ b/cmd/neofs-node/config.go @@ -8,6 +8,8 @@ import ( "net" "os" "os/signal" + "path/filepath" + "strings" "sync" atomicstd "sync/atomic" "syscall" @@ -135,6 +137,18 @@ type shardCfg struct { } } +// id returns persistent id of a shard. It is different from the ID used in runtime +// and is primarily used to identify shards in the configuration. +func (c *shardCfg) id() string { + // This calculation should be kept in sync with + // pkg/local_object_storage/engine/control.go file. + var sb strings.Builder + for i := range c.subStorages { + sb.WriteString(filepath.Clean(c.subStorages[i].path)) + } + return sb.String() +} + type subStorageCfg struct { // common for all storages typ string @@ -597,13 +611,13 @@ func (c *cfg) engineOpts() []engine.Option { return opts } -type shardOptsWithMetaPath struct { - metaPath string +type shardOptsWithID struct { + configID string shOpts []shard.Option } -func (c *cfg) shardOpts() []shardOptsWithMetaPath { - shards := make([]shardOptsWithMetaPath, 0, len(c.EngineCfg.shards)) +func (c *cfg) shardOpts() []shardOptsWithID { + shards := make([]shardOptsWithID, 0, len(c.EngineCfg.shards)) for _, shCfg := range c.EngineCfg.shards { var writeCacheOpts []writecache.Option @@ -666,8 +680,8 @@ func (c *cfg) shardOpts() []shardOptsWithMetaPath { } } - var sh shardOptsWithMetaPath - sh.metaPath = shCfg.metaCfg.path + var sh shardOptsWithID + sh.configID = shCfg.id() sh.shOpts = []shard.Option{ shard.WithLogger(c.log), shard.WithRefillMetabase(shCfg.refillMetabase), @@ -834,8 +848,8 @@ func (c *cfg) configWatcher(ctx context.Context) { } var rcfg engine.ReConfiguration - for _, optsWithMeta := range c.shardOpts() { - rcfg.AddShard(optsWithMeta.metaPath, optsWithMeta.shOpts) + for _, optsWithID := range c.shardOpts() { + rcfg.AddShard(optsWithID.configID, optsWithID.shOpts) } err = c.cfgObject.cfgLocalStorage.localStorage.Reload(rcfg) diff --git a/pkg/local_object_storage/engine/control.go b/pkg/local_object_storage/engine/control.go index e1f632d8243..216267cb9e0 100644 --- a/pkg/local_object_storage/engine/control.go +++ b/pkg/local_object_storage/engine/control.go @@ -3,6 +3,8 @@ package engine import ( "errors" "fmt" + "path/filepath" + "strings" "sync" "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor" @@ -217,18 +219,18 @@ func (rCfg *ReConfiguration) SetShardPoolSize(shardPoolSize uint32) { rCfg.shardPoolSize = shardPoolSize } -// AddShard adds a shard for the reconfiguration. Path to a metabase is used as -// an identifier of the shard in configuration. -func (rCfg *ReConfiguration) AddShard(metaPath string, opts []shard.Option) { +// AddShard adds a shard for the reconfiguration. +// Shard identifier is calculated from paths used in blobstor. +func (rCfg *ReConfiguration) AddShard(id string, opts []shard.Option) { if rCfg.shards == nil { rCfg.shards = make(map[string][]shard.Option) } - if _, found := rCfg.shards[metaPath]; found { + if _, found := rCfg.shards[id]; found { return } - rCfg.shards[metaPath] = opts + rCfg.shards[id] = opts } // Reload reloads StorageEngine's configuration in runtime. @@ -240,24 +242,26 @@ func (e *StorageEngine) Reload(rcfg ReConfiguration) error { // mark removed shards for removal for id, sh := range e.shards { - _, ok := rcfg.shards[sh.Shard.DumpInfo().MetaBaseInfo.Path] + _, ok := rcfg.shards[calculateShardID(sh.DumpInfo())] if !ok { shardsToRemove = append(shardsToRemove, id) } } // mark new shards for addition - for newPath := range rcfg.shards { + for newID := range rcfg.shards { addShard := true for _, sh := range e.shards { - if newPath == sh.Shard.DumpInfo().MetaBaseInfo.Path { + // This calculation should be kept in sync with node + // configuration parsing during SIGHUP. + if newID == calculateShardID(sh.DumpInfo()) { addShard = false break } } if addShard { - shardsToAdd = append(shardsToAdd, newPath) + shardsToAdd = append(shardsToAdd, newID) } } @@ -265,10 +269,10 @@ func (e *StorageEngine) Reload(rcfg ReConfiguration) error { e.removeShards(shardsToRemove...) - for _, newPath := range shardsToAdd { - sh, err := e.createShard(rcfg.shards[newPath]) + for _, newID := range shardsToAdd { + sh, err := e.createShard(rcfg.shards[newID]) if err != nil { - return fmt.Errorf("could not add new shard with '%s' metabase path: %w", newPath, err) + return fmt.Errorf("could not add new shard with '%s' metabase path: %w", newID, err) } idStr := sh.ID().String() @@ -293,3 +297,13 @@ func (e *StorageEngine) Reload(rcfg ReConfiguration) error { return nil } + +func calculateShardID(info shard.Info) string { + // This calculation should be kept in sync with node + // configuration parsing during SIGHUP. + var sb strings.Builder + for _, sub := range info.BlobStorInfo.SubStorages { + sb.WriteString(filepath.Clean(sub.Path)) + } + return sb.String() +} diff --git a/pkg/local_object_storage/engine/control_test.go b/pkg/local_object_storage/engine/control_test.go index 59750424b19..1d2dee6c031 100644 --- a/pkg/local_object_storage/engine/control_test.go +++ b/pkg/local_object_storage/engine/control_test.go @@ -147,19 +147,18 @@ func engineWithShards(t *testing.T, path string, num int) (*StorageEngine, []str e := New() for i := 0; i < num; i++ { - metaPath := filepath.Join(addPath, fmt.Sprintf("%d.metabase", i)) - currShards = append(currShards, metaPath) - - _, err := e.AddShard( + id, err := e.AddShard( shard.WithBlobStorOptions( blobstor.WithStorages(newStorages(filepath.Join(addPath, strconv.Itoa(i)), errSmallSize))), shard.WithMetaBaseOptions( - meta.WithPath(metaPath), + meta.WithPath(filepath.Join(addPath, fmt.Sprintf("%d.metabase", i))), meta.WithPermissions(0700), meta.WithEpochState(epochState{}), ), ) require.NoError(t, err) + + currShards = append(currShards, calculateShardID(e.shards[id.String()].DumpInfo())) } require.Equal(t, num, len(e.shards))