Saturday 12 July 2014

WDLXTV net.mounts

As is often the case - if you have some elaborate complicated process to do something that should be easy, you probably haven’t read the documentation properly.

I use a net.mounts file in the /conf directory on my WDTV Live to mount an NFS share from my NAS on startup. It’s so simple, but I haven’t always done it this way. I did it the hard way for a long time.

Mounting this share is important. The WDTV Live is hooked up to a TV in my kid’s play room and the NAS’s NFS share offers some quality peace & quiet inducing content! (in moderation)

With such a high household priority I was happy to ssh to the WDTV, provide the required credentials then execute the command to mount the share - every time the device was reset or removed from the power source. This took about 6 months to get old. Six months longer than it should have taken:

$ ssh -lroot wdtv-host-ip
Password:
% xmount nas-host-ip:/kids-media/ NFSMedia nfs

This obviously fails the wife test. If I wasn’t home, there was no way I was going to talk her through anything beyond opening the Terminal.app on the mac.

To make it a little easier I decided to copy the mac’s public key to the ssh authed keys on the WDTV. Gee, so much easier (not really)

$ ssh -lroot wdtv-host-ip
% xmount nas-host-ip:/kids-media/ NFSMedia nfs

With passwordless ssh access I figured I would at least provide a simple one liner method for anyone to mount this bloody share when I wasn’t there!

$ echo "xmount nas-host-ip:/kids-media/ NFSMedia nfs" |ssh -lroot wdtv-host-ip /usr/bin/bash

“Hi sweetheart, Just open Terminal and type …. oh ok, I’ll do it when I get home”

How about I just wrap it up in a shell script, couldn’t be easier right? Of course it could - no-one other than someone that knows what a shell script it should have to execute one.

$ vi mount_nas_share_on_wd.sh

#!/bin/bash
echo "xmount nas-host-ip:/kids-media/ NFSMedia nfs" |ssh -lroot wdtv-host-ip /usr/bin/bash

$ ./mount_nas_share_on_wd.sh

I know, how about I make it double clickable!

$ mv mount_nas_share_on_wd.sh mount_nas_share_on_wd.command

Me: “OK, when the share folder isn’t showing up on the WD, just go to the mac and 2xclick on mount_nas_share_on_wd.command”

Wife: “Can’t it just show up automatically when the WD boots up?”

Me: “Yes, you’d think so wouldn’t you”

So I go back to the exact same web resource where I found the xmount command in the first place http://wiki.wdlxtv.com/Net.mounts and there it was - net.mounts “it will mount network shares on boot”

So reading entire documentation beats cherry picking, in this case at least.

Sunday 16 September 2012

iPhoto vs Directory Structure Sanity

"Exporting iPhoto libraries to my NAS with a sensible directory structure"

Yes, we use iPhoto

I like iPhoto. So does my wife. We share an iPhoto library on the same iMac between user accounts by way of a sparse disk image with the appropriate permissions ignorance for us both to manage a single library.

It works for us

It works well enough, as long as we remember that the iPhoto app must be closed when not in use so when a fast user switching event happens the newly logged in user can open the library. Of course we have forfeited Time Machine backups of the library as it now exists on a volume that may as well be on an externally connected device. But I have a solution for that...

... outside of the Apple microcosm

I recently moved to Android when I replaced my 3GS with an GS3. We also never opted in to the Apple media distribution option, we just rely on plain old DLNA for much of our viewing pleasure, including photographs. There's a ReadyNas NV+ chugging along serving up our files and content .. So here's how I get our important iPhoto albums into a sane structure ready to be served up :-

All the heavy lifting is done by Phoshare


Phoshare

This tool has a great command line interface for scripting your iPhoto library grand plans. I can't say enough about it, just start using it..

Convention

So we (my household) have an agreement that if we want photos to be featured and available within our media serving environment they need to be in a named album (or smart album).

Schedule an export to the NAS

Once a day I run bash script out of cron on the iMac that copies/updates iPhoto albums and smart albums to a directory on my NAS over an AFP share. This is an incremental backup of named albums with Phoshare comparing the iPhoto library to the already exported files and only copying/updating new or changed photos. I do not include dated events (created by iPhoto when you add photos) in this process, although I do have a separate shell script that backs up only the events seeing as the disk image we keep the library on is not included in normal Time Machine backups. The process described below is purely to give us access to our important photo albums in a logically named directory structure outside of the iPhoto and Apple environment.

