Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/control service object status #2912

Merged
merged 2 commits into from
Aug 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Changelog for NeoFS Node
- Indexes inspection command to neofs-lens (#2882)
- Add objects sanity checker to neofs-lens (#2506)
- Support for 0.20.0+ neofs-contract archive format (#2872)
- `neofs-cli control object status` command (#2886)

### Fixed
- Control service's Drop call does not clean metabase (#2822)
Expand Down
92 changes: 92 additions & 0 deletions cmd/neofs-cli/modules/control/objects.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package control

import (
"fmt"

rawclient "github.com/nspcc-dev/neofs-api-go/v2/rpc/client"
"github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/commonflags"
"github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/key"
"github.com/nspcc-dev/neofs-node/pkg/services/control"
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
"github.com/spf13/cobra"
)

const objectFlag = "object"

var objectCmd = &cobra.Command{
Use: "object",
Short: "Direct object operations with storage engine",
}

var objectStatusCmd = &cobra.Command{
Use: "status",
Short: "Check current object status",
Args: cobra.NoArgs,
SilenceUsage: true,
RunE: objectStatus,
}

func objectStatus(cmd *cobra.Command, _ []string) error {
ctx, cancel := commonflags.GetCommandContext(cmd)
defer cancel()

Check warning on line 31 in cmd/neofs-cli/modules/control/objects.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-cli/modules/control/objects.go#L29-L31

Added lines #L29 - L31 were not covered by tests

pk := key.Get(cmd)
addressRaw, err := cmd.Flags().GetString(objectFlag)
if err != nil {
return fmt.Errorf("reading %s flag: %w", objectFlag, err)

Check warning on line 36 in cmd/neofs-cli/modules/control/objects.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-cli/modules/control/objects.go#L33-L36

Added lines #L33 - L36 were not covered by tests
}

var sdkAddr oid.Address
err = sdkAddr.DecodeString(addressRaw)
if err != nil {
return fmt.Errorf("validating address (%s): %w", addressRaw, err)

Check warning on line 42 in cmd/neofs-cli/modules/control/objects.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-cli/modules/control/objects.go#L39-L42

Added lines #L39 - L42 were not covered by tests
}

var resp *control.ObjectStatusResponse
req := &control.ObjectStatusRequest{
Body: &control.ObjectStatusRequest_Body{
ObjectAddress: addressRaw,
},

Check warning on line 49 in cmd/neofs-cli/modules/control/objects.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-cli/modules/control/objects.go#L45-L49

Added lines #L45 - L49 were not covered by tests
}
signRequest(cmd, pk, req)

Check warning on line 51 in cmd/neofs-cli/modules/control/objects.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-cli/modules/control/objects.go#L51

Added line #L51 was not covered by tests

cli := getClient(ctx, cmd)

Check warning on line 53 in cmd/neofs-cli/modules/control/objects.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-cli/modules/control/objects.go#L53

Added line #L53 was not covered by tests

err = cli.ExecRaw(func(client *rawclient.Client) error {
resp, err = control.ObjectStatus(client, req)
return err
})
if err != nil {
return fmt.Errorf("rpc error: %w", err)

Check warning on line 60 in cmd/neofs-cli/modules/control/objects.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-cli/modules/control/objects.go#L55-L60

Added lines #L55 - L60 were not covered by tests
}

verifyResponse(cmd, resp.GetSignature(), resp.GetBody())

Check warning on line 63 in cmd/neofs-cli/modules/control/objects.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-cli/modules/control/objects.go#L63

Added line #L63 was not covered by tests

shards := resp.GetBody().GetShards()
if len(shards) == 0 {
cmd.Println("<empty response>")
return nil

Check warning on line 68 in cmd/neofs-cli/modules/control/objects.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-cli/modules/control/objects.go#L65-L68

Added lines #L65 - L68 were not covered by tests
}

for _, shard := range shards {
cmd.Printf("Shard ID: %s\n", shard.ShardId)
storages := shard.GetStorages()
if len(storages) == 0 {
cmd.Println("\t<empty response>")
continue

Check warning on line 76 in cmd/neofs-cli/modules/control/objects.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-cli/modules/control/objects.go#L71-L76

Added lines #L71 - L76 were not covered by tests
}

for _, storage := range storages {
cmd.Printf("\t%s: %s\n", storage.Type, storage.Status)

Check warning on line 80 in cmd/neofs-cli/modules/control/objects.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-cli/modules/control/objects.go#L79-L80

Added lines #L79 - L80 were not covered by tests
}
}

return nil

Check warning on line 84 in cmd/neofs-cli/modules/control/objects.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-cli/modules/control/objects.go#L84

Added line #L84 was not covered by tests
}

func initObjectStatusFlags() {
initControlFlags(objectStatusCmd)

Check warning on line 88 in cmd/neofs-cli/modules/control/objects.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-cli/modules/control/objects.go#L87-L88

Added lines #L87 - L88 were not covered by tests

flags := objectStatusCmd.Flags()
flags.String(objectFlag, "", "Object address")

Check warning on line 91 in cmd/neofs-cli/modules/control/objects.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-cli/modules/control/objects.go#L90-L91

Added lines #L90 - L91 were not covered by tests
}
6 changes: 6 additions & 0 deletions cmd/neofs-cli/modules/control/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,23 @@
)

func init() {
objectCmd.AddCommand(
objectStatusCmd,
)

Check warning on line 32 in cmd/neofs-cli/modules/control/root.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-cli/modules/control/root.go#L30-L32

Added lines #L30 - L32 were not covered by tests

Cmd.AddCommand(
healthCheckCmd,
setNetmapStatusCmd,
dropObjectsCmd,
shardsCmd,
synchronizeTreeCmd,
objectCmd,

Check warning on line 40 in cmd/neofs-cli/modules/control/root.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-cli/modules/control/root.go#L40

Added line #L40 was not covered by tests
)

initControlHealthCheckCmd()
initControlSetNetmapStatusCmd()
initControlDropObjectsCmd()
initControlShardsCmd()
initControlSynchronizeTreeCmd()
initObjectStatusFlags()

Check warning on line 48 in cmd/neofs-cli/modules/control/root.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-cli/modules/control/root.go#L48

Added line #L48 was not covered by tests
}
18 changes: 18 additions & 0 deletions pkg/services/control/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,3 +200,21 @@
w.FlushCacheResponse = r
return nil
}

type objectStatusResponseWrapper struct {
*ObjectStatusResponse
}

func (w *objectStatusResponseWrapper) ToGRPCMessage() grpc.Message {
return w.ObjectStatusResponse

Check warning on line 209 in pkg/services/control/convert.go

View check run for this annotation

Codecov / codecov/patch

pkg/services/control/convert.go#L208-L209

Added lines #L208 - L209 were not covered by tests
}

func (w *objectStatusResponseWrapper) FromGRPCMessage(m grpc.Message) error {
r, ok := m.(*ObjectStatusResponse)
if !ok {
return message.NewUnexpectedMessageType(m, (*ObjectStatusResponse)(nil))

Check warning on line 215 in pkg/services/control/convert.go

View check run for this annotation

Codecov / codecov/patch

pkg/services/control/convert.go#L212-L215

Added lines #L212 - L215 were not covered by tests
}

w.ObjectStatusResponse = r
return nil

Check warning on line 219 in pkg/services/control/convert.go

View check run for this annotation

Codecov / codecov/patch

pkg/services/control/convert.go#L218-L219

Added lines #L218 - L219 were not covered by tests
}
14 changes: 14 additions & 0 deletions pkg/services/control/rpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
rpcSynchronizeTree = "SynchronizeTree"
rpcEvacuateShard = "EvacuateShard"
rpcFlushCache = "FlushCache"
rpcObjectStatus = "ObjectStatus"
)

// HealthCheck executes ControlService.HealthCheck RPC.
Expand Down Expand Up @@ -191,3 +192,16 @@

return wResp.FlushCacheResponse, nil
}

