Bonjour my geeky friends !:) As you are likely aware, it is now summer-timehere in the northern hemisphere, and thus, i’ve been spending asmuch time away from the computer as possible. That said, it’s been a long time, i shouldn’t have left you,without a strong beat to step to.
Now, if you’re not familiar with kickstarting, it’s basically justa way to automate the installation of an operating environment on amachine – think hands-free installation. Anacondais the OS installation tool used in Fedora, RedHat, and some otherLinux OS’s, and it can be used in a kickstartcapacity. For those of you looking for an intro,i heavily suggest reading over the excellent documentation at theFedora project website. The kickstartconfiguration process could very easily be a couple of blog entrieson its own (which i’ll no doubt get around to in the future), butfor now i want to touch on one particular aspect of it : complexpartition schemes. how it is
The current method for declaring partitions is relatively powerful,in that all manner of basic partitions, LVM components, and evenRAID devices can be specified – but where it fails is in thecreating of the actual partitions on the diskitself. The options that can be supplied to thepartition keywords can make this clunky at best (and impossible atworst).
A basic example of a partitioning scheme that requires nothingoutside of the available functions :
Great, no problem we can easily define that in the kickstart thusly:
part /boot --asprimary --size=128 part / --asprimary --size=20000 part /var/log --asprimary --size=20000 part /home --size=400000 part /opt --size=51680 part swap --size=8192
But what happens if we want to use this same kickstart on anothermachine (or, indeed, many other machines) that don’t have the samedisk size One of the optionsthat can be used with the part keyword is –grow , which tells Anaconda to createas large a partition as possible. This can beused along with –maxsize= , which does exactlywhat you think it does.
Continuing with the example, we can modify the /home partition to be of a variable size, whichshould do us nicely on disks which may be smaller or larger thanour original 500GB unit.
part /home --size=1024 --grow
Here we’ve stated that we’d like the partition to be at least agig, but that it should otherwise be as large as possible given theconstraints of both the other partitions, as well as the totalspace available on the device. But what if youalso want /opt to be variablein size One way would be togrow both of them :
part /home --size=1024 --grow part /opt --size=1024 --grow
Now, what do you think that will do If youguessed grow both of them to half the totalavailable size each , you’d be correct. Maybethis is what you wanted – but then again, maybe itwasn’t. Of course, we could always specify amaximum ceiling on how far /opt will grow :
part /opt --size=1024 --maxsize=200000 --grow
That works, but only at the potential expense of/home. Consider what would happen if this was runagainst a 250GB disk ; the other (static) partitions would eat upsome 48GB, /opt would grow to the maximum specified size of 200GB,and /home would be left with the remaining 2GB of availablespace.
If we were to add more partitions into the mix, the whole thingwould become an imprecise mess rather quickly. Furthermore, we haven’t even begun to look at scenarios where theremay (or may not) more than one disk, nor any fun tricks likeautomatically setting the swap size to be same as the actual amountof RAM (for example). For these sorts of thingswe need a different approach. the magic of pre, the power of parted
The kickstart configuration contains a sectioncalled %pre , which should be familiar to anybodywho’s dealt with RPM packaging. Basically, thepre section contains text which will be parsed by the shell duringthe installation process – in other words, you can write a shellscript here. Fairly be thee warned, however, asthe shell spawned by Anaconda is BusyBox ,not bash , and it lacks some of the functionalitythat you might expect. We can use the %presection to our advantage in many ways – includingpartitioning. Instead of using the built-infunctions to set up the partitions, we can do it ourselves (in amanner of speaking) using parted .
Parted is, as you might expect, a tool for editing partitiondata. Generally speaking it’s an interactivetool, but one of the nifty features is the scripted mode , wherein partitioning commands can be passed toParted on the command-line and executed immediately without furtherintervention. This is very handy in any sort ofautomated scenario, including during a kickstart.
We can use Parted to lay the groundwork for the basic exampleabove, wherein /home is dynamically sized. Initially this will appear inefficient, since we won’t be doinganything that can’t be accomplished by using the existing Kickstartfunctionality, but it provides an excellent base from which to domore interesting things. What follows (untilotherwise noted) are text blocks that can be inserted directly intothe %pre section of the kickstart config :
# clear the MBR and partition table dd if=/dev/zero of=/dev/sda bs=512 count=1 parted -s /dev/sda mklabel msdos
This ensures that the disk is clean, so that we don’t run into anyexisting partition data that might cause trouble. The dd command overwrites thefirst bit of the disk, so that any basic partition information isdestroyed, then Parted is used to create a new disk label.
That little line gives us the total size of the disk, and assignsto a variable named TOTAL . There are other ways to obtain this value, but in keeping with thespirit of using Parted to solve our problems, thisworks. In this instance, awk and cut are used to extract the string we’re interestedin. Continuing on…
# calculate start points let SWAP_START=$TOTAL-8192 let OPT_START=$SWAP_START-51680
Here we determine the starting position for the swap and /optpartitions. Since we know the total size, we cansubtract 8GB from it, and that gives us where the swap partitionstarts. Likewise, we can calculate the startingposition of /opt based on the start point of swap (and so forth,were there other partitions to calculate).
The variables we populated above are used here in order to createthe partitions on the disk. The syntax is verysimple :
parted -s : run Parted inscripted (non-interactive) mode. /dev/sda : the device (later, we’ll see how todetermine this dynamically). mkpart : the action to take (makepartition). primary | extended | logical : the type ofpartition. ext3 : the type of filesystem (there are a numberof possible options, but ext3 is pretty standard). Notice that the extended and swap definitions do notcontain a filesystem type – it is not necessary. start# end# : the start and end points, expressedin MB.
Finally, we must still declare the partitions in the usualway. Take note that this does not occur in the%pre section – this goes in the normal portion of the configurationfor defining partitions :
part /boot --onpart=/dev/sda1 part / --onpart=/dev/sda2 part /var/log --onpart=/dev/sda3 part /home --onpart=/dev/sda5 part /opt --onpart=/dev/sda6 part swap --onpart=/dev/sda7
As i mentioned when we began this section, yes, this is (so far) aremarkably inefficient way to set this particular basicconfiguration up. But, again to re-iterate, thisexercise is about putting the groundwork in place for much moreinteresting applications of the technique. mo’ drives, mo’ better
Perhaps some of your machines have more than one drive, and somedon’t. These sorts of things can be determined,and then reacted upon dynamically using the describedtechnique. Back to the %pre section :
# Determine number of drives (one or two in this case) set $(list-harddrives) let numd=$#/2 d1=$1 d2=$3
In this case, we’re using a built-in functioncalled list-harddrives to helpus determine which drive or drives are present, and then assigntheir device identifiers to variables. In otherwords, if you have an sda andan sdb , those identifiers will be assignedto $d1 and $d2 , and if you just have an sda, then $d2 will be empty.
This gives us some interesting new options ; for example, if wewanted to put /home on to the second drive, we could write up somesimple logic to make that happen :
# if $d2 has a value, it's that of the second device. if [ ! -z $d2 ] then HOMEDEVICE=$d2 else HOMEDEVICE=$d1 fi
# snip... part /home --size=1024 --ondisk=/dev/$HOMEDEVICE --grow
That, of course, assumes that the other partitions are defined, andthat /home is the only entity which should be grown dynamically –but you get the idea. There’s nothing stopping usfrom writing a normal shell script that could determine the numberof drives, their total size, and where the partition start pointsshould be based on that information. In fact,let’s examine this idea a little further. the size, she is dynamic !
Instead of trying to wrangle the partition sizes together with thedefault options, we can get as complex (or as simple) as we likewith a few if statements, and some basic maths. Thinking about our layout then, we can express something like thefollowing quite easily :
If there isone drive that is at least 500 GB in size, then /opt should be 200GB, and /home should consume the rest. If there isone drive is less than 500 GB, but more than 250 GB, then /opt and/home should each take half. If there isone drive that is less than 250 GB, then /home should taketwo-thirds, and /opt gets the rest.
# $TOTAL from above... if [ $TOTAL -ge 512000 ] then let OPT_START=$SWAP_START-204800 elif [ $TOTAL -lt 512000 ] && [$TOTAL -ge 256000 ] then # get the dynamic space total, which is betweenwhere /var/log ends, and swap begins let DYN_TOTAL=$SWAP_START-40256 let OPT_START=$DYN_TOTAL/2 elif [ $TOTAL -lt 256000 ] then let DYN_TOTAL=$SWAP_START-40256 let OPT_START=$DYN_TOTAL/3 let OPT_START=$OPT_START+$OPT_START fi
Now, instead of having to create three different kickstart files,each describing a different scenario, we’ve covered it with one –nice ! other possibilities
At the end of the day, the possilibities are nearly endless, withthe only restriction being that whatever you’d like to do has to bedo-able in BusyBox – which, at this level, provides a lot greatfunctionality.
Stay tuned for more entries related to kickstarting, PXE-basedinstallations, and so forth, all to come here on dan’s linuxblog. Cheers !