Skip to content. | Skip to navigation

Personal tools
You are here: Home TBSI Technology Blog Topics snack


Nov 03, 2009

User input during a Fedora Kickstart

by Eric Smith — last modified Nov 04, 2009 08:55 PM
Filed Under:

Kickstart is Fedora's automated installation facility. Sometimes we need to get user input on the computer being built. Read on for how to do that.

In order to reliably build our servers, we use kickstart and PXE to give us a simple, repeatable process. During this build process, we need user input to decide exactly which configuration to apply to the system being built.

In order to do that, we run a Python script in the ks.cfg %pre section that uses the snack library to get information from the user. Snack is the (poorly documented) UI toolkit that comes with kickstart/anaconda. Here's how you use it in %pre.

First, you need a %pre section that runs the python interpreter. To do that, start the section with:

%pre --interpreter /usr/bin/python

Next, you need to realize that the kickstart screen you usually see runs on tty3. But the snack UI will show up on tty1. So we use a little routine to switch tty's:

def set_tty(n):
    f = open('/dev/tty%d' % n, 'a')
    os.dup2(f.fileno(), sys.stdin.fileno())
    os.dup2(f.fileno(), sys.stdout.fileno())
    os.dup2(f.fileno(), sys.stderr.fileno())

Next comes the function that actually calls snack to get the user input. Don't worry about the host_config parameter, instead focus on how snack is used. This code build a dialog box with a listbox and an OK button:

def get_user_input(host_config, default=None):
    # get the hostname, from it the other params are computed
    # return the hostname and everything that's derived from it
    # which for now is just the disk layout scheme

    from snack import SnackScreen, Listbox, Grid, Label, Entry, Button, GridForm

    def host_list():
        def hosts():
            return sorted(host_config.keys())

        lb = Listbox(height=len(host_config), returnExit=True)
        for host in hosts():
            lb.append(host, host)
        if default in host_config.keys():
        return lb

    screen = SnackScreen()
    form = GridForm(screen, 'Select host to configure', 1, 2)
    form.add(host_list(), 0, 0, (0, 0, 0, 1))
    form.add(Button('OK'), 0, 1)

    # now run the form
    result = form.runOnce()

    hostname = form.childList[0].current()
    return {'layout': host_config[hostname],
            'hostname': hostname,

Finally, put it all together:

set_tty(1)  # change to tty1, we're called by kickstart with stdout as tty3
user_args = get_user_input(host_config, args.args.get('tb-host'))
set_tty(3)  # restore

If you ever need to find information on snack, it helps to know that it's a wrapper for newt. So you can Google on "snack newt python" to get some useful answers. But be warned that there's not much there and you might have to look through the source code to snack.