diff --git a/cmd/neofs-node/config/node/config.go b/cmd/neofs-node/config/node/config.go index d575f88f..adabeb16 100644 --- a/cmd/neofs-node/config/node/config.go +++ b/cmd/neofs-node/config/node/config.go @@ -145,3 +145,30 @@ func (p PersistentStateConfig) Path() string { return PersistentStatePathDefault } + +// SubnetConfig represents node configuration related to subnets. +type SubnetConfig config.Config + +// Init initializes SubnetConfig from "subnet" sub-section of "node" section +// of the root config. +func (x *SubnetConfig) Init(root config.Config) { + *x = SubnetConfig(*root.Sub(subsection).Sub("subnet")) +} + +// ExitZero returns value of "exit_zero" config parameter as bool. +// Returns false if value can not be cast. +func (x SubnetConfig) ExitZero() bool { + return config.BoolSafe((*config.Config)(&x), "exit_zero") +} + +// IterateSubnets casts value of "entries" config parameter to string slice, +// iterates over all of its elements and passes them to f. +// +// Does nothing if value can not be cast to string slice. +func (x SubnetConfig) IterateSubnets(f func(string)) { + ids := config.StringSliceSafe((*config.Config)(&x), "entries") + + for i := range ids { + f(ids[i]) + } +} diff --git a/cmd/neofs-node/config/node/config_test.go b/cmd/neofs-node/config/node/config_test.go index 2d09c4e3..827b57a7 100644 --- a/cmd/neofs-node/config/node/config_test.go +++ b/cmd/neofs-node/config/node/config_test.go @@ -35,6 +35,20 @@ func TestNodeSection(t *testing.T) { require.Empty(t, attribute) require.Equal(t, false, relay) require.Equal(t, PersistentStatePathDefault, persistatePath) + + var subnetCfg SubnetConfig + + subnetCfg.Init(*empty) + + require.False(t, subnetCfg.ExitZero()) + + called := false + + subnetCfg.IterateSubnets(func(string) { + called = true + }) + + require.False(t, called) }) const path = "../../../../config/example/node" @@ -99,6 +113,20 @@ func TestNodeSection(t *testing.T) { address.Uint160ToString(wKey.GetScriptHash())) require.Equal(t, "/state", persistatePath) + + var subnetCfg SubnetConfig + + subnetCfg.Init(*c) + + require.True(t, subnetCfg.ExitZero()) + + var ids []string + + subnetCfg.IterateSubnets(func(id string) { + ids = append(ids, id) + }) + + require.Equal(t, []string{"123", "456", "789"}, ids) } configtest.ForEachFileType(path, fileConfigTest) diff --git a/cmd/neofs-node/netmap.go b/cmd/neofs-node/netmap.go index 81b2048d..453b484d 100644 --- a/cmd/neofs-node/netmap.go +++ b/cmd/neofs-node/netmap.go @@ -8,6 +8,7 @@ import ( netmapV2 "github.com/nspcc-dev/neofs-api-go/v2/netmap" netmapGRPC "github.com/nspcc-dev/neofs-api-go/v2/netmap/grpc" "github.com/nspcc-dev/neofs-api-go/v2/refs" + nodeconfig "github.com/nspcc-dev/neofs-node/cmd/neofs-node/config/node" "github.com/nspcc-dev/neofs-node/pkg/core/netmap" "github.com/nspcc-dev/neofs-node/pkg/morph/client/netmap/wrapper" "github.com/nspcc-dev/neofs-node/pkg/morph/event" @@ -17,6 +18,7 @@ import ( "github.com/nspcc-dev/neofs-node/pkg/services/control" netmapService "github.com/nspcc-dev/neofs-node/pkg/services/netmap" netmapSDK "github.com/nspcc-dev/neofs-sdk-go/netmap" + subnetid "github.com/nspcc-dev/neofs-sdk-go/subnet/id" "go.uber.org/atomic" "go.uber.org/zap" ) @@ -87,6 +89,8 @@ func initNetmapService(c *cfg) { c.cfgNodeInfo.localInfo.SetAttributes(parseAttributes(c.appCfg)...) c.cfgNodeInfo.localInfo.SetState(netmapSDK.NodeStateOffline) + readSubnetCfg(c) + if c.cfgMorph.client == nil { initMorphComponents(c) } @@ -165,6 +169,29 @@ func initNetmapService(c *cfg) { } } +func readSubnetCfg(c *cfg) { + var subnetCfg nodeconfig.SubnetConfig + + subnetCfg.Init(*c.appCfg) + + var ( + id subnetid.ID + err error + ) + + subnetCfg.IterateSubnets(func(idTxt string) { + err = id.UnmarshalText([]byte(idTxt)) + fatalOnErrDetails("parse subnet entry", err) + + c.cfgNodeInfo.localInfo.EnterSubnet(id) + }) + + if subnetCfg.ExitZero() { + subnetid.MakeZero(&id) + c.cfgNodeInfo.localInfo.ExitSubnet(id) + } +} + // bootstrapNode adds current node to the Network map. // Must be called after initNetmapService. func bootstrapNode(c *cfg) { diff --git a/config/example/node.env b/config/example/node.env index 858c2f3a..e4e83f94 100644 --- a/config/example/node.env +++ b/config/example/node.env @@ -16,6 +16,8 @@ NEOFS_NODE_ATTRIBUTE_0=Price:11 NEOFS_NODE_ATTRIBUTE_1="UN-LOCODE:RU MSK" NEOFS_NODE_RELAY=true NEOFS_NODE_PERSISTENT_STATE_PATH=/state +NEOFS_NODE_SUBNET_EXIT_ZERO=true +NEOFS_NODE_SUBNET_ENTRIES=123 456 789 # gRPC section NEOFS_GRPC_NUM=2 diff --git a/config/example/node.json b/config/example/node.json index 4da27e54..a6213ef5 100644 --- a/config/example/node.json +++ b/config/example/node.json @@ -28,6 +28,14 @@ "relay": true, "persistent_state": { "path": "/state" + }, + "subnet": { + "exit_zero": true, + "entries": [ + "123", + "456", + "789" + ] } }, "grpc": { diff --git a/config/example/node.yaml b/config/example/node.yaml index 80a48b98..ddbe1756 100644 --- a/config/example/node.yaml +++ b/config/example/node.yaml @@ -25,6 +25,12 @@ node: relay: true # start Storage node in relay mode without bootstrapping into the Network map persistent_state: # path to persistent state file of Storage node path: /state + subnet: + exit_zero: true # toggle entrance to zero subnet (overrides corresponding attribute and occurrence in `entries`) + entries: # list of IDs of subnets to enter in a text format of NeoFS API protocol (overrides corresponding attributes) + - 123 + - 456 + - 789 grpc: num: 2 # total number of listener endpoints