// ObjectStatus executes ControlService.ObjectStatus RPC.
func ObjectStatus(cli *client.Client, req *ObjectStatusRequest, opts ...client.CallOption) (*ObjectStatusResponse, error) {
wResp := &objectStatusResponseWrapper{new(ObjectStatusResponse)}
wReq := &requestWrapper{m: req}

Check warning on line 199 in pkg/services/control/rpc.go

View check run for this annotation

Codecov / codecov/patch

pkg/services/control/rpc.go#L197-L199

Added lines #L197 - L199 were not covered by tests

err := client.SendUnary(cli, common.CallMethodInfoUnary(serviceName, rpcObjectStatus), wReq, wResp, opts...)
if err != nil {
return nil, err

Check warning on line 203 in pkg/services/control/rpc.go

View check run for this annotation

Codecov / codecov/patch

pkg/services/control/rpc.go#L201-L203

Added lines #L201 - L203 were not covered by tests
}

return wResp.ObjectStatusResponse, nil

Check warning on line 206 in pkg/services/control/rpc.go

View check run for this annotation

Codecov / codecov/patch

pkg/services/control/rpc.go#L206

Added line #L206 was not covered by tests
}
94 changes: 94 additions & 0 deletions pkg/services/control/server/object_status.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package control

import (
"context"
"fmt"
"strings"

"github.com/nspcc-dev/neofs-node/pkg/services/control"
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)

