# 画面設計書 3-AGリスナー管理

## 概要

本ドキュメントは、dbatools PowerShellモジュールにおける可用性グループリスナーの管理機能の設計書です。可用性グループのネットワークリスナーの追加、取得、設定変更、削除といった操作を提供するコマンド群について記述します。

### 本画面の処理概要

AGリスナー管理機能は、SQL Server AlwaysOn可用性グループへのクライアント接続を提供するネットワークリスナーのライフサイクル管理を実現するPowerShellコマンド群です。

**業務上の目的・背景**：可用性グループリスナーは、アプリケーションが可用性グループに接続するための仮想ネットワーク名（VNN）とIPアドレスを提供します。リスナーを使用することで、フェイルオーバーが発生しても接続文字列を変更せずに、自動的に現在のプライマリレプリカに接続できます。本機能群により、リスナーの作成、構成確認、ポート変更、削除を効率的に行うことができ、クライアント接続性の管理を簡素化します。

**画面へのアクセス方法**：PowerShellコンソールまたはPowerShell ISE/VS Codeから各コマンドレットを実行します。`Get-DbaAgListener`、`Add-DbaAgListener`、`Set-DbaAgListener`、`Remove-DbaAgListener`などのコマンドを使用します。

**主要な操作・処理内容**：
1. **リスナーの取得（Get-DbaAgListener）**：可用性グループに設定されているリスナーの情報（名前、ポート、IP構成等）を取得
2. **リスナーの追加（Add-DbaAgListener）**：静的IPまたはDHCPを使用して可用性グループにリスナーを作成
3. **リスナーの設定変更（Set-DbaAgListener）**：リスナーのポート番号を変更
4. **リスナーの削除（Remove-DbaAgListener）**：可用性グループからリスナーを削除

**画面遷移**：CLIベースのため画面遷移は存在しませんが、Get-DbaAgListenerの出力をパイプラインでSet-DbaAgListenerやRemove-DbaAgListenerに渡すことで、取得→変更/削除といったワークフローを構成できます。

**権限による表示制御**：リスナーの操作にはALTER AVAILABILITY GROUP権限またはsysadmin固定サーバーロールが必要です。また、Windows Server Failover Cluster（WSFC）の権限も必要となる場合があります。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 2 | Add-DbaAgListener | 主機能 | 可用性グループリスナーの作成 |
| 14 | Get-DbaAgListener | 主機能 | 可用性グループリスナー構成の取得 |
| 19 | Remove-DbaAgListener | 主機能 | 可用性グループリスナーの削除 |
| 23 | Set-DbaAgListener | 補助機能 | 可用性グループリスナーのポート番号変更 |

## 画面種別

コマンドラインインターフェース（CLI）- PowerShellコマンドレット群

## URL/ルーティング

該当なし（PowerShellモジュールのため）

コマンド呼び出し例：
- `Get-DbaAgListener -SqlInstance sql2017a -AvailabilityGroup AG1`
- `Add-DbaAgListener -SqlInstance sql2017 -AvailabilityGroup SharePoint -IPAddress 10.0.20.20`
- `Set-DbaAgListener -SqlInstance sql2017 -AvailabilityGroup SharePoint -Port 14333`
- `Remove-DbaAgListener -SqlInstance sql2017 -Listener SharePointListener`

## 入出力項目

### Get-DbaAgListener パラメータ

| パラメータ名 | 型 | 必須 | 説明 |
|-------------|-----|------|------|
| SqlInstance | DbaInstanceParameter[] | No | 接続先SQL Serverインスタンス（2012以降） |
| SqlCredential | PSCredential | No | 代替認証情報 |
| AvailabilityGroup | string[] | No | フィルタリング対象のAG名 |
| Listener | string[] | No | フィルタリング対象のリスナー名 |
| InputObject | AvailabilityGroup[] | No | パイプライン入力用AGオブジェクト |
| EnableException | switch | No | 例外処理の有効化 |

### Add-DbaAgListener パラメータ

