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.