mirror of
https://github.com/kopia/kopia.git
synced 2025-12-23 22:57:50 -05:00
Supported are:
```
$ kopia throttle set \
--download-bytes-per-second=N | unlimited
--upload-bytes-per-second=N | unlimited
--read-requests-per-second=N | unlimited
--write-requests-per-second=N | unlimited
--list-requests-per-second=N | unlimited
--concurrent-reads=N | unlimited
--concurrent-writes=N | unlimited
```
To change parameters of a running server use:
```
$ kopia server throttle set \
--address=<server-url> \
--server-control-password=<password> \
--download-bytes-per-second=N | unlimited
--upload-bytes-per-second=N | unlimited
--read-requests-per-second=N | unlimited
--write-requests-per-second=N | unlimited
--list-requests-per-second=N | unlimited
--concurrent-reads=N | unlimited
--concurrent-writes=N | unlimited
```
174 lines
7.0 KiB
Go
174 lines
7.0 KiB
Go
package cli_test
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/kopia/kopia/internal/testutil"
|
|
"github.com/kopia/kopia/repo/blob/throttling"
|
|
"github.com/kopia/kopia/tests/testenv"
|
|
)
|
|
|
|
func TestServerControl(t *testing.T) {
|
|
env := testenv.NewCLITest(t, testenv.RepoFormatNotImportant, testenv.NewInProcRunner(t))
|
|
|
|
dir0 := testutil.TempDirectory(t)
|
|
dir1 := testutil.TempDirectory(t)
|
|
dir2 := testutil.TempDirectory(t)
|
|
dir3 := testutil.TempDirectory(t)
|
|
|
|
env.RunAndExpectSuccess(t, "repo", "create", "filesystem", "--path", env.RepoDir, "--override-username=another-user", "--override-hostname=another-host")
|
|
env.RunAndExpectSuccess(t, "snap", "create", dir0)
|
|
|
|
env.RunAndExpectSuccess(t, "repo", "connect", "filesystem", "--path", env.RepoDir, "--override-username=test-user", "--override-hostname=test-host")
|
|
env.RunAndExpectSuccess(t, "snap", "create", dir1)
|
|
env.RunAndExpectSuccess(t, "snap", "create", dir2)
|
|
|
|
serverStarted := make(chan struct{})
|
|
serverStopped := make(chan struct{})
|
|
|
|
var sp testutil.ServerParameters
|
|
|
|
go func() {
|
|
wait, _ := env.RunAndProcessStderr(t, sp.ProcessOutput,
|
|
"server", "start", "--insecure", "--random-server-control-password", "--address=127.0.0.1:0")
|
|
|
|
close(serverStarted)
|
|
|
|
wait()
|
|
|
|
close(serverStopped)
|
|
}()
|
|
|
|
select {
|
|
case <-serverStarted:
|
|
t.Logf("server started on %v", sp.BaseURL)
|
|
|
|
case <-time.After(5 * time.Second):
|
|
t.Fatalf("server did not start in time")
|
|
}
|
|
|
|
const (
|
|
pollFrequency = 100 * time.Millisecond
|
|
waitTimeout = 15 * time.Second
|
|
)
|
|
|
|
require.Eventually(t, func() bool {
|
|
lines := env.RunAndExpectSuccess(t, "server", "status", "--address", sp.BaseURL, "--server-control-password", sp.ServerControlPassword)
|
|
t.Logf("lines: %v", lines)
|
|
return hasLine(lines, "IDLE: test-user@test-host:"+dir1) && hasLine(lines, "IDLE: test-user@test-host:"+dir2)
|
|
}, waitTimeout, pollFrequency)
|
|
|
|
lines := env.RunAndExpectSuccess(t, "server", "status", "--address", sp.BaseURL, "--server-control-password", sp.ServerControlPassword, "--remote")
|
|
require.Len(t, lines, 3)
|
|
require.Contains(t, lines, "IDLE: test-user@test-host:"+dir1)
|
|
require.Contains(t, lines, "IDLE: test-user@test-host:"+dir2)
|
|
require.Contains(t, lines, "REMOTE: another-user@another-host:"+dir0)
|
|
|
|
// create snapshot outside of the server
|
|
env.RunAndExpectSuccess(t, "snap", "create", dir3)
|
|
env.RunAndExpectSuccess(t, "server", "refresh", "--address", sp.BaseURL, "--server-control-password", sp.ServerControlPassword)
|
|
|
|
require.Eventually(t, func() bool {
|
|
lines := env.RunAndExpectSuccess(t, "server", "status", "--address", sp.BaseURL, "--server-control-password", sp.ServerControlPassword, "--remote")
|
|
t.Logf("lines: %v", lines)
|
|
return hasLine(lines, "IDLE: test-user@test-host:"+dir3)
|
|
}, waitTimeout, pollFrequency)
|
|
|
|
env.RunAndExpectSuccess(t, "server", "flush", "--address", sp.BaseURL, "--server-control-password", sp.ServerControlPassword)
|
|
|
|
// trigger server snapshot
|
|
env.RunAndExpectSuccess(t, "server", "snapshot", "--address", sp.BaseURL, "--server-control-password", sp.ServerControlPassword, "--all")
|
|
env.RunAndExpectSuccess(t, "server", "snapshot", "--address", sp.BaseURL, "--server-control-password", sp.ServerControlPassword, dir1)
|
|
env.RunAndExpectFailure(t, "server", "snapshot", "--address", sp.BaseURL, "--server-control-password", sp.ServerControlPassword, "no-such-dir")
|
|
|
|
// neither dir nor --all specified
|
|
env.RunAndExpectFailure(t, "server", "snapshot", "--address", sp.BaseURL, "--server-control-password", sp.ServerControlPassword)
|
|
|
|
// cancel snapshot
|
|
env.RunAndExpectSuccess(t, "server", "cancel", "--address", sp.BaseURL, "--server-control-password", sp.ServerControlPassword, "--all")
|
|
|
|
env.RunAndExpectSuccess(t, "server", "pause", "--address", sp.BaseURL, "--server-control-password", sp.ServerControlPassword, dir1)
|
|
env.RunAndExpectSuccess(t, "server", "resume", "--address", sp.BaseURL, "--server-control-password", sp.ServerControlPassword, dir1)
|
|
|
|
env.RunAndExpectSuccess(t, "server", "throttle", "set", "--address", sp.BaseURL, "--server-control-password", sp.ServerControlPassword,
|
|
"--download-bytes-per-second=1000000000",
|
|
"--upload-bytes-per-second=2000000000",
|
|
"--read-requests-per-second=300",
|
|
"--write-requests-per-second=400",
|
|
"--list-requests-per-second=500",
|
|
"--concurrent-reads=300",
|
|
"--concurrent-writes=400",
|
|
)
|
|
|
|
require.Equal(t, []string{
|
|
"Max Download Speed: 1 GB/s",
|
|
"Max Upload Speed: 2 GB/s",
|
|
"Max Read Requests Per Second: 300",
|
|
"Max Write Requests Per Second: 400",
|
|
"Max List Requests Per Second: 500",
|
|
"Max Concurrent Reads: 300",
|
|
"Max Concurrent Writes: 400",
|
|
}, env.RunAndExpectSuccess(t, "server", "throttle", "get", "--address", sp.BaseURL, "--server-control-password", sp.ServerControlPassword))
|
|
|
|
env.RunAndExpectSuccess(t, "server", "throttle", "set", "--address", sp.BaseURL, "--server-control-password", sp.ServerControlPassword,
|
|
"--upload-bytes-per-second=unlimited",
|
|
"--write-requests-per-second=unlimited",
|
|
)
|
|
|
|
env.RunAndExpectFailure(t, "server", "throttle", "set", "--address", sp.BaseURL, "--server-control-password", sp.ServerControlPassword,
|
|
"--upload-bytes-per-second=-10",
|
|
)
|
|
|
|
require.Equal(t, []string{
|
|
"Max Download Speed: 1 GB/s",
|
|
"Max Upload Speed: (unlimited)",
|
|
"Max Read Requests Per Second: 300",
|
|
"Max Write Requests Per Second: (unlimited)",
|
|
"Max List Requests Per Second: 500",
|
|
"Max Concurrent Reads: 300",
|
|
"Max Concurrent Writes: 400",
|
|
}, env.RunAndExpectSuccess(t, "server", "throttle", "get", "--address", sp.BaseURL, "--server-control-password", sp.ServerControlPassword))
|
|
|
|
var limits throttling.Limits
|
|
|
|
testutil.MustParseJSONLines(t, env.RunAndExpectSuccess(t, "server", "throttle", "get", "--address", sp.BaseURL, "--server-control-password", sp.ServerControlPassword, "--json"), &limits)
|
|
require.Equal(t, throttling.Limits{
|
|
ReadsPerSecond: 300,
|
|
WritesPerSecond: 0,
|
|
ListsPerSecond: 500,
|
|
UploadBytesPerSecond: 0,
|
|
DownloadBytesPerSecond: 1e+09,
|
|
ConcurrentReads: 300,
|
|
ConcurrentWrites: 400,
|
|
}, limits)
|
|
|
|
env.RunAndExpectSuccess(t, "server", "shutdown", "--address", sp.BaseURL, "--server-control-password", sp.ServerControlPassword)
|
|
|
|
select {
|
|
case <-serverStopped:
|
|
t.Logf("server shut down")
|
|
|
|
case <-time.After(15 * time.Second):
|
|
t.Fatalf("server did not shutdown in time")
|
|
}
|
|
|
|
// this will fail since the server is down
|
|
env.RunAndExpectFailure(t, "server", "status", "--address", sp.BaseURL, "--server-control-password", sp.ServerControlPassword)
|
|
env.RunAndExpectFailure(t, "server", "flush", "--address", sp.BaseURL, "--server-control-password", sp.ServerControlPassword)
|
|
env.RunAndExpectFailure(t, "server", "refresh", "--address", sp.BaseURL, "--server-control-password", sp.ServerControlPassword)
|
|
env.RunAndExpectFailure(t, "server", "shutdown", "--address", sp.BaseURL, "--server-control-password", sp.ServerControlPassword)
|
|
}
|
|
|
|
func hasLine(lines []string, lookFor string) bool {
|
|
for _, l := range lines {
|
|
if l == lookFor {
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|