Jump to contentJump to page navigation: previous page [access key p]/next page [access key n]
適用先 openSUSE Leap 15.7

7 ERB テンプレート Edit source

ERB テンプレートとは、プロファイル内に Ruby 言語のコードを埋め込むことのできる機能で、インストール時にプロファイルを修正する機能を提供します。この仕組みを利用することで、システムの状態を検知してプロファイル内の設定値を調整したり、セクションの追加や削除などを行ったりすることができます。

ERB 機能を有効化するには、プロファイルのファイル名に .erb という拡張子を追加します (例: autoyast.xml.erb) 。このような仕組みが存在することから、ルールやクラスと ERB テンプレートを同時に使用することはできません。

7.1 ERB とは? Edit source

ERB とは Embedded Ruby の略で、 Ruby プログラミング言語の力を借りて様々なコンテンツ生成を行うための仕組みです。 ERB を利用してプロファイル内に Ruby コードを含めることで、インストール先のシステムに依存した様々なプロファイル調整を行うことができるようになります。

ERB を使用する場合、 Ruby 言語のコードは <% 記号から %> 記号までの間に記述します。また、コマンドの出力をそのままプロファイルに入れ込みたい場合は、イコール記号 ( = ) で設定します。

例 7.1: ERB を利用したファイルの取り込み
<bootloader>
  <% require "open-uri" %>
  <%= URI.open("http://192.168.1.1/profiles/bootloader-common.xml").read %>
</bootloader> <!-- this line gets replaced with the content of bootloader-common.xml -->

Ruby の仕組みを利用することで、任意のコマンドを実行することもできます。たとえばコマンドの出力結果を取得したい場合は、コマンドの前後をバッククオートで括ります。また、コマンドの実行が成功したかどうかを調べたい場合は、 system 関数を使用してください。

