Kitchen driver for oVirt

[SRA Advent Calendar](https://qiita.com/advent-calendar/2020/sra)の2日目です。
ネットワークシステムサービス第１事業部の ふじまき です。

[Test Kitchen](https://kitchen.ci/)で[oVirt](https://ovirt.org/)を使う場合、[Vagrant](https://www.vagrantup.com/)と[VagrantのoVirt用のモジュール](https://github.com/myoung34/vagrant-ovirt4)を追加して、kitchenドライバーはVagrantを使えばよいのですが、LinuxサーバにVagrant入れたくない（偏見）ので[kitchen-ovirt](https://github.com/uskf/kitchen-ovirt)を作ってみました。

なお、今のところWindowsには対応してません。:slight_smile:

# kitchen-ovirtの使い方
[ここ](https://github.com/uskf/kitchen-ovirt/blob/main/README.md)の詳細日本語版:grinning:

## インストール
ソースをビルドするか[gemをダウンロード](https://github.com/uskf?tab=packages&repo_name=kitchen-ovirt)して、インストールします。

```
$ gem install /path/to/kitchen-ovirt-0.0.1.gem
```
CentOS7系の場合、Software CollectionsでRuby2.5以上をインストール、有効にしておく必要があります。（Ruby2.4でもovirt-engine-sdkの4.3.1を事前に入れておけばOK）

## 設定

|パラメータ|必須？|デフォルト値|説明|例|
|:--------|:-----|:----------|:---|:--|
|engine_url|yes|なし|oVirtのAPIのURL|https://ovirt.example.com/ovirt-engine/api|
|ovirt_username|no|admin@internal|APIをリクエストする時のユーザー名|kitchen@internal|
|ovirt_password|yes|なし|ovirt_usernameで指定したユーザーのパスワード|kitchen-password|
|vm_net_interface|yes|なし|仮想マシン内でIPをアサインするインターフェイス名|eth0|
|vm_net_address|yes|なし|仮想マシンに設定するIPアドレス|192.168.1.2|
|vm_net_netmask|yes|なし|仮想マシンに設定するネットマスク。IPv6の場合はプリフィックス|255.255.255.0 , 64|
|datacenter|no|Default|使用するoVirtのデータセンター名|TokyoDataCenter|
|cluster|no|Default|使用するoVirtのクラスター名|Cluster123|
|template|no|.kitchen.ymlのplatform名|使用するテンプレート名。デフォルト以外を指定したい場合のみ|centos-7-v1|
|vm_name|no|tk-"suite名"-"platform名"-"ランダム文字"|oVirt上の仮想マシン名|kitchen-test-123|
|vm_username|no|root|仮想マシンにログインする管理者アカウント||
|vm_password|no|root123|仮想マシンの管理者アカウントに設定するパスワード||
|vm_description|no|Test Kitchen VM|oVirt上の仮想マシンにつける説明||
|vm_net_ipver|no|IPv4|仮想マシンで使用するIPプロトコルバージョン。IPv4 or IPv6を指定||
|dns_servers|no|なし|仮想マシンで使用するDNSサーバ。複数の場合はカンマ区切り|"192.168.1.1,192.168.2.1"|
|wait_after_up|no|10|仮想マシン起動後のウェイト（秒）||

wait_after_upはoVirtが仮想マシン起動を認識してもcloud-init諸々が完了してない事があるので念のためのウェイト。

## テンプレート仮想マシン作成
基本は以下の流れ

1. oVirt上でゲストを作成
1. 作成したゲストにcloud-initをインストール
1. その他必要な設定諸々をする（後述）
1. シャットダウンしてテンプレート作成メニューで「テンプレートをシーリングする」のチェックを付けてテンプレート作成

私の場合chef(cinc)を使っており、毎回インストールするのは無駄なのでテンプレート仮想マシンにインストールしています。

### CentOS 7,8
必須のカスタマイズは特になし。なおCentOS6（2020年11月30日でEoL）標準のcloud-initはoVirt 4.4では動きませんでした。

### Ubuntu Server 18.04 / 20.04共通
Ubuntu 16.04は未確認。

+ rootユーザーにパスワードを設定。
+ openssh-serverを入れる。
+ rootユーザーのsshログインを許可＆ログイン確認しておく。

手元の環境では仮想マシンのNICに固定IPをアサインし、その設定消してからテンプレートにすると何故かネットワークが自動起動しない（cloud-initで設定は更新されていて、netplan applyするとupする。謎）のでDHCP有効なままテンプレート化しています。

### Ubuntu Server 20.04
上記に加えて

+ fstabのデバイスがuuid指定になっている場合、通常のデバイス名に直す
+ 以下のcloud-init設定削除

```
$ sudo rm /etc/cloud/cloud.cfg.d/subiquity-disable-cloudinit-networking.cfg
$ sudo rm /etc/cloud/cloud.cfg.d/99-installer.cfg
```
+ oVirtが使うDatasourceのConfigDriveを有効にする設定ファイルを作成

```
$ echo 'datasource_list: [ ConfigDrive ]' | sudo tee /etc/cloud/cloud.cfg.d/99-datasource.cfg
```

# kitchen driverの書き方
一応、プログラミングネタとしてちょっとだけ。
以前は[kitchen driver create](https://docs.chef.io/workstation/ctl_kitchen/#kitchen-driver-create)でひな形を作れたらしいですが、[機能が削除](https://github.com/test-kitchen/test-kitchen/pull/1290)されているので、kitchen-ovirtの作成ではgemでひな形作って構成は既存ドライバを真似ています。

作り方のドキュメントが無いのですが、大体以下のような流れで作る事が出来ます。

1. Kitchen::Driver::Baseを継承して新規ドライバのクラスを作成
1. createメソッドの中で[SDK](https://github.com/oVirt/ovirt-engine-sdk-ruby)を使って新規仮想マシンを作成し、引数で受け取ったハッシュ("state")の:server_nameに仮想マシン名、:hostnameにIPアドレス、:usernameにsshログインユーザー名、:passwordにsshログインパスワードを格納
1. destroyメソッドの中で作成した仮想マシンを破棄、stateをクリア
1. .kitchen.ymlに書くドライバのコンフィグはrequired_config/default_configで宣言



# Tips: chef-workstationでprovisionerにcincを使う
Chefの公式パッケージは2019年4月頃に有償化され、コミュニティビルドのパッケージを配布する[CINC](https://cinc.sh/)が立ち上がりました。
が、cinc-workstationパッケージは現在pre-releaseとなっており有償化前のchef-workstationを使っている環境も多いと思います。（私含む）

chef-workstation環境の.kitchen.ymlのprovisionerで

```
install_strategy: once
product_name: cinc
```
と書いてもチェックで弾かれて動きません。

このチェックはchef-workstationパッケージに含まれているmixlib-installというgemの中で[静的に定義されている](https://github.com/chef/mixlib-install/blob/v3.11.22/lib/mixlib/install/product.rb#L234)ので、以下4行追加すると動くようになります。

```
  product "cinc" do
    product_name "Cinc Client"
    package_name "cinc"
  end
```
当たり前ですが、cinc-workstationでは最初から入っているので修正不要です。