Edited at

OpenStack(Mitaka)で、EFI起動させてみる

More than 1 year has passed since last update.

■自分の環境

・ホストサーバ:ubuntu 16.04

・libvertのバージョン:1.3.1

・OpenStack:mitaka

■必須環境

・libvertのバージョン:1.2.9以上

・OpenStack:mitaka以上であること

■対象とする読者

OpenStack環境はすでにできているが、仮想サーバをEFI起動させたいという方に向けて書いています。

自分はなかなかハマってしまったので、備忘として。

やることがわかっていれば、簡単なのでしょうが、仮想化の初心者なので。。。

大きく分けて、3つの作業を行います。

1.KVMで、EFI起動できるようにする。

2.Glanceへのイメージ登録時に、EFI起動の設定を加える。

3.起動ファイルの再作成(バグ?対応。本当はいらない作業)

■参考にしたURL

また、今回の調査にあたり、以下のサイトや記事を参考にさせていただきました。

みなさま、ありがとうございます。

OpenStackドキュメント - Boot From UEFI image

uefi_bootsupport_techtip_final.pdf

OpenStackドキュメント - Images and instances

QEMU の為の UEFI ファームウェアのビルド手順

libvirt の UEFI 設定

第441回 QEMU/KVMでUEFIファームウェアを使う

それでは、始めていきます。

(EFI起動は、OpenStackのMitakaからの対応らしいので、ご注意を)


1.KVMで、EFI起動できるようにする。

自分はOpenStackの仮想サーバを、KVMで実行しているのですが、

KVMは、デフォルトではEFI起動はせず、BIOSでの起動となってしまうようです。

Horizonで作成したインスタンスを起動しようとすると、

エラーメッセージが出てきて、なんだか切ない気持ちになります。

スクリーンショット 2017-02-24 19.02.31.png

そこで、まずはKVMでもEFI起動できるようにしていきます。

その前にlibvertのバージョンを調べます。

・libvirtのバージョン確認


$ virsh version

コンパイル時に使用したライブラリ: libvirt 1.3.1

使用中のライブラリ: libvirt 1.3.1

使用中の API: QEMU 1.3.1

実行中のハイパーバイザー: QEMU 2.5.0


libvirtのバージョンが1.2.9以上であることを確認してください。

バージョンに問題がなければ、KVMでEFI起動できるようにするための「OVMF」をインストールします。

・OVMFをインストール


$ sudo apt install ovmf


・何かできている

以下のコマンドを打って、それぞれ2つのファイルができていることを確認します。


$ ls /usr/share/OVMF/

OVMF_CODE.fd

OVMF_VARS.fd


これで、KVM側の作業は終了です。


2.Glanceへのイメージ登録時に、EFI起動の設定を加える。

Glanceへのイメージの登録の際に、EFI起動するための指定が必要です。

Horizonでは、設定項目がなさそうなので、コマンドラインから、Glanceの登録を行います。

・glanceイメージを登録

(筆者はvdiファイルを取り込んだので、file、disk-formatなどは環境に合わせた値に変換してください。)


$ openstack image create "NAME" --file XXXXXXXXXX.vdi --disk-format vdi --container-format bare --property hw_firmware_type=uefi --public


「--property hw_firmware_type=uefi」がポイント!

このpropertyを指定しないと、OpenStack側は、EFI起動せず、BIOSで起動させようとしてしまうので、注意してください!

MySqlでglanceユーザでログインし、「image_properties」テーブルを参照してみてください。

先ほど登録したGlanceイメージのpropertyが、name:hw_firmware_type、 value:uefiで登録されていることを確認します。


$ sudo mysql glance

MariaDB [glance]> select * from image_properties;

+----+--------------------------------------+-------------- ---+-------+---------------------+---------------

| id | image_id | name | value | created_at | updated_at >| deleted_at | deleted |

+----+--------------------------------------+------------- ----+-------+---------------------+---------------

| 1 | xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx | hw_firmware_type | uefi | 2017-01-01 04:57:31 | 2017-01-01 04:57:31 | NULL | 0 |

+----+--------------------------------------+-------------- ---+-------+---------------------+---------------


これで、準備はOK。

その前に。。。

・driver.pyをちょっと見てみる

先ほど設定した「--property hw_firmware_type=uefi」はどのように使用されるのでしょうか。

そのヒントは、以下のpyファイルに書かれているようです。


$ view /usr/lib/python2.7/dist-packages/nova/virt/libvirt/driver.py



driver.py


(前略)
DEFAULT_UEFI_LOADER_PATH = {                          ←①
"x86_64": "/usr/share/OVMF/OVMF_CODE.fd",
"aarch64": "/usr/share/AAVMF/AAVMF_CODE.fd"
}

(中略)

