Last updated at 2016-07-06 13:53:15 by oucs0089

Modifying Orchard NetBoot Offerings

Orchard's NetBoot service runs on a Debian GNU/Linux virtual server and replicates much, but not all, of the functionality of a Mac OS X Server based NetBoot service. This document provides some background information on NetBoot, and general instructions on adding a new NetBoot set to the server. Instructions on how to set-up your own NetBoot server in your department will be published soon.

Terminology

  • NetBoot: A service that allows a Macintosh to boot up over a TCP/IP network from a NetBoot set hosted on a server, so that the local system disk, if present, is not used as the boot volume. Broadly, this can be thought of as booting off an external disk that is located across a network.

  • NetBoot set: A folder that resides on a NetBoot server containing boot components, identifying information, and a disk image of a bootable system volume. Multiple NetBoot sets may be offered by a NetBoot service, with a default set always designated.

  • Diskless NetBoot: Because the bootable system volume of a NetBoot set is made available to the client with read-only access, any filesystem changes that take place during the NetBoot session, including writes to swap, must be written to some other storage. By default, a local volume on the client is used for this writable storage, but this dependency makes manipulations of that volume such as reformatting and imaging impossible. To avoid this limitation, a NetBoot set can be configured such that it will use alternative storage locations for this task - this is known as Diskless NetBoot.

  • BSDP: Boot Service Discovery Protocol is the name of Apple's NetBoot discovery and configuration protocol, which is designed to be encapsulated within DHCP packets using certain vendor specific options (see options 43 and 60 in RFC 2132, and Apple's BSDP documentation). While sometimes referred to as 'BSDP packets', these are in fact normal DHCP packets that simply encapsulate BSDP information in a standard way.

Background Information

The most basic Macintosh NetBoot service has three essential components:

  • A specially configured DHCP service, to respond to BSDP requests (encapsulated in DHCP packets).
  • A TFTP service, to allow downloading of initial boot files from a NetBoot set by the client.

  • An HTTP or NFS service, to provide read-only access to the disk image containing the system volume for the NetBoot set.

These services do not have to be running on the same server, although it is typical that they are.

When a Mac is instructed to NetBoot (for example, when started with the 'N' key held down), it will first attempt to obtain an IP address via the normal DHCP process. After obtaining an IP, the Mac will send out a BSDP request encapsulated in a different DHCP packet that is recognised by the specially configured DHCP service on the NetBoot server, which may or may not be the same DHCP service that provided the IP address moments before.

The initial information from the client informs the NetBoot server of the client's hardware type, and the server responds by offering a list of platform-appropriate NetBoot sets. The client responds with a selection, and finally the server responds with all the necessary information for booting from the selected set. At a minimum, four packets of BSDP information are exchanged before the client can begin its initial NetBoot.

The server must always offer one default NetBoot set, which is automatically selected by the client when booting with the 'N' key depressed. Additional NetBoot sets can be viewed and selected by booting with the 'Option' key depressed on newer Macintoshes. The option to view and select NetBoot sets via the 'Startup Disk' preference pane in System Preferences is not currently available when using a non-Apple-provided NetBoot service, due to nonstandard ports on which the Preference Pane expects to receive the server's BSDP responses.

In order to offer Diskless NetBoot functionality, a NetBoot server typically has to offer a fourth service: a read-write network share to which filesystem changes and swap data can be written, with a special directory structure created to accommodate each client's NetBoot sessions. However, to sidestep the complexity involved in re-implementing this, we modify a startup script on our NetBoot images so that clients instead create and mount a RAM-disk at boot. This provides a small but adequate amount of local, off-disk, read-write storage for changes to be written to, obviating the need for a network based solution.

Since all DHCP communications are initiated by a client broadcasting on the local network, they cannot directly reach a NetBoot server located on another subnet. This limitation is overcome via DHCP Relaying, which when working with Cisco routers is achieved by configuring one or more IP Helper Addresses on each subnet. These IP Helper Addresses can point to various DHCP servers external to the subnet, including NetBoot servers. Therefore, it is usually necessary to request the addition of an IP Helper Address in order to make the NetBoot service available on a new subnet.


Adding a NetBoot Set to the Server

Step 1: Transferring a new NetBoot Set