| パラメータ名 | 型 | 必須 | 説明 |
|-------------|-----|------|------|
| SqlInstance | DbaInstanceParameter[] | No | 接続先SQL Serverインスタンス |
| SqlCredential | PSCredential | No | 認証情報 |
| AvailabilityGroup | string[] | Yes(SqlInstance使用時) | 対象の可用性グループ名 |
| Name | string | No | リスナー名（デフォルトはAG名） |
| IPAddress | ipaddress[] | No | 静的IPアドレス（マルチサブネット対応） |
| SubnetIP | ipaddress[] | No | サブネットIPアドレス（自動計算可） |
| SubnetMask | ipaddress[] | No | サブネットマスク（デフォルト255.255.255.0） |
| Port | int | No | ポート番号（デフォルト1433） |
| Dhcp | switch | No | DHCP使用 |
| Passthru | switch | No | 作成前のオブジェクトを返却 |
| InputObject | AvailabilityGroup[] | No | パイプライン入力用AGオブジェクト |

### Set-DbaAgListener パラメータ

| パラメータ名 | 型 | 必須 | 説明 |
|-------------|-----|------|------|
| SqlInstance | DbaInstanceParameter[] | No | 接続先SQL Serverインスタンス |
| SqlCredential | PSCredential | No | 認証情報 |
| AvailabilityGroup | string[] | Yes(SqlInstance使用時) | 対象の可用性グループ名 |
| Listener | string[] | No | 対象のリスナー名 |
| Port | int | Yes | 新しいポート番号 |
| InputObject | AvailabilityGroupListener[] | No | パイプライン入力用リスナーオブジェクト |

### Remove-DbaAgListener パラメータ

| パラメータ名 | 型 | 必須 | 説明 |
|-------------|-----|------|------|
| SqlInstance | DbaInstanceParameter[] | No | 接続先SQL Serverインスタンス |
| SqlCredential | PSCredential | No | 認証情報 |
| Listener | string[] | Yes(SqlInstance使用時) | 削除対象のリスナー名 |
| AvailabilityGroup | string[] | No | 対象の可用性グループ名 |
| InputObject | AvailabilityGroupListener[] | No | パイプライン入力用リスナーオブジェクト |

## 表示項目

### Get-DbaAgListener / Add-DbaAgListener 出力プロパティ

| プロパティ名 | 型 | 説明 |
|-------------|-----|------|
| ComputerName | string | SQLインスタンスのコンピュータ名 |
| InstanceName | string | SQLインスタンス名 |
| SqlInstance | string | 完全修飾インスタンス名 |
| AvailabilityGroup | string | 可用性グループ名 |
| Name | string | リスナー名 |
| PortNumber | int | クライアント接続用ポート番号 |
| ClusterIPConfiguration | string | WSFCクラスタIP構成 |
| AvailabilityGroupListenerIPAddresses | Collection | IPアドレス構成のコレクション |

### Remove-DbaAgListener 出力プロパティ

| プロパティ名 | 型 | 説明 |
|-------------|-----|------|
| ComputerName | string | SQLインスタンスのコンピュータ名 |
| InstanceName | string | SQLインスタンス名 |
| SqlInstance | string | 完全修飾インスタンス名 |
| AvailabilityGroup | string | 可用性グループ名 |
| Listener | string | リスナー名 |
| Status | string | 操作結果（Removed） |

## イベント仕様

### 1-Get-DbaAgListener実行

**処理フロー**：
1. SqlInstanceまたはInputObjectの検証
2. SqlInstance指定時はGet-DbaAvailabilityGroupを呼び出してAGオブジェクトを取得
3. InputObject.AvailabilityGroupListenersコレクションを取得
4. Listenerパラメータが指定されている場合はフィルタリング
5. 各リスナーにComputerName、InstanceName、SqlInstance、AvailabilityGroupを追加
6. Select-DefaultViewで表示プロパティを選択して出力

### 2-Add-DbaAgListener実行

**処理フロー**：
1. パラメータ検証（IPAddressとDhcpの排他、サブネットマスク数のチェック）
2. SqlInstance指定時はGet-DbaAvailabilityGroupでAGオブジェクトを取得
3. SubnetIPが未指定の場合、IPAddressとSubnetMaskから計算
4. AvailabilityGroupListenerオブジェクトを作成
5. PortNumberを設定
6. 各IPアドレスに対してAvailabilityGroupListenerIPAddressオブジェクトを作成し追加
7. Passthru使用時はオブジェクトを返却、それ以外はInvoke-Createでリスナーを作成
8. Get-DbaAgListenerで作成したリスナーを取得して返却

