Skip to content

Commit

Permalink
[nspcc-dev#1681] service/object: Fail all operations in maintenance mode
Browse files Browse the repository at this point in the history
Storage node should not provide NeoFS Object API service when it is
under maintenance.

Declare `Common` service that unifies behavior of all object operations.
The implementation pre-checks if node is under maintenance and returns
`apistatus.NodeUnderMaintenance` if so. Use `Common` service as a first
logical processor in object service pipeline.

Signed-off-by: Leonard Lyubich <ctulhurider@gmail.com>
  • Loading branch information
cthulhu-rider committed Oct 14, 2022
1 parent 6123b04 commit fd1458a
Show file tree
Hide file tree
Showing 7 changed files with 98 additions and 47 deletions.
19 changes: 6 additions & 13 deletions cmd/neofs-node/object.go
Original file line number Diff line number Diff line change
Expand Up @@ -254,8 +254,7 @@ func initObjectService(c *cfg) {
c.workers = append(c.workers, pol)

var os putsvc.ObjectStorage = engineWithoutNotifications{
e: ls,
state: &c.internals,
e: ls,
}

if c.cfgNotifications.enabled {
Expand Down Expand Up @@ -291,7 +290,7 @@ func initObjectService(c *cfg) {

sSearch := searchsvc.New(
searchsvc.WithLogger(c.log),
searchsvc.WithLocalStorageEngine(ls, &c.internals),
searchsvc.WithLocalStorageEngine(ls),
searchsvc.WithClientConstructor(coreConstructor),
searchsvc.WithTraverserGenerator(
traverseGen.WithTraverseOptions(
Expand All @@ -318,7 +317,6 @@ func initObjectService(c *cfg) {
),
getsvc.WithNetMapSource(c.netMapSource),
getsvc.WithKeyStorage(keyStorage),
getsvc.WithNodeState(&c.internals),
)

*c.cfgObject.getSvc = *sGet // need smth better
Expand Down Expand Up @@ -378,8 +376,11 @@ func initObjectService(c *cfg) {
),
)

var commonSvc objectService.Common
commonSvc.Init(&c.internals, aclSvc)

respSvc := objectService.NewResponseService(
aclSvc,
&commonSvc,
c.respSvc,
)

Expand Down Expand Up @@ -583,16 +584,8 @@ func (e engineWithNotifications) Put(o *objectSDK.Object) error {

type engineWithoutNotifications struct {
e *engine.StorageEngine

state util.NodeState
}

func (e engineWithoutNotifications) Put(o *objectSDK.Object) error {
if e.state.IsMaintenance() {
var st apistatus.NodeUnderMaintenance

return st
}

return engine.Put(e.e, o)
}
91 changes: 91 additions & 0 deletions pkg/services/object/common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package object

import (
"context"

objectV2 "github.com/nspcc-dev/neofs-api-go/v2/object"
apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status"
)

// NodeState is storage node state processed by Object service.
type NodeState interface {
// IsMaintenance checks if node is under maintenance. Node MUST NOT serve
// local object operations. Node MUST respond with apistatus.NodeUnderMaintenance
// error if IsMaintenance returns true.
IsMaintenance() bool
}

// Common is an Object API ServiceServer which encapsulates logic spread to all
// object operations.
//
// If underlying NodeState.IsMaintenance returns true, all operations are
// immediately failed with apistatus.NodeUnderMaintenance.
type Common struct {
state NodeState

nextHandler ServiceServer
}

// Init initializes the Common instance.
func (x *Common) Init(state NodeState, nextHandler ServiceServer) {
x.state = state
x.nextHandler = nextHandler
}

var errMaintenance apistatus.NodeUnderMaintenance

func (x *Common) Get(req *objectV2.GetRequest, stream GetObjectStream) error {
if x.state.IsMaintenance() {
return errMaintenance
}

return x.nextHandler.Get(req, stream)
}

func (x *Common) Put(ctx context.Context) (PutObjectStream, error) {
if x.state.IsMaintenance() {
return nil, errMaintenance
}

return x.nextHandler.Put(ctx)
}

func (x *Common) Head(ctx context.Context, req *objectV2.HeadRequest) (*objectV2.HeadResponse, error) {
if x.state.IsMaintenance() {
return nil, errMaintenance
}

return x.nextHandler.Head(ctx, req)
}

func (x *Common) Search(req *objectV2.SearchRequest, stream SearchStream) error {
if x.state.IsMaintenance() {
return errMaintenance
}

return x.nextHandler.Search(req, stream)
}

func (x *Common) Delete(ctx context.Context, req *objectV2.DeleteRequest) (*objectV2.DeleteResponse, error) {
if x.state.IsMaintenance() {
return nil, errMaintenance
}

return x.nextHandler.Delete(ctx, req)
}

func (x *Common) GetRange(req *objectV2.GetRangeRequest, stream GetObjectRangeStream) error {
if x.state.IsMaintenance() {
return errMaintenance
}

return x.nextHandler.GetRange(req, stream)
}

func (x *Common) GetRangeHash(ctx context.Context, req *objectV2.GetRangeHashRequest) (*objectV2.GetRangeHashResponse, error) {
if x.state.IsMaintenance() {
return nil, errMaintenance
}

return x.nextHandler.GetRangeHash(ctx, req)
}
7 changes: 0 additions & 7 deletions pkg/services/object/get/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,10 +130,3 @@ func WithKeyStorage(store *util.KeyStorage) Option {
c.keyStore = store
}
}

// WithNodeState provides util.NodeState to Service.
func WithNodeState(v util.NodeState) Option {
return func(c *cfg) {
c.localStorage.(*storageEngineWrapper).state = v
}
}
8 changes: 0 additions & 8 deletions pkg/services/object/get/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/engine"
internal "github.com/nspcc-dev/neofs-node/pkg/services/object/internal/client"
internalclient "github.com/nspcc-dev/neofs-node/pkg/services/object/internal/client"
"github.com/nspcc-dev/neofs-node/pkg/services/object/util"
apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status"
"github.com/nspcc-dev/neofs-sdk-go/object"
)
Expand All @@ -30,8 +29,6 @@ type clientWrapper struct {
}

type storageEngineWrapper struct {
state util.NodeState

engine *engine.StorageEngine
}

Expand Down Expand Up @@ -199,11 +196,6 @@ func (c *clientWrapper) get(exec *execCtx, key *ecdsa.PrivateKey) (*object.Objec
}

func (e *storageEngineWrapper) get(exec *execCtx) (*object.Object, error) {
if e.state != nil && e.state.IsMaintenance() {
var st apistatus.NodeUnderMaintenance
return nil, st
}

if exec.headOnly() {
var headPrm engine.HeadPrm
headPrm.WithAddress(exec.address())
Expand Down
3 changes: 1 addition & 2 deletions pkg/services/object/search/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,9 @@ func WithLogger(l *logger.Logger) Option {

// WithLocalStorageEngine returns option to set local storage
// instance.
func WithLocalStorageEngine(e *engine.StorageEngine, state util.NodeState) Option {
func WithLocalStorageEngine(e *engine.StorageEngine) Option {
return func(c *cfg) {
c.localStorage = &storageEngineWrapper{
state: state,
storage: e,
}
}
Expand Down
8 changes: 0 additions & 8 deletions pkg/services/object/search/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
internalclient "github.com/nspcc-dev/neofs-node/pkg/services/object/internal/client"
"github.com/nspcc-dev/neofs-node/pkg/services/object/util"
"github.com/nspcc-dev/neofs-node/pkg/services/object_manager/placement"
apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status"
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
)
Expand All @@ -31,8 +30,6 @@ type clientWrapper struct {
}

type storageEngineWrapper struct {
state util.NodeState

storage *engine.StorageEngine
}

Expand Down Expand Up @@ -121,11 +118,6 @@ func (c *clientWrapper) searchObjects(exec *execCtx, info client.NodeInfo) ([]oi
}

func (e *storageEngineWrapper) search(exec *execCtx) ([]oid.ID, error) {
if e.state != nil && e.state.IsMaintenance() {
var st apistatus.NodeUnderMaintenance
return nil, st
}

var selectPrm engine.SelectPrm
selectPrm.WithFilters(exec.searchFilters())
selectPrm.WithContainerID(exec.containerID())
Expand Down
9 changes: 0 additions & 9 deletions pkg/services/object/util/node_state.go

This file was deleted.

0 comments on commit fd1458a

Please sign in to comment.