diff --git a/.gitea/workflows/test.yml b/.gitea/workflows/test.yml index 2347d6ccd..5655eeea7 100644 --- a/.gitea/workflows/test.yml +++ b/.gitea/workflows/test.yml @@ -766,6 +766,24 @@ jobs: echo "" done + test_osd_tags: + runs-on: ubuntu-latest + needs: build + container: ${{env.TEST_IMAGE}}:${{github.sha}} + steps: + - name: Run test + id: test + timeout-minutes: 3 + run: /root/vitastor/tests/test_osd_tags.sh + - name: Print logs + if: always() && steps.test.outcome == 'failure' + run: | + for i in /root/vitastor/testdata/*.log /root/vitastor/testdata/*.txt; do + echo "-------- $i --------" + cat $i + echo "" + done + test_enospc: runs-on: ubuntu-latest needs: build diff --git a/mon/mon.js b/mon/mon.js index f28f16076..bd2d7e0bb 100644 --- a/mon/mon.js +++ b/mon/mon.js @@ -871,7 +871,7 @@ class Mon const levels = this.config.placement_levels||{}; levels.host = levels.host || 100; levels.osd = levels.osd || 101; - const tree = { '': { children: [] } }; + const tree = {}; let up_osds = {}; for (const node_id in this.state.config.node_placement||{}) { @@ -926,6 +926,20 @@ class Mon } } } + return { up_osds, levels, osd_tree: tree }; + } + + make_hier_tree(tree) + { + const levels = this.config.placement_levels||{}; + levels.host = levels.host || 100; + levels.osd = levels.osd || 101; + tree = { ...tree }; + for (const node_id in tree) + { + tree[node_id] = { ...tree[node_id], children: [] }; + } + tree[''] = { children: [] }; for (const node_id in tree) { if (node_id === '' || tree[node_id].level === 'osd' && (!tree[node_id].size || tree[node_id].size <= 0)) @@ -941,7 +955,7 @@ class Mon const parent = parent_level && parent_level < node_level ? node_cfg.parent : ''; tree[parent].children.push(tree[node_id]); } - return { up_osds, levels, osd_tree: tree }; + return tree; } async stop_all_pgs(pool_id) @@ -1197,7 +1211,8 @@ class Mon { return; } - let included = [ ...(pool_tree[root_node] || {}).children||[] ]; + let hier_tree = this.make_hier_tree(pool_tree); + let included = [ ...(hier_tree[root_node] || {}).children||[] ]; for (let i = 0; i < included.length; i++) { if (included[i].children) @@ -1206,19 +1221,10 @@ class Mon } } let cur = pool_tree[root_node] || {}; - if (cur) + while (cur && cur.id) { included.unshift(cur); - } - while (cur.id) - { - let parent = cur.parent||''; - if (pool_tree[parent]) - { - included.unshift(pool_tree[parent]); - pool_tree[parent] = { ...pool_tree[parent], children: [ cur ] }; - cur = pool_tree[parent]; - } + cur = pool_tree[cur.parent||'']; } included = included.reduce((a, c) => { a[c.id||''] = true; return a; }, {}); for (const item in pool_tree) @@ -1366,6 +1372,7 @@ class Mon pool_cfg.bitmap_granularity || this.config.bitmap_granularity || 4096, pool_cfg.immediate_commit || this.config.immediate_commit || 'none' ); + pool_tree = this.make_hier_tree(pool_tree); // First try last_clean_pgs to minimize data movement let prev_pgs = []; for (const pg in ((this.state.history.last_clean_pgs.items||{})[pool_id]||{})) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index f44fe279e..a0da98dc6 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -64,6 +64,8 @@ TEST_NAME=csum_4k_dmj OSD_ARGS="--data_csum_type crc32c --inmemory_metadata fal TEST_NAME=csum_4k_dj OSD_ARGS="--data_csum_type crc32c --inmemory_journal false" OFFSET_ARGS=$OSD_ARGS ./test_heal.sh TEST_NAME=csum_4k OSD_ARGS="--data_csum_type crc32c" OFFSET_ARGS=$OSD_ARGS ./test_heal.sh +./test_osd_tags.sh + ./test_enospc.sh SCHEME=xor ./test_enospc.sh IMMEDIATE_COMMIT=1 ./test_enospc.sh diff --git a/tests/test_osd_tags.sh b/tests/test_osd_tags.sh new file mode 100755 index 000000000..405088a77 --- /dev/null +++ b/tests/test_osd_tags.sh @@ -0,0 +1,36 @@ +#!/bin/bash -ex + +. `dirname $0`/common.sh + +TIME=$(date '+%s') +$ETCDCTL put /vitastor/config/osd/1 '{"tags":["a"]}' +$ETCDCTL put /vitastor/config/osd/2 '{"tags":["a"]}' +$ETCDCTL put /vitastor/config/osd/3 '{"tags":["a"]}' +$ETCDCTL put /vitastor/config/osd/4 '{"tags":["a"]}' +$ETCDCTL put /vitastor/config/osd/5 '{"tags":["b"]}' +$ETCDCTL put /vitastor/config/osd/6 '{"tags":["b"]}' +$ETCDCTL put /vitastor/config/osd/7 '{"tags":["b"]}' +$ETCDCTL put /vitastor/config/osd/8 '{"tags":["b"]}' +$ETCDCTL put /vitastor/osd/stats/1 '{"host":"stor1","size":1073741824,"time":"'$TIME'"}' +$ETCDCTL put /vitastor/osd/stats/2 '{"host":"stor1","size":1073741824,"time":"'$TIME'"}' +$ETCDCTL put /vitastor/osd/stats/3 '{"host":"stor2","size":1073741824,"time":"'$TIME'"}' +$ETCDCTL put /vitastor/osd/stats/4 '{"host":"stor2","size":1073741824,"time":"'$TIME'"}' +$ETCDCTL put /vitastor/osd/stats/5 '{"host":"stor3","size":1073741824,"time":"'$TIME'"}' +$ETCDCTL put /vitastor/osd/stats/6 '{"host":"stor3","size":1073741824,"time":"'$TIME'"}' +$ETCDCTL put /vitastor/osd/stats/7 '{"host":"stor4","size":1073741824,"time":"'$TIME'"}' +$ETCDCTL put /vitastor/osd/stats/8 '{"host":"stor4","size":1073741824,"time":"'$TIME'"}' +$ETCDCTL put /vitastor/config/pools '{"1":{"name":"testpool","scheme":"replicated","pg_size":2,"pg_minsize":2,"pg_count":16,"failure_domain":"host","osd_tags":["a"]}}' + +node mon/mon-main.js --etcd_address $ETCD_URL --etcd_prefix "/vitastor" >>./testdata/mon.log 2>&1 & +MON_PID=$! + +sleep 2 + +etcdctl --endpoints=http://localhost:12379 get --prefix /vitastor/config/pgs --print-value-only + +if ! (etcdctl --endpoints=http://localhost:12379 get --prefix /vitastor/config/pgs --print-value-only | \ + jq -s -e '[ [ .[0].items["1"] | .[].osd_set | map(. | select(. != "" and (.|tonumber) < 5)) ][] | select((. | length) == 2) ] | length == 16'); then + format_error "Some PGs missing replicas" +fi + +format_green OK diff --git a/tests/test_root_node.sh b/tests/test_root_node.sh index c6538276b..6542202c6 100755 --- a/tests/test_root_node.sh +++ b/tests/test_root_node.sh @@ -26,6 +26,5 @@ if ! (etcdctl --endpoints=http://localhost:12379 get --prefix /vitastor/config/p jq -s -e '[ [ .[0].items["1"] | .[].osd_set | map(. | select(. != "" and (.|tonumber) < 5)) ][] | select((. | length) == 2) ] | length == 16'); then format_error "Some PGs missing replicas" fi - format_error "Some PGs missing replicas" format_green OK