The yak shaving expedition continues…
Previously I set out to create a base box for QNX and naively expected to do a vagrant up and have everything work. HA!
Vagrant was very offended at my presumption and started going on about how it was impossible to recognise the OS I was trying to use.
So I entered the magical world of vagrant plugins and specifically guest and guest capability plugins
Let me start by saying that the vagrant API is beautifuly done. Simple, flexible and cleanly coded. The only downside, which is a result of this flexibility, is that you won’t ever get an exhaustive reference. You have to dive into the code!
Now, to build a guest plugin there are four things that need to be defined:
Guest
The guest plugin needs it’s name and one method, detect? and looks like this
We did say that QNX is BSD-like, didn’t we?
##Guest capabilities
With a bit of trial and error I figured out the minimum amount of capabilities that a guest plugin must have to survive booting and shutting down.
These are
I added change_hostname just because it was easy.
Instead of listing here the implementation code and make this post miles long with copy-paste-able information why don’t you head on to github and browse at leisure?
What took you so long?
So a few things that I had to get right for this plugin to work.
Gem structure
I’m not really sure, but a file named exactly like your plugin (in this case vagrant-guest-qnx.rb) at the top of your gem’s structure seems to be what vagrant expects. Didn’t actually see it documented anywhere but I browsed several 3rd party plugins and copied the structure from vagrant-berkshelf.
I lifted the handy loader guard there as well:
So this code won’t give you ugly stacktraces by chance.
The shell
This actually cost quite a bit of time. Vagrant generally has awesome logging, very detailed, but in this case it kept exiting with “no error message” so I had to dig in and use the magical powers of sprinkled puts. Turns out all machine.communicate.execute calls were returning exit status 126.
Now for all you youngsters out there, 126 and 127 are usually shell code for “bloody hell, I can’t find what you want me to run”. And as it turns out, when communicating over ssh vagrant defaults to running everything with bash.
Unfortunately bash is not available on stock QNX which uses ksh and links it to /bin/sh. So we need
in the Vagrantfile.
Shared folders
There are no VMWare Tools or Guest Additions for QNX. I don’t expect there will ever be. Yet Vagrant tries to establish a share between host and the VM and (in by now typical fashion) ends up hanging forever. So one more addition to the Vagrantfile is needed
And that’s it!
##Tadaaa!
This is the bare minimum Vagrantfile needed to operate the base box you created by faithfully following my instructions
You will need to install the vagrant-guest-qnx plugin (yes, it’s up on rubygems)
There are also a few constraints on the QNX VM:
Because there is no sudo in the stock VM everything is done with su. For that reason the default no-password setting for root is still there. For the purposes of this yak shaving expedition that is more than enough. There is a sudo package for QNX and if by some miracle someone is interested, a pull request will be very welcome.
Halting does not shutdown very fast. Although shutdown is performed, because there are no VM extensions the VM is still listed as running. So you have to wait for the forced shutdown. Not very nice but good enough.
I now declare this yak shaved!