Wednesday Feb 04, 2009

Fattening packages - supporting multiple variants in a single package

Dealing with parts of a package

Traditionally, packaging systems have placed optional components of a package in separate packages, and established conventions for naming such components, such as -localization, -locale, -devel, -doc, etc. This method of ad-hoc decomposition makes it more difficult for GUI programs to offer the appropriate choices when selecting components, makes the introduction of new optional components difficult and makes installing documentation after the fact a painful process.

Packaging options also exist which are mutually exclusive; the typical example is which architecture the package supports. One cannot select both sparc and x86, since the two architecture's files collide - /usr/bin/ls is either a sparc binary or a i386 binary. Other examples of such colliding options include debug vs non-debug kernel binaries, and global vs nonglobal zones.

Initially we started solving the problem of selecting parts of a package using more or less ad-hoc client-side filtering, but it became clear that the publisher of the package needed to be able to describe what components intersected or were optional, and that we needed to be able to clearly distinguish between the two cases. Thus, we refer to options that may be selected or not selected in any combination, such as various locales, documentation, etc., as facets. Options which must be mutually exclusive are called variants. Both variants and facet appear as tags on IPS actions, and result in the action being selected or de-selected for installation.

An example of variant tags on an action is:

dir group=sys mode=0755 owner=root path=kernel/drv/amd64

