mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-09-25 01:14:50 +00:00
CHAP authentication (RFC 7143 S12.1): - auth.go: CHAPAuthenticator with MD5 challenge-response, ValidateCHAPConfig - login.go: multi-PDU SecurityNeg flow (challenge → verify → transit) - main.go: -chap-user/-chap-secret CLI flags with validation Online volume expand: - blockvol.go: Expand() with flusher pause, snapMu TOCTOU guard, alignment check - Rejects shrink (ErrShrinkNotSupported) and resize with active snapshots Prometheus metrics: - metrics.go: metricsAdapter wrapping BlockDevice, 15 metrics (counters, histograms, gauge funcs for WAL/dirty-map/epoch/role/snapshots) - Dedicated prometheus.NewRegistry() per server instance Admin HTTP endpoints: - POST /snapshot (create/delete/restore/list) - POST /resize (online expand) - GET /metrics (Prometheus text format) - VolumeSize added to /status response Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
145 lines
3.5 KiB
Go
145 lines
3.5 KiB
Go
package blockvol
|
|
|
|
import (
|
|
"bytes"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
)
|
|
|
|
// TestResize_ExpandWorks grows a 1MB volume to 2MB, writes to the new region,
|
|
// and reads back to verify.
|
|
func TestResize_ExpandWorks(t *testing.T) {
|
|
dir := t.TempDir()
|
|
path := filepath.Join(dir, "expand.blk")
|
|
|
|
vol, err := CreateBlockVol(path, CreateOptions{
|
|
VolumeSize: 1024 * 1024, // 1MB
|
|
BlockSize: 4096,
|
|
WALSize: 64 * 1024, // 64KB (small for test)
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("create: %v", err)
|
|
}
|
|
defer vol.Close()
|
|
|
|
// Write to last block of original size.
|
|
lastLBA := uint64((1024*1024)/4096 - 1)
|
|
data := make([]byte, 4096)
|
|
for i := range data {
|
|
data[i] = 0xAA
|
|
}
|
|
if err := vol.WriteLBA(lastLBA, data); err != nil {
|
|
t.Fatalf("write last block: %v", err)
|
|
}
|
|
|
|
// Expand to 2MB.
|
|
newSize := uint64(2 * 1024 * 1024)
|
|
if err := vol.Expand(newSize); err != nil {
|
|
t.Fatalf("expand: %v", err)
|
|
}
|
|
|
|
// Verify volume size updated.
|
|
if vol.Info().VolumeSize != newSize {
|
|
t.Fatalf("expected VolumeSize=%d, got %d", newSize, vol.Info().VolumeSize)
|
|
}
|
|
|
|
// Write to a block in the new region.
|
|
newLBA := uint64((1024 * 1024) / 4096) // first block in expanded region
|
|
data2 := make([]byte, 4096)
|
|
for i := range data2 {
|
|
data2[i] = 0xBB
|
|
}
|
|
if err := vol.WriteLBA(newLBA, data2); err != nil {
|
|
t.Fatalf("write new region: %v", err)
|
|
}
|
|
|
|
// Read back old data.
|
|
got, err := vol.ReadLBA(lastLBA, 4096)
|
|
if err != nil {
|
|
t.Fatalf("read old block: %v", err)
|
|
}
|
|
if !bytes.Equal(got, data) {
|
|
t.Fatal("old block data mismatch after expand")
|
|
}
|
|
|
|
// Read back new data.
|
|
got2, err := vol.ReadLBA(newLBA, 4096)
|
|
if err != nil {
|
|
t.Fatalf("read new block: %v", err)
|
|
}
|
|
if !bytes.Equal(got2, data2) {
|
|
t.Fatal("new block data mismatch after expand")
|
|
}
|
|
|
|
// Verify file size on disk.
|
|
fi, _ := os.Stat(path)
|
|
extentStart := vol.super.WALOffset + vol.super.WALSize
|
|
expected := int64(extentStart + newSize)
|
|
if fi.Size() != expected {
|
|
t.Fatalf("file size: expected %d, got %d", expected, fi.Size())
|
|
}
|
|
}
|
|
|
|
// TestResize_ShrinkRejected verifies that attempting to shrink returns an error.
|
|
func TestResize_ShrinkRejected(t *testing.T) {
|
|
dir := t.TempDir()
|
|
path := filepath.Join(dir, "shrink.blk")
|
|
|
|
vol, err := CreateBlockVol(path, CreateOptions{
|
|
VolumeSize: 1024 * 1024,
|
|
BlockSize: 4096,
|
|
WALSize: 64 * 1024,
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("create: %v", err)
|
|
}
|
|
defer vol.Close()
|
|
|
|
err = vol.Expand(512 * 1024) // shrink
|
|
if err != ErrShrinkNotSupported {
|
|
t.Fatalf("expected ErrShrinkNotSupported, got %v", err)
|
|
}
|
|
|
|
// Same size = no-op.
|
|
if err := vol.Expand(1024 * 1024); err != nil {
|
|
t.Fatalf("same-size expand should be no-op: %v", err)
|
|
}
|
|
}
|
|
|
|
// TestResize_WithSnapshotsRejected verifies that resize is blocked when
|
|
// snapshots are active.
|
|
func TestResize_WithSnapshotsRejected(t *testing.T) {
|
|
dir := t.TempDir()
|
|
path := filepath.Join(dir, "snap-resize.blk")
|
|
|
|
vol, err := CreateBlockVol(path, CreateOptions{
|
|
VolumeSize: 1024 * 1024,
|
|
BlockSize: 4096,
|
|
WALSize: 64 * 1024,
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("create: %v", err)
|
|
}
|
|
defer vol.Close()
|
|
|
|
// Create a snapshot.
|
|
if err := vol.CreateSnapshot(1); err != nil {
|
|
t.Fatalf("create snapshot: %v", err)
|
|
}
|
|
|
|
// Try to expand -- should fail.
|
|
err = vol.Expand(2 * 1024 * 1024)
|
|
if err != ErrSnapshotsPreventResize {
|
|
t.Fatalf("expected ErrSnapshotsPreventResize, got %v", err)
|
|
}
|
|
|
|
// Delete snapshot, then expand should work.
|
|
if err := vol.DeleteSnapshot(1); err != nil {
|
|
t.Fatalf("delete snapshot: %v", err)
|
|
}
|
|
if err := vol.Expand(2 * 1024 * 1024); err != nil {
|
|
t.Fatalf("expand after snapshot delete: %v", err)
|
|
}
|
|
}
|