Compare commits

..

2 Commits

Author SHA1 Message Date
fe85092910 Fix vitastor-cli ls-pgs printing an empty table instead of an error
When the pool was not found or the etcd request failed, load_pg_stats()
stored the error, but loop() still ran format_pgs() which replaced the
message with a table built from the pool config. ls-pgs then printed
only a table header, or a table without stats, instead of the error.
2026-10-20 10:39:51 +03:00
19d20291ba Fix vitastor-cli ls-pgs DEGRADED column showing misplaced data
The DEGRADED column of the ls-pgs table used the fmt_misplaced key, so
it repeated MISPLACED and never showed degraded data. The JSON output
was correct.
2026-10-20 10:38:23 +03:00
8 changed files with 51 additions and 58 deletions

View File

@@ -470,8 +470,6 @@ These, however, can still be modified with -f|--force.
See [create-pool](#create-pool) for parameter descriptions.
Renaming with --name fails if another pool already has the new name.
Examples:
`vitastor-cli modify-pool pool_A --name pool_B`

View File

@@ -487,8 +487,6 @@ OSD PARENT UP SIZE USED% TAGS WEIGHT BLOCK BITMAP
Описания параметров смотрите в [create-pool](#create-pool).
Переименование с --name завершается ошибкой, если у другого пула уже есть такое имя.
Примеры:
`vitastor-cli modify-pool pool_A --name pool_B`

View File

@@ -235,7 +235,6 @@ static const char* help_text =
" [--immediate_commit <all|small|none>] [--pg_stripe_size <size>]\n"
" These, however, can still be modified with -f|--force.\n"
" See create-pool for parameter descriptions.\n"
" Renaming with --name fails if another pool already has the new name.\n"
" Examples:\n"
" vitastor-cli modify-pool pool_A --name pool_B\n"
" vitastor-cli modify-pool 2 --pg_size 4 -n 128\n"

View File

@@ -251,7 +251,7 @@ resume_1:
{ "title", "MISPLACED" },
});
cols.push_back(json11::Json::object{
{ "key", "fmt_misplaced" },
{ "key", "fmt_degraded" },
{ "title", "DEGRADED" },
});
cols.push_back(json11::Json::object{
@@ -273,6 +273,8 @@ resume_1:
load_pg_stats();
if (parent->waiting > 0)
return;
if (state == 100)
return;
format_pgs();
state = 100;
}

View File

@@ -117,22 +117,6 @@ resume_1:
return;
}
if (new_cfg["name"] != old_cfg["name"])
{
for (auto & pce: kv.value.object_items())
{
if (pce.second["name"] == new_cfg["name"])
{
result = (cli_result_t){
.err = EEXIST,
.text = "Pool with name \""+new_cfg["name"].string_value()+"\" already exists (ID "+pce.first+")",
};
state = 100;
return;
}
}
}
if (new_cfg.find("used_for_app") != new_cfg.end() && !force)
{
// Check that pool doesn't have images

View File

@@ -18,8 +18,6 @@ SCHEME=ec ./test_change_pg_count.sh
./test_create_nomaxid.sh
./test_modify_pool_name.sh
./test_etcd_fail.sh
ANTIETCD=1 ./test_etcd_fail.sh
@@ -63,6 +61,7 @@ OLD=1 SCHEME=ec ./test_snapshot.sh
OLD=1 ./test_move_reappear.sh
./test_degraded.sh
./test_pg_ls.sh
./test_rm.sh

View File

@@ -1,34 +0,0 @@
#!/bin/bash -ex
# Test that modify-pool --name refuses to take the name of another pool
. `dirname $0`/common.sh
wait_etcd
POOL='"scheme":"replicated","pg_size":2,"pg_minsize":1,"pg_count":1,"failure_domain":"osd"'
$ETCDCTL put /vitastor/config/pools '{"1":{"name":"pool1",'$POOL'},"2":{"name":"pool2",'$POOL'}}'
for p in pool2 2; do
r=0
$VITASTOR_CLI modify-pool $p --name pool1 || r=$?
if [[ $r != 17 ]]; then
format_error "modify-pool $p --name pool1 should fail with EEXIST (17), but exited with $r"
fi
done
names=$($ETCDCTL get --print-value-only /vitastor/config/pools | jq -c '[ .[].name ]')
if [[ "$names" != '["pool1","pool2"]' ]]; then
format_error "Pool names should stay pool1, pool2, but they are $names"
fi
# A free name and the pool's own name are still accepted
$VITASTOR_CLI modify-pool pool2 --name pool3
$VITASTOR_CLI modify-pool pool3 --name pool3 --pg_count 2
cfg=$($ETCDCTL get --print-value-only /vitastor/config/pools | jq -c '[ .[] | [ .name, .pg_count ] ]')
if [[ "$cfg" != '[["pool1",1],["pool3",2]]' ]]; then
format_error "Pools should be pool1 (1 PG) and pool3 (2 PGs), but they are $cfg"
fi
format_green OK

47
tests/test_pg_ls.sh Executable file
View File

@@ -0,0 +1,47 @@
#!/bin/bash -ex
# Test vitastor-cli ls-pgs on degraded PGs
PG_COUNT=4
PG_SIZE=3
PG_MINSIZE=2
# Keep degraded objects until the checks are done
GLOBAL_CONFIG=',"no_recovery":true'
. `dirname $0`/run_3osds.sh
$VITASTOR_CLI create -s 32M testimg
# Data written while OSD 3 is down is degraded when it comes back
kill -9 $OSD3_PID
$ETCDCTL del /vitastor/osd/state/3
wait_condition 60 "$ETCDCTL get --prefix /vitastor/pg/state/ --print-value-only | jq -s -e '[ .[] | select(.state | index(\"degraded\")) ] | length == $PG_COUNT'" "PG peering without OSD 3"
$VITASTOR_CLI dd if=/dev/urandom oimg=testimg bs=1M count=32
start_osd 3
wait_condition 60 "$ETCDCTL get --prefix /vitastor/pgstats/ --print-value-only | jq -s -e '[ .[] | select(.degraded_count > 0) ] | length == $PG_COUNT'" "PG degradation"
$VITASTOR_CLI ls-pgs
# NUM and DEGRADED of every PG from the table, and degraded_count from JSON
$VITASTOR_CLI ls-pgs | awk 'NR == 1 { n = index($0, "NUM"); d = index($0, "DEGRADED"); e = index($0, "INCOMPLETE") }
NR > 1 { num = substr($0, n); sub(/ .*/, "", num); deg = substr($0, d, e-d); sub(/ +$/, "", deg); print num " " deg }' > ./testdata/pg_ls.txt
$VITASTOR_CLI ls-pgs --json | jq -r '.[] | "\(.pg_num) \(.degraded_count // 0)"' > ./testdata/pg_ls_json.txt
if [[ $(wc -l < ./testdata/pg_ls.txt) != $PG_COUNT ]]; then
format_error "ls-pgs should list $PG_COUNT PGs"
fi
while read num count; do
shown=$(awk '$1 == '$num' { $1 = ""; sub(/^ /, ""); print }' ./testdata/pg_ls.txt)
if [[ -z "$shown" || $count -gt 0 && "$shown" = "0 B" || $count -eq 0 && "$shown" != "0 B" ]]; then
format_error "ls-pgs shows DEGRADED=$shown for PG $num with $count degraded objects"
fi
done < ./testdata/pg_ls_json.txt
# An unknown pool is an error, not an empty table
if out=$($VITASTOR_CLI ls-pgs --pool nosuchpool 2>&1); then
format_error "ls-pgs should fail for an unknown pool"
fi
if [[ "$out" != "Pool nosuchpool not found" ]]; then
format_error "ls-pgs prints '$out' instead of the unknown pool error"
fi
format_green OK