Skip to content

Building a Microkernel ISO

Daniel Pittman edited this page Feb 21, 2013 · 22 revisions

The Microkernel used by Razor is actually a variant of the Tiny Core Linux (TCL) kernel.

The Microkernel is built using the 'Core' release of TCL, which can be found here. In order to run the tools that are needed by the Microkernel (Facter for discovery), a number of TCL Extensions need to be added to our Microkernel.

Building the Microkernel creates a "bundle" - a single gzipped tarfile - that contains an 'overlay file' (another gzipped tarfile), as well as the scripts and dependencies are needed to merge that overlay file with the 'standard' TCL Core ISO (which is also included in the bundle file) in order to build a new version of the Razor Microkernel ISO.

The components for the overlay file (and the dependencies that it needs) are all either copied over from the Razor-Microkernel project or downloaded from online sources to local directories (if they are not part of the Razor-Microkernel project) before being included in the bundle file.

Setting up to build

Building a new ISO image is reasonably simple, but there are a few things you should probably consider before you get started:

If you will be rebuilding the bundle file for the ISO image more than once, it really pays to have a standard HTTP proxy in place to cache the files you are downloading. This is an enormous speedup for the second and subsequent runs.

The "out of the box" configuration of squid and other proxies is typically fine; you are dealing with binary files no larger than 12MB in general.

You will need to be on a Linux system to rebuild the ISO image, but you can download the bundle file more or less anywhere that has POSIX-ish tools.

You will need to run the rebuild as root, or to use fakeroot. In the later case you also need the 7z executable on the system doing the rebuilding - check for p7zip-full or p7zip in your distributions.

We strongly recommend the rebuild is done without real root privileges, but they are both officially supported.

Building the Razor Microkernel ISO 'Bundle'

The standard bundle can be built by running this command:

./build-bundle-file.sh \
    -b additional-build-files/builtin-extensions.lst \
    -m additional-build-files/mirror-extensions.lst

Don't forget to pass --build-prod-image or --build-debug-image if you want something other than a "development" build of the ISO image.

The script that is used for this process (the 'build-bundle-file.sh' script) can be found in the top-level directory of the Razor-Microkernel project itself. The usage for this script is readily available by adding a '-h' (or '--help') flag to the command line when invoking the script:

test@server:~/Razor-Microkernel$ ./build-bundle-file.sh -h

Usage: ./build-bundle-file.sh OPTIONS

This script builds a gzipped tarfile containing all of the files necessary to
build an instance of the Razor Microkernel ISO.

OPTIONS:
   -h, --help                 print usage for this command
   -b, --builtin-list=FILE    file containing extensions to install as builtin
   -m, --mirror-list=FILE     file containing extensions to add to TCE mirror
   -p, --build-prod-image     build a production ISO (no openssh, no passwd)
   -d, --build-debug-image    build a debug ISO (enable automatic console login)
   -t, --tc-passwd=PASSWD     specify a password for the tc user

Note; currently, the default is to build a development ISO (which includes the
openssh.tcz extension along with the openssh/openssl configuration file changes
and the passwd changes needed to access the Microkernel image from the command
line or via the console).  Also note that only one of the '-p' and '-d' flags
may be specified and the '-t' option may not be used when building a production
ISO (using the '-p' flag).

test@server:~/Razor-Microkernel$

When invoking this script, the '-b' and '-m' flags (or their more verbose equivalents) MUST be provided (if they are not, then an error will be thrown and the command usage will be printed), and the files that are included as arguments to these two flags must be readable. These files should contain a list of builtin extensions and local TCE mirror extensions (respectively) that should be downloaded and included in the overlay file we are creating. The builtin extensions are those that should be installed as part of the boot process for the Microkernel (making them available when tasks like network initialization take place, for example), while the TCE mirror extensions are simply placed into a local TCE mirror in the Microkernel's filesystem (where they can be used as part of the Microkernel Controller initialization process, post-boot). Examples for these two files are included in the 'additional-build-files' subdirectory in the Razor Microkernel project (the files are called 'builtin-extensions.lst' and 'mirror-extensions.lst', respectively). The other arguments to the script are optional, and default values are used if they are not specified (by default, the previous downloads are not re-used and the system builds a development Microkernel, not a production one). A simple example of the usage for this shell script that uses the default lists of extensions provided as a part of the Razor-Microkernel project is as follows:

