From 4eb0ed11f8e56beee3dfbee632cb4b9cad3bb47c Mon Sep 17 00:00:00 2001 From: Pavel Karpy Date: Wed, 21 Sep 2022 23:57:46 +0300 Subject: [PATCH] [#1809] node: Do not boot up if metabase is outdated Signed-off-by: Pavel Karpy --- CHANGELOG.md | 1 + pkg/local_object_storage/metabase/control.go | 2 ++ pkg/local_object_storage/metabase/version.go | 8 +++++++- pkg/local_object_storage/shard/control.go | 4 ++++ 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 71ee7500e9..530b34fb47 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ Changelog for NeoFS Node ### Fixed - Description of command `netmap nodeinfo` (#1821) - Proper status for object.Delete if session token is missing (#1697) +- Fail startup if metabase has an old version (#1809) ### Removed - Remove WIF and NEP2 support in `neofs-cli`'s --wallet flag (#1128) diff --git a/pkg/local_object_storage/metabase/control.go b/pkg/local_object_storage/metabase/control.go index 25cd5ae638..93b9a4458f 100644 --- a/pkg/local_object_storage/metabase/control.go +++ b/pkg/local_object_storage/metabase/control.go @@ -58,6 +58,8 @@ func (db *DB) Open(readOnly bool) error { // Init initializes metabase. It creates static (CID-independent) buckets in underlying BoltDB instance. // +// Returns ErrOutdatedVersion if a database at the provided path is outdated. +// // Does nothing if metabase has already been initialized and filled. To roll back the database to its initial state, // use Reset. func (db *DB) Init() error { diff --git a/pkg/local_object_storage/metabase/version.go b/pkg/local_object_storage/metabase/version.go index f5af18c126..5d1d9d84f2 100644 --- a/pkg/local_object_storage/metabase/version.go +++ b/pkg/local_object_storage/metabase/version.go @@ -2,6 +2,7 @@ package meta import ( "encoding/binary" + "errors" "fmt" "go.etcd.io/bbolt" @@ -12,6 +13,11 @@ const version = 2 var versionKey = []byte("version") +// ErrOutdatedVersion is returned on initializing +// an existing metabase that is not compatible with +// the current code version. +var ErrOutdatedVersion = errors.New("invalid version") + func checkVersion(tx *bbolt.Tx, initialized bool) error { b := tx.Bucket(shardInfoBucket) if b != nil { @@ -19,7 +25,7 @@ func checkVersion(tx *bbolt.Tx, initialized bool) error { if len(data) == 8 { stored := binary.LittleEndian.Uint64(data) if stored != version { - return fmt.Errorf("invalid version: expected=%d, stored=%d", version, stored) + return fmt.Errorf("%w: expected=%d, stored=%d", ErrOutdatedVersion, version, stored) } } } diff --git a/pkg/local_object_storage/shard/control.go b/pkg/local_object_storage/shard/control.go index 4fdc2e8dc9..c48275e09a 100644 --- a/pkg/local_object_storage/shard/control.go +++ b/pkg/local_object_storage/shard/control.go @@ -116,6 +116,10 @@ func (s *Shard) Init() error { for _, component := range components { if err := component.Init(); err != nil { if component == s.metaBase { + if errors.Is(err, meta.ErrOutdatedVersion) { + return err + } + err = s.handleMetabaseFailure("init", err) if err != nil { return err