NetBoot sets are stored in the directory /srv/netboot/<service_fqdn>/sets/ on the NetBoot server. This directory is writable by users in the group NSMS\nsms_group, to which all NSMS staff AD accounts should belong.

Before transferring a new NetBoot set to the server, confirm the following:

  • There is adequate space on the server's /srv partition for the new set.
  • The .nbi folder's name is unique and contains no spaces.

  • The index number of the set is unique among sets already present, and between 1 and 65535 (index numbers above 4095 are normally used for images common across multiple NetBoot servers).

The Index of a set can be found in the Index key of the NBImageInfo.plist file within the .nbi folder.

Connect to the NetBook server then use rsync to transfer the new NetBoot set to the server, as shown below. If updating an existing set, the --ignore-existing option can be omitted to allow overwriting of files.

user@netboot.server:~$ rsync -r --ignore-existing --progress <user>@<source_host>:<New_NetBoot_Set>.nbi /srv/netboot/<service_fqdn>/sets/

Step 2: Replacing an existing NetBoot image by adhering to the naming scheme

Updating an existing NetBoot image, i.e. 10.9.1 to 10.9.2, does not require a major change in the DHCP service configuration (see below) as long as one sticks to a few conventions:

  1. The .nbi folder's name is Orchard-NetBoot_<OSVERSION>-<OSBUILD>-<NSMSREVISION>.nbi, i.e. Orchard-NetBoot_10.8.5-12F45-23.nbi (23rd revision of the 10.8.5 NetBoot image). The image name can be created using the following convenient command in the running NetBoot systen:

    NSMS_REVISION=1; echo "Orchard-NetBoot_$(sw_vers -productVersion)-$(sw_vers -buildVersion)-${NSMS_REVISION}.nbi"
  2. The NBImageInfo.plist within the .nbi folder has to contain the following values:

    • Index must match the designated index for the major OS:

      • 1024 = 10.10 (image id 01:00:04:00)
      • 2048 = 10.9 (image id 01:00:08:00)
      • 2096 = 10.8 (image id 01:00:10:00)
    • Name must match the user friendly display string Orchard NetBoot <MAJOROSVERSION>:

      • Orchard NetBoot 10.10

      • Orchard NetBoot 10.9

      • Orchard NetBoot 10.8

    • Description should contain the same information as the .nbi folder name and potentially a date the image was last updated and by whom.

  3. The dhcpd.conf needs replacing the filename and option root-path in the relevant if option BSDP.selected_boot_image_id section. Please note that the dhcpd.conf is under version control and managed by puppet.

Directory Structure of a .nbi folder

For reference: the directory structure of every .nbi folder should be as follows

Orchard-NetBoot_10.9.1-13B42-1.nbi/
Orchard-NetBoot_10.9.1-13B42-1.nbi/NBImageInfo.plist
Orchard-NetBoot_10.9.1-13B42-1.nbi/i386
Orchard-NetBoot_10.9.1-13B42-1.nbi/i386/booter
Orchard-NetBoot_10.9.1-13B42-1.nbi/i386/PlatformSupport.plist
Orchard-NetBoot_10.9.1-13B42-1.nbi/i386/x86_64
Orchard-NetBoot_10.9.1-13B42-1.nbi/i386/x86_64/kernelcache
Orchard-NetBoot_10.9.1-13B42-1.nbi/NetBoot.dmg

.

Step 3: Reconfiguring the DHCP Service (optional)

Once the new NetBoot set is on the server, we must add its information to the DHCP server configuration in order for it to be offered to clients.

We use the ubiquitous ISC DHCP, which has its configuration file located at /etc/dhcp/dhcpd.conf on the server. However, the file is managed using Puppet, so you must instead edit the file /config/puppet/dist/<service_fqdn>/etc/dhcp/dhcpd.conf in the NSMS Subversion repository. Instructions on updating a config file via Puppet can be adapted from the Apache config instructions given here.

Please use a copy of the existing dhcpd.conf file to follow along with the documentation that follows:

The rules set up in the configuration file are consulted every time the DHCP server receives a DHCP packet from a client. If the configuration file specifies a test to be performed on a parameter, it is implied that that this parameter is one found in the packet received by the server, which is being acted upon. If a parameter is simply indicated with a value, it is implied that this parameter will be included in the packet that may subsequently be sent back to the client.