./build-bundle-file.sh -r -b additional-build-files/builtin-extensions.lst \
        -m additional-build-files/mirror-extensions.lst -d -t test1234 2>&1 | tee t.t

The 'build-bundle-file.sh' script must be run from the top-level directory of the Razor-Microkernel project. When it is invoked, this script will first create a directory structure that looks something like the following:

tmp-build-dir/
└── build_dir

Here, 'tmp-build-dir' is the working directory created by the script and the 'tmp-build-dir/build_dir' subdirectory is the directory we will be using to create the final bundle. This 'bundle' file will contain the overlay file itself (in the 'razor-microkernel-files.tar.gz' file that is placed into the 'tmp-build-dir/build_dir/dependencies' directory), along with all of the files and scripts that are needed in order to turn that to turn that overlay file into a working Razor Microkernel instance.

Copying the Razor-Microkernel Project Files

It should be noted that the sub-directories of the 'tmp-build-dir' directory (with the exception of the 'build_dir' subdirectory) will eventually be mapped into the root-level directories in the overlay file that we are building here (eg. the 'tmp-build-dir/usr/local/bin' directory in the local filesystem will correspond to the 'usr/local/bin' directory in our overlay). We should also note that the final directory structure that results from this build process will be left in place at the completion of the bundle build process (so that the downloads that the directory structure contains can be re-used, if necessary, to build another bundle (with additional extensions?).

After creating the initial 'build_dir' subdirectory (and the 'build_dir/dependencies' subdirectory), the 'build-bundle-file.sh' script copies over the scripts that will be needed to build the Razor Microkernel ISO directly from the 'iso-build-files' subdirectory of the Razor-Microkernel project. These scripts are placed directly into the 'tmp-build-dir/build_dir' subdirectory. If we are building a production ISO, the copy of the 'rebuild_iso.sh' script that is made via this process will also be modified (on the fly using 'sed') so that it outputs an ISO file with the string 'prod' in its name (rather than the string 'dev') when it is invoked. The next step in the process is to copy over the modified DHCP client scripts from the Razor-Microkernel project to the corresponding locations in the 'tmp-build-dir'. After that, the script copies over the Razor Microkernel Controller script (and its dependencies) into the appropriate locations in the 'tmp-build-dir/usr/local/bin' and 'tmp-build-dir/usr/local/lib/razor_microcontroller' subdirectories. Finally, the script copies over the list of gems from the 'opt/gems/gem.list' file of the Razor-Microkernel project into the 'tmp-build-dir/opt/gems' subdirectory. With that step, the process of copying files from the Razor Microkernel project into the directories that we will be creating our overlay from is complete and we are ready to start downloading some dependencies.

Downloading Additional Dependencies

The download process starts by using the list of gems that was copied over from the Razor-Microkernel project (above) to determine what gems should be downloaded (so that they will be included in the overlay file). The gems in that list are downloaded to the 'tmp-build-dir/opt/gems' directory using the 'gem fetch...' command (Note; this assumes that the local system has RubyGems already installed on it and that the 'gem' command is accessible by the user running this shell script). With the gems in place, the script then downloads two sets of extensions from the TCL Extension Repository (or TCE repository). The first set of extensions downloaded are used to construct a local TCE mirror, and the second set are placed into a subdirectory from which they will automatically be installed during the boot process. The actual extensions that are installed are read from flat files containing the list of extensions to include in the local mirror and a list of extensions to set up as 'built-in extensions' (which appear in the 'additional-build-files/mirror-extensions.lst' and 'additional-build-files/builtin-extensions.lst' files in the Razor-Microkernel project, respectively). Files from the first list will be placed into a mirror subdirectory under the 'tmp-build-dir/tmp/tinycorelinux' subdirectory, while those from the second will be placed into the 'tmp-build-dir/tmp/builtin' subdirectory. In the second case, the list of extensions that is loaded is also used to construct a 'tmp-build-dir/tmp/builtin/onboot.lst' file that will be used by the Microkernel to determine which of the 'built-in' extensions should be loaded on boot.

Building the Bundle

After the 'bundle initialization' process is complete, the directory structure will actually look a bit more complicated (currently, this is what it looks like after initializing the temporary build directory but before building the bundle):

build-files
└── razor-microkernel-bundle-dev.tar.gz
tmp-build-dir
├── build_dir
│   ├── add_version_to_mk_fs.rb
│   ├── build_initial_directories.sh
│   ├── build_iso_yaml.rb
│   ├── Core-current.iso
│   ├── dependencies
│   │   ├── mcollective-setup-files.tar.gz
│   │   ├── mk-open-vm-tools.tar.gz
│   │   ├── razor-microkernel-overlay.tar.gz
│   │   └── ssh-setup-files.tar.gz
│   └── rebuild_iso.sh
├── etc
│   ├── init.d
│   │   └── dhcp.sh
│   ├── inittab
│   ├── passwd
│   └── shadow
├── mcollective-2.0.0.tgz
├── opt
│   ├── bootsync.sh
│   ├── gems
│   │   └── ...
│   └── rubygems-1.8.24.tgz
├── tmp
│   ├── builtin
│   │   ├── onboot.lst
│   │   └── optional
│   │       └── ...
│   ├── first_checkin.yaml
│   ├── mk_conf.yaml
│   └── tinycorelinux
│       ├── 4.x
│       │   └── x86
│       │       └── tcz
│       │           └── ...
│       └── ...
├── usr
│   ├── local
│   │   ├── bin
│   │   │   ├── lscpu
│   │   │   └── ...
│   │   ├── lib
│   │   │   └── ruby
│   │   │       └── 1.8
│   │   │           └── razor_microkernel
│   │   │               └── ...
│   │   ├── mcollective -> /usr/local/tce.installed/mcollective-2.0.0
│   │   ├── sbin
│   │   │   └── sfdisk
│   │   └── tce.installed
│   │       └── mcollective-2.0.0
│   │           └── ...
│   ├── sbin
│   │   └── dmidecode -> /usr/local/sbin/dmidecode
│   └── share
│       └── udhcpc
│           └── dhcp_mk_config.script
└── util-linux.tcz

With this directory structure in place, building the actual bundle is a very simple process (consisting of one command in the 'build-bundle-file.sh' script). When this process is complete, a single bundle file will be added to the 'build-files' subdirectory of the Razor-Microkernel project (named 'razor-microkernel-bundle-dev.tar.gz' for a development bundle and 'razor-microkernel-bundle-prod.tar.gz' for a production bundle). That bundle file will contain all of the scripts and files that are needed to build a new Microkernel ISO from the current Razor-Microkernel project (and the latest versions of its dependencies). This is what that current contents of a development bundle look like:

-rw-rw-r-- tjmcs/tjmcs 8290304 2012-06-04 22:24 Core-current.iso
-rwxrwxr-x tjmcs/tjmcs    1385 2012-05-02 13:55 add_version_to_mk_fs.rb
-rwxrwxr-x tjmcs/tjmcs    1263 2012-06-19 16:50 build_initial_directories.sh
-rwxrwxr-x tjmcs/tjmcs    2501 2012-05-02 13:25 build_iso_yaml.rb
drwxrwxr-x tjmcs/tjmcs       0 2012-06-21 16:27 dependencies/
-rw-rw-r-- tjmcs/tjmcs 30176283 2012-06-21 16:27 dependencies/razor-microkernel-overlay.tar.gz
-rw-rw-r-- tjmcs/tjmcs   813074 2012-06-08 14:19 dependencies/mk-open-vm-tools.tar.gz
-rw-r--r-- tjmcs/tjmcs     5723 2012-06-07 19:45 dependencies/ssh-setup-files.tar.gz
-rw-r--r-- tjmcs/tjmcs      374 2012-06-06 15:30 dependencies/mcollective-setup-files.tar.gz
-rwxr-xr-x tjmcs/tjmcs     1414 2012-05-02 13:46 rebuild_iso.sh

To use this bundle file, simply copy it over to another directory on this (or another) machine and unpack it

# tar zxvf razor-microkernel-bundle-dev.tar.gz

From that same directory, the sequence of commands to build a new ISO is actually quite simple. First, build the directory structure needed to for the script that constructs the new ISO:

# ./build_initial_directories.sh

then, invoke the script that actually builds the ISO

# ./rebuild_iso.sh [VERSION_NO]

Note; there is a single (optional) argument to this second script, the version number for the Microkernel ISO that you are building. If specified, three-digit (eg. 0.9.3) or four digit (0.9.3.1) version number should be used for this argument. If this optional argument is left out, then a version number will be constructed for you based on the version of the Razor-Microkernel project that was used to build the bundle file that contained this script (for those who are really interested, this auto-generated version number will be constructed using the latest tag applied to the Razor-Microkernel project and the commit information for any commits that have been made since the project was tagged with that tag).

Once the second shell script command finishes, you should have a new Razor Microkernel ISO build in the current working directory; an ISO that is suitable for use with Razor and that contains all of the dependencies and extensions included in the bundle build process (above). If, for some reason, you find an issue with the ISO you have built, rebuilding a new ISO is as simple as running the same pair of shell scripts that are shown, above; perhaps with a new set of built-in and/or additional extensions declared during the initial bundle build process.

Notes on Dependencies in the Build Processes

There are a few dependencies that must be met for this build process to run successfully. The bundle file build process (described above) relies on the 'unsquashfs' command to extract the 'lscpu' and 'sfdisk' commands from the 'util-linux.tcz' extension that it downloads from the standard Tiny Core Linux Extension Mirror. That same script also makes extensive use of the 'wget' command to download the dependencies that it needs and uses the 'gem' command to 'fetch' the gems that are needed from the 'Ruby Gems' gem repository. Finally, the dynamic downloading of the dependencies and extensions that need to be included in the overlay file that is being constructed require that an active network connection exists (with access to the internet) and that the local Razor-Microkernel project directory be writeable by the current user. If any of these dependencies are not met, the bundle file build process will fail.

The script that builds the Microkernel ISO also has a number of dependencies on system level commands that may or may not exist on all platforms (and that may or may not be accessible for all users on any given platform). It uses the 'chroot' and 'ldconfig' commands to set up the contents of the 'tmp' subdirectory that it uses when building the 'core.gz' file that will be placed into the Microkernel ISO. If these commands are not accessible (or are not usable by the current user), then the resulting ISO may or may not be usable as a boot image by Razor. This script also uses the 'cpio' command to construct the 'core.gz' file and uses the 'advdef' command to further compress that file before placing it into the Microkernel ISO. We have seen issues on some platforms with the flags for these commands not being consistent (or with these commands not being available at all). The build process has been successfully tested and used under recent releases of Ubuntu (the 64-bit server release, but that's probably not important), but failed for some users who were trying to use the same scripts under OS X. The Ubuntu Server instance we have used most extensively uses the GNU cpio command and advancecomp v1.15 (for the 'advdef' command). This build process hasn't much testing on other platforms to date, so your mileage may vary in terms when it comes to using this build process (depending on the platform that you use).

Summary

By following the procedure outlined, above, we were able to create 'bundle file' containing an 'overlay' that can be used to add a number of extensions to the default TCL Core distribution. We were then able to use that 'bundle file' (the 'overlay' along with the additional dependencies and scripts that it contains) to build a new Microkernel ISO from the standard TCL Core distribution ISO.

The 'build-bundle-file.sh' script

The current 'build-bundle-file.sh' script can be found here. For convenience, we've also provided a nearly complete view of the contents of the 'tmp-build-dir' directory for reference, below. This view shows what this directory structure looks like after the 'build-bundle-file.sh' script has been run, and can be used to determine what is included in the bundle file itself. We say "nearly complete" (above) because we've truncated the actual directory contents a bit (we are only showing the 'tcz' files for the extensions, not the associated md5, list, info, and dep files, and we've cut out all of the files and subdirectories under the 'tmp-build-dir/usr/local/tce.installed/mcollective-2.0.0' directory). Other than the contents that we are not showing, the rest of the structure is intact.

Followed by the post-build directory structure:

tmp-build-dir/
├── build_dir
│   ├── add_version_to_mk_fs.rb
│   ├── build_initial_directories.sh
│   ├── build_iso_yaml.rb
│   ├── Core-current.iso
│   ├── dependencies
│   │   ├── mcollective-setup-files.tar.gz
│   │   ├── mk-open-vm-tools.tar.gz
│   │   ├── razor-microkernel-overlay.tar.gz
│   │   └── ssh-setup-files.tar.gz
│   └── rebuild_iso.sh
├── etc
│   ├── init.d
│   │   └── dhcp.sh
│   ├── inittab
│   ├── passwd
│   └── shadow
├── mcollective-2.0.0.tgz
├── opt
│   ├── bootsync.sh
│   ├── gems
│   │   ├── daemons-1.1.8.gem
│   │   ├── facter-1.6.9.gem
│   │   ├── gem.list
│   │   ├── json_pure-1.7.3.gem
│   │   └── stomp-1.2.2.gem
│   └── rubygems-1.8.24.tgz
├── tmp
│   ├── builtin
│   │   ├── onboot.lst
│   │   └── optional
│   │       ├── bash.tcz
│   │       ├── dmidecode.tcz
│   │       ├── firmware-bnx2.tcz
│   │       ├── gcc_libs.tcz
│   │       ├── libssl-0.9.8.tcz
│   │       ├── lshw.tcz
│   │       ├── openssh.tcz
│   │       ├── openssl-1.0.0.tcz
│   │       ├── ruby.tcz
│   │       └── scsi-3.0.21-tinycore.tcz
│   ├── first_checkin.yaml
│   ├── mk_conf.yaml
│   └── tinycorelinux
│       ├── 4.x
│       │   └── x86
│       │       └── tcz
│       │           ├── fuse.tcz
│       │           ├── glib2-dev.tcz
│       │           ├── glib2.tcz
│       │           ├── libdnet.tcz
│       │           ├── libffi-dev.tcz
│       │           ├── libffi.tcz
│       │           ├── ncurses-common.tcz
│       │           ├── ncurses.tcz
│       │           ├── perl5.tcz
│       │           └── procps.tcz
│       ├── kmod-install-list.yaml
│       └── tce-install-list.yaml
├── usr
│   ├── local
│   │   ├── bin
│   │   │   ├── lscpu
│   │   │   ├── mcollectived -> /usr/local/mcollective/bin/mcollectived
│   │   │   ├── rz_mk_controller.rb
│   │   │   ├── rz_mk_control_server.rb
│   │   │   ├── rz_mk_init.rb
│   │   │   ├── rz_mk_tce_mirror.rb
│   │   │   └── rz_mk_web_server.rb
│   │   ├── lib
│   │   │   └── ruby
│   │   │       └── 1.8
│   │   │           └── razor_microkernel
│   │   │               ├── logging.rb
│   │   │               ├── rz_host_utils.rb
│   │   │               ├── rz_mk_configuration_manager.rb
│   │   │               ├── rz_mk_fact_manager.rb
│   │   │               ├── rz_mk_gem_controller.rb
│   │   │               ├── rz_mk_hardware_facter.rb
│   │   │               ├── rz_mk_kernel_module_manager.rb
│   │   │               ├── rz_mk_registration_manager.rb
│   │   │               └── rz_network_utils.rb
│   │   ├── mcollective -> /usr/local/tce.installed/mcollective-2.0.0
│   │   ├── sbin
│   │   │   └── sfdisk
│   │   └── tce.installed
│   │       └── mcollective-2.0.0
│   │           └── ...
│   ├── sbin
│   │   └── dmidecode -> /usr/local/sbin/dmidecode
│   └── share
│       └── udhcpc
│           └── dhcp_mk_config.script
└── util-linux.tcz
Clone this wiki locally