Recent recipes

Both were great

  • Miso chicken – I used chicken thighs, basically marinade (/500g chicken) pan fried to internal temperature 70deg C
    • 2 Tbps Miso paste
    • 1 1/2 tsp sesame oil
    • 1 1/2 tsp chopped ginger
    • 1 1/2 tsp chopped garlic
    • 1/4 tsp chilli flakes (I added just a merest pinch of our dried chilli)
  • Tuna pasta, good hot or cold
    • tuna, capers, cream, mixed seeds, lemon zest

Slackbot on Raspberry Pi

As per Benjie.Me and Neopixels on Raspberry and also JGarff

import re
import time
import json
from slackclient import SlackClient
import time
from neopixel import *

# LED strip configuration:
LED_COUNT = 8 # Number of LED pixels.
LED_PIN = 18 # GPIO pin connected to the pixels (must support PWM!).
LED_FREQ_HZ = 800000 # LED signal frequency in hertz (usually 800khz)
LED_DMA = 5 # DMA channel to use for generating signal (try 5)
LED_BRIGHTNESS = 20 # Set to 0 for darkest and 255 for brightest
LED_INVERT = False # True to invert the signal (when using NPN transistor level shift)

def theaterChase(strip, color, wait_ms=50, iterations=2):
 """Movie theater light style chaser animation."""
 for j in range(iterations):
 for q in range(3):
 for i in range(0, strip.numPixels(), 3):
 strip.setPixelColor(i+q, color)
 for i in range(0, strip.numPixels(), 3):
 strip.setPixelColor(i+q, 0)

# Create NeoPixel object with appropriate configuration.
# Intialize the library (must be called once before other functions).

# Slack integration
slack_client = SlackClient(YOUR_API_KEY_HERE)

# Fetch your Bot's User ID
user_list = slack_client.api_call("users.list")
for user in user_list.get('members'):
 if user.get('name') == "labs-pi":
 slack_user_id = user.get('id')

# Start connection
if slack_client.rtm_connect():
 print "Connected!"

 while True:
 for message in slack_client.rtm_read():
 if 'text' in message and message['text'].startswith("<@%s>" % slack_ user_id):

 print "Message received: %s" % json.dumps(message, indent=2)

 message_text = message['text'].\
 split("<@%s>" % slack_user_id)[1].\

 if re.match(r'.*light.*on.*', message_text, re.IGNORECASE):
 theaterChase(strip, Color(127,127,127))
 text="Lights are now on",

 if re.match(r'.*light.*off.*', message_text, re.IGNORECASE):
 theaterChase(strip, Color(0,0,0))
 text="Lights are now off",

Posted in IT

Windows 10 Boot Recovery or Not

I woke on the morn of Good Friday to find the PC at the BIOS screen with a CPU overheat error. Despite the CPU fan being listed as spinning at 1800RPM, the CPU was cooking along at 75deg or so..

Time for a shutdown and vacuum out the dust. Something I’ve done routinely in the past, but this time it all went wrong. On starting the system again…. it didn’t.

After an extremely frustrating sequence of reboots, BIOS setting review, recovery USB key creation I think what happened was that I managed to clear the motherboard BIOS settings. Given that my boot disk was still a pair of Seagate Barracuda’s in Intel RAID1 (mirror), I think that this also was the primary cause of my subsequent inability to boot. That I had installed a SSD for Windows 10 system when I did a clean install (after the original Win7 to Win10 upgrade), was a cause of additional confusion.

Additional complications included building a windows system restore USB key (on another Win10 system), and trying to use the startup repair (available under system recovery menu). Also I think at some point I ran a Linux install-mbr utility. I also ran

bootsect /nt60 ALL / force
bootrec /fixbmbr
bootrec /fixboot
bootsec /scanos
bootrec /rebuildbcd

The RAID pair were an original MBR partion table, and the new SSD a GPT. From a hardware perspective the Asus P8P67 Pro included a 6Gbps SATA Marvel 9120 interface that I am fairly certain are addressable by UEFI BIOS, but not in the early start sequence of the Win10 kernel boot.

Finally, by the time all this had been tried, I ended up with an SSD that had a Microsoft Reserved Partition (16MB), an EFI system partition that was in fact relabelled data partition with my Win10 system in it (200GB or so), and a Recovery partition (500MB or so). At this stage, bootsect /scanos was no longer finding the Windows system install, although in some circumstances is it was located in a path like /?/Volume3/….