The script

#! /bin/bash

# Set up some constants
MEDIA_SERVER="192.168.1.6"
MEDIA_SERVER_SHARE_URI="afp://;AUTH=No%20User%20Authent@$MEDIA_SERVER/media"
MEDIA_SHARE_MOUNT_POINT="/Volumes/media"

PHOTO_LIB_DISK_IMAGE="/Users/Shared/PhotoLibrary.sparseimage"
PHOTO_LIB_MOUNT_POINT="/Volumes/PhotoLibrary"

IPHOTO_LIBRARY="$PHOTO_LIB_MOUNT_POINT/iPhoto Library"
MEDIA_SHARE_DESTINATION="$MEDIA_SHARE_MOUNT_POINT/Pictures/iPhoto/"


# Mount/Attach the iPhoto Library sparse image if not already attached
if [ ! -d "$PHOTO_LIB_MOUNT_POINT" ]; then
 echo "Attaching $PHOTO_LIB_DISK_IMAGE"
 hdiutil attach $PHOTO_LIB_DISK_IMAGE >/dev/null
fi

# Mount the media share if not already mounted
if ! mount | grep "$MEDIA_SHARE_MOUNT_POINT" > /dev/null; then
 echo "Mounting share $MEDIA_SHARE_MOUNT_POINT"
 mkdir -p $MEDIA_SHARE_MOUNT_POINT
 mount_afp $MEDIA_SERVER_SHARE_URI $MEDIA_SHARE_MOUNT_POINT
fi

# Export iPhoto albums to media share
echo "Exporting iPhoto albums to $MEDIA_SHARE_DESTINATION"
/Applications/Phoshare.app/Contents/MacOS/Phoshare -a . -s . -kfud --gps --pictures -x "Last Import|Last 12 Months|Flagged" --iphoto "$IPHOTO_LIBRARY" --export "$MEDIA_SHARE_DESTINATION"

You can see the full list of Phoshare CLI options here - "Scripting Phoshare"

Thursday 6 September 2012

Sass, Compass & my Eclipse projects



I wanted to integrate Sass/Compass CSS generation into my Eclipse projects with automated compiling of my .scss files.

I'm not really a front end guy and loathe managing CSS, particularly in CSS notation. I looked at Compass a few years ago, liked it, then forgot about it. I obviously hit some tipping point recently and went back to revisit it. The idea of features like mixins and variables appeal to me as a Java dev.

So here's how I do integration into my Java WebObjects projects in Eclipse 3.7.2 on Mac OS X 10.8.1.

First up - installing compass:
sudo gem update --system
sudo gem install compass
Now for my eclipse project..
cd ~/MyWorkspace/MyEclipseProject
As a part of my stock WebObjects (Project WOnder) project directory structure I'll make use of the Resources and WebServerResources directories.

My Compass project will live here:
Resources/compass

My Sass source files will live here:
Resources/sass

And my compiled CSS files will be created/updated here:
WebServerResources/css-sass

So I create a Compass project inside my Eclipse project:
cd Resources/compasscompass init --sass-dir ../sass --css-dir ../../WebServerResources/css-sass
and back to my project root
cd ../..
This creates the following project, source and css files:

Resources/compass/.sass-cache
Resources/compass/config.rb

Resources/sass/ie.scss
Resources/sass/print.scss
Resources/sass/screen.scss

WebServerResources/css-sass/ie.css
WebServerResources/css-sass/print.css
WebServerResources/css-sass/screen.css

For automatic build integration I create a dedicated build xml file in my Eclipse project root build-compass.xml containing the following:


<project name="MyEclipseProject" default="compass.compile" basedir="Resources/compass">
<target name="compass.compile">
<exec executable="compass" dir=".">
<arg value="compile"/>
</exec>
<eclipse.refreshLocal resource="../../WebServerResources/css-sass" depth="infinite"/>
</target>
</project>


Now to set up an Ant Builder in the project's properties dialog.
Properties -> Builders -> New (and choose Ant Builder)


In the Main tab I give it a name, in this case compass.compile, and set the Build File value to the file we just created:


In the Targets tab I set Auto Build to and in the Build Options tab I "Specify Resources" referencing my Sass source file directory.


