# バッチ設計書 11-223.backup-zfs

## 概要

本ドキュメントは、FreeBSDのperiodicフレームワークにおけるdailyバッチ `223.backup-zfs` の設計仕様を記述する。本バッチはZFSプール及びファイルシステムの構成情報をバックアップし、変更差分を検出する。

### 本バッチの処理概要

本バッチは、ZFS（Zettabyte File System）のプール及びファイルシステムに関する構成情報を定期的にバックアップし、前回バックアップとの差分を検出・報告する処理を行う。

**業務上の目的・背景**：ZFSはFreeBSDの主要ストレージシステムであり、プール構成やファイルシステム設定は障害復旧やシステム再構築時に不可欠な情報である。本バッチは、これらの情報を日次でバックアップし、構成変更を早期に検知することで、障害対応の迅速化と構成管理の自動化を実現する。

**バッチの実行タイミング**：日次（daily periodic）で実行される。デフォルトでは無効（daily_backup_zfs_enable=NO）であり、管理者が明示的に有効化する必要がある。

**主要な処理内容**：
1. `zpool list` コマンドでZFSプール一覧を取得し、`/var/backups/zpool_list.bak` としてローテーション保存する
2. `zfs list` コマンドでZFSファイルシステム一覧を取得し、`/var/backups/zfs_list.bak` としてローテーション保存する
3. `daily_backup_zfs_props_enable=YES` の場合、`zfs get` でファイルシステムプロパティ、`zpool get` でプールプロパティをバックアップする
4. 各バックアップについて前回との差分比較を行い、verboseモード時には差分を出力する

**前後の処理との関連**：No.10（222.backup-gmirror）と同じdailyバックアップカテゴリに属する。前提となるバッチはないが、ZFSプールがインポートされている必要がある。

**影響範囲**：`/var/backups/` ディレクトリ配下のバックアップファイル（zpool_list.bak, zfs_list.bak, zfs_props.bak, zpool_props.bak）に影響する。

## バッチ種別

データバックアップ / 差分検出・レポート生成

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | 日次 |
| 実行時刻 | periodicフレームワークの日次実行時刻（デフォルト: 3:01） |
| 実行曜日 | 毎日 |
| 実行日 | 毎日 |
| トリガー | cron経由のperiodicフレームワーク |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| daily_backup_zfs_enable | "YES"に設定されていること（デフォルト: NO） |
| ZFSプールの存在 | 少なくとも1つのZFSプールがインポートされていること |
| /var/backups ディレクトリ | バックアップ出力先ディレクトリが存在すること |

### 実行可否判定