So how did I ultimately resolve?

  1. Made the decision to get the SSD bootable and abandon the RAID pair to start.
  2. Rebuilt the partitions on the SSD broadly following this with
    1. boot from windows recovery and run command prompt
    2. diskpart
    3. list disk
    4. select disk X
    5. list partition
    6. select partition 2 (the "EFI" partition that wasn't)
    7. setid EBD0A0A2-B9E5-4433-87C0-68B6B72699C7
    8. shrink desired=200
    9. create partition EFI size=200
    10. format quick fs=fat32 label="System"
    11. exit
    12. bootrec /fixboot
    13. bcdboot c:\windows /s b: /f ALL
      1. (Or maybe I ran bootrec /rebuildbcd later.Initially the fact that I was still plugged into the Marvell SATA meant that step (M) was failing).


Posted in IT

20 Minute VC – the schizophrenia of raising v.s. running the business

Listening this morning to Micah Rosenbloom via Harry Stebbings and heard something like the following at 16 minutes.

(Harry) as Jason Lemkin at SaaStr says… the best investors are those who know the benchmarks for the next round and then are able to help the founders attain them.


(Micah) I feel there is some wisdom there, but that it was possible to become obsessed with what was required for the next round, and as a result you focus on building the deck for the next round, not on building the business… The second challenge is that the goal posts keep moving, e.g. the MRR moves from $100K to $200K to do a series A. It’s hard to build your company just for the next round.


(Micah) wishes he could put blinders on his founders, have them not talk about the next round for 12 months after taking money. This is the venture train,… immediately after you get the hit, you are after the next hit.

An balanced focus on capital efficiency on business fundamentals. Good perspective and perhaps an antidote to VC echo chamber.

SaaStr 2017


This is a long post about my experience at SaaStr Annual 2017 this year. I attended as development in my role as board member of Inference Technology Group. Inference is a SaaS business and so the conference focus on scaling, management and governance, unit economics, and venture capital was highly relevant.

Challenges of Scaling a Saas business – Recruitment, Culture and the Goldilocks Pace

Stories of executive focus on recruitment, culture and the right rate of growth were common in the keynote talks. These included those running a number of now large and successful SaaS businesses: Chris O’Neill (Evernote), Geoff Lawson (Twilio), Peter Gassner (Veeva), Russel Fradin (Dynamic Signal), and Anand Sanwal (CB Insights).

All discussed extensive periods where recruitment had been more than half of their role.

Many also stressed the importance of being a little contrarian – pursuing little loved business hypothesis, or pushing back on venture capitalist ‘growth at all costs’ strategies. From the VC perspective, one cited the #1 reason for the failure of SaaS companies as growing too fast; another that the #1 reason for SaaS companies to fail to hit plan was delay in hiring sales resources. One CEO spoke to the challenge of hiring external VPs can send a signal to internal talent that there is limited opportunities for promotion.

Keeping Board and Founders Aligned (David Barrett, Founder & CEO of Expensify)

Expensify is about 100 employees and 25K customers. David spoke about the relationship between board and CEO. He suggested the board needs to understand it’s role as a check on the CEO’s powers. They must also understand that the CEO & Founder has an incredible emotional investment in the success of the business at the same time as usually being in an incredible stretch role.

For management, he outlined that they must know what is within their delegation and do those things. They must also work hard to have a rapport with the board members, and to keep communications with investors frequent (e.g. fortnightly).

From a mechanics perspective, Expensify board meetings are quarterly, for a couple of hours, focused on strategic decisions selecting between options; and mechanical resolutions, particularly regards equity.

In passing, he opined that independent directors offer limited value.

How to miss a quarter (Aaref Hilaly – Sequoia Capital)

Aaref shared that the Sequoia portfolio of companies, great though they might be, have collectively missed a lot of quarters.

His advice – you’ll almost certainly miss a quarter so prepare, and know how to execute when it happens.

This was outlined in three parts.

  1. Don’t manage the board, engage them. This starts with product over metrics – know what you are doing to win; perhaps oriented at earlier stage companies. For companies > $2.5M ARR with large ACV, perhaps guidance starts to become knowing what it takes to win deals, not just obsessing over aggregate metrics. In Aaraf’s talk he suggested the board must be able to
    1. Explain what the company’s offering does
    2. Why it is better than the competition’s approach
    3. How we will approach winning an important market
  2. Everybody misses at some point; so don’t deny, hope, or fall prey to doom or gloom; instead own the miss, be honest about the mistake, help the board process the implications.
  3. Put the board to work. Leverage what they can bring to the table in terms of customers, partnerships and alliances, or recruitment.

VCs on Metrics

David Skok (General Partner, Matrix Partners)

David Skok spoke about the SaaS funnel – comprising the usual sales funnel as well as the subsequent management of expansion within established accounts. Slides 77 – 82 show the 12 levers around product/market fit; sales funnel; customer life-time value (LTV); and Cash Requirement; and building a great organisation.

Of the 12, I feel that (4) CAC is an intermediate result of the more fundamental (6) productivity per rep and the unlisted marketing metrics (cost per marketing qualified lead); (11) Months to recover CAC is also an intermediate result, but obviously significant.

Finally, reverse funnel math (slide 67) makes a simple relevant point that you’ll need to find leads equivalent to the product of each funnel stage conversion proportion per win (required to reach MRR add requirements). When coupled with the sales rep as a unit of business growth, along with that rep’s productivity over time curve (slide 47), you have the basic kernel of scaling a SaaS business with [field] sales.

12 Key Levers of SaaS Success


David Spitz (Managing Director, Pacific Crest Securities)

David Spitz spoke on Measure your success and tell your story with SaaS metrics. It explored a simple analogy of filling a leaky bucket – recurring revenues [dissapating/growing] with [churn/expansion] – with a water can (or perhaps more appropriately, a hose) of new recurring revenue at the cost of customer acquisition.

His take-outs were that these metrics were crucial to understand your business (but you mustn’t overlook their shortcomings, particularly regards LTV); that investors love the unit economics, but the rate of capital consumption / generation governs long term success; and that while growth + profitability must exceed 40%, the public market more highly values growth.

After covering the complex ways that churn can be measured, the pitfalls of lifetime customer value (LTV) and Cost of Customer Acquisition (CAC) calculations, it focused on results from a sample of public (N ~ 10 – 35) and Pacific Crest SaaS survey results (generally N ~ 240) across CAC ratio, CAC payback period, ARR achieved v.s. cumulative burn, and valuation as a function of growth plus profitability.

Some key metrics for the 50 business with annual recurring revenues between US$2.5-5M include (all in USD) from that survey are as follows

Item 33rd %ile median 66th %ile
Revenue per FTE: $94K
Sales and marketing spend as proportion of revenue
(at growth > 40% p.a)
~ 48%
Growth 31% p.a. 70% p.a.
Customer Acquisition Cost per $1 annual contract value $1.13
Annual contract value ~ $10K $25K ~ $50K
Annual gross $ churn ~ 5% ~ 8% ~ 15%
Equity investment required to reach $5M ARR $8M

David also discussed what appeared to be a gating metric for the VC community, the “Rule of 40%”. In order to be attractive to fund, the sum of revenue growth and unlevered free cash flow margin (EBITDA / Revenue?) are to exceed 40%. This rule is taken to hold most particularly for business more mature business with ARR of more than $10M.  The median for survey respondants was only 20%, and only 26% exceeded this bar (N = 77).

Aydin Senkut (Founder & Managing Director Felicis Ventures)

Aydin presented a subset of the style of metrics gathered by the Pacific Crest survey for the businesses within the Felicis Ventures portfolio. Felicis use this as benchmarking to help CEOs of their business understand their companies performance.

There were 25th / 75th percentile data give for a couple of key metrics as follows

Item 25th %ile median 75th %ile
Revenue per FTE:
$55k $111K $214k
Annual revenue (not ARR) per $ raised:
$0.13 $0.4 $0.71

VCs on Raising

Elizabeth Yin, Partner 500 Startups.

Elizabeth spoke about 11 funding secrets learned from 1,600 startups.

Two in particular resonated; number (2), describing the basis for VC fund dynamics, and the need for winners to win big; and number (7), creating a forcing function for raising.

The first dove tailed with other speakers throughout the conference, describing how VC general partners are competing within a given fund to deploy capital, that they receive most remuneration based on the the initial deployment, and that these facts together with the asymmetric distributon of payoffs led to large amounts of funds being pumped into business’ that showed the best chance of being unicorns.

The second described that getting funding, and getting the best chance of funding on your terms required multiple VCs to be entertained in parallel, and statements such as the following used to create urgency.

  • I’m moving into three all partner meetings next week on Sand Hill
  • I’m doing four investor meetings a week

Meetings should be scheduled 4 weeks in advance. Multiple parties should be lined up in back to back sessions. You need to start by building a list of potential funders, doing research, and understanding the way the process progresses

  1. First meeting
  2. all partner meeting
  3. discuss terms
  4. receive term sheet

At each stage, specific questions and requests such as “Do you need to have an all partner meeting to make a decision” should be used in order to drive forward to the next step.

Founders Wisdom

My favourite founders were Peter Gassner (Veeva), Anand Sanwal (CB Insights) and David Barrett (Expensify).

Peter Gassner

  • When a trend is early, everyone thinks you are wrong
  • Sell yourself first, whether in negotiation or in a hire. Get the right value, not the most.
  • We are running a profitable business. We thought that was a good thing.
  • Engaged people working together. Your team is your peers, not the people you lead.

Anand Sanwal

The other 61 items available here from @asanwal

  • You can revenue fund a beast
  • Don’t take advice from non-customers
  • Don’t believe being outfunded will kill you
  • Don’t sell to startups
  • Once revenue scales you will need to plan to pay down technical debt
  • Don’t fear the grind – non elegant solutions can work
  • Don’t try to innovate in HR

David Barrett

  • (To a founder with a majority share asking for advice on hiring an independent director) If you want to get advice, why don’t you just call one hundred people instead of just one?


Testing Openstack with Ansible and all-in-one install on Hyper-V

I installed Openstack recently in order to get my head around some aspects. I used my desktop (16GB RAM, decent chunk of SSD & i7-2600 @ 3.4GHz).

After looking at the 50 ways to install Openstack, I went with the developer ansible automation. Installation proceeded as follows.

Install Deployment Host

This contains the ansible configuration and drives the process.

  1. Install Ubuntu as per requirements
    1. Installed 14.04 (yes, it’s old. They may fix that soon.)
    2. apt-get install aptitude build-essential git ntp ntpdate \
        openssh-server python-dev sudo
    3. git clone -b stable/mitaka \ \

Networking assignments

Network IP Range VLAN
Host management
Container Management Network 10
Tunnel (VXLAN) Network 20
Storage Network 11


My numbering was

Host Host mgmt Container mgmt Tunnel Storage


Making Hyper-V connect up VLAN trunks that are run as bonded Ethernets

Hyper-v manager can’t set trunk mode on adapters so doing this with powershell run as administrator

Get-VM Deployment | Set-VMNetworkAdapterVlan -Trunk -AllowedVlanIdList 1-100 -NativeVlanId 0
Get-VM Node1 | Set-VMNetworkAdapterVlan -Trunk -AllowedVlanIdList 1-100 -NativeVlanId 0

Note – the NativeVlanId 0 is required to bridge this into the untagged management domain for the external network.

Also need to configure (Network Adapter | Advanced Features | MAC Address) to enable mac address spoofing (which the active/backup bonding will do)


Install Target Host

As per the docs and above. Could be improved by using MAAS but I won’t go there yet.


Configure networking

Did this by hand, but probably able to be skipped now that the ansible stuff generates this?


Deployment configuration questions – while configuring the yml and friends


Aged APT repo & keys… and figuring out that

Initially AOI failed in deployment due to untrusted packages; like a fool I tried hand-deploying the broken ones

apt-get install libasan0 libatomic1 libgomp1 libitm1 libc-dev-bin \
  linux-libc-dev libc6-dev libexpat1-dev libpython2.7-dev \
  libquadmath0 libtsan0 python3-libapparmor python3-pkg-resources \
  python3-apparmor apparmor-utils binutils cpp-4.8 libgcc-4.8-dev \
  gcc-4.8 libstdc++-4.8-dev g++-4.8 libdpkg-perl dpkg-dev \
  python2.7-dev python-software-properties

Running openstack-ansible setup-hosts.yml didn’t get me much further – failed again with security hardening – postfix install – so added added a no-authenticate in the yml files; not the right place though.

Stopped, thought, learnt and instead tried

apt-key update
apt-get update

Which (after agreeing to a key update from recollection) resolved the issues

Continuing on to manually run playbooks

openstack-ansible setup-hosts.yml
openstack-ansible setup-infrastructure.yml

Note the formating of the output of Ansible running the playbooks – should be no errors.

Confirmed with

ansible galera_container -m shell -a \
   "mysql -h localhost -e 'show status like \"%wsrep_cluster_%\";'"

Then finally installing openstack

openstack-ansible setup-openstack.yml


Wait something like an hour

It’s up!

Login at with admin / 5f915721a645bf38735ff099

Everything appeared to be running – but for Cinder volume block storage is down, probably because I my just have skipped some necessary LVM prep steps.

Posted in IT

Testing glusterfs on centos

Following along the CentOS howto using Centos 7.2

Just a couple of things have changed since it was written:

  1. As per the CentOS storage special interest group, you can now get the glusterfs packages without using wget to retrieve additional repos:
    yum install centos-release-gluster
    yum install glusterfs-server samba
  2. Evidently xfs filesystems should be formatted to inode size 512 bytes, not 256.
  3. If you want to delete a volume immediately after creating, you’ll need some incantations to re-use the bricks without re-formating them.

Along the way I asked myself the following questions

  1. Should each of the physical disks be surfaced as a separate volume group and allocated within a single logical volume using 100% of the VG? Allocating 100% prevents using LVM snapshots, but why would you ever want to do that (or is that a building block for GlusterFS snapshots?)  Is there something that could be done to use HSM and LVM to balance blocks on each node?
  2. What is the best filesystem for the bricks? XFS is the default. As above, it should be formatted with 512 byte inodes.
  3. What should the network segmentation and firewall zone configuration be?
  4. What brick layout, replica setting and stripe setting makes sense? The number of bricks are required to be the product of the number of replicas and stripes.
  5. How to best utilise SSD
    1. Through glusterfs file level tiering in the March gluster / Redhat storage tech preview? This version also allows access to erasure coding, lowering the cost of storage replication.
      1. immediately available in the Centos 7.2 build. BUT… works at the file level, so not so helpful with VMs. However if sharding is turned on, perhaps it works at the shard level?
    2. Through block level management with dm-cache or similar, preferably integrated to LVM?
    3. Through hardware RAID controller?
Posted in IT

Cropping multiple images with Gimp and script-fu

I recently had a series of video screenshots from a Gotomeeting screencapture. The presenter screen had resolution 1366×768; the meeting organiser 1920×1080.

The result was that all the images were surrounded with a black border. In turning the screencapture into a set of stills to represent as narrated video, I used the following in Gimp

  • Start Gimp and enter Filters | Script-fu | Console
  • In the console that comes up, paste the following to define the batch-resize function
(define (batch-resize pattern
(let* ((filelist (cadr (file-glob pattern 1))))
 (while (not (null? filelist))
        (let* ((filename (car filelist))
        (image (car (gimp-file-load RUN-NONINTERACTIVE
                                    filename filename)))
        (drawable (car (gimp-image-get-active-layer image))))
        (gimp-layer-resize drawable new-width new-height offx offy)
        (gimp-image-resize-to-layers image)
        (gimp-file-save RUN-NONINTERACTIVE
                        image drawable filename filename)
        (gimp-image-delete image))
        (set! filelist (cdr filelist)))))

  • Then in the same console you can run the following
(batch-resize "/path/to/screenshots/*png" 1366 768 -272 -157)

Note that this was on a windows system – and the format of the filesystem path is still with forward slash. Note also, this will replace existing files with modified versions.

If you want to perform some other form of processing on each file, the key function to replace is (gimp-layer-resize …)

Form more information, see the Script-fu Tutorial or the Gimp scripting manualIT

Posted in IT

The dangers and opportunities of statistical multiplexing gain


Evidently Sandringham used to be served by first a house drawn, and then an electric, tram. The horse drawn services were wound up in 1914 as “The cost of keeping horses for these peak [holiday] times led to the demise of the Company’s services”.

Telco profits often stem from statistical multiplexing gains – sell 1000 x 10 Mbps user services, provision only 500 Mbps backhaul. Beware, though, if you have service level obligations in peak periods and have high peak to average demand statistics.

Ref. Rotary Club of Sandringham bus shelter display on Bay Rd.

Home again



Somewhat symmetrically… back at southern cross for sunrise. Turns out our fellow passenger from London was also catching the Sandringham line, we meet him again on the platform.

Dolphins! On the bay past Brighton Beach. Good to be home.