Flatcar Container LinuxのOEM領域を更新してvmtoolsd.serviceのエラーを解決する

VMwareのOEM機能が搭載されたFlatcar Container Linuxがv2605.5.0にアップグレードされると、
OEM領域が古いままなためにライブラリのバージョンが一致せず、`vmtoolsd.service` が起動に失敗する。

```connsole
# systemctl status vmtoolsd.service
● vmtoolsd.service - VMware Tools Agent
     Loaded: loaded (/etc/systemd/system/vmtoolsd.service; enabled; vendor preset: enabled)
    Drop-In: /etc/systemd/system/vmtoolsd.service.d
             └─90-tmpfiles-cve-2015-4191.conf
     Active: failed (Result: exit-code) since Fri 2020-09-25 14:35:02 JST; 1s ago
       Docs: https://github.com/vmware/open-vm-tools
    Process: 60187 ExecStartPre=/usr/bin/ln -sfT /usr/share/oem/vmware-tools /etc/vmware-tools (code=exited, status=0/SUCCESS)
    Process: 60189 ExecStart=/usr/share/oem/bin/vmtoolsd (code=exited, status=127)
   Main PID: 60189 (code=exited, status=127)

Sep 25 14:35:02 flatcar systemd[1]: Starting VMware Tools Agent...
Sep 25 14:35:02 flatcar systemd[1]: Started VMware Tools Agent.
Sep 25 14:35:02 flatcar vmtoolsd[60189]: /usr/share/oem/bin/vmtoolsd: error while loading shared libraries: libssl.so.1.0.0: cannot open shared object file: No such file or directory
Sep 25 14:35:02 flatcar systemd[1]: vmtoolsd.service: Main process exited, code=exited, status=127/n/a
Sep 25 14:35:02 flatcar systemd[1]: vmtoolsd.service: Failed with result 'exit-code'.
```

この問題を解決するには、`/usr/share/oem`を更新する必要があるが、当該ディレクトリは独立のパーティション`/dev/sda6`となっており、
FlatcarのOS更新機能では当該パーティションは更新されない問題がある。

本稿では、公式のインストールディスクイメージからoemパーティションを取得して、現用中のFlatcar Container LinuxのOEM領域を更新する手順を説明する。

## TL;DR

