# 画面設計書 123-スナップショットクローン

## 概要

本ドキュメントは、OpenSearchのスナップショットクローンAPI（PUT /_snapshot/{repository}/{snapshot}/_clone/{target_snapshot}）の画面設計書である。同一リポジトリ内でスナップショットのインデックスを別のスナップショットにクローンするREST APIエンドポイントの仕様を定義する。

### 本画面の処理概要

**業務上の目的・背景**：スナップショットクローンは、既存のスナップショットから特定のインデックスだけを別のスナップショットとしてコピーする機能である。物理的なデータコピーを伴わず、リポジトリ内のメタデータ操作のみで実現されるため高速である。これにより、大規模なスナップショットから必要なインデックスだけを切り出して管理したり、スナップショットの部分的な保持ポリシーを実現できる。

**画面へのアクセス方法**：REST APIクライアントから `PUT /_snapshot/{repository}/{snapshot}/_clone/{target_snapshot}` エンドポイントにHTTP PUTリクエストを送信してアクセスする。リクエストボディにクローン対象のインデックスを指定する。

**主要な操作・処理内容**：
1. クライアントがソーススナップショット名、ターゲットスナップショット名、クローン対象インデックスを指定してPUTリクエストを送信する
2. クラスタマネージャノードがクローン処理を開始する
3. SnapshotsServiceがクラスタ状態を更新し、クローン操作を記録する
4. リポジトリ内でメタデータのみをコピーする（物理データコピーなし）
5. クローン完了後、新しいスナップショットとしてリポジトリインデックスに登録する

**画面遷移**：スナップショット取得（GET /_snapshot/{repository}/{snapshot}）で対象を確認した後に本APIを呼び出す。クローン後のスナップショットはスナップショットリストア（POST /_snapshot/{repository}/{target_snapshot}/_restore）で利用できる。

**権限による表示制御**：クラスタレベルの管理権限が必要。セキュリティプラグイン有効時はスナップショット管理の書き込み権限を持つユーザーのみアクセス可能。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 63 | スナップショット作成・管理 | 主機能 | スナップショットのインデックスを同一リポジトリ内の別スナップショットにクローンする処理 |

## 画面種別

登録（REST API - データ作成）

## URL/ルーティング

| メソッド | パス | 説明 |
|---------|------|------|
| PUT | `/_snapshot/{repository}/{snapshot}/_clone/{target_snapshot}` | スナップショットをクローン |

## 入出力項目

### パスパラメータ

| 項目名 | 型 | 必須 | 説明 |
|--------|------|------|------|
| repository | string | Yes | リポジトリ名 |
| snapshot | string | Yes | クローン元のスナップショット名 |
| target_snapshot | string | Yes | 作成するクローン先のスナップショット名 |

### クエリパラメータ

| 項目名 | 型 | 必須 | デフォルト | 説明 |
|--------|------|------|-----------|------|
| cluster_manager_timeout | time | No | 30s | クラスタマネージャノードへの接続タイムアウト |
| master_timeout | time | No | 30s | （非推奨）cluster_manager_timeout を使用すること |

### リクエストボディ

| 項目名 | 型 | 必須 | 説明 |
|--------|------|------|------|
| indices | string/array | Yes | クローン対象のインデックス名。カンマ区切り文字列または配列 |

## 表示項目

### レスポンスボディ

| 項目名 | 型 | 説明 |
|--------|------|------|
| acknowledged | boolean | リクエストが受理されたかどうか |

## イベント仕様

### 1-スナップショットクローンリクエスト

クライアントからPUTリクエストを受信すると以下の処理が実行される：

1. RestCloneSnapshotActionがリクエストパラメータとボディを解析し、CloneSnapshotRequestを生成する
2. リクエストボディからindicesを抽出する（XContentMapValues.nodeStringArrayValue使用）
3. IndicesOptionsを適用する
4. TransportCloneSnapshotActionがクラスタマネージャノードで実行される
5. SnapshotsService#cloneSnapshot()が呼び出される
6. クラスタ状態にクローン操作を記録する
7. リポジトリ内でメタデータレベルのクローンを実行する
8. AcknowledgedResponseとして結果を返却する

## データベース更新仕様

### 操作別データベース影響一覧

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| PUT リクエスト | クラスタ状態（SnapshotsInProgress） | UPDATE | クローン操作の進行状態を記録 |
| PUT リクエスト | リポジトリメタデータ（RepositoryData） | INSERT | 新しいスナップショットエントリをリポジトリインデックスに追加 |

### テーブル別更新項目詳細

#### リポジトリメタデータ

| 操作 | 項目 | 更新値・取得条件 | 備考 |
|-----|------|-----------------|------|
| INSERT | SnapshotId | ターゲットスナップショット名と新規UUID | クローン先スナップショット |
| INSERT | IndexId | ソーススナップショットから指定インデックスのメタデータをコピー | 物理データコピーなし |

## メッセージ仕様

