Collecting GUIDs for RIS prestaged computer accounts with NetBSD

Abstract:

One of the most time consuming and repetitive tasks in supporting an organization with a large number of computers is the handling of turnover of old computers as they become obsolete and new machine orders. A typical setup consisted of copying down the MAC addresses and destination hostnames on a piece of paper, typing them up and emailing them to someone else, wait for that person to update the DHCP server, create a station and config file for the new computer account, etc., etc. This project is to reduce the amount of human intervention needed to set up a machine.

Disclaimer:

I chose NetBSD for this project because it's most familiar to me. I have no doubt that someone could accomplish the same results with Linux and BusyBox, or any other combination.

I do not cover site security measures and common sense service lock down. Obviously if anyone on the internet can connect to your database server and create a host record, you have a security problem.

Jump to a section:

Concept:

"What we're trying to do here is..." simplify workstation setup so that as many repetitive tasks as possible are eliminated. A while back someone realized that a significant portion of the support staff time is spent typing emails and waiting for another staff member to do something that they didn't have permission to do themselves. Workstation installation and upgrades is just one small facet of the big picture, but I believe it's the most taxing and time consuming. After a little flow charting and discussion, we settled on the following procedure:

  1. Boot the client system from some type of removable media device. I use USB flash drives and CDs. With a little more effort, one could probably fit the kernel on a floppy as well.

  2. Request a DHCP lease using a dhcp-client-identifier so that the client can get a static temporary IP to upload the data to the server.

  3. Download a list of valid OUs from the server with FTP, and display it on screen.

  4. Prompt the user to enter the desired hostname of the machine, a destination OU, and confirm that the probed MAC address, serial number, and GUID look sane.

  5. Using the NetBSD FTP client, we request a URL similar to http://server.com.edu.biz.net/compreg.php?HOSTNAME=$HOSTSNAME&MAC=$MAC&GUID=$GUID&...

    With the -o file output option we take the results from the servers script operations and check for an error. If there's an error prompt to retry, if not we ask to reboot or shut down the system. Though since no file systems are mounted, you can just hit the power switch.

  6. The server side scripts scan for duplicate GUIDs, MAC addresses, serial numbers, and sends a ping the specified host name. If the host is alive it sends back an error and drops the request, if everything else looks good, the host entry is added to the database or any matching records are marked for deletion and then it's added with an update flag set. Another script scans the database for records with the update or delete flags set. Using the updated information, that script fires other scripts to:

    Now we have a prestaged computer account, updated dhcp, updated asset information, and removed old data almost completely automatically. What use to take the time of up to four people is now down to at most 2, usually only one.

Back to top

Requirements:

Back to top

Setup:

