Dynamic RedHat Kickstarts With PHP
I have been preoccupied with the automation of a RedHat Linux install, from the PXEBoot process to release to production mode. As a budding sysadmin in an HPC environment, that means many machines to install. The more I can get software to do, the better.
On that note, I realized the future of provisioning Linux systems en masse was to abandon the concept of one kickstart file per system type. Why can’t I just dynamically generate them based on what each host is hardware-wise and also what the machine is supposed to do? Well, I did just that. The magic lies in the fact that the RedHat installer environment allows for a kickstart file to be downloaded via HTTP. All I need to do is to write a PHP script that spits out a custom kickstart file based on the connecting IP address:
<?php
include("config.php");
mysql_connect("host", "user", "password") or die(mysql_error());
mysql_select_db("database") or die(mysql_error());
$server = (empty($_GET['addr'])) ? $_SERVER['REMOTE_ADDR'] : $_GET['addr'];
$result = mysql_query("SELECT system_type, service_type FROM sys_inventory WHERE ip = '$server'") or die(mysql_error());
$row = mysql_fetch_array($result);
$system = $row['system_type'];
$service = $row['service_type'];
$packages = '';
$result = mysql_query("SELECT package from packages where service_type = 'global' or service_type = '$service'");
while ($row = mysql_fetch_array($result)) {
$packages .= $row['package'] . "\n";
}
config_global();
config_system($system);
config_service($service);
echo"%packages --resolvedeps\n";
echo "$packages\n";
echo "%pre\n";
echo "cp /mnt/source/ks_scripts/pre.sh /\n";
echo "/pre.sh $system $service \n";
echo "\n";
echo "%post --nochroot\n";
echo "cp /mnt/source/ks_scripts/postnochroot.sh /mnt/sysimage/tmp/\n";
echo "cp /mnt/source/ks_scripts/post.sh /mnt/sysimage/tmp/\n";
echo "/mnt/sysimage/tmp/postnochroot.sh $system $service\n";
echo "\n";
echo "%post\n";
echo "/tmp/post.sh $system $service\n";
?>
You supply a config.php file to generate the global configs:
<?php
function config_global() {
// Just echo the options that you want everybody to have, like root passwords, partitioning, whatever
}
function config_system($system) {
if ($system == "dell") {
// Maybe some special partitioning options?
}
if ($system == "sun") {
}
}
function config_service($service){
if ($service == "webserver") {
}
if ($service == "mailserver") {
}
}
?>
Next, you shove shell scripts (pre.sh, postnochroot.sh, post.sh in a directory that the installer can access, like a NFS mount:
#!/bin/sh
# %PRE section script
SYSTEM=$1
SERVICE=$2
# Put your global stuff here
# Define unique system-oriented procedures
case $SYSTEM in
dell)
# Do stuff
;;
sun)
;;
*)
echo "System type not recognized. Is it in the database?";
;;
esac
# Define unique service-oriented procedures
case $SERVICE in
webserver)
;;
mailserver)
;;
*)
echo "Service type not recognized. Is it in the database?";
;;
esac
Now, you just need a MySQL database that at least stores the ip, the system type, and the service type, and you’ll be on your way to a fully-automated Linux server setup! I’ll document this in more detail and release the sourcecode and documentation in a better format than a blog post, but at least you can play with it now!
Kickstart docs: here