fix: preserve migrated storage guards during deployment
This commit is contained in:
@@ -4980,3 +4980,5 @@ npm run verify:phase8
|
|||||||
| TC-PORTAL-008 | Prometheus同时返回系统盘、数据盘、第三块磁盘,顺序打乱或有缺失点 | 全部挂载点各有容量卡片及独立趋势;按设备/挂载点匹配,不串盘,不以0填缺失点;采集失败清空指标 |
|
| TC-PORTAL-008 | Prometheus同时返回系统盘、数据盘、第三块磁盘,顺序打乱或有缺失点 | 全部挂载点各有容量卡片及独立趋势;按设备/挂载点匹配,不串盘,不以0填缺失点;采集失败清空指标 |
|
||||||
| TC-PORTAL-009 | 系统盘或任一数据盘分别超过容量阈值 | 使用原有效阈值逐盘告警,信息含挂载点与设备;基础和托管规则无同名重复;tmpfs/overlay等虚拟盘不参与 |
|
| TC-PORTAL-009 | 系统盘或任一数据盘分别超过容量阈值 | 使用原有效阈值逐盘告警,信息含挂载点与设备;基础和托管规则无同名重复;tmpfs/overlay等虚拟盘不参与 |
|
||||||
| TC-PORTAL-010 | 测试发布与安全边界 | 新独立恢复资产的custom dump、运行tar、配置tar、原标记和SHA全部验证后才能发布;查服务、health、Stream、窗口日志与资源哈希;不发/补发/重投短信,不修改客户/余额/通道配置 |
|
| TC-PORTAL-010 | 测试发布与安全边界 | 新独立恢复资产的custom dump、运行tar、配置tar、原标记和SHA全部验证后才能发布;查服务、health、Stream、窗口日志与资源哈希;不发/补发/重投短信,不修改客户/余额/通道配置 |
|
||||||
|
| TC-STORAGE-DEPLOY-001 | 数据盘迁移后安装/发布前置检查;在隔离挂载命名空间隐藏数据盘或绑定挂载 | 两个入口均在初始化/发布写入前拒绝继续;验证UUID、源/目标inode、读写属性及既有存储标记;宿主挂载及服务PID不变 |
|
||||||
|
| TC-STORAGE-DEPLOY-002 | 数据盘迁移后发布业务代码 | 新恢复资产在数据盘上,custom dump/tar/SHA验证通过;存储服务PID、绑定挂载、fstab、环境及systemd保护保持不变;代码回退不恢复旧系统盘业务数据;系统盘和数据盘均有真实监控指标 |
|
||||||
|
|||||||
@@ -4206,3 +4206,9 @@ git diff --check
|
|||||||
- 外部HTTP实际下载的主JS/CSS与服务器文件SHA-256一致:`index-BaM_U9uq.js`=`b14c2ee21f80d718e6f78289cc6e676f215c2e16bd24712202df731aeadb3d6f`,`index-D8PbKTXI.css`=`86b17c3845da62022861df97536db00df9d241ceac9677434d7028286e0ac0ca`;本次涉及的8个页面JS(通用字段、发送记录、系统监控、客户端签名/模板/批量任务/发送详情/上行短信)逐个下载与本地构建哈希一致。
|
- 外部HTTP实际下载的主JS/CSS与服务器文件SHA-256一致:`index-BaM_U9uq.js`=`b14c2ee21f80d718e6f78289cc6e676f215c2e16bd24712202df731aeadb3d6f`,`index-D8PbKTXI.css`=`86b17c3845da62022861df97536db00df9d241ceac9677434d7028286e0ac0ca`;本次涉及的8个页面JS(通用字段、发送记录、系统监控、客户端签名/模板/批量任务/发送详情/上行短信)逐个下载与本地构建哈希一致。
|
||||||
- 回归结果维持API 581项、前端45项通过,测试用例见 `TC-PORTAL-001..010`。浏览器插件在网络恢复后仍多次导航、截图及DOM读取超时,真实页面视觉效果、浏览器控制台及登录后交互验收尚未完成,留待用户在测试环境验收,不标记为已通过。
|
- 回归结果维持API 581项、前端45项通过,测试用例见 `TC-PORTAL-001..010`。浏览器插件在网络恢复后仍多次导航、截图及DOM读取超时,真实页面视觉效果、浏览器控制台及登录后交互验收尚未完成,留待用户在测试环境验收,不标记为已通过。
|
||||||
- 证据:服务器 `/tmp/cmpp-sixfix-deploy.log`、`/tmp/cmpp-sixfix-before.json`、`/tmp/cmpp-sixfix-after.json` 及恢复点清单。提交时仅纳入本轮代码/用例/进度追加,原有4份修改文档及3项未跟踪文件仍保留为未提交状态。
|
- 证据:服务器 `/tmp/cmpp-sixfix-deploy.log`、`/tmp/cmpp-sixfix-before.json`、`/tmp/cmpp-sixfix-after.json` 及恢复点清单。提交时仅纳入本轮代码/用例/进度追加,原有4份修改文档及3项未跟踪文件仍保留为未提交状态。
|
||||||
|
|
||||||
|
## 2026-08-31 迁移后预生产六项修复发布准备
|
||||||
|
|
||||||
|
- 用户明确授权推送最新代码并发布预生产,提醒数据迁移已完成。重新读取迁移记录及线上事实:预生产业务标记仍为 `1a5063a`,三项存储分别绑定到 `/data/postgresql`、`/data/redis`、`/data/minio`,数据盘UUID为 `ef4ee3bb-a19b-4aeb-b00c-aa2b995611c2`,备份入口解析到 `/data/cmpp-platform-backups`;12项服务active,三条Stream pending/lag为0。
|
||||||
|
- 三份尚未提交的迁移保护脚本与线上LF归一化SHA逐项一致,本轮仅接续提交 `production-bootstrap.sh`、`production-deploy.sh`、`check-data-storage.sh`,其余原有修改及未跟踪文档保持不动。补充部署契约及 `TC-STORAGE-DEPLOY-001/002`,隔离mount namespace中隐藏Redis绑定后两入口前置部分均拒绝继续,宿主挂载与存储PID不变。
|
||||||
|
- 本次发布只切换应用代码和相关监控规则,不重新迁移/恢复数据库,不重启PostgreSQL、Redis或MinIO,不改fstab、存储保护、环境及业务配置。首份新恢复资产因Redis配置路径错误在tar阶段中止,未部署;核实 `/etc/redis/redis.conf` 后重新建立完整资产,最终证据另记。
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
fail() { echo "CMPP data storage unavailable: $*" >&2; exit 1; }
|
||||||
|
expected_uuid=$(cat /etc/cmpp-platform/data-disk.uuid) || fail "expected UUID configuration is missing"
|
||||||
|
[[ "$expected_uuid" =~ ^[a-f0-9-]{36}$ ]] || fail "invalid expected UUID"
|
||||||
|
mountpoint -q /data || fail "/data is not mounted"
|
||||||
|
[[ "$(findmnt -rn -M /data -o UUID)" == "$expected_uuid" ]] || fail "/data UUID mismatch"
|
||||||
|
[[ "$(cat /data/.cmpp-data-disk.uuid)" == "$expected_uuid" ]] || fail "data marker mismatch"
|
||||||
|
case ",$(findmnt -rn -M /data -o OPTIONS)," in *,rw,*) ;; *) fail "/data is read-only";; esac
|
||||||
|
check_one() {
|
||||||
|
local role="$1" source target
|
||||||
|
case "$role" in
|
||||||
|
postgresql) source=/data/postgresql; target=/var/lib/pgsql ;;
|
||||||
|
redis) source=/data/redis; target=/var/lib/redis ;;
|
||||||
|
minio) source=/data/minio; target=/var/lib/minio ;;
|
||||||
|
*) fail "unknown service $role" ;;
|
||||||
|
esac
|
||||||
|
mountpoint -q "$target" || fail "$target is not a mount point"
|
||||||
|
[[ "$(findmnt -rn -M "$target" -o UUID)" == "$expected_uuid" ]] || fail "$target UUID mismatch"
|
||||||
|
[[ "$(stat -Lc '%d:%i' "$source")" == "$(stat -Lc '%d:%i' "$target")" ]] || fail "$target does not map to $source"
|
||||||
|
case ",$(findmnt -rn -M "$target" -o OPTIONS)," in *,rw,*) ;; *) fail "$target is read-only";; esac
|
||||||
|
case "$role" in
|
||||||
|
postgresql) [[ -s "$target/data/PG_VERSION" && -d "$target/data/base" ]] || fail "existing PostgreSQL cluster is missing" ;;
|
||||||
|
redis) [[ -s "$target/dump.rdb" ]] || fail "existing Redis RDB is missing" ;;
|
||||||
|
minio) [[ -s "$target/.minio.sys/format.json" ]] || fail "existing MinIO format is missing" ;;
|
||||||
|
esac
|
||||||
|
echo "CMPP storage OK: $role $target -> $source UUID=$expected_uuid"
|
||||||
|
}
|
||||||
|
case "${1:-all}" in
|
||||||
|
all) check_one postgresql; check_one redis; check_one minio ;;
|
||||||
|
*) check_one "$1" ;;
|
||||||
|
esac
|
||||||
@@ -1,6 +1,15 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -Eeuo pipefail
|
set -Eeuo pipefail
|
||||||
|
|
||||||
|
# Existing data-disk installations must fail before any initialization or release writes.
|
||||||
|
if [[ -e /etc/cmpp-platform/data-disk.uuid || -e /etc/systemd/system/postgresql.service.d/50-cmpp-data-disk.conf ]]; then
|
||||||
|
if [[ ! -x /usr/local/sbin/cmpp-data-storage-check ]]; then
|
||||||
|
echo "Missing CMPP data-disk guard; refusing to continue." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
/usr/local/sbin/cmpp-data-storage-check all
|
||||||
|
fi
|
||||||
|
|
||||||
APP_DIR="${APP_DIR:-/opt/cmpp-platform}"
|
APP_DIR="${APP_DIR:-/opt/cmpp-platform}"
|
||||||
REPO_URL="${REPO_URL:-http://175.27.255.91:3000/hectorzhao/lislgosms.git}"
|
REPO_URL="${REPO_URL:-http://175.27.255.91:3000/hectorzhao/lislgosms.git}"
|
||||||
BRANCH="${BRANCH:-main}"
|
BRANCH="${BRANCH:-main}"
|
||||||
|
|||||||
@@ -1,6 +1,15 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -Eeuo pipefail
|
set -Eeuo pipefail
|
||||||
|
|
||||||
|
# Existing data-disk installations must fail before any initialization or release writes.
|
||||||
|
if [[ -e /etc/cmpp-platform/data-disk.uuid || -e /etc/systemd/system/postgresql.service.d/50-cmpp-data-disk.conf ]]; then
|
||||||
|
if [[ ! -x /usr/local/sbin/cmpp-data-storage-check ]]; then
|
||||||
|
echo "Missing CMPP data-disk guard; refusing to continue." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
/usr/local/sbin/cmpp-data-storage-check all
|
||||||
|
fi
|
||||||
|
|
||||||
APP_DIR="${APP_DIR:-/opt/cmpp-platform}"
|
APP_DIR="${APP_DIR:-/opt/cmpp-platform}"
|
||||||
ENV_FILE="${ENV_FILE:-/etc/cmpp-platform/cmpp-platform.env}"
|
ENV_FILE="${ENV_FILE:-/etc/cmpp-platform/cmpp-platform.env}"
|
||||||
ADMIN_CREDENTIAL_FILE="${ADMIN_CREDENTIAL_FILE:-/root/cmpp-platform-admin.txt}"
|
ADMIN_CREDENTIAL_FILE="${ADMIN_CREDENTIAL_FILE:-/root/cmpp-platform-admin.txt}"
|
||||||
|
|||||||
@@ -6,6 +6,25 @@ const bootstrap = readFileSync(resolve(import.meta.dirname, 'production-bootstra
|
|||||||
const apiMain = readFileSync(resolve(import.meta.dirname, '../../api/src/main.ts'), 'utf8');
|
const apiMain = readFileSync(resolve(import.meta.dirname, '../../api/src/main.ts'), 'utf8');
|
||||||
const apiTimeouts = readFileSync(resolve(import.meta.dirname, '../../api/src/http-server-timeouts.ts'), 'utf8');
|
const apiTimeouts = readFileSync(resolve(import.meta.dirname, '../../api/src/http-server-timeouts.ts'), 'utf8');
|
||||||
const workerMain = readFileSync(resolve(import.meta.dirname, '../../api/src/send-worker.ts'), 'utf8');
|
const workerMain = readFileSync(resolve(import.meta.dirname, '../../api/src/send-worker.ts'), 'utf8');
|
||||||
|
const storageCheck = readFileSync(resolve(import.meta.dirname, 'check-data-storage.sh'), 'utf8');
|
||||||
|
for (const [name, script] of [['deploy', deploy], ['bootstrap', bootstrap]]) {
|
||||||
|
const guard = script.indexOf('/usr/local/sbin/cmpp-data-storage-check all');
|
||||||
|
const initialization = script.indexOf('APP_DIR=');
|
||||||
|
if (guard < 0 || initialization < 0 || guard > initialization) {
|
||||||
|
throw new Error(`${name} must verify migrated storage before initialization or release writes`);
|
||||||
|
}
|
||||||
|
for (const marker of ['data-disk.uuid', '50-cmpp-data-disk.conf', '[[ ! -x /usr/local/sbin/cmpp-data-storage-check ]]', 'refusing to continue.']) {
|
||||||
|
if (!script.includes(marker)) throw new Error(`${name} is missing the data-disk fail-closed guard: ${marker}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const marker of [
|
||||||
|
'mountpoint -q /data', 'findmnt -rn -M /data -o UUID', '/data/.cmpp-data-disk.uuid',
|
||||||
|
'mountpoint -q "$target"', 'findmnt -rn -M "$target" -o UUID', "stat -Lc '%d:%i'",
|
||||||
|
'findmnt -rn -M "$target" -o OPTIONS', '/data/postgresql', '/data/redis', '/data/minio',
|
||||||
|
'PG_VERSION', 'dump.rdb', '.minio.sys/format.json',
|
||||||
|
]) {
|
||||||
|
if (!storageCheck.includes(marker)) throw new Error(`data storage guard is missing: ${marker}`);
|
||||||
|
}
|
||||||
const required = [
|
const required = [
|
||||||
'compression_config=/etc/nginx/conf.d/cmpp-compression.conf',
|
'compression_config=/etc/nginx/conf.d/cmpp-compression.conf',
|
||||||
': >"$compression_config"',
|
': >"$compression_config"',
|
||||||
@@ -65,4 +84,4 @@ if (gatewayRestart < 0 || apiRestart < gatewayRestart || workerRestart < apiRest
|
|||||||
throw new Error('production deploy must restart Gateway before API and the send worker so API startup restores active channels');
|
throw new Error('production deploy must restart Gateway before API and the send worker so API startup restores active channels');
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Production deployment verified: Nginx/API guards and the split durable send worker contract are present.');
|
console.log('Production deployment verified: migrated storage fail-closed guards, Nginx/API guards and the split durable send worker contract are present.');
|
||||||
|
|||||||
Reference in New Issue
Block a user