assembling services for boot with smf(5)

In order to deal with some pretty stringent backwards compatibility requirements for install, smf(5) attempts to self-assemble services during boot. I won't go into the vagaries of why it is so helpful to avoid having to write the smf(5) repository during install/upgrade now, and instead stick to the tactical details of what happens in Solaris/OpenSolaris. Most of this focuses on the behaviour of smf(5) during the first boot.

Some background details

First, a refresher (or an introduction, depending on your perspective). The delivery mechanism for services in Solaris smf are Service Manifests. They're a bunch of XML goo which describe metadata and optionally data about a service: how do I start it, what's the service model, is it an inetd service, etc. If you're interested in how to write a manifest, see the Service Developer Introduction. However, the system doesn't really know anything about a service described by a manfest until it is imported with svccfg import. At import time, the data is copied from the manifest and put into the smf(5) repository. (I wrote a bit about the design choices we made when creating the repository in another post.)

Once a service is in the repository, all of the smf(5) framework kicks in for that service -- displaying it with svcs(1), starting it during boot, restarting on failure, etc. But, until the service has been imported into the repository, smf(5) knows nothing about it. The persistent repository information is stored as a data file in /etc/svc/repository.db.

The seed repository

As I already mentioned, smf(5) only cares about the repository, so we need to generate enough of a repository to get the system to the point where it can import more manifests. What's required for that? Essentially, the / and /usr filesystems must be mounted and writable. We need the utilities from /usr and obviously we can't write to /etc/svc/repository.db without a writable root filesystem. We call this repository the seed.

When you build OpenSolaris (and when we build Solaris internally) in addition to compiling all of the smf(5) source code, we also assemble the seed repository. Essentially, what goes in the seed is what's required to start svc:/system/manifest-import:default. You can see how we assemble this during the build in usr/src/cmd/svc/seed/Makefile. We build a seed for both the global zone and the non-global zones, since the non-global zones require fewer services to get to manifest-import.

You can look at what's in the seed repository for your system. For something resembling current OpenSolaris bits, this looks like:

    $ cp /lib/svc/seed/global.db /tmp/global.db
    $ svccfg     
    svc:> repository /tmp/global.db
    svc:> list

If you look carefully at that Makefile, though, we don't place these in the normal repository location, we stash them at /lib/svc/seed/[non]global.db. This ensures that when folks use bfu, we don't over-write the local service configuration with the very limited seed repository! It is important to note that no /etc/svc/repository.db gets generated during the OpenSolaris build process.

Placing the seed

There's logic in both bfu and the i.manifest package class-action script which place the appropriate seed repository in /etc/svc/repository.db if the file doesn't already exist. Thus, if you're using bfu or the Solaris pkgadd(1M), we copy the seed to the correct location for you. The Solaris install CD/DVD/netinstall image also creates its own repository.db, based on the seed we generate during the ON build.

Finally, the boot discussion

OK, so now we have a system with a very very limited seed set of services as its repository. Those services are really limited, and don't even include essential things like ssh(1). But, the system is able to boot to the point of running the manifest-import service. We'll assume it does so successfully. Then the manifest-import start method kicks in. First we find all the manifests in /var/svc/manifest:

    423 nonsite_dirs=`/usr/bin/find /var/svc/manifest/\* -name site -prune -o -type d \\
    424 	-print -prune`
    426 nonsite_manifests=`/lib/svc/bin/mfstscan $nonsite_dirs`
    427 site_manifests=`/lib/svc/bin/mfstscan /var/svc/manifest/site`
    429 manifests="$nonsite_manifests $site_manifests"

