Unity 8's Snappy Scope
I recently began a new position at Canonical. I joined this company in particular to give myself more opportunities for growth. Now, when I say that, people tend to assume I'm talking about a managerial track. I'm not sure why they tend to jump there, but it's not what I'm referring to here. I'm talking about technical growth. I feel at the top of my game when I'm learning something brand new, and I needed a company that facilitated that. Canonical has delivered.
My background is quite heavily focused on C++. My resume revolves around it, and the interviews each probed the depths of my C++ understanding. So, as logic dictates, my first technical tasking is in-- you guessed it-- Go.
This is fantastic. Not that I particularly care about Go (I'd never used it before now), but because it broadens my horizons. I've been entrenched in the Google-test-driven C++ world for a while, so it's nice to be able to dig into a new language, with new testing idioms. This can't not make me a better all-around engineer.
I joined the company amidst the fervor of Snappy (or Ubuntu Core)-- a transactionally updated version of Ubuntu targeted mainly at embedded devices. In order to be transactionally updated, Ubuntu Core uses a different packaging mechanism than regular-old Ubuntu. Ubuntu, as a Debian derivative, obviously uses .debs, but Ubuntu Core uses a packaging format called Snap, which is the successor of Click (the packaging format currently used on the Ubuntu Phone). In addition, a large number of Ubuntu Core components are written in Go, thus the choice of language for my piece.
Quick Ubuntu Core Background
Ubuntu Core is brand new, and pretty beta. Things are changing quickly, and I'm pretty new to the whole thing, so take what I say here with a grain of salt.
The master plan, as I understand it, is for Ubuntu to dominate the Internet of Things (IoT). The problem with embedded devices today is that one typically buys them from the manufacturer with some firmware installed, and then that device runs forever without anyone touching it again. At first glance that's a good thing-- the device should run forever. But the side effect of this is that the software on the device never gets updated. A good example of how this is a problem is with routers: a public-facing device, with security holes, that never gets updated to fix the holes. Pretending that the manufacturer even releases new software to fix the problems, the consumer can't be bothered to: A) check to see that there is an update, or B) apply said update.
Ubuntu Core is attempting to solve this problem by changing these manual firmware flashes to software updates that can be safely automated, because they're completely transactional, i.e. they can be reversed if they cause problems.
In addition to this, because the embedded device is running Ubuntu, you should be able to install whatever applications you want. Of course, since these are embedded devices, you have no way to do that unless you want to SSH into them or something. We thought of that with Ubuntu Core: You can use WebDM to configure each device remotely!
Ubuntu Core + Ubuntu Mobile
Okay, so Ubuntu Core has a pretty solid story behind it. So does Ubuntu Mobile. However, Canonical wants to fuse the two together. This makes sense-- they have very similar components already (security model, transactional updates, app store, etc.), but they still have a lot of differences, particularly regarding the packaging and software install/update/run model. That's (partially) where I come in.
Ubuntu Core makes the assumption that the user will do nothing locally (since an embedded device is also typically a headless device). Adding Ubuntu Mobile changes the game a bit, since a user is now doing everything locally. One of the first components we need is essentially a local-only WebDM-- a local app store. Since Ubuntu Mobile uses Unity 8, it makes sense for this to be a Unity Scope.
"But wait," you're thinking. "Doesn't Ubuntu Mobile already have an app store?" Indeed it does, but that scope is for installing Click packages; we need one for Snappy packages.
"But wait," you may also be thinking. "The Unity Scope API documentation is only available for C++. Didn't you say this was in Go?" Ah, you are astute! This isn't officially supported just yet, but my colleagues James Henstridge and Xavi Garcia have been slaving away on Go bindings for the Unity Scope API, and they are quite functional.
We're hoping to throw together a proof-of-concept very soon, which gave us a hudle really early-on: We don't want to duplicate the effort that has gone into WebDM. WebDM is also written in Go, so we were hoping we could at least share libraries or something. Unfortunately, WebDM wasn't written that way-- it has a REST API for the web interface, and that's it.
That's okay. Snappy is indeed pretty beta, so we'll work on getting WebDM to where it needs to go. Until then, we still don't want to duplicate effort talking to the overarching Ubuntu Store API, so in our proof-of-concept we'll just be using the existing WebDM REST API. We're doing this in a very modular way so we can rip it out easily later.
We're still very early-on in the development process, but you can check it out (and even contribute!) if you like.
How to test
First of all, you should check out the project's README. It will be more up-to-date than this post.
- Ubuntu 15.04 (Vivid)
- Ubuntu Core running somewhere (I just put it in a VM)
- WebDM must be installed
- WebDM must be accessible from where the scope is running
- Unity Scope Tool
Install the required packages:
$ sudo apt-get install unity-scope-tool golang-go bzr
Now setup your Go workspace. This is what I use:
$ mkdir -p ~/src/go # Create the workspace directory
$ echo "export GOPATH=~/src/go" >> ~/.bashrc # Make this environment whenever you login
$ echo "export PATH=\$GOPATH/bin:\$PATH"
$ source ~/.bashrc # Make it your environment now
Now grab the scope itself:
$ cd $GOPATH
$ go get launchpad.net/unity-scope-snappy/snappy-scope
This should result in a snappy-scope binary being placed into $GOPATH/bin/. However, it can't be run directly-- this is where the Unity Scope Tool comes in.
Each Unity Scope requires a .ini file describing itself and how to launch it, and Go scopes are no different. The Snappy Scope's .ini file is alongside the source code, so launch it like this:
$ cd $GOPATH
$ unity-scope-tool src/launchpad.net/unity-scope-snappy/snappy-scope/snappy-scope.ini
The scope by default uses the webdm.local hostname to communicate with WebDM. If that's not working, edit the snappy-scope.ini file to tell it where to look for WebDM. Something like this:
ScopeRunner = $GOPATH/bin/snappy-scope --runtime %R --scope %S -webdm=<ip:port of webdm>
As you can see, the functionality of the scope is currently quite limited. At the time of this writing, all it can do is display applications from the store. I'm currently working on making those applications installable.
I haven't yet noticed anything missing from the Go Scope bindings. Definitely worth checking out!