1. `daily_backup_zfs_enable` が "YES" でない場合、ZFSリスト関連のバックアップをスキップ（rc=0で正常終了）
2. `daily_backup_zfs_enable` が "YES" の場合、`zpool list` を実行し、出力が空であれば警告を出力してrc=2で終了
3. `daily_backup_zfs_props_enable` が "YES" の場合のみ、プロパティバックアップを実行

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| daily_backup_zfs_enable | 文字列 | Yes | NO | バッチの有効/無効フラグ |
| daily_backup_zfs_props_enable | 文字列 | No | NO | プロパティバックアップの有効/無効フラグ |
| daily_backup_zfs_verbose | 文字列 | No | NO | 差分レポート出力の有効/無効フラグ |
| daily_backup_zpool_list_flags | 文字列 | No | （なし） | zpool listコマンドへの追加フラグ |
| daily_backup_zfs_list_flags | 文字列 | No | （なし） | zfs listコマンドへの追加フラグ |
| daily_backup_zfs_get_flags | 文字列 | No | all | zfs getコマンドへのフラグ |
| daily_backup_zpool_get_flags | 文字列 | No | （なし） | zpool getコマンドへのフラグ |
| daily_diff_flags | 文字列 | No | -b -U 0 | 差分比較時のdiffコマンドフラグ |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| zpool list出力 | テキスト | ZFSプール一覧情報 |
| zfs list出力 | テキスト | ZFSファイルシステム一覧情報 |
| zfs get出力 | テキスト | ZFSファイルシステムプロパティ情報 |
| zpool get出力 | テキスト | ZFSプールプロパティ情報 |
| /var/backups/*.bak | テキストファイル | 前回バックアップデータ |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| /var/backups/zpool_list.bak | テキストファイル | 最新のzpool list出力 |
| /var/backups/zpool_list.bak2 | テキストファイル | 前回のzpool list出力 |
| /var/backups/zfs_list.bak | テキストファイル | 最新のzfs list出力 |
| /var/backups/zfs_list.bak2 | テキストファイル | 前回のzfs list出力 |
| /var/backups/zfs_props.bak | テキストファイル | 最新のzfs getプロパティ出力 |
| /var/backups/zfs_props.bak2 | テキストファイル | 前回のzfs getプロパティ出力 |
| /var/backups/zpool_props.bak | テキストファイル | 最新のzpool getプロパティ出力 |
| /var/backups/zpool_props.bak2 | テキストファイル | 前回のzpool getプロパティ出力 |
| 標準出力 | テキスト | 差分レポート（verboseモード時） |

### 出力ファイル仕様

| 項目 | 内容 |
|-----|------|
| ファイル名 | zpool_list.bak / zfs_list.bak / zfs_props.bak / zpool_props.bak |
| 出力先 | /var/backups/ |
| 文字コード | システムデフォルト |
| 区切り文字 | コマンド出力依存 |

## 処理フロー

### 処理シーケンス

```
1. periodic.confの読み込み
   └─ /etc/defaults/periodic.confとローカル設定を読み込む
2. daily_backup_zfs_verbose判定
   └─ YESの場合、差分表示フラグを設定
3. daily_backup_zfs_enable判定
   └─ YESでない場合、ZFSリストバックアップをスキップ
4. zpool list実行
   └─ 結果が空ならエラーメッセージを出力してrc=2
5. zpool_list.tmpに出力 → rotate関数でローテーション
   └─ 前回bakと比較、差異があればbak2に退避しtmpをbakに昇格
6. zfs list実行 → zfs_list.tmpに出力 → rotate
7. daily_backup_zfs_props_enable判定
   └─ YESの場合のみ以下を実行
8. zfs get実行 → zfs_props.tmpに出力 → rotate
9. zpool get実行 → zpool_props.tmpに出力 → rotate
10. 終了コード(rc)を返却して終了
```

### フローチャート

```mermaid
flowchart TD
    A[バッチ開始] --> B[periodic.conf読み込み]
    B --> C{daily_backup_zfs_enable=YES?}
    C -->|No| D[スキップ rc=0]
    C -->|Yes| E[zpool list実行]
    E --> F{zpools出力あり?}
    F -->|No| G[警告出力 rc=2]
    F -->|Yes| H[zpool_list.tmp保存・rotate]
    H --> I[zfs list実行・zfs_list.tmp保存・rotate]
    I --> J{daily_backup_zfs_props_enable=YES?}
    J -->|No| K[終了]
    J -->|Yes| L[zfs get実行・zfs_props.tmp保存・rotate]
    L --> M[zpool get実行・zpool_props.tmp保存・rotate]
    M --> K
    D --> N[exit rc]
    G --> N
    K --> N
```

## データベース操作仕様

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

本バッチはデータベース操作を行わない。ファイルシステム上のバックアップファイルのみを操作する。

| 処理 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| N/A | N/A | N/A | データベース操作なし |

### テーブル別操作詳細

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| rc=1 | 変更検出 | 前回バックアップとの差異を検出した場合、または初回バックアップの場合 | 正常な変更通知であり対処不要 |
| rc=2 | 設定不整合 | daily_backup_zfs_enable=YESだがZFSプールが存在しない | ZFS環境を確認するか設定を無効化する |
| rc=3 | 処理エラー | ファイルのmvやcmpコマンドが失敗した場合 | /var/backupsディレクトリのパーミッションやディスク容量を確認する |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし（リトライ機構なし） |
| リトライ間隔 | N/A |
| リトライ対象エラー | N/A |

### 障害時対応

バッチ失敗時は/var/backups/配下の.tmpファイルが残存する可能性がある。手動で.tmpファイルを削除し、再実行することで復旧可能。.bak2ファイルに前々回のバックアップが保持されているため、データ損失のリスクは低い。

## トランザクション仕様

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | 各バックアップファイル単位（rotate関数単位） |
| コミットタイミング | 各rotate処理完了時 |
| ロールバック条件 | ファイル操作失敗時（rc=3を設定するが処理は継続） |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | ZFSプール数・ファイルシステム数に依存 |
| 目標処理時間 | 通常数秒以内（大規模環境でも1分以内） |
| メモリ使用量上限 | シェルスクリプトのため最小限 |

## 排他制御

特別な排他制御は実装されていない。periodicフレームワークにより日次で1回のみ実行されることが想定されている。同時実行された場合、.tmpファイルの競合が発生する可能性がある。

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| 開始ログ | バッチ開始時 | "Backup of ZFS information for all imported pools" |
| 差分ログ | 変更検出時（verbose時） | diff出力 |
| 警告ログ | ZFSプール未検出時 | "daily_backup_zfs_enable is set to YES but no zpools found." |
| 初回ログ | 初回バックアップ時（verbose時） | バックアップ内容全体をcat出力 |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| 終了コード | rc!=0 | periodicフレームワーク経由のメール通知 |
| ZFSプール未検出 | rc=2 | periodicフレームワーク経由のメール通知 |

## 備考

- 作成者: Miroslav Lachman <000.fbsd@quip.cz>
- rotate関数は、.bak（前回）と.tmp（今回）を比較し、差異があれば.bakを.bak2に退避してから.tmpを.bakにリネームする2世代管理を行う
- daily_backup_zpool_get_flagsのデフォルト値はperiodic.confに明示されていないが、daily_backup_zfs_get_flagsは"all"がデフォルト
- ソースファイル: `usr.sbin/periodic/etc/daily/223.backup-zfs`