- イメージファイルのパーティション6がoem領域なので、パーティション6を`/dev/sda6`に書き込む。
- インストール先ディスクが`sda`でない場合は読み替えること。
- OEM typeが`vmware_raw`でない場合は読み替えること。
- 何度も同じ作業を繰り返すときは、[OEM領域をイメージ化](#オプションoem領域をイメージ化する)してしまい、手順を簡略化する。

```shell
systemctl stop vmtoolsd.service
source /etc/os-release
source /usr/share/flatcar/update.conf
curl -O https://$GROUP.release.flatcar-linux.net/amd64-usr/$VERSION/flatcar_production_vmware_raw_image.bin.bz2
bunzip2 flatcar_production_vmware_raw_image.bin.bz2
mount | grep /usr/share/oem
sudo losetup --show -P /dev/loop0 flatcar_production_vmware_raw_image.bin
sudo dd if=/dev/loop0p6 of=/dev/sda6 bs=1M
sudo mount -o remount /usr/share/oem
sudo losetup -vd /dev/loop0
sudo losetup -l
diff /usr/share/oem/units/vmtoolsd.service /etc/systemd/system/vmtoolsd.service \
|| sudo cp -v /usr/share/oem/units/vmtoolsd.service /etc/systemd/system/vmtoolsd.service \
&& sudo systemctl daemon-reload
sudo systemctl restart vmtoolsd.service
sudo systemctl status vmtoolsd.service
rm flatcar_production_vmware_raw_image.bin.bz2
```

## `vmtoolsd.service`を止める
```shell
systemctl stop vmtoolsd.service
```

## ディスクイメージの取得

同じバージョンのイメージファイルを取得する。OEM typeが`vmware_raw`でない場合は、読み替えること。

```shell
source /etc/os-release
source /usr/share/flatcar/update.conf
curl -O https://$GROUP.release.flatcar-linux.net/amd64-usr/$VERSION/flatcar_production_vmware_raw_image.bin.bz2
bunzip2 flatcar_production_vmware_raw_image.bin.bz2
```

単に最新を使用したい場合は、`current`を使用する。

```shell
curl -O https://stable.release.flatcar-linux.net/amd64-usr/current/flatcar_production_vmware_raw_image.bin.bz2
bunzip2 flatcar_production_vmware_raw_image.bin.bz2
```

## oemパーティションを確認する

binファイルをfdiskすると、パーティション構成が判明する。これを、今エラーが出ているFlatcarと比較してパーティション番号を特定する。6番目とわかる

```shell
sudo mount | grep /usr/share/oem
sudo fdisk -l /dev/sda
sudo fdisk -l -u flatcar_production_vmware_raw_image.bin
```

```console
flatcar ~ # mount | grep /usr/share/oem
/dev/sda6 on /usr/share/oem type ext4 (rw,nodev,relatime,seclabel)

flatcar ~ # fdisk -l /dev/sda
Disk /dev/sda: 16 GiB, 17179869184 bytes, 33554432 sectors
Disk model: Virtual disk
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: A8495FA4-32CD-41AC-8448-CD234771C249

Device       Start      End  Sectors  Size Type
/dev/sda1     4096   266239   262144  128M EFI System
/dev/sda2   266240   270335     4096    2M BIOS boot
/dev/sda3   270336  2367487  2097152    1G unknown
/dev/sda4  2367488  4464639  2097152    1G unknown
/dev/sda6  4464640  4726783   262144  128M Linux filesystem
/dev/sda7  4726784  4857855   131072   64M unknown
/dev/sda9  4857856 33554398 28696543 13.7G unknown

flatcar ~ # fdisk -l -u flatcar_production_vmware_raw_image.bin
Disk flatcar_production_vmware_raw_image.bin: 4.4 GiB, 4756340736 bytes, 9289728 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: 00000000-0000-0000-0000-000000000001

Device                                     Start     End Sectors  Size Type
flatcar_production_vmware_raw_image.bin1    4096  266239  262144  128M EFI System
flatcar_production_vmware_raw_image.bin2  266240  270335    4096    2M BIOS boot
flatcar_production_vmware_raw_image.bin3  270336 2367487 2097152    1G unknown
flatcar_production_vmware_raw_image.bin4 2367488 4464639 2097152    1G unknown
flatcar_production_vmware_raw_image.bin6 4464640 4726783  262144  128M Linux filesystem
flatcar_production_vmware_raw_image.bin7 4726784 4857855  131072   64M unknown
flatcar_production_vmware_raw_image.bin9 4857856 9285631 4427776  2.1G unknown
```


## イメージファイルをloop0にアタッチする
複数パーティションが含まれるため、`-P`を使用する。

```shell
sudo losetup --show -P /dev/loop0 flatcar_production_vmware_raw_image.bin
```

`losetup`以外に`kpartx`や`partx`を使う手もある

## マウントして差分を確認する

- コンフィグファイルなどが存在しないかなど、上書きして問題がないことを確認する
- 古いバージョンでは、`cloud-config.yml`が存在していた。
- `2605.5.0`ではイメージファイルの内容(ここでは`/mnt/oem`)と実際にデプロイFlatcar Container Linux 2605.5.0の`/usr/share/oem`には差分がない

```shell
sudo mkdir /mnt/oem
sudo mount -t ext4 /dev/loop0p6 /mnt/oem
sudo diff -ur /mnt/oem /usr/share/oem/
sudo umount /mnt/oem
sudo rmdir /mnt/oem
```

## 上書きする
`dd`でパーティションごと上書きする。不安な場合は、`rsync`等を使用すれば良い。

```shell
sudo dd if=/dev/loop0p6 of=/dev/sda6 bs=1M
sudo mount -o remount /usr/share/oem
```

だめなときは、マウントし直す。

```shell
sudo umount /usr/share/oem
sudo mount -t ext4 -o ro,nodev,relatime,seclabel /dev/sda6 /usr/share/oem
```

## loop0をデタッチする
```shell
sudo losetup -vd /dev/loop0
sudo losetup -l
```

## ファイルが同じか確認する
`vmtoolsd.service`の定義が更新されていないか確認し、更新されていれば上書きする。

```shell
ls -la /etc/systemd/system/vmtoolsd.service
diff /usr/share/oem/units/vmtoolsd.service /etc/systemd/system/vmtoolsd.service \
|| sudo cp -v /usr/share/oem/units/vmtoolsd.service /etc/systemd/system/vmtoolsd.service \
&& sudo systemctl daemon-reload
```

## `vmtoolsd.service`を起動する

```shell
sudo systemctl restart vmtoolsd.service
sudo systemctl status vmtoolsd.service
```


## (オプション)oem領域をイメージ化する

Flatcar Container LinuxのVMを多数抱えている場合、毎回ディスク取得すると大変なので、イメージ化してしまう。CPUアーキテクチャ、バージョン、チャネル等の不一致には注意すること。

```shell
source /etc/os-release
source /usr/share/flatcar/update.conf
curl -O https://$GROUP.release.flatcar-linux.net/amd64-usr/$VERSION/flatcar_production_vmware_raw_image.bin.bz2
bunzip2 flatcar_production_vmware_raw_image.bin.bz2
sudo losetup --show -P /dev/loop0 flatcar_production_vmware_raw_image.bin
sudo dd if=/dev/loop0p6 of=flatcar_vmware_raw_oem_part_image.bin bs=1M
sudo losetup -vd /dev/loop0
sudo losetup -l
rm -v flatcar_production_vmware_raw_image.bin
```

このイメージがあれば、領域置き換えは下記となる。

```shell
sudo systemctl stop vmtoolsd.service
sudo dd if=flatcar_vmware_raw_oem_part_image.bin of=/dev/sda6 bs=1M
sudo mount -o remount /usr/share/oem
cat /usr/share/oem/units/vmtoolsd.service
sudo umount /usr/share/oem
sudo mount -t ext4 -o ro,nodev,relatime,seclabel /dev/sda6 /usr/share/oem
cat /usr/share/oem/units/vmtoolsd.service
diff /usr/share/oem/units/vmtoolsd.service /etc/systemd/system/vmtoolsd.service
sudo systemctl restart vmtoolsd.service
sudo systemctl status vmtoolsd.service
```



## 参考
- After upgrading a CoreOS virutal machine, the open-vm-tools in /usr/share/oem/ is not upgraded (2142569) https://kb.vmware.com/s/article/2142569
- Update Vendor tools on existing installations (e.g. VMWare open-vm.tools) · Issue #21 · flatcar-linux/Flatcar https://github.com/flatcar-linux/Flatcar/issues/21
- vmtoolsd misses libssl.so.1.0.0 · Issue #192 · flatcar-linux/Flatcar https://github.com/flatcar-linux/Flatcar/issues/192