Red Hat Training

A Red Hat training course is available for Red Hat Enterprise Linux

5.6. Anaconda アドオンの作成

以下のセクションでは、Hello World という名前のサンプルアドオンを作成およびテストするプロセスについて説明します。このサンプルアドオンは、全インターフェイス (Kickstart、GUI および TUI) をサポートします。このサンプルアドオンのソースは rhinstaller/hello-world-anaconda-addon リポジトリーから取得できます。このリポジトリーをクローンするか、ウェブインターフェイスでソースを開くことが推奨されます。
もう 1 つ確認するリポジトリーは、rhinstaller/anaconda です。ここにはインストーラーのソースコードがあり、本セクションでこのコードの一部が参照されます。
アドオン自体の開発を開始する前に、次の説明に従ってディレクトリー構造を作成することから始めます。「Anaconda アドオンの構造」 .次に、「キックスタートのサポート」、キックスタートのサポートはすべてのアドオンで必須です。その後、オプションで続行できます「グラフィカルユーザーインターフェイス」「テキスト形式のユーザーインターフェイス」必要に応じて。

5.6.1. キックスタートのサポート

Kickstart サポートはアドオンで最初に開発すべき点です。グラフィカルおよびテキストベースのインターフェイスのサポートなど他のパッケージはこれに依存します。まず、これまでに作成した com_example_hello_world/ks/ ディレクトリーに移動し、__init__.py ファイルがあることを確認して、さらに hello_world.py という名前の Python スクリプトを追加します。
ビルトインの Kickstart コマンドとは異なり、アドオンは独自の セクション で使用されます。Kickstart ファイル内でのアドオンの使用はそれぞれ %addon ステートメントで開始され、%end で終了します。%addon 行にはアドオンの名前 (%addon com_example_hello_world など) と、オプションで引数一覧も含めます (アドオンがこれらに対応している場合)。
Kickstart ファイルでのアドオンの使用例は以下のようになります。

例3 Kickstart ファイルでのアドオンの使用

%addon ADDON_NAME [arguments]
first line
second line
...
%end
アドオンのキックスタートサポートのキークラスは AddonData と呼ばれます。このクラスは pyanaconda.addons で定義され、キックスタートファイルからのデータを解析および保存するためのオブジェクトを表します。
引数は、AddonData クラスから継承されたアドオンクラスのインスタンスに、リストとして渡されます。最初の行と最後の行の間にあるものはすべて、一度に一行ずつアドオンのクラスに渡されます。Hello World のアドオンサンプルをシンプルにするために、このブロック内のすべての行を単一行にまとめ、元の行を空白で区切ります。
サンプルのアドオンでは、%addon 行からの引数リストの処理のメソッドとセクション内の行を処理するメソッドのあるクラスを AddonData から継承する必要があります。pyanaconda/addons.py モジュールにはこれに使用可能な以下の 2 つのメソッドが含まれています。
  • handle_header: %addon 行のリスト (およびエラー報告用の行番号) を取ります。
  • handle_line: %addon%end のステートメント間のコンテンツの単一行を取ります。
以下では、上記のメソッドを使用する Hello World アドオンの例を表示します。

例4 handle_header と handle_line の使用

from pyanaconda.addons import AddonData
from pykickstart.options import KSOptionParser

# export HelloWorldData class to prevent Anaconda's collect method from taking
# AddonData class instead of the HelloWorldData class
# :see: pyanaconda.kickstart.AnacondaKSHandler.__init__
__all__ = ["HelloWorldData"]

HELLO_FILE_PATH = "/root/hello_world_addon_output.txt"

class HelloWorldData(AddonData):
    """
    Class parsing and storing data for the Hello world addon.

    :see: pyanaconda.addons.AddonData

    """

def __init__(self, name):
    """
    :param name: name of the addon
    :type name: str

    """

    AddonData.__init__(self, name)
    self.text = ""
    self.reverse = False

def handle_header(self, lineno, args):
    """
    The handle_header method is called to parse additional arguments in the
    %addon section line.

    :param lineno: the current linenumber in the kickstart file
    :type lineno: int
    :param args: any additional arguments after %addon <name>
    :type args: list

    """

    op = KSOptionParser()
    op.add_option("--reverse", action="store_true", default=False,
    dest="reverse", help="Reverse the display of the addon text")
    (opts, extra) = op.parse_args(args=args, lineno=lineno)

    # Reject any additoinal arguments. Since AddonData.handle_header
    # rejects any arguments, we can use it to create an error message
    # and raise an exception.
    if extra:
        AddonData.handle_header(self, lineno, extra)

    # Store the result of the option parsing
    self.reverse = opts.reverse

