[SUPPORT] node, ir, morph: Add new config option upgrade_mode #1075
14 changed files with 59 additions and 13 deletions
|
@ -34,6 +34,7 @@ func reloadConfig() error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
cmode.Store(cfg.GetBool("node.kludge_compatibility_mode"))
|
||||||
err = logPrm.SetLevelString(cfg.GetString("logger.level"))
|
err = logPrm.SetLevelString(cfg.GetString("logger.level"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -43,6 +43,8 @@ func defaultConfiguration(cfg *viper.Viper) {
|
||||||
setControlDefaults(cfg)
|
setControlDefaults(cfg)
|
||||||
|
|
||||||
cfg.SetDefault("governance.disable", false)
|
cfg.SetDefault("governance.disable", false)
|
||||||
|
|
||||||
|
cfg.SetDefault("node.kludge_compatibility_mode", false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func setControlDefaults(cfg *viper.Viper) {
|
func setControlDefaults(cfg *viper.Viper) {
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/misc"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/misc"
|
||||||
|
@ -37,6 +38,7 @@ var (
|
||||||
cfg *viper.Viper
|
cfg *viper.Viper
|
||||||
configFile *string
|
configFile *string
|
||||||
configDir *string
|
configDir *string
|
||||||
|
cmode = &atomic.Bool{}
|
||||||
)
|
)
|
||||||
|
|
||||||
func exitErr(err error) {
|
func exitErr(err error) {
|
||||||
|
@ -62,6 +64,8 @@ func main() {
|
||||||
cfg, err = newConfig()
|
cfg, err = newConfig()
|
||||||
exitErr(err)
|
exitErr(err)
|
||||||
|
|
||||||
|
cmode.Store(cfg.GetBool("node.kludge_compatibility_mode"))
|
||||||
|
|
||||||
metrics := irMetrics.NewInnerRingMetrics()
|
metrics := irMetrics.NewInnerRingMetrics()
|
||||||
|
|
||||||
err = logPrm.SetLevelString(
|
err = logPrm.SetLevelString(
|
||||||
|
@ -84,7 +88,7 @@ func main() {
|
||||||
metricsCmp = newMetricsComponent()
|
metricsCmp = newMetricsComponent()
|
||||||
metricsCmp.init()
|
metricsCmp.init()
|
||||||
|
|
||||||
innerRing, err = innerring.New(ctx, log, cfg, intErr, metrics)
|
innerRing, err = innerring.New(ctx, log, cfg, intErr, metrics, cmode)
|
||||||
exitErr(err)
|
exitErr(err)
|
||||||
|
|
||||||
pprofCmp.start()
|
pprofCmp.start()
|
||||||
|
|
|
@ -109,6 +109,9 @@ type applicationConfiguration struct {
|
||||||
lowMem bool
|
lowMem bool
|
||||||
rebuildWorkers uint32
|
rebuildWorkers uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if need to run node in compatibility with other versions mode
|
||||||
|
cmode *atomic.Bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type shardCfg struct {
|
type shardCfg struct {
|
||||||
|
@ -204,10 +207,13 @@ func (a *applicationConfiguration) readConfig(c *config.Config) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// clear if it is rereading
|
// clear if it is rereading
|
||||||
|
cmode := a.cmode
|
||||||
*a = applicationConfiguration{}
|
*a = applicationConfiguration{}
|
||||||
|
a.cmode = cmode
|
||||||
}
|
}
|
||||||
|
|
||||||
a._read = true
|
a._read = true
|
||||||
|
a.cmode.Store(nodeconfig.CompatibilityMode(c))
|
||||||
|
|
||||||
// Logger
|
// Logger
|
||||||
|
|
||||||
|
@ -648,7 +654,11 @@ type cfgControlService struct {
|
||||||
var persistateSideChainLastBlockKey = []byte("side_chain_last_processed_block")
|
var persistateSideChainLastBlockKey = []byte("side_chain_last_processed_block")
|
||||||
|
|
||||||
func initCfg(appCfg *config.Config) *cfg {
|
func initCfg(appCfg *config.Config) *cfg {
|
||||||
c := &cfg{}
|
c := &cfg{
|
||||||
|
applicationConfiguration: applicationConfiguration{
|
||||||
|
cmode: &atomic.Bool{},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
err := c.readConfig(appCfg)
|
err := c.readConfig(appCfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -292,3 +292,8 @@ func (l PersistentPolicyRulesConfig) Perm() fs.FileMode {
|
||||||
func (l PersistentPolicyRulesConfig) NoSync() bool {
|
func (l PersistentPolicyRulesConfig) NoSync() bool {
|
||||||
return config.BoolSafe((*config.Config)(l.cfg), "no_sync")
|
return config.BoolSafe((*config.Config)(l.cfg), "no_sync")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CompatibilityMode returns true if need to run node in compatibility with previous versions mode.
|
||||||
|
func CompatibilityMode(c *config.Config) bool {
|
||||||
|
return config.BoolSafe(c.Sub(subsection), "kludge_compatibility_mode")
|
||||||
|
}
|
||||||
|
|
|
@ -48,6 +48,7 @@ func initMorphComponents(ctx context.Context, c *cfg) {
|
||||||
}),
|
}),
|
||||||
client.WithSwitchInterval(morphconfig.SwitchInterval(c.appCfg)),
|
client.WithSwitchInterval(morphconfig.SwitchInterval(c.appCfg)),
|
||||||
client.WithMorphCacheMetrics(c.metricsCollector.MorphCacheMetrics()),
|
client.WithMorphCacheMetrics(c.metricsCollector.MorphCacheMetrics()),
|
||||||
|
client.WithCompatibilityMode(c.cmode),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.log.Info(logs.FrostFSNodeFailedToCreateNeoRPCClient,
|
c.log.Info(logs.FrostFSNodeFailedToCreateNeoRPCClient,
|
||||||
|
|
8
go.mod
8
go.mod
|
@ -40,8 +40,8 @@ require (
|
||||||
go.uber.org/zap v1.26.0
|
go.uber.org/zap v1.26.0
|
||||||
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a
|
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a
|
||||||
golang.org/x/sync v0.6.0
|
golang.org/x/sync v0.6.0
|
||||||
golang.org/x/sys v0.16.0
|
golang.org/x/sys v0.18.0
|
||||||
golang.org/x/term v0.16.0
|
golang.org/x/term v0.18.0
|
||||||
google.golang.org/grpc v1.61.0
|
google.golang.org/grpc v1.61.0
|
||||||
google.golang.org/protobuf v1.33.0
|
google.golang.org/protobuf v1.33.0
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
|
@ -121,8 +121,8 @@ require (
|
||||||
go.opentelemetry.io/otel/sdk v1.22.0 // indirect
|
go.opentelemetry.io/otel/sdk v1.22.0 // indirect
|
||||||
go.opentelemetry.io/proto/otlp v1.1.0 // indirect
|
go.opentelemetry.io/proto/otlp v1.1.0 // indirect
|
||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
golang.org/x/crypto v0.18.0 // indirect
|
golang.org/x/crypto v0.21.0 // indirect
|
||||||
golang.org/x/net v0.20.0 // indirect
|
golang.org/x/net v0.23.0 // indirect
|
||||||
golang.org/x/text v0.14.0 // indirect
|
golang.org/x/text v0.14.0 // indirect
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 // indirect
|
google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect
|
||||||
|
|
BIN
go.sum
BIN
go.sum
Binary file not shown.
|
@ -462,6 +462,7 @@ func (s *Server) initMorph(ctx context.Context, cfg *viper.Viper, errChan chan<-
|
||||||
name: morphPrefix,
|
name: morphPrefix,
|
||||||
from: fromSideChainBlock,
|
from: fromSideChainBlock,
|
||||||
morphCacheMetric: s.irMetrics.MorphCacheMetrics(),
|
morphCacheMetric: s.irMetrics.MorphCacheMetrics(),
|
||||||
|
cmode: s.cmode,
|
||||||
}
|
}
|
||||||
|
|
||||||
// create morph client
|
// create morph client
|
||||||
|
|
|
@ -103,6 +103,8 @@ type (
|
||||||
// should report start errors
|
// should report start errors
|
||||||
// to the application.
|
// to the application.
|
||||||
runners []func(chan<- error) error
|
runners []func(chan<- error) error
|
||||||
|
|
||||||
|
cmode *atomic.Bool
|
||||||
}
|
}
|
||||||
|
|
||||||
chainParams struct {
|
chainParams struct {
|
||||||
|
@ -113,6 +115,7 @@ type (
|
||||||
sgn *transaction.Signer
|
sgn *transaction.Signer
|
||||||
from uint32 // block height
|
from uint32 // block height
|
||||||
morphCacheMetric metrics.MorphCacheMetrics
|
morphCacheMetric metrics.MorphCacheMetrics
|
||||||
|
cmode *atomic.Bool
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -330,12 +333,13 @@ func (s *Server) registerStarter(f func() error) {
|
||||||
|
|
||||||
// New creates instance of inner ring sever structure.
|
// New creates instance of inner ring sever structure.
|
||||||
func New(ctx context.Context, log *logger.Logger, cfg *viper.Viper, errChan chan<- error,
|
func New(ctx context.Context, log *logger.Logger, cfg *viper.Viper, errChan chan<- error,
|
||||||
metrics *metrics.InnerRingServiceMetrics,
|
metrics *metrics.InnerRingServiceMetrics, cmode *atomic.Bool,
|
||||||
) (*Server, error) {
|
) (*Server, error) {
|
||||||
var err error
|
var err error
|
||||||
server := &Server{
|
server := &Server{
|
||||||
log: log,
|
log: log,
|
||||||
irMetrics: metrics,
|
irMetrics: metrics,
|
||||||
|
cmode: cmode,
|
||||||
}
|
}
|
||||||
|
|
||||||
server.sdNotify, err = server.initSdNotify(cfg)
|
server.sdNotify, err = server.initSdNotify(cfg)
|
||||||
|
@ -485,6 +489,7 @@ func createClient(ctx context.Context, p *chainParams, errChan chan<- error) (*c
|
||||||
}),
|
}),
|
||||||
client.WithSwitchInterval(p.cfg.GetDuration(p.name+".switch_interval")),
|
client.WithSwitchInterval(p.cfg.GetDuration(p.name+".switch_interval")),
|
||||||
client.WithMorphCacheMetrics(p.morphCacheMetric),
|
client.WithMorphCacheMetrics(p.morphCacheMetric),
|
||||||
|
client.WithCompatibilityMode(p.cmode),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ func (h filenameHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
|
||||||
func (h *filenameHeap) Push(x any) {
|
func (h *filenameHeap) Push(x any) {
|
||||||
*h = append(*h, x.(heapInfo))
|
*h = append(*h, x.(heapInfo))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *filenameHeap) Pop() any {
|
func (h *filenameHeap) Pop() any {
|
||||||
old := *h
|
old := *h
|
||||||
n := len(old)
|
n := len(old)
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
|
||||||
|
@ -48,6 +49,8 @@ type cfg struct {
|
||||||
switchInterval time.Duration
|
switchInterval time.Duration
|
||||||
|
|
||||||
morphCacheMetrics metrics.MorphCacheMetrics
|
morphCacheMetrics metrics.MorphCacheMetrics
|
||||||
|
|
||||||
|
cmode *atomic.Bool
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -311,3 +314,11 @@ func WithMorphCacheMetrics(morphCacheMetrics metrics.MorphCacheMetrics) Option {
|
||||||
c.morphCacheMetrics = morphCacheMetrics
|
c.morphCacheMetrics = morphCacheMetrics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithCompatibilityMode indicates that Client is working in compatibility mode
|
||||||
|
// in this mode we need to keep backward compatibility with services with previous version.
|
||||||
|
func WithCompatibilityMode(cmode *atomic.Bool) Option {
|
||||||
|
return func(c *cfg) {
|
||||||
|
c.cmode = cmode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -566,14 +566,19 @@ func (c *Client) notaryCosigners(invokedByAlpha bool, ir []*keys.PublicKey, comm
|
||||||
}
|
}
|
||||||
s := make([]actor.SignerAccount, 2, 3)
|
s := make([]actor.SignerAccount, 2, 3)
|
||||||
// Proxy contract that will pay for the execution.
|
// Proxy contract that will pay for the execution.
|
||||||
|
// Do not change this:
|
||||||
|
// We must be able to call NNS contract indirectly from the Container contract.
|
||||||
|
// Thus, CalledByEntry is not sufficient.
|
||||||
|
// In future we may restrict this to all the usecases we have.
|
||||||
|
scopes := transaction.Global
|
||||||
|
if c.cfg.cmode != nil && c.cfg.cmode.Load() {
|
||||||
|
// Set it to None to keep ability to send notary requests during upgrade
|
||||||
|
scopes = transaction.None
|
||||||
|
}
|
||||||
s[0] = actor.SignerAccount{
|
s[0] = actor.SignerAccount{
|
||||||
Signer: transaction.Signer{
|
Signer: transaction.Signer{
|
||||||
Account: c.notary.proxy,
|
Account: c.notary.proxy,
|
||||||
// Do not change this:
|
Scopes: scopes,
|
||||||
// We must be able to call NNS contract indirectly from the Container contract.
|
|
||||||
// Thus, CalledByEntry is not sufficient.
|
|
||||||
// In future we may restrict this to all the usecases we have.
|
|
||||||
Scopes: transaction.Global,
|
|
||||||
},
|
},
|
||||||
Account: notary.FakeContractAccount(c.notary.proxy),
|
Account: notary.FakeContractAccount(c.notary.proxy),
|
||||||
}
|
}
|
||||||
|
|
|
@ -130,7 +130,7 @@ func TestGetSubTreeOrderAsc(t *testing.T) {
|
||||||
|
|
||||||
t.Run("boltdb forest", func(t *testing.T) {
|
t.Run("boltdb forest", func(t *testing.T) {
|
||||||
p := pilorama.NewBoltForest(pilorama.WithPath(filepath.Join(t.TempDir(), "pilorama")))
|
p := pilorama.NewBoltForest(pilorama.WithPath(filepath.Join(t.TempDir(), "pilorama")))
|
||||||
require.NoError(t, p.Open(context.Background(), 0644))
|
require.NoError(t, p.Open(context.Background(), 0o644))
|
||||||
require.NoError(t, p.Init())
|
require.NoError(t, p.Init())
|
||||||
testGetSubTreeOrderAsc(t, p)
|
testGetSubTreeOrderAsc(t, p)
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in a new issue