### 3-Set-DbaAgListener実行

**処理フロー**：
1. SqlInstanceまたはInputObjectの検証
2. SqlInstance使用時はAvailabilityGroup必須チェック
3. Get-DbaAgListenerで対象リスナーを取得
4. 各リスナーに対してPortNumberプロパティを設定
5. Alter()メソッドを呼び出して変更を適用
6. 変更後のリスナーオブジェクトを返却

### 4-Remove-DbaAgListener実行

**処理フロー**：
1. SqlInstanceまたはInputObjectの検証
2. SqlInstance使用時はListener必須チェック
3. Get-DbaAgListenerで対象リスナーを取得
4. 各リスナーに対してDrop()メソッドを実行
5. 結果オブジェクト（ComputerName、InstanceName、SqlInstance、AvailabilityGroup、Listener、Status）を返却

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| Add-DbaAgListener | sys.availability_group_listeners | INSERT | リスナーメタデータの作成 |
| Add-DbaAgListener | sys.availability_group_listener_ip_addresses | INSERT | リスナーIPアドレスの登録 |
| Set-DbaAgListener | sys.availability_group_listeners | UPDATE | ポート番号の更新 |
| Remove-DbaAgListener | sys.availability_group_listeners | DELETE | リスナーメタデータの削除 |

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

#### sys.availability_group_listeners

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | dns_name | リスナー名 | Add-DbaAgListener実行時 |
| INSERT | port | ポート番号 | Add-DbaAgListener実行時 |
| UPDATE | port | 新ポート番号 | Set-DbaAgListener実行時 |
| DELETE | - | 指定されたリスナー | Remove-DbaAgListener実行時 |

## メッセージ仕様

| メッセージ種別 | メッセージ内容 | 発生条件 |
|--------------|--------------|---------|
| Error | You must supply either -SqlInstance or an Input Object | 必須パラメータ不足時 |
| Error | You must specify one or more databases and one or more Availability Groups when using the SqlInstance parameter | AG未指定時 |
| Error | You cannot specify both an IP address and the Dhcp switch | IPAddressとDhcp両方指定時 |
| Error | You can only specify a single subnet when using Dhcp | Dhcp使用時に複数サブネット指定 |
| Error | When specifying multiple IP addresses, the number of subnet masks must match | IPとサブネットマスク数不一致時 |
| Error | You must specify one or more listeners when using the SqlInstance parameter | リスナー未指定時（Remove） |
| Success | Removed | リスナー削除成功時 |

## 例外処理

| 例外状態 | 処理内容 |
|---------|---------|
| 接続エラー | Stop-Function -Category ConnectionErrorを発生させ、処理を中断 |
| パラメータ不正 | Stop-Functionでエラーメッセージを表示し、処理を中断 |
| リスナー作成失敗 | Invoke-Createの例外をキャッチしてStop-Functionを呼び出し |
| Alter失敗 | Stop-Functionでエラーを報告 |
| Drop失敗 | Stop-Function -Continueで次のリスナーに進む |

## 備考

- リスナー名が未指定の場合、可用性グループ名がデフォルトで使用される
- マルチサブネット構成では複数のIPアドレスを指定可能
- サブネットIPが未指定の場合、IPアドレスとサブネットマスクから自動計算される
- サブネットマスクのデフォルトは255.255.255.0（/24）
- ポートのデフォルトは1433
- DHCPモードでは複数サブネットはサポートされない
- Set-DbaAgListenerはポート番号の変更のみをサポート

---

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

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

### 推奨読解順序

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

AGリスナー管理で使用されるSMOオブジェクトの構造を理解することが重要です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Get-DbaAgListener.ps1 | `public/Get-DbaAgListener.ps1` | AvailabilityGroupListenerオブジェクトの構造とプロパティを理解する |

**読解のコツ**: AvailabilityGroupListenerはAvailabilityGroup.AvailabilityGroupListenersコレクションから取得され、PortNumber、ClusterIPConfiguration、AvailabilityGroupListenerIPAddresses等の重要なプロパティを持つ。

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