def handle_line(self, line):
    """
    The handle_line method that is called with every line from this addon's
    %addon section of the kickstart file.

    :param line: a single line from the %addon section
    :type line: str

    """

    # simple example, we just append lines to the text attribute
    if self.text is "":
        self.text = line.strip()
    else:
        self.text += " " + line.strip()
この例では、必要なメソッドのインポートと __all__ 変数の定義から始めます。これは、Anaconda の collect メソッドがアドオン固有の HelloWorldData ではなく AddonData クラスを取得しないようにするのに必要な変数を定義します。
この例は、親の __init__ を呼び出して、self.textself.reverse 属性を False に初期化する __init__ メソッドで、AddonData から継承したクラス HelloWorldData の定義を示しています。
self.reverse 属性が handle_header メソッドに反映され、self.texthandle_line に反映されます。handle_header メソッドは pykickstart が提供する KSOptionParser のインスタンスを使用して、%addon 行で使用される追加オプションを解析し、handle_line は各行の最初と終了時に空白のコンテンツ行を取り除き、self.text に追加します。
上記のコードは、 Kickstart ファイルからデータを読み取るという、インストールプロセスにおけるデータライフサイクルの第 1 フェーズをカバーしています。次のステップは、そのデータを使用してインストールプロセスを進めることです。この場合、事前定義された方法が 2 つあります。
  • setup: インストール処理の開始前に呼び出され、インストールランタイム環境の変更に使用されます。
  • execute: 処理の最後に呼び出され、ターゲットシステムの変更に使用されます。
これら 2 つのメソッドを使用するには、新たなインポートと定数をモジュールに追加する必要があります。例を示します。

例5 setup および execute メソッドのインポート

import os.path

from pyanaconda.addons import AddonData
from pyanaconda.constants import ROOT_PATH

HELLO_FILE_PATH = "/root/hello_world_addon_output.txt"
setup および execute メソッドを含む Hello World アドオンの更新例を以下に示します。

例6 setup および execute メソッドの使用

def setup(self, storage, ksdata, instclass, payload):
    """
    The setup method that should make changes to the runtime environment
    according to the data stored in this object.

    :param storage: object storing storage-related information
    (disks, partitioning, bootloader, etc.)
    :type storage: blivet.Blivet instance
    :param ksdata: data parsed from the kickstart file and set in the
    installation process
    :type ksdata: pykickstart.base.BaseHandler instance
    :param instclass: distribution-specific information
    :type instclass: pyanaconda.installclass.BaseInstallClass
    :param payload: object managing packages and environment groups
    for the installation
    :type payload: any class inherited from the pyanaconda.packaging.Payload
    class
    """

    # no actions needed in this addon
    pass

def execute(self, storage, ksdata, instclass, users, payload):
    """
    The execute method that should make changes to the installed system. It
    is called only once in the post-install setup phase.

    :see: setup
    :param users: information about created users
    :type users: pyanaconda.users.Users instance

    """

    hello_file_path = os.path.normpath(ROOT_PATH + HELLO_FILE_PATH)
    with open(hello_file_path, "w") as fobj:
        fobj.write("%s\n" % self.text)
上記の例では、setup メソッドは何もせず、Hello World アドオンはインストールランタイム環境に変化を加えません。execute メソッドは、保存したテキストを、ターゲットシステムのルート (/) ディレクトリーで作成したファイルに書き込みます。
上記の例で最も重要な情報は、それら 2 つのメソッドに渡される引数の量と意味です。これらは、例の中の docstring に記載されています。
データライフサイクルの最終フェーズ、およびキックスタートサポートを提供するモジュールで必要なコードの最後の部分は、インストール時に設定された値を含む新しいキックスタートファイルを、説明したようにインストールプロセスの最後に生成します。の「Anaconda のアーキテクチャー」.これは、インストールデータを格納するツリーのような構造構造で __str__ メソッドを呼び出すことで実行されます。つまり、AddonData から継承されたクラスは、有効なキックスタート構文で保存されたデータを返す独自の __str__ メソッドを定義する必要があります。この返されるデータは、pykickstart を使用して再度解析する必要があります。
Hello World の例では、__str__ メソッドを以下の例のようになります。

例7 __str__ メソッドの定義

def __str__(self):
    """
    What should end up in the resulting kickstart file, i.e. the %addon
    section containing string representation of the stored data.

    """

    addon_str = "%%addon %s" % self.name

    if self.reverse:
        addon_str += "--reverse"

    addon_str += "\n%s\n%%end" % self.text
    return addon_str
キックスタートサポートモジュールに必要なメソッドすべて (handle_headerhandle_linesetupexecute、および __str__) が含まれると、有効な Anaconda アドオンになります。次のセクションに進み、グラフィカルおよびテキストベースのユーザーインターフェイスのサポートを追加するか、次のセクションに進むことができます。「Anaconda アドオンのデプロイおよびテスト」アドオンをテストします。