History, philosophy and adding your own distribution
UML builder grew out of my frustration at trying to using mkrootfs that came with UML. It required root/sudo access, and didn't run any of the package installation scripts. It also didn't setup a lot of things such as root password, X servers, getty/login ttys etc. I tried to fix it for the distribution of my choice (Mandrake 8.1) and failed. (This is because mkrootfs is more of a minimalist power user tool).
I finally decided to write my own implementation, based on experience of hacking mkrootfs. One thing that was immediately apparent is that the install of the rpms needs to be done under the distributions own tools, and inside the guest system. I wrote one in TCL which became unmaintainable by the time I was half finished. Consequently I started again in Python, which built on the TCL experience. The Python code isn't that good since it is the first Python program I have ever written, and it has to run on any version of Python from 1.5 up (thanks to RedHat).
UML builder does a two stage install. The first bit is to gather up all the information and files necessary for the install to happen (see them in installfs as a subdirectory of your --dir argument. It then boots into that new environment and installs all the rpms.
Various support files are located in the profile directory that contain things like the 2nd stage installer (also in Python), information about the various distributions, and scripts that copied into the guest.
To make a new distribution, copy one of the .p files from the profile directory, and specify that in your --distro argument (if the name has a '/' in it, it is assumed to be a direct filename rather than one in the profile directory.
You will need to competely redo the modules variable in the profile, as well as most of the others. Then look on the first CD for the distribution. Usually alongside the RPMS directory, there will be one named base that contains various files, one of which will provide some sort of information about what packages are part of what components when selected via the dsistributions own installed. You will need to munge the format of this information as appropriate.
Then run listallfiles from the profile directory with the arguments being all the rpms and save the output. This will tell you what files come from which rpm.
Finally run the maint.py script from the profile directory with the first argument being the RPMS directory (on your hard disk) and the second being your distribution file. It will verify that the various modules are complete. It will also print out information on any rpms that are mutually dependent (ie they require each other). If both are explicitly mentioned in the module, then they are ordered as there, otherwise the order is undetermined.
Do an installation using your new profile, and look for any error messages when the rpms are installing. These are usually for ordering reasons. Sometimes you will need to switch the order of mutually dependent rpms, and sometimes you will need to add in synthetic requires information that the package maintainer should have had.
This can take several iterations until you get it right. You'll also wonder how these distributions manage to ever install without any warnings.
When you finally have a distro you know works correctly, please use the patch submission or email a URL to it on the developer mailing list.