diff --git a/.github/workflows/build-cloudberry-rocky8.yml b/.github/workflows/build-cloudberry-rocky8.yml index 2abf88060e3..c8068f098cb 100644 --- a/.github/workflows/build-cloudberry-rocky8.yml +++ b/.github/workflows/build-cloudberry-rocky8.yml @@ -311,6 +311,7 @@ jobs: "contrib/pgstattuple:installcheck", "contrib/tablefunc:installcheck", "contrib/passwordcheck:installcheck", + "contrib/pg_aux_catalog:installcheck", "contrib/pg_buffercache:installcheck", "contrib/sslinfo:installcheck"] }, diff --git a/.github/workflows/build-cloudberry.yml b/.github/workflows/build-cloudberry.yml index ca75f7b42e7..99bc67c99b7 100644 --- a/.github/workflows/build-cloudberry.yml +++ b/.github/workflows/build-cloudberry.yml @@ -304,6 +304,7 @@ jobs: "contrib/pgstattuple:installcheck", "contrib/tablefunc:installcheck", "contrib/passwordcheck:installcheck", + "contrib/pg_aux_catalog:installcheck", "contrib/pg_buffercache:installcheck", "contrib/sslinfo:installcheck"] }, diff --git a/.github/workflows/build-deb-cloudberry.yml b/.github/workflows/build-deb-cloudberry.yml index 85d917b8ff0..fee69b073f7 100644 --- a/.github/workflows/build-deb-cloudberry.yml +++ b/.github/workflows/build-deb-cloudberry.yml @@ -243,6 +243,7 @@ jobs: "contrib/pgstattuple:installcheck", "contrib/tablefunc:installcheck", "contrib/passwordcheck:installcheck", + "contrib/pg_aux_catalog:installcheck", "contrib/pg_buffercache:installcheck", "contrib/sslinfo:installcheck"] }, diff --git a/.github/workflows/yezzey-ci.yaml b/.github/workflows/yezzey-ci.yaml new file mode 100644 index 00000000000..82511c4f701 --- /dev/null +++ b/.github/workflows/yezzey-ci.yaml @@ -0,0 +1,335 @@ +# -------------------------------------------------------------------- +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed +# with this work for additional information regarding copyright +# ownership. The ASF licenses this file to You under the Apache +# License, Version 2.0 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of the +# License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. See the License for the specific language governing +# permissions and limitations under the License. +# +# -------------------------------------------------------------------- +# Yezzey CI Workflow +# -------------------------------------------------------------------- +name: Yezzey CI Pipeline + +on: + push: + branches: [ main ] + pull_request: + types: [opened, synchronize, reopened, edited] + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} + +env: + CLOUDBERRY_HOME: "/usr/local/cloudberry-db" + CLOUDBERRY_VERSION: "main" + +jobs: + + ## Stage 1: Build artifacts and run tests for cloudberry + + test-cloudberry: + name: Build and Test Yezzey Cloudberry + runs-on: ubuntu-latest + container: + image: apache/incubator-cloudberry:cbdb-build-ubuntu22.04-latest + options: >- + --user root + -h cdw + -v /usr/share:/host_usr_share + -v /usr/local:/host_usr_local + -v /opt:/host_opt + + services: + # Define the MinIO service container + minio: + image: lazybit/minio # Use a specific MinIO image tag + ports: + - 9000:9000 # Expose MinIO's API port (9000) + - 9001:9001 # Expose MinIO's console port (optional, for web UI) + env: + # MinIO root credentials (required for admin access) + MINIO_ROOT_USER: some_key + MINIO_ROOT_PASSWORD: some_key + # Healthcheck to ensure MinIO is ready before the job proceeds + options: >- + --name minio + --health-cmd "curl --fail http://localhost:9000/minio/health/live" + --health-interval 10s + --health-timeout 5s + --health-retries 5 + volumes: + - ${{ github.workspace }}/data:/data + + steps: + - name: Checkout Cloudberry source + uses: actions/checkout@v4 + with: + path: cloudberry + submodules: true + + - name: Checkout Yproxy source + uses: actions/checkout@v4 + with: + repository: open-gpdb/yproxy + ref: master + path: yproxy + + - name: Cloudberry Environment Initialization + shell: bash + env: + LOGS_DIR: build-logs + SRC_DIR: ${{ github.workspace }}/cloudberry + run: | + set -eo pipefail + if ! su - gpadmin -c "/tmp/init_system.sh"; then + echo "::error::Container initialization failed" + exit 1 + fi + + mkdir -p "${SRC_DIR}/build-logs" + chown -R gpadmin:gpadmin "${SRC_DIR}/build-logs" + mkdir -p "${LOGS_DIR}/details" + chown -R gpadmin:gpadmin . + chmod -R 755 . + chmod 777 "${LOGS_DIR}" + + df -kh / + rm -rf /__t/* + df -kh / + + df -h | tee -a "${LOGS_DIR}/details/disk-usage.log" + free -h | tee -a "${LOGS_DIR}/details/memory-usage.log" + + { + echo "=== Environment Information ===" + uname -a + df -h + free -h + env + } | tee -a "${LOGS_DIR}/details/environment.log" + + echo "SRC_DIR=${GITHUB_WORKSPACE}" | tee -a "$GITHUB_ENV" + + - name: Install MinIO Client (mc) + shell: bash + run: | + set -exo pipefail + # Download mc for Linux (amd64) + curl -fsSL -o mc https://dl.min.io/client/mc/release/linux-amd64/mc + chmod +x mc + sudo mv mc /usr/local/bin/mc # Make mc available system-wide + + - name: Configure MinIO service + shell: bash + run: | + set -exo pipefail + # Add the MinIO service as an "alias" in mc (name it "minio-ci") + mc alias set minio-ci http://minio:9000 some_key some_key + + # Verify the connection + mc admin info minio-ci + + # Create buckets + mc mb minio-ci/gpyezzey + mc mb minio-ci/gpyezzey2 + mc mb minio-ci/gpyezzey3 + + - name: Run Apache Cloudberry configure script + shell: bash + env: + SRC_DIR: ${{ github.workspace }}/cloudberry + run: | + set -eo pipefail + chmod +x "${SRC_DIR}"/devops/build/automation/cloudberry/scripts/configure-cloudberry.sh + if ! time su - gpadmin -c "cd ${SRC_DIR} && SRC_DIR=${SRC_DIR} ENABLE_DEBUG=${{ env.ENABLE_DEBUG }} CONFIGURE_EXTRA_OPTS=${{ env.CONFIGURE_EXTRA_OPTS }} ${SRC_DIR}/devops/build/automation/cloudberry/scripts/configure-cloudberry.sh"; then + echo "::error::Configure script failed" + exit 1 + fi + + - name: Run Apache Cloudberry build script + shell: bash + env: + SRC_DIR: ${{ github.workspace }}/cloudberry + run: | + set -eo pipefail + + chmod +x "${SRC_DIR}"/devops/build/automation/cloudberry/scripts/build-cloudberry.sh + if ! time su - gpadmin -c "cd ${SRC_DIR} && SRC_DIR=${SRC_DIR} ${SRC_DIR}/devops/build/automation/cloudberry/scripts/build-cloudberry.sh"; then + echo "::error::Build script failed" + exit 1 + fi + + - name: Run Yezzey build script + shell: bash + env: + SRC_DIR: ${{ github.workspace }}/cloudberry + run: | + set -eo pipefail + + if ! time su - gpadmin -c "cd ${SRC_DIR}/gpcontrib/yezzey && make && make install"; then + echo "::error::Build yezzey failed" + exit 1 + fi + + - name: Deploy yezzey config + shell: bash + env: + SRC_DIR: ${{ github.workspace }}/cloudberry + run: | + set -eo pipefail + + chmod +x "${SRC_DIR}"/gpcontrib/yezzey/devops/scripts/prepare_test_yezzey.sh + if ! time su - gpadmin -c "cd ${SRC_DIR}/gpcontrib/yezzey && devops/scripts/prepare_test_yezzey.sh"; then + echo "::error::Config yezzey failed" + exit 1 + fi + + - name: Install yproxy + shell: bash + env: + SRC_DIR: ${{ github.workspace }}/yproxy + run: | + set -eo pipefail + + # Install latest Go compiler + sudo apt update + sudo apt install -y software-properties-common + sudo add-apt-repository ppa:longsleep/golang-backports + sudo apt update + sudo apt install -y golang-go + + # Install lib dependencies + + sudo apt install -y libbrotli-dev liblzo2-dev libsodium-dev curl cmake + + # Fetch project and build + git config --global --add safe.directory ${SRC_DIR} + cd ${SRC_DIR} + make build + + mv devbin/yproxy /usr/bin/yproxy + + #Check the installation + yproxy --version + + - name: Create demo cluster with yezzey + shell: bash + env: + SRC_DIR: ${{ github.workspace }}/cloudberry + run: | + set -eo pipefail + + if ! time su - gpadmin -c "cd ${SRC_DIR} && gpcontrib/yezzey/devops/scripts/create_demo_yezzey_cloudberry.sh"; then + echo "::error::Create cluster with yezzey failed" + exit 1 + fi + + - name: Run tests + shell: bash + env: + SRC_DIR: ${{ github.workspace }}/cloudberry + run: | + set -eo pipefail + set -x + + chmod +x "${SRC_DIR}"/gpcontrib/yezzey/devops/scripts/launch_yproxy.sh + if ! time su - gpadmin -c "cd ${SRC_DIR} && gpcontrib/yezzey/devops/scripts/launch_yproxy.sh && cd ${SRC_DIR}/gpcontrib/yezzey && source /usr/local/cloudberry-db/cloudberry-env.sh && source ../../gpAux/gpdemo/gpdemo-env.sh && IS_CLOUDBERRY=true make installcheck"; then + echo "::error::Test yezzey failed" + cat ${SRC_DIR}/gpcontrib/yezzey/regression.diffs + exit 1 + fi + + - name: Upload test logs + uses: actions/upload-artifact@v4 + with: + name: test-logs-cloudberry-${{ needs.build.outputs.build_timestamp }} + path: | + build-logs/ + retention-days: 7 + + - name: Upload test results files + uses: actions/upload-artifact@v4 + with: + name: results-cloudberry-${{ needs.build.outputs.build_timestamp }} + path: | + **/regression.out + **/regression.diffs + **/results/ + retention-days: 7 + + - name: Upload test regression logs + if: failure() || cancelled() + uses: actions/upload-artifact@v4 + with: + name: regression-logs-cloudberry-${{ needs.build.outputs.build_timestamp }} + path: | + **/regression.out + **/regression.diffs + **/results/ + **/yproxy.log + cloudberry/gpAux/gpdemo/datadirs/standby/log/ + cloudberry/gpAux/gpdemo/datadirs/qddir/demoDataDir-1/log/ + cloudberry/gpAux/gpdemo/datadirs/dbfast1/demoDataDir0/log/ + cloudberry/gpAux/gpdemo/datadirs/dbfast2/demoDataDir1/log/ + cloudberry/gpAux/gpdemo/datadirs/dbfast3/demoDataDir2/log/ + cloudberry/gpAux/gpdemo/datadirs/dbfast_mirror1/demoDataDir0/log/ + cloudberry/gpAux/gpdemo/datadirs/dbfast_mirror2/demoDataDir1/log/ + cloudberry/gpAux/gpdemo/datadirs/dbfast_mirror3/demoDataDir2/log/ + retention-days: 7 + + ## ====================================================================== + ## Job: report + ## ====================================================================== + + report: + name: Generate Apache Cloudberry Build Report + needs: [test-cloudberry] + if: always() + runs-on: ubuntu-22.04 + steps: + - name: Generate Final Report + run: | + { + echo "# Yezzey Test Pipeline Report" + + echo "## Job Status" + echo "- Cloudberry Job: ${{ needs.test-cloudberry.result }}" + echo "- Completion Time: $(date -u +'%Y-%m-%d %H:%M:%S UTC')" + + if [[ "${{ needs.test-cloudberry.result }}" == "success" ]]; then + echo "✅ Pipeline completed successfully" + else + echo "⚠️ Pipeline completed with failures" + + if [[ "${{ needs.test-cloudberry.result }}" != "success" ]]; then + echo "### Cloudberry Test Failure" + echo "Check build logs for details" + fi + + fi + } >> "$GITHUB_STEP_SUMMARY" + + - name: Notify on failure + if: | + (needs.test-cloudberry.result != 'success') + run: | + echo "::error::Build/Test pipeline failed! Check job summaries and logs for details" + echo "Timestamp: $(date -u +'%Y-%m-%d %H:%M:%S UTC')" + echo "Cloudberry Result: ${{ needs.test-cloudberry.result }}" + diff --git a/.gitmodules b/.gitmodules index a7b61644ee2..f900edb6807 100644 --- a/.gitmodules +++ b/.gitmodules @@ -15,3 +15,6 @@ path = dependency/yyjson url = https://github.com/ibireme/yyjson.git +[submodule "gpcontrib/yezzey"] + path = gpcontrib/yezzey + url = https://github.com/open-gpdb/yezzey.git diff --git a/configure b/configure index febd1b30169..6c94bce46bd 100755 --- a/configure +++ b/configure @@ -722,6 +722,7 @@ with_apr_config with_libcurl with_rt with_zstd +with_yezzey with_libbz2 LZ4_LIBS LZ4_CFLAGS @@ -943,6 +944,9 @@ with_zlib with_lz4 with_libbz2 with_zstd +with_diskquota +with_gp_stats_collector +with_yezzey with_rt with_libcurl with_apr_config @@ -11250,6 +11254,56 @@ $as_echo "yes" >&6; } fi fi +# +# gp_stats_collector +# + + + +# Check whether --with-gp-stats-collector was given. +if test "${with_gp_stats_collector+set}" = set; then : + withval=$with_gp_stats_collector; + case $withval in + yes) + : + ;; + no) + : + ;; + *) + as_fn_error $? "no argument expected for --with-gp-stats-collector option" "$LINENO" 5 + ;; + esac + +else + with_gp_stats_collector=no + +fi + +# +# yezzey +# + +# Check whether --with-yezzey was given. +if test "${with_yezzey+set}" = set; then : + withval=$with_yezzey; + case $withval in + yes) + : + ;; + no) + : + ;; + *) + as_fn_error $? "no argument expected for --with-yezzey option" "$LINENO" 5 + ;; + esac + +else + with_yezzey=no + +fi + # # Realtime library # diff --git a/configure.ac b/configure.ac index 6f6ba21bbd3..308e0872f07 100644 --- a/configure.ac +++ b/configure.ac @@ -1373,6 +1373,27 @@ if test "$with_zstd" = yes; then PKG_CHECK_MODULES([ZSTD], [libzstd >= 1.4.0]) fi +# +# yezzey +# +PGAC_ARG_BOOL(with, yezzey, no, + [build with Yezzey extension]) +AC_SUBST(with_yezzey) + +# +# diskquota +# +PGAC_ARG_BOOL(with, diskquota, yes, + [build with diskquota extension]) +AC_SUBST(with_diskquota) + +# +# gp_stats_collector +# +PGAC_ARG_BOOL(with, gp_stats_collector, yes, + [build with gp_stats_collector extension]) +AC_SUBST(with_gp_stats_collector) + # # Realtime library # diff --git a/contrib/Makefile b/contrib/Makefile index b14600e3557..01315b1f6f8 100644 --- a/contrib/Makefile +++ b/contrib/Makefile @@ -34,6 +34,7 @@ SUBDIRS = \ old_snapshot \ pageinspect \ passwordcheck \ + pg_aux_catalog \ postgres_fdw \ pg_buffercache \ pg_freespacemap \ diff --git a/contrib/pg_aux_catalog/.gitignore b/contrib/pg_aux_catalog/.gitignore new file mode 100644 index 00000000000..c4ec060cefb --- /dev/null +++ b/contrib/pg_aux_catalog/.gitignore @@ -0,0 +1,6 @@ +# Generated test output +/log/ +/results/ +/tmp_check/ +/isolation2/results/ +/isolation2/output_iso/ diff --git a/contrib/pg_aux_catalog/Makefile b/contrib/pg_aux_catalog/Makefile new file mode 100644 index 00000000000..439ecf31a76 --- /dev/null +++ b/contrib/pg_aux_catalog/Makefile @@ -0,0 +1,37 @@ +# contrib/pg_aux_catalog/Makefile + +MODULE_big = pg_aux_catalog +OBJS = \ + $(WIN32RES) \ + pg_aux_catalog.o + +EXTENSION = pg_aux_catalog +DATA = pg_aux_catalog--1.0.sql + +PGFILEDESC = "pg_aux_catalog - auxiliary catalog management" + +REGRESS = pg_aux_catalog +REGRESS_OPTS = --init-file=$(top_srcdir)/src/test/regress/init_file + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/pg_aux_catalog +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif + +# Multi-session resource-group permission tests, run with the GPDB isolation2 +# harness. Requires a running cluster with resource groups enabled +# (gp_resource_manager=group); see installcheck-resgroup in +# src/test/isolation2. Not part of the default "installcheck". +installcheck-isolation2: install + $(pg_isolation2_regress_installcheck) \ + --init-file=$(top_builddir)/src/test/regress/init_file \ + --inputdir=$(srcdir)/isolation2 \ + --outputdir=isolation2 \ + --schedule=$(srcdir)/isolation2/isolation2_schedule + diff --git a/contrib/pg_aux_catalog/README.md b/contrib/pg_aux_catalog/README.md new file mode 100644 index 00000000000..a89535838ee --- /dev/null +++ b/contrib/pg_aux_catalog/README.md @@ -0,0 +1,71 @@ +# pg_aux_catalog + +Auxiliary catalog management for Apache Cloudberry. + +This extension provisions the **`mdb_admin`** privilege role, which lets a +non-superuser manage resource groups in managed-service deployments where the +client is never given superuser. + +## Background + +In Greenplum/Cloudberry only a superuser may `CREATE`/`ALTER`/`DROP` resource +groups or move a running query between groups with `pg_resgroup_move_query()`. +The server gates those four entry points on membership of `mdb_admin`, +identified by a **fixed OID (8067)** rather than by name, so the privilege is +recognised reliably across the coordinator and all segments. + +A fixed OID cannot be obtained from a plain `CREATE ROLE` (that assigns an +ordinary OID). This extension provides the one supported way to create the +role at OID 8067. + +## Functions + +### `pg_create_mdb_admin_role() returns oid` + +Creates the `mdb_admin` role with its fixed OID (8067). +Returns the OID of the created role (8067). Errors if a role with that OID or +the name `mdb_admin` already exists. The OID assignment is dispatched to the +segments, so the role has the same OID cluster-wide. + +## Usage + +```sql +CREATE EXTENSION pg_aux_catalog; + +-- Provision the role (the control plane does this once per cluster). +SELECT pg_create_mdb_admin_role(); + +-- Grant the capability to a tenant admin. +GRANT mdb_admin TO cloud_admin; + +-- cloud_admin can now manage resource groups without superuser: +SET ROLE cloud_admin; +CREATE RESOURCE GROUP rg_tenant WITH (concurrency = 4, cpu_max_percent = 20); +ALTER RESOURCE GROUP rg_tenant SET cpu_max_percent 30; +DROP RESOURCE GROUP rg_tenant; +``` + +`admin_group` and `system_group` remain superuser-only for `ALTER`/`DROP`: +they are infrastructure, not user-tunable groups. + +## Building and testing + +```sh +make -C contrib/pg_aux_catalog install +make -C contrib/pg_aux_catalog installcheck +``` + +`installcheck` runs a single-session regression test (role creation and the +resource-group permission gate). A multi-session isolation2 test covering the +dispatched / cross-session behaviour lives under `isolation2/` and is run +separately, against a cluster with resource groups enabled +(`gp_resource_manager=group`): + +```sh +make -C contrib/pg_aux_catalog installcheck-isolation2 +``` + +## Credits + +Based on [pg-sharding/cpg](https://github.com/pg-sharding/cpg) commit +`7b8c912`. Some tests are adapted from open-gpdb/gpdb commit `3ac99962ad2`. diff --git a/contrib/pg_aux_catalog/expected/pg_aux_catalog.out b/contrib/pg_aux_catalog/expected/pg_aux_catalog.out new file mode 100644 index 00000000000..32e52b9728d --- /dev/null +++ b/contrib/pg_aux_catalog/expected/pg_aux_catalog.out @@ -0,0 +1,46 @@ +-- Tests for the pg_aux_catalog extension: creation of the fixed-OID +-- mdb_admin role and the resource-group permission gate it enables. +CREATE EXTENSION pg_aux_catalog; +-- --------------------------------------------------------------------- +-- pg_create_mdb_admin_role() creates the mdb_admin role with its fixed OID. +-- --------------------------------------------------------------------- +SELECT pg_create_mdb_admin_role() AS mdb_admin_oid; + mdb_admin_oid +--------------- + 8067 +(1 row) + +-- The role exists with the fixed OID and is a non-login, non-superuser, +-- connection-limited role. +SELECT oid = 8067 AS has_fixed_oid, rolcanlogin, rolsuper, + rolcreaterole, rolcreatedb, rolconnlimit + FROM pg_authid WHERE rolname = 'mdb_admin'; + has_fixed_oid | rolcanlogin | rolsuper | rolcreaterole | rolcreatedb | rolconnlimit +---------------+-------------+----------+---------------+-------------+-------------- + t | f | f | f | f | 0 +(1 row) + +-- Creating it a second time is rejected. +SELECT pg_create_mdb_admin_role(); +ERROR: role with OID 8067 already exists +-- --------------------------------------------------------------------- +-- Resource-group permission gate: a role that is not a member of mdb_admin +-- is rejected on every entry point. These checks run before the "resource +-- group is enabled" check, so they are deterministic regardless of the +-- resource manager in use. +-- --------------------------------------------------------------------- +CREATE ROLE regress_rg_noadmin; +SET ROLE regress_rg_noadmin; +CREATE RESOURCE GROUP regress_rg_x WITH (concurrency=1, cpu_max_percent=5); +ERROR: must be mdb_admin to create resource groups +ALTER RESOURCE GROUP regress_rg_x SET cpu_max_percent 6; +ERROR: must be mdb_admin to alter resource groups +DROP RESOURCE GROUP regress_rg_x; +ERROR: must be mdb_admin to drop resource groups +RESET ROLE; +DROP ROLE regress_rg_noadmin; +-- --------------------------------------------------------------------- +-- Cleanup. +-- --------------------------------------------------------------------- +DROP ROLE mdb_admin; +DROP EXTENSION pg_aux_catalog; diff --git a/contrib/pg_aux_catalog/isolation2/expected/resgroup_mdb_admin.out b/contrib/pg_aux_catalog/isolation2/expected/resgroup_mdb_admin.out new file mode 100644 index 00000000000..7d8ed663485 --- /dev/null +++ b/contrib/pg_aux_catalog/isolation2/expected/resgroup_mdb_admin.out @@ -0,0 +1,218 @@ +-- Tests permission checks for the mdb_admin role with +-- resource groups enabled. + +-- start_matchsubs +-- m/ERROR: cannot find process: \d+/ +-- s/\d+/XXX/g +-- end_matchsubs + +DROP ROLE IF EXISTS role_rg_admin; +DROP +DROP ROLE IF EXISTS role_rg_noadmin; +DROP +DROP ROLE IF EXISTS mdb_admin; +DROP +-- start_ignore +DROP RESOURCE GROUP rg_perm_admin1; +DROP RESOURCE GROUP rg_perm_admin2; +DROP RESOURCE GROUP rg_perm_revoke1; +DROP RESOURCE GROUP rg_perm_revoke2; +DROP RESOURCE GROUP rg_perm_test; +-- end_ignore + +-- --------------------------------------------------------------------- +-- Setup. mdb_admin is identified by its fixed OID, so it must be created +-- through contrib/pg_aux_catalog (a plain CREATE ROLE would assign a +-- different OID and the permission checks would not recognise its members). +-- --------------------------------------------------------------------- +CREATE RESOURCE GROUP rg_perm_test WITH (concurrency=2, cpu_max_percent=10); +CREATE +CREATE EXTENSION IF NOT EXISTS pg_aux_catalog; +CREATE EXTENSION +SELECT pg_create_mdb_admin_role(); + pg_create_mdb_admin_role +-------------------------- + 8067 +(1 row) + +CREATE ROLE role_rg_admin RESOURCE GROUP rg_perm_test; +CREATE +CREATE ROLE role_rg_noadmin RESOURCE GROUP rg_perm_test; +CREATE +GRANT mdb_admin TO role_rg_admin; +GRANT + +-- --------------------------------------------------------------------- +-- 1. Member of mdb_admin can CREATE/ALTER/DROP resource groups +-- (statements are dispatched to segments). +-- --------------------------------------------------------------------- +1: SET ROLE role_rg_admin; +SET +1: CREATE RESOURCE GROUP rg_perm_admin1 WITH (concurrency=1, cpu_max_percent=5); +CREATE +1: ALTER RESOURCE GROUP rg_perm_admin1 SET cpu_max_percent 6; +ALTER +1: DROP RESOURCE GROUP rg_perm_admin1; +DROP + +-- 2. Even a member cannot ALTER or DROP the system admin_group. +1: ALTER RESOURCE GROUP admin_group SET cpu_max_percent 99; +ERROR: must be superuser to alter resource group "admin_group" +1: DROP RESOURCE GROUP admin_group; +ERROR: must be superuser to drop resource group "admin_group" +1q: ... + +-- --------------------------------------------------------------------- +-- 3. A non-member is rejected on every entry point. +-- --------------------------------------------------------------------- +2: SET ROLE role_rg_noadmin; +SET +2: CREATE RESOURCE GROUP rg_perm_admin2 WITH (concurrency=1, cpu_max_percent=5); +ERROR: must be mdb_admin to create resource groups +2: ALTER RESOURCE GROUP rg_perm_test SET cpu_max_percent 7; +ERROR: must be mdb_admin to alter resource groups +2: DROP RESOURCE GROUP rg_perm_test; +ERROR: must be mdb_admin to drop resource groups +2q: ... + +-- --------------------------------------------------------------------- +-- 4. pg_resgroup_move_query() honours the same permission check. +-- The first call (non-member) must fail with "must be mdb_admin". +-- The second call (member) gets past the permission gate and +-- fails on the pid lookup (masked by start_matchsubs above). +-- --------------------------------------------------------------------- +3: SET ROLE role_rg_noadmin; +SET +3: SELECT pg_resgroup_move_query(999999999, 'admin_group'); +ERROR: must be mdb_admin to move query +3: RESET ROLE; +RESET +3: SET ROLE role_rg_admin; +SET +3: SELECT pg_resgroup_move_query(999999999, 'admin_group'); +ERROR: cannot find process: XXX +3q: ... + +-- --------------------------------------------------------------------- +-- 5. Cross-session REVOKE takes effect on the granted session's +-- next statement (the privilege is re-checked per command, not +-- cached at SET ROLE time). +-- --------------------------------------------------------------------- +4: SET ROLE role_rg_admin; +SET +4: CREATE RESOURCE GROUP rg_perm_revoke1 WITH (concurrency=1, cpu_max_percent=5); +CREATE +5: REVOKE mdb_admin FROM role_rg_admin; +REVOKE +4: CREATE RESOURCE GROUP rg_perm_revoke2 WITH (concurrency=1, cpu_max_percent=5); +ERROR: must be mdb_admin to create resource groups +4: DROP RESOURCE GROUP rg_perm_revoke1; +ERROR: must be mdb_admin to drop resource groups +4q: ... +5q: ... + +-- --------------------------------------------------------------------- +-- Cleanup. Roles must be dropped before the resource group they +-- reference, otherwise DROP RESOURCE GROUP fails with +-- "resource group is used by at least one role". +-- --------------------------------------------------------------------- +RESET ROLE; +RESET +DROP ROLE role_rg_admin; +DROP +DROP ROLE role_rg_noadmin; +DROP +DROP ROLE mdb_admin; +DROP +DROP RESOURCE GROUP rg_perm_revoke1; +DROP +DROP RESOURCE GROUP rg_perm_test; +DROP + + +-- --------------------------------------------------------------------- +-- 1. Member of mdb_admin can CREATE/ALTER/DROP resource groups +-- (statements are dispatched to segments). +-- --------------------------------------------------------------------- +1: SET ROLE role_rg_admin; +SET +1: CREATE RESOURCE GROUP rg_perm_admin1 WITH (concurrency=1, cpu_max_percent=5); +CREATE +1: ALTER RESOURCE GROUP rg_perm_admin1 SET cpu_max_percent 6; +ALTER +1: DROP RESOURCE GROUP rg_perm_admin1; +DROP + +-- 2. Even a member cannot ALTER or DROP the system admin_group. +1: ALTER RESOURCE GROUP admin_group SET cpu_max_percent 99; +ERROR: must be superuser to alter resource group "admin_group" +1: DROP RESOURCE GROUP admin_group; +ERROR: must be superuser to drop resource group "admin_group" +1q: ... + +-- --------------------------------------------------------------------- +-- 3. A non-member is rejected on every entry point. +-- --------------------------------------------------------------------- +2: SET ROLE role_rg_noadmin; +SET +2: CREATE RESOURCE GROUP rg_perm_admin2 WITH (concurrency=1, cpu_max_percent=5); +ERROR: must be mdb_admin to create resource groups +2: ALTER RESOURCE GROUP rg_perm_test SET cpu_max_percent 7; +ERROR: must be mdb_admin to alter resource groups +2: DROP RESOURCE GROUP rg_perm_test; +ERROR: must be mdb_admin to drop resource groups +2q: ... + +-- --------------------------------------------------------------------- +-- 4. pg_resgroup_move_query() honours the same permission check. +-- The first call (non-member) must fail with "must be mdb_admin". +-- The second call (member) gets past the permission gate and +-- fails on the pid lookup (masked by start_matchsubs above). +-- --------------------------------------------------------------------- +3: SET ROLE role_rg_noadmin; +SET +3: SELECT pg_resgroup_move_query(999999999, 'admin_group'); +ERROR: must be mdb_admin to move query +3: RESET ROLE; +RESET +3: SET ROLE role_rg_admin; +SET +3: SELECT pg_resgroup_move_query(999999999, 'admin_group'); +ERROR: cannot find process: XXX +3q: ... + +-- --------------------------------------------------------------------- +-- 5. Cross-session REVOKE takes effect on the granted session's +-- next statement (the privilege is re-checked per command, not +-- cached at SET ROLE time). +-- --------------------------------------------------------------------- +4: SET ROLE role_rg_admin; +SET +4: CREATE RESOURCE GROUP rg_perm_revoke1 WITH (concurrency=1, cpu_max_percent=5); +CREATE +5: REVOKE mdb_admin FROM role_rg_admin; +REVOKE +4: CREATE RESOURCE GROUP rg_perm_revoke2 WITH (concurrency=1, cpu_max_percent=5); +ERROR: must be mdb_admin to create resource groups +4: DROP RESOURCE GROUP rg_perm_revoke1; +ERROR: must be mdb_admin to drop resource groups +4q: ... +5q: ... + +-- --------------------------------------------------------------------- +-- Cleanup. Roles must be dropped before the resource group they +-- reference, otherwise DROP RESOURCE GROUP fails with +-- "resource group is used by at least one role". +-- --------------------------------------------------------------------- +RESET ROLE; +RESET +DROP ROLE role_rg_admin; +DROP +DROP ROLE role_rg_noadmin; +DROP +DROP ROLE mdb_admin; +DROP +DROP RESOURCE GROUP rg_perm_revoke1; +DROP +DROP RESOURCE GROUP rg_perm_test; +DROP diff --git a/contrib/pg_aux_catalog/isolation2/isolation2_schedule b/contrib/pg_aux_catalog/isolation2/isolation2_schedule new file mode 100644 index 00000000000..cb32fe3e768 --- /dev/null +++ b/contrib/pg_aux_catalog/isolation2/isolation2_schedule @@ -0,0 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +test: resgroup_mdb_admin diff --git a/contrib/pg_aux_catalog/isolation2/sql/resgroup_mdb_admin.sql b/contrib/pg_aux_catalog/isolation2/sql/resgroup_mdb_admin.sql new file mode 100644 index 00000000000..1b7ea19fb3e --- /dev/null +++ b/contrib/pg_aux_catalog/isolation2/sql/resgroup_mdb_admin.sql @@ -0,0 +1,91 @@ +-- Tests permission checks for the mdb_admin role with +-- resource groups enabled. + +-- start_matchsubs +-- m/ERROR: cannot find process: \d+/ +-- s/\d+/XXX/g +-- end_matchsubs + +DROP ROLE IF EXISTS role_rg_admin; +DROP ROLE IF EXISTS role_rg_noadmin; +DROP ROLE IF EXISTS mdb_admin; +-- start_ignore +DROP RESOURCE GROUP rg_perm_admin1; +DROP RESOURCE GROUP rg_perm_admin2; +DROP RESOURCE GROUP rg_perm_revoke1; +DROP RESOURCE GROUP rg_perm_revoke2; +DROP RESOURCE GROUP rg_perm_test; +-- end_ignore + +-- --------------------------------------------------------------------- +-- Setup. mdb_admin is identified by its fixed OID, so it must be created +-- through contrib/pg_aux_catalog (a plain CREATE ROLE would assign a +-- different OID and the permission checks would not recognise its members). +-- --------------------------------------------------------------------- +CREATE RESOURCE GROUP rg_perm_test WITH (concurrency=2, cpu_max_percent=10); +CREATE EXTENSION IF NOT EXISTS pg_aux_catalog; +SELECT pg_create_mdb_admin_role(); +CREATE ROLE role_rg_admin RESOURCE GROUP rg_perm_test; +CREATE ROLE role_rg_noadmin RESOURCE GROUP rg_perm_test; +GRANT mdb_admin TO role_rg_admin; + +-- --------------------------------------------------------------------- +-- 1. Member of mdb_admin can CREATE/ALTER/DROP resource groups +-- (statements are dispatched to segments). +-- --------------------------------------------------------------------- +1: SET ROLE role_rg_admin; +1: CREATE RESOURCE GROUP rg_perm_admin1 WITH (concurrency=1, cpu_max_percent=5); +1: ALTER RESOURCE GROUP rg_perm_admin1 SET cpu_max_percent 6; +1: DROP RESOURCE GROUP rg_perm_admin1; + +-- 2. Even a member cannot ALTER or DROP the system admin_group. +1: ALTER RESOURCE GROUP admin_group SET cpu_max_percent 99; +1: DROP RESOURCE GROUP admin_group; +1q: + +-- --------------------------------------------------------------------- +-- 3. A non-member is rejected on every entry point. +-- --------------------------------------------------------------------- +2: SET ROLE role_rg_noadmin; +2: CREATE RESOURCE GROUP rg_perm_admin2 WITH (concurrency=1, cpu_max_percent=5); +2: ALTER RESOURCE GROUP rg_perm_test SET cpu_max_percent 7; +2: DROP RESOURCE GROUP rg_perm_test; +2q: + +-- --------------------------------------------------------------------- +-- 4. pg_resgroup_move_query() honours the same permission check. +-- The first call (non-member) must fail with "must be mdb_admin". +-- The second call (member) gets past the permission gate and +-- fails on the pid lookup (masked by start_matchsubs above). +-- --------------------------------------------------------------------- +3: SET ROLE role_rg_noadmin; +3: SELECT pg_resgroup_move_query(999999999, 'admin_group'); +3: RESET ROLE; +3: SET ROLE role_rg_admin; +3: SELECT pg_resgroup_move_query(999999999, 'admin_group'); +3q: + +-- --------------------------------------------------------------------- +-- 5. Cross-session REVOKE takes effect on the granted session's +-- next statement (the privilege is re-checked per command, not +-- cached at SET ROLE time). +-- --------------------------------------------------------------------- +4: SET ROLE role_rg_admin; +4: CREATE RESOURCE GROUP rg_perm_revoke1 WITH (concurrency=1, cpu_max_percent=5); +5: REVOKE mdb_admin FROM role_rg_admin; +4: CREATE RESOURCE GROUP rg_perm_revoke2 WITH (concurrency=1, cpu_max_percent=5); +4: DROP RESOURCE GROUP rg_perm_revoke1; +4q: +5q: + +-- --------------------------------------------------------------------- +-- Cleanup. Roles must be dropped before the resource group they +-- reference, otherwise DROP RESOURCE GROUP fails with +-- "resource group is used by at least one role". +-- --------------------------------------------------------------------- +RESET ROLE; +DROP ROLE role_rg_admin; +DROP ROLE role_rg_noadmin; +DROP ROLE mdb_admin; +DROP RESOURCE GROUP rg_perm_revoke1; +DROP RESOURCE GROUP rg_perm_test; diff --git a/contrib/pg_aux_catalog/pg_aux_catalog--1.0.sql b/contrib/pg_aux_catalog/pg_aux_catalog--1.0.sql new file mode 100644 index 00000000000..a1e1b00fcce --- /dev/null +++ b/contrib/pg_aux_catalog/pg_aux_catalog--1.0.sql @@ -0,0 +1,10 @@ +/* contrib/pg_aux_catalog/pg_aux_catalog--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION pg_aux_catalog" to load this file. \quit + +-- Create the mdb_admin role with fixed OID 8067 +CREATE FUNCTION pg_create_mdb_admin_role() +RETURNS OID +AS 'MODULE_PATHNAME', 'pg_create_mdb_admin_role' +LANGUAGE C PARALLEL SAFE STRICT; diff --git a/contrib/pg_aux_catalog/pg_aux_catalog.c b/contrib/pg_aux_catalog/pg_aux_catalog.c new file mode 100644 index 00000000000..958bd2f55be --- /dev/null +++ b/contrib/pg_aux_catalog/pg_aux_catalog.c @@ -0,0 +1,105 @@ +/*------------------------------------------------------------------------- + * + * pg_aux_catalog.c + * Extension for auxiliary catalog management + * + * contrib/pg_aux_catalog/pg_aux_catalog.c + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *------------------------------------------------------------------------- + */ +#include "postgres.h" + +#include "catalog/oid_dispatch.h" +#include "catalog/pg_authid.h" +#include "commands/user.h" +#include "fmgr.h" +#include "miscadmin.h" +#include "nodes/makefuncs.h" +#include "nodes/parsenodes.h" +#include "utils/acl.h" +#include "utils/builtins.h" +#include "utils/syscache.h" + +PG_MODULE_MAGIC; + +/* Name of the mdb_admin role; its OID is MDB_ADMIN_ROLEID (see acl.h). */ +#define MDB_ADMIN_ROLE_NAME "mdb_admin" + +PG_FUNCTION_INFO_V1(pg_create_mdb_admin_role); + +/* + * Create the mdb_admin role with its fixed OID (MDB_ADMIN_ROLEID, 8067). + * + * The core privilege checks identify mdb_admin by this fixed OID (see acl.c + * and resgroupcmds.c), so the role must always be created with it. On a + * Cloudberry cluster the OID is dispatched to the segments so the role ends + * up with the same OID everywhere. Returns the new role's OID. + */ +Datum +pg_create_mdb_admin_role(PG_FUNCTION_ARGS) +{ + CreateRoleStmt stmt; + List *options = NIL; + Oid roleid; + + /* + * Only a superuser may establish the mdb_admin privilege role. Otherwise + * a CREATEROLE user could drop mdb_admin and re-create it (CreateRole only + * requires CREATEROLE), taking ownership of the fixed-OID role and + * granting the capability to itself. + */ + if (!superuser()) + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("must be superuser to create the mdb_admin role"))); + + /* Check if a role with the fixed OID already exists. */ + if (SearchSysCacheExists1(AUTHOID, ObjectIdGetDatum(MDB_ADMIN_ROLEID))) + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("role with OID %u already exists", MDB_ADMIN_ROLEID))); + + /* Check if a role named "mdb_admin" already exists. */ + if (SearchSysCacheExists1(AUTHNAME, CStringGetDatum(MDB_ADMIN_ROLE_NAME))) + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("role \"%s\" already exists", MDB_ADMIN_ROLE_NAME))); + + /* Build options for CreateRole: connection limit = 0. */ + options = list_make1(makeDefElem("connectionlimit", + (Node *) makeInteger(0), -1)); + + /* Prepare the CreateRoleStmt. */ + memset(&stmt, 0, sizeof(stmt)); + stmt.type = T_CreateRoleStmt; + stmt.stmt_type = ROLESTMT_ROLE; + stmt.role = MDB_ADMIN_ROLE_NAME; + stmt.options = options; + + /* + * Request the fixed OID for the role. GetNewOidForAuthId() consumes and + * clears this override. + */ + next_aux_pg_authid_oid = MDB_ADMIN_ROLEID; + + roleid = CreateRole(NULL, &stmt); + + PG_RETURN_OID(roleid); +} diff --git a/contrib/pg_aux_catalog/pg_aux_catalog.control b/contrib/pg_aux_catalog/pg_aux_catalog.control new file mode 100644 index 00000000000..aff4205f7eb --- /dev/null +++ b/contrib/pg_aux_catalog/pg_aux_catalog.control @@ -0,0 +1,5 @@ +# pg_aux_catalog extension +comment = 'auxiliary catalog management (mdb_admin role creation)' +default_version = '1.0' +module_pathname = '$libdir/pg_aux_catalog' +relocatable = false diff --git a/contrib/pg_aux_catalog/sql/pg_aux_catalog.sql b/contrib/pg_aux_catalog/sql/pg_aux_catalog.sql new file mode 100644 index 00000000000..aa16ffe4e13 --- /dev/null +++ b/contrib/pg_aux_catalog/sql/pg_aux_catalog.sql @@ -0,0 +1,38 @@ +-- Tests for the pg_aux_catalog extension: creation of the fixed-OID +-- mdb_admin role and the resource-group permission gate it enables. + +CREATE EXTENSION pg_aux_catalog; + +-- --------------------------------------------------------------------- +-- pg_create_mdb_admin_role() creates the mdb_admin role with its fixed OID. +-- --------------------------------------------------------------------- +SELECT pg_create_mdb_admin_role() AS mdb_admin_oid; + +-- The role exists with the fixed OID and is a non-login, non-superuser, +-- connection-limited role. +SELECT oid = 8067 AS has_fixed_oid, rolcanlogin, rolsuper, + rolcreaterole, rolcreatedb, rolconnlimit + FROM pg_authid WHERE rolname = 'mdb_admin'; + +-- Creating it a second time is rejected. +SELECT pg_create_mdb_admin_role(); + +-- --------------------------------------------------------------------- +-- Resource-group permission gate: a role that is not a member of mdb_admin +-- is rejected on every entry point. These checks run before the "resource +-- group is enabled" check, so they are deterministic regardless of the +-- resource manager in use. +-- --------------------------------------------------------------------- +CREATE ROLE regress_rg_noadmin; +SET ROLE regress_rg_noadmin; +CREATE RESOURCE GROUP regress_rg_x WITH (concurrency=1, cpu_max_percent=5); +ALTER RESOURCE GROUP regress_rg_x SET cpu_max_percent 6; +DROP RESOURCE GROUP regress_rg_x; +RESET ROLE; +DROP ROLE regress_rg_noadmin; + +-- --------------------------------------------------------------------- +-- Cleanup. +-- --------------------------------------------------------------------- +DROP ROLE mdb_admin; +DROP EXTENSION pg_aux_catalog; diff --git a/gpMgmt/bin/gpinitsystem b/gpMgmt/bin/gpinitsystem index fa85d42ae3f..f8d42e87b11 100755 --- a/gpMgmt/bin/gpinitsystem +++ b/gpMgmt/bin/gpinitsystem @@ -1272,6 +1272,7 @@ CREATE_QD_DB () { if [ x"$HEAP_CHECKSUM" == x"on" ]; then cmd="$cmd --data-checksums" fi + cmd="$cmd --allow-group-access" LOG_MSG "[INFO]:-Commencing local $cmd" $cmd >> $LOG_FILE 2>&1 RETVAL=$? diff --git a/gpMgmt/bin/lib/gpconfigurenewsegment b/gpMgmt/bin/lib/gpconfigurenewsegment index c37c70bf1fa..a372ad291ec 100755 --- a/gpMgmt/bin/lib/gpconfigurenewsegment +++ b/gpMgmt/bin/lib/gpconfigurenewsegment @@ -9,7 +9,7 @@ import shutil from optparse import Option, OptionGroup, OptionParser, OptionValueError, SUPPRESS_USAGE from gppylib.gpparseopts import OptParser, OptChecker -from gppylib.commands.gp import ModifyConfSetting, SegmentStart, SegmentStop +from gppylib.commands.gp import GpConfigHelper, ModifyConfSetting, SegmentStart, SegmentStop from gppylib.commands.pg import PgBaseBackup from gppylib.db import dbconn from gppylib.commands import unix @@ -268,6 +268,24 @@ class ConfExpSegCmd(Command): self.set_results(modifyConfCmd.get_results()) raise + # Update --content-id flag in wal-g for archive-restore GUCs if present + for guc in ['archive_command', 'restore_command']: + read_cmd = GpConfigHelper('Read %s' % guc, self.datadir, guc, getParameter=True) + read_cmd.run(validateAfter=True) + + val = read_cmd.get_value() + if not read_cmd.was_successful() or not val: + continue + + new_val = re.sub(r'(--content-id(?:=|\s+))-?\d+', r'\g<1>' + str(self.contentid), val) + if new_val != val: + write_cmd = GpConfigHelper('Update %s' % guc, self.datadir, guc, value=new_val) + try: + write_cmd.run(validateAfter=True) + except Exception: + self.set_results(write_cmd.get_results()) + raise + # We might need to stop the segment if the last setup failed past this point if os.path.exists('%s/postmaster.pid' % self.datadir): logger.info('%s/postmaster.pid exists. Stopping segment' % self.datadir) diff --git a/gpMgmt/bin/lib/gpcreateseg.sh b/gpMgmt/bin/lib/gpcreateseg.sh index 5dd0f5b0006..89f5f405295 100755 --- a/gpMgmt/bin/lib/gpcreateseg.sh +++ b/gpMgmt/bin/lib/gpcreateseg.sh @@ -106,6 +106,7 @@ CREATE_QES_PRIMARY () { cmd="$cmd $LC_ALL_SETTINGS" cmd="$cmd --max_connections=$QE_MAX_CONNECT" cmd="$cmd --shared_buffers=$QE_SHARED_BUFFERS" + cmd="$cmd --allow-group-access" if [ x"$HEAP_CHECKSUM" == x"on" ]; then cmd="$cmd --data-checksums" fi diff --git a/gpcontrib/Makefile b/gpcontrib/Makefile index 8d95a14f876..c62855d3089 100644 --- a/gpcontrib/Makefile +++ b/gpcontrib/Makefile @@ -35,6 +35,12 @@ else diskquota endif +ifeq "$(with_gp_stats_collector)" "yes" + recurse_targets += gp_stats_collector +endif +ifeq "$(with_yezzey)" "yes" + recurse_targets += yezzey +endif ifeq "$(with_zstd)" "yes" recurse_targets += zstd endif diff --git a/gpcontrib/yezzey b/gpcontrib/yezzey new file mode 160000 index 00000000000..2b5dcadd45b --- /dev/null +++ b/gpcontrib/yezzey @@ -0,0 +1 @@ +Subproject commit 2b5dcadd45b4183a4aa5ab976e50c97f0d4c7057 diff --git a/src/Makefile.global.in b/src/Makefile.global.in index 77b58e7aa76..457a4a0944e 100644 --- a/src/Makefile.global.in +++ b/src/Makefile.global.in @@ -271,6 +271,9 @@ with_zstd = @with_zstd@ ZSTD_CFLAGS = @ZSTD_CFLAGS@ ZSTD_LIBS = @ZSTD_LIBS@ EVENT_LIBS = @EVENT_LIBS@ +with_diskquota = @with_diskquota@ +with_gp_stats_collector = @with_gp_stats_collector@ +with_yezzey = @with_yezzey@ ########################################################################## # diff --git a/src/backend/catalog/oid_dispatch.c b/src/backend/catalog/oid_dispatch.c index 6f39a07857e..95afd25d0b0 100644 --- a/src/backend/catalog/oid_dispatch.c +++ b/src/backend/catalog/oid_dispatch.c @@ -129,6 +129,7 @@ #include "catalog/pg_type.h" #include "catalog/pg_user_mapping.h" #include "catalog/oid_dispatch.h" +#include "access/transam.h" #include "cdb/cdbvars.h" #include "executor/execdesc.h" #include "lib/rbtree.h" @@ -156,6 +157,18 @@ static MemoryContext oids_context = NULL; static bool preserve_oids_on_commit = false; +/* + * OID to assign to the next auxiliary pg_authid role created through + * GetNewOidForAuthId(), or InvalidOid for the normal allocation path. + * + * This is the GPDB analogue of upstream PostgreSQL's + * binary_upgrade_next_pg_authid_oid (which is disabled here in favour of the + * generic OID pre-assignment machinery). It lets contrib/pg_aux_catalog + * create roles such as mdb_admin with a fixed, well-known OID. It is reset + * to InvalidOid as soon as it is consumed. + */ +Oid next_aux_pg_authid_oid = InvalidOid; + /* * These will be used by the schema restoration process during binary upgrade, * so any new object must not use any Oid in this structure or else there will @@ -423,6 +436,7 @@ GetNewOrPreassignedOid(Relation relation, Oid indexId, AttrNumber oidcolumn, OidAssignment *searchkey) { Oid oid; + Oid forcedOid = searchkey->oid; searchkey->catalog = RelationGetRelid(relation); @@ -461,8 +475,18 @@ GetNewOrPreassignedOid(Relation relation, Oid indexId, AttrNumber oidcolumn, { MemoryContext oldcontext; - /* Assign a new oid, and memorize it in the list of OIDs to dispatch */ - oid = GetNewOidWithIndex(relation, indexId, oidcolumn); + /* + * Assign a new oid, and memorize it in the list of OIDs to dispatch. + * + * A caller may request a fixed, well-known OID by passing it in + * searchkey->oid (e.g. the mdb_admin auxiliary role, see + * GetNewOidForAuthId()). In that case use the requested OID instead + * of allocating a fresh one, but still record it for dispatch so the + * QEs end up with the same OID. + */ + oid = OidIsValid(forcedOid) + ? forcedOid + : GetNewOidWithIndex(relation, indexId, oidcolumn); oldcontext = MemoryContextSwitchTo(get_oids_context()); searchkey->oid = oid; @@ -479,7 +503,9 @@ GetNewOrPreassignedOid(Relation relation, Oid indexId, AttrNumber oidcolumn, } else { - oid = GetNewOidWithIndex(relation, indexId, oidcolumn); + oid = OidIsValid(forcedOid) + ? forcedOid + : GetNewOidWithIndex(relation, indexId, oidcolumn); } return oid; @@ -572,6 +598,25 @@ GetNewOidForAuthId(Relation relation, Oid indexId, AttrNumber oidcolumn, memset(&key, 0, sizeof(OidAssignment)); key.type = T_OidAssignment; key.objname = rolname; + + /* + * Allow auxiliary roles (such as mdb_admin, see contrib/pg_aux_catalog) + * to be created with a fixed, well-known OID. The OID is supplied through + * the next_aux_pg_authid_oid override, mirroring how upstream PostgreSQL + * assigns role OIDs during binary upgrade. We only honor it for OIDs in + * the auxiliary range to avoid clashing with normal OID allocation, and + * reset it immediately so it affects a single role only. + */ + if (OidIsValid(next_aux_pg_authid_oid)) + { + if (!IsAuxOid(next_aux_pg_authid_oid)) + elog(ERROR, "pre-assigned auxiliary role OID %u is out of the auxiliary OID range", + next_aux_pg_authid_oid); + + key.oid = next_aux_pg_authid_oid; + next_aux_pg_authid_oid = InvalidOid; + } + return GetNewOrPreassignedOid(relation, indexId, oidcolumn, &key); } diff --git a/src/backend/commands/resgroupcmds.c b/src/backend/commands/resgroupcmds.c index 384675edb7f..b746a3db49b 100644 --- a/src/backend/commands/resgroupcmds.c +++ b/src/backend/commands/resgroupcmds.c @@ -34,6 +34,7 @@ #include "commands/resgroupcmds.h" #include "miscadmin.h" #include "nodes/pg_list.h" +#include "utils/acl.h" #include "utils/builtins.h" #include "utils/datetime.h" #include "utils/fmgroids.h" @@ -103,11 +104,11 @@ CreateResourceGroup(CreateResourceGroupStmt *stmt) int nResGroups; MemoryContext oldContext; - /* Permission check - only superuser can create groups. */ - if (!superuser()) + /* Permission check - only superuser or mdb_admin can create groups. */ + if (!is_member_of_role(GetUserId(), MDB_ADMIN_ROLEID)) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("must be superuser to create resource groups"))); + errmsg("must be mdb_admin to create resource groups"))); /* * Check for an illegal name ('none' is used to signify no group in ALTER ROLE). @@ -269,11 +270,11 @@ DropResourceGroup(DropResourceGroupStmt *stmt) Oid groupid; ResourceGroupCallbackContext *callbackCtx; - /* Permission check - only superuser can drop resource groups. */ - if (!superuser()) + /* Permission check - only superuser or mdb_admin can drop resource groups. */ + if (!is_member_of_role(GetUserId(), MDB_ADMIN_ROLEID)) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("must be superuser to drop resource groups"))); + errmsg("must be mdb_admin to drop resource groups"))); /* * Check the pg_resgroup relation to be certain the resource group already @@ -302,6 +303,13 @@ DropResourceGroup(DropResourceGroupStmt *stmt) */ groupid = ((Form_pg_resgroup) GETSTRUCT(tuple))->oid; + /* Permission check - only superuser can drop the admin/system resource groups. */ + if (!superuser() && (groupid == ADMINRESGROUP_OID || groupid == SYSTEMRESGROUP_OID)) + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("must be superuser to drop resource group \"%s\"", + stmt->name))); + /* cannot DROP default resource groups */ if (groupid == DEFAULTRESGROUP_OID || groupid == ADMINRESGROUP_OID @@ -375,11 +383,24 @@ AlterResourceGroup(AlterResourceGroupStmt *stmt) ResourceGroupCallbackContext *callbackCtx; MemoryContext oldContext; - /* Permission check - only superuser can alter resource groups. */ - if (!superuser()) + /* Permission check - only mdb_admin can alter resource groups. */ + if (!is_member_of_role(GetUserId(), MDB_ADMIN_ROLEID)) + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("must be mdb_admin to alter resource groups"))); + + /* + * Check the pg_resgroup relation to be certain the resource group already + * exists. + */ + groupid = get_resgroup_oid(stmt->name, false); + + /* Permission check - only superuser can alter the admin/system resource groups. */ + if (!superuser() && (groupid == ADMINRESGROUP_OID || groupid == SYSTEMRESGROUP_OID)) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("must be superuser to alter resource groups"))); + errmsg("must be superuser to alter resource group \"%s\"", + stmt->name))); /* Currently we only support to ALTER one limit at one time */ Assert(list_length(stmt->options) == 1); @@ -406,12 +427,6 @@ AlterResourceGroup(AlterResourceGroupStmt *stmt) checkResgroupCapLimit(limitType, value); } - /* - * Check the pg_resgroup relation to be certain the resource group already - * exists. - */ - groupid = get_resgroup_oid(stmt->name, false); - if (limitType == RESGROUP_LIMIT_TYPE_CONCURRENCY && value == 0 && groupid == ADMINRESGROUP_OID) @@ -500,7 +515,7 @@ AlterResourceGroup(AlterResourceGroupStmt *stmt) RESGROUP_DEFAULT_CPU_WEIGHT, ""); updateResgroupCapabilityEntry(pg_resgroupcapability_rel, - groupid, RESGROUP_LIMIT_TYPE_CPUSET, + groupid, RESGROUP_LIMIT_TYPE_CPUSET, 0, caps.cpuset); } else if (limitType == RESGROUP_LIMIT_TYPE_CPU) @@ -1007,7 +1022,7 @@ parseStmtOptions(CreateResourceGroupStmt *stmt, ResGroupCaps *caps) else mask |= 1 << type; - if (type == RESGROUP_LIMIT_TYPE_CPUSET) + if (type == RESGROUP_LIMIT_TYPE_CPUSET) { const char *cpuset = defGetString(defel); strlcpy(caps->cpuset, cpuset, sizeof(caps->cpuset)); @@ -1611,7 +1626,7 @@ checkCpuSetByRole(const char *cpuset) * ex: * cpuset = "1;4" * then we should assign '1' to corrdinator and '4' to segment - * + * * cpuset = "1" * assign '1' to both coordinator and segment */ diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c index 1baf148f987..906480c5137 100644 --- a/src/backend/utils/adt/acl.c +++ b/src/backend/utils/adt/acl.c @@ -5129,48 +5129,6 @@ mdb_admin_allow_bypass_owner_checks(Oid userId, Oid ownerId) // -- non-upstream patch end -// -- non-upstream patch begin -/* - * Is userId allowed to bypass ownership check - * and tranfer onwership to ownerId role? - */ -bool -mdb_admin_allow_bypass_owner_checks(Oid userId, Oid ownerId) -{ - Oid mdb_admin_roleoid; - /* - * Never allow nobody to grant objects to - * superusers. - * This can result in various CVE. - * For paranoic reasons, check this even before - * membership of mdb_admin role. - */ - if (superuser_arg(ownerId)) { - return false; - } - - mdb_admin_roleoid = get_role_oid("mdb_admin", true /*if nodoby created mdb_admin role in this database*/); - /* Is userId actually member of mdb admin? */ - if (!is_member_of_role(userId, mdb_admin_roleoid)) { - /* if no, disallow. */ - return false; - } - - /* - * Now, we need to check if ownerId - * is some dangerous role to trasfer membership to. - * - * For now, we check that ownerId does not have - * priviledge to execute server program or/and - * read/write server files, or/and pg read/write all data - */ - - /* All checks passed, hope will not be hacked here (again) */ - return !has_privs_of_unwanted_system_role(ownerId); -} - -// -- non-upstream patch end - /* * Is member a member of role (directly or indirectly)? * diff --git a/src/backend/utils/resgroup/resgroup_helper.c b/src/backend/utils/resgroup/resgroup_helper.c index 00aaded168d..5acca0be5e7 100644 --- a/src/backend/utils/resgroup/resgroup_helper.c +++ b/src/backend/utils/resgroup/resgroup_helper.c @@ -21,6 +21,7 @@ #include "cdb/cdbvars.h" #include "commands/resgroupcmds.h" #include "storage/procarray.h" +#include "utils/acl.h" #include "utils/builtins.h" #include "utils/datetime.h" #include "utils/resgroup.h" @@ -464,10 +465,10 @@ pg_resgroup_move_query(PG_FUNCTION_ARGS) (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errmsg("resource group is not enabled")))); - if (!superuser()) + if (!is_member_of_role(GetUserId(), MDB_ADMIN_ROLEID)) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - (errmsg("must be superuser to move query")))); + (errmsg("must be mdb_admin to move query")))); if (Gp_role == GP_ROLE_DISPATCH) { diff --git a/src/include/access/transam.h b/src/include/access/transam.h index 687799bec9f..a1bf330b762 100644 --- a/src/include/access/transam.h +++ b/src/include/access/transam.h @@ -208,6 +208,16 @@ FullTransactionIdAdvance(FullTransactionId *dest) #define FirstBinaryUpgradeReservedObjectId 9000 #define LastBinaryUpgradeReservedObjectId 9100 +/* + * Reserve a block of OIDs for auxiliary catalog objects (such as the + * mdb_admin role created by contrib/pg_aux_catalog). These need fixed, + * well-known OIDs that are stable across clusters, so they live in their own + * range below FirstBinaryUpgradeReservedObjectId. + */ +#define FirstAuxObjectId 8000 +#define LastAuxObjectId 9000 +#define IsAuxOid(oid) ((oid) >= FirstAuxObjectId && (oid) < LastAuxObjectId) + /* * VariableCache is a data structure in shared memory that is used to track * OID and XID assignment state. For largely historical reasons, there is diff --git a/src/include/catalog/oid_dispatch.h b/src/include/catalog/oid_dispatch.h index fbb7a14f59e..d9c543bee5d 100644 --- a/src/include/catalog/oid_dispatch.h +++ b/src/include/catalog/oid_dispatch.h @@ -16,6 +16,13 @@ #include "utils/relcache.h" #include "access/htup.h" +/* + * OID to assign to the next auxiliary pg_authid role created through + * GetNewOidForAuthId(), or InvalidOid for normal allocation. Set by + * contrib/pg_aux_catalog to create roles such as mdb_admin with a fixed OID. + */ +extern PGDLLIMPORT Oid next_aux_pg_authid_oid; + /* Functions used in master */ extern List *GetAssignedOidsForDispatch(void); diff --git a/src/include/utils/acl.h b/src/include/utils/acl.h index 49068f04b2f..e3949dd8769 100644 --- a/src/include/utils/acl.h +++ b/src/include/utils/acl.h @@ -213,6 +213,14 @@ extern bool is_member_of_role_nosuper(Oid member, Oid role); extern bool is_admin_of_role(Oid member, Oid role); // -- non-upstream patch begin +/* + * Fixed, well-known OID of the mdb_admin role. The role is created by + * contrib/pg_aux_catalog (pg_create_mdb_admin_role()) with this OID, and the + * resource-group permission checks identify it by OID. It lives in the + * auxiliary OID range (see IsAuxOid()). + */ +#define MDB_ADMIN_ROLEID 8067 + extern bool mdb_admin_allow_bypass_owner_checks(Oid userId, Oid ownerId); extern void check_mdb_admin_is_member_of_role(Oid member, Oid role); diff --git a/src/test/isolation2/expected/gpexpand_archive_restore_conf.out b/src/test/isolation2/expected/gpexpand_archive_restore_conf.out new file mode 100644 index 00000000000..08d97a49c47 --- /dev/null +++ b/src/test/isolation2/expected/gpexpand_archive_restore_conf.out @@ -0,0 +1,1047 @@ +-- Verify that gpexpand correctly updates segment-specific flags for wal-g in +-- archive_command and restore_command when initializing new segments. +-- +-- Previously, these GUCs were copied verbatim from the template segment +-- (content 0), causing new segments to invoke archiving with an incorrect +-- content-id (possible overwriting archive or restoring other's data). + +-- Cleanup any previous state +!\retcode yes | gpexpand -c; +-- start_ignore +20260225:10:13:28:029615 gpexpand:cdw:gpadmin-[INFO]:-local Cloudberry Version: 'postgres (Apache Cloudberry) 3.0.0-devel+dev.4.g01c21009c35 build dev' +20260225:10:13:28:029615 gpexpand:cdw:gpadmin-[INFO]:-coordinator Cloudberry Version: 'PostgreSQL 14.4 (Apache Cloudberry 3.0.0-devel+dev.4.g01c21009c35 build dev) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 11.4.0-1ubuntu1~22.04.2) 11.4.0, 64-bit compiled on Feb 25 2026 10:08:48 (with assert checking)' +20260225:10:13:28:029615 gpexpand:cdw:gpadmin-[INFO]:-Querying gpexpand schema for current expansion state + +System Expansion is used to add segments to an existing CBDB array. +gpexpand did not detect a System Expansion that is in progress. + +Before initiating a System Expansion, you need to provision and burn-in +the new hardware. Please be sure to run gpcheckperf to make sure the +new hardware is working properly. + +Please refer to the Admin Guide for more information. + +Would you like to initiate a new System Expansion Yy|Nn (default=N): +> +Enter a comma separated list of new hosts you want +to add to your array. Do not include interface hostnames. +**Enter a blank line to only add segments to existing hosts**[]: +> 20260225:10:13:28:029615 gpexpand:cdw:gpadmin-[ERROR]:-gpexpand failed: You must be adding two or more hosts when expanding a system with mirroring enabled. + +Exiting... +20260225:10:13:28:029615 gpexpand:cdw:gpadmin-[INFO]:-Shutting down gpexpand... + +-- end_ignore +(exited with code 3) +!\retcode gpshrink -c; +-- start_ignore +20260225:10:13:28:029633 gpshrink:cdw:gpadmin-[INFO]:-local Cloudberry Version: 'postgres (Apache Cloudberry) 3.0.0-devel+dev.4.g01c21009c35 build dev' +20260225:10:13:28:029633 gpshrink:cdw:gpadmin-[INFO]:-coordinator Cloudberry Version: 'PostgreSQL 14.4 (Apache Cloudberry 3.0.0-devel+dev.4.g01c21009c35 build dev) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 11.4.0-1ubuntu1~22.04.2) 11.4.0, 64-bit compiled on Feb 25 2026 10:08:48 (with assert checking)' +20260225:10:13:28:029633 gpshrink:cdw:gpadmin-[INFO]:-Removing gpshrink schema +20260225:10:13:28:029633 gpshrink:cdw:gpadmin-[INFO]:-Cleanup Finished. exiting... + +-- end_ignore +(exited with code 0) +!\retcode rm -r /tmp/datadirs/; +-- start_ignore +rm: cannot remove '/tmp/datadirs/': No such file or directory + +-- end_ignore +(exited with code 1) + +-- Set GUCs on all segments, hardcode --content-id to 0 +!\retcode gpconfig -c restore_command -v '/bin/true'; +-- start_ignore +20260225:10:13:29:029665 gpconfig:cdw:gpadmin-[INFO]:-completed successfully with parameters '-c restore_command -v /bin/true' + +-- end_ignore +(exited with code 0) +!\retcode gpconfig -c archive_command -v 'wal-g seg wal-push %p --content-id=0'; +-- start_ignore +20260225:10:13:29:029714 gpconfig:cdw:gpadmin-[INFO]:-completed successfully with parameters '-c archive_command -v 'wal-g seg wal-push %p --content-id=0'' + +-- end_ignore +(exited with code 0) +!\retcode gpstop -u; +-- start_ignore +20260225:10:13:29:029763 gpstop:cdw:gpadmin-[INFO]:-Starting gpstop with args: -u +20260225:10:13:29:029763 gpstop:cdw:gpadmin-[INFO]:-Gathering information and validating the environment... +20260225:10:13:29:029763 gpstop:cdw:gpadmin-[INFO]:-Obtaining Cloudberry Coordinator catalog information +20260225:10:13:29:029763 gpstop:cdw:gpadmin-[INFO]:-Obtaining Segment details from coordinator... +20260225:10:13:29:029763 gpstop:cdw:gpadmin-[INFO]:-Cloudberry Version: 'postgres (Apache Cloudberry) 3.0.0-devel+dev.4.g01c21009c35 build dev' +20260225:10:13:29:029763 gpstop:cdw:gpadmin-[INFO]:-Signalling all postmaster processes to reload + +-- end_ignore +(exited with code 0) + +-- Prepare expansion configuration +!\retcode echo "localhost|localhost|7008|/tmp/datadirs/dbfast4/demoDataDir3|9|3|p localhost|localhost|7009|/tmp/datadirs/dbfast_mirror4/demoDataDir3|10|3|m" > /tmp/testexpand; +-- start_ignore + +-- end_ignore +(exited with code 0) + +-- Expand +!\retcode gpexpand -i /tmp/testexpand; +-- start_ignore +20260225:10:13:29:029792 gpexpand:cdw:gpadmin-[INFO]:-local Cloudberry Version: 'postgres (Apache Cloudberry) 3.0.0-devel+dev.4.g01c21009c35 build dev' +20260225:10:13:29:029792 gpexpand:cdw:gpadmin-[INFO]:-coordinator Cloudberry Version: 'PostgreSQL 14.4 (Apache Cloudberry 3.0.0-devel+dev.4.g01c21009c35 build dev) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 11.4.0-1ubuntu1~22.04.2) 11.4.0, 64-bit compiled on Feb 25 2026 10:08:48 (with assert checking)' +20260225:10:13:29:029792 gpexpand:cdw:gpadmin-[INFO]:-Querying gpexpand schema for current expansion state +20260225:10:13:29:029792 gpexpand:cdw:gpadmin-[INFO]:-Successfully finished pg_controldata /home/gpadmin/cloudberry/gpAux/gpdemo/datadirs/dbfast1/demoDataDir0 for dbid 2: +stdout: pg_control version number: 13000700 +Catalog version number: 302509031 +Database system identifier: 7610743540553465864 +Database cluster state: in production +pg_control last modified: Wed 25 Feb 2026 10:13:25 AM GMT +Latest checkpoint location: 0/C067FA8 +Latest checkpoint's REDO location: 0/C067F70 +Latest checkpoint's REDO WAL file: 000000010000000000000003 +Latest checkpoint's TimeLineID: 1 +Latest checkpoint's PrevTimeLineID: 1 +Latest checkpoint's full_page_writes: on +Latest checkpoint's NextXID: 0:877 +Latest checkpoint's NextGxid: 9 +Latest checkpoint's NextOID: 16392 +Latest checkpoint's NextRelfilenode: 12002 +Latest checkpoint's NextMultiXactId: 1 +Latest checkpoint's NextMultiOffset: 0 +Latest checkpoint's oldestXID: 810 +Latest checkpoint's oldestXID's DB: 13425 +Latest checkpoint's oldestActiveXID: 876 +Latest checkpoint's oldestMultiXid: 1 +Latest checkpoint's oldestMulti's DB: 1 +Latest checkpoint's oldestCommitTsXid:0 +Latest checkpoint's newestCommitTsXid:0 +Time of latest checkpoint: Wed 25 Feb 2026 10:13:25 AM GMT +Fake LSN counter for unlogged rels: 0/3E8 +Minimum recovery ending location: 0/0 +Min recovery ending loc's timeline: 0 +Backup start location: 0/0 +Backup end location: 0/0 +End-of-backup record required: no +wal_level setting: replica +wal_log_hints setting: off +max_connections setting: 750 +max_worker_processes setting: 14 +max_wal_senders setting: 10 +max_prepared_xacts setting: 250 +max_locks_per_xact setting: 128 +track_commit_timestamp setting: off +Maximum data alignment: 8 +Database block size: 32768 +Blocks per segment of large relation: 32768 +WAL block size: 32768 +Bytes per WAL segment: 67108864 +Maximum length of identifiers: 64 +Maximum columns in an index: 32 +Maximum size of a TOAST chunk: 8140 +Size of a large-object chunk: 8192 +Date/time type storage: 64-bit integers +Float8 argument passing: by value +Data page checksum version: 1 +Mock authentication nonce: 4ab1899cbfd68b59268d02e0d5a1966c0ee3f4b463979bc5372053c2b14ece58 +File encryption method: + +stderr: +20260225:10:13:29:029792 gpexpand:cdw:gpadmin-[INFO]:-Successfully finished pg_controldata /home/gpadmin/cloudberry/gpAux/gpdemo/datadirs/dbfast_mirror1/demoDataDir0 for dbid 5: +stdout: pg_control version number: 13000700 +Catalog version number: 302509031 +Database system identifier: 7610743540553465864 +Database cluster state: in archive recovery +pg_control last modified: Wed 25 Feb 2026 10:12:19 AM GMT +Latest checkpoint location: 0/C005578 +Latest checkpoint's REDO location: 0/C005578 +Latest checkpoint's REDO WAL file: 000000010000000000000003 +Latest checkpoint's TimeLineID: 1 +Latest checkpoint's PrevTimeLineID: 1 +Latest checkpoint's full_page_writes: on +Latest checkpoint's NextXID: 0:872 +Latest checkpoint's NextGxid: 3 +Latest checkpoint's NextOID: 16392 +Latest checkpoint's NextRelfilenode: 12002 +Latest checkpoint's NextMultiXactId: 1 +Latest checkpoint's NextMultiOffset: 0 +Latest checkpoint's oldestXID: 810 +Latest checkpoint's oldestXID's DB: 13425 +Latest checkpoint's oldestActiveXID: 0 +Latest checkpoint's oldestMultiXid: 1 +Latest checkpoint's oldestMulti's DB: 1 +Latest checkpoint's oldestCommitTsXid:0 +Latest checkpoint's newestCommitTsXid:0 +Time of latest checkpoint: Wed 25 Feb 2026 10:12:16 AM GMT +Fake LSN counter for unlogged rels: 0/3E8 +Minimum recovery ending location: 0/C005600 +Min recovery ending loc's timeline: 1 +Backup start location: 0/0 +Backup end location: 0/0 +End-of-backup record required: no +wal_level setting: replica +wal_log_hints setting: off +max_connections setting: 750 +max_worker_processes setting: 14 +max_wal_senders setting: 10 +max_prepared_xacts setting: 250 +max_locks_per_xact setting: 128 +track_commit_timestamp setting: off +Maximum data alignment: 8 +Database block size: 32768 +Blocks per segment of large relation: 32768 +WAL block size: 32768 +Bytes per WAL segment: 67108864 +Maximum length of identifiers: 64 +Maximum columns in an index: 32 +Maximum size of a TOAST chunk: 8140 +Size of a large-object chunk: 8192 +Date/time type storage: 64-bit integers +Float8 argument passing: by value +Data page checksum version: 1 +Mock authentication nonce: 4ab1899cbfd68b59268d02e0d5a1966c0ee3f4b463979bc5372053c2b14ece58 +File encryption method: + +stderr: +20260225:10:13:29:029792 gpexpand:cdw:gpadmin-[INFO]:-Successfully finished pg_controldata /home/gpadmin/cloudberry/gpAux/gpdemo/datadirs/dbfast2/demoDataDir1 for dbid 3: +stdout: pg_control version number: 13000700 +Catalog version number: 302509031 +Database system identifier: 7610743540653109260 +Database cluster state: in production +pg_control last modified: Wed 25 Feb 2026 10:13:25 AM GMT +Latest checkpoint location: 0/C067FA8 +Latest checkpoint's REDO location: 0/C067F70 +Latest checkpoint's REDO WAL file: 000000010000000000000003 +Latest checkpoint's TimeLineID: 1 +Latest checkpoint's PrevTimeLineID: 1 +Latest checkpoint's full_page_writes: on +Latest checkpoint's NextXID: 0:877 +Latest checkpoint's NextGxid: 9 +Latest checkpoint's NextOID: 16392 +Latest checkpoint's NextRelfilenode: 12002 +Latest checkpoint's NextMultiXactId: 1 +Latest checkpoint's NextMultiOffset: 0 +Latest checkpoint's oldestXID: 810 +Latest checkpoint's oldestXID's DB: 13425 +Latest checkpoint's oldestActiveXID: 876 +Latest checkpoint's oldestMultiXid: 1 +Latest checkpoint's oldestMulti's DB: 1 +Latest checkpoint's oldestCommitTsXid:0 +Latest checkpoint's newestCommitTsXid:0 +Time of latest checkpoint: Wed 25 Feb 2026 10:13:25 AM GMT +Fake LSN counter for unlogged rels: 0/3E8 +Minimum recovery ending location: 0/0 +Min recovery ending loc's timeline: 0 +Backup start location: 0/0 +Backup end location: 0/0 +End-of-backup record required: no +wal_level setting: replica +wal_log_hints setting: off +max_connections setting: 750 +max_worker_processes setting: 14 +max_wal_senders setting: 10 +max_prepared_xacts setting: 250 +max_locks_per_xact setting: 128 +track_commit_timestamp setting: off +Maximum data alignment: 8 +Database block size: 32768 +Blocks per segment of large relation: 32768 +WAL block size: 32768 +Bytes per WAL segment: 67108864 +Maximum length of identifiers: 64 +Maximum columns in an index: 32 +Maximum size of a TOAST chunk: 8140 +Size of a large-object chunk: 8192 +Date/time type storage: 64-bit integers +Float8 argument passing: by value +Data page checksum version: 1 +Mock authentication nonce: 91cf6a7a7826dd0c9f8ff23a43d226c7a1a72752a9b1544a78c7cfbe62970991 +File encryption method: + +stderr: +20260225:10:13:29:029792 gpexpand:cdw:gpadmin-[INFO]:-Successfully finished pg_controldata /home/gpadmin/cloudberry/gpAux/gpdemo/datadirs/dbfast_mirror2/demoDataDir1 for dbid 6: +stdout: pg_control version number: 13000700 +Catalog version number: 302509031 +Database system identifier: 7610743540653109260 +Database cluster state: in archive recovery +pg_control last modified: Wed 25 Feb 2026 10:12:19 AM GMT +Latest checkpoint location: 0/C005578 +Latest checkpoint's REDO location: 0/C005578 +Latest checkpoint's REDO WAL file: 000000010000000000000003 +Latest checkpoint's TimeLineID: 1 +Latest checkpoint's PrevTimeLineID: 1 +Latest checkpoint's full_page_writes: on +Latest checkpoint's NextXID: 0:872 +Latest checkpoint's NextGxid: 3 +Latest checkpoint's NextOID: 16392 +Latest checkpoint's NextRelfilenode: 12002 +Latest checkpoint's NextMultiXactId: 1 +Latest checkpoint's NextMultiOffset: 0 +Latest checkpoint's oldestXID: 810 +Latest checkpoint's oldestXID's DB: 13425 +Latest checkpoint's oldestActiveXID: 0 +Latest checkpoint's oldestMultiXid: 1 +Latest checkpoint's oldestMulti's DB: 1 +Latest checkpoint's oldestCommitTsXid:0 +Latest checkpoint's newestCommitTsXid:0 +Time of latest checkpoint: Wed 25 Feb 2026 10:12:16 AM GMT +Fake LSN counter for unlogged rels: 0/3E8 +Minimum recovery ending location: 0/C005600 +Min recovery ending loc's timeline: 1 +Backup start location: 0/0 +Backup end location: 0/0 +End-of-backup record required: no +wal_level setting: replica +wal_log_hints setting: off +max_connections setting: 750 +max_worker_processes setting: 14 +max_wal_senders setting: 10 +max_prepared_xacts setting: 250 +max_locks_per_xact setting: 128 +track_commit_timestamp setting: off +Maximum data alignment: 8 +Database block size: 32768 +Blocks per segment of large relation: 32768 +WAL block size: 32768 +Bytes per WAL segment: 67108864 +Maximum length of identifiers: 64 +Maximum columns in an index: 32 +Maximum size of a TOAST chunk: 8140 +Size of a large-object chunk: 8192 +Date/time type storage: 64-bit integers +Float8 argument passing: by value +Data page checksum version: 1 +Mock authentication nonce: 91cf6a7a7826dd0c9f8ff23a43d226c7a1a72752a9b1544a78c7cfbe62970991 +File encryption method: + +stderr: +20260225:10:13:29:029792 gpexpand:cdw:gpadmin-[INFO]:-Successfully finished pg_controldata /home/gpadmin/cloudberry/gpAux/gpdemo/datadirs/dbfast3/demoDataDir2 for dbid 4: +stdout: pg_control version number: 13000700 +Catalog version number: 302509031 +Database system identifier: 7610743540636610571 +Database cluster state: in production +pg_control last modified: Wed 25 Feb 2026 10:13:25 AM GMT +Latest checkpoint location: 0/C067FA8 +Latest checkpoint's REDO location: 0/C067F70 +Latest checkpoint's REDO WAL file: 000000010000000000000003 +Latest checkpoint's TimeLineID: 1 +Latest checkpoint's PrevTimeLineID: 1 +Latest checkpoint's full_page_writes: on +Latest checkpoint's NextXID: 0:877 +Latest checkpoint's NextGxid: 9 +Latest checkpoint's NextOID: 16392 +Latest checkpoint's NextRelfilenode: 12002 +Latest checkpoint's NextMultiXactId: 1 +Latest checkpoint's NextMultiOffset: 0 +Latest checkpoint's oldestXID: 810 +Latest checkpoint's oldestXID's DB: 13425 +Latest checkpoint's oldestActiveXID: 876 +Latest checkpoint's oldestMultiXid: 1 +Latest checkpoint's oldestMulti's DB: 1 +Latest checkpoint's oldestCommitTsXid:0 +Latest checkpoint's newestCommitTsXid:0 +Time of latest checkpoint: Wed 25 Feb 2026 10:13:25 AM GMT +Fake LSN counter for unlogged rels: 0/3E8 +Minimum recovery ending location: 0/0 +Min recovery ending loc's timeline: 0 +Backup start location: 0/0 +Backup end location: 0/0 +End-of-backup record required: no +wal_level setting: replica +wal_log_hints setting: off +max_connections setting: 750 +max_worker_processes setting: 14 +max_wal_senders setting: 10 +max_prepared_xacts setting: 250 +max_locks_per_xact setting: 128 +track_commit_timestamp setting: off +Maximum data alignment: 8 +Database block size: 32768 +Blocks per segment of large relation: 32768 +WAL block size: 32768 +Bytes per WAL segment: 67108864 +Maximum length of identifiers: 64 +Maximum columns in an index: 32 +Maximum size of a TOAST chunk: 8140 +Size of a large-object chunk: 8192 +Date/time type storage: 64-bit integers +Float8 argument passing: by value +Data page checksum version: 1 +Mock authentication nonce: deb1a8b64d8bc3ddf938a6ec69c7c9785d8f32343c42e3878fe207fbee3ac992 +File encryption method: + +stderr: +20260225:10:13:29:029792 gpexpand:cdw:gpadmin-[INFO]:-Successfully finished pg_controldata /home/gpadmin/cloudberry/gpAux/gpdemo/datadirs/dbfast_mirror3/demoDataDir2 for dbid 7: +stdout: pg_control version number: 13000700 +Catalog version number: 302509031 +Database system identifier: 7610743540636610571 +Database cluster state: in archive recovery +pg_control last modified: Wed 25 Feb 2026 10:12:19 AM GMT +Latest checkpoint location: 0/C005578 +Latest checkpoint's REDO location: 0/C005578 +Latest checkpoint's REDO WAL file: 000000010000000000000003 +Latest checkpoint's TimeLineID: 1 +Latest checkpoint's PrevTimeLineID: 1 +Latest checkpoint's full_page_writes: on +Latest checkpoint's NextXID: 0:872 +Latest checkpoint's NextGxid: 3 +Latest checkpoint's NextOID: 16392 +Latest checkpoint's NextRelfilenode: 12002 +Latest checkpoint's NextMultiXactId: 1 +Latest checkpoint's NextMultiOffset: 0 +Latest checkpoint's oldestXID: 810 +Latest checkpoint's oldestXID's DB: 13425 +Latest checkpoint's oldestActiveXID: 0 +Latest checkpoint's oldestMultiXid: 1 +Latest checkpoint's oldestMulti's DB: 1 +Latest checkpoint's oldestCommitTsXid:0 +Latest checkpoint's newestCommitTsXid:0 +Time of latest checkpoint: Wed 25 Feb 2026 10:12:16 AM GMT +Fake LSN counter for unlogged rels: 0/3E8 +Minimum recovery ending location: 0/C005600 +Min recovery ending loc's timeline: 1 +Backup start location: 0/0 +Backup end location: 0/0 +End-of-backup record required: no +wal_level setting: replica +wal_log_hints setting: off +max_connections setting: 750 +max_worker_processes setting: 14 +max_wal_senders setting: 10 +max_prepared_xacts setting: 250 +max_locks_per_xact setting: 128 +track_commit_timestamp setting: off +Maximum data alignment: 8 +Database block size: 32768 +Blocks per segment of large relation: 32768 +WAL block size: 32768 +Bytes per WAL segment: 67108864 +Maximum length of identifiers: 64 +Maximum columns in an index: 32 +Maximum size of a TOAST chunk: 8140 +Size of a large-object chunk: 8192 +Date/time type storage: 64-bit integers +Float8 argument passing: by value +Data page checksum version: 1 +Mock authentication nonce: deb1a8b64d8bc3ddf938a6ec69c7c9785d8f32343c42e3878fe207fbee3ac992 +File encryption method: + +stderr: +20260225:10:13:29:029792 gpexpand:cdw:gpadmin-[INFO]:-Heap checksum setting consistent across cluster +20260225:10:13:29:029792 gpexpand:cdw:gpadmin-[INFO]:-Syncing Apache Cloudberry extensions +20260225:10:13:29:029792 gpexpand:cdw:gpadmin-[ERROR]:-Syncing of Apache Cloudberry extensions has failed. +Traceback (most recent call last): + File "/usr/local/cloudberry-db/bin/gpexpand", line 1935, in sync_packages + operation.get_ret() + File "/usr/local/cloudberry-db/lib/python/gppylib/operations/__init__.py", line 64, in get_ret + if isinstance(self.ret, Exception): +AttributeError: 'SyncPackages' object has no attribute 'ret' +20260225:10:13:29:029792 gpexpand:cdw:gpadmin-[WARNING]:-Please run gppkg --clean after successful expansion. +20260225:10:13:30:029792 gpexpand:cdw:gpadmin-[INFO]:-Locking catalog +20260225:10:13:30:029792 gpexpand:cdw:gpadmin-[INFO]:-Locked catalog +20260225:10:13:30:029792 gpexpand:cdw:gpadmin-[INFO]:-Creating segment template +20260225:10:13:33:029792 gpexpand:cdw:gpadmin-[INFO]:-Copying postgresql.conf from existing segment into template +20260225:10:13:33:029792 gpexpand:cdw:gpadmin-[INFO]:-Copying pg_hba.conf from existing segment into template +20260225:10:13:34:029792 gpexpand:cdw:gpadmin-[INFO]:-Creating schema tar file +20260225:10:13:36:029792 gpexpand:cdw:gpadmin-[INFO]:-Distributing template tar file to new hosts +20260225:10:13:52:029792 gpexpand:cdw:gpadmin-[INFO]:-Configuring new segments (primary) +20260225:10:13:52:029792 gpexpand:cdw:gpadmin-[INFO]:-{'localhost': '/tmp/datadirs/dbfast4/demoDataDir3:7008:true:false:9:3::-1:'} +20260225:10:13:54:029792 gpexpand:cdw:gpadmin-[INFO]:-Starting to create new pg_hba.conf on primary segments +20260225:10:13:54:029792 gpexpand:cdw:gpadmin-[INFO]:-None of the reachable segments require update to pg_hba.conf +20260225:10:13:54:029792 gpexpand:cdw:gpadmin-[INFO]:-SegmentStart pg_ctl cmd is env GPSESSID=0000000000 GPERA=None $GPHOME/bin/pg_ctl -D /tmp/datadirs/dbfast4/demoDataDir3 -l /tmp/datadirs/dbfast4/demoDataDir3/log/startup.log -w -t 600 -o " -p 7008 -c gp_role=utility -M " start +20260225:10:13:55:029792 gpexpand:cdw:gpadmin-[INFO]:-Cleaning up temporary template files +20260225:10:13:56:029792 gpexpand:cdw:gpadmin-[INFO]:-Cleaning up databases in new segments. +20260225:10:13:56:029792 gpexpand:cdw:gpadmin-[INFO]:-SegmentStart pg_ctl cmd is env GPSESSID=0000000000 GPERA=None $GPHOME/bin/pg_ctl -D /tmp/datadirs/dbfast4/demoDataDir3 -l /tmp/datadirs/dbfast4/demoDataDir3/log/startup.log -w -t 600 -o " -p 7008 -c gp_role=utility " start +20260225:10:13:56:029792 gpexpand:cdw:gpadmin-[INFO]:-Unlocking catalog +20260225:10:13:56:029792 gpexpand:cdw:gpadmin-[INFO]:-Unlocked catalog +20260225:10:13:57:029792 gpexpand:cdw:gpadmin-[INFO]:-Creating expansion schema +20260225:10:13:57:029792 gpexpand:cdw:gpadmin-[INFO]:-Populating gpexpand.status_detail with data from database postgres +20260225:10:13:57:029792 gpexpand:cdw:gpadmin-[INFO]:-Populating gpexpand.status_detail with data from database template1 +20260225:10:13:57:029792 gpexpand:cdw:gpadmin-[INFO]:-Populating gpexpand.status_detail with data from database isolation2parallelretrcursor +20260225:10:13:57:029792 gpexpand:cdw:gpadmin-[INFO]:-Populating gpexpand.status_detail with data from database isolation2test +20260225:10:13:58:029792 gpexpand:cdw:gpadmin-[INFO]:-Starting new mirror segment synchronization +20260225:10:14:08:029792 gpexpand:cdw:gpadmin-[INFO]:-************************************************ +20260225:10:14:08:029792 gpexpand:cdw:gpadmin-[INFO]:-Initialization of the system expansion complete. +20260225:10:14:08:029792 gpexpand:cdw:gpadmin-[INFO]:-To begin table expansion onto the new segments +20260225:10:14:08:029792 gpexpand:cdw:gpadmin-[INFO]:-rerun gpexpand +20260225:10:14:08:029792 gpexpand:cdw:gpadmin-[INFO]:-************************************************ +20260225:10:14:08:029792 gpexpand:cdw:gpadmin-[INFO]:-Exiting... + +-- end_ignore +(exited with code 0) +!\retcode gpexpand -i /tmp/testexpand; +-- start_ignore +20260225:10:14:08:030678 gpexpand:cdw:gpadmin-[INFO]:-local Cloudberry Version: 'postgres (Apache Cloudberry) 3.0.0-devel+dev.4.g01c21009c35 build dev' +20260225:10:14:08:030678 gpexpand:cdw:gpadmin-[INFO]:-coordinator Cloudberry Version: 'PostgreSQL 14.4 (Apache Cloudberry 3.0.0-devel+dev.4.g01c21009c35 build dev) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 11.4.0-1ubuntu1~22.04.2) 11.4.0, 64-bit compiled on Feb 25 2026 10:08:48 (with assert checking)' +20260225:10:14:08:030678 gpexpand:cdw:gpadmin-[INFO]:-Querying gpexpand schema for current expansion state +20260225:10:14:09:030678 gpexpand:cdw:gpadmin-[INFO]:-EXPANSION COMPLETED SUCCESSFULLY +20260225:10:14:09:030678 gpexpand:cdw:gpadmin-[INFO]:-Exiting... + +-- end_ignore +(exited with code 0) + +-- Get the new segment's datadir (content=3) +!\retcode psql -d postgres -Aqt -c "SELECT datadir FROM gp_segment_configuration WHERE content = 3 AND role = 'p'" > /tmp/new_segment_datadir; +-- start_ignore + +-- end_ignore +(exited with code 0) + +-- Confirm that the --content-id flag within archive_command has been +-- updated to match the new segment's content. The restore_command +-- lacks --content-id flag and should be unchanged. +! grep "^archive_command" $(cat /tmp/new_segment_datadir)/postgresql.conf; +archive_command='wal-g seg wal-push %p --content-id=3' + +! grep "^restore_command" $(cat /tmp/new_segment_datadir)/postgresql.conf; +restore_command='/bin/true' + + +-- Cleanup +!\retcode gpconfig -r restore_command; +-- start_ignore +20260225:10:14:09:030725 gpconfig:cdw:gpadmin-[INFO]:-completed successfully with parameters '-r restore_command' + +-- end_ignore +(exited with code 0) +!\retcode gpconfig -r archive_command; +-- start_ignore +20260225:10:14:10:030829 gpconfig:cdw:gpadmin-[INFO]:-completed successfully with parameters '-r archive_command' + +-- end_ignore +(exited with code 0) +!\retcode gpstop -u; +-- start_ignore +20260225:10:14:10:030933 gpstop:cdw:gpadmin-[INFO]:-Starting gpstop with args: -u +20260225:10:14:10:030933 gpstop:cdw:gpadmin-[INFO]:-Gathering information and validating the environment... +20260225:10:14:10:030933 gpstop:cdw:gpadmin-[INFO]:-Obtaining Cloudberry Coordinator catalog information +20260225:10:14:10:030933 gpstop:cdw:gpadmin-[INFO]:-Obtaining Segment details from coordinator... +20260225:10:14:10:030933 gpstop:cdw:gpadmin-[INFO]:-Cloudberry Version: 'postgres (Apache Cloudberry) 3.0.0-devel+dev.4.g01c21009c35 build dev' +20260225:10:14:10:030933 gpstop:cdw:gpadmin-[INFO]:-Signalling all postmaster processes to reload + +-- end_ignore +(exited with code 0) + +!\retcode gpshrink -i /tmp/testexpand; +-- start_ignore +20260225:10:14:10:030997 gpshrink:cdw:gpadmin-[INFO]:-local Cloudberry Version: 'postgres (Apache Cloudberry) 3.0.0-devel+dev.4.g01c21009c35 build dev' +20260225:10:14:10:030997 gpshrink:cdw:gpadmin-[INFO]:-coordinator Cloudberry Version: 'PostgreSQL 14.4 (Apache Cloudberry 3.0.0-devel+dev.4.g01c21009c35 build dev) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 11.4.0-1ubuntu1~22.04.2) 11.4.0, 64-bit compiled on Feb 25 2026 10:08:48 (with assert checking)' +20260225:10:14:10:030997 gpshrink:cdw:gpadmin-[INFO]:-Successfully finished pg_controldata /home/gpadmin/cloudberry/gpAux/gpdemo/datadirs/dbfast1/demoDataDir0 for dbid 2: +stdout: pg_control version number: 13000700 +Catalog version number: 302509031 +Database system identifier: 7610743540553465864 +Database cluster state: in production +pg_control last modified: Wed 25 Feb 2026 10:13:25 AM GMT +Latest checkpoint location: 0/C067FA8 +Latest checkpoint's REDO location: 0/C067F70 +Latest checkpoint's REDO WAL file: 000000010000000000000003 +Latest checkpoint's TimeLineID: 1 +Latest checkpoint's PrevTimeLineID: 1 +Latest checkpoint's full_page_writes: on +Latest checkpoint's NextXID: 0:877 +Latest checkpoint's NextGxid: 9 +Latest checkpoint's NextOID: 16392 +Latest checkpoint's NextRelfilenode: 12002 +Latest checkpoint's NextMultiXactId: 1 +Latest checkpoint's NextMultiOffset: 0 +Latest checkpoint's oldestXID: 810 +Latest checkpoint's oldestXID's DB: 13425 +Latest checkpoint's oldestActiveXID: 876 +Latest checkpoint's oldestMultiXid: 1 +Latest checkpoint's oldestMulti's DB: 1 +Latest checkpoint's oldestCommitTsXid:0 +Latest checkpoint's newestCommitTsXid:0 +Time of latest checkpoint: Wed 25 Feb 2026 10:13:25 AM GMT +Fake LSN counter for unlogged rels: 0/3E8 +Minimum recovery ending location: 0/0 +Min recovery ending loc's timeline: 0 +Backup start location: 0/0 +Backup end location: 0/0 +End-of-backup record required: no +wal_level setting: replica +wal_log_hints setting: off +max_connections setting: 750 +max_worker_processes setting: 14 +max_wal_senders setting: 10 +max_prepared_xacts setting: 250 +max_locks_per_xact setting: 128 +track_commit_timestamp setting: off +Maximum data alignment: 8 +Database block size: 32768 +Blocks per segment of large relation: 32768 +WAL block size: 32768 +Bytes per WAL segment: 67108864 +Maximum length of identifiers: 64 +Maximum columns in an index: 32 +Maximum size of a TOAST chunk: 8140 +Size of a large-object chunk: 8192 +Date/time type storage: 64-bit integers +Float8 argument passing: by value +Data page checksum version: 1 +Mock authentication nonce: 4ab1899cbfd68b59268d02e0d5a1966c0ee3f4b463979bc5372053c2b14ece58 +File encryption method: + +stderr: +20260225:10:14:10:030997 gpshrink:cdw:gpadmin-[INFO]:-Successfully finished pg_controldata /home/gpadmin/cloudberry/gpAux/gpdemo/datadirs/dbfast_mirror1/demoDataDir0 for dbid 5: +stdout: pg_control version number: 13000700 +Catalog version number: 302509031 +Database system identifier: 7610743540553465864 +Database cluster state: in archive recovery +pg_control last modified: Wed 25 Feb 2026 10:12:19 AM GMT +Latest checkpoint location: 0/C005578 +Latest checkpoint's REDO location: 0/C005578 +Latest checkpoint's REDO WAL file: 000000010000000000000003 +Latest checkpoint's TimeLineID: 1 +Latest checkpoint's PrevTimeLineID: 1 +Latest checkpoint's full_page_writes: on +Latest checkpoint's NextXID: 0:872 +Latest checkpoint's NextGxid: 3 +Latest checkpoint's NextOID: 16392 +Latest checkpoint's NextRelfilenode: 12002 +Latest checkpoint's NextMultiXactId: 1 +Latest checkpoint's NextMultiOffset: 0 +Latest checkpoint's oldestXID: 810 +Latest checkpoint's oldestXID's DB: 13425 +Latest checkpoint's oldestActiveXID: 0 +Latest checkpoint's oldestMultiXid: 1 +Latest checkpoint's oldestMulti's DB: 1 +Latest checkpoint's oldestCommitTsXid:0 +Latest checkpoint's newestCommitTsXid:0 +Time of latest checkpoint: Wed 25 Feb 2026 10:12:16 AM GMT +Fake LSN counter for unlogged rels: 0/3E8 +Minimum recovery ending location: 0/C005600 +Min recovery ending loc's timeline: 1 +Backup start location: 0/0 +Backup end location: 0/0 +End-of-backup record required: no +wal_level setting: replica +wal_log_hints setting: off +max_connections setting: 750 +max_worker_processes setting: 14 +max_wal_senders setting: 10 +max_prepared_xacts setting: 250 +max_locks_per_xact setting: 128 +track_commit_timestamp setting: off +Maximum data alignment: 8 +Database block size: 32768 +Blocks per segment of large relation: 32768 +WAL block size: 32768 +Bytes per WAL segment: 67108864 +Maximum length of identifiers: 64 +Maximum columns in an index: 32 +Maximum size of a TOAST chunk: 8140 +Size of a large-object chunk: 8192 +Date/time type storage: 64-bit integers +Float8 argument passing: by value +Data page checksum version: 1 +Mock authentication nonce: 4ab1899cbfd68b59268d02e0d5a1966c0ee3f4b463979bc5372053c2b14ece58 +File encryption method: + +stderr: +20260225:10:14:10:030997 gpshrink:cdw:gpadmin-[INFO]:-Successfully finished pg_controldata /home/gpadmin/cloudberry/gpAux/gpdemo/datadirs/dbfast2/demoDataDir1 for dbid 3: +stdout: pg_control version number: 13000700 +Catalog version number: 302509031 +Database system identifier: 7610743540653109260 +Database cluster state: in production +pg_control last modified: Wed 25 Feb 2026 10:13:25 AM GMT +Latest checkpoint location: 0/C067FA8 +Latest checkpoint's REDO location: 0/C067F70 +Latest checkpoint's REDO WAL file: 000000010000000000000003 +Latest checkpoint's TimeLineID: 1 +Latest checkpoint's PrevTimeLineID: 1 +Latest checkpoint's full_page_writes: on +Latest checkpoint's NextXID: 0:877 +Latest checkpoint's NextGxid: 9 +Latest checkpoint's NextOID: 16392 +Latest checkpoint's NextRelfilenode: 12002 +Latest checkpoint's NextMultiXactId: 1 +Latest checkpoint's NextMultiOffset: 0 +Latest checkpoint's oldestXID: 810 +Latest checkpoint's oldestXID's DB: 13425 +Latest checkpoint's oldestActiveXID: 876 +Latest checkpoint's oldestMultiXid: 1 +Latest checkpoint's oldestMulti's DB: 1 +Latest checkpoint's oldestCommitTsXid:0 +Latest checkpoint's newestCommitTsXid:0 +Time of latest checkpoint: Wed 25 Feb 2026 10:13:25 AM GMT +Fake LSN counter for unlogged rels: 0/3E8 +Minimum recovery ending location: 0/0 +Min recovery ending loc's timeline: 0 +Backup start location: 0/0 +Backup end location: 0/0 +End-of-backup record required: no +wal_level setting: replica +wal_log_hints setting: off +max_connections setting: 750 +max_worker_processes setting: 14 +max_wal_senders setting: 10 +max_prepared_xacts setting: 250 +max_locks_per_xact setting: 128 +track_commit_timestamp setting: off +Maximum data alignment: 8 +Database block size: 32768 +Blocks per segment of large relation: 32768 +WAL block size: 32768 +Bytes per WAL segment: 67108864 +Maximum length of identifiers: 64 +Maximum columns in an index: 32 +Maximum size of a TOAST chunk: 8140 +Size of a large-object chunk: 8192 +Date/time type storage: 64-bit integers +Float8 argument passing: by value +Data page checksum version: 1 +Mock authentication nonce: 91cf6a7a7826dd0c9f8ff23a43d226c7a1a72752a9b1544a78c7cfbe62970991 +File encryption method: + +stderr: +20260225:10:14:10:030997 gpshrink:cdw:gpadmin-[INFO]:-Successfully finished pg_controldata /home/gpadmin/cloudberry/gpAux/gpdemo/datadirs/dbfast_mirror2/demoDataDir1 for dbid 6: +stdout: pg_control version number: 13000700 +Catalog version number: 302509031 +Database system identifier: 7610743540653109260 +Database cluster state: in archive recovery +pg_control last modified: Wed 25 Feb 2026 10:12:19 AM GMT +Latest checkpoint location: 0/C005578 +Latest checkpoint's REDO location: 0/C005578 +Latest checkpoint's REDO WAL file: 000000010000000000000003 +Latest checkpoint's TimeLineID: 1 +Latest checkpoint's PrevTimeLineID: 1 +Latest checkpoint's full_page_writes: on +Latest checkpoint's NextXID: 0:872 +Latest checkpoint's NextGxid: 3 +Latest checkpoint's NextOID: 16392 +Latest checkpoint's NextRelfilenode: 12002 +Latest checkpoint's NextMultiXactId: 1 +Latest checkpoint's NextMultiOffset: 0 +Latest checkpoint's oldestXID: 810 +Latest checkpoint's oldestXID's DB: 13425 +Latest checkpoint's oldestActiveXID: 0 +Latest checkpoint's oldestMultiXid: 1 +Latest checkpoint's oldestMulti's DB: 1 +Latest checkpoint's oldestCommitTsXid:0 +Latest checkpoint's newestCommitTsXid:0 +Time of latest checkpoint: Wed 25 Feb 2026 10:12:16 AM GMT +Fake LSN counter for unlogged rels: 0/3E8 +Minimum recovery ending location: 0/C005600 +Min recovery ending loc's timeline: 1 +Backup start location: 0/0 +Backup end location: 0/0 +End-of-backup record required: no +wal_level setting: replica +wal_log_hints setting: off +max_connections setting: 750 +max_worker_processes setting: 14 +max_wal_senders setting: 10 +max_prepared_xacts setting: 250 +max_locks_per_xact setting: 128 +track_commit_timestamp setting: off +Maximum data alignment: 8 +Database block size: 32768 +Blocks per segment of large relation: 32768 +WAL block size: 32768 +Bytes per WAL segment: 67108864 +Maximum length of identifiers: 64 +Maximum columns in an index: 32 +Maximum size of a TOAST chunk: 8140 +Size of a large-object chunk: 8192 +Date/time type storage: 64-bit integers +Float8 argument passing: by value +Data page checksum version: 1 +Mock authentication nonce: 91cf6a7a7826dd0c9f8ff23a43d226c7a1a72752a9b1544a78c7cfbe62970991 +File encryption method: + +stderr: +20260225:10:14:10:030997 gpshrink:cdw:gpadmin-[INFO]:-Successfully finished pg_controldata /home/gpadmin/cloudberry/gpAux/gpdemo/datadirs/dbfast3/demoDataDir2 for dbid 4: +stdout: pg_control version number: 13000700 +Catalog version number: 302509031 +Database system identifier: 7610743540636610571 +Database cluster state: in production +pg_control last modified: Wed 25 Feb 2026 10:13:25 AM GMT +Latest checkpoint location: 0/C067FA8 +Latest checkpoint's REDO location: 0/C067F70 +Latest checkpoint's REDO WAL file: 000000010000000000000003 +Latest checkpoint's TimeLineID: 1 +Latest checkpoint's PrevTimeLineID: 1 +Latest checkpoint's full_page_writes: on +Latest checkpoint's NextXID: 0:877 +Latest checkpoint's NextGxid: 9 +Latest checkpoint's NextOID: 16392 +Latest checkpoint's NextRelfilenode: 12002 +Latest checkpoint's NextMultiXactId: 1 +Latest checkpoint's NextMultiOffset: 0 +Latest checkpoint's oldestXID: 810 +Latest checkpoint's oldestXID's DB: 13425 +Latest checkpoint's oldestActiveXID: 876 +Latest checkpoint's oldestMultiXid: 1 +Latest checkpoint's oldestMulti's DB: 1 +Latest checkpoint's oldestCommitTsXid:0 +Latest checkpoint's newestCommitTsXid:0 +Time of latest checkpoint: Wed 25 Feb 2026 10:13:25 AM GMT +Fake LSN counter for unlogged rels: 0/3E8 +Minimum recovery ending location: 0/0 +Min recovery ending loc's timeline: 0 +Backup start location: 0/0 +Backup end location: 0/0 +End-of-backup record required: no +wal_level setting: replica +wal_log_hints setting: off +max_connections setting: 750 +max_worker_processes setting: 14 +max_wal_senders setting: 10 +max_prepared_xacts setting: 250 +max_locks_per_xact setting: 128 +track_commit_timestamp setting: off +Maximum data alignment: 8 +Database block size: 32768 +Blocks per segment of large relation: 32768 +WAL block size: 32768 +Bytes per WAL segment: 67108864 +Maximum length of identifiers: 64 +Maximum columns in an index: 32 +Maximum size of a TOAST chunk: 8140 +Size of a large-object chunk: 8192 +Date/time type storage: 64-bit integers +Float8 argument passing: by value +Data page checksum version: 1 +Mock authentication nonce: deb1a8b64d8bc3ddf938a6ec69c7c9785d8f32343c42e3878fe207fbee3ac992 +File encryption method: + +stderr: +20260225:10:14:10:030997 gpshrink:cdw:gpadmin-[INFO]:-Successfully finished pg_controldata /home/gpadmin/cloudberry/gpAux/gpdemo/datadirs/dbfast_mirror3/demoDataDir2 for dbid 7: +stdout: pg_control version number: 13000700 +Catalog version number: 302509031 +Database system identifier: 7610743540636610571 +Database cluster state: in archive recovery +pg_control last modified: Wed 25 Feb 2026 10:12:19 AM GMT +Latest checkpoint location: 0/C005578 +Latest checkpoint's REDO location: 0/C005578 +Latest checkpoint's REDO WAL file: 000000010000000000000003 +Latest checkpoint's TimeLineID: 1 +Latest checkpoint's PrevTimeLineID: 1 +Latest checkpoint's full_page_writes: on +Latest checkpoint's NextXID: 0:872 +Latest checkpoint's NextGxid: 3 +Latest checkpoint's NextOID: 16392 +Latest checkpoint's NextRelfilenode: 12002 +Latest checkpoint's NextMultiXactId: 1 +Latest checkpoint's NextMultiOffset: 0 +Latest checkpoint's oldestXID: 810 +Latest checkpoint's oldestXID's DB: 13425 +Latest checkpoint's oldestActiveXID: 0 +Latest checkpoint's oldestMultiXid: 1 +Latest checkpoint's oldestMulti's DB: 1 +Latest checkpoint's oldestCommitTsXid:0 +Latest checkpoint's newestCommitTsXid:0 +Time of latest checkpoint: Wed 25 Feb 2026 10:12:16 AM GMT +Fake LSN counter for unlogged rels: 0/3E8 +Minimum recovery ending location: 0/C005600 +Min recovery ending loc's timeline: 1 +Backup start location: 0/0 +Backup end location: 0/0 +End-of-backup record required: no +wal_level setting: replica +wal_log_hints setting: off +max_connections setting: 750 +max_worker_processes setting: 14 +max_wal_senders setting: 10 +max_prepared_xacts setting: 250 +max_locks_per_xact setting: 128 +track_commit_timestamp setting: off +Maximum data alignment: 8 +Database block size: 32768 +Blocks per segment of large relation: 32768 +WAL block size: 32768 +Bytes per WAL segment: 67108864 +Maximum length of identifiers: 64 +Maximum columns in an index: 32 +Maximum size of a TOAST chunk: 8140 +Size of a large-object chunk: 8192 +Date/time type storage: 64-bit integers +Float8 argument passing: by value +Data page checksum version: 1 +Mock authentication nonce: deb1a8b64d8bc3ddf938a6ec69c7c9785d8f32343c42e3878fe207fbee3ac992 +File encryption method: + +stderr: +20260225:10:14:10:030997 gpshrink:cdw:gpadmin-[INFO]:-Successfully finished pg_controldata /tmp/datadirs/dbfast_mirror4/demoDataDir3 for dbid 10: +stdout: pg_control version number: 13000700 +Catalog version number: 302509031 +Database system identifier: 7610743519254633466 +Database cluster state: in archive recovery +pg_control last modified: Wed 25 Feb 2026 10:14:07 AM GMT +Latest checkpoint location: 0/1C000060 +Latest checkpoint's REDO location: 0/1C000028 +Latest checkpoint's REDO WAL file: 000000010000000000000007 +Latest checkpoint's TimeLineID: 1 +Latest checkpoint's PrevTimeLineID: 1 +Latest checkpoint's full_page_writes: on +Latest checkpoint's NextXID: 0:966 +Latest checkpoint's NextGxid: 8196 +Latest checkpoint's NextOID: 33402 +Latest checkpoint's NextRelfilenode: 24576 +Latest checkpoint's NextMultiXactId: 1 +Latest checkpoint's NextMultiOffset: 0 +Latest checkpoint's oldestXID: 810 +Latest checkpoint's oldestXID's DB: 13425 +Latest checkpoint's oldestActiveXID: 966 +Latest checkpoint's oldestMultiXid: 1 +Latest checkpoint's oldestMulti's DB: 1 +Latest checkpoint's oldestCommitTsXid:0 +Latest checkpoint's newestCommitTsXid:0 +Time of latest checkpoint: Wed 25 Feb 2026 10:14:02 AM GMT +Fake LSN counter for unlogged rels: 0/3E8 +Minimum recovery ending location: 0/1C000110 +Min recovery ending loc's timeline: 1 +Backup start location: 0/0 +Backup end location: 0/0 +End-of-backup record required: no +wal_level setting: replica +wal_log_hints setting: off +max_connections setting: 750 +max_worker_processes setting: 14 +max_wal_senders setting: 10 +max_prepared_xacts setting: 250 +max_locks_per_xact setting: 128 +track_commit_timestamp setting: off +Maximum data alignment: 8 +Database block size: 32768 +Blocks per segment of large relation: 32768 +WAL block size: 32768 +Bytes per WAL segment: 67108864 +Maximum length of identifiers: 64 +Maximum columns in an index: 32 +Maximum size of a TOAST chunk: 8140 +Size of a large-object chunk: 8192 +Date/time type storage: 64-bit integers +Float8 argument passing: by value +Data page checksum version: 1 +Mock authentication nonce: ec79bca6b7c99a5ea2ac78e41778e68c225231739152db9d7d59cc19b9096a29 +File encryption method: + +stderr: +20260225:10:14:10:030997 gpshrink:cdw:gpadmin-[INFO]:-Successfully finished pg_controldata /tmp/datadirs/dbfast4/demoDataDir3 for dbid 9: +stdout: pg_control version number: 13000700 +Catalog version number: 302509031 +Database system identifier: 7610743519254633466 +Database cluster state: in production +pg_control last modified: Wed 25 Feb 2026 10:14:02 AM GMT +Latest checkpoint location: 0/1C000060 +Latest checkpoint's REDO location: 0/1C000028 +Latest checkpoint's REDO WAL file: 000000010000000000000007 +Latest checkpoint's TimeLineID: 1 +Latest checkpoint's PrevTimeLineID: 1 +Latest checkpoint's full_page_writes: on +Latest checkpoint's NextXID: 0:966 +Latest checkpoint's NextGxid: 8196 +Latest checkpoint's NextOID: 33402 +Latest checkpoint's NextRelfilenode: 24576 +Latest checkpoint's NextMultiXactId: 1 +Latest checkpoint's NextMultiOffset: 0 +Latest checkpoint's oldestXID: 810 +Latest checkpoint's oldestXID's DB: 13425 +Latest checkpoint's oldestActiveXID: 966 +Latest checkpoint's oldestMultiXid: 1 +Latest checkpoint's oldestMulti's DB: 1 +Latest checkpoint's oldestCommitTsXid:0 +Latest checkpoint's newestCommitTsXid:0 +Time of latest checkpoint: Wed 25 Feb 2026 10:14:02 AM GMT +Fake LSN counter for unlogged rels: 0/3E8 +Minimum recovery ending location: 0/0 +Min recovery ending loc's timeline: 0 +Backup start location: 0/0 +Backup end location: 0/0 +End-of-backup record required: no +wal_level setting: replica +wal_log_hints setting: off +max_connections setting: 750 +max_worker_processes setting: 14 +max_wal_senders setting: 10 +max_prepared_xacts setting: 250 +max_locks_per_xact setting: 128 +track_commit_timestamp setting: off +Maximum data alignment: 8 +Database block size: 32768 +Blocks per segment of large relation: 32768 +WAL block size: 32768 +Bytes per WAL segment: 67108864 +Maximum length of identifiers: 64 +Maximum columns in an index: 32 +Maximum size of a TOAST chunk: 8140 +Size of a large-object chunk: 8192 +Date/time type storage: 64-bit integers +Float8 argument passing: by value +Data page checksum version: 1 +Mock authentication nonce: ec79bca6b7c99a5ea2ac78e41778e68c225231739152db9d7d59cc19b9096a29 +File encryption method: + +stderr: +20260225:10:14:10:030997 gpshrink:cdw:gpadmin-[INFO]:-Heap checksum setting consistent across cluster +20260225:10:14:11:030997 gpshrink:cdw:gpadmin-[INFO]:-Locking catalog +20260225:10:14:11:030997 gpshrink:cdw:gpadmin-[INFO]:-Locked catalog +20260225:10:14:11:030997 gpshrink:cdw:gpadmin-[INFO]:-Unlocking catalog +20260225:10:14:11:030997 gpshrink:cdw:gpadmin-[INFO]:-Unlocked catalog +20260225:10:14:11:030997 gpshrink:cdw:gpadmin-[INFO]:-Creating shrink schema +20260225:10:14:12:030997 gpshrink:cdw:gpadmin-[INFO]:-Populating gpshrink.status_detail with data from database postgres +20260225:10:14:12:030997 gpshrink:cdw:gpadmin-[INFO]:-Populating gpshrink.status_detail with data from database template1 +20260225:10:14:12:030997 gpshrink:cdw:gpadmin-[INFO]:-Populating gpshrink.status_detail with data from database isolation2parallelretrcursor +20260225:10:14:12:030997 gpshrink:cdw:gpadmin-[INFO]:-Populating gpshrink.status_detail with data from database isolation2test +20260225:10:14:12:030997 gpshrink:cdw:gpadmin-[INFO]:-************************************************ +20260225:10:14:12:030997 gpshrink:cdw:gpadmin-[INFO]:-Initialization of the system shrink complete. +20260225:10:14:12:030997 gpshrink:cdw:gpadmin-[INFO]:-To begin table shrink onto the new segments +20260225:10:14:12:030997 gpshrink:cdw:gpadmin-[INFO]:-rerun gpshrink +20260225:10:14:12:030997 gpshrink:cdw:gpadmin-[INFO]:-************************************************ +20260225:10:14:12:030997 gpshrink:cdw:gpadmin-[INFO]:-Exiting... + +-- end_ignore +(exited with code 0) +!\retcode gpshrink -i /tmp/testexpand; +-- start_ignore +20260225:10:14:13:031255 gpshrink:cdw:gpadmin-[INFO]:-local Cloudberry Version: 'postgres (Apache Cloudberry) 3.0.0-devel+dev.4.g01c21009c35 build dev' +20260225:10:14:13:031255 gpshrink:cdw:gpadmin-[INFO]:-coordinator Cloudberry Version: 'PostgreSQL 14.4 (Apache Cloudberry 3.0.0-devel+dev.4.g01c21009c35 build dev) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 11.4.0-1ubuntu1~22.04.2) 11.4.0, 64-bit compiled on Feb 25 2026 10:08:48 (with assert checking)' +20260225:10:14:13:031255 gpshrink:cdw:gpadmin-[INFO]:-Shrinking postgres.gpexpand.status_detail +20260225:10:14:13:031255 gpshrink:cdw:gpadmin-[INFO]:-Finished shrinking postgres.gpexpand.status_detail +20260225:10:14:14:031255 gpshrink:cdw:gpadmin-[INFO]:-Shrinking postgres.gpshrink.status_detail +20260225:10:14:14:031255 gpshrink:cdw:gpadmin-[INFO]:-Finished shrinking postgres.gpshrink.status_detail +20260225:10:14:14:031255 gpshrink:cdw:gpadmin-[INFO]:-Shrinking postgres.gpexpand.status +20260225:10:14:14:031255 gpshrink:cdw:gpadmin-[INFO]:-Finished shrinking postgres.gpexpand.status +20260225:10:14:14:031255 gpshrink:cdw:gpadmin-[INFO]:-Shrinking postgres.gpshrink.status +20260225:10:14:14:031255 gpshrink:cdw:gpadmin-[INFO]:-Finished shrinking postgres.gpshrink.status +20260225:10:14:18:031255 gpshrink:cdw:gpadmin-[INFO]:-SHRINK COMPLETED SUCCESSFULLY +20260225:10:14:18:031255 gpshrink:cdw:gpadmin-[INFO]:-Locking catalog +20260225:10:14:18:031255 gpshrink:cdw:gpadmin-[INFO]:-Locked catalog +20260225:10:14:19:031255 gpshrink:cdw:gpadmin-[INFO]:-Unlocking catalog +20260225:10:14:19:031255 gpshrink:cdw:gpadmin-[INFO]:-Unlocked catalog +20260225:10:14:19:031255 gpshrink:cdw:gpadmin-[INFO]:-Exiting... + +-- end_ignore +(exited with code 0) + +!\retcode yes | gpexpand -c; +-- start_ignore +20260225:10:14:19:031525 gpexpand:cdw:gpadmin-[INFO]:-local Cloudberry Version: 'postgres (Apache Cloudberry) 3.0.0-devel+dev.4.g01c21009c35 build dev' +20260225:10:14:19:031525 gpexpand:cdw:gpadmin-[INFO]:-coordinator Cloudberry Version: 'PostgreSQL 14.4 (Apache Cloudberry 3.0.0-devel+dev.4.g01c21009c35 build dev) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 11.4.0-1ubuntu1~22.04.2) 11.4.0, 64-bit compiled on Feb 25 2026 10:08:48 (with assert checking)' +20260225:10:14:19:031525 gpexpand:cdw:gpadmin-[INFO]:-Querying gpexpand schema for current expansion state + + +Do you want to dump the gpexpand.status_detail table to file? Yy|Nn (default=Y): +> 20260225:10:14:19:031525 gpexpand:cdw:gpadmin-[INFO]:-Dumping gpexpand.status_detail to /home/gpadmin/cloudberry/gpAux/gpdemo/datadirs/qddir/demoDataDir-1/gpexpand.status_detail +20260225:10:14:19:031525 gpexpand:cdw:gpadmin-[INFO]:-Removing gpexpand schema +20260225:10:14:19:031525 gpexpand:cdw:gpadmin-[INFO]:-Cleanup Finished. exiting... + +-- end_ignore +(exited with code 0) +!\retcode gpshrink -c; +-- start_ignore +20260225:10:14:20:031554 gpshrink:cdw:gpadmin-[INFO]:-local Cloudberry Version: 'postgres (Apache Cloudberry) 3.0.0-devel+dev.4.g01c21009c35 build dev' +20260225:10:14:20:031554 gpshrink:cdw:gpadmin-[INFO]:-coordinator Cloudberry Version: 'PostgreSQL 14.4 (Apache Cloudberry 3.0.0-devel+dev.4.g01c21009c35 build dev) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 11.4.0-1ubuntu1~22.04.2) 11.4.0, 64-bit compiled on Feb 25 2026 10:08:48 (with assert checking)' +20260225:10:14:20:031554 gpshrink:cdw:gpadmin-[INFO]:-Removing gpshrink schema +20260225:10:14:20:031554 gpshrink:cdw:gpadmin-[INFO]:-Cleanup Finished. exiting... + +-- end_ignore +(exited with code 0) +!\retcode rm -r /tmp/datadirs/; +-- start_ignore + +-- end_ignore +(exited with code 0) +!\retcode rm /tmp/new_segment_datadir; +-- start_ignore + +-- end_ignore +(exited with code 0) + diff --git a/src/test/isolation2/isolation2_expandshrink_schedule b/src/test/isolation2/isolation2_expandshrink_schedule index 3fd75a5eff0..89787bc1818 100644 --- a/src/test/isolation2/isolation2_expandshrink_schedule +++ b/src/test/isolation2/isolation2_expandshrink_schedule @@ -1,3 +1,4 @@ # Tests for gpexpand and gpshrink # Keep for single schedule due to redistribute all the table in all database -test: gpexpand_gpshrink \ No newline at end of file +test: gpexpand_gpshrink +test: gpexpand_archive_restore_conf diff --git a/src/test/isolation2/sql/gpexpand_archive_restore_conf.sql b/src/test/isolation2/sql/gpexpand_archive_restore_conf.sql new file mode 100644 index 00000000000..39cdf458f22 --- /dev/null +++ b/src/test/isolation2/sql/gpexpand_archive_restore_conf.sql @@ -0,0 +1,48 @@ +-- Verify that gpexpand correctly updates segment-specific flags for wal-g in +-- archive_command and restore_command when initializing new segments. +-- +-- Previously, these GUCs were copied verbatim from the template segment +-- (content 0), causing new segments to invoke archiving with an incorrect +-- content-id (possible overwriting archive or restoring other's data). + +-- Cleanup any previous state +!\retcode yes | gpexpand -c; +!\retcode gpshrink -c; +!\retcode rm -r /tmp/datadirs/; + +-- Set GUCs on all segments, hardcode --content-id to 0 +!\retcode gpconfig -c restore_command -v '/bin/true'; +!\retcode gpconfig -c archive_command -v 'wal-g seg wal-push %p --content-id=0'; +!\retcode gpstop -u; + +-- Prepare expansion configuration +!\retcode echo "localhost|localhost|7008|/tmp/datadirs/dbfast4/demoDataDir3|9|3|p +localhost|localhost|7009|/tmp/datadirs/dbfast_mirror4/demoDataDir3|10|3|m" > /tmp/testexpand; + +-- Expand +!\retcode gpexpand -i /tmp/testexpand; +!\retcode gpexpand -i /tmp/testexpand; + +-- Get the new segment's datadir (content=3) +!\retcode psql -d postgres -Aqt -c "SELECT datadir FROM gp_segment_configuration +WHERE content = 3 AND role = 'p'" > /tmp/new_segment_datadir; + +-- Confirm that the --content-id flag within archive_command has been +-- updated to match the new segment's content. The restore_command +-- lacks --content-id flag and should be unchanged. +! grep "^archive_command" $(cat /tmp/new_segment_datadir)/postgresql.conf; +! grep "^restore_command" $(cat /tmp/new_segment_datadir)/postgresql.conf; + +-- Cleanup +!\retcode gpconfig -r restore_command; +!\retcode gpconfig -r archive_command; +!\retcode gpstop -u; + +!\retcode gpshrink -i /tmp/testexpand; +!\retcode gpshrink -i /tmp/testexpand; + +!\retcode yes | gpexpand -c; +!\retcode gpshrink -c; +!\retcode rm -r /tmp/datadirs/; +!\retcode rm /tmp/new_segment_datadir; + diff --git a/src/test/regress/expected/privileges.out b/src/test/regress/expected/privileges.out index ee9f8fa1530..de323f54114 100644 --- a/src/test/regress/expected/privileges.out +++ b/src/test/regress/expected/privileges.out @@ -2007,9 +2007,13 @@ END$$; ALTER FUNCTION terminate_nothrow OWNER TO pg_signal_backend; SELECT backend_type FROM pg_stat_activity WHERE CASE WHEN COALESCE(usesysid, 10) = 10 THEN terminate_nothrow(pid) END; - backend_type --------------- -(0 rows) + backend_type +------------------------------ + autovacuum launcher + dtx recovery process + logical replication launcher + login monitor +(4 rows) ROLLBACK; -- test default ACLs diff --git a/src/test/regress/output/misc.source b/src/test/regress/output/misc.source index a0c63418446..f2f7c0dee32 100644 --- a/src/test/regress/output/misc.source +++ b/src/test/regress/output/misc.source @@ -613,6 +613,6 @@ CONTEXT: SQL function "equipment" during startup SELECT mdb_locale_enabled(); mdb_locale_enabled -------------------- - t + f (1 row)