pyvmomiでゲストOSのプロセス情報取得やコマンドを実行して検証してみた

VMwareのWeb APIでは、Web APIからVMware toolsを経由してゲストOSの操作が可能です。
ゲストOSを操作できるメソッドを提供しているオブジェクトは以下の通りです。

# 操作可能なオブジェクト

[https://goo.gl/oWfeHL](https://goo.gl/oWfeHL)

| オブジェクト名              | 説明                                                                       |
|:----------------------------|:---------------------------------------------------------------------------|
| aliasManager                | シングルサイオンのメソッドを提供するオブジェクト                           |
| authManager                 | ゲスト認証操作のメソッドを提供するオブジェクト                             |
| fileManager                 | ゲストOSのファイル・ディレクトリを操作できるメソッドを提供するオブジェクト |
| guestWindowsRegistryManager | Windowsレジストリを操作できるメソッドを提供するオブジェクト                |
| processManager              | ゲストOSのプロセスやコマンドが実行できるメソッドを提供するオブジェクト     |

ここでは `processManager` を使ってプロセス一覧取得や起動及びコマンドの実行をしてみます。

# 環境

| 項目                                         | バージョン           |
|:---------------------------------------------|:---------------------|
| vCenter                                      | 6.5.0 ビルド 4602587 |
| [pyvmomi](https://github.com/vmware/pyvmomi) | 6.5.0.2017.5.post1   |
| python                                       | 3.4.5                |

# 検証方針

* ゲストOS(CentOS7)のプロセス一覧を取得してみる
* ゲストOS(CentOS7)のサービスを起動してみる
* ゲストOS(CentOS7)でコマンドを実行してみる

# 検証

## ゲストOSのプロセス一覧取得

ここでは、ゲストOSのプロセス一覧を取得してみます。

### ソース

https://gist.github.com/sky-joker/58c63b5f48201a9aeb56a537a5a91720

### 説明

`ListProcessesInGuest` メソッドでは、仮想マシンMOBと認証情報を引数として渡すと戻り値としてゲストOSのプロセス一覧オブジェクト(GuestProcessInfo)が取得できます。

### 実行

実行に問題がなければ `pid: プロセス名` が一覧で表示されます。

```bash
$ ./get-guestos-processes.py -vc vcenter01.local -tvm centos -gu root
vCenter Password:
Guest OS Password:
1: /usr/lib/systemd/systemd --switched-root --system --deserialize 21
2: kthreadd
3: ksoftirqd/0
4: kworker/0:0
(snip)
```

エージェントレスでのプロセス監視などで役に立ちます :-)

## ゲストOSのサービスを起動

ここでは、httpdを起動してみたいと思います。

### ソース

https://gist.github.com/sky-joker/59c6dc6573472ed9a49a408b38fb4e45

### 説明

`GuestProgramSpec` データオブジェクトを生成し、以下のプロパティを設定しています。

| プロパティ名 | 説明                         |
|:-------------|:-----------------------------|
| arguments    | 実行するプログラムに渡す引数 |
| programPath  | 実行するプログラムのフルパス |

`GuestProgramSpec` データオブジェクトを `StartProgramInGuest` メソッドに渡すと問題がなければ戻り値として実行したコマンドの `pid` が取得できます。

ここでは、httpdをsystemctl経由から起動しています。

### 実行

実行に問題がなければ実行したコマンドの `pid` が表示されます。

```bash
$ ./start-guestos-service.py -vc vcenter01.local -tvm centos -gu root
vCenter Password:
Guest OS Password:
2394
```

実行したゲストOSで確認してみます。

```bash
[root@localhost ~]# pgrep httpd
2395
2396
2397
2398
2399
2400
```

API上で取得したpidはsystemctlで実行した時のpidなので、実際に動作しているpidではありません。
この場合、ListProcessesInGuestも一緒に使って問題なく起動したか？のチェック処理を入れるなどの対処が必要です。

## ゲストOSでコマンドを実行

`StartProgramInGuest` を使えば任意のコマンドが実行できることがわかったのでプロセスを起動する以外にちょっと試して見ました。
ここでは `echo` を使ってファイルを作成してみたいと思います。

### ソース

https://gist.github.com/sky-joker/294f86b79a84406bb3afa03b152258d0

### 説明

`TEST` という文字列を `output.txt` に吐き出してみます。

### 実行

実行してみます。

```bash
$ ./exec-guestos-cmd.py -vc vcenter01.local -tvm centos -gu root
vCenter Password:
Guest OS Password:
2422
```

ゲストOSで出力されたファイルを確認します。

```bash
[root@localhost ~]# cat /root/output.txt
TEST
```

標準での出力先は、プログラムを実行したユーザーのホームディレクトリになります。
そのため、出力先のファイルを絶対パスで記述するか [workingDirectory](https://goo.gl/WouyT8) プロパティでコマンドを実行するディレクトリパスを指定します。

`StartProgramInGuest` を使うことで任意のコマンドを実行出来ることはわかりましたが、いかんせん戻り値がpidなので実行したプログラムの戻り値などを取得する場合には使えなさそうです。(lsで結果を取得とか)
そういうのは `VIX` とかだと出来るのかな。
ちなみに `TerminateProcessInGuest` メソッドを使うとプロセスを停止させることができます。