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) strip.show() time.sleep(wait_ms/1000.0) for i in range(0, strip.numPixels(), 3): strip.setPixelColor(i+q, 0) # Create NeoPixel object with appropriate configuration. strip = Adafruit_NeoPixel(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS) # Intialize the library (must be called once before other functions). strip.begin() # 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') break # 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).\ strip() if re.match(r'.*light.*on.*', message_text, re.IGNORECASE): theaterChase(strip, Color(127,127,127)) slack_client.api_call( "chat.postMessage", channel=message['channel'], text="Lights are now on", as_user=True) if re.match(r'.*light.*off.*', message_text, re.IGNORECASE): theaterChase(strip, Color(0,0,0)) slack_client.api_call( "chat.postMessage", channel=message['channel'], text="Lights are now off", as_user=True) time.sleep(1)
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?
- Made the decision to get the SSD bootable and abandon the RAID pair to start.
- Rebuilt the partitions on the SSD broadly following this with
- boot from windows recovery and run command prompt
select disk X
select partition 2 (the "EFI" partition that wasn't)
create partition EFI size=200
format quick fs=fat32 label="System"
bcdboot c:\windows /s b: /f ALL
- (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).
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.
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.
- 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
- Explain what the company’s offering does
- Why it is better than the competition’s approach
- How we will approach winning an important market
- 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.
- 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.
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)
|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:
|Annual revenue (not ARR) per $ raised:
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
- First meeting
- all partner meeting
- discuss terms
- 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.
My favourite founders were Peter Gassner (Veeva), Anand Sanwal (CB Insights) and David Barrett (Expensify).
- 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.
- 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
- (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?
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.
- Install Ubuntu as per requirements
- Installed 14.04 (yes, it’s old. They may fix that soon.)
apt-get install aptitude build-essential git ntp ntpdate \ openssh-server python-dev sudo
git clone -b stable/mitaka \ https://github.com/openstack/openstack-ansible.git \ /opt/openstack-ansible scripts/bootstrap-ansible.sh
|Container Management Network||172.29.236.0/22||10|
|Tunnel (VXLAN) Network||172.29.240.0/22||20|
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.
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
- Unsure that the network for neutron_linuxbridge_agent br-vlan has host_bind_override: “eth12” that is accurate. This is meant to be a physical interface as per http://docs.openstack.org/developer/openstack-ansible/mitaka/install-guide/configure-networking.html
- Had to uncomment at least one thing in the user_variable.yml
- Used the AIO templates for this all-in-one install.
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.
ansible galera_container -m shell -a \ "mysql -h localhost -e 'show status like \"%wsrep_cluster_%\";'"
Then finally installing openstack
Wait something like an hour
Login at https://10.2.0.50/ 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.
Following along the CentOS howto using Centos 7.2
Just a couple of things have changed since it was written:
- 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
- Evidently xfs filesystems should be formatted to inode size 512 bytes, not 256.
- 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
- 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?
- What is the best filesystem for the bricks? XFS is the default. As above, it should be formatted with 512 byte inodes.
- What should the network segmentation and firewall zone configuration be?
- 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.
- How to best utilise SSD
- 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.
- 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?
- Through block level management with dm-cache or similar, preferably integrated to LVM?
- Through hardware RAID controller?
- 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.
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 new-width new-height offx offy) (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 …)
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.
Bristol Street Art Tours – although we could have walked the streets of Bristol for free and seen these amazing works, we wouldn’t have had a window into the other world that street artists inhabit. Our guide opened up the complexity of practicing street art – legality vs illegality, tourism, technical production, attitudes from city authority, impermanence, the inter-generational conflict, digital archiving and promotion, and international participation in the recent historical context.
I was so good, I didn’t mind it was 12 degrees and raining.
BTW, the guide did cover Banksy, too.