Here this directory action is tagged with variant.arch=i386, indicating that this directory should only be installed on i386 machines (Solaris doesn't distinguish between 32 and 64 bit architectures) and, which shows that this directory should only be installed in the global zone and not in local zones as those don't contain kernel components.

Note that any action in the repository can be so tagged, including dependencies.

During installation planning, all actions not applicable to the current image are removed from consideration. If a user with a down-rev version of IPS that doesn't understand variants attempts to install a fat package, either an exception will occur indicating that duplicate actions have been found, or if a set action is found with an architecture tag an assertion will trigger. In either case the solution is either to stop attempting to install fat packages, or upgrade your version of IPS to the latest available for your build.

The initial implementation in build 106 supports only variants (facets are coming later on). To faciliate detection of attempts to install packages on the wrong architecture, our publication code now inserts set actions into packages to indicate what architectures the package supports:

set name=variant.arch value=sparc value=i386 

Publishing Fat packages

We produce fat packages by publishing separately on each architecture, and then merging the resulting manifests. Actions which are identical for both architectures are not tagged w/ variant tags; those that differ or exist only for one architecture are tagged.  Packages that exist only on one architecture are tagged to indicate that as well. This step can be repeated for different variants, and more than two variants types can be combined at once, so packages containing debug kernel binaries could be merged w/ non-debug versions, and then merged across several architectures. An example of a merged manifest can be seen here. Of course, those using pkgsend to create packages can simply insert the appropriate tags directly. For the curious, the code to merge packages can be seen here. Further work is needed to improve the performance of publishing the merged packages; allowing multiple repositories to share the filestore would help greatly here.

Tuesday Feb 12, 2008

Indiana Preview 2 - my new desktop

This weekend I decided to bite the bullet and convert my desktop to Indiana Preview 2. Since unlike most people at Sun my desktop machine also receives my email, and hosts both my home directory and calendar server, the switch-over needed some quiet concentration on my part to insure nothing important got left behind.

The installation of Preview 2 (now available here) went smoothly – not surprising, since I'd tested many trial builds on the same machine, a 2 x 2.8GHz Ultra 40. After installation completed and the machine rebooted, I created a second zpool with the two remaining drives; I use this for my home directory, mail spool, tunes and pkg server. This isolates me from any difficulties with the new installer or possible future upgrade problems. ZFS of course makes this all very easy:

: barts@cyber[227]; zfs list
NAME                              USED  AVAIL  REFER  MOUNTPOINT
rpool                            2.63G   224G  49.5K  /rpool
rpool@install                        0      -  49.5K  -
rpool/ROOT                       2.62G   224G    18K  none
rpool/ROOT@install                   0      -    18K  -
rpool/ROOT/preview2              2.62G   224G  2.09G  legacy
rpool/ROOT/preview2@install      66.8M      -  1.94G  -
rpool/ROOT/preview2/opt           483M   224G   483M  /opt
rpool/ROOT/preview2/opt@install    77K      -  3.61M  -
rpool/export                     2.44M   224G    19K  /export
rpool/export@install               15K      -    19K  -
rpool/export/home                2.41M   224G  2.39M  /export/home
rpool/export/home@install          19K      -    21K  -
zfs                               177G  51.8G    21K  /zfs
zfs/home                          133G  51.8G   133G  /export/home/cyber
zfs/local                         291M  51.8G   291M  /usr/local
zfs/mail                          110M  51.8G   110M  /var/mail
zfs/music                        43.4G  51.8G  43.3G  /zfs/music
zfs/music@2.1.2008               2.54M      -  42.3G  -
zfs/repo                           18K  51.8G    18K  /zfs/repo
: barts@cyber[228]; 

I then got to thinking about having a mirrored root pool; I hunted up one more 250GB drive, hot plugged it into the machine (love those SATA features) and used cfgadm -al and cfgadm -c to get Solaris to find the drive. Zpool attach took care of establishing the mirror; the mirror was resilvered in just a few minutes since ZFS knows what's data and what's empty space.

Now I needed dovecot, since I run an IMAP server to allow remote access of my mail. Off to for a tarball, download, configure and hmm – no C compiler. pkg search -r gcc told me that I needed SUNWgcc installed, so pkg install SUNWgcc grabbed the compiler, assembler and binutils. Cool. Run configure again and whoops – no headers! pkg search -r stdlib.h said I needed SUNWhea, so pkg install SUNWhea and I was compiling dovecot.... For a quick look at the packages available in Indiana so far browse over to I wrote this blog post using openoffice – which you'll find in a package called openoffice.

Indiana and IPS are usable, but we've still got a lot work to do:

  • The packages need to be re-factored into smaller pieces and renamed and tagged to better support minimization, searching, etc.

  • The command line pkg interface needs some attention...

  • and here's still much work to be done in constraints, simplifying pkg publishing and there are lots of bugs, tracebacks and other issues to address.


However, it's coming together – and being able to upgrade from preview2 from preview1 without running any postinstall scripts helps use feel better about the assertions that started the project....

Monday Nov 05, 2007

A programmer's ABCs

Several years ago, before blogging, I cons'd up a programmer's ABC for Stephen Hahn's first child, Benjamin.  I'd forgotten about this until Stephen mentioned last week and mailed me a link to the image; I'd lost the original.  It's a little SPARC-centric, but so was I at the time:


A Programmer's ABC

A is for algorithm, patented or not.

B is for break, to jump out of this rot.

C is for continue, to jump to the top of one's loops.

D is for default, the case that handles the oops.

E is for else, the predicate's inversion.

F is for for, of the loops the most popular version.

G is for goto, a jump oft considered dubious.

H is for hardware, for profits salubrious.

I is for if, a conditional statement.

J is for jmpl, an indirect jump causing performance abatement.

K is for thousands in powers of two.

L is for long, whose size recently grew.

M is for membar, whose use can confound.

N is for NOP, which in delay slots often is found.

O is for operator, whose overloading is oft unsupportable.

P is for pragma, with usage unportable.

Q is for quadword, the largest of all.

R is for return, when we make the stack not so tall.

S is for switch, a computed goto for which we all yearn.

T is for trap, from which we may never return.

U is for unsigned, to avoid two's complement extension.

V is for volatile, whose presence incites apprehension.

W is for WSTATE register, for window traps most topical.

X is for XOR, bitwise not logical.

Y is for Y register, deprecated for years.

Z is for zero, whose dereferencing everyone fears.


An engineer's viewpoint on Solaris...


« April 2014