Drop the AGPL license in favor of a source-available license. See the blog post [1] for details. [1] https://www.scylladb.com/2024/12/18/why-were-moving-to-a-source-available-license/
251 lines
7.9 KiB
Python
251 lines
7.9 KiB
Python
#
|
|
# Copyright 2024-present ScyllaDB
|
|
#
|
|
# SPDX-License-Identifier: LicenseRef-ScyllaDB-Source-Available-1.0
|
|
#
|
|
from test.nodetool.utils import check_nodetool_fails_with
|
|
from test.nodetool.rest_api_mock import expected_request
|
|
import pytest
|
|
|
|
|
|
@pytest.mark.parametrize("key_option", (None, "-hf", "--hex-format"))
|
|
def test_getsstables(nodetool, key_option):
|
|
cmd = ["getsstables", "ks", "tbl", "mykey"]
|
|
params = {"key": "mykey"}
|
|
if key_option:
|
|
cmd.append(key_option)
|
|
params["format"] = "hex"
|
|
res = nodetool(*cmd, expected_requests=[
|
|
expected_request("GET", "/column_family/",
|
|
response=[{"ks": "ks", "cf": "tbl", "type": "ColumnFamilies"}]),
|
|
expected_request(
|
|
"GET",
|
|
"/column_family/sstables/by_key/ks:tbl",
|
|
params=params,
|
|
response=[
|
|
"/var/lib/scylla/data/ks/tbl-3ca78460d61611eea0b49524e39553c0/me-3gec_0mu7_5az0024x96bfm476r6-big-Data.db",
|
|
"/var/lib/scylla/data/ks/tbl-3ca78460d61611eea0b49524e39553c0/me-3gec_0mu7_7bz0024x96bfm476r6-big-Data.db",
|
|
]),
|
|
])
|
|
assert res.stdout == (
|
|
"""/var/lib/scylla/data/ks/tbl-3ca78460d61611eea0b49524e39553c0/me-3gec_0mu7_5az0024x96bfm476r6-big-Data.db
|
|
/var/lib/scylla/data/ks/tbl-3ca78460d61611eea0b49524e39553c0/me-3gec_0mu7_7bz0024x96bfm476r6-big-Data.db
|
|
""")
|
|
|
|
|
|
def test_getsstables_unknown_ks(nodetool, scylla_only):
|
|
check_nodetool_fails_with(
|
|
nodetool,
|
|
("getsstables", "unknown_ks", "tbl", "mykey"),
|
|
{"expected_requests": [expected_request("GET", "/column_family/",
|
|
response=[{"ks": "ks", "cf": "tbl", "type": "ColumnFamilies"}])]},
|
|
["error processing arguments: unknown keyspace: unknown_ks"],
|
|
)
|
|
|
|
|
|
def test_getsstables_unknown_tbl(nodetool):
|
|
check_nodetool_fails_with(
|
|
nodetool,
|
|
("getsstables", "ks", "unknown_tbl", "mykey"),
|
|
{"expected_requests": [expected_request("GET", "/column_family/",
|
|
response=[{"ks": "ks", "cf": "tbl", "type": "ColumnFamilies"}])]},
|
|
["error processing arguments: unknown table: unknown_tbl",
|
|
"ColumnFamilyStore for ks/unknown_tbl not found."]
|
|
)
|
|
|
|
|
|
ks_tbl_sstable_info = {
|
|
"keyspace": "ks",
|
|
"table": "tbl",
|
|
"sstables": [
|
|
{
|
|
"size": 5746,
|
|
"data_size": 90,
|
|
"index_size": 24,
|
|
"filter_size": 332,
|
|
"timestamp": "2024-03-11T08:13:19Z",
|
|
"generation": "3gec_0mu7_5az0024x96bfm476r6",
|
|
"level": 0,
|
|
"version": "me",
|
|
"extended_properties": [
|
|
{
|
|
"group": "compression_parameters",
|
|
"attributes": [
|
|
{
|
|
"key": "sstable_compression",
|
|
"value": "org.apache.cassandra.io.compress.LZ4Compressor"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"size": 6746,
|
|
"data_size": 290,
|
|
"index_size": 124,
|
|
"filter_size": 232,
|
|
"timestamp": "2024-03-10T08:13:19Z",
|
|
"generation": "3gec_0mu7_6bz0024x96bfm476r6",
|
|
"level": 0,
|
|
"version": "me",
|
|
"properties": [
|
|
{
|
|
"key": "foo",
|
|
"value": "bar"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
|
|
|
|
ks_tbl2_sstable_info = {
|
|
"keyspace": "ks",
|
|
"table": "tbl2",
|
|
"sstables": [
|
|
{
|
|
"size": 5481,
|
|
"data_size": 44,
|
|
"index_size": 8,
|
|
"filter_size": 172,
|
|
"timestamp": "2024-03-11T08:13:20Z",
|
|
"generation": "3gec_0mu8_5vrgh24x96bfm476r6",
|
|
"level": 0,
|
|
"version": "me",
|
|
"extended_properties": [
|
|
{
|
|
"group": "compression_parameters",
|
|
"attributes": [
|
|
{
|
|
"key": "sstable_compression",
|
|
"value": "org.apache.cassandra.io.compress.LZ4Compressor"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
|
|
|
|
ks2_tbl_sstable_info = {
|
|
"keyspace": "ks2",
|
|
"table": "tbl"
|
|
}
|
|
|
|
|
|
def _check_sstableinfo_output(res, info, is_cassandra):
|
|
lines = res.split('\n')
|
|
i = 0
|
|
|
|
assert lines[i] == ''
|
|
i += 1
|
|
|
|
def split(ln):
|
|
return tuple(part.strip() for part in ln.split(':'))
|
|
|
|
for entry in info:
|
|
if "sstables" not in entry and is_cassandra:
|
|
i += 2
|
|
else:
|
|
assert split(lines[i]) == ("keyspace", entry["keyspace"])
|
|
i += 1
|
|
|
|
assert split(lines[i]) == ("table", entry["table"])
|
|
i += 1
|
|
|
|
if "sstables" in entry:
|
|
assert lines[i] == "sstables :"
|
|
i += 1
|
|
else:
|
|
continue
|
|
|
|
for index, sstable in enumerate(entry["sstables"]):
|
|
assert lines[i].lstrip() == f"{index} :"
|
|
i += 1
|
|
|
|
for key in ["data_size", "filter_size", "index_size", "level", "size", "generation", "version",
|
|
"timestamp"]:
|
|
print_key = key.replace("_", " ")
|
|
if print_key == "timestamp":
|
|
parts = split(lines[i])
|
|
assert parts[0] == print_key
|
|
# Java nodetool does a weird reformatting of the date which I see no sense in replicating
|
|
if not is_cassandra:
|
|
assert ":".join(parts[1:]) == sstable[key]
|
|
else:
|
|
assert split(lines[i]) == (print_key, str(sstable[key]))
|
|
i += 1
|
|
|
|
if "properties" in sstable:
|
|
assert lines[i].strip() == "properties :"
|
|
i += 1
|
|
|
|
for prop in sstable["properties"]:
|
|
assert split(lines[i]) == (prop["key"], prop["value"])
|
|
i += 1
|
|
|
|
if "extended_properties" in sstable:
|
|
assert lines[i].strip() == "extended properties :"
|
|
i += 1
|
|
|
|
for ext_prop in sstable["extended_properties"]:
|
|
assert lines[i].strip() == f"{ext_prop['group']} :"
|
|
i += 1
|
|
|
|
for attr in ext_prop["attributes"]:
|
|
assert split(lines[i]) == (attr["key"], attr["value"])
|
|
i += 1
|
|
|
|
|
|
def test_sstableinfo(nodetool, request):
|
|
info = [ks_tbl_sstable_info, ks_tbl2_sstable_info, ks2_tbl_sstable_info]
|
|
res = nodetool("sstableinfo", expected_requests=[
|
|
expected_request(
|
|
"GET",
|
|
"/storage_service/sstable_info",
|
|
response=info),
|
|
])
|
|
_check_sstableinfo_output(res.stdout, info, request.config.getoption("nodetool") == "cassandra")
|
|
|
|
|
|
def test_sstableinfo_keyspace(nodetool, request):
|
|
info = [ks_tbl_sstable_info, ks_tbl2_sstable_info]
|
|
res = nodetool("sstableinfo", "ks", expected_requests=[
|
|
expected_request(
|
|
"GET",
|
|
"/storage_service/sstable_info",
|
|
params={"keyspace": "ks"},
|
|
response=info),
|
|
])
|
|
_check_sstableinfo_output(res.stdout, info, request.config.getoption("nodetool") == "cassandra")
|
|
|
|
|
|
def test_sstableinfo_keyspace_table(nodetool, request):
|
|
info = [ks_tbl_sstable_info]
|
|
res = nodetool("sstableinfo", "ks", "tbl", expected_requests=[
|
|
expected_request(
|
|
"GET",
|
|
"/storage_service/sstable_info",
|
|
params={"keyspace": "ks", "cf": "tbl"},
|
|
response=info),
|
|
])
|
|
_check_sstableinfo_output(res.stdout, info, request.config.getoption("nodetool") == "cassandra")
|
|
|
|
|
|
def test_sstableinfo_keyspace_tables(nodetool, request):
|
|
info = [ks_tbl_sstable_info, ks_tbl2_sstable_info]
|
|
res = nodetool("sstableinfo", "ks", "tbl", "tbl2", expected_requests=[
|
|
expected_request(
|
|
"GET",
|
|
"/storage_service/sstable_info",
|
|
params={"keyspace": "ks", "cf": "tbl"},
|
|
response=[ks_tbl_sstable_info]),
|
|
expected_request(
|
|
"GET",
|
|
"/storage_service/sstable_info",
|
|
params={"keyspace": "ks", "cf": "tbl2"},
|
|
response=[ks_tbl2_sstable_info]),
|
|
])
|
|
_check_sstableinfo_output(res.stdout, info, request.config.getoption("nodetool") == "cassandra")
|