I can now edit my Sass source files in Eclipse, on save they compile to CSS in my WebServerResources directory which has been refreshed to reflect any changes.

My console output show me the following on successful compilation:


Buildfile: /Users/me/MyWorkspace/MyEclipseProject/build-compass.xml

compass.compile:
        [exec] [31m [0m [32midentical [0m ../../WebServerResources/css-sass/ie.css 
        [exec] [31m [0m [32midentical [0m ../../WebServerResources/css-s [31m [0m [31m [0m [31m [0mass/print.css 
        [exec] [31m [0m [32midentical [0m ../../WebServerResources/css-sass/screen.css 
BUILD SUCCESSFUL
Total time: 1 second

or something like this on build failure:



Buildfile: /Users/me/MyWorkspace/MyEclipseProject/build-compass.xml

compass.compile:
        [exec] [31m [0m [31m [0m [31m [0m [31m [0m [32midentical [0m ../../WebServerResources/css-sass/ie.css 
        [exec] [31m [0m [32midentical [0m ../../WebServerResources/css-sass/print.css 
        [exec] [31m [0m [31m    error [0m screen.scss (Line 15: Undefined variable: "$defaudltSpacing".)
        [exec] [33moverwrite [0m ../../WebServerResources/css-sass/screen.css 
        [exec] Result: 1
BUILD SUCCESSFUL
Total time: 1 second




As always YMMV..

Saturday 8 October 2011

Zero to Hosted in a cup of coffee...

...and the cost of 2

So on a whim I decided my small but thriving organisation needed to be consolidated under a single online brand. We needed an internet presence with business grade communications tools at our finger tips including hosted mail, calendaring and an assortment of collaboration and productivity tools available in the office and on the road to keep us one step ahead of the competition.

Let's call this organisation my, errmm, family..  Of course we didn't need this stuff. More accurately we didn't need another version of this stuff. We've been getting along just fine with our individual mailboxes, IM, blogs, photo hosting, social networking accounts etc etc. Mostly free, mostly easy to collaborate with each other e.g. the odd shared spreadsheet document here or private photo album there.

It was more an exercise in how stupidly quick, easy and cheap organisational hosting can be.

There are of course virtually limitless variations of resources you could use to achieve the same, but my recipe ended up being:

Crazy Domains to register my domain name. I ended up with a name under the .org TLD at a cost of $18 for 2 years. I probably paid too much, but seeing as this was the only step with a $ cost I wasn't too fussed.

FreeDNS for umm free DNS! I chose FreeDNS because it googled well and I wanted free domain name hosting, that's it.  I needed to be able to manage my own DNS records and it offers open slather management of your domain.

Google Apps "for free" this part was probably fairly obvious. The features available for free (for up to 10 users within your organisation) would be cheap at twice the price..


It probably doesn't warrant a step by step how to other that the above being the crucial steps, I did them in that order but I guess you don't really have to. The only minor issues I had were Crazy Domains trying valiantly to up-sell me from just a domain registration during the sign up process and the TXT DNS record required by Google Apps to verify your ownership of the domain, I needed to surround the destination value in double quotes. A summary of what my zone looks like is:

IN NS ns1.afraid.org.
IN NS ns2.afraid.org.
IN NS ns3.afraid.org.
IN NS ns4.afraid.org.
IN MX 1 aspmx.l.google.com.
IN MX 5 alt1.aspmx.l.google.com.
IN MX 5 alt2.aspmx.l.google.com.
IN MX 10 aspmx2.googlemail.com.
IN MX 10 aspmx3.googlemail.com.
IN TXT "google-site-verification=blahblah"
IN CNAME ghs.google.com.
IN CNAME ghs.google.com.
IN CNAME ghs.google.com.
IN CNAME ghs.google.com.

So for $9 a year every member of our "organisation" has a mailbox (an email address they can keep forever and whatever aliases he/she likes) @ourdomain.org (7GB at moment gmail? for free? pfff, match that commercial hosting service), shared calendaring (all happy to be added to your favourite smart phone as an Exchange account), sites with a pretty decent site builder to have the ever important website version of kids birthday party invitations, docs and all the other google features. We also have the ability to point some host names around to existing stuff e.g. an app engine application, or maybe a blog!

hmmm, airconhum.ourdomain.org..