func (s *Server) ObjectStatus(_ context.Context, request *control.ObjectStatusRequest) (*control.ObjectStatusResponse, error) {
err := s.isValidRequest(request)
if err != nil {
return nil, status.Error(codes.PermissionDenied, err.Error())

Check warning on line 17 in pkg/services/control/server/object_status.go

View check run for this annotation

Codecov / codecov/patch

pkg/services/control/server/object_status.go#L14-L17

Added lines #L14 - L17 were not covered by tests
}

// check availability
err = s.ready()
if err != nil {
return nil, err

Check warning on line 23 in pkg/services/control/server/object_status.go

View check run for this annotation

Codecov / codecov/patch

pkg/services/control/server/object_status.go#L21-L23

Added lines #L21 - L23 were not covered by tests
}

var addr oid.Address
err = addr.DecodeString(request.GetBody().GetObjectAddress())
if err != nil {
return nil, status.Errorf(codes.InvalidArgument, "parsing object address: %s", err)

Check warning on line 29 in pkg/services/control/server/object_status.go

View check run for this annotation

Codecov / codecov/patch

pkg/services/control/server/object_status.go#L26-L29

Added lines #L26 - L29 were not covered by tests
}

st, err := s.storage.ObjectStatus(addr)
if err != nil {
return nil, status.Errorf(codes.Internal, "storage engine error: %s", err)

Check warning on line 34 in pkg/services/control/server/object_status.go

View check run for this annotation

Codecov / codecov/patch

pkg/services/control/server/object_status.go#L32-L34

Added lines #L32 - L34 were not covered by tests
}

resp := &control.ObjectStatusResponse{
Body: &control.ObjectStatusResponse_Body{},

Check warning on line 38 in pkg/services/control/server/object_status.go

View check run for this annotation

Codecov / codecov/patch

pkg/services/control/server/object_status.go#L37-L38

Added lines #L37 - L38 were not covered by tests
}

for _, sh := range st.Shards {
respSh := new(control.ObjectStatusResponse_Body_Shard)
respSh.ShardId = sh.ID

Check warning on line 43 in pkg/services/control/server/object_status.go

View check run for this annotation

Codecov / codecov/patch

pkg/services/control/server/object_status.go#L41-L43

Added lines #L41 - L43 were not covered by tests

if len(sh.Shard.Metabase.State) == 0 {

Check warning on line 45 in pkg/services/control/server/object_status.go

View check run for this annotation

Codecov / codecov/patch

pkg/services/control/server/object_status.go#L45

Added line #L45 was not covered by tests
// can be reconsidered since it is possible to get
// resynchronized state when meta knows nothing about
// stored objects in blob; however, it is a control
// service, not a debug util
continue

Check warning on line 50 in pkg/services/control/server/object_status.go

View check run for this annotation

Codecov / codecov/patch

pkg/services/control/server/object_status.go#L50

Added line #L50 was not covered by tests
}

respSh.Storages = append(respSh.Storages, &control.ObjectStatusResponse_Body_Shard_Status{
Type: "metabase",
Status: strings.Join(sh.Shard.Metabase.State, ","),
})

Check warning on line 56 in pkg/services/control/server/object_status.go

View check run for this annotation

Codecov / codecov/patch

pkg/services/control/server/object_status.go#L53-L56

Added lines #L53 - L56 were not covered by tests

for _, subStorage := range sh.Shard.Blob.Substorages {
respSh.Storages = append(respSh.Storages,
&control.ObjectStatusResponse_Body_Shard_Status{
Type: subStorage.Type,
Status: fmt.Sprintf("path: %q", subStorage.Path),
},
)

Check warning on line 64 in pkg/services/control/server/object_status.go

View check run for this annotation

Codecov / codecov/patch

pkg/services/control/server/object_status.go#L58-L64

Added lines #L58 - L64 were not covered by tests
}

var wcStatus string
switch {
case sh.Shard.Writecache.PathDB != "":
wcStatus = fmt.Sprintf("database path: %q", sh.Shard.Writecache.PathDB)
case sh.Shard.Writecache.PathFSTree != "":
wcStatus = fmt.Sprintf("fsTree path: %q", sh.Shard.Writecache.PathFSTree)

Check warning on line 72 in pkg/services/control/server/object_status.go

View check run for this annotation

Codecov / codecov/patch

pkg/services/control/server/object_status.go#L67-L72

Added lines #L67 - L72 were not covered by tests
}

// it can be turned off, it is OK
if wcStatus != "" {
respSh.Storages = append(respSh.Storages,
&control.ObjectStatusResponse_Body_Shard_Status{
Type: "write-cache",
Status: wcStatus,
},
)

Check warning on line 82 in pkg/services/control/server/object_status.go

View check run for this annotation

Codecov / codecov/patch

pkg/services/control/server/object_status.go#L76-L82

Added lines #L76 - L82 were not covered by tests
}

resp.Body.Shards = append(resp.Body.Shards, respSh)

Check warning on line 85 in pkg/services/control/server/object_status.go

View check run for this annotation

Codecov / codecov/patch

pkg/services/control/server/object_status.go#L85

Added line #L85 was not covered by tests
}

err = SignMessage(s.key, resp)
if err != nil {
return nil, status.Error(codes.Internal, err.Error())

Check warning on line 90 in pkg/services/control/server/object_status.go

View check run for this annotation

Codecov / codecov/patch

pkg/services/control/server/object_status.go#L88-L90

Added lines #L88 - L90 were not covered by tests
}

return resp, nil

Check warning on line 93 in pkg/services/control/server/object_status.go

View check run for this annotation

Codecov / codecov/patch

pkg/services/control/server/object_status.go#L93

Added line #L93 was not covered by tests
}
Loading
Loading