例 7.2: Ruby におけるコマンドの実行
<% files = `ls` %> <!-- files にはコマンドの実行結果が入ります (例: "file1
file2
file3") -->
<% success = system("dmidecode | grep some-model") %> <!-- success には true もしくは false のいずれかが入ります -->

このほか条件句やループなど、高度な Ruby 言語構造を含めることもできます。

例 7.3: Ruby 言語構造の使用
<% ip_forward = File.read("/proc/sys/net/ipv4/ip_forward").strip %>
<% if ip_forward == "1" %>
  <!-- 何らかの処理 -->
<% end %>

<% files = `ls /tmp/config/*.xml` %>
<% files.split.each do |file| %>
  <%= file.read %>
<% end %>

AutoYaST では ヘルパー関数 と呼ばれる仕組みも提供しています。これは disks (ディスク) や network_cards (ネットワークカード) など、インストール先のシステムに関する様々な情報を取得することができる仕組みです。ヘルパーの一覧と値の意味について、詳しくは 7.2項 「テンプレートヘルパー」 をお読みください。

7.2 テンプレートヘルパー Edit source

テンプレートヘルパーは Ruby メソッド集であり、プロファイル内で使用することで様々なインストール先システムの情報を収集することができます。

7.2.1 boot_efi? Edit source

boot_efi? はブール値のヘルパーで、システムが EFI で起動されているかどうかを表します。下記の例では、現在の起動モードに合わせてブートローダを設定しています。

例 7.4: ブートローダの設定
<% if env.boot_efi? %>
  <loader_type>grub2-efi</loader_type>
<% else %>
  <loader_type>grub2</loader_type>
<% end %>

7.2.2 disks Edit source

disks ヘルパーは、検出されたディスクの一覧を返却するヘルパー関数です。一覧の各要素には、デバイス名やサイズなどの基本的な情報が含まれます。

キー

:device

String

デバイスのカーネル名 (例: sda)

:model

String

ディスクの型番

:serial

String

シリアル番号

:size

Integer

ディスクサイズ (セクタ数)

:udev_names

Array<String>

ディスクの udev 名の一覧 (プロファイル内でデバイスを指定する際、これらのいずれかを使用することができます)

:vendor

String

製造元の名前

下記のプロファイル例は、最も容量の大きいディスクに対してインストールを行う場合の例を示しています。検出されたディスクの一覧をサイズで並び替え、末尾のデバイスを選択します。あとは device 要素に対して :device キーで取得できた値を代入して使用します。

例 7.5: 最も容量の大きいディスクの使用
<partitioning t="list">
  <drive>
    <% disk = disks.sort_by { |d| d[:size] }.last %> <!-- find the largest disk -->
    <device><%= disk[:device] %></device> <!-- print the disk device name -->
    <initialize t="boolean">true</initialize>
    <use>all</use>
  </drive>
</partitioning>

7.2.3 network_cards Edit source

network_cards ヘルパーはネットワークカードの一覧を返す関数です。ここにはネットワークカードの名前のほか、状態に関する情報 (接続されているかどうかなど) も含まれています。

キー

:device

String

デバイス名 (例: eth0 , enp3s0 など)

:mac

String

MAC アドレス

:active

Boolean

デバイスが有効化されているかどうか

:link

Boolean

デバイスが接続されているかどうか

:vendor

String

製造元の名前

下記の例では、ネットワークに接続されている最初のネットワークカードを検出し、そのネットワークカードで DHCP を使用するように設定します。

例 7.6: 接続されているネットワークカードの設定
<interfaces t="list">
  <% with_link = network_cards.sort_by { |n| n[:name] }.find { |n| n[:link] } %>
  <% if with_link %>
    <interface>
      <device><%= with_link[:device] %></device>
      <startmode>auto</startmode>
      <bootproto>dhcp</bootproto>
      </interface>
  <% end %>
</interfaces>

7.2.4 os_release Edit source

os_release ヘルパーは、オペレーティングシステムに関する情報を返す関数です。これは /etc/os-release ファイルから情報を読み込みます。

キー

:id

String

ディストリビューション ID ( 例: sles, opensuse-tumbleweed )

:name

String

ディストリビューション名 ( 例: SLES, openSUSE Tumbleweed )

:version

String

ディストリビューションのバージョン ( 例: 15.2 )

この情報を使用することで、インストールすべき製品を判断することができます。たとえば SLE と openSUSE で異なる設定を適用することができるようになります。

例 7.7: 異なるディストリビューションに対して同じプロファイルを適用する設定
<products t="list">
  <% if os_release[:id] == 'sle' %>
  <product>SLES</product>
  <% else %>
  <product>openSUSE</product>
  <% end %>
</products>

7.2.5 hardware Edit source

hardware ヘルパーは追加のハードウエア情報を提供する仕組みです。ここには hwinfo コマンドからの全ての情報が含まれていて、その他のヘルパーでは不十分な場合の回避策として使用することができます。たとえば下記の例では、 hardware ヘルパーを利用して USB デバイスのフィルタリングを行っています。 hardware ヘルパーで提供される情報についての詳細は、 7.3項 「ERB ヘルパーの実行」 をお読みください。

例 7.8: USB デバイスのフィルタ
<% usb_disks = hardware["disk"].select { |d| d["driver"] != "usb-storage" } %>

7.3 ERB ヘルパーの実行 Edit source

AutoYaST の ERB ヘルパーを実行するにあたって Ruby コンソールを使用して結果を確認することができます。 ERB ヘルパーは Y2Autoinstallation::Y2ERB::TemplateEnvironment クラスのインスタンスを介してアクセスできます。下記のようにして root で Ruby インタプリタを起動して確認してください: irb -ryast -rautoinstall/y2erb

例 7.9: ヘルパーの実行
irb > env = Y2Autoinstallation::Y2ERB::TemplateEnvironment.new  # env 変数にはヘルパーのインスタンスが代入されます

irb > env.disks
=>
[{:vendor=>"WDC", :device=>"sda", ...},
 {:vendor=>"TOSHIBA", :device=>"sdb", ...},
...]

irb > env.hardware.keys
=>
["architecture",
 "bios",
 "bios_video",
 ...]

irb > env.hardware["architecture"]
=>
"x86_64"

7.4 ERB プロファイルの生成 Edit source

AutoYaST のコマンドラインでは check-profile コマンドが提供されています。これは ERB ファイルからプロファイルを生成するための仕組みで、このコマンドは AutoYaST に対して ERB コードの処理と実行を依頼して、プロファイルの生成を行います。これを利用することで、期待通りにプロファイルが生成されるかどうかを確認することができます。サポートされている全てのオプションを表示するには、 autoyast check-profile --help のように入力して実行してください。たとえば下記の例では、 AutoYaST に対してプロファイルのダウンロードと解釈を依頼して、 ERB コードの実行と事前スクリプトの実行までを行っています。実行結果は result.xml ファイルに出力されます。

例 7.10: プロファイルの生成
 > sudo yast2 autoyast check-profile filename=http://192.168.1.100/autoinst.erb output=result.xml run-scripts=true run-erb=true
警告
警告: check-profile の許可について

ほとんどの場合、 check-profile には root のアクセス権限が必要となります。そのため、インストール前スクリプトや ERB プロファイルを root で動作させることになることに注意してください。信頼できるプロファイルのみを指定してください。

7.5 ERB プロファイルのデバッグ Edit source

ERB の処理や動作を 1 つずつ確認していきたい場合は、 YaST の提供する byebug デバッガをお使いください。具体的には rubygem(byebug) パッケージをインストールしたあと、 Y2DEBUGGER 環境変数を 1 に設定します。

例 7.11: デバッグ環境の準備
> sudo zypper --non-interactive in "rubygem(byebug)"
> sudo Y2DEBUGGER=1 yast2 autoyast check-profile ...

ブレークポイントを追加したい場合は、その箇所に <% byebug %> を追加するだけです。 byebug に関する詳細は、 https://github.com/deivid-rodriguez/byebug (英語) をお読みください。

例 7.12: ブレークポイントの追加
<% byebug %>
<% if system("dmidecode | grep some-model") %>
  <!-- 何らかの処理 -->
%<% end %>

7.6 ERB とルール/クラスの比較 Edit source

ERB とルール/クラスのどちらもプロファイルを動的に生成する仕組みですが、一般的には ERB のほうが読みやすく理解しやすい仕組みです。また、大きく異なる点として、ルールとクラスがプロファイルの合成に対応しているのに対して、 ERB は対応していないことがあげられます。プロファイルの合成に関する詳細は、 第6章 「ルールとクラス をお読みください。もう一方の ERB では、 Ruby という高度な言語の威力を存分に発揮することができます。たとえば下記の 2 つの例では、 /dev/sdb が存在した場合、 /home をそのデバイス内に作成するよう指示しています。

例 7.13: ルールとクラス
<rule>
  <custom1>
    <script>
if blkid | grep /dev/sdb > /dev/null; then
echo -n "yes"
else
echo -n "no"
fi;
    </script>
    <match>yes</match>
    <match_type>exact</match_type>
  </custom1>
  <result>
    <profile>classes/sdb_home.xml</profile>
    <dont_merge config:type="list">
      <element>partition</element>
    </dont_merge>
  </result>
</rule>
例 7.14: ERB
<% home_in_sdb = disks.map { |d| d[:device] }.include?("sdb") %>

<partitioning config:type="list">
  <drive>
    ...
  </drive>
  <% if home_in_sdb %>
  <drive>
    <device>/dev/sdb</device>
    <disklabel>none</disklabel>
    <partitions t="list">
      <partition>
        <format t="boolean">true</format>
        <filesystem t="symbol">xfs</filesystem>
        <mount>/home</mount>
      </partition>
    </partitions>
  </drive>
  <% end %>
</partitioning>
このページを印刷