Skip to content
Browse files
Improve vagrant docs
  • Loading branch information
neykov authored and nacx committed Mar 28, 2017
1 parent 57690d2 commit 8475e633542308277f8bc9b7b9c1cb221b691662
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 9 deletions.
@@ -89,9 +89,26 @@ Testing

vagrant box add ubuntu/xenial64
vagrant box add ubuntu/trusty64
# Refer to the "Windows boxes" section below on how to create the "boxcutter/eval-win7x86-enterprise" image (optional)
mvn clean install -Plive

Windows boxes

The easiest way to create a Windows Vagrant test image is using the [boxcutter-windows](
packer templates.

brew install packer # or the corresponding alternative for your distribution
git clone boxcutter-windows
cd boxcutter-windows
make virtualbox/eval-win2012r2-standard
vagrant box add boxcutter/eval-win2012r2-standard ./box/virtualbox/

Cleaning up

@@ -27,7 +27,7 @@

<name>Vagrant provider</name>
<name>jclouds Vagrant provider</name>

@@ -27,6 +27,75 @@

* <p>
* The provider serves the following purposes:
* <ol>
* <li>holds information that's not available elsewhere - hostname and IPs</li>
* <li>cache of available machines</li>
* <li>cache of the machine state</li>
* </ol>
* <p>
* To expand on each one:
* <p>
* 1. Hostname and IPs of the machine are fetched on boot using vagrant's provisioning scripts.
* There are a couple of reasons for that. First vagrant calls are very expensive (relatively
* for a local call). Each exec takes at least several seconds. Integrating them with the boot
* saves a couple of ssh calls. Second the windows winrm transport is available only through the
* provisioning scripts. Can't call "vagrant powershell " later. This makes the information
* available only when creating the machine.
* <p>
* Possible solutions:
* <ul>
* <li>
* Store those in the yaml file that's already being created, containing the machine specs
* to be passed to the Vagrantfile script. We are already storing some additional info in there
* like imageId and hardwareId. A drawback is that the information could change
* so those values would become stale.
* </li>
* <li>
* Query the machine when we need them. Not possible with Windows; not possible if the machine
* is halted.
* </li>
* <li>
* Keep them as is (in memory only). When the process stops the information is lost. On a new
* start if doesn't know the hostname and IPs. Depending on the intended usage of the provider
* could be enough.
* Possibly a combination of the above would work best, depending on the OS. Perhaps coupled
* with a refreshing mechanism.
* The file could store other information like the tags and the metadata.
* </li>
* </ul>
* <p>
* 2. Existing machines list can be reconstructed easily - just listing the files on the disk.
* Worth mentioning that machines created by jclouds follow some conventions. Manually
* created machines are not considered. The provider creates a yaml file describing the requirements
* and some meta, then a generic Vagrantfile reads those and creates a machine based on them.
* Presently the provider is only interested in machines it creates or machines created
* from previous runs. That's a local "service" and no concurrent modifications of the machines
* is expected. There could be parallel processes running but still each one would
* manage its own machines. That's even strongly discouraged that since virtualbox (vboxmanage) has
* problems when it's executed in parallel. Currently the vagrant bindings explicitly serialise
* execs of vagrant.
* <p>
* 3. Machine status can reliably be inferred. The key here is that the vagrant commands are
* synchronous. If "vagrant up" completes successfully then the status is RUNNING. If it fails
* an exception propagates and signals an error. This makes it possible to save on expensive
* state polling. It gets more obvious when several machines are spun up in parallel. Since
* vagrant commands are executed sequentially a vagrant up would block other vagrant status
* commands for quite a while.
* Possible improvements: time out the status value, refreshing it after some period on request
* <p>
* The registry allows us to really streamline machine creation. All it takes is a single
* "vagrant up". It needs around a minute to return a usable machine (obviously depends on the
* image and is dominated by OS boot). Whereas before introducing the registry it would take
* at least 50% more. And it gets worse with the more machines being created in parallel.
* <p>
* Expiring (and refreshing) machine list while running might not be wanted - would result in
* parallel execution of vagrant command against another's process machines. Virtualbox (vboxmanage)
* fails indeterministically when executed in parallel. Expiring the status would be a nice
* improvement.
public class VagrantNodeRegistry {

@@ -20,7 +20,6 @@
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;

import java.util.NoSuchElementException;
import java.util.Set;

import org.jclouds.compute.ComputeService;
@@ -44,8 +43,8 @@
* Building the image:
* $ git clone boxcutter-windows
* $ cd boxcutter-windows
* $ make virtualbox/eval-win7x86-enterprise
* $ vagrant box add boxcutter/eval-win7x86-enterprise box/virtualbox/
* $ make virtualbox/eval-win2012r2-standard
* $ vagrant box add boxcutter/eval-win2012r2-standard ./box/virtualbox/
@Test(groups = "live", singleThreaded = true, enabled = true, testName = "WindowsLiveTest")
public class WindowsLiveTest extends BaseComputeServiceContextLiveTest {
@@ -60,6 +59,7 @@ public WindowsLiveTest() {
protected void initializeContext() {
client = view.getComputeService();

protected TemplateBuilder templateBuilder() {
@@ -81,8 +81,6 @@ protected Template buildTemplate(TemplateBuilder templateBuilder) {

public void testGet() throws Exception {

Set<? extends NodeMetadata> nodes = client.createNodesInGroup("vagrant-win", 1, buildTemplate(templateBuilder()));
NodeMetadata node = Iterables.getOnlyElement(nodes);
OperatingSystem os = node.getOperatingSystem();
@@ -99,8 +97,6 @@ public void testGet() throws Exception {

public void testBoxConfig() {

Image image = view.getComputeService().getImage(getImageId());

BoxConfig.Factory boxConfigFactory = new BoxConfig.Factory();
@@ -111,7 +107,7 @@ public void testBoxConfig() {

private void skipIfImageNotPresent() {
Image image = view.getComputeService().getImage(getImageId());
Image image = client.getImage(getImageId());
if (image == null) {
throw new SkipException("Image " + getImageId() + " not available. Skipping windows tests.");

0 comments on commit 8475e63

Please sign in to comment.