Our dhcpd.conf file uses a custom class to handle packets containing BSDP data: class "Apple-i386-NetBoot". Changes to the file that we will make to add, remove, or modify NetBoot set offerings will all be confined to this class. However, we rely on settings elsewhere in the file to instruct the server to ignore packets from unknown hosts and, by omission, to do nothing with packets representing requests for IP addresses and other standard network configuration information (since we rely on the University's main DHCP servers for this).

The rules defined in our Apple-i386-NetBoot class are therefore consulted only if the received packet has not been disqualified by the conditions mentioned above, and if other parameters of the packet (its vendor-class-identifier) identify it as being from an Intel Mac requesting NetBoot information.

The rules are further enclosed in an if-statement that ensures that the DHCP packet is of the correct type. If the statement's test is successful, the DHCP server is instructed to label its returned packets with a related vendor-class-identifier value so that the client can recognise them as BSDP responses.

Now, we've reached the main rules. These rules are divided into two sections, each enclosed by an if-statement with mutually exclusive conditions, for the two types of queries and responses the server can handle:

  1. if option BSDP.message_type = 1

  2. if option BSDP.message_type = 2

'LIST' Section Overview:

BSDP.message_type = 1 indicates a BSDP LIST query (from the client) or response (from the server). These are encapsulated within DHCP INFORM and ACK packets, respectively. LIST refers to a listing of available NetBoot sets for the client's platform (platform being more of a historical concern for handling PowerPC and Intel Macs differently). Thus, the query from the client is a request for the list NetBoot sets it may use, and the response from the server provides that information. In more detail, the server's response contains the following parameters:

  • The IP of DHCP server that is responding to the BSDP LIST query
  • The server's priority (relevant should more than one NetBoot server respond to the client - a server may adjust its priority based on load)

  • The ID of the default NetBoot set

  • (optionally) The ID of the last NetBoot set the client chose on this server, if the server has this information on record.

  • The list of available NetBoot sets

As you can see from the way these parameters are set in the configuration file, we are in some cases using static values for certain parameters that would be dynamically generated by a 'real' (Mac OS X Server based) Mac NetBoot server: for example, load-based priority adjustment, or storage of previous NetBoot choices by the client. For our purposes, however, this is not much of a problem.

'SELECT' Section Overview:

BSDP.message_type = 2 indicates to a BSDP SELECT message from the client or response from the server (again encapsulated within DHCP INFORM and ACK packets, respectively). The client's SELECT message contains the NetBoot set it has chosen from the server's LIST response, and the server's subsequent SELECT response contains the following parameters which enable the client to find the resources to boot from its selected set:

  • A confirmation of the identity of the selected NetBoot set

  • The IP address of the TFTP server with the necessary boot components for that NetBoot set

  • The complete path to the booter file on the TFTP server

  • The URL of the disk image for the system disk of that NetBoot set

  • The Computer Name to be used by the NetBooted Mac while it is running.

With this information, it should be somewhat more clear as to what we are doing when we edit the dhcpd.conf file to add, modify, or remove NetBoot sets.

'LIST' Section Editing:

Let's go back to the first section, where we deal with BSDP 'LIST' queries:

There are three parameters we may want to modify here, with somewhat self-explanatory names, but cryptic values:

  • BSDP.default_boot_image_id

  • BSDP.selected_boot_image_id

  • BSDP.boot_image_list

Each 'boot image ID' (either 'default' or 'selected') is a sequence of 4 bytes separated by colons, written in hexadecimal. The first byte indicates the type of image contained in the NetBoot set ('1' for an OS X Client OS for NetBoot rather than NetInstall), the second byte is unused ('0'), and the last two bytes represent the NetBoot set's Index number.

For example, the boot image ID 01:00:00:7B can be broken down as follows:

01:

00:

00:7B

Mac OS X Client system for NetBoot

(unused byte)

The NetBoot set's Index is 123 (decimal), which is 7B in hexadecimal

Incidentally, it should now be clear why NetBoot set Index numbers have a range of 1 through 65,535.

With this information, we can set the BSDP.default_boot_image_id and BSDP.selected_boot_image_id parameters, if we are changing the default NetBoot set. The two values should be the same - remember, we're faking some Mac OS X server functionality here. You can convert decimal to hexadecimal using Calculator.app, or in the Terminal with the following command:

printf '%x\n' <decimal number to convert>

The hexadecimal parameter values are not case sensitive.

The BSDP.boot_image_list parameter, which we look at next, is a bit more of a headache. While the use of a custom option space for NetBoot parameters allows us to specify most values neatly and avoid much hex wrangling, we can't avoid it with this one. It represents the list of available NetBoot sets, structured as follows:

Image ID for default set : Length of name in bytes, as hex : Name in hexadecimal ASCII : Image ID for first alternate set : Length of name in bytes, as hex : Name in hexadecimal ASCII : Image ID for second alternate set : Length of name in bytes, as hex : Name in hexadecimal ASCII : And so on...

The following command can be used to obtain the length of the name as well as its hexadecimal representation:

echo <Netboot Set Name> | perl -e 'while (<>){s/(.)/sprintf("%X:",ord($1))/ge;my $len=length()/3;s/:$//;print "\n Length (hex): ".sprintf("%02X",$len)."\n   Name (hex): $_\n";}'

The name should (but doesn't have to) correspond to the value of the Name key in the set's NBImageInfo.plist file. Spaces are acceptable in the actual name, although not in the name of the .nbi folder.

As an example, suppose we had two sets, as follows:

Default Set

First Alternate Image

Index:

123

456

Type:

OS X Client, for NetBoot

OS X Client, for NetBoot

Name:

'Orchard Primary 10.8.4 NetBoot'

'10.9.0 NetBoot for Testing Only'

The correct value for the BSDP.boot_image_list parameter would then be:

01:00:00:7B:1E:4F:72:63:68:61:72:64:20:50:72:69:6D:61:72:79:20:31:30:2E:38:2E:34:20:4E:65:74:42:6F:6F:74:01:00:01:C8:1F:31:30:2E:39:2E:30:20:4E:65:74:42:6F:6F:74:20:66:6F:72:20:54:65:73:74:69:6E:67:20:4F:6E:6C:79

or, broken up to be a bit more comprehensible, and with comments:

# Default boot image ID: 123
01:00:00:7B:
    # Name length: 30 chars
    1E: 
        # Name: Orchard Primary 10.8.4 NetBoot
        4F:72:63:68:61:72:64:20:50:72:69:6D:61:72:79:20:31:30:2E:38:2E:34:20:4E:65:74:42:6F:6F:74:
# First alternate boot image ID: 456
01:00:01:C8:
    # Name length: 31 chars
    1F:
        # Name: 10.9.0 NetBoot for Testing Only
        31:30:2E:39:2E:30:20:4E:65:74:42:6F:6F:74:20:66:6F:72:20:54:65:73:74:69:6E:67:20:4F:6E:6C:79

Please do not attempt to modify the configuration until this makes sense to you, and you can produce exactly the same sequence of hexadecimal numbers from the example parameters!

Breaking up the sequence into multiple lines and adding whitespace and comment lines is very helpful in keeping the configuration file comprehensible, and does not affect how it is parsed by the DHCP server.

'SELECT' Section Editing:

Now let's move to the second section, where we deal with BSDP 'SELECT' queries:

Here, we use one if-statement with a single branch for each offered set. The test is a match of the BSDP.selected_boot_image_id from the client's SELECT message. Make sure your if-statement's condition matches the boot image ID for the set you're adding or modifying.

Luckily, setting the values of the parameters here is easier. There are four that we must set:

  • BSDP.selected_boot_image_id

  • filename

  • root-path

  • BSDP.machine_name

BSDP.selected_boot_image_id has already been covered. This is returned to the client here to confirm that the information given is for their selected set.

filename is the TFTP path to the booter file on the TFTP server. This parameter, unlike the others we've covered, should not be specified with the option keyword.

root-path is the complete HTTP URL of the NetBoot.dmg file of the set.

BSDP.machine_name is the Computer Name the client should use while NetBooted.


Testing

It is possible to test the dhcpd.conf file for syntax errors with the following command on a machine with ISC DHCP Server installed:

/usr/sbin/dhcpd -q -t -cf <path to new dhcpd.conf file>

However, it is perhaps more likely that an error will occur within the vendor specific options we have configured, which will not be picked up by the DHCPD parser.

Instead, after making configuration changes, check by Option-booting a recent Mac to ensure that it is correctly displaying the expected sets, and that each can be selected and booted successfully, and that the default image is correctly obtained when booting with the N-key depressed.


Orchard is a close co-operation of