処理の起点となるコマンドのprocessブロックを特定します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Get-DbaAgListener.ps1 | `public/Get-DbaAgListener.ps1` | Line 94-119: processブロックでの取得処理 |
| 2-2 | Add-DbaAgListener.ps1 | `public/Add-DbaAgListener.ps1` | Line 135-230: リスナー作成処理 |

**主要処理フロー（Get-DbaAgListener）**:
1. **Line 95-98**: SqlInstance/InputObjectの検証
2. **Line 100-102**: Get-DbaAvailabilityGroupでAGオブジェクトを取得
3. **Line 104-107**: AvailabilityGroupListenersをループしフィルタリング
4. **Line 111-118**: カスタムプロパティを追加し出力

#### Step 3: Add-DbaAgListenerの処理フローを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Add-DbaAgListener.ps1 | `public/Add-DbaAgListener.ps1` | リスナー作成処理を理解する |

**主要処理フロー（Add-DbaAgListener）**:
- **Line 136-156**: パラメータ検証（IPAddress/Dhcp排他等）
- **Line 162-189**: サブネットIP/マスクの処理と計算
- **Line 191-194**: リスナー名のデフォルト設定（AG名）
- **Line 197-198**: AvailabilityGroupListenerオブジェクト作成
- **Line 200-216**: IPアドレス設定のループ処理
- **Line 218-223**: Passthru判定とInvoke-Create実行
- **Line 227**: Get-DbaAgListenerで結果取得

#### Step 4: Set/Removeコマンドを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Set-DbaAgListener.ps1 | `public/Set-DbaAgListener.ps1` | Line 94-123: ポート変更処理 |
| 4-2 | Remove-DbaAgListener.ps1 | `public/Remove-DbaAgListener.ps1` | Line 86-121: 削除処理 |

**主要処理フロー（Set-DbaAgListener）**:
- **Line 112-122**: 各リスナーのPortNumber設定とAlter()呼び出し

**主要処理フロー（Remove-DbaAgListener）**:
- **Line 103-120**: 各リスナーのDrop()呼び出しと結果出力

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

```
Get-DbaAgListener
    |
    +-- Get-DbaAvailabilityGroup (SqlInstance使用時)
    |
    +-- InputObject.AvailabilityGroupListeners
    |
    +-- Select-DefaultView

Add-DbaAgListener
    |
    +-- Get-DbaAvailabilityGroup (SqlInstance使用時)
    |
    +-- New-Object AvailabilityGroupListener
    |
    +-- New-Object AvailabilityGroupListenerIPAddress (各IP分)
    |       +-- AvailabilityGroupListenerIPAddresses.Add()
    |
    +-- Invoke-Create (Passthru未使用時)
    |
    +-- Get-DbaAgListener

Set-DbaAgListener
    |
    +-- Get-DbaAgListener
    |
    +-- aglistener.PortNumber = Port
    |
    +-- aglistener.Alter()

Remove-DbaAgListener
    |
    +-- Get-DbaAgListener
    |
    +-- AvailabilityGroupListeners[].Drop()
```

### データフロー図

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

AvailabilityGroup名 ----->  Get-DbaAvailabilityGroup  ----+
IPAddress           ----->                                 |
SubnetMask          ----->  サブネットIP計算              |
Port                ----->                                 |
                           +<------------------------------+
                           |
                           v
               AvailabilityGroupListener作成
                           |
                           v
               AvailabilityGroupListenerIPAddress追加
                           |
                           v
                   Invoke-Create
                           |
                           v
               AvailabilityGroupListener
                     オブジェクト
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Get-DbaAgListener.ps1 | `public/Get-DbaAgListener.ps1` | ソース | AGリスナー情報の取得 |
| Add-DbaAgListener.ps1 | `public/Add-DbaAgListener.ps1` | ソース | AGリスナーの作成 |
| Set-DbaAgListener.ps1 | `public/Set-DbaAgListener.ps1` | ソース | AGリスナーのポート変更 |
| Remove-DbaAgListener.ps1 | `public/Remove-DbaAgListener.ps1` | ソース | AGリスナーの削除 |
| Get-DbaAvailabilityGroup.ps1 | `public/Get-DbaAvailabilityGroup.ps1` | ソース | 可用性グループ情報の取得 |