mfstscan is a private command which finds any manifests in the subdirectories provided and checks to see if they've changed since last import. Then we import any manifests which have changed, keeping a running count so the user knows something is happening:

    443 	set -- $manifests
    444 	backup=`echo "$#/$#" | sed 's/.//g'`
    445 	fwidth=`echo "$#\\c" | wc -c`
    447 	echo "Loading smf(5) service descriptions: \\c" > /dev/msglog
    449 	i=1; n=$#
    450 	while [ $# -gt 0 ]; do
    451 		printf "%${fwidth}s/%${fwidth}s" $i $n > /dev/msglog
    452 		svccfg_import $1
    453 		i=`expr $i + 1`
    454 		shift
    455 		echo "$backup\\c" > /dev/msglog
    456 	done

But how do services get enabled?

Some of you may have noticed, though, that OpenSolaris has most of the services specified as disabled in their service manifests. You can see this, for example, with the syslog manifest. The enabled='false' means that the service will be disabled after it is imported. But, on your running Solaris system, it is enabled.

What's happening after the manifest imports in the manifest-import start method is that profiles are being applied. As I described here, profiles are just a way to enable or disable a bunch of services. Solaris/OpenSolaris tries to deliver as many services as possible as disabled in their manifest, so that an administrator can choose carefully which services they want to enable, and when we add new ones, they won't be automatically enabled unless absolutely necessary to get to manifest-import. We look for the following profiles and apply them in order:


generic.xml is created as a link to generic_open.xml both during the build process and by the Solaris packaging tools. The platform.xml profile is created as a link to the appropriate file during boot by the manifest-import start method:

    480 if [ ! -f /var/svc/profile/platform.xml ]; then
    481 	this_karch=`uname -m`
    482 	this_plat=`uname -i`
    484 	if [ -f /var/svc/profile/platform_$this_plat.xml ]; then
    485 		platform_profile=platform_$this_plat.xml
    486 	elif [ -f /var/svc/profile/platform_$this_karch.xml ]; then
    487 		platform_profile=platform_$this_karch.xml
    488 	else
    489 		platform_profile=platform_none.xml
    490 	fi
    492 	ln -s $platform_profile /var/svc/profile/platform.xml
    493 fi

Finally, site.xml is left entirely to the control of the administrator. If you're interested in re-visiting this boot order, take a look at smf_bootstrap(5). These profiles enable all of the services that were just added by manifest-import. If you want to use one of our limited profiles like generic_limited_net.xml, you can do the following before reboot (i.e. during jumpstart):

    $ ln -sf /var/svc/profile/generic_limited_net.xml /var/svc/profile/generic.xml

Or, you can just place your customizations into /var/svc/profile/site.xml, and they'll be applied after the Solaris/OpenSolaris-delivered profiles are applied.

Technorati Tags: , , and .


What about setting properties for services like ttymon/prompt astring "`uname -n` console login:" ttymon/terminal_type astring sun in svc:/system/console-login:default? What is best practice for doing this during install/jumpstart?

Posted by Matthew Flanagan on June 26, 2005 at 04:19 PM PDT #

When using flar-archives for cloning installations the platform.xml is not newly symlinked when installing onto another hardware platform.
iE.: We created our flar on a SF880 and installed it onto a SF280R. The platform.xml link ist still like this:

<code>platform.xml -> platform_SUNW,Sun-Fire-880.xml</code>

So when booting the new machine it always tells that the sf880drd is misconfigured.
Just a question: Which platfrom\*.xml is the right on for

a) a SF280R


b) an U250?

Posted by Peter Ohlerich on November 02, 2005 at 08:47 PM PST #

Hi liane,

I have one question:

If we try to "svccfg import" one service in our script with a manifest file which is diffirent with the manifest in the /var/svc/manifest/subdir/, since in the article, you mentioned after the reboot, SMF (manifest-import) will try to navigate the directory of /var/svc/manifest to see if the manifest has changed. (obviously, here, it has been changed since we import it from another file which is not stored in /var/svc/manifest/subdir and with different contents), so, in this case, SMF will re-import it again?

We see some logs like:
[ Jan 15 21:32:24 Rereading configuration. ]
[ Feb 26 14:25:22 Disabled. ]
[ Feb 26 14:25:22 Rereading configuration. ] --- done by our application
[ Feb 26 15:50:05 Rereading configuration. ] ---done by fresh installatin reboot--import file /var/svc/manifest/application/management/servera.xml
[ Feb 26 18:53:56 Enabled. ]

If the answer is yes, does this "re-import" action will happen in each reboot of just for the first boot?


Posted by Jumin on March 17, 2008 at 01:26 AM PDT #

Post a Comment:
  • HTML Syntax: NOT allowed

Liane Praza-Oracle


« July 2016