FOG Postinit scripts, before the magic begins...

  • Moderator

    Part 1 Postint Scripts

    The FOG developers added a new feature with the release of FOG 1.3.4. This feature is called “postinit scripts”. These scripts are akin to the FOG postdownload scripts which are called after the system has been imaged, but before the target computer rebooted. In contract the postinit scripts are called just after the FOS engine starts and before it starts working on the target computer. More precisely, these user created scripts are called just before the main fog selector program executes. Please be aware that the postinit hook script fog.postinit is called every time the FOS engine (the high performance customized Linux OS that runs on the target hardware) is loaded. To state this another way, the postinit scripts are run before the following actions: disk wipe, compatibility tests, quick registration, full registration, inventory, quick imaging, capture, and deploy. Your custom postinit scripts must take this into account and act accordingly so that your code only runs on specific actions (more on this later).

    This feature was created to allow the FOG admin the ability to interact with the target hardware just prior to the FOS engine starts to interact with the target computer. For example lets say you had a raid controller that required specific commands to be executed before image capture can take place. You would use a FOG postinit script to prepare the raid array for imaging (flush cache to disk, quiesce the array, etc). Another example would be that some hardware assisted software raid (i.e. commonly called “fake-raid”) controllers require specific drivers to be loaded into the operating system before the OS can actually “see” the raid array as an array. FOG does provide a software raid controller (mdadm) that can see MS Windows software raid and some intel software raid controllers [ ] without any custom commands. But there are other software raid controllers that need specific setup parameter to ensure FOS is connected to the array properly. This is where the postinit scripts comes into play.

    In the example below this command will initialize a specific hardware assisted software raid array. Without this command the FOS engine just sees /dev/sda and /dev/sdb as just a bunch of (independent) disks [JBOD] and not a real raid array.

    mdadm --build /dev/md0 --raid-devices=2 --chunk=16 --level=0 /dev/sda /dev/sdb

    So how do I use this fancy new feature?

    As I stated above, beginning with FOG 1.3.4 the developers created a directory in the /images/dev directory to hold your postinit scripts. The full path the FOG hook script is /images/dev/postinitscripts/fog.postinit for image capture and /images/postinitscripts/fog.postinit during all other FOS engine operations. Since this location changes based on the type of operation being performed, its probably best for your script to use the FOG supplied variable of $postinitpath which will always point to the proper location. You can either add the required commands directly to the fog.postinit script (not recommended), or create a new bash script, then call your new script from the fog.postinit script (recommended).

    The following is an example framework you can use to write your own fog.postinit script. In this example lets call our fog.postinit script fog.LenovoP50
    touch /images/dev/postinitscripts/fog.LenovoP50
    chmod 755 /images/dev/postinitscripts/fog.LenovoP50
    vi /images/dev/postinitscripts/fog.LenovoP50
    Then paste in the following text:

    # place script commands here that should execute every time for every FOS action
    ## We need this command to run to enable the software raid on the Lenovo P50
    mdadm --build /dev/md0 --raid-devices=2 --chunk=16 --level=0 /dev/sda /dev/sdb
    # I added some additional check here just in case you wanted to highly customize the postinit script's actions. This section is not mandatory.    
    if [[ -n $mode && $mode != +(*debug*) && -z $type ]]; then
        case $mode in
                # fog wipe disk
                # fog check disk
                # fog disk surface test
                # fog quick registration
                # fog full registration
                # fog full inventory
                # fog quick image
                # all other generic operations
        # place script commands here that should be run for any of the utility functions
        case $type in
                # fog image deploy
                # fog image capture
                # the code should never get here, we'll just add so the script doesn't break
        # place script commands here that should be run for either image capture or deploy

    Now to call our custom postinit script fog.LenovoP50 we need to append the fog hook bash script fog.postinit with following line.

    . $postinitpath/fog.LenovoP50


  • #wiki worthy

  • Moderator

    Part 2 Advanced Postinit script

    The above custom postinit scrip will execute for every hardware model we have. Its possible that those commands in our /images/dev/postinitscripts/fog.LenovoP50 are only relevant for the Lenovo P50. We need to provide some kind of selector program to run the fog.LenovoP50 only when a Lenovo P50 is detected and at no other time.

    To do this we can use a FOS utility called dmidecode to read the target computer’s SMBIOS settings to help identify what computer the target computer is and then select the most appropriate postinit script to run.

    In this example we are going to use these three different SMBIOS queries to help identify the motherboard manufacturer and model.

    This query will detect the hardware manufacturer of the motherboard:
    dmidecode -s baseboard-manufacturer

    Dell is a bit unique and places the system name (i.e OptiPlex 9020) in this smbios location:
    dmidecode -s system-product-name

    For almost all manufacturer (I believe lenovo too) you have to use this location:
    dmidecode -s baseboard-product-name

    Its a trival issue, you just need to be aware that if you don’t get the answer you expect, you might want to look about at different smbios locations. There are no absolute rules here. It is up to the system board manufacturer to decide where things go.

    In the example below we’ll create a new selector program that will detect the motherboard type and run the fog.LenovoP50 postinit script only when a P50 is detected.

    Lets start by creating a new bash script
    touch /images/dev/postinitscripts/fog.ACME.selector
    chmod 755 /images/dev/postinitscripts/fog.ACME.selector
    vi /images/dev/postinitscripts/fog.ACME.selector

    Now paste the following into the fog.ACME.selector script

    sysmanufact=$(dmidecode -s system-manufacturer | tr -cd '\40\60-\176')
    if [[ -z ${systemanufact} ]]; then
        #system manufacturer is blank so try to pick up name from baseboard
        # / motherboard value
        sysmanufact=$(dmidecode -s baseboard-manufacturer | tr -cd '\40\60-\176')
    case ${sysmanufact} in
            machine=$(dmidecode -s system-product-name  | tr -cd '\60-\176')
           # Do this for all other machines i.e. Intel and Lenovo
            machine=$(dmidecode -s baseboard-product-name | tr -cd '\60-\176')

    Now with this code snippet above we have the system manufacture name stored in $sysmanufact variable and the machine model name stored in $machine. From here we can create a conditional if statment and only call our Lenovo postinit script when the machine matches what we just pulled out of the running target system with dmidecode.

    # Test to see if the machine name matches P50, if so then call our custom  postinit script. 
    if [[ ${machine} == "P50" ]]; then
        . $postinitpath/fog.LenovoP50

    The last part we need to do is update the fog.postinit hook script with the name of our selector script.

    In the /images/dev/postinitscripts/fog.postinit remote the line . $postinitpath/fog.LenovoP50 and replace it with this line . $postinitpath/fog.ACME.selector

    Thats all there is to it. The FOG postinit selector script will be called every time from the FOG postinit hook script, but the fog.LenovoP50 will only be called when a Lenovo P50 is detected.

    Please note: I used the Lenovo P50 throughout this document. Its been a while since I worked with Lenovo products but I know they are actually referenced by their internal ID. I might expect the smbios code to return a value like 20EN001SUS instead of P50. I only used the term P50 for consistency throughout this document


  • Moderator

    This post is deleted!