OpenAIを使ってチャットでvCenterの仮想マシンを管理してみる

この投稿は[vExperts Advent Calendar 2024](https://adventar.org/calendars/10310) の18日目の記事です。

# 概要
自宅で使っているvCenter上の仮想マシンを、なんとなくチャットを使って管理してみたいなと思って試してみます。
せっかくなので最近流行りの生成AIも使ってみます。
(作成物は突貫工事なところもあり、結構ガバガバなのはお許しください)

## 本記事で構成する環境
今回は以下のようなイメージで構成してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406495/455c8137-4e52-b256-dcbd-81ddeb41a37b.png)



まずvCenterを操作するためのAPI環境を用意しています。
Pythonではpyvmomiというものを使うことで、vCenterへ接続し仮想マシンの管理などを行うことができます。

続いて、ユーザーとチャットをするチャットボットを提供する環境を用意します。
今回はこのチャットボット環境内のバックエンド側で、OpenAIやvCenterのAPIとのやり取りを行うようにします。

## OpenAIとのやり取りの実装について
今回OpenAIとのやり取りとしては以下の2段階で構成しています。
1. APIへのリクエストの作成
    - ユーザーのチャットの内容から何がしたいかを汲み取り、APIに必要なパラメータなどを取り出す
1. ユーザーへ返す内容の作成
    - APIから取得した情報をわかりやすい内容に整形してチャットに返す

基本的には1でチャットの入力からAPIへのリクエストを生成して、2でAPIから返ってきた内容をチャットに返す感じとしています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406495/166a18a0-0297-5c4c-a4eb-7e9dee902f5e.png)


# 構築
## API側の準備
今回はお試し的な部分もあるため、簡易的に以下が実施できるAPIを用意しました。
- 仮想マシンの一覧を取得
- 指定した仮想マシンの詳細な情報を取得
- 指定した仮想マシンの電源管理 (パワーオン, OSシャットダウン, 再起動, パワーオフ)

vCenterの操作に関しては前述の通り、`pyVmomi`を用いて行っています。
SmartConnectという関数を用いて簡単にvCenterへの認証処理は実装できるので、ぜひPythonをお使いの方はお試しください。
https://docs.vmware.com/en/VMware-vSphere/8.0/vsphere-apis-sdks-getting-started/GUID-86B616CD-38B9-4795-917D-8211CB1C33EA.html

ちなみに少し悩んだところとして、仮想マシンのパワーオン/オフなどの操作に関しては、実行中と実行完了とでタスク状況が変わります。この点はエラー判定など実装時には少し考慮してあげる必要があると思います。
今回はタスクの実行が完了するまで待機をするような感じにしています。

なお、今回作成したソースは以下に格納しています。

https://github.com/murajo/vcenter_manage_api

試しにAPIを起動してリクエストを送った雰囲気は以下のような感じです。

***仮想マシンの一覧取得***
```bash
curl http://192.168.0.115:5000/vms

## 出力
{
	"vms": [
		{
			"cpu_count": 4,
			"memory_size": 40960,
			"name": "esxi-03",
			"power_state": "poweredOff"
		},
		{
			"cpu_count": 2,
			"memory_size": 8192,
			"name": "ubuntu-netbox",
			"power_state": "poweredOff"
		},
***以下省略***
	]
}
```

***仮想マシンの詳細取得***
```bash
curl http://192.168.0.115:5000/vm_details?vm_name=ubuntu-netbox

## 出力
{
	"vm_details": {
		"cpu_count": 2,
		"created_time": "Sat, 21 Sep 2024 06:42:27 GMT",
		"disk_sizes": [
			{
				"disk_label": "Hard disk 1",
				"size_gb": 200
			}
		],
		"ip_address": "192.168.0.113",
		"memory_size": 8192,
		"name": "ubuntu-netbox",
		"os": "Ubuntu Linux (64-bit)",
		"power_state": "poweredOn",
		"vmware_tools_status": "toolsOk"
	}
}
```

***仮想マシンのパワーオフ***
```bash
curl -X POST http://192.168.0.115:5000/vms/power \
     -H "Content-Type: application/json" \
     -d '{
           "vm_name": "ubuntu-netbox",
           "operation": "poweroff"
         }'
## 出力
{"message":"Operation 'poweroff' executed successfully for VM 'ubuntu-netbox'."}
```

一応こんな感じで利用できるようにできたため、起動しておいて次にいきます。


## チャットボット側の準備
続いてチャットボット側の準備をしていきます。

まず前述の通り今回はOpenAIを2段階挟むようにしています。
1つ目は先ほど用意したvCenterのAPIを叩くための内容を用意してもらいます。

以下のようなプロンプトでAPI情報を渡して必要なリクエスト内容を用意してもらいます。
※まだプロンプトの知見がないため、今回はChatGPTくんに用意してもらいました
```python
    api_description = """
    You are an assistant for managing virtual machines via a vCenter API.
    The API supports the following actions:
    - "list_vms": Lists all virtual machines. No parameters are required.
    - "get_vm_details": Gets details of a specific virtual machine. Required parameter: vm_name (string).
    - "manage_power": Manages the power state of a virtual machine. Required parameters:
      - vm_name (string): Name of the virtual machine.
      - operation (string): One of "start", "shutdown", "restart", or "poweroff".
    Respond with a Python dictionary that specifies the action and its parameters.
    """
```

2つ目はAPIから取得した情報をユーザーに返すための内容を準備してもらう内容です。
※こちらも同様にChatGPTくんに用意してもらっています
```python
    enhancement_prompt = """
    You are an assistant enhancing responses for a virtual machine management system.
    Based on the following details, generate a clear and friendly summary:
    - User Input: {user_input}
    - Parsed Command: {parsed_command}
    - vCenter API Response: {vcenter_response}
    Ensure the response is concise and helpful for the user.
    """.format(
        user_input=original_input,
        parsed_command=json.dumps(parsed_command, indent=2),
        vcenter_response=json.dumps(vcenter_response, indent=2)
    )
```

最後にUI側として今回はGradioを用いています。
生成AI関連ではかなり利用されているもので、簡易的に利用できるのでおすすめです。

https://www.gradio.app/

チャットの画面は以下のような感じです。
ここにどんどんチャットした内容がたまっていくイメージです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406495/fbf99300-535d-867d-76e9-a70e967dec56.png)


ここまでの内容をもとにあとは処理を書いて作成を行っておきます。
こちらで作成したソースは以下に格納しています。

https://github.com/murajo/vcenter_manage_chat

# 動作確認
それでは最後にここまで作成した内容をそれぞれ実行した状態でチャットを送って動作確認をしてみます。

まず何ができるのかの質問と仮想マシンの一覧取得を依頼した際は以下のような感じでした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406495/9dbbffdc-32c1-f71e-9754-1c34d8f8386b.png)

続いて指定した仮想マシンの詳細取得、パワーオフ、パワーオフ後の詳細取得をした様子は以下です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406495/c922520c-0153-1c05-8f2e-01d02a9d2d00.png)

問題なく動作をしてそうです。
一応vSphere Client上でも確認して、パワーオフのタスクもしっかり実行されていることが確認できています。

# まとめ
今回は簡易的ですが、OpenAIを用いたチャットでvCenterの仮想マシンを管理してみました。
(まだ実装が甘いせいか、全く同じ内容で仮想マシン名を指定しているのに、仮想マシン名がないと無視されることがありました)

OpenAIやpyvmomiは初めて触ったので結構勉強になりました。
また試す機会があった際は、プロンプトも自分で作成できるようにして、もう少し柔軟に作れればと思います。