storagenode/console: Add current storage used per satellite to storagenode api

Right now, the best way for a storage node operator to get the current
space used for each satellite is to run the `storagenode exit-satellite`
command for graceful exit, and cancel at the second confirmation prompt.
This is convoluted and the data is readily available from the Blobs
Usage Cache.

This change adds the current space used by each satellite to the
endpoints `/api/sno` and `/api/sno/satellite/<Satellite ID>`

Change-Id: I2173005bb016fc76db96fd598d26b485e5b2aa0b
This commit is contained in:
Moby von Briesen 2020-10-14 12:37:50 -04:00 committed by Stefan Benten
parent 0b43b93259
commit aa86c0889c
2 changed files with 56 additions and 33 deletions

View File

@ -40,6 +40,7 @@ var (
type Service struct { type Service struct {
log *zap.Logger log *zap.Logger
trust *trust.Pool trust *trust.Pool
usageCache *pieces.BlobsUsageCache
bandwidthDB bandwidth.DB bandwidthDB bandwidth.DB
reputationDB reputation.DB reputationDB reputation.DB
storageUsageDB storageusage.DB storageUsageDB storageusage.DB
@ -62,11 +63,16 @@ type Service struct {
// NewService returns new instance of Service. // NewService returns new instance of Service.
func NewService(log *zap.Logger, bandwidth bandwidth.DB, pieceStore *pieces.Store, version *checker.Service, func NewService(log *zap.Logger, bandwidth bandwidth.DB, pieceStore *pieces.Store, version *checker.Service,
allocatedDiskSpace memory.Size, walletAddress string, versionInfo version.Info, trust *trust.Pool, allocatedDiskSpace memory.Size, walletAddress string, versionInfo version.Info, trust *trust.Pool,
reputationDB reputation.DB, storageUsageDB storageusage.DB, pricingDB pricing.DB, satelliteDB satellites.DB, pingStats *contact.PingStats, contact *contact.Service, estimation *estimatedpayout.Service) (*Service, error) { reputationDB reputation.DB, storageUsageDB storageusage.DB, pricingDB pricing.DB, satelliteDB satellites.DB,
pingStats *contact.PingStats, contact *contact.Service, estimation *estimatedpayout.Service, usageCache *pieces.BlobsUsageCache) (*Service, error) {
if log == nil { if log == nil {
return nil, errs.New("log can't be nil") return nil, errs.New("log can't be nil")
} }
if usageCache == nil {
return nil, errs.New("usage cache can't be nil")
}
if bandwidth == nil { if bandwidth == nil {
return nil, errs.New("bandwidth can't be nil") return nil, errs.New("bandwidth can't be nil")
} }
@ -94,6 +100,7 @@ func NewService(log *zap.Logger, bandwidth bandwidth.DB, pieceStore *pieces.Stor
return &Service{ return &Service{
log: log, log: log,
trust: trust, trust: trust,
usageCache: usageCache,
bandwidthDB: bandwidth, bandwidthDB: bandwidth,
reputationDB: reputationDB, reputationDB: reputationDB,
storageUsageDB: storageUsageDB, storageUsageDB: storageUsageDB,
@ -113,10 +120,11 @@ func NewService(log *zap.Logger, bandwidth bandwidth.DB, pieceStore *pieces.Stor
// SatelliteInfo encapsulates satellite ID and disqualification. // SatelliteInfo encapsulates satellite ID and disqualification.
type SatelliteInfo struct { type SatelliteInfo struct {
ID storj.NodeID `json:"id"` ID storj.NodeID `json:"id"`
URL string `json:"url"` URL string `json:"url"`
Disqualified *time.Time `json:"disqualified"` Disqualified *time.Time `json:"disqualified"`
Suspended *time.Time `json:"suspended"` Suspended *time.Time `json:"suspended"`
CurrentStorageUsed int64 `json:"currentStorageUsed"`
} }
// Dashboard encapsulates dashboard stale data. // Dashboard encapsulates dashboard stale data.
@ -163,13 +171,20 @@ func (s *Service) GetDashboardData(ctx context.Context) (_ *Dashboard, err error
zap.Error(SNOServiceErr.Wrap(err))) zap.Error(SNOServiceErr.Wrap(err)))
continue continue
} }
_, currentStorageUsed, err := s.usageCache.SpaceUsedBySatellite(ctx, rep.SatelliteID)
if err != nil {
s.log.Warn("unable to get Satellite Current Storage Used", zap.String("Satellite ID", rep.SatelliteID.String()),
zap.Error(SNOServiceErr.Wrap(err)))
continue
}
data.Satellites = append(data.Satellites, data.Satellites = append(data.Satellites,
SatelliteInfo{ SatelliteInfo{
ID: rep.SatelliteID, ID: rep.SatelliteID,
Disqualified: rep.DisqualifiedAt, Disqualified: rep.DisqualifiedAt,
Suspended: rep.SuspendedAt, Suspended: rep.SuspendedAt,
URL: url.Address, URL: url.Address,
CurrentStorageUsed: currentStorageUsed,
}, },
) )
} }
@ -212,18 +227,19 @@ type PriceModel struct {
// Satellite encapsulates satellite related data. // Satellite encapsulates satellite related data.
type Satellite struct { type Satellite struct {
ID storj.NodeID `json:"id"` ID storj.NodeID `json:"id"`
StorageDaily []storageusage.Stamp `json:"storageDaily"` StorageDaily []storageusage.Stamp `json:"storageDaily"`
BandwidthDaily []bandwidth.UsageRollup `json:"bandwidthDaily"` BandwidthDaily []bandwidth.UsageRollup `json:"bandwidthDaily"`
StorageSummary float64 `json:"storageSummary"` StorageSummary float64 `json:"storageSummary"`
BandwidthSummary int64 `json:"bandwidthSummary"` BandwidthSummary int64 `json:"bandwidthSummary"`
EgressSummary int64 `json:"egressSummary"` EgressSummary int64 `json:"egressSummary"`
IngressSummary int64 `json:"ingressSummary"` IngressSummary int64 `json:"ingressSummary"`
Audit reputation.Metric `json:"audit"` CurrentStorageUsed int64 `json:"currentStorageUsed"`
Uptime reputation.Metric `json:"uptime"` Audit reputation.Metric `json:"audit"`
OnlineScore float64 `json:"onlineScore"` Uptime reputation.Metric `json:"uptime"`
PriceModel PriceModel `json:"priceModel"` OnlineScore float64 `json:"onlineScore"`
NodeJoinedAt time.Time `json:"nodeJoinedAt"` PriceModel PriceModel `json:"priceModel"`
NodeJoinedAt time.Time `json:"nodeJoinedAt"`
} }
// GetSatelliteData returns satellite related data. // GetSatelliteData returns satellite related data.
@ -261,6 +277,11 @@ func (s *Service) GetSatelliteData(ctx context.Context, satelliteID storj.NodeID
return nil, SNOServiceErr.Wrap(err) return nil, SNOServiceErr.Wrap(err)
} }
_, currentStorageUsed, err := s.usageCache.SpaceUsedBySatellite(ctx, satelliteID)
if err != nil {
return nil, SNOServiceErr.Wrap(err)
}
rep, err := s.reputationDB.Get(ctx, satelliteID) rep, err := s.reputationDB.Get(ctx, satelliteID)
if err != nil { if err != nil {
return nil, SNOServiceErr.Wrap(err) return nil, SNOServiceErr.Wrap(err)
@ -279,18 +300,19 @@ func (s *Service) GetSatelliteData(ctx context.Context, satelliteID storj.NodeID
} }
return &Satellite{ return &Satellite{
ID: satelliteID, ID: satelliteID,
StorageDaily: storageDaily, StorageDaily: storageDaily,
BandwidthDaily: bandwidthDaily, BandwidthDaily: bandwidthDaily,
StorageSummary: storageSummary, StorageSummary: storageSummary,
BandwidthSummary: bandwidthSummary.Total(), BandwidthSummary: bandwidthSummary.Total(),
EgressSummary: egressSummary.Total(), CurrentStorageUsed: currentStorageUsed,
IngressSummary: ingressSummary.Total(), EgressSummary: egressSummary.Total(),
Audit: rep.Audit, IngressSummary: ingressSummary.Total(),
Uptime: rep.Uptime, Audit: rep.Audit,
OnlineScore: rep.OnlineScore, Uptime: rep.Uptime,
PriceModel: satellitePricing, OnlineScore: rep.OnlineScore,
NodeJoinedAt: rep.JoinedAt, PriceModel: satellitePricing,
NodeJoinedAt: rep.JoinedAt,
}, nil }, nil
} }

View File

@ -619,6 +619,7 @@ func New(log *zap.Logger, full *identity.FullIdentity, db DB, revocationDB exten
peer.Contact.PingStats, peer.Contact.PingStats,
peer.Contact.Service, peer.Contact.Service,
peer.Estimation.Service, peer.Estimation.Service,
peer.Storage2.BlobsCache,
) )
if err != nil { if err != nil {
return nil, errs.Combine(err, peer.Close()) return nil, errs.Combine(err, peer.Close())