forked from TrueCloudLab/frostfs-node
[#1764] neofs-node: Validate config before usage
Signed-off-by: Evgenii Stratonikov <evgeniy@morphbits.ru>
This commit is contained in:
parent
6f45cc81fc
commit
0fb5c51ac9
7 changed files with 153 additions and 15 deletions
|
@ -6,6 +6,7 @@ Changelog for NeoFS Node
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Changelog updates CI step (#1808)
|
- Changelog updates CI step (#1808)
|
||||||
|
- Validate storage node configuration before node startup (#1805)
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
|
|
@ -240,13 +240,7 @@ type cfgReputation struct {
|
||||||
|
|
||||||
var persistateSideChainLastBlockKey = []byte("side_chain_last_processed_block")
|
var persistateSideChainLastBlockKey = []byte("side_chain_last_processed_block")
|
||||||
|
|
||||||
func initCfg(path string) *cfg {
|
func initCfg(appCfg *config.Config) *cfg {
|
||||||
var p config.Prm
|
|
||||||
|
|
||||||
appCfg := config.New(p,
|
|
||||||
config.WithConfigFile(path),
|
|
||||||
)
|
|
||||||
|
|
||||||
key := nodeconfig.Key(appCfg)
|
key := nodeconfig.Key(appCfg)
|
||||||
|
|
||||||
var logPrm logger.Prm
|
var logPrm logger.Prm
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neofs-node/cmd/neofs-node/config"
|
||||||
"github.com/nspcc-dev/neofs-node/misc"
|
"github.com/nspcc-dev/neofs-node/misc"
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/services/control"
|
"github.com/nspcc-dev/neofs-node/pkg/services/control"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
@ -44,7 +45,12 @@ func main() {
|
||||||
os.Exit(SuccessReturnCode)
|
os.Exit(SuccessReturnCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
c := initCfg(*configFile)
|
appCfg := config.New(config.Prm{}, config.WithConfigFile(*configFile))
|
||||||
|
|
||||||
|
err := validateConfig(appCfg)
|
||||||
|
fatalOnErr(err)
|
||||||
|
|
||||||
|
c := initCfg(appCfg)
|
||||||
|
|
||||||
initApp(c)
|
initApp(c)
|
||||||
|
|
||||||
|
|
91
cmd/neofs-node/validate.go
Normal file
91
cmd/neofs-node/validate.go
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neofs-node/cmd/neofs-node/config"
|
||||||
|
engineconfig "github.com/nspcc-dev/neofs-node/cmd/neofs-node/config/engine"
|
||||||
|
shardconfig "github.com/nspcc-dev/neofs-node/cmd/neofs-node/config/engine/shard"
|
||||||
|
treeconfig "github.com/nspcc-dev/neofs-node/cmd/neofs-node/config/tree"
|
||||||
|
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/blobovniczatree"
|
||||||
|
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/fstree"
|
||||||
|
)
|
||||||
|
|
||||||
|
// validateConfig validates storage node configuration.
|
||||||
|
func validateConfig(c *config.Config) error {
|
||||||
|
shardNum := 0
|
||||||
|
paths := make(map[string]pathDescription)
|
||||||
|
return engineconfig.IterateShards(c, false, func(sc *shardconfig.Config) error {
|
||||||
|
if sc.WriteCache().Enabled() {
|
||||||
|
err := addPath(paths, "writecache", shardNum, sc.WriteCache().Path())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := addPath(paths, "metabase", shardNum, sc.Metabase().Path()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
treeConfig := treeconfig.Tree(c)
|
||||||
|
if treeConfig.Enabled() {
|
||||||
|
err := addPath(paths, "pilorama", shardNum, sc.Pilorama().Path())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
blobstor := sc.BlobStor().Storages()
|
||||||
|
if len(blobstor) != 2 {
|
||||||
|
// TODO (@fyrcik): remove after #1522
|
||||||
|
return fmt.Errorf("blobstor section must have 2 components, got: %d", len(blobstor))
|
||||||
|
}
|
||||||
|
for i := range blobstor {
|
||||||
|
switch blobstor[i].Type() {
|
||||||
|
case fstree.Type, blobovniczatree.Type:
|
||||||
|
default:
|
||||||
|
// FIXME #1764 (@fyrchik): this line is currently unreachable,
|
||||||
|
// because we panic in `sc.BlobStor().Storages()`.
|
||||||
|
return fmt.Errorf("unexpected storage type: %s (shard %d)",
|
||||||
|
blobstor[i].Type(), shardNum)
|
||||||
|
}
|
||||||
|
if blobstor[i].Perm()&0600 != 0600 {
|
||||||
|
return fmt.Errorf("invalid permissions for blobstor component: %s, "+
|
||||||
|
"expected at least rw- for the owner (shard %d)",
|
||||||
|
blobstor[i].Perm(), shardNum)
|
||||||
|
}
|
||||||
|
if blobstor[i].Path() == "" {
|
||||||
|
return fmt.Errorf("blobstor component path is empty (shard %d)", shardNum)
|
||||||
|
}
|
||||||
|
err := addPath(paths, fmt.Sprintf("blobstor[%d]", i), shardNum, blobstor[i].Path())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
shardNum++
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
type pathDescription struct {
|
||||||
|
shard int
|
||||||
|
component string
|
||||||
|
}
|
||||||
|
|
||||||
|
func addPath(paths map[string]pathDescription, component string, shard int, path string) error {
|
||||||
|
if path == "" {
|
||||||
|
return fmt.Errorf("%s at shard %d has empty path", component, shard)
|
||||||
|
}
|
||||||
|
|
||||||
|
path = filepath.Clean(path)
|
||||||
|
c, ok := paths[path]
|
||||||
|
if ok {
|
||||||
|
return fmt.Errorf("%s at shard %d and %s at shard %d have the same paths: %s",
|
||||||
|
c.component, c.shard, component, shard, path)
|
||||||
|
}
|
||||||
|
|
||||||
|
paths[path] = pathDescription{shard: shard, component: component}
|
||||||
|
return nil
|
||||||
|
}
|
38
cmd/neofs-node/validate_test.go
Normal file
38
cmd/neofs-node/validate_test.go
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neofs-node/cmd/neofs-node/config"
|
||||||
|
configtest "github.com/nspcc-dev/neofs-node/cmd/neofs-node/config/test"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestValidate(t *testing.T) {
|
||||||
|
const exampleConfigPrefix = "../../config/"
|
||||||
|
t.Run("examples", func(t *testing.T) {
|
||||||
|
p := filepath.Join(exampleConfigPrefix, "example/node")
|
||||||
|
configtest.ForEachFileType(p, func(c *config.Config) {
|
||||||
|
var err error
|
||||||
|
require.NotPanics(t, func() {
|
||||||
|
err = validateConfig(c)
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("mainnet", func(t *testing.T) {
|
||||||
|
os.Clearenv() // ENVs have priority over config files, so we do this in tests
|
||||||
|
p := filepath.Join(exampleConfigPrefix, "mainnet/config.yml")
|
||||||
|
c := config.New(config.Prm{}, config.WithConfigFile(p))
|
||||||
|
require.NoError(t, validateConfig(c))
|
||||||
|
})
|
||||||
|
t.Run("testnet", func(t *testing.T) {
|
||||||
|
os.Clearenv() // ENVs have priority over config files, so we do this in tests
|
||||||
|
p := filepath.Join(exampleConfigPrefix, "testnet/config.yml")
|
||||||
|
c := config.New(config.Prm{}, config.WithConfigFile(p))
|
||||||
|
require.NoError(t, validateConfig(c))
|
||||||
|
})
|
||||||
|
}
|
|
@ -21,15 +21,19 @@ storage:
|
||||||
shard:
|
shard:
|
||||||
0:
|
0:
|
||||||
metabase:
|
metabase:
|
||||||
path: <storage-path>/metabase
|
path: /storage/path/metabase
|
||||||
perm: 0600
|
perm: 0600
|
||||||
blobstor:
|
blobstor:
|
||||||
path: <storage-path>/blobstor
|
- path: /storage/path/blobovnicza
|
||||||
perm: 0600
|
type: blobovnicza
|
||||||
blobovnicza:
|
perm: 0600
|
||||||
opened_cache_capacity: 32
|
opened_cache_capacity: 32
|
||||||
depth: 1
|
depth: 1
|
||||||
width: 1
|
width: 1
|
||||||
|
- path: /storage/path/fstree
|
||||||
|
type: fstree
|
||||||
|
perm: 0600
|
||||||
|
depth: 4
|
||||||
writecache:
|
writecache:
|
||||||
enabled: false
|
enabled: false
|
||||||
gc:
|
gc:
|
||||||
|
|
|
@ -36,12 +36,16 @@ storage:
|
||||||
path: /storage/metabase
|
path: /storage/metabase
|
||||||
perm: 0777
|
perm: 0777
|
||||||
blobstor:
|
blobstor:
|
||||||
path: /storage/blobstor
|
- path: /storage/path/blobovnicza
|
||||||
perm: 0777
|
type: blobovnicza
|
||||||
blobovnicza:
|
perm: 0600
|
||||||
opened_cache_capacity: 32
|
opened_cache_capacity: 32
|
||||||
depth: 1
|
depth: 1
|
||||||
width: 1
|
width: 1
|
||||||
|
- path: /storage/path/fstree
|
||||||
|
type: fstree
|
||||||
|
perm: 0600
|
||||||
|
depth: 4
|
||||||
writecache:
|
writecache:
|
||||||
enabled: false
|
enabled: false
|
||||||
gc:
|
gc:
|
||||||
|
|
Loading…
Reference in a new issue