org_fedora_hello_world/ks/ directory you have created previously, make sure it contains an __init__.py file, and add another Python script named hello_world.py.
%addon statement and is closed by %end. The %addon line also contains the name of the add-on (such as %addon org_fedora_hello_world) and optionally a list of arguments, if the add-on supports them.
Example 2. Using an Add-on in a Kickstart File
%addon ADDON_NAME [arguments] first line second line ... %end
AddonData. This class is defined in pyanaconda.addons and represents an object for parsing and storing data from a Kickstart file.
AddonData class. Anything between the first and last line is passed to the add-on's class one line at a time. To keep the example Hello World add-on simple, it will merge all lines in this block into a single line and separate the original lines with a space.
AddonData with a method for handling the list of arguments from the %addon line, and a method for handling lines inside the section. The pyanaconda/addons.py module contains two methods which can be used for this:
handle_header - takes a list of arguments from the %addon line (and line numbers for error reporting)
handle_line - takes a single line of content from between the %addon and %end statements
Example 3. Using handle_header and 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 additional arguments. if extra: msg = "Unhandled arguments on %%addon line for %s" % self.name if lineno != None: raise KickstartParseError(formatErrorMsg(lineno, msg=msg)) else: raise KickstartParseError(msg) # 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__ variable which is necessary to prevent Anaconda's collect method from taking the AddonData class instead of add-on specific HelloWorldData.
HelloWorldData class inherited from AddonData with its __init__ method calling the parent's __init__ and initializing the attributes self.text and self.reverse to False.
self.reverse attribute is populated in the handle_header method, and the self.text is populated in handle_line. The handle_header method uses an instance of the KSOptionParser provided by pykickstart to parse additional options used on the %addon line, and handle_line strips the content lines of white space at the beginning and end of each line, and appends them to self.text.
setup - called before the installation transaction starts and used to make changes to the installation runtime environment
execute - called at the end of the transaction and used to make changes to the target system
Example 4. Importing the setup and execute Methods
import os.path from pyanaconda.addons import AddonData from pyanaconda.constants import getSysRoot from pykickstart.options import KSOptionParser from pykickstart.errors import KickstartParseError, formatErrorMsg HELLO_FILE_PATH = "/root/hello_world_addon_output.txt"
setup and execute methods included is below:
Example 5. Using the setup and execute Methods
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: pyanaconda.packaging.dnfpayload.DNFPayload """ # 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(getSysroot() + HELLO_FILE_PATH) with open(hello_file_path, "w") as fobj: fobj.write("%s\n" % self.text)
setup method does nothing; the Hello World add-on does not make any changes to the installation runtime environment. The execute method writes stored text into a file created in the target system's root (/) directory.
__str__ method recursively on the tree-like structure storing installation data, which means that the class inherited from AddonData must define its own __str__ method which returns its stored data in valid Kickstart syntax. This returned data must be possible to parse again using pykickstart.
__str__ method will be similar to the following example:
Example 6. Defining a __str__ Method
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\n" % self.text return addon_str
handle_header, handle_line, setup, execute and __str__), it becomes a valid Anaconda add-on. You can continue with the following sections to add support for the graphical and text-based user interfaces, or you can continue with Section 7, “Deploying and Testing an Anaconda Add-on” and test the add-on.