You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by na...@apache.org on 2017/02/01 11:02:55 UTC

jclouds-labs git commit: Load existing machines info on startup

Repository: jclouds-labs
Updated Branches:
  refs/heads/2.0.x a5a4f30b1 -> e4c809dbd


Load existing machines info on startup

* Lets jclouds manage vagrant machines from previous runs.
* Update README, removing fixed limitations - vagrant user no longer shared with other providers.
* Remove null checks in guice managed constructors


Project: http://git-wip-us.apache.org/repos/asf/jclouds-labs/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds-labs/commit/e4c809db
Tree: http://git-wip-us.apache.org/repos/asf/jclouds-labs/tree/e4c809db
Diff: http://git-wip-us.apache.org/repos/asf/jclouds-labs/diff/e4c809db

Branch: refs/heads/2.0.x
Commit: e4c809dbd60eedec509610eac759b2c3400b2a9e
Parents: a5a4f30
Author: Svetoslav Neykov <sv...@neykov.name>
Authored: Sun Jan 29 19:13:52 2017 +0200
Committer: Ignasi Barrera <na...@apache.org>
Committed: Wed Feb 1 12:01:44 2017 +0100

----------------------------------------------------------------------
 vagrant/README.md                               |   1 -
 .../jclouds/vagrant/api/VagrantApiFacade.java   |   9 +-
 .../vagrant/api/VagrantBoxApiFacade.java        |  28 ++++
 .../compute/VagrantComputeServiceAdapter.java   |  82 ++++------
 .../config/PersistVagrantCredentialsModule.java |   8 +-
 .../VagrantComputeServiceContextModule.java     |  28 +++-
 .../org/jclouds/vagrant/domain/VagrantNode.java |   4 +
 .../jclouds/vagrant/functions/BoxToImage.java   |   4 +-
 .../functions/MachineToNodeMetadata.java        |  47 +-----
 .../jclouds/vagrant/internal/ImageSupplier.java |  55 +++++++
 .../jclouds/vagrant/internal/MachineConfig.java |   9 +-
 .../vagrant/internal/VagrantCliFacade.java      |  18 ++-
 .../internal/VagrantExistingMachines.java       | 155 +++++++++++++++++++
 .../vagrant/internal/VagrantNodeRegistry.java   |  41 ++++-
 .../VagrantDefaultImageCredentials.java         |   5 +-
 .../functions/MachineToNodeMetadataTest.java    |  79 +---------
 .../vagrant/internal/VagrantNodeLoaderTest.java | 116 ++++++++++++++
 .../internal/VagrantNodeRegistryTest.java       |  12 +-
 18 files changed, 489 insertions(+), 212 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e4c809db/vagrant/README.md
----------------------------------------------------------------------
diff --git a/vagrant/README.md b/vagrant/README.md
index 3fa71a3..36194dd 100644
--- a/vagrant/README.md
+++ b/vagrant/README.md
@@ -119,4 +119,3 @@ Limitations
 -----------
 
 * Machines are created sequentially, no support for parallel execution from virtualbox provider
-* Something prevents using vagrant at the same time with other jclouds providers - they try to login with vagrant user.

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e4c809db/vagrant/src/main/java/org/jclouds/vagrant/api/VagrantApiFacade.java
----------------------------------------------------------------------
diff --git a/vagrant/src/main/java/org/jclouds/vagrant/api/VagrantApiFacade.java b/vagrant/src/main/java/org/jclouds/vagrant/api/VagrantApiFacade.java
index c3bccfd..d87cedb 100644
--- a/vagrant/src/main/java/org/jclouds/vagrant/api/VagrantApiFacade.java
+++ b/vagrant/src/main/java/org/jclouds/vagrant/api/VagrantApiFacade.java
@@ -17,13 +17,12 @@
 package org.jclouds.vagrant.api;
 
 import java.io.File;
-import java.util.Collection;
 
 import org.jclouds.domain.LoginCredentials;
 