I highly recommend you read Building an embedded NetBSD system before you attempt this so you can understand what's going on.

  1. Patch and build DMIdecode

    This patch is against version 2.5 of DMIdecode. Basically all it does is remove spaces from the output and use unique names for information I'm interested in. This lets me get away with grep and cut instead of having to add sed and awk.

    
    --- dmidecode.c 2004-10-14 14:33:20.000000000 -0400
    +++ ../../dmidecode-2.5/dmidecode.c     2004-12-23 11:46:25.000000000 -0500
    @@ -316,7 +316,7 @@
                    return;
            }
            
    -       printf(" %02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
    +       printf("%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
                    p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
                    p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
     }
    @@ -2831,13 +2831,13 @@
                    case 1: /* 3.3.2 System Information */
                            printf("\tSystem Information\n");
                            if(h->length<0x08) break;
    -                       printf("\t\tManufacturer: %s\n",
    +                       printf("\t\tSystem Manufacturer:%s\n",
                                    dmi_string(h, data[0x04]));
    -                       printf("\t\tProduct Name: %s\n",
    +                       printf("\t\tSystem Product Name:%s\n",
                                    dmi_string(h, data[0x05]));
    -                       printf("\t\tVersion: %s\n",
    +                       printf("\t\tVersion:%s\n",
                                    dmi_string(h, data[0x06]));
    -                       printf("\t\tSerial Number: %s\n",
    +                       printf("\t\tSystem Serial Number:%s\n",
                                    dmi_string(h, data[0x07]));
                            if(h->length<0x19) break;
                            printf("\t\tUUID:");
    @@ -2856,7 +2856,7 @@
                                    dmi_string(h, data[0x05]));
                            printf("\t\tVersion: %s\n",
                                    dmi_string(h, data[0x06]));
    -                       printf("\t\tSerial Number: %s\n",
    +                       printf("\t\tBase Board Serial Number: %s\n",
                                    dmi_string(h, data[0x07]));
                            if(h->length<0x0F) break;
                            printf("\t\tAsset Tag: %s\n",
    
  2. Setup a crunchgen config file to build a crunched binary.

    CrunchGen config file example

    # List of directories to search for the object code of the programs we want to include
    srcdirs /usr/src/bin /usr/src/sbin /usr/src/distrib/utils /usr/src/usr.bin

    # Programs we want crunched
    progs init sh reboot ls x_dhclient route ftp mount newfs mount_ffs cat cut grep ifconfig mv rm sleep tput

    # make a link from sh to -sh in the event that a script or program calls -sh
    ln sh -sh

    # mount_mfs is a link to newfs
    ln newfs mount_mfs

    # List of libs that crunchgen needs to examine for dependencies
    libs -lz -lutil -lcrypt -ll -ledit -ltermcap -lm

  3. Configure and build a kernel

    You will need at least the following sets from the NetBSD FTP site:

    1. Extract the sets somewhere and customize the INSTALL kernel in src/sys/arch/i386/conf or copy my kernel config there.
    2. cd to the base src directory
    3. mkdir ../obj
    4. ./build.sh -m i386 tools kernel=KERNELCONFIGFILENAME
    5. Wait a long time for the compile to finish
    6. cd to the directory listed at the conclusion of the compile and copy the file netbsd to where the crunchgen config file is located with a .md or some identifying extension to show it's not the final kernel.

  4. Run make in each of the program directories listed in the crunchgen config file to generate the program objects
  5. Run crunchgen -m Makefile crunchgenconfigfile.conf
  6. Run make
  7. Set up the target file system tree directories, file system links, and fstab.

    create bin,etc,dev,root,sbin,var,var/db,var/run

    /etc/fstab need only contain the line "/dev/md0a / ffs rw 1 1"

    /etc/dhclient.conf should have something like "send dhcp-client-identifier "Reaper";"

  8. Customize /etc/rc to do what you want
  9. copy the dmidecode binary and your crunched binary to the tree
  10. run makefs to create the file system image. Note that the makefs file system size option must be smaller than the size specified in the kernel config file.
  11. run mdsetimage to stuff the file system into the kernel you copied earlier.
  12. gzip the kernel to "netbsd".
  13. bootstrap the install media and copy the kernel to it
  14. Try booting it. Remember that some BIOSs require that USB Emulation be enabled to boot from USB and that not all BIOS versions support all usb devices.

Back to top

Making bootable media:

Bootstrapping is fairly straight forward. Installboot and the associated files in /usr/mdec should let you boot FAT, FFS, and ISO9660. I have successfully booted USB key chains that use SCSI over bulk transfers on all the machines that support booting from USB. However, I've only had success using key chains that use ATAPI over bulk on the latest Intel 915 boards.

ISO9660 booting is a bit more complex. You'll need to create a 1.44 or 2.88 MB floppy image with makefs. Then use vnconfig to attach the image file so that you can boot strap it. Once you have that image set up and boot strapped you can write it to a CD using El-Torito floppy disk emulation with cdrecord or your favorite cd mastering application.

Back to top

Database table structure:

Since we are only using the DB to create a dhcpd.conf file and a flat hosts file, the table is pretty sparse. There's no reason you couldn't use DMIdecode to dump the processor name, type, speed, model, stepping, cache sizes and speeds, etc.

variable var type type
Hostname varchar(255) Primary key and unique
IP varchar(255) unique
MAC address varchar(255) unique
GUID varchar(255) unique
Serial number varchar(255) unique
Destination OU varchar(255)
Comments varchar(255)

Back to top

Server side script examples:

The scripts are going to depend on what database and script solution you want to use. We are using PHP MySQL, Perl, and ActivePerl. If you get stuck on something here, feel free to email me. We are still working out some of the special cases, so I prefer not to post what we have until it's been tested some more.

Back to top

Links:

Back to top

Possible future additions:

Legal:

Valid HTML 4.01!