StupidDog's blog

IT関連の手近な所で、疑問に思った事を調べた記録

「Vagrantで、apt-get upgradeを含んだプロビジョニングで発生するエラーについて」

はじめに

VagrantでUbuntu14.04 Serverの環境構築を行っていたところ、今まで成功していたプロビジョニングのコードが失敗するようになりました。
調査の結果、原因と解決方法を以下にまとめます。

作業環境

ホストOS

Ubuntu14.04 Desktop 64bit
Vagrant 1.6.3
VirtualBox 4.3.12.r93733

ゲストOS

Ubuntu14.04 Server 64bit

概要

  1. プロビジョニングが失敗した時の状態
  2. 原因の調査
  3. 解決方法の調査
  4. 解決方法
  5. まとめ

1.プロビジョニングが失敗した時の状態

環境構築に使用したコード

Vagrantfile
# -*- mode: ruby -*-
# vi: set ft=ruby :

VAGRANTFILE_API_VERSION = "2"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.box = "ubuntu1404"

  config.vm.provision :shell, inline:<<-EOS
    apt-get upgrade
    apt-get -y upgrade
  EOS
end

失敗した時の出力(抜粋)

...
==> default: Package configuration┌──────────────────────────┤ Configuring grub-pc ├──────────────────────────┐│││ The GRUB boot loader was previously installed to a disk that is no││ longer present, or whose unique identifier has changed for some reason.   ││ It is important to make sure that the installed GRUB core image stays in  ││ sync with GRUB modules and grub.cfg. Please check again to make sure││ that GRUB is written to the appropriate boot devices.││││ If you're unsure which drive is designated as boot drive by your BIOS,    ││ it is often a good idea to install GRUB to all of them.││││ Note: it is possible to install GRUB to partition boot records as well,   ││ and some appropriate partitions are offered here. However, this forces    ││ GRUB to use the blocklist mechanism, which makes it less reliable, and    ││ therefore is not recommended.││││<Ok>│││└───────────────────────────────────────────────────────────────────────────┘
==> default: Failed to open terminal.64 (1:5.14-2ubuntu3.1) ...
==> default: debconf: whiptail output the above errors, giving up!
==> default: dpkg: error processing package grub-pc (--configure):
==> default:  subprocess installed post-installation script returned error exit status 255
...

2.原因の調査

失敗時の出力からプロビジョニング中にgrub-pcの設定画面を開こうとして失敗していることが分かります。
プロビジョニング中に入力を求める設定画面は使用できません。
この設定画面を回避する必要があります。

何故、grub-pcパッケージの設定画面が開くようになったか?
apt-get upgradeで更新対象になっているので、BOXファイル作成時よりgrub-pcのバージョンが上がった事が推測できます。
プロビジョニングをせずに、環境を構築しSSHで接続後、grub-pcパッケージのバージョンを確認します。

vagrant@ubuntu-1404:~$ sudo dpkg --list | grep grub
ii  grub-common                         2.02~beta2-9                  amd64        GRand Unified Bootloader (common files)
ii  grub-gfxpayload-lists               0.6                           amd64        GRUB gfxpayload blacklist
ii  grub-pc                             2.02~beta2-9                  amd64        GRand Unified Bootloader, version 2 (PC/BIOS version)
ii  grub-pc-bin                         2.02~beta2-9                  amd64        GRand Unified Bootloader, version 2 (PC/BIOS binaries)
ii  grub2-common                        2.02~beta2-9                  amd64        GRand Unified Bootloader (common files for version 2)

「2.02-beta2-9」である事が分かります。

次に手入力で、apt-get upgradeを行います。
設定画面が表示されるのですが、何故かGRUBのインストール先デバイスの問い合せです(原因は後ほど)。
構築している仮想環境のHDDは1つなので、/dev/sda (42949 MB: VBOX_HARDDISK)にチェックを入れてOKとします。


ちょっと小さいですが whiptail を使用した画面が表示されることの確認です。

apt-get upgrade後の、grub-pcパッケージのバージョンを確認します。

vagrant@ubuntu-1404:~$ sudo dpkg --list | grep grub
sudo dpkg --list | greo grub
ii  grub-common                         2.02~beta2-9ubuntu1           amd64        GRand Unified Bootloader (common files)
ii  grub-gfxpayload-lists               0.6                           amd64        GRUB gfxpayload blacklist
ii  grub-pc                             2.02~beta2-9ubuntu1           amd64        GRand Unified Bootloader, version 2 (PC/BIOS version)
ii  grub-pc-bin                         2.02~beta2-9ubuntu1           amd64        GRand Unified Bootloader, version 2 (PC/BIOS binaries)
ii  grub2-common                        2.02~beta2-9ubuntu1           amd64        GRand Unified Bootloader (common files for version 2)

