That's one Snappy MOOS
So you're a roboticist, looking at Ubuntu Core and Snappy, trying to decide if they're a good fit for your project. You come across some ROS documentation and realize that the ROS support is first-class, but you're not using ROS. No, you're using the Mission Oriented Operating Suite (MOOS). Why is there no documentation on using MOOS? Because it's too easy to need a document, that's why.
Note that there are two commonly-used projects here, MOOS, and MOOS IvP. The latter uses the former, and adds some more modules on top. It also has a more complicated build system when it comes to packaging, so we're only going to talk about MOOS here (I'll make another post regarding MOOS IvP).
Typical MOOS build process
MOOS is just good-old CMake, so the typical build process looks pretty, well, typical. First we grab and extract the latest release:
$ wget https://github.com/themoos/core-moos/archive/10.0.2.a-release.tar.gz
$ tar xzf 10.0.2.a-release.tar.gz
Now we configure and build it:
$ mkdir build
$ cd build/
$ cmake ../core-moos-10.0.2.a-release/
There are even sensible install rules in there if you want to run make install. Creating a new module to make use of it is also easy-- just refer to this example.
Packaging MOOS as a .snap
.snaps are built using a tool called Snapcraft. For this example we're going to target Ubuntu Core 15.04, which requires Snapcraft v1 (the latest release in that line as of this writing is v1.0.2). For more information on installing/getting started with Snapcraft, head this direction.
Let's get started. First of all, we're going to borrow this example from MOOS, with one modification to the CMakeLists.txt: an install rule. Just put it at the bottom, like this:
RUNTIME DESTINATION bin
If this isn't clear, the finished code for this post has been pushed here. We need the install rule, or Snapcraft won't know which files to place where when creating the final .snap.
Now we're going to create the following directory structure:
The snapcraft.yaml file is the recipe used by Snapcraft to "craft" the .snap. Open it up in your favorite editor.
Let's begin by providing some general metadata about the .snap, so add something like the following:
vendor: me <firstname.lastname@example.org>
summary: MOOS Example
description: Simple ping/pong example for MOOS
In Snapcraft v1 that icon is required, so if you don't have one run this command to make one:
$ echo "<svg />" > icon.svg
Back in the snapcraft.yaml, we need to tell Snapcraft about the parts making up our .snap. In our case, there are two parts: the MOOS core, and our ping/pong example:
after: [core-moos] # Build this part after MOOS
The snapcraft.yaml we have so far will result in a valid .snap, but it doesn't export any behavior. Let's make MOOSDB run as a service, at boot:
description: MOOS router
Let's also add a few binaries to use our ping/pong example (binaries don't run at boot, they're run by the logged-in user):
exec: ex1010 --ping
So that adds two binaries: ping and pong. Their functionalities should be obvious.
Believe it or not, we're done here. Let's save and close snapcraft.yaml, and create the .snap:
$ cd moos-example/
Wait for a minute while MOOS is fetched and built, then the local code is built, and finally while the .snap is being created. Once it's finished, take it for a spin!
Testing the resulting .snap
Note that you need an Ubuntu Core device with the same architecture as the .snap you just created (it can be a real device, or virtualized). Pick your poison. Once you have it up and running, you can scp your .snap to it and install it by running this command on the device:
$ sudo snappy install /path/to/my.snap --allow-unauthenticated
Now, on the device, you can see MOOSDB running:
$ sudo snappy service status moos-example
Snap Service State
moos-example MOOSDB enabled; loaded; active (running)
So now we can run our ping/pong example. In one terminal (logged into the device), run:
In another terminal (also logged into the device), run:
And you'll see them communicating, just as you'd expect.
"So what's the big deal? What did I just accomplish?" I hear you asking. You actually accomplished a number of things:
- You now have an entire MOOS system prepared for deployment/sharing. All dependencies are included in the .snap-- it will run on any Ubuntu Core 15.04 installation.
- You've configured exactly what should be run on boot for the robotic system, no need to fiddle with config files.
- By using Ubuntu Core, you now have a transactional deployment/update strategy for free. You can even get automatic updates on your devices if they connect to the internet and you upload your .snap to the store.
- Perhaps most importantly, your MOOS system is running completely confined. Even if it has an exploitable vulnerability, the confinement model of Ubuntu Core means an attacker's potential damage is very limited.
If these things are important to you, I definitely suggest you spend some time experimenting with Ubuntu Core, Snappy, and Snapcraft. For your reference, the code used in this post is in GitHub.