ブログ

【Hyper-V】自動バックアップ結果をSlackへ通知する方法

ITツール紹介

2024.04.05

こんにちは、顧客サービス部の中木村です。
本記事ではHyper-Vの自動バックアップ結果をSlackへ通知する方法についてご紹介します。
社内のVDIサーバー管理を担当しているのですが、バックアップ管理に時間がかかるので効率化を図りました。
実際に使用しているスクリプトと設定方法についても紹介しますので、ぜひ最後までお読みください。

 

この記事はこんな方にオススメ
  • Hyper-Vのバックアップ管理を効率化したい!
  • Hyper-Vの自動バックアップの設定方法を知りたい
  • Hyper-Vのバックアップ結果をSlackに通知したい
  • ps1ファイルをタスクスケジューラで設定する方法

 

できたもの

成果物はこちらです。
このように、バックアップファイル名サイズなどSlackチャンネルに通知することができます。

 

準備物

  1. PowerShell ISE(管理者権限で起動が必要)
  2. Web hook URLの取得
  3. 通知するチャンネルの作成
  4. バックアップの保存先パスの準備

 

スクリプトの目的と動作設計

まず、今回はHyper-V上の仮想マシン(vhdx)を指定したパスにエクスポートして、結果によりslackに通知するのが目標です。
今回はバックアップ処理の条件を以下のようにしました。

  • バックアップは三世代管理
  • 三世代前のバックアップはフォルダごと削除
  • バックアップ結果をSlackに通知
  • 作成・削除したバックアップファイルの名前やサイズもSlackに通知する

処理の全体像は以下の図のように考えました。

 

スクリプトの紹介

# Slack Webhook URL
$slackUrl = "https://hooks.slack.com/services/xxxxxxxxxxxxxx"

# 保存先のフルパス
$exportPath = "C:\Path\To\Backup\Folder"

# 保持するバックアップの世代数
$generationsToKeep = 3

# 保存先のフォルダが存在しない場合は作成
if (-not (Test-Path $exportPath)) {
    New-Item -Path $exportPath -ItemType Directory | Out-Null
}

# バックアップを作成する仮想マシンのリスト
$vmNameList = @("VM1", "VM2", "VM3")

foreach ($vmName in $vmNameList) {
    $exportFileName = "$vmName-$(Get-Date -Format 'yyyyMMdd-HHmmss').exp"
    $exportFilePath = Join-Path -Path $exportPath -ChildPath $exportFileName
    $exportFailed = $false

    # エクスポートを試行
    try {
        Export-VM -Name $vmName -Path $exportFilePath -Confirm:$false
    } catch {
        Write-Warning "仮想マシン $vmName のエクスポートが失敗しました。エラー: $_"
        $slackMessage = "仮想マシン $vmName のエクスポートが失敗しました。"
        $slackColor = "danger" # アタッチメント赤色
        $exportFailed = $true
    }

    if (-not $exportFailed) {
        # フォルダ配下の.vhdxファイルを取得して合計サイズを計算
        $vhdxFiles = Get-ChildItem -Path $exportFilePath -Filter *.vhdx -Recurse
        $exportFileSize = [math]::Round(($vhdxFiles | Measure-Object -Property Length -Sum).Sum / 1GB, 2)

        if ($exportFileSize -eq 0) {
            # バックアップが失敗した場合のメッセージを構築
            $slackMessage = "仮想マシン $vmName のエクスポートが失敗しました。手動で実行してください。"
            $slackColor = "danger" # アタッチメント赤色
            $exportFileName = "ファイルは作成されてません"
        } else {
            # バックアップが成功した場合のメッセージを構築
            $slackMessage = "仮想マシンのバックアップが完了しました。"
            $slackColor = "good" # アタッチメント緑色
        }

        # Slackにメッセージを送信
        $body = @{
            attachments = @(
                @{
                    text = $slackMessage
                    color = $slackColor
                    fallback = $slackMessage
                    fields = @(
                        @{
                            title = "バックアップファイル名"
                            value = $exportFileName
                            short = $true
                        },
                        @{
                            title = "サイズ(GB)"
                            value = $exportFileSize
                            short = $true
                        }
                    )
                }
            )
        } | ConvertTo-Json -Depth 4

        Invoke-RestMethod -Uri $slackUrl -Method POST -Body $body -ContentType 'application/json; charset=utf-8'

        # 古いバックアップファイルを削除
        $backupFiles = Get-ChildItem -Path $exportPath | Sort-Object LastWriteTime

        if ($backupFiles.Count -gt $generationsToKeep) {
            $backupFilesToDelete = $backupFiles | Select-Object -First ($backupFiles.Count - $generationsToKeep)

            foreach ($backupFileToDelete in $backupFilesToDelete) {
                # 削除するファイルの情報をSlackに通知するメッセージを作成
                $deletedFileName = $backupFileToDelete.Name
                $slackMessage = "古いバックアップファイルが削除されました。"
                $slackColor = "danger" # アタッチメント赤色

                # Slackにメッセージを送信
                $body = @{
                    attachments = @(
                        @{
                            text = $slackMessage
                            color = $slackColor
                            fallback = $slackMessage
                            fields = @(
                                @{
                                    title = "削除されたファイル名"
                                    value = $deletedFileName
                                    short = $true
                                }
                            )
                        }
                    )
                } | ConvertTo-Json -Depth 4
                Invoke-RestMethod -Uri $slackUrl -Method POST -Body $body -ContentType 'application/json; charset=utf-8'

                # ファイルを削除
                Remove-Item -Path $backupFileToDelete.FullName -Force
            }
        } else {
            # Slackに通知するメッセージを作成
            $slackMessage = "残すべきバックアップファイルが指定した世代数よりも少ないため、削除は行いません。"
            $slackColor = "warning" # アタッチメント黄色

            # Slackにメッセージを送信
            $body = @{
                attachments = @(
                    @{
                        text = $slackMessage
                        color = $slackColor
                        fallback = $slackMessage
                    }
                )
            } | ConvertTo-Json -Depth 4

            Invoke-RestMethod -Uri $slackUrl -Method POST -Body $body -ContentType 'application/json; charset=utf-8'
        }
    }
}

