Deploying a single golden image to different hardware with FOG

  • Moderator


    The bits I’m going to cover here are the general outline of what needs to be done to create and deploy a hardware independent image across your fleet of computers. In this tutorial I’m going to discuss how to do this with Dell computers. I know this process works with Lenovo, Intel NUC, and a few others with some caveats. I’m going to touch on some steps that you need to do in MDT to build your universal reference image, but I’m not going to discuss how to setup MDT to create your reference images. There are plenty of examples on the internet on how to do this.

    This process makes use of a custom script that gets executed post image deployment but prior to the reboot of the FOS client. This step is vial since we need to make some tweaks to the windows environment pre first windows boot. This is the key. I can’t/won’t share that script I created because of my contract with my employer, because it is derived work because of my employment. So that script is intellectual property of my company. I’ve held the job title of unemployed, its not a great title. The pay stinks, the stress level is high, but the hours are great. I don’t plan on going there any time soon, so no script for you. BUT, sitting here on my zorin (ubuntu) dell laptop I should be able to reverse engineer the important parts to give the crafty scripters here the tools they need to create their own post install script.

    Our master image is created following the standard Microsoft SOE guidelines, meaning MDT to build the reference image, sysprep to reseal the image, use a custom unattend.xml file (required to make this process work for Win10) and some disk imaging tool to capture and deploy the image to the target hardware. In this process sysprep is mandatory since we want to create a single image that can be deployed to any hardware. The generalize process of sysprep removes all hardware references (for the reference image) so that when windows first boots it goes through the hardware discovery process. Without sysprepping the image the process I’m going to discuss will not work. So use sysprep.

    When I started out creating this process for FOG, I began with the process we created for deploying Windows XP from a usb stick using Ghost. In that process we would automate the image deployment with ghost to lay a hardware independent image onto the target hardware and then detect the current hardware using a DOS program that would query smbios to get the target hardware. Then once the target hardware was known we would move the correct driver pack into a location where windows would find it on the first boot. This worked extremely well with Windows XP. So I took the knowledge that I had from that process and tried to do something similar with FOG.

    I do have to say I did not think up this entire process all by my self. I did start the design base on the information found on this wiki page. This page and associated scripts gave me just what I needed to take our xp/ghost process and covert it to windows 7/FOG. So without that wiki page the remainder could not be possible.

  • Moderator

    Part 1 MDT setup

    For this process we use MDT and the lite touch method to create our reference image. As I noted above, I’m not going to discuss any parts of setting MDT up for the lite touch. But I will say that it took me about 3 days to go from never touching MDT to capturing my first reference image with FOG. So its not that hard to learn. I do have to say that our reference image is built on a vSphere virtual machine. We used this method since the vm virtual machine doesn’t require any hardware specific drivers to make the system deploy. All of the MS native drivers work for this host system. Using a virtual machine is the recommended method when creating a clean reference (golden, mother) image or what ever you want to call it. You can create your reference image on real hardware no problem, but its a bit slower. Also using a virtual machine you can create snapshots of your reference system as you develop your golden image. It saves time having to rebuild the image for each tweak in the task sequence. In the beginning I was taking a vm snapshot prior to sysprepping as I was working on the unattend.xml file. It saved a bunch of time.

    For Dell hardware this web site will save you a bunch of hunting around for model specific drivers. I recommend you bookmark it since you will use it a few times.

    Back to MDT. From the website above you will want to download the WinPE 3.x driver cab.
    I also recommend that you install winzip or 7-zip on your workstation since we will use one of those to extract the cab file. Its much faster to use 7-zip than the extract command on the cab files, believe me

    What you want to do is install the Dell WinPE 3.x driver cab into MDT Out of Box Drivers section. This will install all of Dell boot time drivers so that your reference can boot on any Dell target hardware. This step is not specifically required for building a reference image on a VM. What it does do is preload Dell’s common drivers into your reference image build in case you don’t get your fog post install scripts just right during development your target computer will have at the minimum disk and network access. As I said this part may not be necessary. I loaded them from the beginning of developing the process and it worked. I never did try to remove them to see if the process broke. I found a path that worked reliably and stuck with it.

    Now one of the keys to this universal image process is we need to tell our reference image where to look for drivers when new hardware is detected. So one of the last task sequences in the MDT build process updates the following registry key “HKLM\Software\Microsoft\Windows\CurrentVersion\DevicePath” to include a folder path of my choosing. In this example I’m going to place my target specific files in C:\Drivers. Originally I just appended C:\Drivers to the device path until I ran across trying to deploy to a Dell 780. The Optiplex 780 has a sound card that is supported by the native windows driver except for one specific thing. The native windows driver (found in the c:\windows\inf folder) doesn’t support the use of internal speaker. Everything else worked great as long as you connected an external speaker to the 780. But if you use the Dell sound driver the internal speaker worked as it should. So to avoid this type of issue I have windows search the c:\driver folder first then the c:\windows\inf folder. With all 15 models in my fleet, all of them work perfectly searching for drivers in this order.

    So back to MDT, that task sequence uses the windows REG.EXE function to update the above mentioned key with this value. “C:\Drivers;%SystemRoot%\inf;” and we force that registry key to be set even if it previously exists. Note: for Win10 this registry key is no longer used. You will need to insert a section into your unattend.xml file that will instruct the installer do the same thing as this registry key

    At the end of the MDT build process I have a batch file that runs the sysprep command with the required parameters. The sysprep command might look similar to this: sysprep.exe /quiet /generalize /oobe /shutdown /unattend:C:\Windows\panther\Unattend.xml

    So from there once sysprep process completes the virtual machine will shutdown. I then pxe boot the vm into fog and capture the image as you would normally.

    You can do Part 1 without using MDT. You will just put windows into audit mode as you install it from DVD. You will have to manually update the registry and install the Dell WinPE 3.0 driver cab, but it is possible to get the results without MDT. We use MDT to automate this entire process so we get the same exact results every time we build the golden image. We go this route so we don’t have to deal with the reseal count or any of that mess. The other part I didn’t add above is that MDT will install all of the windows updates during the reference image build process. So our reference image will have all of the update at the time of image capture. Since its all automated from the image deployment, windows updates, and applications install you just start the build process and walk away. When you come back the image will be ready for sysprep and image capture.

  • Moderator

    Part 2 Driver package setup

    The disk structure to hold the actual drivers we will setup on the fog server will look something similar to this

    /images/drivers/{hardware_type}/{os_type}/{arch}/{driver files}

    So for a Dell Optiplex 7010 drivers for windows 7 x64 the directory path will look like this

    /images/drivers/Optiplex7010/win7/x64/{driver files from dell cab}

    This structure is important since we will use a bash script to identify the correct hardware and to move the appropriate driver files to the target computer in our post install script. I found its much easier to build this entire structure on a Windows system then use 7-zip to create a single (or multiple) zip files to your fog server and then unpack them on the fog server.

    You will want to use the Dell web site that I recommended for you to bookmark above to locate the proper driver cabs for your hardware fleet. Download these cab files for the proper Windows OS to your windows computer. Use 7-Zip to extract the cab files into a similar disk structure to what we will use on the FOG server. You MUST remember that case IS important here so watch your case. The only directory that will use upper case is the hardware model parent folder. In the case of the script I’ll outline later I remove all spaces and non-ascii characters from the model name, but case is preserved. So on your windows computer create a parent folder called C:\drivers (note the lower case name) Then create the hardware model name as they come from smbios (actually on linux we’ll use the dmidecode command to extract the model name. And then below the model name create 2 folders called win7 and win10 (if that is the OS you will support). Now open the cab file for the proper model with 7-zip and copy the x86 and x64 folders to the proper driver location in the path from above. It WILL take some time to create this structure. After the first 2 or 3 hardware models you will get the process down and the remainder will go pretty quickly.

    To save you some time here are the names of the Dell systems named I have in my driver library.
    LatitudeE6400, LatitudeE6410, LatitudeE6420, LatitudeE6220, LatitudeE6430, LatitudeE6230, LatitudeE7440, LatitudeE7240, LatitudeE7450, LatitudeE7250, LatitudeE7470, LatitudeE7270, OptiPlex780, OptiPlex790, OptiPlex7010, OptiPlex3010, OptiPlex9030, OptiPlex3020, VMwareVirtualPlatform

    Remember: CASE IS Important for Linux. These are the systems names that come out of smbios, with the spaces removed.

    {note: upload an empty template driver zip file here}

    I do have to give you one word of warning when deploying non Dell drivers. I can say that all of the Dell drivers I’ve found so far have been signed. If you deploy a driver (like for lenovo or intel nuc) that is not signed it will not install with this method. You can get it to install properly if you install the driver’s unsigned certificate in the golden image. It kind of a pain in the butt to work with unsigned drivers but you still can make them work with this process.

    One other comment on drivers, this posted method will only work if your drivers are in the extracted form (i.e. not embedded in a .exe, .zip, or .cab file. This only works for extracted drivers out of their containers. The dell driver cab has the drivers in the correct form for this process already. I can say that 90% of the drivers for the Panasonic Toughbook come in .exe form. This is also a pita to work with. BUT if you are cagey you can start to install the .exe drivers, but before you press the OK to install driver button, check %temp% directory. Sometimes the .exe installers will extract the drivers to that location before you press the OK to install button. Glean the drives from that location first then cancel the .exe driver install program.

  • Moderator

    Part 3 The post install script I can’t show you

    FOG has the ability to run user defined scripts post image deployment. These scripts are placed in the /image/postinstallscripts folder. These user defined scripts are call from the master script called fog.postinstall {verify names typing from memory}. These scripts are executed on the FOS client post image deployment (it is important to remember this fact). The FOS client has access to the local hard drive as well as the FOG server to the NFS share.

    For the sake of this (wall of text) lets call this user defined script fog.driverinstall (reminder I can’t post the actual script here only the general concepts)

    This driverinstall script should first set a few variables that will be used during the script. This example will be for windows 7 only, but one could reference the fog parameter $osid to find out the exact OS that is being deployed by fog.

    # windows 7

    Remember this script is running on the FOS client so we will need to connect the FOS client to both the local hard drive and the FOG server. Since this script can’t/shouldn’t rely on what other fog scripts have done already, some of the following steps are redundant but they do function.

    We need to connect back to the local hard drive. Windows 7 (C: drive) is located in the second partition on the local hard drive

    # create a directory to hang the Windows C: drive partition on
    mkdir /ntfs 2>/dev/null
    # mount that C: drive partition on the directory we just created
    mount.ntfs-3g "${osdiskpart}" /ntfs 2>/tmp/mntfail

    You will probably want to do some error checking here to make sure the mount command worked.
    Create the local drivers folder on the deployed windows hard drive.

    # Just in case MDT didn't create the driver directory make it here
    mkdir /ntfs/Drivers 2>/dev/null

    Now we’ll do a quick hack to see what OS architecture was deployed to the target computer

    # check to see what arch was installed on the target
    if [ -d "/ntfs/Windows/SysWOW64" ]

    While this next part isn’t important since we are deploying to Dell computers you may need to know the manufacture name since other hardware places the machine model in different locations in the smbios. One might want to put a select case statement in based on the manufacture name. This command uses dmidecode to query for the system manufacturer value from smbios. If the sysmanufact variable comes up blank you may need to query the baseboard element of smbios instead of the system element.

    # query the smbios system element to pick up the manufacturer name
    sysmanufact=`dmidecode -s system-manufacturer `;
    # strip out any embedded spaces in the manufacturer name

    Now we can pick up the model name from the target computer.

    # query the smbios to pick up the product name i.e. OptiPlex 7010
    machine=`dmidecode -s system-product-name`;
    # Pull out any spaces in the machine name

    In the command above I’m querying the machine name from the system element of the smbios. The second line just removes any spaces in the machine name. I’m doing this because the machine name is part of the driver path. Removing the spaces keeps me from having to escape them.

    You may want to write the detected values into the C:\Drivers folder. You may need this information as you develop the directory structure for new hardware. This way you can see exactly what the script is detected.

    # Write out what we detected to a text file on the C: drive in case we need to inspect what happened
    # later (post image boot). You may need this information for debugging purposes or new hardware detection
    echo "Detected [${sysmanufact}] [${machine}] [${driverver}] with this arch [${setarch}] " >> /ntfs/Drivers/machine.txt

    This next part is where we get down to business. First we’ll create a link to the actual driver path on the fog server to a temp folder. I originally had to do this when there were spaces in the driver file path. The filter above removed that requirement. I left this in my code because it allowed me to use a smaller path on the copy command.

    # Remove any legacy links and build a new link
    rm -f /tmp/mydrivers;
    # Create a new link between the physical driver path an a local (short name) path
    ln -s "/images/drivers/${machine}/${driverver}/${setarch}/" /tmp/mydrivers;

    And finally we copy the driver files from the fog server to the C:\Drivers folder on the target computer.

    # Check to ensure the required driver folder exists. If it doesn't exist something happened
    # with the link statement (i.e. the driver path was not found)
    if [ -d "/tmp/mydrivers" ]
        # move the files from the FOG server to the C: drive partition
        cp -r /tmp/mydrivers/* /ntfs/Drivers;
        # Oh crap something happened, I wasn't able to map/find the drivers to copy

    And finally you will need to do some cleanup work at the end of the script.

    # do a little house cleaning and remove the directory link
    rm -f /tmp/mydrivers;
    # unmount the FOG server nfs share
    umount /ntfs

    Please remember the above script fragments do not make a complete script. They are only the critical bits that I hacked together to make a logical program flow. If you use them to create your own bash script you will need to add a bunch of error checking to make sure things are where they need to be when they need to be there.

  • Moderator

    Part 4 Short version (summary)

    1. Add Dell WinPE 3.0 drivers to out of box drivers in MDT
    2. Create a folder called C:\Drivers (watch the case)
    3. Add a task sequence to MDT to change the registry key “HKLM\Software\Microsoft\Windows\CurrentVersion\DevicePath” to this “C:\Drivers;%SystemRoot%\inf;C:\Drivers;%SystemRoot%\inf;”
    4. On a windows computer setup the driver directory structure as in drivers/{hardware_type}/{os_type}/{arch}/{driver files}
    5. Download and extract the driver from the cab files and place them in the correct directory location
    6. Use 7-zip to compress all files and directories below drivers into a single zip file
    7. Move that zip file to your fog server /images directory
    8. Use the linux command unzip to extract the zip files onto the FOG server
    9. Create your fog.driverinstall script and place it in /images/postinstallscripts directory
    10. Update the fog.postinstall script to call your fog.driverinstall script
    11. Deploy your image.

    You can use FOG’s built in deploy debug task to work on and debug your script. You can also use the FOS client to query the smbios with the dmidecode command as you develop drivers for new hardware. (I personally find it easier to deploy to new hardware then just read the content of the machine.txt file to see what the script detected. With this process you can add new computer hardware at any time by just creating the driver structure in /image/drivers. There is no need to recreate your golden image for each new hardware that you choose to deploy to.