multinode/console: list node satellite infos

Change-Id: Ic6cb8d1a6fd7637fdb7bf49e040c43ac30ab1bbf
This commit is contained in:
Yaroslav Vorobiov 2021-01-05 09:59:22 +02:00
parent fb00d099cf
commit 5a43c86b68
8 changed files with 428 additions and 54 deletions

View File

@ -194,7 +194,7 @@ func (controller *Nodes) Delete(w http.ResponseWriter, r *http.Request) {
}
}
// ListInfos handles node info list retrieval.
// ListInfos handles node basic info list retrieval.
func (controller *Nodes) ListInfos(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
@ -215,6 +215,35 @@ func (controller *Nodes) ListInfos(w http.ResponseWriter, r *http.Request) {
}
}
// ListInfosSatellite handles node satellite specific info list retrieval.
func (controller *Nodes) ListInfosSatellite(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
defer mon.Task()(&ctx)(&err)
w.Header().Add("Content-Type", "application/json")
vars := mux.Vars(r)
satelliteID, err := storj.NodeIDFromString(vars["satelliteID"])
if err != nil {
controller.serveError(w, http.StatusBadRequest, ErrNodes.Wrap(err))
return
}
infos, err := controller.service.ListInfosSatellite(ctx, satelliteID)
if err != nil {
controller.log.Error("list node satellite infos internal error", zap.Error(err))
controller.serveError(w, http.StatusInternalServerError, ErrNodes.Wrap(err))
return
}
if err = json.NewEncoder(w).Encode(infos); err != nil {
controller.log.Error("failed to write json response", zap.Error(err))
return
}
}
// serveError set http statuses and send json error.
func (controller *Nodes) serveError(w http.ResponseWriter, status int, err error) {
w.WriteHeader(status)

View File

@ -59,6 +59,7 @@ func NewServer(log *zap.Logger, config Config, nodes *nodes.Service, listener ne
nodesRouter.HandleFunc("", nodesController.Add).Methods(http.MethodPost)
nodesRouter.HandleFunc("", nodesController.List).Methods(http.MethodGet)
nodesRouter.HandleFunc("/infos", nodesController.ListInfos).Methods(http.MethodGet)
nodesRouter.HandleFunc("/infos/{satelliteID}", nodesController.ListInfosSatellite).Methods(http.MethodGet)
nodesRouter.HandleFunc("/{id}", nodesController.Get).Methods(http.MethodGet)
nodesRouter.HandleFunc("/{id}", nodesController.UpdateName).Methods(http.MethodPatch)
nodesRouter.HandleFunc("/{id}", nodesController.Delete).Methods(http.MethodDelete)

View File

@ -50,3 +50,14 @@ type NodeInfo struct {
DiskSpaceLeft int64
BandwidthUsed int64
}
// NodeInfoSatellite contains satellite specific node internal state.
type NodeInfoSatellite struct {
ID storj.NodeID
Name string
Version string
LastContact time.Time
OnlineScore float64
AuditScore float64
SuspensionScore float64
}

View File

@ -115,10 +115,12 @@ func (service *Service) ListInfos(ctx context.Context) (_ []NodeInfo, err error)
ApiKey: node.APISecret,
}
bandwidthSummaryRequest := &multinodepb.BandwidthMonthSummaryRequest{
Header: header,
nodeVersion, err := nodeClient.Version(ctx, &multinodepb.VersionRequest{Header: header})
if err != nil {
return NodeInfo{}, Error.Wrap(err)
}
bandwidthSummary, err := bandwidthClient.MonthSummary(ctx, bandwidthSummaryRequest)
lastContact, err := nodeClient.LastContact(ctx, &multinodepb.LastContactRequest{Header: header})
if err != nil {
return NodeInfo{}, Error.Wrap(err)
}
@ -128,12 +130,10 @@ func (service *Service) ListInfos(ctx context.Context) (_ []NodeInfo, err error)
return NodeInfo{}, Error.Wrap(err)
}
nodeVersion, err := nodeClient.Version(ctx, &multinodepb.VersionRequest{Header: header})
if err != nil {
return NodeInfo{}, Error.Wrap(err)
bandwidthSummaryRequest := &multinodepb.BandwidthMonthSummaryRequest{
Header: header,
}
lastContact, err := nodeClient.LastContact(ctx, &multinodepb.LastContactRequest{Header: header})
bandwidthSummary, err := bandwidthClient.MonthSummary(ctx, bandwidthSummaryRequest)
if err != nil {
return NodeInfo{}, Error.Wrap(err)
}
@ -157,3 +157,71 @@ func (service *Service) ListInfos(ctx context.Context) (_ []NodeInfo, err error)
return infos, nil
}
// ListInfosSatellite queries node satellite specific info from all nodes via rpc.
func (service *Service) ListInfosSatellite(ctx context.Context, satelliteID storj.NodeID) (_ []NodeInfoSatellite, err error) {
defer mon.Task()(&ctx)(&err)
nodes, err := service.nodes.List(ctx)
if err != nil {
return nil, Error.Wrap(err)
}
var infos []NodeInfoSatellite
for _, node := range nodes {
info, err := func() (_ NodeInfoSatellite, err error) {
conn, err := service.dialer.DialNodeURL(ctx, storj.NodeURL{
ID: node.ID,
Address: node.PublicAddress,
})
if err != nil {
return NodeInfoSatellite{}, Error.Wrap(err)
}
defer func() {
err = errs.Combine(err, conn.Close())
}()
nodeClient := multinodepb.NewDRPCNodeClient(conn)
header := &multinodepb.RequestHeader{
ApiKey: node.APISecret,
}
nodeVersion, err := nodeClient.Version(ctx, &multinodepb.VersionRequest{Header: header})
if err != nil {
return NodeInfoSatellite{}, Error.Wrap(err)
}
lastContact, err := nodeClient.LastContact(ctx, &multinodepb.LastContactRequest{Header: header})
if err != nil {
return NodeInfoSatellite{}, Error.Wrap(err)
}
rep, err := nodeClient.Reputation(ctx, &multinodepb.ReputationRequest{
Header: header,
SatelliteId: satelliteID,
})
if err != nil {
return NodeInfoSatellite{}, Error.Wrap(err)
}
return NodeInfoSatellite{
ID: node.ID,
Name: node.Name,
Version: nodeVersion.Version,
LastContact: lastContact.LastContact,
OnlineScore: rep.Online.Score,
AuditScore: rep.Audit.Score,
SuspensionScore: rep.Audit.SuspensionScore,
}, nil
}()
if err != nil {
return nil, Error.Wrap(err)
}
infos = append(infos, info)
}
return infos, nil
}

View File

@ -408,6 +408,175 @@ func (m *LastContactResponse) GetLastContact() time.Time {
return time.Time{}
}
type ReputationRequest struct {
Header *RequestHeader `protobuf:"bytes,1,opt,name=header,proto3" json:"header,omitempty"`
SatelliteId NodeID `protobuf:"bytes,2,opt,name=satellite_id,json=satelliteId,proto3,customtype=NodeID" json:"satellite_id"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ReputationRequest) Reset() { *m = ReputationRequest{} }
func (m *ReputationRequest) String() string { return proto.CompactTextString(m) }
func (*ReputationRequest) ProtoMessage() {}
func (*ReputationRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_9a45fd79b06f3a1b, []int{9}
}
func (m *ReputationRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ReputationRequest.Unmarshal(m, b)
}
func (m *ReputationRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ReputationRequest.Marshal(b, m, deterministic)
}
func (m *ReputationRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_ReputationRequest.Merge(m, src)
}
func (m *ReputationRequest) XXX_Size() int {
return xxx_messageInfo_ReputationRequest.Size(m)
}
func (m *ReputationRequest) XXX_DiscardUnknown() {
xxx_messageInfo_ReputationRequest.DiscardUnknown(m)
}
var xxx_messageInfo_ReputationRequest proto.InternalMessageInfo
func (m *ReputationRequest) GetHeader() *RequestHeader {
if m != nil {
return m.Header
}
return nil
}
type ReputationResponse struct {
Online *ReputationResponse_Online `protobuf:"bytes,1,opt,name=online,proto3" json:"online,omitempty"`
Audit *ReputationResponse_Audit `protobuf:"bytes,2,opt,name=audit,proto3" json:"audit,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ReputationResponse) Reset() { *m = ReputationResponse{} }
func (m *ReputationResponse) String() string { return proto.CompactTextString(m) }
func (*ReputationResponse) ProtoMessage() {}
func (*ReputationResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_9a45fd79b06f3a1b, []int{10}
}
func (m *ReputationResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ReputationResponse.Unmarshal(m, b)
}
func (m *ReputationResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ReputationResponse.Marshal(b, m, deterministic)
}
func (m *ReputationResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_ReputationResponse.Merge(m, src)
}
func (m *ReputationResponse) XXX_Size() int {
return xxx_messageInfo_ReputationResponse.Size(m)
}
func (m *ReputationResponse) XXX_DiscardUnknown() {
xxx_messageInfo_ReputationResponse.DiscardUnknown(m)
}
var xxx_messageInfo_ReputationResponse proto.InternalMessageInfo
func (m *ReputationResponse) GetOnline() *ReputationResponse_Online {
if m != nil {
return m.Online
}
return nil
}
func (m *ReputationResponse) GetAudit() *ReputationResponse_Audit {
if m != nil {
return m.Audit
}
return nil
}
type ReputationResponse_Online struct {
Score float64 `protobuf:"fixed64,1,opt,name=score,proto3" json:"score,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ReputationResponse_Online) Reset() { *m = ReputationResponse_Online{} }
func (m *ReputationResponse_Online) String() string { return proto.CompactTextString(m) }
func (*ReputationResponse_Online) ProtoMessage() {}
func (*ReputationResponse_Online) Descriptor() ([]byte, []int) {
return fileDescriptor_9a45fd79b06f3a1b, []int{10, 0}
}
func (m *ReputationResponse_Online) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ReputationResponse_Online.Unmarshal(m, b)
}
func (m *ReputationResponse_Online) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ReputationResponse_Online.Marshal(b, m, deterministic)
}
func (m *ReputationResponse_Online) XXX_Merge(src proto.Message) {
xxx_messageInfo_ReputationResponse_Online.Merge(m, src)
}
func (m *ReputationResponse_Online) XXX_Size() int {
return xxx_messageInfo_ReputationResponse_Online.Size(m)
}
func (m *ReputationResponse_Online) XXX_DiscardUnknown() {
xxx_messageInfo_ReputationResponse_Online.DiscardUnknown(m)
}
var xxx_messageInfo_ReputationResponse_Online proto.InternalMessageInfo
func (m *ReputationResponse_Online) GetScore() float64 {
if m != nil {
return m.Score
}
return 0
}
type ReputationResponse_Audit struct {
Score float64 `protobuf:"fixed64,1,opt,name=score,proto3" json:"score,omitempty"`
SuspensionScore float64 `protobuf:"fixed64,2,opt,name=suspension_score,json=suspensionScore,proto3" json:"suspension_score,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ReputationResponse_Audit) Reset() { *m = ReputationResponse_Audit{} }
func (m *ReputationResponse_Audit) String() string { return proto.CompactTextString(m) }
func (*ReputationResponse_Audit) ProtoMessage() {}
func (*ReputationResponse_Audit) Descriptor() ([]byte, []int) {
return fileDescriptor_9a45fd79b06f3a1b, []int{10, 1}
}
func (m *ReputationResponse_Audit) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ReputationResponse_Audit.Unmarshal(m, b)
}
func (m *ReputationResponse_Audit) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ReputationResponse_Audit.Marshal(b, m, deterministic)
}
func (m *ReputationResponse_Audit) XXX_Merge(src proto.Message) {
xxx_messageInfo_ReputationResponse_Audit.Merge(m, src)
}
func (m *ReputationResponse_Audit) XXX_Size() int {
return xxx_messageInfo_ReputationResponse_Audit.Size(m)
}
func (m *ReputationResponse_Audit) XXX_DiscardUnknown() {
xxx_messageInfo_ReputationResponse_Audit.DiscardUnknown(m)
}
var xxx_messageInfo_ReputationResponse_Audit proto.InternalMessageInfo
func (m *ReputationResponse_Audit) GetScore() float64 {
if m != nil {
return m.Score
}
return 0
}
func (m *ReputationResponse_Audit) GetSuspensionScore() float64 {
if m != nil {
return m.SuspensionScore
}
return 0
}
func init() {
proto.RegisterType((*RequestHeader)(nil), "multinode.RequestHeader")
proto.RegisterType((*DiskSpaceRequest)(nil), "multinode.DiskSpaceRequest")
@ -418,45 +587,58 @@ func init() {
proto.RegisterType((*VersionResponse)(nil), "multinode.VersionResponse")
proto.RegisterType((*LastContactRequest)(nil), "multinode.LastContactRequest")
proto.RegisterType((*LastContactResponse)(nil), "multinode.LastContactResponse")
proto.RegisterType((*ReputationRequest)(nil), "multinode.ReputationRequest")
proto.RegisterType((*ReputationResponse)(nil), "multinode.ReputationResponse")
proto.RegisterType((*ReputationResponse_Online)(nil), "multinode.ReputationResponse.Online")
proto.RegisterType((*ReputationResponse_Audit)(nil), "multinode.ReputationResponse.Audit")
}
func init() { proto.RegisterFile("multinode.proto", fileDescriptor_9a45fd79b06f3a1b) }
var fileDescriptor_9a45fd79b06f3a1b = []byte{
// 514 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x52, 0xc1, 0x6e, 0xd3, 0x40,
0x10, 0x25, 0x34, 0x24, 0xf5, 0x24, 0x50, 0x58, 0x0e, 0x18, 0x93, 0x10, 0x64, 0x21, 0x11, 0x09,
0xc9, 0x46, 0xe9, 0x0f, 0xa0, 0x50, 0x15, 0x24, 0x0a, 0x2a, 0x4e, 0xc5, 0x81, 0x03, 0xd1, 0xc6,
0x9e, 0x3a, 0x4b, 0x6d, 0xaf, 0xd9, 0x5d, 0x07, 0xe5, 0x2f, 0x38, 0xf1, 0x3b, 0x5c, 0xf9, 0x0a,
0xf8, 0x15, 0x94, 0xf5, 0xc6, 0x71, 0xa0, 0x05, 0x29, 0xb7, 0x99, 0x37, 0x33, 0xef, 0x8d, 0x66,
0x1e, 0x1c, 0xa4, 0x45, 0xa2, 0x58, 0xc6, 0x23, 0xf4, 0x72, 0xc1, 0x15, 0x27, 0x56, 0x05, 0x38,
0x10, 0xf3, 0x98, 0x97, 0xb0, 0x33, 0x88, 0x39, 0x8f, 0x13, 0xf4, 0x75, 0x36, 0x2b, 0xce, 0x7d,
0xc5, 0x52, 0x94, 0x8a, 0xa6, 0x79, 0xd9, 0xe0, 0x0e, 0xe1, 0x66, 0x80, 0x9f, 0x0b, 0x94, 0xea,
0x15, 0xd2, 0x08, 0x05, 0xb9, 0x07, 0x6d, 0x9a, 0xb3, 0xe9, 0x05, 0x2e, 0xed, 0xc6, 0xa3, 0xc6,
0xb0, 0x1b, 0xb4, 0x68, 0xce, 0x5e, 0xe3, 0xd2, 0x3d, 0x82, 0xdb, 0x47, 0x4c, 0x5e, 0x4c, 0x72,
0x1a, 0xa2, 0x19, 0x21, 0xcf, 0xa0, 0x35, 0xd7, 0x63, 0xba, 0xb7, 0x33, 0xb2, 0xbd, 0xcd, 0x5e,
0x5b, 0xb4, 0x81, 0xe9, 0x73, 0xbf, 0x37, 0xe0, 0x4e, 0x8d, 0x46, 0xe6, 0x3c, 0x93, 0x48, 0x7a,
0x60, 0xd1, 0x24, 0xe1, 0x21, 0x55, 0x18, 0x69, 0xaa, 0xbd, 0x60, 0x03, 0x90, 0x01, 0x74, 0x0a,
0x89, 0xd1, 0x34, 0x67, 0x18, 0xa2, 0xb4, 0xaf, 0xeb, 0x3a, 0xac, 0xa0, 0x53, 0x8d, 0x90, 0x3e,
0xe8, 0x6c, 0xaa, 0x04, 0x95, 0x73, 0x7b, 0xaf, 0x9c, 0x5f, 0x21, 0x67, 0x2b, 0x80, 0x10, 0x68,
0x9e, 0x0b, 0x44, 0xbb, 0xa9, 0x0b, 0x3a, 0xd6, 0x8a, 0x0b, 0xca, 0x12, 0x3a, 0x4b, 0xd0, 0xbe,
0x61, 0x14, 0xd7, 0x00, 0x71, 0x60, 0x9f, 0x2f, 0x50, 0xac, 0x28, 0xec, 0x96, 0x2e, 0x56, 0xb9,
0x7b, 0x0a, 0xbd, 0x31, 0xcd, 0xa2, 0x2f, 0x2c, 0x52, 0xf3, 0x37, 0x3c, 0x53, 0xf3, 0x49, 0x91,
0xa6, 0x54, 0x2c, 0x77, 0xbf, 0xc9, 0x21, 0xf4, 0xaf, 0x60, 0x34, 0xe7, 0x21, 0xd0, 0xd4, 0xab,
0x94, 0x97, 0xd1, 0xb1, 0x3b, 0x86, 0x5b, 0xef, 0x51, 0x48, 0xc6, 0xb3, 0xdd, 0x85, 0x9f, 0xc2,
0x41, 0xc5, 0x61, 0xa4, 0x6c, 0x68, 0x2f, 0x4a, 0x48, 0xb3, 0x58, 0xc1, 0x3a, 0x75, 0x8f, 0x81,
0x9c, 0x50, 0xa9, 0x5e, 0xf0, 0x4c, 0xd1, 0x50, 0xed, 0x2e, 0xfa, 0x11, 0xee, 0x6e, 0xf1, 0x18,
0xe1, 0x97, 0xd0, 0x4d, 0xa8, 0x54, 0xd3, 0xb0, 0xc4, 0x0d, 0x9d, 0xe3, 0x95, 0x06, 0xf6, 0xd6,
0x06, 0xf6, 0xce, 0xd6, 0x06, 0x1e, 0xef, 0xff, 0xf8, 0x39, 0xb8, 0xf6, 0xf5, 0xd7, 0xa0, 0x11,
0x74, 0x92, 0x0d, 0xe1, 0xe8, 0x1d, 0xb4, 0x27, 0x8a, 0x0b, 0x1a, 0x23, 0x39, 0x06, 0xab, 0xf2,
0x1a, 0x79, 0x50, 0xdb, 0xec, 0x4f, 0x23, 0x3b, 0xbd, 0xcb, 0x8b, 0xe5, 0x6e, 0xa3, 0x0c, 0xac,
0xea, 0x41, 0x84, 0x42, 0xb7, 0xfe, 0x24, 0xf2, 0xa4, 0x36, 0xfa, 0x2f, 0x63, 0x38, 0xc3, 0xff,
0x37, 0x1a, 0xbd, 0x6f, 0x0d, 0x68, 0xbe, 0xe5, 0x11, 0x92, 0xe7, 0xd0, 0x36, 0x0f, 0x22, 0xf7,
0x6b, 0xd3, 0xdb, 0x8f, 0x77, 0x9c, 0xcb, 0x4a, 0xe6, 0xac, 0x27, 0xd0, 0xa9, 0x5d, 0x9b, 0xf4,
0x6b, 0xad, 0x7f, 0x7f, 0xd3, 0x79, 0x78, 0x55, 0xb9, 0x64, 0x1b, 0x3f, 0xfe, 0xe0, 0x4a, 0xc5,
0xc5, 0x27, 0x8f, 0x71, 0x5f, 0x07, 0x7e, 0x2e, 0xd8, 0x82, 0x2a, 0xf4, 0xab, 0xb9, 0x7c, 0x36,
0x6b, 0xe9, 0x67, 0x1d, 0xfe, 0x0e, 0x00, 0x00, 0xff, 0xff, 0x70, 0xf2, 0x78, 0x97, 0xa5, 0x04,
0x00, 0x00,
// 670 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x54, 0xcf, 0x6e, 0xd3, 0x4e,
0x10, 0xfe, 0xa5, 0xcd, 0x9f, 0x66, 0x92, 0x5f, 0xff, 0x2c, 0x48, 0x18, 0x93, 0x34, 0xc8, 0x54,
0xa2, 0x08, 0x29, 0x81, 0xf4, 0x84, 0xc4, 0x01, 0x42, 0x55, 0x5a, 0x51, 0xa0, 0x38, 0x15, 0x07,
0x0e, 0x44, 0x9b, 0x78, 0x9a, 0x2c, 0x75, 0xbc, 0xc6, 0xbb, 0x0e, 0xf4, 0x2d, 0x78, 0x23, 0xae,
0x3c, 0x03, 0x87, 0x22, 0x9e, 0x82, 0x2b, 0xf2, 0xee, 0xc6, 0x71, 0x4a, 0x5b, 0xa4, 0x72, 0xdb,
0xfd, 0xe6, 0x9b, 0xef, 0x1b, 0xef, 0xcc, 0x18, 0x56, 0xc6, 0xb1, 0x2f, 0x59, 0xc0, 0x3d, 0x6c,
0x86, 0x11, 0x97, 0x9c, 0x94, 0x53, 0xc0, 0x86, 0x21, 0x1f, 0x72, 0x0d, 0xdb, 0x8d, 0x21, 0xe7,
0x43, 0x1f, 0x5b, 0xea, 0xd6, 0x8f, 0x8f, 0x5a, 0x92, 0x8d, 0x51, 0x48, 0x3a, 0x0e, 0x35, 0xc1,
0xd9, 0x84, 0xff, 0x5d, 0xfc, 0x18, 0xa3, 0x90, 0xbb, 0x48, 0x3d, 0x8c, 0xc8, 0x0d, 0x28, 0xd1,
0x90, 0xf5, 0x8e, 0xf1, 0xc4, 0xca, 0xdd, 0xce, 0x6d, 0x56, 0xdd, 0x22, 0x0d, 0xd9, 0x0b, 0x3c,
0x71, 0xb6, 0x61, 0x75, 0x9b, 0x89, 0xe3, 0x6e, 0x48, 0x07, 0x68, 0x52, 0xc8, 0x03, 0x28, 0x8e,
0x54, 0x9a, 0xe2, 0x56, 0xda, 0x56, 0x73, 0x56, 0xd7, 0x9c, 0xac, 0x6b, 0x78, 0xce, 0xd7, 0x1c,
0xac, 0x65, 0x64, 0x44, 0xc8, 0x03, 0x81, 0xa4, 0x06, 0x65, 0xea, 0xfb, 0x7c, 0x40, 0x25, 0x7a,
0x4a, 0x6a, 0xd1, 0x9d, 0x01, 0xa4, 0x01, 0x95, 0x58, 0xa0, 0xd7, 0x0b, 0x19, 0x0e, 0x50, 0x58,
0x0b, 0x2a, 0x0e, 0x09, 0x74, 0xa0, 0x10, 0x52, 0x07, 0x75, 0xeb, 0xc9, 0x88, 0x8a, 0x91, 0xb5,
0xa8, 0xf3, 0x13, 0xe4, 0x30, 0x01, 0x08, 0x81, 0xfc, 0x51, 0x84, 0x68, 0xe5, 0x55, 0x40, 0x9d,
0x95, 0xe3, 0x84, 0x32, 0x9f, 0xf6, 0x7d, 0xb4, 0x0a, 0xc6, 0x71, 0x0a, 0x10, 0x1b, 0x96, 0xf8,
0x04, 0xa3, 0x44, 0xc2, 0x2a, 0xaa, 0x60, 0x7a, 0x77, 0x0e, 0xa0, 0xd6, 0xa1, 0x81, 0xf7, 0x89,
0x79, 0x72, 0xf4, 0x92, 0x07, 0x72, 0xd4, 0x8d, 0xc7, 0x63, 0x1a, 0x9d, 0x5c, 0xfd, 0x4d, 0xb6,
0xa0, 0x7e, 0x81, 0xa2, 0x79, 0x1e, 0x02, 0x79, 0x55, 0x8a, 0x7e, 0x19, 0x75, 0x76, 0x3a, 0xb0,
0xfc, 0x16, 0x23, 0xc1, 0x78, 0x70, 0x75, 0xe3, 0xfb, 0xb0, 0x92, 0x6a, 0x18, 0x2b, 0x0b, 0x4a,
0x13, 0x0d, 0x29, 0x95, 0xb2, 0x3b, 0xbd, 0x3a, 0x3b, 0x40, 0xf6, 0xa9, 0x90, 0xcf, 0x78, 0x20,
0xe9, 0x40, 0x5e, 0xdd, 0xf4, 0x3d, 0x5c, 0x9b, 0xd3, 0x31, 0xc6, 0xcf, 0xa1, 0xea, 0x53, 0x21,
0x7b, 0x03, 0x8d, 0x1b, 0x39, 0xbb, 0xa9, 0x07, 0xb8, 0x39, 0x1d, 0xe0, 0xe6, 0xe1, 0x74, 0x80,
0x3b, 0x4b, 0xdf, 0x4e, 0x1b, 0xff, 0x7d, 0xf9, 0xd1, 0xc8, 0xb9, 0x15, 0x7f, 0x26, 0xe8, 0x7c,
0x86, 0x35, 0x17, 0xc3, 0x58, 0x52, 0xf9, 0x2f, 0x6f, 0x43, 0x1e, 0x42, 0x55, 0x50, 0x89, 0xbe,
0xcf, 0x24, 0xf6, 0x98, 0xa7, 0xa6, 0xae, 0xda, 0x59, 0x4e, 0x3c, 0xbf, 0x9f, 0x36, 0x8a, 0xaf,
0xb8, 0x87, 0x7b, 0xdb, 0x6e, 0x25, 0xe5, 0xec, 0x79, 0xce, 0xaf, 0x1c, 0x90, 0xac, 0xb5, 0xf9,
0xb2, 0xc7, 0x50, 0xe4, 0x81, 0xcf, 0x02, 0x34, 0xde, 0x1b, 0x73, 0xde, 0x67, 0xe9, 0xcd, 0xd7,
0x8a, 0xeb, 0x9a, 0x1c, 0xf2, 0x08, 0x0a, 0x34, 0xf6, 0x98, 0x54, 0x05, 0x54, 0xda, 0x77, 0x2e,
0x4f, 0x7e, 0x9a, 0x50, 0x5d, 0x9d, 0x61, 0xaf, 0x43, 0x51, 0x8b, 0x91, 0xeb, 0x50, 0x10, 0x03,
0x1e, 0xe9, 0x0a, 0x72, 0xae, 0xbe, 0xd8, 0xbb, 0x50, 0x50, 0xfc, 0xf3, 0xc3, 0xe4, 0x1e, 0xac,
0x8a, 0x58, 0x84, 0x18, 0x24, 0xed, 0xef, 0x69, 0xc2, 0x82, 0x22, 0xac, 0xcc, 0xf0, 0x6e, 0x02,
0xb7, 0xdf, 0x40, 0xa9, 0x2b, 0x79, 0x44, 0x87, 0x48, 0x76, 0xa0, 0x9c, 0xee, 0x37, 0xb9, 0x95,
0xa9, 0xf6, 0xec, 0xcf, 0xc3, 0xae, 0x9d, 0x1f, 0xd4, 0x5f, 0xd2, 0x0e, 0xa0, 0x9c, 0x2e, 0x05,
0xa1, 0x50, 0xcd, 0x2e, 0x06, 0xb9, 0x9b, 0x49, 0xbd, 0x6c, 0x19, 0xed, 0xcd, 0xbf, 0x13, 0x8d,
0xdf, 0xcf, 0x1c, 0xe4, 0x93, 0xa6, 0x92, 0x27, 0x50, 0x32, 0x4b, 0x41, 0x6e, 0x66, 0xb2, 0xe7,
0x97, 0xcd, 0xb6, 0xcf, 0x0b, 0x99, 0x86, 0xef, 0x43, 0x25, 0x33, 0xe1, 0xa4, 0x9e, 0xa1, 0xfe,
0xb9, 0x41, 0xf6, 0xfa, 0x45, 0x61, 0xa3, 0xb6, 0x07, 0x30, 0x6b, 0x34, 0xa9, 0x5d, 0xd0, 0x7f,
0xad, 0x55, 0xbf, 0x74, 0x3a, 0x3a, 0x1b, 0xef, 0x1c, 0x21, 0x79, 0xf4, 0xa1, 0xc9, 0x78, 0x4b,
0x1d, 0x5a, 0x61, 0xc4, 0x26, 0x54, 0x62, 0x2b, 0x4d, 0x0b, 0xfb, 0xfd, 0xa2, 0xda, 0xb5, 0xad,
0xdf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x8e, 0x0c, 0xc4, 0x6b, 0x64, 0x06, 0x00, 0x00,
}
// --- DRPC BEGIN ---
@ -604,6 +786,7 @@ type DRPCNodeClient interface {
Version(ctx context.Context, in *VersionRequest) (*VersionResponse, error)
LastContact(ctx context.Context, in *LastContactRequest) (*LastContactResponse, error)
Reputation(ctx context.Context, in *ReputationRequest) (*ReputationResponse, error)
}
type drpcNodeClient struct {
@ -634,14 +817,24 @@ func (c *drpcNodeClient) LastContact(ctx context.Context, in *LastContactRequest
return out, nil
}
func (c *drpcNodeClient) Reputation(ctx context.Context, in *ReputationRequest) (*ReputationResponse, error) {
out := new(ReputationResponse)
err := c.cc.Invoke(ctx, "/multinode.Node/Reputation", in, out)
if err != nil {
return nil, err
}
return out, nil
}
type DRPCNodeServer interface {
Version(context.Context, *VersionRequest) (*VersionResponse, error)
LastContact(context.Context, *LastContactRequest) (*LastContactResponse, error)
Reputation(context.Context, *ReputationRequest) (*ReputationResponse, error)
}
type DRPCNodeDescription struct{}
func (DRPCNodeDescription) NumMethods() int { return 2 }
func (DRPCNodeDescription) NumMethods() int { return 3 }
func (DRPCNodeDescription) Method(n int) (string, drpc.Receiver, interface{}, bool) {
switch n {
@ -663,6 +856,15 @@ func (DRPCNodeDescription) Method(n int) (string, drpc.Receiver, interface{}, bo
in1.(*LastContactRequest),
)
}, DRPCNodeServer.LastContact, true
case 2:
return "/multinode.Node/Reputation",
func(srv interface{}, ctx context.Context, in1, in2 interface{}) (drpc.Message, error) {
return srv.(DRPCNodeServer).
Reputation(
ctx,
in1.(*ReputationRequest),
)
}, DRPCNodeServer.Reputation, true
default:
return "", nil, nil, false
}
@ -704,4 +906,20 @@ func (x *drpcNodeLastContactStream) SendAndClose(m *LastContactResponse) error {
return x.CloseSend()
}
type DRPCNode_ReputationStream interface {
drpc.Stream
SendAndClose(*ReputationResponse) error
}
type drpcNodeReputationStream struct {
drpc.Stream
}
func (x *drpcNodeReputationStream) SendAndClose(m *ReputationResponse) error {
if err := x.MsgSend(m); err != nil {
return err
}
return x.CloseSend()
}
// --- DRPC END ---

View File

@ -45,6 +45,7 @@ message BandwidthMonthSummaryResponse {
service Node {
rpc Version(VersionRequest) returns (VersionResponse);
rpc LastContact(LastContactRequest) returns (LastContactResponse);
rpc Reputation(ReputationRequest) returns (ReputationResponse);
}
message VersionRequest {
@ -62,3 +63,21 @@ message LastContactRequest {
message LastContactResponse {
google.protobuf.Timestamp last_contact = 1 [(gogoproto.stdtime) = true, (gogoproto.nullable) = false];
}
message ReputationRequest {
RequestHeader header = 1;
bytes satellite_id = 2 [(gogoproto.customtype) = "NodeID", (gogoproto.nullable) = false];
}
message ReputationResponse {
message Online {
double score = 1;
}
message Audit {
double score = 1;
double suspension_score = 2;
}
Online online = 1;
Audit audit = 2;
}

View File

@ -13,6 +13,7 @@ import (
"storj.io/storj/private/multinodepb"
"storj.io/storj/storagenode/apikeys"
"storj.io/storj/storagenode/contact"
"storj.io/storj/storagenode/reputation"
)
var _ multinodepb.DRPCNodeServer = (*NodeEndpoint)(nil)
@ -21,19 +22,21 @@ var _ multinodepb.DRPCNodeServer = (*NodeEndpoint)(nil)
//
// architecture: Endpoint
type NodeEndpoint struct {
log *zap.Logger
apiKeys *apikeys.Service
version version.Info
contact *contact.PingStats
log *zap.Logger
apiKeys *apikeys.Service
version version.Info
contact *contact.PingStats
reputation reputation.DB
}
// NewNodeEndpoint creates new multinode node endpoint.
func NewNodeEndpoint(log *zap.Logger, apiKeys *apikeys.Service, version version.Info, contact *contact.PingStats) *NodeEndpoint {
func NewNodeEndpoint(log *zap.Logger, apiKeys *apikeys.Service, version version.Info, contact *contact.PingStats, reputation reputation.DB) *NodeEndpoint {
return &NodeEndpoint{
log: log,
apiKeys: apiKeys,
version: version,
contact: contact,
log: log,
apiKeys: apiKeys,
version: version,
contact: contact,
reputation: reputation,
}
}
@ -62,3 +65,27 @@ func (node *NodeEndpoint) LastContact(ctx context.Context, req *multinodepb.Last
LastContact: node.contact.WhenLastPinged(),
}, nil
}
// Reputation returns reputation for specific satellite.
func (node *NodeEndpoint) Reputation(ctx context.Context, req *multinodepb.ReputationRequest) (_ *multinodepb.ReputationResponse, err error) {
defer mon.Task()(&ctx)(&err)
if err = authenticate(ctx, node.apiKeys, req.GetHeader()); err != nil {
return nil, rpcstatus.Wrap(rpcstatus.Unauthenticated, err)
}
rep, err := node.reputation.Get(ctx, req.SatelliteId)
if err != nil {
return nil, rpcstatus.Wrap(rpcstatus.Internal, err)
}
return &multinodepb.ReputationResponse{
Online: &multinodepb.ReputationResponse_Online{
Score: rep.OnlineScore,
},
Audit: &multinodepb.ReputationResponse_Audit{
Score: rep.Audit.Score,
SuspensionScore: rep.Audit.UnknownScore,
},
}, nil
}

View File

@ -795,7 +795,8 @@ func New(log *zap.Logger, full *identity.FullIdentity, db DB, revocationDB exten
peer.Log.Named("multinode:node-endpoint"),
apiKeys,
peer.Version.Service.Info,
peer.Contact.PingStats)
peer.Contact.PingStats,
peer.DB.Reputation())
if err = multinodepb.DRPCRegisterStorage(peer.Server.DRPC(), peer.Multinode.Storage); err != nil {
return nil, errs.Combine(err, peer.Close())