Wednesday, September 23, 2015

Setting up NFS on openSuse

Something I've wanted to do for a long time is set up a network file share (NFS). And with the discovery that the /home partition on my old development box is rapidly filling up, it seemed like a good time to do it. That way, I can transfer some of the less server-centric stuff to my laptop, on which I'm doing more general-purpose computing, development, etc.

I'm not actually sitting at the box where I configured the server and made notes of this process. But it went something like the following.

The first order of business is to make the server filesystem available on my laptop, which also runs openSuse. It turns out that there is a package, nfs-server, implemented as a kernel module, which provides the service. It's not installed by default, so I head over to the package management tool, YaST, and install it.

No dependencies. Bada bing, bada boom.

I decide to see if I can get it running. In the System Services panel, it's now there as nfs-server. It's disabled (won't start automatically) and not running. I click "start/stop". Clicking on the "Details" button opens a dialog with a complaint about not being able to bind to a port, as it's already taken (by another service). Hmm. What service? Why wouldn't it choose an available port? In an intuitive stroke of genius, I start the rcp-bind service, which I read somewhere is needed by NFS. The service now starts. Beginner's luck takes the day. You gotta love this stuff.

On the client machine (laptop), I open the NFS client panel in YaST system services. There's a couple of text fields, server domain and filesystem path. Hoping for the best, I just click "Choose". A pop-up informs me that it's scanning the local network for a NFS service. It fails to find one.

A Google search turns up some good documentation at
There's a command "showmount" that may help. I enter the following in the root terminal window:

$> showmount -e

And what do you know? It reports the following:

Export list for /multimedia/music

As this is the directory I had specified in the server config file (etc/exports), I know it speaks sooth. Amazing? How was it able to find the service while the YaST NFS Client tool was unable to even when pointing it at the server box? I mess around with it some more but nothing can make it find the service.

But now life is good. The laptop found the service.

Next, mounting the filesystem on the client provided another challenge. I'm not sure exactly what solved it. It was one of the following: actually mounting the server filesystem to be exported (for some odd reason), or adding "fsid=0" to the entry in /etc/exports. The "fsid=0" issue is discussed at .

At the end of the day, it works. And it appears to be maintainable. Even after a server restart, the service is available on the client.

Saturday, August 22, 2015


My JQuery resume

Polymer web components and Dart

A couple of weeks ago I finished reworking the Polymer and Dart Codelab example SPA produced by the good people at Google demonstrating the use of the 0.5 release of Polymer. After looking it over, I determined it would make a good general template for the creation of CRUD clients for various REST APIs. In other words, it's a great little example of a single-page app (SPA) to perform the standard operations - create, read, update and delete (CRUD) - in the browser.

I forked the Github repository and issued a pull request. I'll try to remember to include a link here when I get around to deploying it on App Engine.

But I dreaded the idea of having to reproduce the entire project for each REST API - or, more accurately, service - for which I want to provide a browser UI. So the task became how to minimize the repetition involved in creating a CRUD client for an API service. Note that the concept of web services isn't exactly required at this point in our discussion. The data could also come from a local file or AJAX request.

Subclassing Polymer custom components

At the 0.5 milestone, Polymer supports the subclassing of custom components. What this means, exactly, is somewhat unclear, as evidenced by the dropping of its support in the 1.0 release. But I was intrigued with the possibility of abstracting out the CRUD boilerplate and getting some nifty custom web component polymorphism action. I was somewhat successful.

First came the task of determining what the base class(es) would contain. All conceivable, at least to me, interactions with a collection of objects consist of our basic CRUD operations. Therefore, a base class called ItemElement was created. ItemElement would consist of the following:

  1. An instance of the model class Item, item
  2. Stubs, at least, for the CRUD methods read() and update()
Since the other CRUD methods, create() and delete(), are natural as members of a collection class, the ItemList class was created for them. ItemList contains, at a minimum, the following members:

  1. A list of Item instances, items
  2. Stubs, at least, for the CRUD methods create() and delete()
At this point, much of the implementation of Codelab, CodelabElement and CodelabList could be moved into the Item, ItemElement and ItemList classes, respectively. And so it was, leaving only calls to the base class implementations in the Codelab classes.

Next steps

With the success of this basic refactoring, I have stepped back to consider what to do next. Some targets are obvious, such as the difficulty in controlling the placement of HTML elements in the Codelab components. When a base class contains HTML elements, interspersing HTML elements into them from within subclass components is tricky and largely undocumented outside of a brief discussion of the <content> and <shadow> elements on the Polymer website. One is left with the idea that a great deal of flexibility can be leveraged from these. But how?

The next candidate for refactoring consists of removing the form classes ItemForm and CodelabForm contained in the files item_form.[dart/html] and codelab_form.[dart/html] It looks to me that these four files can be easily eliminated from the project by factoring their contents into the ItemElement class. Since the custom Polymer component <item-element> contains logic to control the display of an item based on whether it is being edited, the <item-form> component appears to be at best a convenient abstraction and at worst a design flaw.

Finally, adding the calls to a Codelab web service is on this list of enhancements. This presents particularly attractive possibilities for refactoring. Initial experiments indicate that large portions of the REST API interaction can live in the base classes ItemElement and ItemList. This should be most enjoyable and I expect to report back how Dart made doing this a pleasure.


I plan to write about web 2.0 computing, languages, etc, and invite the reader to take a broad, long-range perspective on events which are shaping the digital and social worlds, increasingly merging into one.

There are lots of blogs covering every imaginable aspect of computing and software. But here lets take a moment to stop and reflect on what it all means... 42.

Just joking. I haven't read Hitchhiker's Guide all the way through, but it's always good to know, when you're feeling lost, that everyone else is, too.