<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Tim Foster&#039;s Web Log</title>
	<atom:link href="http://timsfoster.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://timsfoster.wordpress.com</link>
	<description></description>
	<lastBuildDate>Fri, 23 Dec 2011 00:21:24 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='timsfoster.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>Tim Foster&#039;s Web Log</title>
		<link>http://timsfoster.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://timsfoster.wordpress.com/osd.xml" title="Tim Foster&#039;s Web Log" />
	<atom:link rel='hub' href='http://timsfoster.wordpress.com/?pushpress=hub'/>
		<item>
		<title>FeedPlus &#8211; converting G+ feeds to Atom, and now Twitter</title>
		<link>http://timsfoster.wordpress.com/2011/12/13/feedplus-twitter/</link>
		<comments>http://timsfoster.wordpress.com/2011/12/13/feedplus-twitter/#comments</comments>
		<pubDate>Tue, 13 Dec 2011 07:51:16 +0000</pubDate>
		<dc:creator>timsfoster</dc:creator>
				<category><![CDATA[Off-topic]]></category>

		<guid isPermaLink="false">http://timsfoster.wordpress.com/?p=2888</guid>
		<description><![CDATA[I&#8217;ve added a feature to FeedPlus, the command line G+ to Atom converter I mentioned previously. It now has option &#8230;<p><a href="http://timsfoster.wordpress.com/2011/12/13/feedplus-twitter/">Continue reading &#187;</a></p><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=timsfoster.wordpress.com&amp;blog=11695716&amp;post=2888&amp;subd=timsfoster&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.flickr.com/photos/hapinachu/667766525/"><img src="http://timsfoster.files.wordpress.com/2011/09/robot-hamster.jpg?w=529" alt="Original image by hapinachu on Flickr" title="Original image by hapinachu on Flickr"   class="alignleft size-full wp-image-2804" /></a></p>
<p>I&#8217;ve added a feature to <a href="https://github.com/timfoster/FeedPlus">FeedPlus</a>, the command line G+ to Atom converter I <a href="http://timsfoster.wordpress.com/2011/09/08/feedplus-creating-an-atom-feed-from-a-g-public-stream/">mentioned previously</a>.  It now has option to also post to your Twitter stream directly, rather than going via <a href="http://twitterfeed.com/">Twitterfeed</a>.</p>
<p>I found that, despite Twitterfeed claiming a 30 minute interval between checking the RSS/Atom URL it was configured to repost to Twitter, updates weren&#8217;t being pulled that frequently and often a G+ update I&#8217;d write that was relatively timely would finally appear several hours later.  I decided it&#8217;d be better to work out how to post directly to Twitter.</p>
<p>For webapps, this didn&#8217;t appear to be too complex, but it&#8217;s a bit more involved for CLI applications (OAuth, yuck!)  <a href="http://code.google.com/p/python-twitter/">python-twitter</a> helps a lot though, and it seems to be working so far.  For now, I&#8217;ve got this running in a cron job that fires every 5 minutes, and while it&#8217;s definitely not as network-efficient as it could be, it&#8217;s doing the job just fine.</p>
<p>As before, I&#8217;m really hoping Google will come along with proper G+ to Twitter bridging (and in that direction: yes it&#8217;s lossy, but 140 characters just seems so restricting these days!)  I&#8217;m also hoping that more of the folks I follow on Twitter will ditch both Facebook and Twitter, and give G+ another go &#8211; we&#8217;ll see.</p>
<p>Comments and bug reports welcome over on <a href="https://github.com/timfoster/FeedPlus">the FeedPlus Github page</a>.</p>
<br />Filed under: <a href='http://timsfoster.wordpress.com/category/off-topic/'>Off-topic</a>  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/timsfoster.wordpress.com/2888/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/timsfoster.wordpress.com/2888/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/timsfoster.wordpress.com/2888/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/timsfoster.wordpress.com/2888/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/timsfoster.wordpress.com/2888/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/timsfoster.wordpress.com/2888/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/timsfoster.wordpress.com/2888/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/timsfoster.wordpress.com/2888/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/timsfoster.wordpress.com/2888/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/timsfoster.wordpress.com/2888/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/timsfoster.wordpress.com/2888/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/timsfoster.wordpress.com/2888/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/timsfoster.wordpress.com/2888/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/timsfoster.wordpress.com/2888/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=timsfoster.wordpress.com&amp;blog=11695716&amp;post=2888&amp;subd=timsfoster&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://timsfoster.wordpress.com/2011/12/13/feedplus-twitter/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">timsfoster</media:title>
		</media:content>

		<media:content url="http://timsfoster.files.wordpress.com/2011/09/robot-hamster.jpg" medium="image">
			<media:title type="html">Original image by hapinachu on Flickr</media:title>
		</media:content>
	</item>
		<item>
		<title>The IPS System Repository</title>
		<link>http://timsfoster.wordpress.com/2011/11/09/the-ips-system-repository/</link>
		<comments>http://timsfoster.wordpress.com/2011/11/09/the-ips-system-repository/#comments</comments>
		<pubDate>Wed, 09 Nov 2011 15:14:46 +0000</pubDate>
		<dc:creator>timsfoster</dc:creator>
				<category><![CDATA[IPS]]></category>
		<category><![CDATA[OpenSolaris]]></category>

		<guid isPermaLink="false">http://timsfoster.wordpress.com/?p=2848</guid>
		<description><![CDATA[I&#8217;m excited about today&#8217;s launch of Solaris 11 &#8211; I&#8217;ve been contributing to Solaris for quite a while now, pretty &#8230;<p><a href="http://timsfoster.wordpress.com/2011/11/09/the-ips-system-repository/">Continue reading &#187;</a></p><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=timsfoster.wordpress.com&amp;blog=11695716&amp;post=2848&amp;subd=timsfoster&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.flickr.com/photos/nori_n/271373399/"><img src="http://timsfoster.files.wordpress.com/2011/11/plumbing.jpg?w=529" alt="Original image by nori_n" title="Original image by nori_n"   class="alignleft size-full wp-image-2858" /></a></p>
<p>I&#8217;m excited about today&#8217;s launch of Solaris 11 &#8211; I&#8217;ve been contributing to Solaris for quite a while now, pretty much since 1996, but my involvement in S11 has been the most fun I&#8217;ve had in all releases so far.</p>
<p>I&#8217;ve talked before about some of the work I&#8217;ve done on IPS over the last two years &#8211; <a class="reference external" href="http://timsfoster.wordpress.com/2010/11/09/pkg-history-enhancements/">pkg history</a>, <a class="reference external" href="http://timsfoster.wordpress.com/2011/02/24/pkgdepend-improvements/">pkgdepend</a> (and <a class="reference external" href="http://timsfoster.wordpress.com/2010/06/08/pkg5-smf-manifest-dependency-support/">here</a>), <a class="reference external" href="http://timsfoster.wordpress.com/2010/08/26/pkglint1/">pkglint</a> and <a class="reference external" href="http://timsfoster.wordpress.com/2011/03/24/pkgsend-and-svr4-packaging/">pkgsend</a> and most recently, helping to put together the <a class="reference external" href="http://timsfoster.wordpress.com/2011/10/17/replacing-the-application-packaging-developers-guide">IPS Developer Guide</a>.</p>
<p>Today, I&#8217;m going to talk about the system repository and how I helped.</p>
<h3>How zones differ from earlier releases</h3>
<p>Zones that use IPS are different than those in Solaris 10, in that they are always full-root: every zone contains its own local copy of each package, they don&#8217;t inherit packaged content from the global zone as &quot;sparse&quot; zones did in Solaris 10.</p>
<p>This simplifies a lot of zone-related functionality: for the most part, administrators can treat a zone as if it were a full Solaris instance, albeit a <em>very small</em> one. By default new zones in S11 are tiny. However, packaging with zones is a little more complex, and the system aims to hide that complexity<br />
from users.</p>
<p>Some packages in the zone always need to be kept in sync with those packages in the global zone. For example, anything which delivers a kernel module and a userland application that interfaces with it must be kept in sync between the global zone and any non-global zones on the system.</p>
<p>In earlier OpenSolaris releases, after each global-zone update, each non-global zone had to be updated by hand, attaching and detaching each zone.  During that detach/attach the ipkg brand scripts determined which packages were now in the global zone, and updated the non-global zone accordingly.</p>
<p>In addition, in OpenSolaris, the packaging system itself didn&#8217;t have any way of ensuring that every publisher in the global zone was also available in the non-global zone, making updates difficult if switching publishers.</p>
<h3>Zones in Solaris 11</h3>
<p>In Solaris 11, zones are now first-class citizens of the packaging system.  Each zone is installed as a <em>linked image</em>, connected to the <em>parent image</em>, which is the global zone.</p>
<p>During packaging operations in the global zone, IPS recurses into any non-global zones to ensure that packages which need to be kept in sync between the global and non-global zones are kept in sync.</p>
<p>For this to happen, it&#8217;s important for the zone to have access to all of the IPS repositories that are available from the global zone.</p>
<p>This is problematic for a few reasons:</p>
<ul class="simple">
<li>the zone might not be on the same subnet as the global zone</li>
<li>the global-zone administrator might not want to distribute SSL keys/certs for the repos to all zone administrators</li>
<li>the global zone might change its publisher configuration, requiring publisher configuration change in every non-global zone</li>
</ul>
<h3>The System Repository</h3>
<p>The system repository, and accompanying zones-proxy services was our solution to the list of problems above.</p>
<p>The SMF Services responsible are:</p>
<ul class="simple">
<li>svc:/application/pkg/system-repository:default</li>
<li>svc:/application/pkg/zones-proxyd:default</li>
<li>svc:/application/pkg/zones-proxy-client:default</li>
</ul>
<p>The first two services run in the global zone, the last one runs in the non-global zones.</p>
<p>With these services, the system repository shares publisher configuration to all non-global zones on the system, and also acts as a conduit to the publishers configured in the global zone.  Inside the non-global zone, these proxied global-zone publishers are called <em>system publishers</em>.</p>
<p>When performing packaging operations inside a zone that accesses those publishers, Solaris proxies access through the system repository.  While proxying, the system repository also caches any file-content that was<br />
downloaded.  If there are lots of zones all downloading the same packaged content, that will be efficiently managed.</p>
<h3>Implementation</h3>
<p>If you don&#8217;t care about how all this works behind the scenes, then you can stop reading now.</p>
<p>There&#8217;s three parts to making all of the above work, apart from the initial <em>linked image</em> functionality that Ed worked on, which was fundamental to all of the system repository work.</p>
<ul class="simple">
<li>IPS client/repository support</li>
<li>Zones proxy</li>
<li>System repository</li>
</ul>
<h3>IPS client/repository support</h4>
<p>Brock managed the heavy lifting here.  This work involved:</p>
<ul class="simple">
<li>defining an interchange format that IPS could use to pass publisher configuration between the global and non-global zones</li>
<li>refreshing the system repository service on every parent image publisher change</li>
<li>allowing local publisher configuration to merge with system publisher configuration</li>
<li>ensuring that system-provided publishers could not have their order changed</li>
<li>allowing an image to be created that has no publishers</li>
<li>toggling use of the system publisher</li>
</ul>
<h3>Zones proxy</h3>
<p>The zones proxy client, when started in the non-global zone creates a socket which listens on an inet port on 127.0.0.1.  It passes the file descriptor for this socket to the zones proxy daemon via a door call.</p>
<p>The zones proxy daemon then listens for connections on the file descriptor. When the zone proxy daemon receives  a connection, it proxies the connection to the system repository.</p>
<p>This allows the zone to access the system repository without any additional networking configuration needed (which I think is pretty neat &#8211; nicely done Krister!)</p>
<h3>System repository</h3>
<p>The system repository itself consists of two components:</p>
<ul class="simple">
<li>A Python program, <tt class="docutils literal">/usr/lib/pkg.sysrepo</tt></li>
<li>A custom Apache 2.2 instance</li>
</ul>
<p>Brock initially prototyped some httpd.conf configurations, and I worked on the code to write them automatically, produce the response that the system repository would use to inform zones of the configured publishers, and also worked out how to proxy access to file-based publishers in the global zone, which was an interesting problem to solve.</p>
<p>When you start the system-repository service in the global zone, <tt class="docutils literal">pkg.sysrepo(1)</tt> determines the enabled, configured publishers then creates a response file served to non-global zones that want to discover the publishers configured in the global zone.  It then uses a <a class="reference external" href="http://www.makotemplates.org/">Mako</a> template from <tt class="docutils literal">/etc/pkg/sysrepo/sysrepo_httpd.conf.mako</tt> to generate an Apache configuration file.</p>
<p>The configuration file describes a basic caching proxy, providing limited access to the URLs of each publisher, as well as allowing URL rewrites to serve any file-based repositories.   It uses the SSL keys and certificates from the global zone, and allows proxies access to those from the non-global zone over http.<br />
(remember, data served by the system repository between the zone and non-global zone goes over the zones proxy socket, so http is fine here: access from the proxy to the publisher still goes over https)</p>
<p>The system repository service then starts an Apache instance, and a daemon to keep the proxy cache down to its configured maximum size.  More detail on the options available to tune the system repository are in <tt class="docutils literal">pkg.sysrepo(1)</tt> man page.</p>
<h3>Result?</h3>
<p>The practical upshot of all this, is that all zones can access all publishers configured on the global zone, and if that configuration changes, the zones publishers automatically change too.   Of course, non-global zones can add their own publishers, but aren&#8217;t allowed to change the order, or disable any system<br />
publishers.</p>
<p>Here&#8217;s what the <tt class="docutils literal">pkg publisher</tt> output looks like in a non-global zone:</p>
<pre class="literal-block">
root&#064;puroto:~# pkg publisher
PUBLISHER                             TYPE     STATUS   URI
solaris                  (non-sticky, syspub) origin   online   proxy://http://pkg.oracle.com/solaris11/release/
mypublisher              (syspub)     origin   online   http://localhost:1008/mypublisher/89227627f3c003d11b1e4c0b5356a965ef7c9712/
test                     (syspub)     origin   online   http://localhost:1008/test/eec48b7c8b107bb3ec9b9cf0f119eb3d90b5303e/
</pre>
<p>and here&#8217;s the system repository running in the global zone:</p>
<pre class="literal-block">
$ ps -fu pkg5srv | grep httpd
 pkg5srv   206  2334   0 12:02:02 ?           0:00 /usr/apache2/2.2/bin/64/httpd.worker -f /system/volatile/pkg/sysrepo/sysrepo_ht
 pkg5srv   204  2334   0 12:02:02 ?           0:00 /usr/apache2/2.2/bin/64/httpd.worker -f /system/volatile/pkg/sysrepo/sysrepo_ht
 pkg5srv   205  2334   0 12:02:02 ?           0:00 /usr/apache2/2.2/bin/64/httpd.worker -f /system/volatile/pkg/sysrepo/sysrepo_ht
 pkg5srv   939  2334   0 12:46:32 ?           0:00 /usr/apache2/2.2/bin/64/httpd.worker -f /system/volatile/pkg/sysrepo/sysrepo_ht
</pre>
<p>Personally, I&#8217;ve found this capability to be incredibly useful.  I work from home, and have a system with an internet-facing non-global zone, and a global zone accessing our corporate VPN.  My non-global zone is able to securely access new packages when it needs to (and I get to test my own code at the same time!)</p>
<p>Performing a <tt class="docutils literal">pkg update</tt> from the global zone ensures that all zones are kept in sync, and will update all zones automatically (though, as mentioned in the <a href="http://download.oracle.com/docs/cd/E23824_01/html/821-1460/z.pkginst.ov-10.html#scrolltoc">Zones administration guide</a>, <tt class="docutils literal">pkg update &lt;list of packages&gt;</tt> will simply update the global zone, and ensure that during that update <strong>only</strong> the packages that cross the kernel/userland boundary are updated in each zone.)</p>
<p>Working on zones and the system repository was a lot of fun &#8211; hope you find it useful.</p>
<br />Filed under: <a href='http://timsfoster.wordpress.com/category/ips/'>IPS</a>, <a href='http://timsfoster.wordpress.com/category/opensolaris/'>OpenSolaris</a>  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/timsfoster.wordpress.com/2848/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/timsfoster.wordpress.com/2848/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/timsfoster.wordpress.com/2848/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/timsfoster.wordpress.com/2848/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/timsfoster.wordpress.com/2848/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/timsfoster.wordpress.com/2848/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/timsfoster.wordpress.com/2848/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/timsfoster.wordpress.com/2848/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/timsfoster.wordpress.com/2848/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/timsfoster.wordpress.com/2848/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/timsfoster.wordpress.com/2848/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/timsfoster.wordpress.com/2848/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/timsfoster.wordpress.com/2848/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/timsfoster.wordpress.com/2848/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=timsfoster.wordpress.com&amp;blog=11695716&amp;post=2848&amp;subd=timsfoster&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://timsfoster.wordpress.com/2011/11/09/the-ips-system-repository/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">timsfoster</media:title>
		</media:content>

		<media:content url="http://timsfoster.files.wordpress.com/2011/11/plumbing.jpg" medium="image">
			<media:title type="html">Original image by nori_n</media:title>
		</media:content>
	</item>
		<item>
		<title>IPS Self-assembly &#8211; Part 1: overlays</title>
		<link>http://timsfoster.wordpress.com/2011/11/09/ips-self-assembly-part-1-overlays/</link>
		<comments>http://timsfoster.wordpress.com/2011/11/09/ips-self-assembly-part-1-overlays/#comments</comments>
		<pubDate>Wed, 09 Nov 2011 15:02:15 +0000</pubDate>
		<dc:creator>timsfoster</dc:creator>
				<category><![CDATA[IPS]]></category>
		<category><![CDATA[OpenSolaris]]></category>

		<guid isPermaLink="false">http://timsfoster.wordpress.com/?p=2831</guid>
		<description><![CDATA[Introduction I&#8217;m starting a small series of blog posts to talk about one of the important concepts in IPS &#8211; &#8230;<p><a href="http://timsfoster.wordpress.com/2011/11/09/ips-self-assembly-part-1-overlays/">Continue reading &#187;</a></p><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=timsfoster.wordpress.com&amp;blog=11695716&amp;post=2831&amp;subd=timsfoster&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.flickr.com/photos/seadam/5999711285"><img src="http://timsfoster.files.wordpress.com/2011/11/cake.jpg?w=529" alt="Original image by 3liz4" title="Original image by 3liz4"   class="alignleft size-full wp-image-2855" /></a><br />
<h2>Introduction</h2>
<p>I&#8217;m starting a small series of blog posts to talk about one of the important concepts in IPS &#8211; self-assembly.  We cover this in the <a class="reference external" href="http://wikis.sun.com/download/attachments/240520636/oracle-solaris-11-ips-dev-guide.pdf?version=1&amp;modificationDate=1320703758000">IPS Developer Guide</a> but don&#8217;t provide many examples as yet.</p>
<p>In the IPS Developer Guide, we introduced the concept of self-assembly as:</p>
<blockquote><p>
Any collection of installed software on a system should be able to build itself into a working configuration when that system is booted, by the time the packaging operation completes, or at software runtime.</p></blockquote>
<p>Lots of software ships with default configuration in sample files, often installed in /etc.   During packaging, these files are commonly marked as &quot;user editable&quot;, with an attribute defining how those user edits should be treated in the case where the shipped example file gets updated in new release of the package.</p>
<p>In IPS, those user editable files are marked with a <tt>preserve</tt> attribute, which is documented in the <a class="reference external" href="http://download.oracle.com/docs/cd/E23824_01/html/E21796/pkg-5.html#scrolltoc">pkg(5)</a> man page.</p>
<p>However, what happens if we want to allow <em>another</em> package to deliver new configuration instead of simply allowing user edits?</p>
<p>By default, IPS will report an error if two packages try to deliver the same file.</p>
<p>In these blog posts, we&#8217;ll take a sample package, and show how it can be modified to allow us to deliver new add-on packages that deliver different configuration.</p>
<p>Before getting into a more complicated true self-assembly scenario (in the next post), we&#8217;ll cover a very simple one first.</p>
<p>In this first post, we&#8217;ll talk about the <tt class="docutils literal">overlay</tt> attribute.  Technically, this example doesn&#8217;t actually cover <em>self-assembly</em>.  Instead, it shows how IPS allows packages to re-deliver configuration files already delivered by another package.</p>
<p>First, let&#8217;s introduce our example package.</p>
<h2>Our example package</h2>
<p>We&#8217;ll use a package that already exists as our example: the <a class="reference external" href="http://www.squid.org">Squid web proxy</a>.</p>
<p>In our examples, we&#8217;re going to delivering a new version of Squid that allows us to achieve our goal of being able to deliver add-on packages to supply configuration.</p>
<p>To be clear, I&#8217;m <strong>not</strong> suggesting all administrators ought to do this &#8211; by using their own private copy of a package shipped by Oracle, they face the burden of maintaining this version themselves: future upgrades from the <tt class="docutils literal">solaris</tt> publisher will not automatically update their version. By default, publishers in IPS are <em>sticky</em> &#8211; so packages installed from one publisher may not be updated by a new version of that package from another publisher.</p>
<p>Publisher <em>stickiness</em> may be overridden, but then the administrator risks that their carefully crafted package gets updated by a version of the package from Oracle. In addition, the presence of a local version of the package may also prevent updates from occurring.</p>
<p>However, when I was looking for an example of the modifications that need to be made to a package which doesn&#8217;t normally participate in self-assembly, Squid fits the bill nicely.</p>
<p>Let&#8217;s look at the choices that were made when Squid was being packaged for Solaris, concentrating on how its configuration files are handled.</p>
<p>Using the following command, we can show the actions associated with the <tt class="docutils literal">squid.conf</tt> files that are delivered in the package:</p>
<pre class="literal-block">
$ pkg contents -H -r -o action.raw -a path=etc/squid/squid.conf* squid | pkgfmt
</pre>
<p>Here is the output from the command:</p>
<pre class="literal-block">
file 7d8f133b331e7460fbbdca593bff31446f8a3bad path=etc/squid/squid.conf \
    owner=root group=webservd mode=0644 \
    chash=272ed7f686ce409a121f427a5b0bf75aed0e2095 \
    original_name=SUNWsquid:etc/squid/squid.conf pkg.csize=1414 pkg.size=3409 \
    preserve=renamenew
file 7d8f133b331e7460fbbdca593bff31446f8a3bad \
    path=etc/squid/squid.conf.default owner=root group=bin mode=0444 \
    chash=272ed7f686ce409a121f427a5b0bf75aed0e2095 pkg.csize=1414 pkg.size=3409
file 971681745b21a3d88481dbadeea6ce7f87b0070a \
    path=etc/squid/squid.conf.documented owner=root group=bin mode=0444 \
    chash=b9662e497184c97fff50b1c249a6e153c51432e1 pkg.csize=60605 \
    pkg.size=200255
</pre>
<p>We can see that the package delivers three files:</p>
<dl class="docutils">
<dt><tt class="docutils literal">etc/squid/squid.conf</tt></dt>
<dd>This is the default configuration file that squid uses.  You can see that it has a <tt class="docutils literal">preserve</tt> attribute, with a value set to <tt class="docutils literal">renamenew</tt> User edits to this file are allowed, and will be preserved on upgrade, and any new versions of the file (delivered by an updated Squid package) will be renamed.</dd>
<dt><tt class="docutils literal">etc/squid/squid.conf.default</tt></dt>
<dd>Squid also ships with a <em>second</em> copy of the configuration file (notice how the hashes are the same as the previous version) with a different name &#8211; presumably to use as a record of the original configuration.</dd>
<dt><tt class="docutils literal">etc/squid/squid.conf.documented</tt></dt>
<dd>Finally we have another copy of the configuration file, this time with more comments included, to better explain the configuration.</dd>
</dl>
<h2>Adding an overlay attribute</h2>
<p>In IPS, two packages are allowed to deliver the same file if:</p>
<ul class="simple">
<li>one package contains a file with the attribute <tt class="docutils literal">overlay=allow</tt></li>
<li>another package contains the same file, with the attribute <tt class="docutils literal">overlay=true</tt></li>
</ul>
<p>In both cases, all other file attributes (<tt class="docutils literal">owner</tt>, <tt class="docutils literal">mode</tt>, <tt class="docutils literal">group</tt>) must match. The <tt class="docutils literal">overlay</tt> attribute is covered in Chapter 3 of the <a class="reference external" href="http://wikis.sun.com/download/attachments/240520636/oracle-solaris-11-ips-dev-guide.pdf?version=1&amp;modificationDate=1320703758000">IPS Developer Guide</a> and is also documented in the <a class="reference external" href="http://download.oracle.com/docs/cd/E23824_01/html/E21796/pkg-5.html#scrolltoc">pkg(5)</a> man page.</p>
<p>Since our sample package doesn&#8217;t deliver its configuration file, <tt class="docutils literal">etc/squid/squid.conf</tt>, with an <tt class="docutils literal">overlay</tt> attribute, we&#8217;ll need to modify the package.</p>
<p>First, we download the package in a raw form, suitable for republishing later, and show where <a class="reference external" href="http://download.oracle.com/docs/cd/E23824_01/html/E21796/pkgrecv-1.html#scrolltoc">pkgrecv(1)</a> stores the manifest:</p>
<pre class="literal-block">
$ pkgrecv -s http://pkg.oracle.com/solaris/release --raw -d squid-proto squid&#064;3.1.8,5.11-0.175.0.0.0.2.537
Processing packages for publisher solaris ...
Retrieving and evaluating 1 package(s)...
PROCESS                                         ITEMS     GET (MB)    SEND (MB)
Completed                                         1/1    18.0/18.0      0.0/0.0

$ find squid-proto -name manifest
squid-proto/web%2Fproxy%2Fsquid/3.1.8%2C5.11-0.175.0.0.0.2.537%3A20111019T121425Z/manifest
</pre>
<p>Next, we&#8217;ll define a simple <a class="reference external" href="http://download.oracle.com/docs/cd/E23824_01/html/E21796/pkgmogrify-1.html#scrolltoc">pkgmogrify(1)</a> transform to add an <tt class="docutils literal">overlay=allow</tt> attribute.</p>
<p>We&#8217;ll also remove the <tt class="docutils literal">solaris</tt> publisher from the FMRI, as we intend to republish this package to our own repository. (This transform is discussed in more detail in Chapter 14 of the <a class="reference external" href="http://wikis.sun.com/download/attachments/240520636/oracle-solaris-11-ips-dev-guide.pdf?version=1&amp;modificationDate=1320703758000">IPS Developer Guide</a>)</p>
<p>The transform looks like:</p>
<pre class="literal-block">
&lt;transform set name=pkg.fmri -&gt; edit value pkg://[^/]+/ pkg://mypublisher/&gt;
&lt;transform file path=etc/squid/squid.conf$ -&gt; set overlay allow&gt;
</pre>
<p>Here&#8217;s how we run it:</p>
<pre class="literal-block">
$ pkgmogrify squid-overlay.mog \
    squid-proto/web%2Fproxy%2Fsquid/3.1.8%2C5.11-0.175.0.0.0.2.537%3A20111019T121425Z/manifest \
    &gt; squid-overlay.mf
</pre>
<p>Finally we can republish our package:</p>
<pre class="literal-block">
$ pkgsend -s myrepository publish \
    -d squid-proto/web%2Fproxy%2Fsquid/3.1.8%2C5.11-0.175.0.0.0.2.537%3A20111019T121425Z \
    squid-overlay.mf
WARNING: Omitting signature action 'signature 2ce2688faa049abe9d5dceeeabc4b17e7b72e792
.
.
.
pkg://mypublisher/web/proxy/squid&#064;3.1.8,5.11-0.175.0.0.0.2.537:20111108T220909Z
PUBLISHED
</pre>
<p>We get a warning when republishing it saying that we&#8217;re dropping the signature action (I&#8217;ve trimmed the output here).</p>
<p>Package signing is always performed on a repository using <a class="external reference" href="http://download.oracle.com/docs/cd/E23824_01/html/E21796/pkgsign-1.html#scrolltoc">pkgsign(1)</a>, never on a manifest.  Since the package&#8217;s timestamp is always updated on publication, that would cause any hardcoded signatures to be invalid.  Package signing is covered in more detail in Chapter 11 of the <a class="reference external" href="http://wikis.sun.com/download/attachments/240520636/oracle-solaris-11-ips-dev-guide.pdf?version=1&amp;modificationDate=1320703758000">IPS Developer Guide</a>.</p>
<p>This gets us part of the way towards our goal: we&#8217;ve now got a version of Squid that can allow other packages to deliver a new copy of <tt class="docutils literal">etc/squid/squid.conf</tt>.</p>
<p>Notice that we&#8217;ve left the version alone on our copy of Squid, so it still complies with the same package version constraints that were on the original version of Squid that was shipped with Solaris.</p>
<h2>Writing Configuration Packages</h2>
<p>At this point, we can start writing packages to deliver new versions of our configuration file.</p>
<p>First let&#8217;s install our modified squid package.  We&#8217;ll add our local repository to the system, and make sure we search for packages there before the <tt class="docutils literal">solaris</tt> publisher, so that our packages are discovered first.</p>
<pre class="literal-block">
$ pfexec pkg set-publisher --search-before=solaris -p ./myrepository
Updated publisher(s): mypublisher
$ pfexec pkg install squid
           Packages to install:  1
       Create boot environment: No
Create backup boot environment: No
            Services to change:  1

DOWNLOAD                                  PKGS       FILES    XFER (MB)
Completed                                  1/1   1519/1519      8.5/8.5

PHASE                                        ACTIONS
Install Phase                              1704/1704

PHASE                                          ITEMS
Package State Update Phase                       1/1
Image State Update Phase                         2/2
</pre>
<p>Next, we&#8217;ll create our configuration package.  Perhaps the only thing we want to change, is the default port that Squid listens on.  Let&#8217;s write a new <tt class="docutils literal">squid.conf</tt> file that uses port 8080 instead of 3128:</p>
<p>Our original squid configuration shows:</p>
<pre class="literal-block">
$ grep 3128 /etc/squid/squid.conf
# Squid normally listens to port 3128
http_port 3128
</pre>
<p>We&#8217;ll write our new configuration:</p>
<pre class="literal-block">
$ mkdir -p squid-conf-proto/etc/squid
$ cat /etc/squid/squid.conf | sed -e 's/3128/8080/g' \
    &gt; squid-conf-proto/etc/squid/squid.conf
$ grep 8080 squid-conf-proto/etc/squid/squid.conf
# Squid normally listens to port 8080
http_port 8080
</pre>
<p>Now, we&#8217;ll create a package for the file.  We&#8217;ll make the package depend on our Squid package.  For this package, since the Squid package already delivers the <tt class="docutils literal">dir</tt> action needed for <tt class="docutils literal">etc/squid</tt> we&#8217;ll just deliver the file-action for our new squid.conf.</p>
<pre class="literal-block">
$ cat &gt; squid-conf.mf
set name=pkg.fmri value=config/web/proxy/squid-configuration&#064;1.0
set name=pkg.summary value=&quot;My Company Inc. Default squid.conf settings&quot;
file path=etc/squid/squid.conf owner=root group=webservd mode=0644 \
    overlay=true preserve=renameold
depend type=require fmri=web/proxy/squid&#064;3.1.8
^D
</pre>
<p>Notice that we have specified <tt class="docutils literal">overlay=true</tt> to indicate that this action should overlay any existing file, and have specified <tt class="docutils literal">preserve=renameold</tt> to indicate that we want the old file renamed if one exists.</p>
<pre class="literal-block">
$ pkgsend -s myrepository publish -d squid-conf-proto squid-conf.mf
pkg://mypublisher/config/web/proxy/squid-configuration&#064;1.0,5.11:20111108T150325Z
PUBLISHED
</pre>
<p>We can now install this package to our system, and check to make sure our changes have appeared:</p>
<pre class="literal-block">
$ pfexec pkg install squid-configuration
           Packages to install:  1
       Create boot environment: No
Create backup boot environment: No

DOWNLOAD                                  PKGS       FILES    XFER (MB)
Completed                                  1/1         1/1      0.0/0.0

PHASE                                        ACTIONS
Install Phase                                    4/4

PHASE                                          ITEMS
Package State Update Phase                       1/1
Image State Update Phase                         2/2

The following unexpected or editable files and directories were
salvaged while executing the requested package operation; they
have been moved to the displayed location in the image:

  etc/squid/squid.conf -&gt; /var/pkg/lost+found/etc/squid/squid.conf-20111108T071810Z

$ grep 8080 /etc/squid/*
/etc/squid/squid.conf:# Squid normally listens to port 8080
/etc/squid/squid.conf:http_port 8080
$ pkg list squid squid-configuration
NAME (PUBLISHER)                                  VERSION                    IFO
config/web/proxy/squid-configuration              1.0                        i--
web/proxy/squid                                   3.1.8-0.175.0.0.0.2.537    i--
</pre>
<h2>Conclusion</h2>
<p>This was a pretty simple case &#8211; we&#8217;ve simply modified an existing package, and delivered a single new package allowing a single configuration package to deliver a change to the file.</p>
<p>This wasn&#8217;t really <em>self-assembly</em> per se, since the configuration is still hard-coded, but it is a common use-case, and provides a good introduction to our next example.</p>
<p>However, what happens if we want to deliver a further change to this file, from another package?  Trying the same approach again, creating a new package &quot;pkg:/config/web/proxy/squid-configuration-redux&quot; then trying to install it,<br />
we see:</p>
<pre class="literal-block">
$ pkgsend -s myrepository publish -d squid-conf-proto squid-conf-redux.mf
pkg://mypublisher/config/web/proxy/squid-configuration-redux&#064;1.0,5.11:20111108T152449Z
PUBLISHED

$ pfexec pkg install squid-configuration-redux
Creating Plan |
pkg install: The following packages all deliver file actions to etc/squid/squid.conf:

  pkg://mypublisher/web/proxy/squid&#064;3.1.8,5.11-0.175.0.0.0.2.537:20111108T151647Z
  pkg://mypublisher/config/web/proxy/squid-configuration-redux&#064;1.0,5.11:20111108T152449Z
  pkg://mypublisher/config/web/proxy/squid-configuration&#064;1.0,5.11:20111108T151420Z

These packages may not be installed together. Any non-conflicting set may
be, or the packages must be corrected before they can be installed.
</pre>
<p>So IPS only allows one configuration package to be installed at a time.  We&#8217;ll uninstall our configuration package, revert the old squid.conf content, then install our new configuration package:</p>
<pre class="literal-block">
$ pfexec pkg uninstall squid-configuration
            Packages to remove:  1
       Create boot environment: No
Create backup boot environment: No

PHASE                                        ACTIONS
Removal Phase                                    3/3

PHASE                                          ITEMS
Package State Update Phase                       1/1
Package Cache Update Phase                       1/1
Image State Update Phase                         2/2

$ pfexec pkg revert /etc/squid/squid.conf
            Packages to update:  1
       Create boot environment: No
Create backup boot environment: No

DOWNLOAD                                  PKGS       FILES    XFER (MB)
Completed                                  1/1         1/1      0.0/0.0

PHASE                                        ACTIONS
Update Phase                                     1/1

PHASE                                          ITEMS
Image State Update Phase                         2/2
$ pfexec pkg install squid-configuration-redux
           Packages to install:  1
       Create boot environment: No
Create backup boot environment: No

DOWNLOAD                                  PKGS       FILES    XFER (MB)
Completed                                  1/1         1/1      0.0/0.0

PHASE                                        ACTIONS
Install Phase                                    4/4

PHASE                                          ITEMS
Package State Update Phase                       1/1
Image State Update Phase                         2/2

The following unexpected or editable files and directories were
salvaged while executing the requested package operation; they
have been moved to the displayed location in the image:

  etc/squid/squid.conf -&gt; /var/pkg/lost+found/etc/squid/squid.conf-20111108T072930Z
</pre>
<p>We see that the new configuration file has been installed.</p>
<p>In the next post in this series, we&#8217;ll provide a more complex example of<br />
self-assembly.</p>
<br />Filed under: <a href='http://timsfoster.wordpress.com/category/ips/'>IPS</a>, <a href='http://timsfoster.wordpress.com/category/opensolaris/'>OpenSolaris</a>  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/timsfoster.wordpress.com/2831/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/timsfoster.wordpress.com/2831/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/timsfoster.wordpress.com/2831/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/timsfoster.wordpress.com/2831/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/timsfoster.wordpress.com/2831/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/timsfoster.wordpress.com/2831/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/timsfoster.wordpress.com/2831/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/timsfoster.wordpress.com/2831/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/timsfoster.wordpress.com/2831/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/timsfoster.wordpress.com/2831/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/timsfoster.wordpress.com/2831/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/timsfoster.wordpress.com/2831/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/timsfoster.wordpress.com/2831/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/timsfoster.wordpress.com/2831/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=timsfoster.wordpress.com&amp;blog=11695716&amp;post=2831&amp;subd=timsfoster&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://timsfoster.wordpress.com/2011/11/09/ips-self-assembly-part-1-overlays/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">timsfoster</media:title>
		</media:content>

		<media:content url="http://timsfoster.files.wordpress.com/2011/11/cake.jpg" medium="image">
			<media:title type="html">Original image by 3liz4</media:title>
		</media:content>
	</item>
		<item>
		<title>Self assembly &#8211; Part 2: multiple packages delivering configuration</title>
		<link>http://timsfoster.wordpress.com/2011/11/09/self-assembly-part-2-multiple-packages-delivering-configuration/</link>
		<comments>http://timsfoster.wordpress.com/2011/11/09/self-assembly-part-2-multiple-packages-delivering-configuration/#comments</comments>
		<pubDate>Wed, 09 Nov 2011 10:08:16 +0000</pubDate>
		<dc:creator>timsfoster</dc:creator>
				<category><![CDATA[IPS]]></category>
		<category><![CDATA[OpenSolaris]]></category>

		<guid isPermaLink="false">http://timsfoster.wordpress.com/?p=2838</guid>
		<description><![CDATA[Introduction In the previous post in this series, we showed how it was possible to take a single package and &#8230;<p><a href="http://timsfoster.wordpress.com/2011/11/09/self-assembly-part-2-multiple-packages-delivering-configuration/">Continue reading &#187;</a></p><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=timsfoster.wordpress.com&amp;blog=11695716&amp;post=2838&amp;subd=timsfoster&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.flickr.com/photos/bre/3458247336/"><img src="http://timsfoster.files.wordpress.com/2011/11/self-assembly.jpg?w=529" alt="Original image by bre pattis" title="Original image by bre pattis"   class="alignleft size-full wp-image-2842" /></a></p>
<h2>Introduction</h2>
<p>In the <a href="http://timsfoster.wordpress.com/2011/11/09/ips-self-assembly-part-1-overlays">previous post</a> in this series, we showed how it was possible to take a single package and republish it, such that other packages could overwrite a default configuration file.</p>
<p>The example we used was the <a class="reference external" href="http://www.squid.org">Squid web proxy</a>, allowing configuration packages to overwrite <tt class="docutils literal">/etc/squid/squid.conf</tt> with new contents.</p>
<p>There was a limitation using that approach: only one package could contribute to that configuration at a time, replacing the entire shipped configuration.</p>
<p>Recall, that we define self-assembly in Chapter 1 of the <a class="reference external" href="http://wikis.sun.com/download/attachments/240520636/oracle-solaris-11-ips-dev-guide.pdf">IPS Developer Guide</a> as:</p>
<blockquote><p>
Any collection of installed software on a system should be able to build itself into a working configuration when that system is booted, by the time the packaging operation completes, or at software runtime.</p></blockquote>
<p>In this post, we&#8217;ll cover a more advanced case than last time: true <em>self-assembly</em>, where the configuration can be delivered by multiple add-on packages, if necessary. In particular, we&#8217;ll continue to talk about Squid, a package that <em>isn&#8217;t</em> normally capable of self-assembly, and will show how we fix that.</p>
<h2>How does self-assembly work?</h2>
<p>The main premise with self-assembly, is that configuration for an application must be built from a <em>composed</em> view of all fragments of the entire configuration that are present on the system. That can be done either by the application itself, in which case nothing else is required on the part of the application packager, or it can be done with an add-on service to assemble the entire configuration file from the delivered fragments.</p>
<p>When a new package delivers another fragment of the configuration, then the application must have its configuration rebuilt to include that fragment.</p>
<p>Similarly, when a fragment is removed from the system, again, the application must have its configuration rebuilt from the remaining fragments on the system.</p>
<p>A good example of self-assembly is in the Solaris package for <tt class="docutils literal"><span class="pre">pkg:/web/server/apache-22</span></tt>.  Solaris ships a default <tt class="docutils literal">httpd.conf</tt> file that has an <tt class="docutils literal">Include</tt> directive that references <tt class="docutils literal">/etc/apache2/2.2/conf.d</tt>.</p>
<p>Packages can deliver a new file to that directory, and use a <tt class="docutils literal">refresh_fmri</tt> actuator causing the system to automatically to refresh the Apache instance<br />
either after a <tt class="docutils literal">pkg install</tt> operation has completed, or after a<br />
<tt class="docutils literal">pkg remove</tt> operation has completed, causing the webserver to rebuild its configuration.</p>
<p>The <em>reason</em> behind self-assembly, is to replace postinstall, preinstall, preremove, postremove and class action scripts, needed by other packaging systems.  Install-time scripting was a common source of errors during application packaging because the scripting had to work in multiple scenarios.</p>
<p>For example, scripts had to correctly run</p>
<ul class="simple">
<li>against alternate image roots, perhaps running on a system that didn&#8217;t have<br />
the necessary tools support to correctly run the script</li>
<li>within the confines of a LiveCD environment</li>
<li>when making edits to an offline zone</li>
</ul>
<p>With IPS, we eliminated those forms of install-time scripting, concentrating on an atomic set of <em>actions</em> (discussed in Chapter 3 of the <a class="reference external" href="http://wikis.sun.com/download/attachments/240520636/oracle-solaris-11-ips-dev-guide.pdf">IPS Developer Guide</a>) that performed common packaging tasks, and allowing for <em>actuators</em> (discussed in Chapter 9 of the <a class="reference external" href="http://wikis.sun.com/download/attachments/240520636/oracle-solaris-11-ips-dev-guide.pdf?version=1&amp;modificationDate=1320703758000">IPS Developer Guide</a>) to run during packaging operations.</p>
<p>Actuators enable self-assembly to work on live systems by restarting or refreshing the necessary SMF services. Since the same SMF services they point to run during boot as well, we don&#8217;t need to do anything when performing operations on alternate images: the next time the image is booted, our self-assembly is completed.</p>
<h2>Making Squid self-assembly aware</h2>
<p>As in the <a href="http://timsfoster.wordpress.com/2011/11/09/ips-self-assembly-part-1-overlays">previous post</a>, we will start by downloading and modifying our Squid package.</p>
<p>This time, we intend to remove the <tt class="docutils literal">etc/squid/squid.conf</tt> file entirely &#8211; our self-assembly service will be constructing this file instead for us.  Recall that<br />
Squid delivers some of its configuration files with the following actions:</p>
<pre class="literal-block">
file 7d8f133b331e7460fbbdca593bff31446f8a3bad path=etc/squid/squid.conf \
    owner=root group=webservd mode=0644 \
    chash=272ed7f686ce409a121f427a5b0bf75aed0e2095 \
    original_name=SUNWsquid:etc/squid/squid.conf pkg.csize=1414 pkg.size=3409 \
    preserve=renamenew
file 7d8f133b331e7460fbbdca593bff31446f8a3bad \
    path=etc/squid/squid.conf.default owner=root group=bin mode=0444 \
    chash=272ed7f686ce409a121f427a5b0bf75aed0e2095 pkg.csize=1414 pkg.size=3409
file 971681745b21a3d88481dbadeea6ce7f87b0070a \
    path=etc/squid/squid.conf.documented owner=root group=bin mode=0444 \
    chash=b9662e497184c97fff50b1c249a6e153c51432e1 pkg.csize=60605 \
    pkg.size=200255
</pre>
<p>Since <tt class="docutils literal">squid.conf.default</tt> is already shipped and is identical to the<br />
<tt class="docutils literal">squid.conf</tt> file that is also delivered, we can use that for the basis of our self-assembly of the <tt class="docutils literal">squid.conf</tt> configuration file.</p>
<p>We download a copy of the package with the following command:</p>
<pre class="literal-block">
$ pkgrecv -s http://pkg.oracle.com/solaris/release --raw -d squid-proto squid&#064;3.1.8,5.11-0.175.0.0.0.2.537
</pre>
<p>which pulls the content into the <tt class="docutils literal"><span class="pre">squid-proto</span></tt> directory.</p>
<p>We&#8217;ll use a series of <a href="http://download.oracle.com/docs/cd/E23824_01/html/E21796/pkgmogrify-1.html#scrolltoc" class="external reference">pkgmogrify(1)</a> transforms to edit the package contents, similar to the ones we used in the <a href="http://timsfoster.wordpress.com/2011/11/09/ips-self-assembly-part-1-overlays">previous post</a>.  We will remove the file action that delivers <tt class="docutils literal">squid.conf</tt> using a <tt class="docutils literal">drop</tt> transform operation, and will also deliver a new directory, <tt class="docutils literal">etc/squid/conf.d</tt>.  Here is the transform file that accomplishes that:</p>
<pre class="literal-block">
&lt;transform set name=pkg.fmri -&gt; edit value pkg://[^/]+/ pkg://mypublisher/&gt;
&lt;transform file path=etc/squid/squid.conf$ -&gt; drop&gt;
dir path=etc/squid/conf.d owner=root group=bin mode=0755
</pre>
<p>We can create a new manifest using this transform using <a href="http://download.oracle.com/docs/cd/E23824_01/html/E21796/pkgmogrify-1.html#scrolltoc" class="external reference">pkgmogrify(1)</a>:</p>
<pre class="literal-block">
$ pkgmogrify squid\-assembly.mog \
    squid-proto/web%2Fproxy%2Fsquid/3.1.8%2C5.11-0.175.0.0.0.2.537%3A20111019T121425Z/manifest \
    &gt; squid-assembly.mf
</pre>
<h2>A self-assembly SMF service</h2>
<p>In order for self-assembly to happen during packaging operations, we need to use an <em>actuator</em> discussed in Chapter 9 of the <a class="reference external" href="http://wikis.sun.com/download/attachments/240520636/oracle-solaris-11-ips-dev-guide.pdf?version=1&amp;modificationDate=1320703758000">IPS Developer Guide</a>.</p>
<p>The actuator is a special tag on any IPS action that points to an SMF service. The SMF service is made up of two components:</p>
<ul class="simple">
<li>The SMF manifest</li>
<li>The SMF method script</li>
</ul>
<p>This self-assembly SMF service is going to be responsible for building the contents of /etc/squid/squid.conf.   We&#8217;ll talk about each component in the following section:</p>
<h3>SMF manifest</h3>
<p>This is what the SMF manifest of our self-assembly service looks like:</p>
<pre class="literal-block">
&lt;?xml version=&quot;1.0&quot;?&gt;
&lt;!DOCTYPE service_bundle SYSTEM &quot;/usr/share/lib/xml/dtd/service_bundle.dtd.1&quot;&gt;

&lt;service_bundle type='manifest' name='Squid:self-assembly'&gt;

&lt;service
    name='config/network/http/squid-assembly'
    type='service'
    version='1'&gt;

    &lt;single_instance /&gt;

    &lt;dependency
        name='fs-local'
        grouping='require_all'
        restart_on='none'
        type='service'&gt;
            &lt;service_fmri value='svc:/system/filesystem/local:default' /&gt;
    &lt;/dependency&gt;

    &lt;dependent
            name='squid_self-assembly-complete'
            grouping='optional_all'
            restart_on='none'&gt;
            &lt;service_fmri value='svc:/milestone/self-assembly-complete' /&gt;
    &lt;/dependent&gt;
    &lt;instance enabled='true' name='default'&gt;
            &lt;exec_method
                type='method'
                name='start'
                exec='/lib/svc/method/squid-self-assembly'
                timeout_seconds='30'/&gt;

            &lt;exec_method
                type='method'
                name='stop'
                exec=':true'
                timeout_seconds='0'/&gt;

            &lt;property_group name='startd' type='framework'&gt;
                &lt;propval name='duration' type='astring' value='transient' /&gt;
            &lt;/property_group&gt;
    &lt;/instance&gt;
&lt;/service&gt;
&lt;/service_bundle&gt;
</pre>
<p>This defines a service instance that we intend to use whenever we deliver new configuration file fragments to the system.</p>
<p>For that to happen, any configuration file fragment added or removed must include a <tt class="docutils literal">restart_fmri</tt> actuator.</p>
<p>For example, a package might deliver a configuration file fragment:</p>
<pre class="literal-block">
file path=etc/squid/squid.conf/myconfig.conf owner=root group=bin mode=0644 \
    restart_fmri=svc:/config/network/http/squid-assembly:default \
    restart_fmri=svc:/network/http/squid:default
</pre>
<p>The other vital thing needed, is an SMF dependency on the SMF service delivered by the Squid package.  We need to add this, so that the Squid application will only be able to start once our self-assembly service has finished producing our configuration file.</p>
<p>First, we&#8217;ll create a <tt class="docutils literal">proto</tt> area for the files we&#8217;re going to add to our Squid package, and copy the default SMF manifest:</p>
<pre class="literal-block">
$ mkdir -p squid-assembly-proto/lib/svc/manifest/network
$ cp /lib/svc/manifest/network/http\-squid.xml squid-assembly-proto/lib/svc/manifest/network
</pre>
<p>Next, we edit the <tt class="docutils literal"><span class="pre">http-squid.xml</span></tt> SMF manifest, adding the following:</p>
<pre class="literal-block">
&lt;!--
  Wait for the Squid self-assembly service to complete
--&gt;
&lt;dependency name='squid-assembly'
    grouping='require_all'
    restart_on='none'
    type='service'&gt;
    &lt;service_fmri
        value='svc:/config/network/http/squid-assembly:default'/&gt;
&lt;/dependency&gt;
</pre>
<p>Now that we&#8217;ve done this, our next step, is writing the method script for our self-assembly service.</p>
<h3>The SMF method script</h4>
<p>We need to write a script, such that when it is run, we end up with /etc/squid.conf containing all changes, as defined in all configuration fragments installed on the system.</p>
<p>This step can be as simple or complex as you&#8217;d like it to be &#8211; essentially we&#8217;re performing postinstall scripting here, but on our terms: we know exactly the environment the script is running in &#8211; that of a booted OS where our package is installed (defined by the <tt class="docutils literal">depend</tt> actions that accompany the package)</p>
<p>Here is a sample script, written in Python (as short as I could make it, so there&#8217;s very little error checking involved here) which takes <tt class="docutils literal">squid.conf.default</tt> copies it to <tt class="docutils literal">squid.conf</tt>, then applies a series of edits to it.</p>
<p>We&#8217;ll save the script as <tt class="docutils literal"><span class="pre">/lib/svc/method/squid-self-assembly</span></tt>.</p>
<pre class="literal-block">
#!/usr/bin/python2.6
import shutil
import os
import re
import logging

# define the paths we'll work with
MASTER=&quot;/etc/squid/squid.conf.default&quot;
CONF_FILE=&quot;/etc/squid/squid.conf&quot;
CONF_DIR=&quot;/etc/squid/conf.d/&quot;

# verbose logging for now
logging.basicConfig(level=logging.DEBUG)

def apply_edits(fragment):
        &quot;&quot;&quot;Takes edit operations in the path &quot;fragment&quot;, and applies
        them to CONF_FILE in order. The syntax of our config file is
        intentionally basic. We support the following operations:

        # lines that start with a hash are comments
        add &lt;line to add to the config file&gt;
        remove &lt;regular expression to remove&gt;
        &quot;&quot;&quot;

        squid_config = file(CONF_FILE).readlines()
        squid_config = &quot;&quot;.join(squid_config)

        # read our list of operations
        operations = open(fragment, &quot;r&quot;).readlines()
        operations = [line.rstrip() for line in operations]
        for op in operations:
                if op.startswith(&quot;add&quot;):
                        addition = op[len(&quot;add&quot;) + 1:]
                        logging.debug(&quot;adding line %s&quot; % addition)
                        squid_config += &quot;\n&quot; + addition
                elif op.startswith(&quot;remove&quot;):
                        exp = op[len(&quot;remove&quot;) + 1:]
                        squid_config = re.sub(exp, &quot;&quot;, squid_config)
                        logging.debug(&quot;removing expression %s&quot; % exp)
                elif op.startswith(&quot;#&quot;):
                        pass

        conf = open(CONF_FILE, &quot;w&quot;)
        conf.write(squid_config + &quot;\n&quot;)
        conf.close()

# first, remove any existing configuration
if os.path.exists(CONF_FILE):
       os.unlink(CONF_FILE)

# now copy the master template file in, on
# which all edits are based
shutil.copy(MASTER, CONF_FILE)
os.chmod(CONF_FILE, 0644)

fragments = []
# now iterate through the contents of /etc/squid/conf.d
# looking for configuration fragments, and apply the changes
# find in a defined order.   We do not look in subdirectories.
for dirpath, dirnames, filenames in os.walk(&quot;/etc/squid/conf.d/&quot;):
        fragments = sorted(filenames)
        break

for fragment in fragments:
        logging.debug(&quot;Applying edits from %s&quot; % fragment)
        apply_edits(os.path.join(CONF_DIR, fragment))
</pre>
<h3>Testing the self-assembly script</h3>
<p>We can now test the self-assembly script.  For the most part, this testing can be done outside the confines of the <a class="reference external" href="http://download.oracle.com/docs/cd/E23824_01/html/E21796/pkg-1.html#scrolltoc">pkg(1)</a> command &#8211; we simply need to ensure<br />
that our self-assembly script runs properly.</p>
<p>First, we&#8217;ll check that the squid.conf file isn&#8217;t present, run the script, then determine that the contents are the same as <tt class="docutils literal">squid.conf.default</tt></p>
<pre class="literal-block">
# ls /etc/squid/squid.conf
/etc/squid/squid.conf: No such file or directory
# /lib/svc/method/squid-self-assembly
# digest -a sha1 /etc/squid/squid.conf.default /etc/squid/squid.conf
(/etc/squid/squid.conf.default) = 7d8f133b331e7460fbbdca593bff31446f8a3bad
(/etc/squid/squid.conf) = 7d8f133b331e7460fbbdca593bff31446f8a3bad
#
</pre>
<p>Next, we&#8217;ll try a simple configuration fragment:</p>
<pre class="literal-block">
# cat &gt; /etc/squid/conf.d/change_http_port.conf
# The default configuration uses port 3128, our organisation uses 8080
# We'll remove that default, add a comment, and add a http_port directive
remove # Squid normally listens to port 3128
remove http_port 3128
add # Our organisation requires Squid to operate on port 8080
add http_port 8080
^D
</pre>
<p>Then we&#8217;ll test the self-assembly script again:</p>
<pre class="literal-block">
# /lib/svc/method/squid-self-assembly
DEBUG:root:  --- applying edits from change_http_port.conf   ---
DEBUG:root:removing expression # Squid normally listens to port 3128
DEBUG:root:removing expression http_port 3128
DEBUG:root:adding line # Our organisation requires Squid to operate on port 8080
DEBUG:root:adding line http_port 8080
</pre>
<p>We can verify that the changes have been made:</p>
<pre class="literal-block">
# grep &quot;port 8080&quot; /etc/squid/squid.conf
# Our organisation requires Squid to operate on port 8080
http_port 8080
</pre>
<p>Now, we&#8217;ll add another configuration fragment:</p>
<pre class="literal-block">
# cat &gt; /etc/squid/conf.d/connect_ports.conf
# We want to allow users to connect to gmail and irc
# over our proxy server.
add # We need to allow access to gmail and irc
add acl Connect_ports port 5222     # gmail chat
add acl Connect_ports port 6667     # irc chat
add http_access allow CONNECT Connect_ports
^D
</pre>
<p>and see what happens when we run the self-assembly script:</p>
<pre class="literal-block">
# /lib/svc/method/squid-self-assembly
DEBUG:root:  --- applying edits from change_http_port.conf   ---
DEBUG:root:removing expression # Squid normally listens to port 3128
DEBUG:root:removing expression http_port 3128
DEBUG:root:adding line # Our organisation requires Squid to operate on port 8080
DEBUG:root:adding line http_port 8080
DEBUG:root:  --- applying edits from connect_ports.conf   ---
DEBUG:root:adding line # We need to allow access to gmail and irc
DEBUG:root:adding line acl Connect_ports port 5222     # gmail chat
DEBUG:root:adding line acl Connect_ports port 6667     # irc chat
DEBUG:root:adding line http_access allow CONNECT Connect_ports
</pre>
<p>Again, we can verify that the edits have been made correctly:</p>
<pre class="literal-block">
# grep &quot;port 8080&quot; /etc/squid/squid.conf
# Our organisation requires Squid to operate on port 8080
http_port 8080
# egrep gmail\|irc /etc/squid/squid.conf
# We need to allow access to gmail and irc
acl Connect_ports port 5222     # gmail chat
acl Connect_ports port 6667     # irc chat
</pre>
<p>And finally, we can see what happens if we remove one of our fragments:</p>
<pre class="literal-block">
# rm /etc/squid/conf.d/connect_ports.conf
# /lib/svc/method/squid-self-assembly
DEBUG:root:  --- applying edits from change_http_port.conf   ---
DEBUG:root:removing expression # Squid normally listens to port 3128
DEBUG:root:removing expression http_port 3128
DEBUG:root:adding line # Our organisation requires Squid to operate on port 8080
DEBUG:root:adding line http_port 8080
#
# grep &quot;port 8080&quot; /etc/squid/squid.conf
# Our organisation requires Squid to operate on port 8080
http_port 8080
# egrep gmail\|irc /etc/squid/squid.conf
#
</pre>
<p>As expected, the configuration file no longer contains the directives configured by <tt class="docutils literal">connect_ports.conf</tt>, since that was removed from the system, but still<br />
contains the changes from <tt class="docutils literal">change_http_port.conf</tt></p>
<h3>Delivering the SMF service</h3>
<p>The bulk of the hard work has been done now &#8211; to recap:</p>
<ul class="simple">
<li>we have modified the Squid package to drop the shipped <tt class="docutils literal">squid.conf</tt> file</li>
<li>we have an SMF service that can perform self assembly, generating<br />
<tt class="docutils literal">squid.conf</tt> files from installed fragments on the system</li>
<li>we have added a dependency to the Squid SMF service on our self-assembly SMF service</li>
</ul>
<p>All that remains, is to ensure that the self-assembly service gets included in<br />
the Squid package.</p>
<p>For that, we&#8217;ll add a few more lines to the <a href="http://download.oracle.com/docs/cd/E23824_01/html/E21796/pkgmogrify-1.html#scrolltoc" class="external reference">pkgmogrify(1)</a> transform that we talked about earlier, so that it looks like:</p>
<pre class="literal-block">
&lt;transform set name=pkg.fmri -&gt; edit value pkg://[^/]+/ pkg://mypublisher/&gt;
&lt;transform file path=etc/squid/squid.conf$ -&gt; drop&gt;
dir path=etc/squid/conf.d owner=root group=bin mode=0755
file path=lib/svc/method/squid/squid-self-assembly group=bin mode=0555 owner=root
file path=lib/svc/manifest/network/http-squid-assembly.xml group=sys \
    mode=0444 owner=root restart_fmri=svc:/system/manifest-import:default
</pre>
<p>Now we can transform our original Squid package, and publish it to our repository:</p>
<pre class="literal-block">
$ pkgmogrify squid-assembly.mog \
    squid-proto/web%2Fproxy%2Fsquid/3.1.8%2C5.11-0.175.0.0.0.2.537%3A20111019T121425Z/manifest \
    &gt; squid\-assembly.mf
$ pkgsend -s myrepository publish -d squid-assembly-proto \
    -d squid-proto/web%2Fproxy%2Fsquid/3.1.8%2C5.11-0.175.0.0.0.2.537%3A20111019T121425Z \
    squid\-assembly.mf
WARNING: Omitting signature action 'signature 2ce2688faa049abe9d5dceeeabc4b17e7b72e792
.
.
pkg://mypublisher/web/proxy/squid&#064;3.1.8,5.11-0.175.0.0.0.2.537:20111108T201820Z
PUBLISHED
$
</pre>
<p>Installing that package, we discover a <tt class="docutils literal"><span class="pre">svc:/config/network/http/squid-assembly</span></tt> service, and verify that when we drop unpackaged files into /etc/squid/conf.d, and restart the self-assembly service, we see what we expect:</p>
<pre class="literal-block">
# more /var/svc/log/config-network-http-squid-assembly\:default.log
[ Nov  8 12:19:50 Enabled. ]
[ Nov  8 12:19:50 Rereading configuration. ]
[ Nov  8 12:19:50 Executing start method (&quot;/lib/svc/method/squid-self-assembly&quot;). ]
[ Nov  8 12:19:50 Method &quot;start&quot; exited with status 0. ]
[ Nov  8 12:23:42 Stopping because service restarting. ]
[ Nov  8 12:23:42 Executing stop method (null). ]
[ Nov  8 12:23:42 Executing start method (&quot;/lib/svc/method/squid-self-assembly&quot;). ]
DEBUG:root:  --- applying edits from change_port.conf   ---
DEBUG:root:removing expression # Squid normally listens to port 3128
DEBUG:root:removing expression http_port 3128
DEBUG:root:adding line # Our organisation requires Squid to operate on port 8080
DEBUG:root:adding line http_port 8080
[ Nov  8 12:23:42 Method &quot;start&quot; exited with status 0. ]
</pre>
<p>We have verified that Squid is performing self-assembly perfectly.</p>
<h2>Delivering new configuration fragments</h2>
<p>Now that we have a service that&#8217;s capable of performing self-assembly, we need to know how to deliver configuration fragments in new packages.</p>
<p>This is simply a case of delivering config files to <tt class="docutils literal">/etc/squid/conf.d</tt>, and applying the correct actuator tags to the manifest.</p>
<p>An example manifest that delivers this would be:</p>
<pre class="literal-block">
set name=pkg.fmri value=pkg:/config/web/proxy/squid-configuration&#064;2.0
set name=pkg.summary value=&quot;Our organisations squid configurations&quot;
file path=etc/squid/conf.d/change_http.conf owner=root group=bin mode=0644 \
    restart_fmri=svc:/config/network/http/squid-assembly:default \
    restart_fmri=svc:/network/http:squid
</pre>
<p>When we publish, then install this manifest, we see:</p>
<pre class="literal-block">
# pkg install squid-configuration&#064;2
           Packages to install:  1
       Create boot environment: No
Create backup boot environment: No
            Services to change:  2

DOWNLOAD                                  PKGS       FILES    XFER (MB)
Completed                                  1/1         1/1      0.0/0.0

PHASE                                        ACTIONS
Install Phase                                    3/3

PHASE                                          ITEMS
Package State Update Phase                       1/1
Image State Update Phase                         2/2
</pre>
<p>We can quickly verify that the Squid configuration has changed:</p>
<pre class="literal-block">
$ curl localhost:8080 | grep squid/
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  2904  100  2904    0     0  1633k      0 --:--:-- --:--:-- --:--:-- 2835k
&lt;p&gt;Generated Tue, 08 Nov 2011 23:00:27 GMT by tcx2250-13 (squid/3.1.8)&lt;/p&gt;
</pre>
<p>And we can backout the configuration by removing the package, and again check that the Squid configuration has changed:</p>
<pre class="literal-block">
# curl localhost:8080 | grep squid
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
curl: (7) couldn't connect to host
# curl localhost:3128 | grep squid/
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  3140  100  3140    0     0  1779k      0 --:--:-- --:--:-- --:--:-- 3066k
&lt;p&gt;Generated Tue, 08 Nov 2011 23:03:37 GMT by tcx2250-13 (squid/3.1.8)&lt;/p&gt;
</pre>
<p>We won&#8217;t go into details here, but clearly, multiple packages could deliver<br />
configuration fragments at the same time, and they would all contribute to the<br />
configuration of our service.</p>
<h2>Conclusion</h2>
<p>This has been a pretty fast example of the <em>self-assembly</em> idiom, but we hope this has been useful, and shows complex scripting operations can be performed in IPS.</p>
<p>There may more work to do to make the Squid application fully self-assembly aware &#8211; we&#8217;ve only covered the main configuration file and have&#8217;t looked at whether we also want to allow the other files in <tt class="docutils literal">/etc/squid</tt> to participate in self-assembly.  If we did want to do that, it would be a case of ensuring that:</p>
<ul class="simple">
<li>we ship a master template for each configuration file</li>
<li>modify our self-assembly SMF service to copy each template into place</li>
<li>ensure our script can perform edits on that file</li>
</ul>
<p>Of course, there&#8217;s other ways in which a self-assembly service could perform edits &#8211; we could use SMF to deliver properties to the service, which are then accessed by a self-assembly script, and placed into a configuration file, but perhaps that&#8217;s an example for another day.</p>
<br />Filed under: <a href='http://timsfoster.wordpress.com/category/ips/'>IPS</a>, <a href='http://timsfoster.wordpress.com/category/opensolaris/'>OpenSolaris</a>  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/timsfoster.wordpress.com/2838/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/timsfoster.wordpress.com/2838/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/timsfoster.wordpress.com/2838/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/timsfoster.wordpress.com/2838/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/timsfoster.wordpress.com/2838/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/timsfoster.wordpress.com/2838/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/timsfoster.wordpress.com/2838/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/timsfoster.wordpress.com/2838/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/timsfoster.wordpress.com/2838/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/timsfoster.wordpress.com/2838/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/timsfoster.wordpress.com/2838/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/timsfoster.wordpress.com/2838/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/timsfoster.wordpress.com/2838/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/timsfoster.wordpress.com/2838/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=timsfoster.wordpress.com&amp;blog=11695716&amp;post=2838&amp;subd=timsfoster&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://timsfoster.wordpress.com/2011/11/09/self-assembly-part-2-multiple-packages-delivering-configuration/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">timsfoster</media:title>
		</media:content>

		<media:content url="http://timsfoster.files.wordpress.com/2011/11/self-assembly.jpg" medium="image">
			<media:title type="html">Original image by bre pattis</media:title>
		</media:content>
	</item>
		<item>
		<title>Replacing the Application Packaging Developer&#8217;s guide</title>
		<link>http://timsfoster.wordpress.com/2011/10/17/replacing-the-application-packaging-developers-guide/</link>
		<comments>http://timsfoster.wordpress.com/2011/10/17/replacing-the-application-packaging-developers-guide/#comments</comments>
		<pubDate>Mon, 17 Oct 2011 22:03:49 +0000</pubDate>
		<dc:creator>timsfoster</dc:creator>
				<category><![CDATA[IPS]]></category>

		<guid isPermaLink="false">http://timsfoster.wordpress.com/?p=2811</guid>
		<description><![CDATA[Over the last while, we&#8217;ve been writing a replacement for the venerable Application Packaging Developer&#8217;s Guide. I started at Sun &#8230;<p><a href="http://timsfoster.wordpress.com/2011/10/17/replacing-the-application-packaging-developers-guide/">Continue reading &#187;</a></p><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=timsfoster.wordpress.com&amp;blog=11695716&amp;post=2811&amp;subd=timsfoster&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Over the last while, we&#8217;ve been writing a replacement for the venerable <a href="http://download.oracle.com/docs/cd/E19963-01/html/821-1672/index.html">Application Packaging Developer&#8217;s Guide</a>.</p>
<p>I started at Sun in the European Localisation group, and writing tools to create (and sometimes hack) SVR4 packages for Solaris was one of the things I had to do quite a bit &#8211; I found myself consulting the Application Packaging Developer&#8217;s Guide frequently.  So, having the opportunity to help write its replacement was pretty cool.</p>
<p>Bart did a great job in defining the structure of the new book, and writing a lot of the initial content. Brock wrote some comprehensive content on package signing, SMF and zones, and I&#8217;ve been working on the guide since then, using some of the original documentation that Stephen wrote.</p>
<p>Unlike the previous guide, we have fewer examples in this guide.  We feel that our <a href="http://src.opensolaris.org/source/xref/pkg/gate/src/man/">man pages</a> are better than the SVR4 packaging man pages were, and already contain useful examples.  This guide is meant to compliment our man pages, not replace them.</p>
<p>The guide is a <em>lot</em> shorter than the old book &#8211; currently 56 pages, as opposed to the 190 pages in the document it replaces.  Some of this is because of the fewer examples we have, but also we don&#8217;t have to write about patch creation, complex postinstall or class-action scripting or relocatable packages.  IPS is simpler than SVR4 in many ways, though there is a learning curve, which this book aims to help with.</p>
<p>There&#8217;s more work to do on the book (as you can tell by the &#8220;XXX&#8221; markers that appear throughout) but what we&#8217;ve got so far is here: <a href="http://src.opensolaris.org/source/xref/pkg/gate/doc/dev-guide/">source code</a>, and here, inelegantly rendered as <a href="http://defect.opensolaris.org/bz/attachment.cgi?id=4607">a pdf</a>.</p>
<p>If you use IPS, or have had experience in packaging software for Solaris previously, I&#8217;d be interested in hearing your thoughts on the content so far.</p>
<p><strong>Updated:</strong>  I&#8217;ve updated the PDF with the latest content as of today, and made sure there&#8217;s a datestamp on the file, so you can tell which version you&#8217;re reading.  Changelog below (though I&#8217;ve not put the source back to the gate, yet, so these changesets will likely be collapsed)</p>
<pre>
changeset:   2576:6b14edfc38b5
tag:         tip
user:        Tim Foster
date:        Fri Oct 21 09:49:15 2011 +1300
description:
	Add another example to chpt14, republishing under a new publisher name

changeset:   2575:0cf619c409b1
user:        Tim Foster
date:        Thu Oct 20 15:51:22 2011 +1300
description:
	complete the SVR4 conversion example in appendix2

changeset:   2574:3a671202fd35
user:        Tim Foster
date:        Thu Oct 20 12:09:48 2011 +1300
description:
	Rewrite the var/share discussion in chapter 10
	Add macros and use them throughout the book
	Add a datestamp and logo to the cover page
	use hg identify for versioning
	add more text explaining why we don't "cross the streams"
	Add note on Immutable Zones to chapter1
	Nobody uses fax machines anymore, do they?
	Add text on pkg.human-version to chapter 3
	Add content for the user action
	Add content for the group action
	Introduce the constraints/freezing section of chapter 6
	Reference constraints/freezing section in chapter 7
	Describe XXX sections more clearly
</pre>
<p><strong>Updated:</strong>  I&#8217;ve added more stuff, replaced the links, but not yet pushed these changes to our external gate. Changelog below.</p>
<pre>
timf@linn[626] hg log -r 2577:
changeset:   2577:83de3ed97341
user:        Tim Foster
date:        Fri Oct 21 16:23:37 2011 +1300
description:
	Break up chpt5
	Move XXX for versioning disussion to chpt3
	Fix table of contents

changeset:   2578:df045bbafc98
user:        Tim Foster
date:        Fri Oct 21 17:19:22 2011 +1300
description:
	Write content for mediated links, with an example

changeset:   2579:1c3d87d950e6
tag:         tip
user:        Tim Foster
date:        Fri Oct 21 17:26:50 2011 +1300
description:
	Move XXX for versioning disussion to chpt3 (fix build)
</pre>
<p><strong>Updated:</strong>  Almost at the final version &#8211; there&#8217;s a few small changes to make, but I&#8217;ve updated the links to the pdf of that version now, which hasn&#8217;t yet been pushed to the gate.  Too many commit messages to indicate what&#8217;s changed unfortunately.</p>
<p><strong>Updated:</strong>  More minor changes and some style/branding tweaks. I&#8217;ve updated the pdf links above (2011-11-07:16:40:12-NZDT 8e2ee40e0bfb tip)</p>
<p><strong>Updated:</strong>  wikis.sun.com seems to be having issues. So in the meantime, there&#8217;s a local copy <a href='http://timsfoster.files.wordpress.com/2011/10/book.pdf'>here</a></p>
<br />Filed under: <a href='http://timsfoster.wordpress.com/category/ips/'>IPS</a>  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/timsfoster.wordpress.com/2811/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/timsfoster.wordpress.com/2811/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/timsfoster.wordpress.com/2811/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/timsfoster.wordpress.com/2811/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/timsfoster.wordpress.com/2811/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/timsfoster.wordpress.com/2811/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/timsfoster.wordpress.com/2811/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/timsfoster.wordpress.com/2811/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/timsfoster.wordpress.com/2811/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/timsfoster.wordpress.com/2811/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/timsfoster.wordpress.com/2811/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/timsfoster.wordpress.com/2811/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/timsfoster.wordpress.com/2811/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/timsfoster.wordpress.com/2811/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=timsfoster.wordpress.com&amp;blog=11695716&amp;post=2811&amp;subd=timsfoster&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://timsfoster.wordpress.com/2011/10/17/replacing-the-application-packaging-developers-guide/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">timsfoster</media:title>
		</media:content>
	</item>
		<item>
		<title>FeedPlus &#8211; creating an Atom feed from a G+ public stream</title>
		<link>http://timsfoster.wordpress.com/2011/09/08/feedplus-creating-an-atom-feed-from-a-g-public-stream/</link>
		<comments>http://timsfoster.wordpress.com/2011/09/08/feedplus-creating-an-atom-feed-from-a-g-public-stream/#comments</comments>
		<pubDate>Thu, 08 Sep 2011 00:00:13 +0000</pubDate>
		<dc:creator>timsfoster</dc:creator>
				<category><![CDATA[Off-topic]]></category>

		<guid isPermaLink="false">http://timsfoster.wordpress.com/?p=2803</guid>
		<description><![CDATA[I had been using Russell Beattie&#8217;s PlusFeed application to create an RSS feed that I could pass to TwitterFeed, in &#8230;<p><a href="http://timsfoster.wordpress.com/2011/09/08/feedplus-creating-an-atom-feed-from-a-g-public-stream/">Continue reading &#187;</a></p><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=timsfoster.wordpress.com&amp;blog=11695716&amp;post=2803&amp;subd=timsfoster&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.flickr.com/photos/hapinachu/667766525/"><img src="http://timsfoster.files.wordpress.com/2011/09/robot-hamster.jpg?w=529" alt="Original image by hapinachu on Flickr" title="Original image by hapinachu on Flickr"   class="alignleft size-full wp-image-2804" /></a></p>
<p>I had been using Russell Beattie&#8217;s <a href="http://plusfeed.appspot.com/">PlusFeed</a> application to create an RSS feed that I could pass to <a href="http://twitterfeed.com/">TwitterFeed</a>, in order to syndicate my G+ posts over to <a href="http://twitter.com/timfoster">Twitter</a>.</p>
<p>It wasn&#8217;t perfect, but was good enough to do the job.</p>
<p>Unfortunately, Google recently <a href="http://www.readwriteweb.com/hack/2011/09/google-ups-pricing-as-app-engi.php">changed the pricing for AppEngine</a>, which led <a href="https://plus.google.com/104961845171318028721/posts/DamjzZBVxd7">Russell to turn off the service</a>.</p>
<p>I wasn&#8217;t able to find any good alternatives out there, so quickly rolled my own.  It takes the id of a G+ user, and spits out an &#8220;atom.xml&#8221; file into the directory you choose, which you can then send to anything that can consume <a href="http://en.wikipedia.org/wiki/Atom_%28standard%29">Atom</a>.</p>
<p>The code is up on GitHub if anyone&#8217;s interested.  My code isn&#8217;t perfect either, but will do the job until something better comes along:  <a href="https://github.com/timfoster/FeedPlus">FeedPlus</a>.</p>
<p>Enjoy.</p>
<p><em>Update, Dec 13th 2011:</em>  I&#8217;ve updated the app to use the offical G+ API now, rather than relying on the json data that Russell&#8217;s app relied on.  Hopefully this will make it a little more stable.  Next stop, add an option to have it post to Twitter directly, rather than just writing atom.</p>
<br />Filed under: <a href='http://timsfoster.wordpress.com/category/off-topic/'>Off-topic</a>  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/timsfoster.wordpress.com/2803/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/timsfoster.wordpress.com/2803/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/timsfoster.wordpress.com/2803/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/timsfoster.wordpress.com/2803/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/timsfoster.wordpress.com/2803/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/timsfoster.wordpress.com/2803/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/timsfoster.wordpress.com/2803/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/timsfoster.wordpress.com/2803/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/timsfoster.wordpress.com/2803/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/timsfoster.wordpress.com/2803/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/timsfoster.wordpress.com/2803/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/timsfoster.wordpress.com/2803/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/timsfoster.wordpress.com/2803/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/timsfoster.wordpress.com/2803/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=timsfoster.wordpress.com&amp;blog=11695716&amp;post=2803&amp;subd=timsfoster&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://timsfoster.wordpress.com/2011/09/08/feedplus-creating-an-atom-feed-from-a-g-public-stream/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">timsfoster</media:title>
		</media:content>

		<media:content url="http://timsfoster.files.wordpress.com/2011/09/robot-hamster.jpg" medium="image">
			<media:title type="html">Original image by hapinachu on Flickr</media:title>
		</media:content>
	</item>
		<item>
		<title>Please unsubscribe me</title>
		<link>http://timsfoster.wordpress.com/2011/07/16/please-unsubscribe-me/</link>
		<comments>http://timsfoster.wordpress.com/2011/07/16/please-unsubscribe-me/#comments</comments>
		<pubDate>Sat, 16 Jul 2011 09:10:36 +0000</pubDate>
		<dc:creator>timsfoster</dc:creator>
				<category><![CDATA[Off-topic]]></category>

		<guid isPermaLink="false">http://timsfoster.wordpress.com/?p=2785</guid>
		<description><![CDATA[As promised here I spent the last week avoiding Twitter and Facebook, giving Google+ a go. Summary? I think it&#8217;s &#8230;<p><a href="http://timsfoster.wordpress.com/2011/07/16/please-unsubscribe-me/">Continue reading &#187;</a></p><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=timsfoster.wordpress.com&amp;blog=11695716&amp;post=2785&amp;subd=timsfoster&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a href="http://timsfoster.files.wordpress.com/2011/07/no-facebook.jpg"><img src="http://timsfoster.files.wordpress.com/2011/07/no-facebook.jpg?w=300&#038;h=195" alt="" title="no-facebook" width="300" height="195" class="alignleft size-medium wp-image-2786" /></a></p>
<p>As promised <a href="https://twitter.com/timfoster/status/89767008933130240">here</a> I spent the last week avoiding Twitter and Facebook, giving <a href="http://plus.google.com">Google+</a> a go.</p>
<p>Summary?  I think it&#8217;s fabulous.</p>
<p>I like the idea of Circles, I like the user interface and have yet to start to accumulate the amount of crap I was tending to get on Facebook (pointless games, updates from people who clicked on spammy &#8220;see who&#8217;s been watching your profile&#8221; apps, that sort of thing)</p>
<p>It&#8217;s missing some stuff so far that for me makes Twitter the better option if you&#8217;re looking to follow interesting people, or look for posts about particular topics but don&#8217;t necessarily know who those people are, or who&#8217;s writing about a particular topic of interest: <a href="http://en.wikipedia.org/wiki/Tag_%28metadata%29#Hashtags">#hashtags</a>.  Being able to tag posts would be useful too, because while I like being able to view just a set of posts from a given Circle of friends, not everything those friends write about is necessarily relevant to me.</p>
<p>I&#8217;ve a few other nits with G+ that I&#8217;d like to see improved as well, including better client support on Android, a public API (which will help towards the first item, no doubt) but I&#8217;m happy to be patient.</p>
<p>It&#8217;s early days with Google+, though what I&#8217;ve seen so far makes me think it won&#8217;t be long before they&#8217;ll have the extra features that seem like an obvious addition to any social networking application.</p>
<p>So, what&#8217;s my plan with Twitter and Facebook?</p>
<p>Well, the week-long experiment on Google plus wasn&#8217;t long enough for me to choose whether or not to keep using one of those other services.  My plan for now, is to hang on to my Twitter account, <a href="http://twitter.com/#!/timfoster">@timfoster</a> and essentially treat it as read-only, except for direct messages and any replies I feel like posting to other folks on Twitter.</p>
<p>I&#8217;m going to try to use <a href="https://plus.google.com/107847990164269071741/posts">+Tim Foster</a> for everything else.</p>
<p>As for Facebook, I&#8217;m going to give it up completely &#8211; I really only started using it to connect with the people that I know who don&#8217;t use Twitter, and seeing as there&#8217;s a better application out there now, it seems like Facebook has outlived its usefulness.  I&#8217;d honestly rather one corporation had a detailed map of me than two (not that I can be particularly precious about this: I&#8217;ve got an Android phone, use Gmail &#8211; so in a sense, I&#8217;ve already signed my soul over to Google)</p>
<p>So, I&#8217;m closing my Facebook account as of next week, and stopping the Twitter re-publication now (I rarely ever actually post on Facebook, usually it&#8217;s just my Twitter feed getting redirected there)</p>
<p>If you would still like to keep up with me, get onto Google Plus &#8211; I&#8217;ve a few invites left which I&#8217;ll give to you if I know you, but I&#8217;m guessing they&#8217;ve got to be close to opening the service for anyone who wants in, invite or not. Otherwise, <a href="https://twitter.com/signup">join Twitter</a>.</p>
<br />Filed under: <a href='http://timsfoster.wordpress.com/category/off-topic/'>Off-topic</a>  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/timsfoster.wordpress.com/2785/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/timsfoster.wordpress.com/2785/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/timsfoster.wordpress.com/2785/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/timsfoster.wordpress.com/2785/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/timsfoster.wordpress.com/2785/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/timsfoster.wordpress.com/2785/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/timsfoster.wordpress.com/2785/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/timsfoster.wordpress.com/2785/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/timsfoster.wordpress.com/2785/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/timsfoster.wordpress.com/2785/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/timsfoster.wordpress.com/2785/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/timsfoster.wordpress.com/2785/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/timsfoster.wordpress.com/2785/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/timsfoster.wordpress.com/2785/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=timsfoster.wordpress.com&amp;blog=11695716&amp;post=2785&amp;subd=timsfoster&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://timsfoster.wordpress.com/2011/07/16/please-unsubscribe-me/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">timsfoster</media:title>
		</media:content>

		<media:content url="http://timsfoster.files.wordpress.com/2011/07/no-facebook.jpg?w=300" medium="image">
			<media:title type="html">no-facebook</media:title>
		</media:content>
	</item>
		<item>
		<title>2011 Armstrong Motor Group Wellington Marathon</title>
		<link>http://timsfoster.wordpress.com/2011/07/10/2011-armstrong-motor-group-wellington-marathon/</link>
		<comments>http://timsfoster.wordpress.com/2011/07/10/2011-armstrong-motor-group-wellington-marathon/#comments</comments>
		<pubDate>Sun, 10 Jul 2011 11:48:00 +0000</pubDate>
		<dc:creator>timsfoster</dc:creator>
				<category><![CDATA[Off-topic]]></category>

		<guid isPermaLink="false">http://timsfoster.wordpress.com/?p=2760</guid>
		<description><![CDATA[I ran the 2011 Wellington Marathon on the 19th of June &#8211; that was my 3rd marathon, and without doubt, &#8230;<p><a href="http://timsfoster.wordpress.com/2011/07/10/2011-armstrong-motor-group-wellington-marathon/">Continue reading &#187;</a></p><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=timsfoster.wordpress.com&amp;blog=11695716&amp;post=2760&amp;subd=timsfoster&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.flickr.com/photos/timf/5843726900/in/photostream/"><img src="http://timsfoster.files.wordpress.com/2011/07/running-crossroads.jpg?w=529" alt="" title="running-crossroads"   class="alignleft size-full wp-image-2761" /></a></p>
<p>I ran the 2011 Wellington Marathon on the 19th of June &#8211; that was my 3rd marathon, and without doubt, the toughest one I&#8217;ve done to date.  As with the <a href="http://timsfoster.wordpress.com/2009/10/27/26-2-miles/">other</a> races that I&#8217;ve<br />
<a href="http://timsfoster.wordpress.com/2010/06/28/2010-harbour-capital-marathon/">run</a>, here&#8217;s a writeup of my experiences.</p>
<p>There&#8217;s also an <a href="http://www.harbourcapital.org.nz/default.asp?PageID=22857">official race report</a>, if you&#8217;re interested.</p>
<p>Going into the build-up for the race this year, my goal was to try to beat last year&#8217;s time, but really I wanted to see if I had a sub-3hr marathon in me, I knew it&#8217;d be a stretch, but I was going to give it a try.</p>
<p>With that in mind, I stepped up to the next level of training, getting  serious about it.  As with earlier years, I thought I&#8217;d stick with <a href="http://www.halhigdon.com/">Hal Higdon&#8217;s</a> training program, but this time going for the <a href="http://web.archive.org/web/20051203085006/http://www.halhigdon.com/marathon/advanced1/advanced1-15.htm">Advanced &#8211; I</a> plan.  Over and above the  &#8220;Intermediate &#8211; 2&#8243; plan that I followed last year, this one added speed-work, hill repeats, tempo runs, and an extra day of running.</p>
<p>So, for 18 weeks during the lead up to the marathon, I was running 6 days a week, which was extremely grueling &#8211; not just for me, but also for my long-suffering family.  They were incredibly supportive during the training, thanks Bob, Ella &amp; Calum!</p>
<p>As before, I took a unit-test-inspired approach, printing out the training plan and sticking it to our fridge, with an aim of turning it green.   Days when I just couldn&#8217;t be bothered running would get a red mark, days when I was unable to run, either because I was sick or because of work-pressure would be highlighted in yellow.  Otherwise, I got on with the training, and slowly coloured each square green when I could. Ella was happy to help colouring too, she did a great job!</p>
<p>Overall, I was happy with the training progress &#8211; <a href="http://www.flickr.com/photos/timf/5844584288/in/photostream">here&#8217;s the completed chart</a>.  I was sick for about 10 days in total, and if you match up pkg(5) integration dates for the projects I was working on, you can probably spot where work got in the way of running :-)</p>
<p>During training, I was getting my <a href="http://www.runnersworld.com/article/0,7120,s6-238-244-255-624-0,00.html">Yasso repeats</a> up to the point where I was definitely in the right ballpark for a sub-3hr finish.</p>
<p>As I got closer to race day though, I became uncertain whether I&#8217;d be able to run the pace I was aiming for over the full distance.  The longest I&#8217;d run at full race-pace was 16k.  Still, I reasoned that those 16k were very hilly during training, so perhaps on the flat, I&#8217;d be alright.  There was only one way to find out.</p>
<p>Race day, like last year, was cold and wet &#8211; a marathon at the end of June is in the depths of winter here.  We lined up on the concourse of the <a href="http://en.wikipedia.org/wiki/Westpac_Stadium">Westpac stadium</a> at 7:30am ready for the off.</p>
<p>My first few kilometers were slow as I moved through the pack, and I only looked at my watch as we approached <a href="http://en.wikipedia.org/wiki/Museum_of_New_Zealand_Te_Papa_Tongarewa">Te Papa</a> seeing that I was a little behind.  I picked up the pace a bit, before settling into my race-pace.</p>
<p>The wind around the Wellington bays was strong and gusty, and like last year, I drafted when I could and took my turn.  Getting out towards Shelly Bay, my 10k time was looking good &#8211; there was another runner doing about the same pace as me so we hung on and kept each other going.  At this point, I was running a pace of between 4:01 and 4:12/km (depending on wind and water stations, I guess) which should have had me finishing around 2:52:00 &#8211; bang on the pace I was hoping for.</p>
<p>Thinking about pacing before the race, I had eventually decided that I&#8217;d go out with a really aggressive pace, aiming for well under a 3hr finish, rather then being more conservative and potentially making it over the line in 3:01 or thereabouts.  While just scraping over the line sub-3hr would have been great,<br />
I&#8217;d hate to have put in all that effort, and only miss my goal by a few seconds.</p>
<p>The question I faced was, was I willing to potentially blow my chances of beating last year&#8217;s time at all or risking the dreaded &#8220;DNF&#8221; (Did Not Finish), just to avoid the anguish of barely missing a sub-3hr finish?  Yes, I was.</p>
<p>At the half-way turn-around, things were still going well.  I was keeping to my pace, and feeling quite good about progress so far, but they say the first half of a marathon is just about transport &#8211; the race really begins at the halfway mark.</p>
<p>My pace slowed slightly leading up to the 30km mark and then I hit the wall &#8211; or rather, my legs did.</p>
<p>With only 10k to go, I started feeling slight twinges in my calves, which made me extremely worried.  I tried easing up on my pace a little, to give my legs a chance.  Apart from my legs though, I still felt good at this point &#8211; I wasn&#8217;t tired or out of breath, and definitely had fight left in me.</p>
<p>Unfortunately, things only got worse from here.  As I made it back along the route we&#8217;d taken earlier, now joined by the half-marathon runners, the cramps in my legs became worse.  At water stations, I&#8217;d drop to walking pace, trying to struggle back up to at least a 5:00/km pace when I started running again, but the cramps persisted and continued to get worse, as did the pain.</p>
<p>Partly it was pain in my legs, which was getting really intense at this point, but also it was from seeing my goal-time slipping away from me: there was nothing I could do about it.</p>
<p>The last 5k were gruesome &#8211; I just wanted to finish the race at this point, and didn&#8217;t care what sort of time I&#8217;d finish in.  Finally limping over line, I was happy it was over, but depressed at the same time.</p>
<p>As it turned out, I did beat last year&#8217;s time of 3:12:39, with a 3:11:37 finish. So, was all the training leading up to the race worth a finish time of only 62 seconds faster than last year?</p>
<p>Well, I can&#8217;t pretend that I wasn&#8217;t hugely disappointed with my result, but at the same time, I keep telling myself that a 3:11 marathon finish isn&#8217;t shabby by any measure.  I know I&#8217;m faster than that, but I&#8217;m still weighing up whether I want to try to prove it or not next year.</p>
<p>In the meantime, I&#8217;m taking a break from running &#8211; give it a few months and perhaps I&#8217;ll be back on the roads again, but for now, I&#8217;m enjoying the extra free time I suddenly seem to have!</p>
<p>Race results, and splits from my watch during the race are below:</p>
<table border="1">
<tr><a href="http://tiktok.biz/wellingtonmarathon/2011/0224/">Tim Foster &#8211; bib number 224</a></tr>
<tr>
<td>Division</td>
<td>M18-39</td>
</tr>
<tr>
<td>Net time</td>
<td>3:11:37</td>
</tr>
<tr>
<td>Net place</td>
<td>25th of 370 total finishers</td>
</tr>
<td>	           </td>
<td>24th of 259 male finishers</td>
</tr>
<td>	           </td>
<td>16th of 136 M18-39 finishers</td>
</tr>
<tr>
<td>Average pace</td>
<td>04:32/km</td>
</tr>
</table>
<table border="1">
<th>Km    </th>
<th>split   </th>
<th>cumulative time</th>
<tr>
<td>1,2   </td>
<td>8:48    </td>
<td></td>
</tr>
<tr>
<td>3-5   </td>
<td>15:39   </td>
<td>24:27</td>
</tr>
<tr>
<td>6,7   </td>
<td>7:51    </td>
<td>32:19</td>
</tr>
<tr>
<td>8,9   </td>
<td>8:10    </td>
<td>40:29</td>
</tr>
<tr>
<td>10,11 </td>
<td>8:25    </td>
<td>48:55</td>
</tr>
<tr>
<td>12,13 </td>
<td>8:28    </td>
<td>57:24</td>
</tr>
<tr>
<td>14,15 </td>
<td>8:04    </td>
<td>1:05:28</td>
</tr>
<tr>
<td>16,17 </td>
<td>8:03    </td>
<td>1:13:31</td>
</tr>
<tr>
<td>18,19 </td>
<td>8:16    </td>
<td>1:21:48</td>
</tr>
<tr>
<td>21.2  </td>
<td>4:34    </td>
<td>1:26.22  ( half way marker )</td>
</tr>
<tr>
<td>22    </td>
<td>3:40    </td>
<td>1:30:02</td>
</tr>
<tr>
<td>23,24 </td>
<td>8:20    </td>
<td>1:38:22</td>
</tr>
<tr>
<td>34,25 </td>
<td>8:31    </td>
<td>1:46:54</td>
</tr>
<tr>
<td>26,27 </td>
<td>8:27    </td>
<td>1:55:22</td>
</tr>
<tr>
<td>28,29 </td>
<td>8:43    </td>
<td>2:04:05</td>
</tr>
<tr>
<td>30,31 </td>
<td>9:45    </td>
<td>2:13:51</td>
</tr>
<tr>
<td>32,33 </td>
<td>9:13    </td>
<td>2:23:05</td>
</tr>
<tr>
<td>34,35 </td>
<td>10:58   </td>
<td>2:34:03</td>
</tr>
<tr>
<td>36,37 </td>
<td>11:21   </td>
<td>2:45:25</td>
</tr>
<tr>
<td>38,39,40,41,42.2   </td>
<td>49:17 &#8211; that&#8217;s wrong, I forgot to stop my watch</td>
</tr>
</table>
<p><a href="http://timsfoster.files.wordpress.com/2011/07/2011-medalrunners.jpg"><img src="http://timsfoster.files.wordpress.com/2011/07/2011-medalrunners.jpg?w=529" alt="" title="2011-medal+runners"   class="aligncenter size-full wp-image-2762" /></a></p>
<br />Filed under: <a href='http://timsfoster.wordpress.com/category/off-topic/'>Off-topic</a>  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/timsfoster.wordpress.com/2760/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/timsfoster.wordpress.com/2760/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/timsfoster.wordpress.com/2760/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/timsfoster.wordpress.com/2760/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/timsfoster.wordpress.com/2760/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/timsfoster.wordpress.com/2760/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/timsfoster.wordpress.com/2760/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/timsfoster.wordpress.com/2760/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/timsfoster.wordpress.com/2760/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/timsfoster.wordpress.com/2760/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/timsfoster.wordpress.com/2760/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/timsfoster.wordpress.com/2760/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/timsfoster.wordpress.com/2760/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/timsfoster.wordpress.com/2760/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=timsfoster.wordpress.com&amp;blog=11695716&amp;post=2760&amp;subd=timsfoster&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://timsfoster.wordpress.com/2011/07/10/2011-armstrong-motor-group-wellington-marathon/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">timsfoster</media:title>
		</media:content>

		<media:content url="http://timsfoster.files.wordpress.com/2011/07/running-crossroads.jpg" medium="image">
			<media:title type="html">running-crossroads</media:title>
		</media:content>

		<media:content url="http://timsfoster.files.wordpress.com/2011/07/2011-medalrunners.jpg" medium="image">
			<media:title type="html">2011-medal+runners</media:title>
		</media:content>
	</item>
		<item>
		<title>What mints are made of</title>
		<link>http://timsfoster.wordpress.com/2011/06/08/what-mints-are-made-of/</link>
		<comments>http://timsfoster.wordpress.com/2011/06/08/what-mints-are-made-of/#comments</comments>
		<pubDate>Wed, 08 Jun 2011 09:48:50 +0000</pubDate>
		<dc:creator>timsfoster</dc:creator>
				<category><![CDATA[Off-topic]]></category>

		<guid isPermaLink="false">http://timsfoster.wordpress.com/?p=2749</guid>
		<description><![CDATA[Had a good conversation with Ella (age 4), as she was cleaning her teeth this evening: &#8220;Dad, do you know &#8230;<p><a href="http://timsfoster.wordpress.com/2011/06/08/what-mints-are-made-of/">Continue reading &#187;</a></p><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=timsfoster.wordpress.com&amp;blog=11695716&amp;post=2749&amp;subd=timsfoster&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.flickr.com/photos/summertomato/3570433046/"><img src="http://timsfoster.files.wordpress.com/2011/06/mint.jpg?w=529" alt="Original image by SummerTomato http://www.flickr.com/photos/summertomato/3570433046/" title="Original image by SummerTomato http://www.flickr.com/photos/summertomato/3570433046/"   class="size-full wp-image-2750" /></a></p>
<p>Had a good conversation with Ella (age 4), as she was cleaning her teeth this evening:</p>
<p>&#8220;Dad, do you know what mints are made of?&#8221;<br />
&#8220;No, I don&#8217;t Ella.  What are they made of?&#8221;<br />
&#8220;Toothpaste and water.&#8221;<br />
&#8220;Really?  Did Mum tell you that?&#8221;<br />
&#8220;Nope.  I just figured it out.&#8221;</p>
<br />Filed under: <a href='http://timsfoster.wordpress.com/category/off-topic/'>Off-topic</a>  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/timsfoster.wordpress.com/2749/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/timsfoster.wordpress.com/2749/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/timsfoster.wordpress.com/2749/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/timsfoster.wordpress.com/2749/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/timsfoster.wordpress.com/2749/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/timsfoster.wordpress.com/2749/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/timsfoster.wordpress.com/2749/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/timsfoster.wordpress.com/2749/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/timsfoster.wordpress.com/2749/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/timsfoster.wordpress.com/2749/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/timsfoster.wordpress.com/2749/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/timsfoster.wordpress.com/2749/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/timsfoster.wordpress.com/2749/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/timsfoster.wordpress.com/2749/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=timsfoster.wordpress.com&amp;blog=11695716&amp;post=2749&amp;subd=timsfoster&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://timsfoster.wordpress.com/2011/06/08/what-mints-are-made-of/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">timsfoster</media:title>
		</media:content>

		<media:content url="http://timsfoster.files.wordpress.com/2011/06/mint.jpg" medium="image">
			<media:title type="html">Original image by SummerTomato http://www.flickr.com/photos/summertomato/3570433046/</media:title>
		</media:content>
	</item>
		<item>
		<title>3d-printing and running shoes</title>
		<link>http://timsfoster.wordpress.com/2011/05/18/3d-printing-and-running-shoes/</link>
		<comments>http://timsfoster.wordpress.com/2011/05/18/3d-printing-and-running-shoes/#comments</comments>
		<pubDate>Wed, 18 May 2011 09:12:08 +0000</pubDate>
		<dc:creator>timsfoster</dc:creator>
				<category><![CDATA[Off-topic]]></category>

		<guid isPermaLink="false">http://timsfoster.wordpress.com/?p=2735</guid>
		<description><![CDATA[Here is a selection of the last three pairs of running shoes I&#8217;ve owned: - they&#8217;re all Asics Nimbus x, &#8230;<p><a href="http://timsfoster.wordpress.com/2011/05/18/3d-printing-and-running-shoes/">Continue reading &#187;</a></p><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=timsfoster.wordpress.com&amp;blog=11695716&amp;post=2735&amp;subd=timsfoster&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Here is a selection of the last three pairs of running shoes I&#8217;ve owned:</p>

<a href='http://timsfoster.wordpress.com/2011/05/18/3d-printing-and-running-shoes/imag0018/' title='IMAG0018'><img data-attachment-id='2736' data-orig-size='2592,1952' data-liked='0'width="150" height="112" src="http://timsfoster.files.wordpress.com/2011/05/imag0018.jpg?w=150&#038;h=112" class="attachment-thumbnail" alt="IMAG0018" title="IMAG0018" /></a>
<a href='http://timsfoster.wordpress.com/2011/05/18/3d-printing-and-running-shoes/imag0013/' title='IMAG0013'><img data-attachment-id='2737' data-orig-size='2592,1952' data-liked='0'width="150" height="112" src="http://timsfoster.files.wordpress.com/2011/05/imag0013.jpg?w=150&#038;h=112" class="attachment-thumbnail" alt="IMAG0013" title="IMAG0013" /></a>
<a href='http://timsfoster.wordpress.com/2011/05/18/3d-printing-and-running-shoes/imag0014/' title='IMAG0014'><img data-attachment-id='2738' data-orig-size='2592,1952' data-liked='0'width="150" height="112" src="http://timsfoster.files.wordpress.com/2011/05/imag0014.jpg?w=150&#038;h=112" class="attachment-thumbnail" alt="IMAG0014" title="IMAG0014" /></a>
<a href='http://timsfoster.wordpress.com/2011/05/18/3d-printing-and-running-shoes/imag0015/' title='IMAG0015'><img data-attachment-id='2739' data-orig-size='2592,1952' data-liked='0'width="150" height="112" src="http://timsfoster.files.wordpress.com/2011/05/imag0015.jpg?w=150&#038;h=112" class="attachment-thumbnail" alt="IMAG0015" title="IMAG0015" /></a>
<a href='http://timsfoster.wordpress.com/2011/05/18/3d-printing-and-running-shoes/imag0016/' title='IMAG0016'><img data-attachment-id='2740' data-orig-size='2592,1952' data-liked='0'width="150" height="112" src="http://timsfoster.files.wordpress.com/2011/05/imag0016.jpg?w=150&#038;h=112" class="attachment-thumbnail" alt="IMAG0016" title="IMAG0016" /></a>
<a href='http://timsfoster.wordpress.com/2011/05/18/3d-printing-and-running-shoes/imag0017/' title='IMAG0017'><img data-attachment-id='2741' data-orig-size='2592,1952' data-liked='0'width="150" height="112" src="http://timsfoster.files.wordpress.com/2011/05/imag0017.jpg?w=150&#038;h=112" class="attachment-thumbnail" alt="IMAG0017" title="IMAG0017" /></a>

<p>- they&#8217;re all Asics Nimbus <em>x</em>, and all from successive years.  I&#8217;ve trained for and run a marathon in each of the last two pairs, and am currently putting my most recent pair through their paces with another race in the next few weeks.  I&#8217;m running 6 days a week at the moment on the road, with a maximum of about 50 miles/week.  I really like these shoes &#8211; honestly, no complaints and no injuries to speak of.</p>
<p>The thing is, it&#8217;s getting to be fairly obvious to me where my runners wear out the fastest &#8211; just on the outside edge of the heel, and at a fairly consistent area on the midsole. (yes, I know I should have changed the red &amp; white pair well before they got into the state they&#8217;re in)</p>
<p>So, here&#8217;s my idea: could someone please come up with a mechanism that allows me to present these old shoes to my running shop the next time I&#8217;m getting a new pair so that they can do a quick 3d-scan of the old shoes, then send the scan off to the factory along with my weight and height, and a brief description of the sort of running I do.</p>
<p>There, they would take the scans, run them through a CAD system, do some magic, then 3d-print a new pair for me with <em>slightly</em> harder-wearing rubber on the bits that wear out most quickly for me.  They&#8217;d send them back to the shop a few weeks later and I&#8217;d pick them up.  I would even pay slightly more for this, if it means my runners don&#8217;t wear out as quickly, and they&#8217;ll have a loyal customer for life.</p>
<p>Yes, I admit to the possibility that perhaps harder-wearing parts of the sole might mean less cushioning in those parts, and that maybe the runners are designed to fall apart at the moment, in the interests of protecting my joints?  Still, it&#8217;d be an interesting experiment I think.</p>
<br />Filed under: <a href='http://timsfoster.wordpress.com/category/off-topic/'>Off-topic</a>  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/timsfoster.wordpress.com/2735/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/timsfoster.wordpress.com/2735/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/timsfoster.wordpress.com/2735/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/timsfoster.wordpress.com/2735/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/timsfoster.wordpress.com/2735/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/timsfoster.wordpress.com/2735/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/timsfoster.wordpress.com/2735/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/timsfoster.wordpress.com/2735/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/timsfoster.wordpress.com/2735/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/timsfoster.wordpress.com/2735/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/timsfoster.wordpress.com/2735/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/timsfoster.wordpress.com/2735/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/timsfoster.wordpress.com/2735/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/timsfoster.wordpress.com/2735/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=timsfoster.wordpress.com&amp;blog=11695716&amp;post=2735&amp;subd=timsfoster&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://timsfoster.wordpress.com/2011/05/18/3d-printing-and-running-shoes/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">timsfoster</media:title>
		</media:content>

		<media:content url="http://timsfoster.files.wordpress.com/2011/05/imag0018.jpg?w=150" medium="image">
			<media:title type="html">IMAG0018</media:title>
		</media:content>

		<media:content url="http://timsfoster.files.wordpress.com/2011/05/imag0013.jpg?w=150" medium="image">
			<media:title type="html">IMAG0013</media:title>
		</media:content>

		<media:content url="http://timsfoster.files.wordpress.com/2011/05/imag0014.jpg?w=150" medium="image">
			<media:title type="html">IMAG0014</media:title>
		</media:content>

		<media:content url="http://timsfoster.files.wordpress.com/2011/05/imag0015.jpg?w=150" medium="image">
			<media:title type="html">IMAG0015</media:title>
		</media:content>

		<media:content url="http://timsfoster.files.wordpress.com/2011/05/imag0016.jpg?w=150" medium="image">
			<media:title type="html">IMAG0016</media:title>
		</media:content>

		<media:content url="http://timsfoster.files.wordpress.com/2011/05/imag0017.jpg?w=150" medium="image">
			<media:title type="html">IMAG0017</media:title>
		</media:content>
	</item>
	</channel>
</rss>