「2.02-beta2-9ubuntu1」にバージョンが変わっています。

「UbuntuUpdates.org」で確認すると「2.02-beta2-9」をベースにしてパッチが当たってるようです。
http://www.ubuntuupdates.org/package/core/trusty/universe/updates/grub2

grub-pcのバージョンが上がったことは確認できました。

3.解決方法の調査

この設定画面を非表示で/dev/sdaが選択される方法を考えます。
環境変数 DEBIAN_FRONTEND に noninteractive を設定後、デフォルト値を指定してupgradeする方法を考えましが、今回の問題を解決することはできませんでした。

別の方法を調べていたところ、debianには自動化のための設定値をテキストファイルではなくデータベースで与える仕組みがあることが分かりました。
その仕組みに対応しているパッケージでは、データベースから設定値を取得するそうです。
データベースを操作するコマンドとして、debconf系のコマンドが用意されています。

設定と参照に使用するコマンドの例

設定(パッケージ/項目単位)
$ echo "set grub-pc/install_devices /dev/sda" | debconf-communicate

参照(パッケージ/項目単位)
$ echo "get grub-pc/install_devices /dev/sda" | debconf-communicate

参照(パッケージ単位)
$ debconf-show grub-pc

grub-pcパッケージは、この仕組みに対応しているようです。
検証のために、環境を再構築して upgrade 実行前に戻します。

upgrade 前にgrub-pcの設定値を確認します。

vagrant@ubuntu-1404:~$ sudo debconf-show grub-pc
  grub2/linux_cmdline_default: quiet splash
  grub-pc/kopt_extracted: false
  grub-pc/mixed_legacy_and_grub2: true
  grub-pc/postrm_purge_boot_grub: false
  grub-pc/install_devices_empty: false
  grub-pc/install_devices_disks_changed:
  grub2/linux_cmdline:
  grub-pc/hidden_timeout: true
  grub2/kfreebsd_cmdline:
  grub-pc/disk_description:
  grub2/kfreebsd_cmdline_default: quiet splash
* grub-pc/install_devices: /dev/disk/by-id/ata-VBOX_HARDDISK_VB36ceb79a-609a9c78
  grub-pc/timeout: 10
  grub-pc/chainload_from_menu.lst: true
  grub-pc/install_devices_failed_upgrade: true
  grub-pc/partition_description:
  grub2/device_map_regenerated:
  grub-pc/install_devices_failed: false

これから設定する予定の install_devices に値が設定されていますが、/dev/sda ではなく/dev/disk/by-id 以下のパスになってます。
ちょっと、/dev/disk/by-id 以下を覗いてみます。

vagrant@ubuntu-1404:~$ ll /dev/disk/by-id
total 0
drwxr-xr-x 2 root root 200 Aug  8 13:58 ./
drwxr-xr-x 4 root root  80 Aug  8 13:58 ../
lrwxrwxrwx 1 root root   9 Aug  8 13:58 ata-VBOX_HARDDISK_VBe49e1f29-745fffe8 -> ../../sda
lrwxrwxrwx 1 root root  10 Aug  8 13:58 ata-VBOX_HARDDISK_VBe49e1f29-745fffe8-part1 -> ../../sda1
lrwxrwxrwx 1 root root  10 Aug  8 13:58 ata-VBOX_HARDDISK_VBe49e1f29-745fffe8-part2 -> ../../sda2
lrwxrwxrwx 1 root root  10 Aug  8 13:58 ata-VBOX_HARDDISK_VBe49e1f29-745fffe8-part5 -> ../../sda5
lrwxrwxrwx 1 root root  10 Aug  8 13:59 dm-name-ubuntu--1404--vg-root -> ../../dm-0
lrwxrwxrwx 1 root root  10 Aug  8 13:59 dm-name-ubuntu--1404--vg-swap_1 -> ../../dm-1
lrwxrwxrwx 1 root root  10 Aug  8 13:59 dm-uuid-LVM-RCIg1EIc6CV1RnqFdUzmRFCB3TyX01FBj9TLfcBDKgLxCDXaac9gZ9FnuetB2xmM -> ../../dm-0
lrwxrwxrwx 1 root root  10 Aug  8 13:59 dm-uuid-LVM-RCIg1EIc6CV1RnqFdUzmRFCB3TyX01FBnmTl3brIQysPjdZwUTwfqdwChucxk6jW -> ../../dm-1
vagrant@ubuntu-1404:~$ 

