内容
# must-gather-downloader
用于 Claude Code 的 MCP 服务器,下载并分析 ReportPortal 测试失败的 must-gather 日志。
给定一个 ReportPortal 测试日志 URL,它会解析相应的 Magna 日志目录,找到 must-gather tarball,下载并在本地提取,提供用于检查集群状态的工具 — Kubernetes 资源、Pod 日志、Ceph 状态、NooBaa 数据等。
## 功能
- **单次工具调用**:粘贴 ReportPortal URL,获取提取的 must-gather 日志
- **本地 tarball 支持**:从磁盘提取 must-gather tarballs,无需 ReportPortal 凭证
- **智能缓存**:重复调用立即返回;不会重复下载
- **并行安全**:多个下载并发运行,无冲突(基于文件的锁定防止同一测试的竞争)
- **资源检索**:直接从 must-gather 读取 Kubernetes 资源、Ceph 输出和 NooBaa 数据
- **Pod 日志检查**:检索完整的 Pod 日志或在其中搜索,带有时间范围和容器过滤
- **类似 Grep 的搜索**:在所有 must-gather 文件中搜索模式
- **测试日志提取**:从 Magna 部署日志中提取 OCS-CI 测试执行跟踪
- **AI 分析**:检索测试失败的自动根因分析
- **自动启动**:安装一次,在每个 Claude Code 会话中可用
## 先决条件
- [uv](https://docs.astral.sh/uv/)(包括 `uvx`)
- ReportPortal API 访问(API 密钥 + 基地址)
- 到 Magna 日志服务器的网络访问
## 安装
### 安装
```bash
claude mcp add must-gather \
-s user \
-e RP_API_KEY="<YOUR_RP_API_TOKEN>" \
-e RP_BASE_URL="<YOUR_BASE_URL>" \
-e RP_SSL_VERIFY="false" \
-- \
uvx --from "git+https://github.com/sagihirshfeld/must-gather-downloader" must-gather-downloader
```
运行此命令后重启 Claude Code。服务器在每次会话中自动启动 — 无需手动步骤。
## 环境变量
| 变量 | 是否必需 | 描述 |
|---|---|---|
| `RP_API_KEY` | 是* | ReportPortal Bearer 令牌(配置文件 > API 密钥) |
| `RP_BASE_URL` | 是* | ReportPortal 实例 URL,无尾斜杠 |
| `MUST_GATHER_CACHE_DIR` | 否 | 重写缓存目录(默认:`/tmp/must-gather-cache`) |
| `RP_SSL_VERIFY` | 否 | SSL 验证:`true`(默认)、`false` 或 CA 捆绑路径 |
\* 不适用于 `extract_local_must_gather`。
## 工具
### 核心
#### `download_must_gather`
从 ReportPortal 测试失败中下载并提取 must-gather 日志。
| 参数 | 是否必需 | 描述 |
|---|---|---|
| `reportportal_url` | 是 | 到测试日志页面的完整 ReportPortal URL |
| `force_redownload` | 否 | 绕过缓存并重新下载(默认:`false`) |
**返回:** `path`、`test_name`、`cluster_name`、`tarball_url`、`cached`、`files_count`
#### `extract_local_must_gather`
提取本地 must-gather tarball 进行分析。当您已经拥有磁盘上的 tarball 且不需要从 ReportPortal 下载时使用此工具。无需 RP 凭证。
| 参数 | 是否必需 | 描述 |
|---|---|---|
| `tarball_path` | 是 | 本地 must-gather tarball(`.tar.gz`、`.tgz` 或 `.tar`)的绝对路径 |
| `force_re_extract` | 否 | 绕过缓存并重新提取(默认:`false`) |
**返回:** `path`、`source_tarball`、`cached`、`files_count`
#### `list_must_gather_contents`
列出下载的 must-gather 的结构 — 命名空间、资源类型、Ceph 数据、NooBaa 部分和 Pod 计数。
| 参数 | 是否必需 | 描述 |
|---|---|---|
| `must_gather_path` | 是 | 从 `download_must_gather` 提取的 `extracted/` 目录路径 |
### 资源检索
#### `get_must_gather_resource`
从 must-gather 检索 Kubernetes 资源、Ceph 命令输出或 NooBaa 资源。支持集群范围资源(节点、PV、SC、对象桶)、命名空间资源(事件、Pod、ConfigMap、Secret、部署、OBC、BackingStore、NamespaceStore、BucketClass、NooBaa)、Ceph 数据(cephhealth、cephstatus、osdtree、osddump)和仅 NooBaa 类型(状态、db_list、诊断、日志、cnpg)。YAML 资源会自动清理(删除 managedFields)。
| 参数 | 是否必需 | 描述 |
|---|---|---|
| `must_gather_path` | 是 | 提取的 must-gather 目录的路径 |
| `resource_type` | 是 | 资源类型(参见上文) |
| `name` | 否 | 特定资源名称(省略以列出可用资源) |
| `namespace` | 否 | 命名空间(命名空间资源所需) |
| `tail` | 否 | 对于事件,最后 N 个事件;对于 NooBaa 日志/诊断,最后 N 行(默认:全部) |
| `subtree` | 否 | `auto`(默认)、`main` 或 `noobaa`。自动检测:仅 NooBaa 类型使用 noobaa,重叠 CRD 类型如果可用则优先使用 noobaa,其他类型使用 main |
### 搜索
#### `search_must_gather`
对所有 must-gather 文件(YAML 资源、Ceph 输出、配置文件、日志)进行类似 Grep 的搜索。自动跳过二进制文件。
| 参数 | 是否必需 | 描述 |
|---|---|---|
| `must_gather_path` | 是 | 提取的 must-gather 目录的路径 |
| `pattern` | 是 | 要搜索的正则表达式或字面字符串 |
| `file_pattern` | 否 | 文件过滤器(例如 `*.yaml`、`*.log`) |
| `max_results` | 否 | 要返回的最大匹配数(默认:50) |
| `case_sensitive` | 否 | 区分大小写的搜索(默认:`false`) |
### Pod 日志
#### `get_must_gather_pod_logs`
检索完整的 Pod 日志内容或在日志中搜索模式。可以列出可用的 Pod(省略 `pod_name`)、检索完整的日志并带有尾部/时间过滤,或在提供 `pattern` 时搜索匹配的行并带有上下文。
| 参数 | 是否必需 | 描述 |
|---|---|---|
| `must_gather_path` | 是 | 提取的 must-gather 目录的路径 |
| `namespace` | 是 | Kubernetes 命名空间 |
| `pod_name` | 否 | Pod 名称或子字符串(省略以列出可用 Pod) |
| `container` | 否 | 容器名称过滤器 |
| `previous` | 否 | 返回 `previous.log`(默认:`false`) |
| `tail` | 否 | 从末尾返回的行数,仅全日志模式(默认:全部) |
| `time_from` | 否 | 开始时间过滤器(例如 `03:38:00`) |
| `time_to` | 否 | 结束时间过滤器(例如 `03:41:00`) |
| `pattern` | 否 | 要搜索的正则表达式或字面字符串(省略以获取完整日志) |
| `context_lines` | 否 | 每个匹配周围的上下文行数(默认:3,仅搜索模式) |
| `max_results` | 否 | 最大匹配数(默认:50,仅搜索模式) |
| `case_sensitive` | 否 | 区分大小写的搜索(默认:`false`,仅搜索模式) |
### 测试分析
#### `get_ocs_ci_test_log`
从 Magna 上的部署日志中检索 OCS-CI 测试执行跟踪。显示测试框架执行了哪些步骤 — 设置、拆除、断言和 oc 命令。不需要先下载 must-gather。
| 参数 | 是否必需 | 描述 |
|---|---|---|
| `reportportal_url` | 是 | 到测试日志页面的完整 ReportPortal URL |
| `test_name` | 是 | 测试函数名称(例如 `test_bucket_notifications[default-logs-pvc]`) |
| `tail` | 否 | 仅返回最后 N 行(默认:全部) |
| `head` | 否 | 仅返回前 N 行(默认:全部) |
#### `get_ai_analysis_report`
为测试检索自动 AI 故障分析 — 根因、推荐操作、证据、置信度和建议的修复。
| 参数 | 是否必需 | 描述 |
|---|---|---|
| `reportportal_url` | 是 | 到测试日志页面的完整 ReportPortal URL |
| `test_name` | 是 | 测试函数名称 |
| `include_traceback` | 否 | 在结果中包含回溯信息(默认:`true`) |
| `include_suggested_fix` | 否 | 包含建议的修复/错误详细信息(默认:`true`) |
## 缓存结构
```
/tmp/must-gather-cache/
├── {test_item_id}/ # 来自 download_must_gather(RP)
│ ├── .lock # 防止并行重复下载
│ ├── metadata.json # 测试名称、集群、tarball URL、时间戳
│ ├── *.tar.gz # 原始 tarball(保留以便重用)
│ └── extracted/ # 提取的 must-gather 内容
├── local-{sha256_prefix}/ # 来自 extract_local_must_gather
│ ├── metadata.json
│ └── extracted/
```
缓存位于 `/tmp`,在重启后清除。使用 `MUST_GATHER_CACHE_DIR` 重写。
## 本地开发
```bash
git clone https://github.com/sagihirshfeld/must-gather-downloader.git
cd must-gather-downloader
pip install -e .
# 设置环境变量
export RP_API_KEY="your-key"
export RP_BASE_URL="https://reportportal.example.com"
# 运行服务器
must-gather-downloader
```