-public interface VagrantApiFacade<B> {
-   interface Factory<B> {
-      VagrantApiFacade<B> create(File path);
+public interface VagrantApiFacade {
+   interface Factory {
+      VagrantApiFacade create(File path);
    }
 
    /**
@@ -35,8 +34,6 @@ public interface VagrantApiFacade<B> {
    void halt(String machineName);
    void destroy(String machineName);
    LoginCredentials sshConfig(String machineName);
-   Collection<B> listBoxes();
-   B getBox(String boxName);
    void haltForced(String name);
    boolean exists();
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e4c809db/vagrant/src/main/java/org/jclouds/vagrant/api/VagrantBoxApiFacade.java
----------------------------------------------------------------------
diff --git a/vagrant/src/main/java/org/jclouds/vagrant/api/VagrantBoxApiFacade.java b/vagrant/src/main/java/org/jclouds/vagrant/api/VagrantBoxApiFacade.java
new file mode 100644
index 0000000..90844ce
--- /dev/null
+++ b/vagrant/src/main/java/org/jclouds/vagrant/api/VagrantBoxApiFacade.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.vagrant.api;
+
+import java.util.Collection;
+
+public interface VagrantBoxApiFacade<B> {
+   interface Factory<B> {
+      VagrantBoxApiFacade<B> create();
+   }
+
+   Collection<B> listBoxes();
+   B getBox(String boxName);
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e4c809db/vagrant/src/main/java/org/jclouds/vagrant/compute/VagrantComputeServiceAdapter.java
----------------------------------------------------------------------
diff --git a/vagrant/src/main/java/org/jclouds/vagrant/compute/VagrantComputeServiceAdapter.java b/vagrant/src/main/java/org/jclouds/vagrant/compute/VagrantComputeServiceAdapter.java
index 665504f..2f19b3e 100644
--- a/vagrant/src/main/java/org/jclouds/vagrant/compute/VagrantComputeServiceAdapter.java
+++ b/vagrant/src/main/java/org/jclouds/vagrant/compute/VagrantComputeServiceAdapter.java
@@ -16,12 +16,9 @@
  */
 package org.jclouds.vagrant.compute;
 
-import static com.google.common.base.Preconditions.checkNotNull;
-
 import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
@@ -59,12 +56,11 @@ import com.google.common.base.Function;
 import com.google.common.base.Predicate;
 import com.google.common.base.Supplier;
 import com.google.common.base.Throwables;
-import com.google.common.collect.FluentIterable;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
 
-public class VagrantComputeServiceAdapter<B> implements ComputeServiceAdapter<VagrantNode, Hardware, B, Location> {
+public class VagrantComputeServiceAdapter implements ComputeServiceAdapter<VagrantNode, Hardware, Image, Location> {
    private static final Pattern PATTERN_IP_ADDR = Pattern.compile("inet ([0-9\\.]+)/(\\d+)");
    private static final Pattern PATTERN_IPCONFIG = Pattern.compile("IPv4 Address[ .]+: ([0-9\\.]+)");
 
@@ -75,25 +71,28 @@ public class VagrantComputeServiceAdapter<B> implements ComputeServiceAdapter<Va
    private final JustProvider locationSupplier;
    private final VagrantNodeRegistry nodeRegistry;
    private final MachineConfig.Factory machineConfigFactory;
-   private final Function<Collection<B>, Collection<B>> outdatedBoxesFilter;
-   private final VagrantApiFacade.Factory<B> cliFactory;
+   private final VagrantApiFacade.Factory cliFactory;
    private final Supplier<? extends Map<String, Hardware>> hardwareSupplier;
+   private final Supplier<Collection<Image>> imageListSupplier;
+   private final Function<String, Image> imageIdToImage;
 
    @Inject
    VagrantComputeServiceAdapter(@Named(VagrantConstants.JCLOUDS_VAGRANT_HOME) String home,
          JustProvider locationSupplier,
          VagrantNodeRegistry nodeRegistry,
          MachineConfig.Factory machineConfigFactory,
-         Function<Collection<B>, Collection<B>> outdatedBoxesFilter,
-         VagrantApiFacade.Factory<B> cliFactory,
-         Supplier<? extends Map<String, Hardware>> hardwareSupplier) {
-      this.home = new File(checkNotNull(home, "home"));
-      this.locationSupplier = checkNotNull(locationSupplier, "locationSupplier");
-      this.nodeRegistry = checkNotNull(nodeRegistry, "nodeRegistry");
-      this.machineConfigFactory = checkNotNull(machineConfigFactory, "machineConfigFactory");
-      this.outdatedBoxesFilter = checkNotNull(outdatedBoxesFilter, "outdatedBoxesFilter");
-      this.cliFactory = checkNotNull(cliFactory, "cliFactory");
-      this.hardwareSupplier = checkNotNull(hardwareSupplier, "hardwareSupplier");
+         VagrantApiFacade.Factory cliFactory,
+         Supplier<? extends Map<String, Hardware>> hardwareSupplier,
+         Supplier<Collection<Image>> imageListSupplier,
+         Function<String, Image> imageIdToImage) {
+      this.home = new File(home);
+      this.locationSupplier = locationSupplier;
+      this.nodeRegistry = nodeRegistry;
+      this.machineConfigFactory = machineConfigFactory;
+      this.cliFactory = cliFactory;
+      this.hardwareSupplier = hardwareSupplier;
+      this.imageListSupplier = imageListSupplier;
+      this.imageIdToImage = imageIdToImage;
       this.home.mkdirs();
    }
 
@@ -104,14 +103,15 @@ public class VagrantComputeServiceAdapter<B> implements ComputeServiceAdapter<Va
 
       init(nodePath, machineName, template);
 
-      NodeAndInitialCredentials<VagrantNode> node = startMachine(nodePath, group, machineName, template.getImage());
+      NodeAndInitialCredentials<VagrantNode> node = startMachine(nodePath, group, machineName,
+            template.getImage(), template.getHardware());
       nodeRegistry.add(node.getNode());
       return node;
    }
 
-   private NodeAndInitialCredentials<VagrantNode> startMachine(File path, String group, String name, Image image) {
+   private NodeAndInitialCredentials<VagrantNode> startMachine(File path, String group, String name, Image image, Hardware hardware) {
 
-      VagrantApiFacade<B> vagrant = cliFactory.create(path);
+      VagrantApiFacade vagrant = cliFactory.create(path);
       String rawOutput = vagrant.up(name);
       String output = normalizeOutput(name, rawOutput);
 
@@ -123,6 +123,7 @@ public class VagrantComputeServiceAdapter<B> implements ComputeServiceAdapter<Va
             .setGroup(group)
             .setName(name)
             .setImage(image)
+            .setHardware(hardware)
             .setNetworks(getNetworks(output, getOsInterfacePattern(osFamily)))
             .setHostname(getHostname(output))
             .build();
@@ -250,14 +251,13 @@ public class VagrantComputeServiceAdapter<B> implements ComputeServiceAdapter<Va
    }
 
    @Override
-   public Iterable<B> listImages() {
-      Collection<B> allBoxes = cliFactory.create(new File(".")).listBoxes();
-      return outdatedBoxesFilter.apply(allBoxes);
+   public Iterable<Image> listImages() {
+      return imageListSupplier.get();
    }
 
    @Override
-   public B getImage(String id) {
-      return cliFactory.create(new File(".")).getBox(id);
+   public Image getImage(String id) {
+      return imageIdToImage.apply(id);
    }
 
    @Override
@@ -309,14 +309,14 @@ public class VagrantComputeServiceAdapter<B> implements ComputeServiceAdapter<Va
 
       VagrantNode node = nodeRegistry.get(id);
       String name = node.name();
-      VagrantApiFacade<B> vagrant = getMachine(node);
+      VagrantApiFacade vagrant = getMachine(node);
       vagrant.up(name);
    }
 
    private void halt(String id) {
       VagrantNode node = nodeRegistry.get(id);
       String name = node.name();
-      VagrantApiFacade<B> vagrant = getMachine(node);
+      VagrantApiFacade vagrant = getMachine(node);
 
       try {
          vagrant.halt(name);
@@ -330,7 +330,7 @@ public class VagrantComputeServiceAdapter<B> implements ComputeServiceAdapter<Va
    public void resumeNode(String id) {
       VagrantNode node = nodeRegistry.get(id);
       String name = node.name();
-      VagrantApiFacade<B> vagrant = getMachine(node);
+      VagrantApiFacade vagrant = getMachine(node);
       vagrant.up(name);
       node.setMachineState(Status.RUNNING);
    }
@@ -344,29 +344,7 @@ public class VagrantComputeServiceAdapter<B> implements ComputeServiceAdapter<Va
 
    @Override
    public Iterable<VagrantNode> listNodes() {
-      return FluentIterable.from(Arrays.asList(home.listFiles()))
-            .transformAndConcat(new Function<File, Collection<VagrantNode>>() {
-               @Override
-               public Collection<VagrantNode> apply(File input) {
-                  File machines = new File(input, VagrantConstants.MACHINES_CONFIG_SUBFOLDER);
-                  VagrantApiFacade<B> vagrant = cliFactory.create(input);
-                  if (input.isDirectory() && machines.exists() && vagrant.exists()) {
-                     Collection<VagrantNode> nodes = new ArrayList<VagrantNode>();
-                     for (File machine : machines.listFiles()) {
-                        if (machine.getName().endsWith(VagrantConstants.MACHINES_CONFIG_EXTENSION)) {
-                           String id = input.getName() + "/" + machine.getName().replace(VagrantConstants.MACHINES_CONFIG_EXTENSION, "");
-                           VagrantNode n = nodeRegistry.get(id);
-                           if (n != null) {
-                              nodes.add(n);
-                           }
-                        }
-                     }
-                     return nodes;
-                  } else {
-                     return ImmutableList.of();
-                  }
-               }
-            });
+      return nodeRegistry.list();
    }
 
    @Override
@@ -379,7 +357,7 @@ public class VagrantComputeServiceAdapter<B> implements ComputeServiceAdapter<Va
       });
    }
 
-   private VagrantApiFacade<B> getMachine(VagrantNode node) {
+   private VagrantApiFacade getMachine(VagrantNode node) {
       File nodePath = node.path();
       return cliFactory.create(nodePath);
    }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e4c809db/vagrant/src/main/java/org/jclouds/vagrant/config/PersistVagrantCredentialsModule.java
----------------------------------------------------------------------
diff --git a/vagrant/src/main/java/org/jclouds/vagrant/config/PersistVagrantCredentialsModule.java b/vagrant/src/main/java/org/jclouds/vagrant/config/PersistVagrantCredentialsModule.java
index d140b76..cd79882 100644
--- a/vagrant/src/main/java/org/jclouds/vagrant/config/PersistVagrantCredentialsModule.java
+++ b/vagrant/src/main/java/org/jclouds/vagrant/config/PersistVagrantCredentialsModule.java
@@ -16,8 +16,6 @@
  */
 package org.jclouds.vagrant.config;
 
-import static com.google.common.base.Preconditions.checkNotNull;
-
 import java.io.File;
 import java.io.IOException;
 import java.util.Map;
@@ -59,10 +57,10 @@ public class PersistVagrantCredentialsModule extends AbstractModule {
             Map<String, Credentials> credentialStore,
             @Nullable @Assisted Statement statement,
             MachineConfig.Factory machineConfigFactory) {
-         this.vagrantNodeRegistry = checkNotNull(vagrantNodeRegistry, "vagrantNodeRegistry");
-         this.credentialStore = checkNotNull(credentialStore, "credentialStore");
+         this.vagrantNodeRegistry = vagrantNodeRegistry;
+         this.credentialStore = credentialStore;
          this.statement = statement;
-         this.machineConfigFactory = checkNotNull(machineConfigFactory, "machineConfigFactory");
+         this.machineConfigFactory = machineConfigFactory;
       }
 
       @Override

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e4c809db/vagrant/src/main/java/org/jclouds/vagrant/config/VagrantComputeServiceContextModule.java
----------------------------------------------------------------------
diff --git a/vagrant/src/main/java/org/jclouds/vagrant/config/VagrantComputeServiceContextModule.java b/vagrant/src/main/java/org/jclouds/vagrant/config/VagrantComputeServiceContextModule.java
index 61f30fd..bb122e4 100644
--- a/vagrant/src/main/java/org/jclouds/vagrant/config/VagrantComputeServiceContextModule.java
+++ b/vagrant/src/main/java/org/jclouds/vagrant/config/VagrantComputeServiceContextModule.java
@@ -32,12 +32,15 @@ import org.jclouds.date.TimeStamp;
 import org.jclouds.domain.Location;
 import org.jclouds.functions.IdentityFunction;
 import org.jclouds.vagrant.api.VagrantApiFacade;
+import org.jclouds.vagrant.api.VagrantBoxApiFacade;
 import org.jclouds.vagrant.compute.VagrantComputeServiceAdapter;
 import org.jclouds.vagrant.domain.VagrantNode;
 import org.jclouds.vagrant.functions.BoxToImage;
 import org.jclouds.vagrant.functions.MachineToNodeMetadata;
 import org.jclouds.vagrant.functions.OutdatedBoxesFilter;
+import org.jclouds.vagrant.internal.ImageSupplier;
 import org.jclouds.vagrant.internal.VagrantCliFacade;
+import org.jclouds.vagrant.internal.VagrantExistingMachines;
 import org.jclouds.vagrant.internal.VagrantWireLogger;
 import org.jclouds.vagrant.strategy.VagrantDefaultImageCredentials;
 import org.jclouds.vagrant.suppliers.VagrantHardwareSupplier;
@@ -53,28 +56,39 @@ import com.google.inject.assistedinject.FactoryModuleBuilder;
 import vagrant.api.CommandIOListener;
 import vagrant.api.domain.Box;
 
-public class VagrantComputeServiceContextModule extends ComputeServiceAdapterContextModule<VagrantNode, Hardware, Box, Location> {
+public class VagrantComputeServiceContextModule extends ComputeServiceAdapterContextModule<VagrantNode, Hardware, Image, Location> {
 
    @Override
    protected void configure() {
       super.configure();
-      bind(new TypeLiteral<ComputeServiceAdapter<VagrantNode, Hardware, Box, Location>>() {
-      }).to(new TypeLiteral<VagrantComputeServiceAdapter<Box>>() {});
+      bind(new TypeLiteral<ComputeServiceAdapter<VagrantNode, Hardware, Image, Location>>() {
+      }).to(VagrantComputeServiceAdapter.class);
       bind(new TypeLiteral<Function<VagrantNode, NodeMetadata>>() {
       }).to(MachineToNodeMetadata.class);
       bind(new TypeLiteral<Function<Box, Image>>() {
       }).to(BoxToImage.class);
       bind(new TypeLiteral<Supplier<? extends Map<String, Hardware>>>() {
       }).to(VagrantHardwareSupplier.class).in(Singleton.class);
+      bind(new TypeLiteral<Function<Collection<Box>, Collection<Box>>>() {
+      }).to(OutdatedBoxesFilter.class);
       bind(new TypeLiteral<Function<Hardware, Hardware>>() {
       }).to(this.<Hardware>castIdentityFunction());
       bind(new TypeLiteral<Function<Location, Location>>() {
       }).to(this.<Location>castIdentityFunction());
-      bind(new TypeLiteral<Function<Collection<Box>, Collection<Box>>>() {
-      }).to(OutdatedBoxesFilter.class);
+      bind(new TypeLiteral<Function<Image, Image>>() {
+      }).to(this.<Image>castIdentityFunction());
+      bind(new TypeLiteral<Supplier<Collection<Image>>>() {
+      }).to(new TypeLiteral<ImageSupplier<Box>>() {});
+      bind(new TypeLiteral<Function<String, Image>>() {
+      }).to(new TypeLiteral<ImageSupplier<Box>>() {});
+      bind(new TypeLiteral<Supplier<Collection<VagrantNode>>>() {
+      }).to(VagrantExistingMachines.class);
+      install(new FactoryModuleBuilder()
+            .implement(VagrantApiFacade.class, VagrantCliFacade.class)
+            .build(VagrantApiFacade.Factory.class));
       install(new FactoryModuleBuilder()
-            .implement(new TypeLiteral<VagrantApiFacade<Box>>() {}, VagrantCliFacade.class)
-            .build(new TypeLiteral<VagrantApiFacade.Factory<Box>>() {}));
+            .implement(new TypeLiteral<VagrantBoxApiFacade<Box>>() {}, VagrantCliFacade.class)
+            .build(new TypeLiteral<VagrantBoxApiFacade.Factory<Box>>() {}));
       bind(PopulateDefaultLoginCredentialsForImageStrategy.class).to(VagrantDefaultImageCredentials.class);
       bind(TemplateBuilderImpl.class).to(ArbitraryCpuRamTemplateBuilderImpl.class);
       bind(CommandIOListener.class).to(VagrantWireLogger.class).in(Singleton.class);

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e4c809db/vagrant/src/main/java/org/jclouds/vagrant/domain/VagrantNode.java
----------------------------------------------------------------------
diff --git a/vagrant/src/main/java/org/jclouds/vagrant/domain/VagrantNode.java b/vagrant/src/main/java/org/jclouds/vagrant/domain/VagrantNode.java
index cfb02ca..66ef095 100644
--- a/vagrant/src/main/java/org/jclouds/vagrant/domain/VagrantNode.java
+++ b/vagrant/src/main/java/org/jclouds/vagrant/domain/VagrantNode.java
@@ -19,6 +19,7 @@ package org.jclouds.vagrant.domain;
 import java.io.File;
 import java.util.Collection;
 
+import org.jclouds.compute.domain.Hardware;
 import org.jclouds.compute.domain.Image;
 import org.jclouds.compute.domain.NodeMetadata.Status;
 
@@ -39,6 +40,8 @@ public abstract class VagrantNode {
 
    public abstract Image image();
 
+   public abstract Hardware hardware();
+
    public abstract Collection<String> networks();
 
    public abstract String hostname();
@@ -54,6 +57,7 @@ public abstract class VagrantNode {
       public abstract Builder setGroup(String group);
       public abstract Builder setName(String name);
       public abstract Builder setImage(Image image);
+      public abstract Builder setHardware(Hardware hardware);
       public abstract Builder setNetworks(Collection<String> networks);
       public abstract Builder setHostname(String hostname);
       public abstract VagrantNode build();

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e4c809db/vagrant/src/main/java/org/jclouds/vagrant/functions/BoxToImage.java
----------------------------------------------------------------------
diff --git a/vagrant/src/main/java/org/jclouds/vagrant/functions/BoxToImage.java b/vagrant/src/main/java/org/jclouds/vagrant/functions/BoxToImage.java
index 1fd77fa..bf0f155 100644
--- a/vagrant/src/main/java/org/jclouds/vagrant/functions/BoxToImage.java
+++ b/vagrant/src/main/java/org/jclouds/vagrant/functions/BoxToImage.java
@@ -16,8 +16,6 @@
  */
 package org.jclouds.vagrant.functions;
 
-import static com.google.common.base.Preconditions.checkNotNull;
-
 import org.jclouds.compute.domain.Image;
 import org.jclouds.compute.domain.Image.Status;
 import org.jclouds.compute.domain.ImageBuilder;
@@ -38,7 +36,7 @@ public class BoxToImage implements Function<Box, Image> {
 
    @Inject
    BoxToImage(BoxConfig.Factory boxConfigFactory) {
-      this.boxConfigFactory = checkNotNull(boxConfigFactory, "boxConfigFactory");
+      this.boxConfigFactory = boxConfigFactory;
    }
 
    @Override

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e4c809db/vagrant/src/main/java/org/jclouds/vagrant/functions/MachineToNodeMetadata.java
----------------------------------------------------------------------
diff --git a/vagrant/src/main/java/org/jclouds/vagrant/functions/MachineToNodeMetadata.java b/vagrant/src/main/java/org/jclouds/vagrant/functions/MachineToNodeMetadata.java
index 298b7cc..755bc50 100644
--- a/vagrant/src/main/java/org/jclouds/vagrant/functions/MachineToNodeMetadata.java
+++ b/vagrant/src/main/java/org/jclouds/vagrant/functions/MachineToNodeMetadata.java
@@ -16,28 +16,19 @@
  */
 package org.jclouds.vagrant.functions;
 
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.util.Map;
 import java.util.Set;
 
 import org.jclouds.collect.Memoized;
-import org.jclouds.compute.domain.Hardware;
-import org.jclouds.compute.domain.HardwareBuilder;
 import org.jclouds.compute.domain.Image;
 import org.jclouds.compute.domain.NodeMetadata;
 import org.jclouds.compute.domain.NodeMetadataBuilder;
 import org.jclouds.compute.domain.OsFamily;
-import org.jclouds.compute.domain.Processor;
-import org.jclouds.compute.util.AutomaticHardwareIdSpec;
 import org.jclouds.domain.Location;
 import org.jclouds.vagrant.domain.VagrantNode;
 import org.jclouds.vagrant.internal.BoxConfig;
-import org.jclouds.vagrant.internal.MachineConfig;
 import org.jclouds.vagrant.reference.VagrantConstants;
 
 import com.google.common.base.Function;
-import com.google.common.base.Optional;
 import com.google.common.base.Supplier;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
@@ -46,19 +37,13 @@ import com.google.inject.Inject;
 public class MachineToNodeMetadata implements Function<VagrantNode, NodeMetadata> {
    private final Location location;
    private final BoxConfig.Factory boxConfigFactory;
-   private final MachineConfig.Factory machineConfigFactory;
-   private final Supplier<? extends Map<String, Hardware>> hardwareSupplier;
 
    @Inject
    MachineToNodeMetadata(
          @Memoized Supplier<Set<? extends Location>> locations,
-         BoxConfig.Factory boxConfigFactory,
-         MachineConfig.Factory machineConfigFactory,
-         Supplier<? extends Map<String, Hardware>> hardwareSupplier) {
-      this.location = Iterables.getOnlyElement(checkNotNull(locations, "locations").get());
-      this.boxConfigFactory = checkNotNull(boxConfigFactory, "boxConfigFactory");
-      this.machineConfigFactory = checkNotNull(machineConfigFactory, "machineConfigFactory");
-      this.hardwareSupplier = checkNotNull(hardwareSupplier, "hardwareSupplier");
+         BoxConfig.Factory boxConfigFactory) {
+      this.location = Iterables.getOnlyElement(locations.get());
+      this.boxConfigFactory = boxConfigFactory;
    }
 
    @Override
@@ -69,7 +54,7 @@ public class MachineToNodeMetadata implements Function<VagrantNode, NodeMetadata
             .group(node.group())
             .imageId(node.image().getId())
             .location(location)
-            .hardware(getHardware(node))
+            .hardware(node.hardware())
             .operatingSystem(node.image().getOperatingSystem())
             .hostname(node.name())
             .status(node.machineState())
@@ -82,30 +67,6 @@ public class MachineToNodeMetadata implements Function<VagrantNode, NodeMetadata
       return nodeMetadataBuilder.build();
    }
 
-   private Hardware getHardware(VagrantNode node) {
-      MachineConfig machineConfig = machineConfigFactory.newInstance(node);
-
-      Map<String, Object> config = machineConfig.load();
-      String hardwareId = config.get(VagrantConstants.CONFIG_HARDWARE_ID).toString();
-      if (hardwareId.equals(VagrantConstants.MACHINES_AUTO_HARDWARE)) {
-         double cpus = Double.parseDouble(config.get(VagrantConstants.CONFIG_CPUS).toString());
-         int memory = Integer.parseInt(config.get(VagrantConstants.CONFIG_MEMORY).toString());
-         AutomaticHardwareIdSpec hardwareSpec = AutomaticHardwareIdSpec.automaticHardwareIdSpecBuilder(cpus, memory, Optional.<Float>absent());
-         return new HardwareBuilder()
-               .id(hardwareSpec.toString())
-               .providerId(hardwareSpec.toString())
-               .processor(new Processor(cpus, 1.0))
-               .ram(memory)
-               .build();
-      } else {
-         Hardware hardware = hardwareSupplier.get().get(hardwareId);
-         if (hardware == null) {
-            throw new IllegalStateException("Unsupported hardwareId " + hardwareId + " for machine " + node.id());
-         }
-         return hardware;
-      }
-   }
-
    private int getLoginPort(Image image) {
       BoxConfig config = boxConfigFactory.newInstance(image);
       String port;

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e4c809db/vagrant/src/main/java/org/jclouds/vagrant/internal/ImageSupplier.java
----------------------------------------------------------------------
diff --git a/vagrant/src/main/java/org/jclouds/vagrant/internal/ImageSupplier.java b/vagrant/src/main/java/org/jclouds/vagrant/internal/ImageSupplier.java
new file mode 100644
index 0000000..fc1c823
--- /dev/null
+++ b/vagrant/src/main/java/org/jclouds/vagrant/internal/ImageSupplier.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.vagrant.internal;
+
+import java.util.Collection;
+
+import org.jclouds.compute.domain.Image;
+import org.jclouds.vagrant.api.VagrantBoxApiFacade;
+
+import com.google.common.base.Function;
+import com.google.common.base.Supplier;
+import com.google.common.collect.Collections2;
+import com.google.inject.Inject;
+
+public class ImageSupplier<B> implements Supplier<Collection<Image>>, Function<String, Image> {
+   private final Function<Collection<B>, Collection<B>> outdatedBoxesFilter;
+   private final VagrantBoxApiFacade.Factory<B> cliFactory;
+   private final Function<B, Image> boxToImage;
+
+   @Inject
+   ImageSupplier(Function<Collection<B>, Collection<B>> outdatedBoxesFilter,
+         VagrantBoxApiFacade.Factory<B> cliFactory,
+         Function<B, Image> boxToImage) {
+      this.outdatedBoxesFilter = outdatedBoxesFilter;
+      this.cliFactory = cliFactory;
+      this.boxToImage = boxToImage;
+   }
+
+   @Override
+   public Collection<Image> get() {
+      Collection<B> boxes = outdatedBoxesFilter.apply(cliFactory.create().listBoxes());
+      return Collections2.transform(boxes, boxToImage);
+   }
+
+   @Override
+   public Image apply(String id) {
+      B box = cliFactory.create().getBox(id);
+      return boxToImage.apply(box);
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e4c809db/vagrant/src/main/java/org/jclouds/vagrant/internal/MachineConfig.java
----------------------------------------------------------------------
diff --git a/vagrant/src/main/java/org/jclouds/vagrant/internal/MachineConfig.java b/vagrant/src/main/java/org/jclouds/vagrant/internal/MachineConfig.java
index 8f23d87..fdf9c02 100644
--- a/vagrant/src/main/java/org/jclouds/vagrant/internal/MachineConfig.java
+++ b/vagrant/src/main/java/org/jclouds/vagrant/internal/MachineConfig.java
@@ -41,8 +41,8 @@ import com.google.common.collect.Maps;
 
 public class MachineConfig {
    public static class Factory {
-      public MachineConfig newInstance(File path, String name) {
-         return new MachineConfig(path, name);
+      public MachineConfig newInstance(File group, String machineName) {
+         return new MachineConfig(group, machineName);
       }
 
       public MachineConfig newInstance(VagrantNode node) {
@@ -52,8 +52,9 @@ public class MachineConfig {
 
    private File configPath;
 
-   protected MachineConfig(File path, String name) {
-      this.configPath = new File(new File(path, VagrantConstants.MACHINES_CONFIG_SUBFOLDER), name + ".yaml");
+   protected MachineConfig(File group, String machineName) {
+      this.configPath = new File(new File(group, VagrantConstants.MACHINES_CONFIG_SUBFOLDER),
+            machineName + VagrantConstants.MACHINES_CONFIG_EXTENSION);
    }
 
    public Map<String, Object> load() {

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e4c809db/vagrant/src/main/java/org/jclouds/vagrant/internal/VagrantCliFacade.java
----------------------------------------------------------------------
diff --git a/vagrant/src/main/java/org/jclouds/vagrant/internal/VagrantCliFacade.java b/vagrant/src/main/java/org/jclouds/vagrant/internal/VagrantCliFacade.java
index 26d592f..8c32e43 100644
--- a/vagrant/src/main/java/org/jclouds/vagrant/internal/VagrantCliFacade.java
+++ b/vagrant/src/main/java/org/jclouds/vagrant/internal/VagrantCliFacade.java
@@ -16,22 +16,20 @@
  */
 package org.jclouds.vagrant.internal;
 
-import static com.google.common.base.Preconditions.checkNotNull;
-
 import java.io.File;
 import java.io.IOException;
 import java.nio.charset.Charset;
 import java.util.Collection;
 
-import javax.inject.Inject;
-
 import org.jclouds.domain.LoginCredentials;
 import org.jclouds.vagrant.api.VagrantApiFacade;
+import org.jclouds.vagrant.api.VagrantBoxApiFacade;
 
 import com.google.common.base.Predicate;
 import com.google.common.collect.Iterables;
 import com.google.common.io.Files;
 import com.google.inject.assistedinject.Assisted;
+import com.google.inject.assistedinject.AssistedInject;
 
 import vagrant.Vagrant;
 import vagrant.api.CommandIOListener;
@@ -39,16 +37,22 @@ import vagrant.api.VagrantApi;
 import vagrant.api.domain.Box;
 import vagrant.api.domain.SshConfig;
 
-public class VagrantCliFacade implements VagrantApiFacade<Box> {
+public class VagrantCliFacade implements VagrantApiFacade, VagrantBoxApiFacade<Box> {
    private final VagrantApi vagrant;
    private final VagrantOutputRecorder outputRecorder;
 
-   @Inject
+   @AssistedInject
    VagrantCliFacade(CommandIOListener wireLogger, @Assisted File path) {
-      this.outputRecorder = new VagrantOutputRecorder(checkNotNull(wireLogger, "wireLogger"));
+      this.outputRecorder = new VagrantOutputRecorder(wireLogger);
       this.vagrant = Vagrant.forPath(path, outputRecorder);
    }
 
+   @AssistedInject
+   VagrantCliFacade(CommandIOListener wireLogger) {
+      this.outputRecorder = new VagrantOutputRecorder(wireLogger);
+      this.vagrant = Vagrant.forPath(new File("."), outputRecorder);
+   }
+
    @Override
    public String up(String machineName) {
       outputRecorder.record();

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e4c809db/vagrant/src/main/java/org/jclouds/vagrant/internal/VagrantExistingMachines.java
----------------------------------------------------------------------
diff --git a/vagrant/src/main/java/org/jclouds/vagrant/internal/VagrantExistingMachines.java b/vagrant/src/main/java/org/jclouds/vagrant/internal/VagrantExistingMachines.java
new file mode 100644
index 0000000..d8c9604
--- /dev/null
+++ b/vagrant/src/main/java/org/jclouds/vagrant/internal/VagrantExistingMachines.java
@@ -0,0 +1,155 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.vagrant.internal;
+
+import java.io.File;
+import java.util.Collection;
+import java.util.Map;
+
+import javax.annotation.Resource;
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.jclouds.compute.domain.Hardware;
+import org.jclouds.compute.domain.HardwareBuilder;
+import org.jclouds.compute.domain.Image;
+import org.jclouds.compute.domain.Processor;
+import org.jclouds.compute.domain.NodeMetadata.Status;
+import org.jclouds.compute.util.AutomaticHardwareIdSpec;
+import org.jclouds.logging.Logger;
+import org.jclouds.vagrant.domain.VagrantNode;
+import org.jclouds.vagrant.reference.VagrantConstants;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Supplier;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+public class VagrantExistingMachines implements Supplier<Collection<VagrantNode>> {
+   @Resource
+   protected Logger logger = Logger.NULL;
+
+   private final File home;
+   private final MachineConfig.Factory machineConfigFactory;
+   private final Supplier<Collection<Image>> imageLister;
+   private final Supplier<? extends Map<String, Hardware>> hardwareSupplier;
+
+   @Inject
+   VagrantExistingMachines(@Named(VagrantConstants.JCLOUDS_VAGRANT_HOME) String home,
+         MachineConfig.Factory machineConfigFactory,
+         Supplier<Collection<Image>> imageLister,
+         Supplier<? extends Map<String, Hardware>> hardwareSupplier) {
+      this.home = new File(home);
+      this.machineConfigFactory = machineConfigFactory;
+      this.imageLister = imageLister;
+      this.hardwareSupplier = hardwareSupplier;
+   }
+
+   @Override
+   public Collection<VagrantNode> get() {
+      File[] groups = home.listFiles();
+      if (groups == null) return ImmutableList.of();
+      Map<String, Image> images = getImages();
+      Collection<VagrantNode> nodes = Lists.newArrayList();
+      for (File group : groups) {
+         File[] machines = new File(group, VagrantConstants.MACHINES_CONFIG_SUBFOLDER).listFiles();
+         if (machines == null) continue;
+         for (File machine : machines) {
+            if (machine.getName().endsWith(VagrantConstants.MACHINES_CONFIG_EXTENSION)) {
+               try {
+                  VagrantNode node = createMachine(group, machine, images);
+                  if (node != null) {
+                     nodes.add(node);
+                  }
+               } catch (RuntimeException e) {
+                  // Skip image, something is broken about it.
+                  // Most probable cause is that another process just deleted it.
+                  logger.debug("Failed loading machine " + machine.getAbsolutePath() + ". Skipping.", e);
+               }
+            }
+         }
+      }
+      return nodes;
+   }
+
+   private Map<String, Image> getImages() {
+      Collection<Image> images = imageLister.get();
+      Map<String, Image> imageMap = Maps.newHashMap();
+      for (Image image : images) {
+         imageMap.put(image.getId(), image);
+      }
+      return imageMap;
+   }
+
+   // Build minimum viable VagrantNode. Just enough to allow users to halt the machine.
+   // If this is found to be inadequate need to keep the missing information in the config
+   // file as we can't always fetch it at this point (machine is halted or Windows).
+   private VagrantNode createMachine(File group, File machine, Map<String, Image> images) {
+      String machineName = machine.getName().replace(VagrantConstants.MACHINES_CONFIG_EXTENSION, "");
+      String id = group.getName() + "/" + machineName;
+      Map<String, Object> config = machineConfigFactory.newInstance(group, machineName).load();
+      String imageName = (String) config.get(VagrantConstants.CONFIG_BOX);
+      Image image = images.get(imageName);
+      if (image == null) {
+         // Machine is unusable if its image is not available, can't be running or started.
+         logger.debug("Skipping machine " + machine.getAbsolutePath() +
+               " because image " + imageName + " no longer available.");
+         return null;
+      }
+      Hardware hardware = getHardware(id, config);
+      // We've got the latest image. Depending on whether the machine is running
+      // or halted it could be using an older image or switch to the latest on UP correspondingly.
+      // Ubuntu for example will change passwords between image versions so we might need to fix
+      // the image version used in future, so it doesn't change and we know which one is used.
+      VagrantNode node = VagrantNode.builder()
+            .setPath(group)
+            .setId(id)
+            .setGroup(group.getName())
+            .setName(machineName)
+            .setImage(image)
+            .setHardware(hardware)
+            .setNetworks(ImmutableList.<String>of())
+            .setHostname("unknown")
+            .build();
+      // Don't bother asking Vagrant for the status as it could take quite a while for all the running machines
+      node.setMachineState(Status.UNRECOGNIZED);
+      return node;
+   }
+
+   private Hardware getHardware(String id, Map<String, ?> config) {
+      String hardwareId = config.get(VagrantConstants.CONFIG_HARDWARE_ID).toString();
+      if (hardwareId.equals(VagrantConstants.MACHINES_AUTO_HARDWARE)) {
+         double cpus = Double.parseDouble(config.get(VagrantConstants.CONFIG_CPUS).toString());
+         int memory = Integer.parseInt(config.get(VagrantConstants.CONFIG_MEMORY).toString());
+         AutomaticHardwareIdSpec hardwareSpec = AutomaticHardwareIdSpec.automaticHardwareIdSpecBuilder(cpus, memory, Optional.<Float>absent());
+         return new HardwareBuilder()
+               .id(hardwareSpec.toString())
+               .providerId(hardwareSpec.toString())
+               .processor(new Processor(cpus, 1.0))
+               .ram(memory)
+               .build();
+      } else {
+         Hardware hardware = hardwareSupplier.get().get(hardwareId);
+         if (hardware == null) {
+            throw new IllegalStateException("Unsupported hardwareId " + hardwareId + " for machine " + id);
+         }
+         return hardware;
+      }
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e4c809db/vagrant/src/main/java/org/jclouds/vagrant/internal/VagrantNodeRegistry.java
----------------------------------------------------------------------
diff --git a/vagrant/src/main/java/org/jclouds/vagrant/internal/VagrantNodeRegistry.java b/vagrant/src/main/java/org/jclouds/vagrant/internal/VagrantNodeRegistry.java
index e4121fd..8355b2d 100644
--- a/vagrant/src/main/java/org/jclouds/vagrant/internal/VagrantNodeRegistry.java
+++ b/vagrant/src/main/java/org/jclouds/vagrant/internal/VagrantNodeRegistry.java
@@ -16,6 +16,7 @@
  */
 package org.jclouds.vagrant.internal;
 
+import java.util.Collection;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.DelayQueue;
@@ -26,6 +27,7 @@ import org.jclouds.date.TimeStamp;
 import org.jclouds.vagrant.domain.VagrantNode;
 
 import com.google.common.base.Supplier;
+import com.google.common.base.Suppliers;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
 
@@ -34,6 +36,24 @@ public class VagrantNodeRegistry {
    private static final long TERMINATED_NODES_EXPIRY_MS = TimeUnit.MINUTES.toMillis(5);
    private static final long VACUUM_PERIOD_MS = TimeUnit.SECONDS.toMillis(15);
 
+   private static class ConcurrentWrapperSupplier implements Supplier<Map<String, VagrantNode>> {
+      private Supplier<Collection<VagrantNode>> existingMachines;
+
+      public ConcurrentWrapperSupplier(Supplier<Collection<VagrantNode>> existingMachines) {
+         this.existingMachines = existingMachines;
+      }
+
+      @Override
+      public Map<String, VagrantNode> get() {
+         Map<String, VagrantNode> nodes = new ConcurrentHashMap<String, VagrantNode>();
+         for (VagrantNode node : existingMachines.get()) {
+            nodes.put(node.id(), node);
+         }
+         return nodes;
+      }
+
+   }
+
    private static class TerminatedNode implements Delayed {
       Supplier<Long> timeSupplier;
       long expiryTime;
@@ -73,21 +93,22 @@ public class VagrantNodeRegistry {
          return unit.convert(expiryTime - timeSupplier.get(), TimeUnit.MILLISECONDS);
       }
    }
-   private Map<String, VagrantNode> nodes = new ConcurrentHashMap<String, VagrantNode>();
-   private DelayQueue<TerminatedNode> terminatedNodes = new DelayQueue<TerminatedNode>();
+
+   private final DelayQueue<TerminatedNode> terminatedNodes = new DelayQueue<TerminatedNode>();
+   private final Supplier<Map<String, VagrantNode>> nodes;
 
    private volatile long lastVacuumMs;
-   private Supplier<Long> timeSupplier;
+   private final Supplier<Long> timeSupplier;
 
    @Inject
-   VagrantNodeRegistry(@TimeStamp Supplier<Long> timeSupplier) {
+   VagrantNodeRegistry(@TimeStamp Supplier<Long> timeSupplier, Supplier<Collection<VagrantNode>> existingMachines) {
       this.timeSupplier = timeSupplier;
+      this.nodes = Suppliers.memoize(new ConcurrentWrapperSupplier(existingMachines));
    }
 
-
    public VagrantNode get(String id) {
       vacuum();
-      return nodes.get(id);
+      return nodes.get().get(id);
    }
 
    protected void vacuum() {
@@ -95,14 +116,18 @@ public class VagrantNodeRegistry {
       if (timeSupplier.get() - lastVacuumMs > VACUUM_PERIOD_MS) {
          TerminatedNode terminated;
          while ((terminated = terminatedNodes.poll()) != null) {
-            nodes.remove(terminated.node.id());
+            nodes.get().remove(terminated.node.id());
          }
          lastVacuumMs = timeSupplier.get();
       }
    }
 
    public void add(VagrantNode node) {
-      nodes.put(node.id(), node);
+      nodes.get().put(node.id(), node);
+   }
+
+   public Collection<VagrantNode> list() {
+      return nodes.get().values();
    }
 
    public void onTerminated(VagrantNode node) {

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e4c809db/vagrant/src/main/java/org/jclouds/vagrant/strategy/VagrantDefaultImageCredentials.java
----------------------------------------------------------------------
diff --git a/vagrant/src/main/java/org/jclouds/vagrant/strategy/VagrantDefaultImageCredentials.java b/vagrant/src/main/java/org/jclouds/vagrant/strategy/VagrantDefaultImageCredentials.java
index 97667cf..fa2f2bb 100644
--- a/vagrant/src/main/java/org/jclouds/vagrant/strategy/VagrantDefaultImageCredentials.java
+++ b/vagrant/src/main/java/org/jclouds/vagrant/strategy/VagrantDefaultImageCredentials.java
@@ -16,7 +16,6 @@
  */
 package org.jclouds.vagrant.strategy;
 
-import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.base.Preconditions.checkState;
 
 import java.io.File;
@@ -59,8 +58,8 @@ public class VagrantDefaultImageCredentials implements PopulateDefaultLoginCrede
          Map<String, Credentials> credentialStore,
          BoxConfig.Factory boxConfigFactory) {
       this.creds = creds;
-      this.credentialStore = checkNotNull(credentialStore, "credentialStore");
-      this.boxConfigFactory = checkNotNull(boxConfigFactory, "boxConfigFactory");
+      this.credentialStore = credentialStore;
+      this.boxConfigFactory = boxConfigFactory;
    }
 
    @Override

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e4c809db/vagrant/src/test/java/org/jclouds/vagrant/functions/MachineToNodeMetadataTest.java
----------------------------------------------------------------------
diff --git a/vagrant/src/test/java/org/jclouds/vagrant/functions/MachineToNodeMetadataTest.java b/vagrant/src/test/java/org/jclouds/vagrant/functions/MachineToNodeMetadataTest.java
index 7f5f5f2..ea02d22 100644
--- a/vagrant/src/test/java/org/jclouds/vagrant/functions/MachineToNodeMetadataTest.java
+++ b/vagrant/src/test/java/org/jclouds/vagrant/functions/MachineToNodeMetadataTest.java
@@ -19,7 +19,6 @@ package org.jclouds.vagrant.functions;
 import static org.testng.Assert.assertEquals;
 
 import java.io.File;
-import java.util.Map;
 import java.util.Set;
 
 import org.easymock.EasyMock;
@@ -36,7 +35,6 @@ import org.jclouds.compute.domain.Processor;
 import org.jclouds.domain.Location;
 import org.jclouds.vagrant.domain.VagrantNode;
 import org.jclouds.vagrant.internal.BoxConfig;
-import org.jclouds.vagrant.internal.MachineConfig;
 import org.jclouds.vagrant.reference.VagrantConstants;
 import org.testng.annotations.Test;
 
@@ -44,7 +42,6 @@ import com.google.common.base.Optional;
 import com.google.common.base.Supplier;
 import com.google.common.base.Suppliers;
 import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 
 import vagrant.api.domain.Box;
@@ -59,14 +56,16 @@ public class MachineToNodeMetadataTest {
                .operatingSystem(os)
                .status(org.jclouds.compute.domain.Image.Status.AVAILABLE)
                .build();
-
+         Hardware hardware = new HardwareBuilder().ids("mini").ram(100).processor(new Processor(1.0, 1)).build();
          ImmutableList<String> networks = ImmutableList.of("172.28.128.3");
+
          VagrantNode node = VagrantNode.builder()
                .setPath(new File("/path/to/machine"))
                .setId("vagrant/node")
                .setGroup("vagrant")
                .setName("node")
                .setImage(image)
+               .setHardware(hardware)
                .setNetworks(networks)
                .setHostname("vagrant-node")
                .build();
@@ -81,26 +80,14 @@ public class MachineToNodeMetadataTest {
          BoxConfig.Factory boxConfigFactory = EasyMock.createMock(BoxConfig.Factory.class);
          EasyMock.expect(boxConfigFactory.newInstance((Image)EasyMock.<Box>anyObject())).andReturn(boxConfig);
 
-         MachineConfig machineConfig = EasyMock.createMock(MachineConfig.class);
-         EasyMock.expect(machineConfig.load()).andReturn(getMachineConfig());
-
-         MachineConfig.Factory machineConfigFactory = EasyMock.createMock(MachineConfig.Factory.class);
-         EasyMock.expect(machineConfigFactory.newInstance(node)).andReturn(machineConfig);
-
-         Hardware hardware = new HardwareBuilder().ids(getHardwareId()).ram(100).processor(new Processor(1.0, 1)).build();
-         Supplier<? extends Map<String, Hardware>> hardwareSupplier = Suppliers.ofInstance(ImmutableMap.of(getHardwareId(), hardware));
-
-         EasyMock.replay(location, boxConfig, boxConfigFactory,
-               machineConfig, machineConfigFactory);
+         EasyMock.replay(location, boxConfig, boxConfigFactory);
 
          @SuppressWarnings({ "unchecked", "rawtypes" })
          Supplier<Set<? extends Location>> locations = (Supplier<Set<? extends Location>>)(Supplier)Suppliers.ofInstance(ImmutableSet.of(location));
 
          MachineToNodeMetadata machineToNodeMetadata = new MachineToNodeMetadata(
                locations,
-               boxConfigFactory,
-               machineConfigFactory,
-               hardwareSupplier);
+               boxConfigFactory);
 
          NodeMetadata nodeMetadataActual = machineToNodeMetadata.apply(node);
 
@@ -122,12 +109,7 @@ public class MachineToNodeMetadataTest {
          assertEquals(nodeMetadataActual.toString(), nodeMetadataExpected.toString());
       }
 
-      protected Map<String, Object> getMachineConfig() {
-         return ImmutableMap.<String, Object>of(VagrantConstants.CONFIG_HARDWARE_ID, getHardwareId());
-      }
-
       protected abstract void customizeBuilder(NodeMetadataBuilder nodeMetadataBuilder);
-      protected abstract String getHardwareId();
       protected abstract OsFamily getOsFamily();
       protected abstract void expectBoxConfig(BoxConfig boxConfig);
    }
@@ -139,10 +121,6 @@ public class MachineToNodeMetadataTest {
             nodeMetadataBuilder.loginPort(2222);
          }
 
-         protected String getHardwareId() {
-            return "mini";
-         }
-
          protected OsFamily getOsFamily() {
             return OsFamily.LINUX;
          }
@@ -169,10 +147,6 @@ public class MachineToNodeMetadataTest {
          protected void customizeBuilder(NodeMetadataBuilder nodeMetadataBuilder) {
             nodeMetadataBuilder.loginPort(22);
          }
-
-         protected String getHardwareId() {
-            return "mini";
-         }
       }
       new MachineToNodeMetadataLinuxMini().doTest();
    }
@@ -189,25 +163,9 @@ public class MachineToNodeMetadataTest {
          }
 
          protected void customizeBuilder(NodeMetadataBuilder nodeMetadataBuilder) {
-            nodeMetadataBuilder.loginPort(2222)
-               .hardware(new HardwareBuilder()
-                  .ids("automatic:cores=2.0;ram=1000")
-                  .processor(new Processor(2.0, 1))
-                  .ram(1000)
-                  .build());
-         }
-
-         @Override
-         protected Map<String, Object> getMachineConfig() {
-            return ImmutableMap.<String, Object>of(
-                  VagrantConstants.CONFIG_HARDWARE_ID, getHardwareId(),
-                  VagrantConstants.CONFIG_CPUS, "2.0",
-                  VagrantConstants.CONFIG_MEMORY, "1000");
+            nodeMetadataBuilder.loginPort(2222);
          }
 
-         protected String getHardwareId() {
-            return "automatic";
-         }
       }
       new MachineToNodeMetadataLinuxMini().doTest();
    }
@@ -219,10 +177,6 @@ public class MachineToNodeMetadataTest {
             nodeMetadataBuilder.loginPort(8899);
          }
 
-         protected String getHardwareId() {
-            return "mini";
-         }
-
          protected OsFamily getOsFamily() {
             return OsFamily.WINDOWS;
          }
@@ -250,9 +204,6 @@ public class MachineToNodeMetadataTest {
             nodeMetadataBuilder.loginPort(5985);
          }
 
-         protected String getHardwareId() {
-            return "mini";
-         }
       }
       new MachineToNodeMetadataLinuxMini().doTest();
    }
@@ -269,25 +220,9 @@ public class MachineToNodeMetadataTest {
          }
 
          protected void customizeBuilder(NodeMetadataBuilder nodeMetadataBuilder) {
-            nodeMetadataBuilder.loginPort(8899)
-               .hardware(new HardwareBuilder()
-                  .ids("automatic:cores=2.0;ram=1000")
-                  .processor(new Processor(2.0, 1))
-                  .ram(1000)
-                  .build());
-         }
-
-         @Override
-         protected Map<String, Object> getMachineConfig() {
-            return ImmutableMap.<String, Object>of(
-                  VagrantConstants.CONFIG_HARDWARE_ID, getHardwareId(),
-                  VagrantConstants.CONFIG_CPUS, "2.0",
-                  VagrantConstants.CONFIG_MEMORY, "1000");
+            nodeMetadataBuilder.loginPort(8899);
          }
 
-         protected String getHardwareId() {
-            return "automatic";
-         }
       }
       new MachineToNodeMetadataLinuxMini().doTest();
    }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e4c809db/vagrant/src/test/java/org/jclouds/vagrant/internal/VagrantNodeLoaderTest.java
----------------------------------------------------------------------
diff --git a/vagrant/src/test/java/org/jclouds/vagrant/internal/VagrantNodeLoaderTest.java b/vagrant/src/test/java/org/jclouds/vagrant/internal/VagrantNodeLoaderTest.java
new file mode 100644
index 0000000..2eeed6a
--- /dev/null
+++ b/vagrant/src/test/java/org/jclouds/vagrant/internal/VagrantNodeLoaderTest.java
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.vagrant.internal;
+
+import static org.testng.Assert.assertEquals;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Map;
+
+import org.easymock.EasyMock;
+import org.jclouds.compute.domain.Hardware;
+import org.jclouds.compute.domain.HardwareBuilder;
+import org.jclouds.compute.domain.Image;
+import org.jclouds.compute.domain.Processor;
+import org.jclouds.vagrant.domain.VagrantNode;
+import org.jclouds.vagrant.reference.VagrantConstants;
+import org.jclouds.vagrant.util.VagrantUtils;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Charsets;
+import com.google.common.base.Supplier;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+import com.google.common.io.Files;
+
+public class VagrantNodeLoaderTest {
+    @Test
+    public void testAutoMachine() throws Exception {
+        ImmutableMap<String, Object> hardwareConfig = ImmutableMap.<String, Object>of(
+                VagrantConstants.CONFIG_HARDWARE_ID, VagrantConstants.MACHINES_AUTO_HARDWARE,
+                VagrantConstants.CONFIG_CPUS, "2",
+                VagrantConstants.CONFIG_MEMORY, "1024");
+        Hardware expectedHardware = new HardwareBuilder().ids("automatic:cores=2.0;ram=1024").ram(1024).processor(new Processor(2.0, 1)).build();
+
+        doTest(hardwareConfig, expectedHardware);
+    }
+
+    @Test
+    public void testSmallMachine() throws Exception {
+        ImmutableMap<String, Object> hardwareConfig = ImmutableMap.<String, Object>of(
+                VagrantConstants.CONFIG_HARDWARE_ID, "small");
+        Hardware expectedHardware = new HardwareBuilder().ids("small").ram(1024).processor(new Processor(1.0, 1)).build();
+
+        doTest(hardwareConfig, expectedHardware);
+    }
+
+    protected void doTest(ImmutableMap<String, Object> hardwareConfig, Hardware expectedHardware) throws IOException {
+        String groupName = "groupId";
+        String machineName = "machineId";
+
+        File home = Files.createTempDir();
+        File group = new File(home, groupName);
+        File machines = new File(group, VagrantConstants.MACHINES_CONFIG_SUBFOLDER);
+        machines.mkdirs();
+        File machine = new File(machines, machineName + VagrantConstants.MACHINES_CONFIG_EXTENSION);
+        Files.write("dummy", machine, Charsets.UTF_8);
+
+        MachineConfig config = EasyMock.createMock(MachineConfig.class);
+        String imageId = "centos/7";
+        EasyMock.expect(config.load()).andReturn(ImmutableMap.<String, Object>builder()
+                .put(VagrantConstants.CONFIG_BOX, imageId)
+                .putAll(hardwareConfig)
+                .build());
+        MachineConfig.Factory factory = EasyMock.createMock(MachineConfig.Factory.class);
+        EasyMock.expect(factory.newInstance(group, machineName)).andReturn(config);
+
+        Image image = EasyMock.createMock(Image.class);
+        EasyMock.expect(image.getId()).andReturn(imageId);
+
+        @SuppressWarnings("unchecked")
+        Supplier<Collection<Image>> imageSupplier = EasyMock.createMock(Supplier.class);
+        EasyMock.expect(imageSupplier.get()).andReturn(ImmutableList.<Image>of(image));
+
+        @SuppressWarnings("unchecked")
+        Supplier<Map<String, Hardware>> hardwareSupplier = EasyMock.createMock(Supplier.class);
+        EasyMock.expect(hardwareSupplier.get()).andReturn(ImmutableMap.<String, Hardware>of(
+                "small", new HardwareBuilder().ids("small").ram(1024).processor(new Processor(1.0, 1)).build()));
+
+        EasyMock.replay(config, factory, imageSupplier, image, hardwareSupplier);
+
+        VagrantExistingMachines nodeLoader = new VagrantExistingMachines(home.getAbsolutePath(), factory, imageSupplier, hardwareSupplier);
+        Collection<VagrantNode> nodes = nodeLoader.get();
+
+        VagrantNode actualNode = Iterables.getOnlyElement(nodes);
+        VagrantNode expectedNode = VagrantNode.builder()
+                .setPath(group)
+                .setId(group.getName() + "/" + machineName)
+                .setGroup(group.getName())
+                .setName(machineName)
+                .setImage(image)
+                .setHardware(expectedHardware)
+                .setNetworks(ImmutableList.<String>of())
+                .setHostname("unknown")
+                .build();
+        assertEquals(actualNode, expectedNode);
+        VagrantUtils.deleteFolder(home);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e4c809db/vagrant/src/test/java/org/jclouds/vagrant/internal/VagrantNodeRegistryTest.java
----------------------------------------------------------------------
diff --git a/vagrant/src/test/java/org/jclouds/vagrant/internal/VagrantNodeRegistryTest.java b/vagrant/src/test/java/org/jclouds/vagrant/internal/VagrantNodeRegistryTest.java
index fb4950c..4ad492a 100644
--- a/vagrant/src/test/java/org/jclouds/vagrant/internal/VagrantNodeRegistryTest.java
+++ b/vagrant/src/test/java/org/jclouds/vagrant/internal/VagrantNodeRegistryTest.java
@@ -22,10 +22,14 @@ import static org.testng.Assert.assertNull;
 import java.io.File;
 import java.util.concurrent.TimeUnit;
 
+import org.easymock.EasyMock;
+import org.jclouds.compute.domain.Hardware;
+import org.jclouds.compute.domain.HardwareBuilder;
 import org.jclouds.compute.domain.Image;
 import org.jclouds.compute.domain.ImageBuilder;
 import org.jclouds.compute.domain.OperatingSystem;
 import org.jclouds.compute.domain.OsFamily;
+import org.jclouds.compute.domain.Processor;
 import org.jclouds.vagrant.domain.VagrantNode;
 import org.testng.annotations.Test;
 
@@ -49,14 +53,19 @@ public class VagrantNodeRegistryTest {
 
    @Test
    public void testNodeRegistry() {
+      VagrantExistingMachines loader = EasyMock.createMock(VagrantExistingMachines.class);
+      EasyMock.expect(loader.get()).andReturn(ImmutableList.<VagrantNode>of());
+      EasyMock.replay(loader);
+
       TestTimeSupplier timeSupplier = new TestTimeSupplier();
-      VagrantNodeRegistry registry = new VagrantNodeRegistry(timeSupplier);
+      VagrantNodeRegistry registry = new VagrantNodeRegistry(timeSupplier, loader);
       OperatingSystem os = new OperatingSystem(OsFamily.UNRECOGNIZED, "Jclouds OS", "10", "x64", "Jclouds Test Image", true);
       Image image = new ImageBuilder()
             .ids("jclouds/box")
             .operatingSystem(os)
             .status(Image.Status.AVAILABLE)
             .build();
+      Hardware hardware = new HardwareBuilder().ids("mini").ram(100).processor(new Processor(1.0, 1)).build();
 
       ImmutableList<String> networks = ImmutableList.of("172.28.128.3");
       VagrantNode node = VagrantNode.builder()
@@ -66,6 +75,7 @@ public class VagrantNodeRegistryTest {
             .setName("node")
             .setImage(image)
             .setNetworks(networks)
+            .setHardware(hardware)
             .setHostname("vagrant-node")
             .build();