現在の設定値に相当するパスが存在していません。
結論から言うと、BOXファイルから環境を構築する度に VBOX_HARDDISK_VB~のid部分が変わります。
データベース上の設定値は更新されません。
よって、実在しないパスとなり、grub-pcパッケージはインストール先を問い合せる画面を表示することになります。
環境変数 DEBIAN_FRONTEND でも表示を抑えられなかった理由はこれです。

では、手入力により解決できるか検証します。

設定値の登録と確認

debconf-コマンドの実行には root権限が必要となります。
プロビジョニング中はコマンドが root権限で実行されますが手入力なので sudo が必要です。

vagrant@ubuntu-1404:~$ sudo sh -c 'echo "set grub-pc/install_devices /dev/sda" | debconf-communicate'
0 value set
vagrant@ubuntu-1404:~$ sudo sh -c 'echo "get grub-pc/install_devices" | debconf-communicate'
0 /dev/sda
vagrant@ubuntu-1404:~$ 
upgradeの実行
vagrant@ubuntu-1404:~$ sudo apt-get -y upgrade

...
Setting up grub-common (2.02~beta2-9ubuntu1) ...
Setting up grub2-common (2.02~beta2-9ubuntu1) ...
Setting up grub-pc-bin (2.02~beta2-9ubuntu1) ...
Setting up grub-pc (2.02~beta2-9ubuntu1) ...
Installing for i386-pc platform.
Installation finished. No error reported.
Generating grub configuration file ...
Warning: Setting GRUB_TIMEOUT to a non-zero value when GRUB_HIDDEN_TIMEOUT is set is no longer supported.
Found linux image: /boot/vmlinuz-3.13.0-24-generic
Found initrd image: /boot/initrd.img-3.13.0-24-generic
done
Setting up linux-firmware (1.127.5) ...
Setting up language-pack-en (1:14.04+20140707) ...
Setting up language-pack-en-base (1:14.04+20140707) ...
Generating locales...
  en_AG.UTF-8... up-to-date
  en_AU.UTF-8... up-to-date
  en_BW.UTF-8... up-to-date
  en_CA.UTF-8... up-to-date
  en_DK.UTF-8... up-to-date
  en_GB.UTF-8... up-to-date
  en_HK.UTF-8... up-to-date
  en_IE.UTF-8... up-to-date
  en_IN.UTF-8... up-to-date
  en_NG.UTF-8... up-to-date
  en_NZ.UTF-8... up-to-date
  en_PH.UTF-8... up-to-date
  en_SG.UTF-8... up-to-date
  en_US.UTF-8... up-to-date
  en_ZA.UTF-8... up-to-date
  en_ZM.UTF-8... up-to-date
  en_ZW.UTF-8... up-to-date
Generation complete.
Setting up language-pack-gnome-en (1:14.04+20140707) ...
Setting up language-pack-gnome-en-base (1:14.04+20140707) ...
Processing triggers for libc-bin (2.19-0ubuntu6.1) ...
Processing triggers for ureadahead (0.100.0-16) ...
Processing triggers for initramfs-tools (0.103ubuntu4.2) ...
update-initramfs: Generating /boot/initrd.img-3.13.0-24-generic

vagrant@ubuntu-1404:~$ sudo dpkg --list | grep grub
ii  grub-common                         2.02~beta2-9ubuntu1           amd64        GRand Unified Bootloader (common files)
ii  grub-gfxpayload-lists               0.6                           amd64        GRUB gfxpayload blacklist
ii  grub-pc                             2.02~beta2-9ubuntu1           amd64        GRand Unified Bootloader, version 2 (PC/BIOS version)
ii  grub-pc-bin                         2.02~beta2-9ubuntu1           amd64        GRand Unified Bootloader, version 2 (PC/BIOS binaries)
ii  grub2-common                        2.02~beta2-9ubuntu1           amd64        GRand Unified Bootloader (common files for version 2)

vagrant@ubuntu-1404:~$ 

4.解決方法

今回の問題に対応したプロビジョニングのコードを含んだ Vagrantfile の内容が以下になります。
debconf-communicate の一行を追加しただけですが・・・

# -*- mode: ruby -*-
# vi: set ft=ruby :

VAGRANTFILE_API_VERSION = "2"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.box = "ubuntu1404"

  config.vm.provision :shell, inline:<<-EOS
    echo "set grub-pc/install_devices /dev/sda" | debconf-communicate
    apt-get update
    apt-get -y upgrade
  EOS
end

5.まとめ

実際に問題が発生した Vagrantfile は、もっと複雑な処理を行っていたのですが、変更していない箇所でエラーが発生していたので原因の特定に回り道をしてしまいました。
今回初めて debconf関連の情報を知ることができて良かった。
これで、この仕組みに対応している他のパッケージで同じ問題が発生しても悩む事はなさそうです♪