if hw_firmware_type == fields.FirmwareType.UEFI:    ←②
if self._has_uefi_support():
global uefi_logged
if not uefi_logged:
LOG.warn(_LW("uefi support is without some kind of "
"functional testing and therefore "
"considered experimental."))
uefi_logged = True
guest.os_loader = DEFAULT_UEFI_LOADER_PATH[    ←③
caps.host.cpu.arch]
guest.os_loader_type = "pflash"
else:
raise exception.UEFINotSupported()
guest.os_mach_type = self._get_machine_type(image_meta, caps)
(後略)


①の部分にて、「DEFAULT_UEFI_LOADER_PATH」の指定が、

OVMFをインストールされた際にできた「OVMF_CODE.fd」に指定されていることがわかります。

これが、EFI起動するためのローダーとなるのでしょう。

さらに、いつこのPATHを使うかというと、

②の「if hw_firmware_type == fields.FirmwareType.UEFI」ブロックの中。

hw_firmware_typeや、UEFIなどの記載があります。

はい、先ほど指定したpropertyの値ですね。

おそらく、fields.FirmwareType.UEFIは、固定文字でuefiとなっているのでしょう。

このif文に入った際に、③でguest.os_loader = DEFAULT_UEFI_LOADER_PATHとあります。

きっとこれで、EFI起動するためのお膳立てはできているはず!


3.起動ファイルの再作成

・まだダメだった

これで普通にインスタンス作成すれば、起動すると思いきや!!

謎のエラーメッセージが出て起動しない!!

スクリーンショット 2017-02-24 22.49.59.png

ここで数時間試行錯誤。

で、ふと思い、KVM側の設定を確認してみる。


$ virsh list

Id |名前 |状態

----------------------------------------------------

20 |instance-00000001 |実行中


・設定を確認

以下のコマンドで、VMの起動設定のXMLファイルを、確認/編集することができます。


$ virsh edit <インスタンス名>



virshコマンド実行

(前略)

<os>
<type arch='x86_64' machine='pc-i440fx-xenial'>hvm</type>
<loader readonly='yes' type='pflash'>/us
r/share/OVMF/OVMF_CODE.fd</loader>
<nvram template='/us
r/share/OVMF/OVMF_CODE.fd'>/var/lib/libvirt/qemu/nvram/インスタンス名_VARS.fd</nvram>
<boot dev='
hd'/>
<smbios mode='
sysinfo'/>
</os>
(後略)

あれれ? 参考にしたサイトと、表示が異なっている!!

「<nvram template='/usr/share/OVMF/OVMF_CODE.fd'>」となっている!?

「<nvram template='/usr/share/OVMF/OVMF_VARS.fd'>」になると思っていたのに!!

こちらのサイトでは、

OVMF_CODE.fdは、ファームウェアの指定で、

OVMF_VARS.fdは、nvramの指定、と説明されていました。

上記の設定は、nvramのテンプレートにOVMF_CODE.fdが設定されている。

うーん。もしかして設定が変なことになってしまっている???

ここは、OpenStack側が、自動で設定する項目のはずなのに。

・仕方ないので、起動ファイルを再作成

すでにOVMF_CODE.dfをテンプレートとして起動ファイルが作成されてしまっているため、

OVMF_VARS.dfをテンプレートとして作成するようにします。

まずは、すでに作成されているファイルがあると、再作成されないため、リネームする。


$ sudo mv /var/lib/libvirt/qemu/nvram/instance-00000001_VARS.fd /var/lib/libvirt/qemu/nvram/instance-00000001_VARS.fd_bk


以下のコマンドで、<os>部分のパラメータを書き換えます。


$ virsh edit <インスタンス名>



virshコマンド実行

(前略)

<os>
<type arch='x86_64' machine='pc-i440fx-xenial'>hvm</type>
<loader readonly='yes' type='pflash'>/us
r/share/OVMF/OVMF_CODE.fd</loader>
<nvram template='/us
r/share/OVMF/OVMF_VARS.fd'></nvram>
<boot dev='
hd'/>
<smbios mode='
sysinfo'/>
</os>
(後略)

・再作成


$ virsh start <インスタンス名>


・設定を確認


$ virsh edit <インスタンス名>



virshコマンド実行

(前略)

<os>
<type arch='x86_64' machine='pc-i440fx-xenial'>hvm</type>
<loader readonly='yes' type='pflash'>/us
r/share/OVMF/OVMF_CODE.fd</loader>
<nvram template='/us
r/share/OVMF/OVMF_VARS.fd'>/var/lib/libvirt/qemu/nvram/インスタンス名_VARS.fd</nvram>  ←値が変更されていることを確認
<boot dev='
hd'/>
<smbios mode='
sysinfo'/>
</os>
(後略)

・いけんじゃねーか

ということで、あとは、コマンドラインでも、Horizonからでも、普通にインスタンスを作成すれば、EFI起動がなされます。

スクリーンショット 2017-02-26 16.43.07.png

本当は、XMLファイルを作成するスクリプトを編集すればスマートなのでしょうが、そこまでは追っていません。

また、今回はmitakaで試しましたが、最新版では解消されているかも??