| HTTPステータス | 条件 | メッセージ例 |
|---------------|------|-------------|
| 200 OK | クローン完了 | `{"acknowledged": true}` |
| 404 Not Found | ソーススナップショットが存在しない | `SnapshotMissingException` |
| 404 Not Found | リポジトリが存在しない | `RepositoryMissingException` |
| 409 Conflict | 同時スナップショット操作による競合 | `ConcurrentSnapshotExecutionException` |
| 400 Bad Request | ターゲットスナップショット名が既に存在 | `InvalidSnapshotNameException` |

## 例外処理

| 例外 | 条件 | 対処 |
|------|------|------|
| SnapshotMissingException | ソーススナップショットが存在しない | 404を返却 |
| RepositoryMissingException | リポジトリが存在しない | 404を返却 |
| InvalidSnapshotNameException | ターゲット名が不正または既に存在 | 400を返却 |
| ConcurrentSnapshotExecutionException | 同時操作が実行中 | 409を返却 |
| ClusterBlockException | METADATA_WRITEブロックが設定されている | 処理をブロック |

## 備考

- クローン操作はメタデータのみのコピーであり、物理的なデータBLOBの複製は発生しないため高速
- ソースとターゲットは同一リポジトリ内に限定される
- リクエストボディは必須で、indicesフィールドにクローン対象インデックスを指定する必要がある
- `master_timeout` パラメータはバージョン2.0.0で非推奨

---

## コードリーディングガイド

本画面を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | CloneSnapshotRequest.java | `server/src/main/java/org/opensearch/action/admin/cluster/snapshots/clone/CloneSnapshotRequest.java` | リクエストパラメータ（repository, snapshot, targetSnapshot, indices）の定義 |

**読解のコツ**: CloneSnapshotRequestのコンストラクタでrepository, snapshot, target_snapshot, indices[]の4つが必須引数として渡される。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | RestCloneSnapshotAction.java | `server/src/main/java/org/opensearch/rest/action/admin/cluster/RestCloneSnapshotAction.java` | ルーティング定義（62行目）とリクエストボディ解析（72-78行目） |

**主要処理フロー**:
1. **62行目**: `PUT /_snapshot/{repository}/{snapshot}/_clone/{target_snapshot}` のルーティング定義
2. **72行目**: リクエストボディをMapとして解析
3. **73-78行目**: CloneSnapshotRequestを生成。repository, snapshot, target_snapshot, indicesを設定
4. **83行目**: IndicesOptionsを適用
5. **84行目**: NodeClient経由でcloneSnapshotアクションを実行

#### Step 3: Transport層の処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | TransportCloneSnapshotAction.java | `server/src/main/java/org/opensearch/action/admin/cluster/snapshots/clone/TransportCloneSnapshotAction.java` | SnapshotsService#cloneSnapshot()への委譲 |
| 3-2 | SnapshotsService.java | `server/src/main/java/org/opensearch/snapshots/SnapshotsService.java` | クローン処理のコアロジック |

### プログラム呼び出し階層図

```
RestCloneSnapshotAction#prepareRequest()
    |
    +-- request.contentParser().map() (ボディ解析)
    |
    +-- XContentMapValues.nodeStringArrayValue() (indices抽出)
    |
    +-- NodeClient#admin().cluster().cloneSnapshot()
            |
            +-- TransportCloneSnapshotAction#clusterManagerOperation()
                    |
                    +-- SnapshotsService#cloneSnapshot()
                            |
                            +-- ClusterState更新タスク投入
                            |       (SnapshotsInProgress追加)
                            |
                            +-- Repository (メタデータクローン)
```

### データフロー図

```
[入力]                          [処理]                     [出力]

PUT /_snapshot/               RestCloneSnapshotAction     AcknowledgedResponse
  /{repository}/              (パラメータ+ボディ解析)       {"acknowledged": true}
  /{snapshot}/_clone/               |
  /{target_snapshot}                v
                              TransportCloneSnapshotAction
Body: {"indices": "..."}      (クラスタマネージャノード)
                                    |
                                    v
                              SnapshotsService
                              (クローン処理)
                                    |
                              RepositoryData更新
                              (メタデータのみ)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| RestCloneSnapshotAction.java | `server/src/main/java/org/opensearch/rest/action/admin/cluster/RestCloneSnapshotAction.java` | ソース | RESTハンドラ |
| TransportCloneSnapshotAction.java | `server/src/main/java/org/opensearch/action/admin/cluster/snapshots/clone/TransportCloneSnapshotAction.java` | ソース | Transportアクション |
| CloneSnapshotRequest.java | `server/src/main/java/org/opensearch/action/admin/cluster/snapshots/clone/CloneSnapshotRequest.java` | ソース | リクエストモデル |
| SnapshotsService.java | `server/src/main/java/org/opensearch/snapshots/SnapshotsService.java` | ソース | クローンコアロジック |
| snapshot.clone.json | `rest-api-spec/src/main/resources/rest-api-spec/api/snapshot.clone.json` | API定義 | REST API仕様定義 |