Github

$slackUrlと$vmNameListは適宜、変更してください。
$vmNameListは複数の仮想マシン名を指定可能です。
※ただしHyper-V側で同時にエクスポートできる数が限られているかもしれないので注意してください。

 

動作テスト

ps1ファイルを作成します。
新しいテキストファイルを作成・編集し、拡張子「.ps1」に変更して保存してください。
ファイルをPowerShell ISEで開き、上記スクリプトをコピペします。
適宜情報を書き換えたらデバッグ実行してください。

 

以下のエラーが発生した場合

Export-VM : このタスクを完了するために必要なアクセス許可がありません。このコンピューター 'SYS-DEV-VDISV' の承認ポリシーの管理者に問い合わせてください。
発生場所 C:\Users\sys_dev\Desktop\backup.ps1:18 文字:9
+         Export-VM -Name $vmName -Path $exportFilePath -Confirm:$false
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Export-VM], VirtualizationException
    + FullyQualifiedErrorId : Unspecified,Microsoft.HyperV.PowerShell.Commands.ExportVM

Export-VMコマンドが実行される際に必要なアクセス許可が不足しているので
以下のコマンドを実行して、実行ポリシーを変更してください。

Set-ExecutionPolicy RemoteSigned

 

タスクスケジューラで設定する方法

タスクの設定から新規設定を行ってください。

トリガーの設定

ここでは例として毎週月曜日と金曜日にバックアップを設定しています。

操作の編集

以下を指定します。

プログラム:C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe

引数:C:\ps1\powershell-vm-backup-slack.ps1 ※ファイルの配置先

 

最後に

いかがでしたでしょうか。
今回はSlackと連携したHyper-Vの仮想マシンの自動バックアップの紹介でした。
今後もSlack連携ツールを紹介予定なので、ぜひご覧ください。

 

この記事を書いた人
中木村
アイクラフト株式会社
顧客サービス部 iSTAFF24Gr.

顧客サービス部の中木村です。
未経験で入社し、システムエンジニアを1年半、現在はインフラエンジニアとして働いています。
いろんな技術について触れていこうと思っています。
趣味は散財です。最近はKailh Deep Sea Silent Box Switch Whaleというキースイッチを購入しました。
サイレントタクタイルっていいですよね。
よろしくお願いします!


ITツール紹介の関連記事