ec777855e1
Implements logic for satellite command to repair a single segment. Segment will be repaired even if it's healthy. This is not checked during this process. As a part of repair command will download whole segment into memory and will try to reupload segment to number of new nodes that equal to existing number of pieces. After successful upload new pieces will completely replace existing pieces. Command: satellite repair-segment <streamid> <position> https://github.com/storj/storj/issues/5254 Change-Id: I8e329718ecf8e457dbee3434e1c68951699007d9
77 lines
2.4 KiB
Go
77 lines
2.4 KiB
Go
// Copyright (C) 2022 Storj Labs, Inc.
|
|
// See LICENSE for copying information.
|
|
|
|
package main
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
"go.uber.org/zap"
|
|
"go.uber.org/zap/zaptest"
|
|
"go.uber.org/zap/zaptest/observer"
|
|
|
|
"storj.io/common/memory"
|
|
"storj.io/common/storj"
|
|
"storj.io/common/testcontext"
|
|
"storj.io/common/testrand"
|
|
"storj.io/storj/private/testplanet"
|
|
)
|
|
|
|
func TestRepairSegment(t *testing.T) {
|
|
testplanet.Run(t, testplanet.Config{
|
|
SatelliteCount: 1, StorageNodeCount: 20, UplinkCount: 1,
|
|
Reconfigure: testplanet.Reconfigure{
|
|
Satellite: testplanet.ReconfigureRS(2, 4, 6, 8),
|
|
},
|
|
}, func(t *testing.T, ctx *testcontext.Context, planet *testplanet.Planet) {
|
|
satellite := planet.Satellites[0]
|
|
|
|
expectedData := testrand.Bytes(20 * memory.KiB)
|
|
err := planet.Uplinks[0].Upload(ctx, planet.Satellites[0], "bucket", "object", expectedData)
|
|
require.NoError(t, err)
|
|
|
|
segments, err := planet.Satellites[0].Metabase.DB.TestingAllSegments(ctx)
|
|
require.NoError(t, err)
|
|
require.Len(t, segments, 1)
|
|
|
|
err = repairSegment(ctx, zaptest.NewLogger(t), satellite.Repairer, satellite.Metabase.DB, segments[0])
|
|
require.NoError(t, err)
|
|
|
|
data, err := planet.Uplinks[0].Download(ctx, planet.Satellites[0], "bucket", "object")
|
|
require.NoError(t, err)
|
|
require.Equal(t, expectedData, data)
|
|
|
|
segmentsAfter, err := planet.Satellites[0].Metabase.DB.TestingAllSegments(ctx)
|
|
require.NoError(t, err)
|
|
require.Len(t, segmentsAfter, 1)
|
|
|
|
// verify that there are no nodes from before repair as we replacing all of them
|
|
require.NotEqual(t, segments[0].Pieces, segmentsAfter[0].Pieces)
|
|
oldNodes := map[storj.NodeID]struct{}{}
|
|
for _, piece := range segments[0].Pieces {
|
|
oldNodes[piece.StorageNode] = struct{}{}
|
|
}
|
|
|
|
for _, piece := range segmentsAfter[0].Pieces {
|
|
_, found := oldNodes[piece.StorageNode]
|
|
require.False(t, found)
|
|
}
|
|
|
|
// delete all pieces
|
|
for _, node := range planet.StorageNodes {
|
|
err := node.Storage2.Store.DeleteSatelliteBlobs(ctx, planet.Satellites[0].ID())
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
// we cannot download segment so repair is not possible
|
|
observedZapCore, observedLogs := observer.New(zap.ErrorLevel)
|
|
observedLogger := zap.New(observedZapCore)
|
|
err = repairSegment(ctx, observedLogger, satellite.Repairer, satellite.Metabase.DB, segments[0])
|
|
require.NoError(t, err)
|
|
require.Contains(t, "download failed", observedLogs.All()[observedLogs.Len()-1].Message)
|
|
|
|
// TODO add more detailed tests
|
|
})
|
|
}
|