provisionr-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From as...@apache.org
Subject git commit: PROVISIONR-22. First steps for golden AMI support:
Date Fri, 29 Mar 2013 10:52:34 GMT
Updated Branches:
  refs/heads/master 43db8f769 -> 6559ede8b


PROVISIONR-22. First steps for golden AMI support:

* The ability to create machines in a pool provisioned with a specific AMI
* New command to support the creation of an AMI from a template

Signed-off-by: Andrei Savu <asavu@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/incubator-provisionr/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-provisionr/commit/6559ede8
Tree: http://git-wip-us.apache.org/repos/asf/incubator-provisionr/tree/6559ede8
Diff: http://git-wip-us.apache.org/repos/asf/incubator-provisionr/diff/6559ede8

Branch: refs/heads/master
Commit: 6559ede8b1df7c26761183e7e3df89a879aa6672
Parents: 43db8f7
Author: Alex Ciminian <alex.ciminian@gmail.com>
Authored: Fri Mar 15 17:36:25 2013 +0200
Committer: Andrei Savu <asavu@apache.org>
Committed: Fri Mar 29 12:50:18 2013 +0200

----------------------------------------------------------------------
 .../java/com/axemblr/provisionr/api/pool/Pool.java |   14 +-
 .../axemblr/provisionr/api/pool/PoolBuilder.java   |    8 +-
 .../axemblr/provisionr/api/software/Software.java  |   26 ++-
 .../provisionr/api/software/SoftwareBuilder.java   |   14 +-
 .../com/axemblr/provisionr/api/pool/PoolTest.java  |    5 +-
 .../provisionr/api/software/SoftwareTest.java      |    4 +-
 .../provisionr/core/CoreProcessVariables.java      |    6 +
 .../activities/SpawnProcessForEachMachine.java     |    1 +
 .../activities/SpawnProcessForEachMachineTest.java |   20 ++-
 .../axemblr/provisionr/commands/CreateCommand.java |  130 +++++++++++++
 .../provisionr/commands/CreateImageCommand.java    |   61 ++++++
 .../provisionr/commands/CreatePoolCommand.java     |  143 ++++-----------
 .../provisionr/commands/CreatePoolCommandTest.java |    2 -
 .../amazon/AmazonProvisionrLiveTest.java           |    2 +-
 .../provisionr/amazon/AmazonProvisionr.java        |    1 +
 .../provisionr/amazon/ProcessVariables.java        |    4 +-
 .../amazon/activities/DumpConsoleOutput.java       |    9 +-
 .../provisionr/amazon/activities/RunInstances.java |   19 +-
 .../activiti/amazonMachineSetup.bpmn20.xml         |  125 ++++++++-----
 .../com/axemblr/provisionr/amazon/userdata.sh      |    2 +-
 .../amazon/activities/CreatePoolLiveTest.java      |    4 +
 .../activities/RunOnDemandInstancesLiveTest.java   |   16 ++
 .../cloudstack/CloudStackProvisionrLiveTest.java   |    2 +-
 .../cloudstack/activities/RunInstances.java        |    2 +-
 .../activities/RunInstancesLiveTest.java           |    2 +-
 25 files changed, 403 insertions(+), 219 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-provisionr/blob/6559ede8/api/src/main/java/com/axemblr/provisionr/api/pool/Pool.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/com/axemblr/provisionr/api/pool/Pool.java b/api/src/main/java/com/axemblr/provisionr/api/pool/Pool.java
index c228197..43a0831 100644
--- a/api/src/main/java/com/axemblr/provisionr/api/pool/Pool.java
+++ b/api/src/main/java/com/axemblr/provisionr/api/pool/Pool.java
@@ -43,11 +43,10 @@ public class Pool extends WithOptions {
     private final int minSize;
     private final int expectedSize;
 
-    private final boolean cacheBaseImage;
     private final int bootstrapTimeInSeconds;
 
     Pool(Provider provider, Network network, AdminAccess adminAccess, Software software, Hardware hardware,
-         int minSize, int expectedSize, boolean cacheBaseImage, int bootstrapTimeInSeconds,
+         int minSize, int expectedSize, int bootstrapTimeInSeconds,
          Map<String, String> options
     ) {
         super(options);
@@ -63,7 +62,6 @@ public class Pool extends WithOptions {
         this.hardware = checkNotNull(hardware, "hardware is null");
         this.minSize = minSize;
         this.expectedSize = expectedSize;
-        this.cacheBaseImage = cacheBaseImage;
         this.bootstrapTimeInSeconds = bootstrapTimeInSeconds;
     }
 
@@ -95,10 +93,6 @@ public class Pool extends WithOptions {
         return expectedSize;
     }
 
-    public boolean isCacheBaseImage() {
-        return cacheBaseImage;
-    }
-
     /**
      * The maximum amount of time to go from 0 to minSize
      */
@@ -108,14 +102,14 @@ public class Pool extends WithOptions {
 
     public PoolBuilder toBuilder() {
         return builder().provider(provider).network(network).adminAccess(adminAccess).software(software)
-            .hardware(hardware).minSize(minSize).cacheBaseImage(cacheBaseImage).expectedSize(expectedSize)
+            .hardware(hardware).minSize(minSize).expectedSize(expectedSize)
             .bootstrapTimeInSeconds(bootstrapTimeInSeconds).options(getOptions());
     }
 
     @Override
     public int hashCode() {
         return Objects.hashCode(provider, network, adminAccess, software, hardware,
-            minSize, expectedSize, cacheBaseImage, bootstrapTimeInSeconds, getOptions());
+            minSize, expectedSize, bootstrapTimeInSeconds, getOptions());
     }
 
     @Override
@@ -131,7 +125,6 @@ public class Pool extends WithOptions {
             && Objects.equal(this.adminAccess, other.adminAccess) && Objects.equal(this.software, other.software)
             && Objects.equal(this.hardware, other.hardware) && Objects.equal(this.minSize, other.minSize)
             && Objects.equal(this.expectedSize, other.expectedSize)
-            && this.cacheBaseImage == other.cacheBaseImage
             && Objects.equal(this.bootstrapTimeInSeconds, other.bootstrapTimeInSeconds)
             && Objects.equal(this.getOptions(), other.getOptions());
     }
@@ -145,7 +138,6 @@ public class Pool extends WithOptions {
             ", software=" + software +
             ", hardware=" + hardware +
             ", minSize=" + minSize +
-            ", cacheBaseImage=" + cacheBaseImage +
             ", expectedSize=" + expectedSize +
             ", bootstrapTimeInSeconds=" + bootstrapTimeInSeconds +
             ", options=" + getOptions() +

http://git-wip-us.apache.org/repos/asf/incubator-provisionr/blob/6559ede8/api/src/main/java/com/axemblr/provisionr/api/pool/PoolBuilder.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/com/axemblr/provisionr/api/pool/PoolBuilder.java b/api/src/main/java/com/axemblr/provisionr/api/pool/PoolBuilder.java
index ea3ec12..3a943bf 100644
--- a/api/src/main/java/com/axemblr/provisionr/api/pool/PoolBuilder.java
+++ b/api/src/main/java/com/axemblr/provisionr/api/pool/PoolBuilder.java
@@ -37,7 +37,6 @@ public class PoolBuilder extends BuilderWithOptions<PoolBuilder> {
     private int minSize = -1;
     private int expectedSize = -1;
 
-    private boolean cacheBaseImage = false;
     private int bootstrapTimeInSeconds = 15 * 60;
 
     @Override
@@ -82,11 +81,6 @@ public class PoolBuilder extends BuilderWithOptions<PoolBuilder> {
         return this;
     }
 
-    public PoolBuilder cacheBaseImage(boolean cacheBaseImage) {
-        this.cacheBaseImage = cacheBaseImage;
-        return this;
-    }
-
     public PoolBuilder bootstrapTimeInSeconds(int bootstrapTimeInSeconds) {
         checkArgument(bootstrapTimeInSeconds > 0, "bootstrapTimeInSeconds should be positive");
         this.bootstrapTimeInSeconds = bootstrapTimeInSeconds;
@@ -95,6 +89,6 @@ public class PoolBuilder extends BuilderWithOptions<PoolBuilder> {
 
     public Pool createPool() {
         return new Pool(provider, network, adminAccess, software, hardware, minSize,
-            expectedSize, cacheBaseImage, bootstrapTimeInSeconds, buildOptions());
+            expectedSize, bootstrapTimeInSeconds, buildOptions());
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-provisionr/blob/6559ede8/api/src/main/java/com/axemblr/provisionr/api/software/Software.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/com/axemblr/provisionr/api/software/Software.java b/api/src/main/java/com/axemblr/provisionr/api/software/Software.java
index 63adfb7..93a15da 100644
--- a/api/src/main/java/com/axemblr/provisionr/api/software/Software.java
+++ b/api/src/main/java/com/axemblr/provisionr/api/software/Software.java
@@ -33,23 +33,29 @@ public class Software extends WithOptions {
         return new SoftwareBuilder();
     }
 
-    private final String baseOperatingSystem;
+    private final String imageId;
+    private final boolean cachedImage;
 
     private final Map<String, String> files;
     private final List<String> packages;
     private final List<Repository> repositories;
 
-    Software(String baseOperatingSystem, Map<String, String> files, List<String> packages,
+    Software(String imageId, boolean cachedImage, Map<String, String> files, List<String> packages,
              List<Repository> repositories, Map<String, String> options) {
         super(options);
-        this.baseOperatingSystem = checkNotNull(baseOperatingSystem, "baseOperatingSystem is null");
+        this.imageId = checkNotNull(imageId, "The supplied imageId was null");
+        this.cachedImage = cachedImage;
         this.files = ImmutableMap.copyOf(files);
         this.packages = ImmutableList.copyOf(packages);
         this.repositories = ImmutableList.copyOf(repositories);
     }
 
-    public String getBaseOperatingSystem() {
-        return baseOperatingSystem;
+    public String getImageId() {
+        return imageId;
+    }
+
+    public boolean isCachedImage() {
+        return cachedImage;
     }
 
     /**
@@ -77,13 +83,13 @@ public class Software extends WithOptions {
     }
 
     public SoftwareBuilder toBuilder() {
-        return builder().baseOperatingSystem(baseOperatingSystem).files(files)
+        return builder().imageId(imageId).files(files)
             .packages(packages).repositories(repositories).options(getOptions());
     }
 
     @Override
     public int hashCode() {
-        return Objects.hashCode(baseOperatingSystem, files, packages, repositories, getOptions());
+        return Objects.hashCode(imageId, cachedImage, files, packages, repositories, getOptions());
     }
 
     @Override
@@ -96,7 +102,8 @@ public class Software extends WithOptions {
         }
 
         final Software other = (Software) obj;
-        return Objects.equal(this.baseOperatingSystem, other.baseOperatingSystem)
+        return Objects.equal(this.imageId, other.imageId)
+            && Objects.equal(this.cachedImage, other.cachedImage)
             && Objects.equal(this.files, other.files)
             && Objects.equal(this.packages, other.packages)
             && Objects.equal(this.repositories, other.repositories)
@@ -106,7 +113,8 @@ public class Software extends WithOptions {
     @Override
     public String toString() {
         return "Software{" +
-            "baseOperatingSystem='" + baseOperatingSystem + '\'' +
+            "imageId='" + imageId + '\'' +
+            ", cachedImage=" + cachedImage +
             ", files=" + files +
             ", packages=" + packages +
             ", repositories=" + repositories +

http://git-wip-us.apache.org/repos/asf/incubator-provisionr/blob/6559ede8/api/src/main/java/com/axemblr/provisionr/api/software/SoftwareBuilder.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/com/axemblr/provisionr/api/software/SoftwareBuilder.java b/api/src/main/java/com/axemblr/provisionr/api/software/SoftwareBuilder.java
index 3c31016..358f273 100644
--- a/api/src/main/java/com/axemblr/provisionr/api/software/SoftwareBuilder.java
+++ b/api/src/main/java/com/axemblr/provisionr/api/software/SoftwareBuilder.java
@@ -25,7 +25,8 @@ import java.util.Map;
 
 public class SoftwareBuilder extends BuilderWithOptions<SoftwareBuilder> {
 
-    private String baseOperatingSystem = "default";
+    private String imageId = "default";
+    private boolean cachedImage = false;
 
     private ImmutableMap.Builder<String, String> files = ImmutableMap.builder();
     private ImmutableList.Builder<String> packages = ImmutableList.builder();
@@ -36,8 +37,13 @@ public class SoftwareBuilder extends BuilderWithOptions<SoftwareBuilder> {
         return this;
     }
 
-    public SoftwareBuilder baseOperatingSystem(String baseOperatingSystem) {
-        this.baseOperatingSystem = checkNotNull(baseOperatingSystem, "baseOperatingSystem");
+    public SoftwareBuilder imageId(String imageId) {
+        this.imageId = checkNotNull(imageId, "The imageId was null");
+        return this;
+    }
+
+    public SoftwareBuilder cachedImage(boolean cachedImage) {
+        this.cachedImage = cachedImage;
         return this;
     }
 
@@ -77,7 +83,7 @@ public class SoftwareBuilder extends BuilderWithOptions<SoftwareBuilder> {
     }
 
     public Software createSoftware() {
-        return new Software(baseOperatingSystem, files.build(), packages.build(),
+        return new Software(imageId, cachedImage, files.build(), packages.build(),
             repositories.build(), buildOptions());
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-provisionr/blob/6559ede8/api/src/test/java/com/axemblr/provisionr/api/pool/PoolTest.java
----------------------------------------------------------------------
diff --git a/api/src/test/java/com/axemblr/provisionr/api/pool/PoolTest.java b/api/src/test/java/com/axemblr/provisionr/api/pool/PoolTest.java
index 5798dd7..583ce70 100644
--- a/api/src/test/java/com/axemblr/provisionr/api/pool/PoolTest.java
+++ b/api/src/test/java/com/axemblr/provisionr/api/pool/PoolTest.java
@@ -17,13 +17,15 @@
 package com.axemblr.provisionr.api.pool;
 
 import static com.axemblr.provisionr.api.AssertSerializable.assertSerializable;
+import static org.fest.assertions.api.Assertions.assertThat;
+
 import com.axemblr.provisionr.api.access.AdminAccess;
 import com.axemblr.provisionr.api.hardware.Hardware;
 import com.axemblr.provisionr.api.network.Network;
 import com.axemblr.provisionr.api.network.Rule;
 import com.axemblr.provisionr.api.provider.Provider;
 import com.axemblr.provisionr.api.software.Software;
-import static org.fest.assertions.api.Assertions.assertThat;
+
 import org.junit.Test;
 
 public class PoolTest {
@@ -54,7 +56,6 @@ public class PoolTest {
             .minSize(20)
             .expectedSize(25)
             .bootstrapTimeInSeconds(60 * 15)
-            .cacheBaseImage(true)
             .createPool();
 
 

http://git-wip-us.apache.org/repos/asf/incubator-provisionr/blob/6559ede8/api/src/test/java/com/axemblr/provisionr/api/software/SoftwareTest.java
----------------------------------------------------------------------
diff --git a/api/src/test/java/com/axemblr/provisionr/api/software/SoftwareTest.java b/api/src/test/java/com/axemblr/provisionr/api/software/SoftwareTest.java
index 8339c15..7179ed7 100644
--- a/api/src/test/java/com/axemblr/provisionr/api/software/SoftwareTest.java
+++ b/api/src/test/java/com/axemblr/provisionr/api/software/SoftwareTest.java
@@ -34,14 +34,14 @@ public class SoftwareTest {
             .createRepository();
 
         Software software = Software.builder()
-            .baseOperatingSystem("ubuntu-10.04")
+            .imageId("default")
             .repository(repository)
             .packages("vim", "git-core", "bigtop-utils")
             .file("http://bin.axemblr.com/something.tar.gz", "/root/something.tar.gz")
             .option("provider", "specific")
             .createSoftware();
 
-        assertThat(software.getBaseOperatingSystem()).isEqualTo("ubuntu-10.04");
+        assertThat(software.getImageId()).isEqualTo("default");
         assertThat(software.toBuilder().createSoftware()).isEqualTo(software);
 
         assertSerializable(software, Software.class);

http://git-wip-us.apache.org/repos/asf/incubator-provisionr/blob/6559ede8/core/src/main/java/com/axemblr/provisionr/core/CoreProcessVariables.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/com/axemblr/provisionr/core/CoreProcessVariables.java b/core/src/main/java/com/axemblr/provisionr/core/CoreProcessVariables.java
index 7375c0d..5dfa1d6 100644
--- a/core/src/main/java/com/axemblr/provisionr/core/CoreProcessVariables.java
+++ b/core/src/main/java/com/axemblr/provisionr/core/CoreProcessVariables.java
@@ -61,4 +61,10 @@ public class CoreProcessVariables {
      * to become available.
      */
     public static final String BOOTSTRAP_TIMEOUT = "bootstrapTimeout";
+
+    /**
+     * Flag that indicates if the image the machines are being built from already has all its software
+     * installed and there's no need to download and install the packages and files.
+     */
+    public static final String IS_CACHED_IMAGE = "isCachedImage";
 }

http://git-wip-us.apache.org/repos/asf/incubator-provisionr/blob/6559ede8/core/src/main/java/com/axemblr/provisionr/core/activities/SpawnProcessForEachMachine.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/com/axemblr/provisionr/core/activities/SpawnProcessForEachMachine.java b/core/src/main/java/com/axemblr/provisionr/core/activities/SpawnProcessForEachMachine.java
index 48ee9ad..4c2e36b 100644
--- a/core/src/main/java/com/axemblr/provisionr/core/activities/SpawnProcessForEachMachine.java
+++ b/core/src/main/java/com/axemblr/provisionr/core/activities/SpawnProcessForEachMachine.java
@@ -82,6 +82,7 @@ public class SpawnProcessForEachMachine implements JavaDelegate {
                 processKey, perMachineProcessBusinessKey,
                 ImmutableMap.<String, Object>of(CoreProcessVariables.POOL, pool,
                     CoreProcessVariables.POOL_BUSINESS_KEY, poolBusinessKey,
+                    CoreProcessVariables.IS_CACHED_IMAGE, pool.getSoftware().isCachedImage(),
                     MACHINE, machine));
 
             LOG.info("Started background '" + type + "' process {} ({}) for machine {}",

http://git-wip-us.apache.org/repos/asf/incubator-provisionr/blob/6559ede8/core/src/test/java/com/axemblr/provisionr/core/activities/SpawnProcessForEachMachineTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/com/axemblr/provisionr/core/activities/SpawnProcessForEachMachineTest.java b/core/src/test/java/com/axemblr/provisionr/core/activities/SpawnProcessForEachMachineTest.java
index 2b26ae5..ccb2aa8 100644
--- a/core/src/test/java/com/axemblr/provisionr/core/activities/SpawnProcessForEachMachineTest.java
+++ b/core/src/test/java/com/axemblr/provisionr/core/activities/SpawnProcessForEachMachineTest.java
@@ -16,22 +16,27 @@
 
 package com.axemblr.provisionr.core.activities;
 
+import static org.fest.assertions.api.Assertions.assertThat;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.withSettings;
+
 import com.axemblr.provisionr.api.pool.Machine;
 import com.axemblr.provisionr.api.pool.Pool;
+import com.axemblr.provisionr.api.software.Software;
 import com.axemblr.provisionr.core.CoreProcessVariables;
 import com.axemblr.provisionr.test.ProcessVariablesCollector;
 import com.google.common.collect.Lists;
+
 import java.util.List;
 import java.util.UUID;
+
 import org.activiti.engine.ProcessEngine;
 import org.activiti.engine.delegate.DelegateExecution;
 import org.activiti.engine.delegate.JavaDelegate;
 import org.activiti.engine.impl.cfg.StandaloneInMemProcessEngineConfiguration;
-import static org.fest.assertions.api.Assertions.assertThat;
 import org.junit.Test;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
 
 public class SpawnProcessForEachMachineTest {
 
@@ -43,8 +48,11 @@ public class SpawnProcessForEachMachineTest {
     @Test
     public void testSpawnSampleProcessForLocalhost() throws Exception {
         DelegateExecution execution = mock(DelegateExecution.class);
-
-        when(execution.getVariable(eq(CoreProcessVariables.POOL))).thenReturn(mock(Pool.class));
+        Pool pool = mock(Pool.class, withSettings().serializable());
+        Software software = mock(Software.class, withSettings().serializable());
+        when(software.isCachedImage()).thenReturn(false);
+        when(pool.getSoftware()).thenReturn(software);
+        when(execution.getVariable(eq(CoreProcessVariables.POOL))).thenReturn(pool);
         when(execution.getVariable(eq(CoreProcessVariables.POOL_BUSINESS_KEY))).thenReturn(BUSINESS_KEY);
 
         List<Machine> machines = Lists.newArrayList(

http://git-wip-us.apache.org/repos/asf/incubator-provisionr/blob/6559ede8/karaf/commands/src/main/java/com/axemblr/provisionr/commands/CreateCommand.java
----------------------------------------------------------------------
diff --git a/karaf/commands/src/main/java/com/axemblr/provisionr/commands/CreateCommand.java b/karaf/commands/src/main/java/com/axemblr/provisionr/commands/CreateCommand.java
new file mode 100644
index 0000000..5072703
--- /dev/null
+++ b/karaf/commands/src/main/java/com/axemblr/provisionr/commands/CreateCommand.java
@@ -0,0 +1,130 @@
+package com.axemblr.provisionr.commands;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.axemblr.provisionr.api.Provisionr;
+import com.axemblr.provisionr.api.access.AdminAccess;
+import com.axemblr.provisionr.api.network.Network;
+import com.axemblr.provisionr.api.network.Rule;
+import com.axemblr.provisionr.api.pool.Pool;
+import com.axemblr.provisionr.api.provider.Provider;
+import com.axemblr.provisionr.commands.predicates.ProvisionrPredicates;
+import com.axemblr.provisionr.core.templates.PoolTemplate;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Charsets;
+import com.google.common.base.Optional;
+import com.google.common.base.Throwables;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.google.common.io.Files;
+import com.google.common.util.concurrent.Service;
+
+import java.io.File;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+import org.apache.felix.gogo.commands.Option;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+
+public abstract class CreateCommand extends OsgiCommandSupport {
+
+    @Option(name = "--id", description = "Service ID (use provisionr:services)", required = true)
+    protected String id;
+
+    @Option(name = "--package", description = "Package to install by default (multi-valued)",
+            multiValued = true)
+    protected List<String> packages = Lists.newArrayList();
+
+    @Option(name = "-t", aliases = "--template", description = "Pre-configured template (packages, files)")
+    protected String template;
+
+    @Option(name = "--timeout", description = "Timeout in seconds for the command's initialization steps. " +
+            "If not specified, defaults to 600 seconds.")
+    protected int bootstrapTimeout = 600;
+
+    protected final List<Provisionr> services;
+
+    protected final List<PoolTemplate> templates;
+
+    public CreateCommand(List<Provisionr> services, List<PoolTemplate> templates) {
+        this.services = checkNotNull(services, "services is null");
+        this.templates = checkNotNull(templates, "templates is null");
+    }
+
+    @VisibleForTesting
+    void setId(String id) {
+        this.id = checkNotNull(id, "id is null");
+    }
+
+    @VisibleForTesting
+    void setPackages(List<String> packages) {
+        this.packages = ImmutableList.copyOf(packages);
+    }
+
+    @VisibleForTesting
+    void setTemplate(String template) {
+        this.template = checkNotNull(template, "template is null");
+    }
+
+    @VisibleForTesting
+    AdminAccess collectCurrentUserCredentialsForAdminAccess() {
+        String userHome = System.getProperty("user.home");
+
+        try {
+            String publicKey = Files.toString(new File(userHome, ".ssh/id_rsa.pub"), Charsets.UTF_8);
+            String privateKey = Files.toString(new File(userHome, ".ssh/id_rsa"), Charsets.UTF_8);
+
+            return AdminAccess.builder().username(System.getProperty("user.name"))
+                .publicKey(publicKey).privateKey(privateKey).createAdminAccess();
+        } catch (Exception e) {
+            throw Throwables.propagate(e);
+        }
+    }
+
+    @VisibleForTesting
+    Pool applyTemplate(Pool pool) {
+        for (PoolTemplate candidate : templates) {
+            if (candidate.getId().equalsIgnoreCase(template)) {
+                return candidate.apply(pool);
+            }
+        }
+        throw new NoSuchElementException("No pool template found with name: " + template);
+    }
+
+    @VisibleForTesting
+    Network buildNetwork(List<Integer> ports) {
+        /* Always allow ICMP and ssh traffic by default */
+        return Network.builder().addRules(
+            Rule.builder().anySource().icmp().createRule(),
+            Rule.builder().anySource().tcp().port(22).createRule()
+        ).addRules(
+            formatPortsAsIngressRules(ports)
+        ).createNetwork();
+    }
+
+    Optional<Provider> getDefaultProvider(Provisionr service) {
+        checkArgument(service.getDefaultProvider().isPresent(), String.format("please configure a default provider " +
+            "by editing etc/com.axemblr.provisionr.%s.cfg", id));
+        return service.getDefaultProvider();
+    }
+
+    Provisionr getService() {
+        Optional<Provisionr> service = Iterables.tryFind(services, ProvisionrPredicates.withId(id));
+        if (!service.isPresent()) {
+            throw new NoSuchElementException("No provisioning service found with id: " + id);
+        }
+        return service.get();
+    }
+
+    private Set<Rule> formatPortsAsIngressRules(List<Integer> ports) {
+        ImmutableSet.Builder<Rule> rules = ImmutableSet.builder();
+        for (int port : ports) {
+            rules.add(Rule.builder().anySource().tcp().port(port).createRule());
+        }
+        return rules.build();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-provisionr/blob/6559ede8/karaf/commands/src/main/java/com/axemblr/provisionr/commands/CreateImageCommand.java
----------------------------------------------------------------------
diff --git a/karaf/commands/src/main/java/com/axemblr/provisionr/commands/CreateImageCommand.java b/karaf/commands/src/main/java/com/axemblr/provisionr/commands/CreateImageCommand.java
new file mode 100644
index 0000000..e5ec778
--- /dev/null
+++ b/karaf/commands/src/main/java/com/axemblr/provisionr/commands/CreateImageCommand.java
@@ -0,0 +1,61 @@
+package com.axemblr.provisionr.commands;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.axemblr.provisionr.api.Provisionr;
+import com.axemblr.provisionr.api.hardware.Hardware;
+import com.axemblr.provisionr.api.hardware.HardwareBuilder;
+import com.axemblr.provisionr.api.pool.Pool;
+import com.axemblr.provisionr.api.software.Software;
+import com.axemblr.provisionr.commands.predicates.ProvisionrPredicates;
+import com.axemblr.provisionr.core.templates.PoolTemplate;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Optional;
+import com.google.common.collect.Iterables;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import org.apache.felix.gogo.commands.Command;
+
+@Command(scope = "provisionr", name = "cache", description = "Create a cached golden image.")
+public class CreateImageCommand extends CreateCommand {
+
+    // TODO: remove this and use a provided parameter
+    private static final String HARDWARE_TYPE = "t1.micro";
+
+    public CreateImageCommand(List<Provisionr> services, List<PoolTemplate> templates) {
+        super(services, templates);
+    }
+
+    @Override
+    protected Object doExecute() throws Exception {
+        Provisionr service = getService();
+        final Pool pool = createPoolOfOne(service);
+        // TODO: create service.startCachingProcess(uuid, pool) in the Provisionr class
+        return null;
+    }
+
+    @VisibleForTesting
+    Pool createPoolOfOne(Provisionr service) {
+
+        final Software software = Software.builder().packages(packages).createSoftware();
+        final Hardware hardware = Hardware.builder().type(HARDWARE_TYPE).createHardware();
+
+        final Pool pool = Pool.builder()
+                .provider(getDefaultProvider(service).get())
+                .hardware(hardware)
+                .software(software)
+                .network(buildNetwork(new ArrayList<Integer>()))
+                .adminAccess(collectCurrentUserCredentialsForAdminAccess())
+                .minSize(1)
+                .expectedSize(1)
+                .bootstrapTimeInSeconds(bootstrapTimeout)
+                .createPool();
+
+        return template != null ? applyTemplate(pool) : pool;
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-provisionr/blob/6559ede8/karaf/commands/src/main/java/com/axemblr/provisionr/commands/CreatePoolCommand.java
----------------------------------------------------------------------
diff --git a/karaf/commands/src/main/java/com/axemblr/provisionr/commands/CreatePoolCommand.java b/karaf/commands/src/main/java/com/axemblr/provisionr/commands/CreatePoolCommand.java
index dc6d1b8..ae7514f 100644
--- a/karaf/commands/src/main/java/com/axemblr/provisionr/commands/CreatePoolCommand.java
+++ b/karaf/commands/src/main/java/com/axemblr/provisionr/commands/CreatePoolCommand.java
@@ -59,10 +59,7 @@ import org.apache.karaf.shell.console.OsgiCommandSupport;
  * --port 80 --port 443 --package nginx --package gunicorn --package python-pip
  */
 @Command(scope = "provisionr", name = "create", description = "Create pool of virtual machines")
-public class CreatePoolCommand extends OsgiCommandSupport {
-
-    @Option(name = "--id", description = "Service ID (use provisionr:services)", required = true)
-    private String id;
+public class CreatePoolCommand extends CreateCommand {
 
     @Option(name = "-k", aliases = "--key", description = "Unique business identifier for this pool", required = true)
     private String key;
@@ -70,65 +67,45 @@ public class CreatePoolCommand extends OsgiCommandSupport {
     @Option(name = "-s", aliases = "--size", description = "Expected pool size")
     private int size = 1;
 
-    @Option(name = "-t", aliases = "--template", description = "Pool pre-configured template")
-    private String template;
-
     @Option(name = "-h", aliases = "--hardware-type", description = "Virtual machine hardware type")
     private String hardwareType = "t1.micro";
 
-    @Option(name = "--timeout", description = "Timeout in seconds for the pool's initialization steps. " +
-        "If not specified, defaults to 600 seconds.")
-    private int bootstrapTimeout = 600;
+    @Option(name = "--port", description = "Firewall ports that need to be open for any TCP traffic " +
+            "(multi-valued). SSH (22) is always open by default.", multiValued = true)
+    private List<Integer> ports = Lists.newArrayList();
 
     @Option(name = "--volume", description = "Block devices that will be attached to each instance. " +
         "(multi-valued) Expects the following format: [mapping]:[size in GB]. ", multiValued = true)
     private List<String> blockDeviceOptions = Lists.newArrayList();
 
-    @Option(name = "-o", aliases = "--provider-options", description = "Provider-specific options (multi-valued)." +
-        "Expects either the key=value format or just plain key. If value is not specified, defaults to 'true'." +
+    @Option(name = "-o", aliases = "--provider-options", description = "Provider-specific options (multi-valued). " +
+        "Expects either the key=value format or just plain key. If value is not specified, defaults to 'true'. " +
         "Supported values: spotBid=x.xxx (Amazon).", multiValued = true)
     private List<String> providerOptions = Lists.newArrayList();
 
-    @Option(name = "--port", description = "Firewall port that need to be open for any TCP traffic " +
-        "(multi-valued). SSH (22) is always open by default.", multiValued = true)
-    private List<Integer> ports = Lists.newArrayList();
-
-    @Option(name = "--package", description = "Package to install by default (multi-valued)",
-        multiValued = true)
-    private List<String> packages = Lists.newArrayList();
-
-    @Option(name = "--cache", description = "Cache base operating system image (including files & packages)")
-    private boolean cacheBaseImage = false;
+    @Option(name = "--image-id", description = "The id of the OS image with which the machines will be created.")
+    private String imageId = "";
 
-    private final List<Provisionr> services;
-
-    private final List<PoolTemplate> templates;
+    @Option(name = "--cached-image", description = "If the machines will have their packages and files downloaded " +
+        "or not. If creating the machines from an existent image, software might already be installed.")
+    private boolean cachedImage = false;
 
     public CreatePoolCommand(List<Provisionr> services, List<PoolTemplate> templates) {
-        this.services = checkNotNull(services, "services is null");
-        this.templates = checkNotNull(templates, "templates is null");
+        super(services, templates);
     }
 
     @Override
     protected Object doExecute() throws Exception {
         checkArgument(size > 0, "size should be a positive integer");
 
-        Optional<Provisionr> service = Iterables.tryFind(services, ProvisionrPredicates.withId(id));
-        if (service.isPresent()) {
-            final Pool pool = createPoolFromArgumentsAndServiceDefaults(service.get());
-
-            final String processInstanceId = service.get().startPoolManagementProcess(key, pool);
-            return String.format("Pool management process started (id: %s)", processInstanceId);
-        } else {
-            throw new NoSuchElementException("No provisioning service found with id: " + id);
-        }
+        Provisionr service = getService();
+        final Pool pool = createPoolFromArgumentsAndServiceDefaults(service);
+        final String processInstanceId = service.startPoolManagementProcess(key, pool);
+        return String.format("Pool management process started (id: %s)", processInstanceId);
     }
 
-    @VisibleForTesting
     Pool createPoolFromArgumentsAndServiceDefaults(Provisionr service) {
-        final Optional<Provider> defaultProvider = service.getDefaultProvider();
-        checkArgument(defaultProvider.isPresent(), String.format("please configure a default provider " +
-            "by editing etc/com.axemblr.provisionr.%s.cfg", id));
+        final Optional<Provider> defaultProvider = getDefaultProvider(service);
 
         /* append the provider options that were passed in and rebuild the default provider */
         // TODO: this currently does not support overriding default options, it will throw an exception
@@ -138,43 +115,28 @@ public class CreatePoolCommand extends OsgiCommandSupport {
                 .build();
         Provider provider = defaultProvider.get().toBuilder().options(options).createProvider();
 
-        /* Always allow ICMP and ssh traffic by default */
-        final Network network = Network.builder().addRules(
-            Rule.builder().anySource().icmp().createRule(),
-            Rule.builder().anySource().tcp().port(22).createRule()
-        ).addRules(
-            formatPortsAsIngressRules()
-        ).createNetwork();
-
+        final Software software = Software.builder()
+                .packages(packages)
+                .imageId(imageId)
+                .cachedImage(cachedImage)
+                .createSoftware();
         final Hardware hardware = Hardware.builder()
                 .type(hardwareType)
                 .blockDevices(parseBlockDeviceOptions(blockDeviceOptions))
                 .createHardware();
 
-        final Software software = Software.builder().packages(packages).createSoftware();
-
         final Pool pool = Pool.builder()
-            .provider(provider)
-            .hardware(hardware)
-            .software(software)
-            .network(network)
-            .adminAccess(collectCurrentUserCredentialsForAdminAccess())
-            .minSize(size)
-            .expectedSize(size)
-            .cacheBaseImage(cacheBaseImage)
-            .bootstrapTimeInSeconds(bootstrapTimeout)
-            .createPool();
+                .provider(provider)
+                .hardware(hardware)
+                .software(software)
+                .network(buildNetwork(ports))
+                .adminAccess(collectCurrentUserCredentialsForAdminAccess())
+                .minSize(size)
+                .expectedSize(size)
+                .bootstrapTimeInSeconds(bootstrapTimeout)
+                .createPool();
 
-        if (template != null) {
-            for (PoolTemplate candidate : templates) {
-                if (candidate.getId().equalsIgnoreCase(template)) {
-                    return candidate.apply(pool);
-                }
-            }
-            throw new NoSuchElementException("No pool template found with name: " + template);
-        }
-
-        return pool;
+        return template != null ? applyTemplate(pool) : pool;
     }
 
     private List<BlockDevice> parseBlockDeviceOptions(List<String> options) {
@@ -197,33 +159,6 @@ public class CreatePoolCommand extends OsgiCommandSupport {
         return result;
     }
 
-    private Set<Rule> formatPortsAsIngressRules() {
-        ImmutableSet.Builder<Rule> rules = ImmutableSet.builder();
-        for (int port : ports) {
-            rules.add(Rule.builder().anySource().tcp().port(port).createRule());
-        }
-        return rules.build();
-    }
-
-    protected AdminAccess collectCurrentUserCredentialsForAdminAccess() {
-        String userHome = System.getProperty("user.home");
-
-        try {
-            String publicKey = Files.toString(new File(userHome, ".ssh/id_rsa.pub"), Charsets.UTF_8);
-            String privateKey = Files.toString(new File(userHome, ".ssh/id_rsa"), Charsets.UTF_8);
-
-            return AdminAccess.builder().username(System.getProperty("user.name"))
-                .publicKey(publicKey).privateKey(privateKey).createAdminAccess();
-        } catch (Exception e) {
-            throw Throwables.propagate(e);
-        }
-    }
-
-    @VisibleForTesting
-    void setId(String id) {
-        this.id = checkNotNull(id, "id is null");
-    }
-
     @VisibleForTesting
     void setKey(String key) {
         this.key = checkNotNull(key, "key is null");
@@ -236,11 +171,6 @@ public class CreatePoolCommand extends OsgiCommandSupport {
     }
 
     @VisibleForTesting
-    void setTemplate(String template) {
-        this.template = checkNotNull(template, "template is null");
-    }
-
-    @VisibleForTesting
     void setHardwareType(String hardwareType) {
         this.hardwareType = checkNotNull(hardwareType, "hardwareType is null");
     }
@@ -251,11 +181,6 @@ public class CreatePoolCommand extends OsgiCommandSupport {
     }
 
     @VisibleForTesting
-    void setPackages(List<String> packages) {
-        this.packages = ImmutableList.copyOf(packages);
-    }
-
-    @VisibleForTesting
     void setProviderOptions(List<String> providerOptions) {
         this.providerOptions = ImmutableList.copyOf(providerOptions);
     }
@@ -266,7 +191,7 @@ public class CreatePoolCommand extends OsgiCommandSupport {
     }
 
     @VisibleForTesting
-    void setCacheBaseImage(boolean cacheBaseImage) {
-        this.cacheBaseImage = cacheBaseImage;
+    void setCachedImage(boolean cachedImage) {
+        this.cachedImage = cachedImage;
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-provisionr/blob/6559ede8/karaf/commands/src/test/java/com/axemblr/provisionr/commands/CreatePoolCommandTest.java
----------------------------------------------------------------------
diff --git a/karaf/commands/src/test/java/com/axemblr/provisionr/commands/CreatePoolCommandTest.java b/karaf/commands/src/test/java/com/axemblr/provisionr/commands/CreatePoolCommandTest.java
index 3a28556..7573ab7 100644
--- a/karaf/commands/src/test/java/com/axemblr/provisionr/commands/CreatePoolCommandTest.java
+++ b/karaf/commands/src/test/java/com/axemblr/provisionr/commands/CreatePoolCommandTest.java
@@ -24,7 +24,6 @@ import static org.mockito.Mockito.when;
 
 import com.axemblr.provisionr.api.Provisionr;
 import com.axemblr.provisionr.api.access.AdminAccess;
-import com.axemblr.provisionr.api.hardware.BlockDevice;
 import com.axemblr.provisionr.api.pool.Pool;
 import com.axemblr.provisionr.api.provider.Provider;
 import com.axemblr.provisionr.api.provider.ProviderBuilder;
@@ -38,7 +37,6 @@ import com.google.common.collect.Lists;
 import com.google.common.io.Resources;
 
 import java.io.IOException;
-import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;

http://git-wip-us.apache.org/repos/asf/incubator-provisionr/blob/6559ede8/providers/amazon-tests/src/test/java/com/axemblr/provisionr/amazon/AmazonProvisionrLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/amazon-tests/src/test/java/com/axemblr/provisionr/amazon/AmazonProvisionrLiveTest.java b/providers/amazon-tests/src/test/java/com/axemblr/provisionr/amazon/AmazonProvisionrLiveTest.java
index 4eea3e7..873c355 100644
--- a/providers/amazon-tests/src/test/java/com/axemblr/provisionr/amazon/AmazonProvisionrLiveTest.java
+++ b/providers/amazon-tests/src/test/java/com/axemblr/provisionr/amazon/AmazonProvisionrLiveTest.java
@@ -118,7 +118,7 @@ public class AmazonProvisionrLiveTest extends ProvisionrLiveTestSupport {
 
         final String destinationPath = "/home/" + adminAccess.getUsername() + "/axemblr.html";
         final Software software = Software.builder()
-            .baseOperatingSystem("ubuntu-12.04")
+            .imageId("default")
             .file("http://axemblr.com", destinationPath)
             .createSoftware();
 

http://git-wip-us.apache.org/repos/asf/incubator-provisionr/blob/6559ede8/providers/amazon/src/main/java/com/axemblr/provisionr/amazon/AmazonProvisionr.java
----------------------------------------------------------------------
diff --git a/providers/amazon/src/main/java/com/axemblr/provisionr/amazon/AmazonProvisionr.java b/providers/amazon/src/main/java/com/axemblr/provisionr/amazon/AmazonProvisionr.java
index 51aa2c8..4255df5 100644
--- a/providers/amazon/src/main/java/com/axemblr/provisionr/amazon/AmazonProvisionr.java
+++ b/providers/amazon/src/main/java/com/axemblr/provisionr/amazon/AmazonProvisionr.java
@@ -78,6 +78,7 @@ public class AmazonProvisionr extends ProvisionrSupport {
         arguments.put(CoreProcessVariables.POOL_BUSINESS_KEY, businessKey);
         arguments.put(CoreProcessVariables.BOOTSTRAP_TIMEOUT, 
                 convertTimeoutToISO8601TimeDuration(pool.getBootstrapTimeInSeconds()));
+        arguments.put(CoreProcessVariables.IS_CACHED_IMAGE, pool.getSoftware().isCachedImage());
 
         /* needed because the Activiti EL doesn't work as expected and properties can't be read from the pool. */
         arguments.put(ProcessVariables.SPOT_BID, pool.getProvider().getOption(ProviderOptions.SPOT_BID));

http://git-wip-us.apache.org/repos/asf/incubator-provisionr/blob/6559ede8/providers/amazon/src/main/java/com/axemblr/provisionr/amazon/ProcessVariables.java
----------------------------------------------------------------------
diff --git a/providers/amazon/src/main/java/com/axemblr/provisionr/amazon/ProcessVariables.java b/providers/amazon/src/main/java/com/axemblr/provisionr/amazon/ProcessVariables.java
index d6795a5..1fc6459 100644
--- a/providers/amazon/src/main/java/com/axemblr/provisionr/amazon/ProcessVariables.java
+++ b/providers/amazon/src/main/java/com/axemblr/provisionr/amazon/ProcessVariables.java
@@ -23,9 +23,9 @@ public class ProcessVariables {
     }
 
     /**
-     * ID of the cached base image
+     * ID of a base image from which to create the others in the pool
      */
-    public static final String CACHED_IMAGE_ID = "cachedImageId";
+    public static final String IMAGE_ID = "imageId";
 
     /**
      * The reservation ID for a pool as String

http://git-wip-us.apache.org/repos/asf/incubator-provisionr/blob/6559ede8/providers/amazon/src/main/java/com/axemblr/provisionr/amazon/activities/DumpConsoleOutput.java
----------------------------------------------------------------------
diff --git a/providers/amazon/src/main/java/com/axemblr/provisionr/amazon/activities/DumpConsoleOutput.java b/providers/amazon/src/main/java/com/axemblr/provisionr/amazon/activities/DumpConsoleOutput.java
index 8fcf8f6..9a792d8 100644
--- a/providers/amazon/src/main/java/com/axemblr/provisionr/amazon/activities/DumpConsoleOutput.java
+++ b/providers/amazon/src/main/java/com/axemblr/provisionr/amazon/activities/DumpConsoleOutput.java
@@ -45,8 +45,11 @@ public class DumpConsoleOutput extends AmazonActivity {
         LOG.info(">> Requesting console output for instance {}", machine.getExternalId());
         GetConsoleOutputResult result = client.getConsoleOutput(
             new GetConsoleOutputRequest().withInstanceId(machine.getExternalId()));
-        String content = new String(Base64.decode(result.getOutput()), Charsets.UTF_8);
-
-        LOG.info("<< Console output for instance {}: {}", machine.getExternalId(), content);
+        if (result.getOutput() != null) {
+            String content = new String(Base64.decode(result.getOutput()), Charsets.UTF_8);
+            LOG.info("<< Console output for instance {}: {}", machine.getExternalId(), content);
+        } else {
+            LOG.warn("<< Console output was null for instance {}", machine.getExternalId());
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-provisionr/blob/6559ede8/providers/amazon/src/main/java/com/axemblr/provisionr/amazon/activities/RunInstances.java
----------------------------------------------------------------------
diff --git a/providers/amazon/src/main/java/com/axemblr/provisionr/amazon/activities/RunInstances.java b/providers/amazon/src/main/java/com/axemblr/provisionr/amazon/activities/RunInstances.java
index 33aa6c1..bd3d191 100644
--- a/providers/amazon/src/main/java/com/axemblr/provisionr/amazon/activities/RunInstances.java
+++ b/providers/amazon/src/main/java/com/axemblr/provisionr/amazon/activities/RunInstances.java
@@ -9,7 +9,6 @@ import com.amazonaws.services.ec2.model.LaunchSpecification;
 import com.amazonaws.services.ec2.model.RequestSpotInstancesRequest;
 import com.amazonaws.services.ec2.model.RunInstancesRequest;
 import com.amazonaws.services.ec2.model.SpotInstanceType;
-import com.axemblr.provisionr.amazon.ProcessVariables;
 import com.axemblr.provisionr.amazon.core.ImageTable;
 import com.axemblr.provisionr.amazon.core.ImageTableQuery;
 import com.axemblr.provisionr.amazon.core.KeyPairs;
@@ -21,6 +20,7 @@ import com.axemblr.provisionr.api.hardware.BlockDevice;
 import com.axemblr.provisionr.api.pool.Pool;
 import com.axemblr.provisionr.api.provider.Provider;
 import com.google.common.base.Charsets;
+import com.google.common.base.Strings;
 import com.google.common.base.Throwables;
 import com.google.common.collect.Lists;
 import com.google.common.io.Resources;
@@ -32,13 +32,12 @@ import java.util.List;
 import net.schmizz.sshj.common.Base64;
 
 import org.activiti.engine.delegate.DelegateExecution;
-import org.activiti.engine.delegate.VariableScope;
 
 public abstract class RunInstances extends AmazonActivity {
 
     public static final String DEFAULT_ARCH = "amd64";
     public static final String DEFAULT_TYPE = "instance-store";
-
+    public static final String DEFAULT_AMI_ID = "ami-0cdf4965"; // Ubuntu 12.10 x64
 
     protected RunInstances(ProviderClientCache providerClientCache) {
         super(providerClientCache);
@@ -62,8 +61,8 @@ public abstract class RunInstances extends AmazonActivity {
         final String keyPairName = KeyPairs.formatNameFromBusinessKey(businessKey);
 
         final String instanceType = pool.getHardware().getType();
-        final String imageId = getImageIdFromProcessVariablesOrQueryImageTable(
-            execution, pool.getProvider(), instanceType);
+        final String imageId = getImageIdFromPoolConfigurationOrQueryImageTable(
+            pool, pool.getProvider(), instanceType);
 
         final String userData = Resources.toString(Resources.getResource(RunInstances.class,
             "/com/axemblr/provisionr/amazon/userdata.sh"), Charsets.UTF_8);
@@ -114,12 +113,12 @@ public abstract class RunInstances extends AmazonActivity {
         }
     }
 
-    private String getImageIdFromProcessVariablesOrQueryImageTable(
-            VariableScope execution, Provider provider, String instanceType
+    private String getImageIdFromPoolConfigurationOrQueryImageTable(
+            Pool pool, Provider provider, String instanceType
         ) {
-            final String imageId = (String) execution.getVariable(ProcessVariables.CACHED_IMAGE_ID);
-            if (imageId != null) {
-                return imageId;
+            final String imageId = pool.getSoftware().getImageId();
+            if (!Strings.isNullOrEmpty(imageId)) {
+                return "default".equals(imageId) ? DEFAULT_AMI_ID : imageId;
             }
 
             ImageTable imageTable;

http://git-wip-us.apache.org/repos/asf/incubator-provisionr/blob/6559ede8/providers/amazon/src/main/resources/OSGI-INF/activiti/amazonMachineSetup.bpmn20.xml
----------------------------------------------------------------------
diff --git a/providers/amazon/src/main/resources/OSGI-INF/activiti/amazonMachineSetup.bpmn20.xml b/providers/amazon/src/main/resources/OSGI-INF/activiti/amazonMachineSetup.bpmn20.xml
index 9a70fe3..7f3f897 100644
--- a/providers/amazon/src/main/resources/OSGI-INF/activiti/amazonMachineSetup.bpmn20.xml
+++ b/providers/amazon/src/main/resources/OSGI-INF/activiti/amazonMachineSetup.bpmn20.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/test">
-  <process id="amazonMachineSetup" name="Amazon Machine Setup">
+  <process id="amazonMachineSetup" name="Amazon Machine Setup" isExecutable="true">
     <endEvent id="endevent1" name="End"></endEvent>
     <serviceTask id="setupAdminAccess" name="Setup Admin Access" activiti:async="true" activiti:exclusive="false" activiti:delegateExpression="${amazon_setupAdminAccess}"></serviceTask>
     <serviceTask id="dumpConsoleOutput" name="Dump Console Output" activiti:async="true" activiti:exclusive="false" activiti:delegateExpression="${amazon_dumpConsoleOutput}"></serviceTask>
@@ -15,107 +15,138 @@
         <timeDuration>PT5S</timeDuration>
       </timerEventDefinition>
     </intermediateCatchEvent>
-    <sequenceFlow id="flow7" name="" sourceRef="installSoftwarePackages" targetRef="endevent1"></sequenceFlow>
-    <sequenceFlow id="flow9" name="" sourceRef="dumpConsoleOutput" targetRef="setupAdminAccess"></sequenceFlow>
-    <sequenceFlow id="flow10" name="" sourceRef="setupAdminAccess" targetRef="downloadFiles"></sequenceFlow>
-    <sequenceFlow id="flow11" name="" sourceRef="downloadFiles" targetRef="installRepositories"></sequenceFlow>
-    <sequenceFlow id="flow12" name="" sourceRef="installRepositories" targetRef="installSoftwarePackages"></sequenceFlow>
-    <sequenceFlow id="flow13" name="" sourceRef="startevent1" targetRef="checkSshPortIsOpen"></sequenceFlow>
-    <sequenceFlow id="flow14" name="" sourceRef="checkSshPortIsOpen" targetRef="exclusivegateway1"></sequenceFlow>
+    <sequenceFlow id="flow7" sourceRef="installSoftwarePackages" targetRef="endevent1"></sequenceFlow>
+    <sequenceFlow id="flow9" sourceRef="dumpConsoleOutput" targetRef="setupAdminAccess"></sequenceFlow>
+    <sequenceFlow id="flow10" name="False" sourceRef="exclusivegateway2" targetRef="downloadFiles">
+      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${isCachedImage == false}]]></conditionExpression>
+    </sequenceFlow>
+    <sequenceFlow id="flow11" sourceRef="downloadFiles" targetRef="installRepositories"></sequenceFlow>
+    <sequenceFlow id="flow12" sourceRef="installRepositories" targetRef="installSoftwarePackages"></sequenceFlow>
+    <sequenceFlow id="flow13" sourceRef="startevent1" targetRef="checkSshPortIsOpen"></sequenceFlow>
+    <sequenceFlow id="flow14" sourceRef="checkSshPortIsOpen" targetRef="exclusivegateway1"></sequenceFlow>
     <sequenceFlow id="flow15" name="True" sourceRef="exclusivegateway1" targetRef="dumpConsoleOutput">
       <conditionExpression xsi:type="tFormalExpression"><![CDATA[${sshPortIsOpen == true}]]></conditionExpression>
     </sequenceFlow>
     <sequenceFlow id="flow16" name="False" sourceRef="exclusivegateway1" targetRef="timerintermediatecatchevent1">
       <conditionExpression xsi:type="tFormalExpression"><![CDATA[${sshPortIsOpen == false}]]></conditionExpression>
     </sequenceFlow>
-    <sequenceFlow id="flow17" name="" sourceRef="timerintermediatecatchevent1" targetRef="checkSshPortIsOpen"></sequenceFlow>
+    <sequenceFlow id="flow17" sourceRef="timerintermediatecatchevent1" targetRef="checkSshPortIsOpen"></sequenceFlow>
+    <exclusiveGateway id="exclusivegateway2" name="Exclusive Gateway"></exclusiveGateway>
+    <sequenceFlow id="flow18" sourceRef="setupAdminAccess" targetRef="exclusivegateway2"></sequenceFlow>
+    <sequenceFlow id="flow19" name="True" sourceRef="exclusivegateway2" targetRef="endevent1">
+      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${isCachedImage == true}]]></conditionExpression>
+    </sequenceFlow>
     <textAnnotation id="textannotation1" textFormat="text/plain">
-      <text><![CDATA[Wait until the SSH port is open on this machine]]></text>
+      <text>Wait until the SSH port is open on this machine</text>
     </textAnnotation>
-    <association id="association1" sourceRef="textannotation1" targetRef="exclusivegateway1" associationDirection="None"></association>
+    <association id="association1" sourceRef="textannotation1" targetRef="exclusivegateway1"></association>
+    <textAnnotation id="textannotation2">
+      <text>If using a cached image, we don't want to run the installation steps.</text>
+    </textAnnotation>
+    <association id="association2" sourceRef="exclusivegateway2" targetRef="textannotation2"></association>
   </process>
   <bpmndi:BPMNDiagram id="BPMNDiagram_amazonMachineSetup">
     <bpmndi:BPMNPlane bpmnElement="amazonMachineSetup" id="BPMNPlane_amazonMachineSetup">
       <bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
-        <omgdc:Bounds height="35" width="35" x="891" y="291"></omgdc:Bounds>
+        <omgdc:Bounds height="35.0" width="35.0" x="945.0" y="200.0"></omgdc:Bounds>
       </bpmndi:BPMNShape>
       <bpmndi:BPMNShape bpmnElement="setupAdminAccess" id="BPMNShape_setupAdminAccess">
-        <omgdc:Bounds height="55" width="105" x="471" y="190"></omgdc:Bounds>
+        <omgdc:Bounds height="55.0" width="105.0" x="471.0" y="190.0"></omgdc:Bounds>
       </bpmndi:BPMNShape>
       <bpmndi:BPMNShape bpmnElement="dumpConsoleOutput" id="BPMNShape_dumpConsoleOutput">
-        <omgdc:Bounds height="55" width="105" x="330" y="190"></omgdc:Bounds>
+        <omgdc:Bounds height="55.0" width="105.0" x="330.0" y="190.0"></omgdc:Bounds>
       </bpmndi:BPMNShape>
       <bpmndi:BPMNShape bpmnElement="installSoftwarePackages" id="BPMNShape_installSoftwarePackages">
-        <omgdc:Bounds height="55" width="105" x="741" y="281"></omgdc:Bounds>
+        <omgdc:Bounds height="55.0" width="105.0" x="910.0" y="281.0"></omgdc:Bounds>
       </bpmndi:BPMNShape>
       <bpmndi:BPMNShape bpmnElement="downloadFiles" id="BPMNShape_downloadFiles">
-        <omgdc:Bounds height="55" width="105" x="471" y="281"></omgdc:Bounds>
+        <omgdc:Bounds height="55.0" width="105.0" x="578.0" y="281.0"></omgdc:Bounds>
       </bpmndi:BPMNShape>
       <bpmndi:BPMNShape bpmnElement="installRepositories" id="BPMNShape_installRepositories">
-        <omgdc:Bounds height="55" width="105" x="602" y="281"></omgdc:Bounds>
+        <omgdc:Bounds height="55.0" width="105.0" x="733.0" y="281.0"></omgdc:Bounds>
       </bpmndi:BPMNShape>
       <bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">
-        <omgdc:Bounds height="35" width="35" x="30" y="200"></omgdc:Bounds>
+        <omgdc:Bounds height="35.0" width="35.0" x="30.0" y="200.0"></omgdc:Bounds>
       </bpmndi:BPMNShape>
       <bpmndi:BPMNShape bpmnElement="checkSshPortIsOpen" id="BPMNShape_checkSshPortIsOpen">
-        <omgdc:Bounds height="55" width="105" x="100" y="190"></omgdc:Bounds>
+        <omgdc:Bounds height="55.0" width="105.0" x="100.0" y="190.0"></omgdc:Bounds>
       </bpmndi:BPMNShape>
       <bpmndi:BPMNShape bpmnElement="exclusivegateway1" id="BPMNShape_exclusivegateway1">
-        <omgdc:Bounds height="40" width="40" x="250" y="197"></omgdc:Bounds>
+        <omgdc:Bounds height="40.0" width="40.0" x="250.0" y="197.0"></omgdc:Bounds>
       </bpmndi:BPMNShape>
       <bpmndi:BPMNShape bpmnElement="timerintermediatecatchevent1" id="BPMNShape_timerintermediatecatchevent1">
-        <omgdc:Bounds height="35" width="35" x="253" y="291"></omgdc:Bounds>
+        <omgdc:Bounds height="35.0" width="35.0" x="253.0" y="291.0"></omgdc:Bounds>
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape bpmnElement="textannotation1" id="BPMNShape_textannotation1">
+        <omgdc:Bounds height="50.0" width="100.0" x="160.0" y="110.0"></omgdc:Bounds>
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape bpmnElement="exclusivegateway2" id="BPMNShape_exclusivegateway2">
+        <omgdc:Bounds height="40.0" width="40.0" x="610.0" y="197.0"></omgdc:Bounds>
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape bpmnElement="textannotation2" id="BPMNShape_textannotation2">
+        <omgdc:Bounds height="61.0" width="100.0" x="520.0" y="99.0"></omgdc:Bounds>
       </bpmndi:BPMNShape>
       <bpmndi:BPMNEdge bpmnElement="flow7" id="BPMNEdge_flow7">
-        <omgdi:waypoint x="846" y="308"></omgdi:waypoint>
-        <omgdi:waypoint x="891" y="308"></omgdi:waypoint>
+        <omgdi:waypoint x="962.0" y="281.0"></omgdi:waypoint>
+        <omgdi:waypoint x="962.0" y="235.0"></omgdi:waypoint>
       </bpmndi:BPMNEdge>
       <bpmndi:BPMNEdge bpmnElement="flow9" id="BPMNEdge_flow9">
-        <omgdi:waypoint x="435" y="217"></omgdi:waypoint>
-        <omgdi:waypoint x="471" y="217"></omgdi:waypoint>
+        <omgdi:waypoint x="435.0" y="217.0"></omgdi:waypoint>
+        <omgdi:waypoint x="471.0" y="217.0"></omgdi:waypoint>
       </bpmndi:BPMNEdge>
       <bpmndi:BPMNEdge bpmnElement="flow10" id="BPMNEdge_flow10">
-        <omgdi:waypoint x="523" y="245"></omgdi:waypoint>
-        <omgdi:waypoint x="523" y="281"></omgdi:waypoint>
+        <omgdi:waypoint x="630.0" y="237.0"></omgdi:waypoint>
+        <omgdi:waypoint x="630.0" y="281.0"></omgdi:waypoint>
+        <bpmndi:BPMNLabel>
+          <omgdc:Bounds height="12.0" width="100.0" x="10.0" y="0.0"></omgdc:Bounds>
+        </bpmndi:BPMNLabel>
       </bpmndi:BPMNEdge>
       <bpmndi:BPMNEdge bpmnElement="flow11" id="BPMNEdge_flow11">
-        <omgdi:waypoint x="576" y="308"></omgdi:waypoint>
-        <omgdi:waypoint x="602" y="308"></omgdi:waypoint>
+        <omgdi:waypoint x="683.0" y="308.0"></omgdi:waypoint>
+        <omgdi:waypoint x="733.0" y="308.0"></omgdi:waypoint>
       </bpmndi:BPMNEdge>
       <bpmndi:BPMNEdge bpmnElement="flow12" id="BPMNEdge_flow12">
-        <omgdi:waypoint x="707" y="308"></omgdi:waypoint>
-        <omgdi:waypoint x="741" y="308"></omgdi:waypoint>
+        <omgdi:waypoint x="838.0" y="308.0"></omgdi:waypoint>
+        <omgdi:waypoint x="910.0" y="308.0"></omgdi:waypoint>
       </bpmndi:BPMNEdge>
       <bpmndi:BPMNEdge bpmnElement="flow13" id="BPMNEdge_flow13">
-        <omgdi:waypoint x="65" y="217"></omgdi:waypoint>
-        <omgdi:waypoint x="100" y="217"></omgdi:waypoint>
+        <omgdi:waypoint x="65.0" y="217.0"></omgdi:waypoint>
+        <omgdi:waypoint x="100.0" y="217.0"></omgdi:waypoint>
       </bpmndi:BPMNEdge>
       <bpmndi:BPMNEdge bpmnElement="flow14" id="BPMNEdge_flow14">
-        <omgdi:waypoint x="205" y="217"></omgdi:waypoint>
-        <omgdi:waypoint x="250" y="217"></omgdi:waypoint>
+        <omgdi:waypoint x="205.0" y="217.0"></omgdi:waypoint>
+        <omgdi:waypoint x="250.0" y="217.0"></omgdi:waypoint>
       </bpmndi:BPMNEdge>
       <bpmndi:BPMNEdge bpmnElement="flow15" id="BPMNEdge_flow15">
-        <omgdi:waypoint x="290" y="217"></omgdi:waypoint>
-        <omgdi:waypoint x="330" y="217"></omgdi:waypoint>
+        <omgdi:waypoint x="290.0" y="217.0"></omgdi:waypoint>
+        <omgdi:waypoint x="330.0" y="217.0"></omgdi:waypoint>
         <bpmndi:BPMNLabel>
-          <omgdc:Bounds height="12" width="100" x="-20" y="9"></omgdc:Bounds>
+          <omgdc:Bounds height="12.0" width="100.0" x="-20.0" y="9.0"></omgdc:Bounds>
         </bpmndi:BPMNLabel>
       </bpmndi:BPMNEdge>
       <bpmndi:BPMNEdge bpmnElement="flow16" id="BPMNEdge_flow16">
-        <omgdi:waypoint x="270" y="237"></omgdi:waypoint>
-        <omgdi:waypoint x="270" y="291"></omgdi:waypoint>
+        <omgdi:waypoint x="270.0" y="237.0"></omgdi:waypoint>
+        <omgdi:waypoint x="270.0" y="291.0"></omgdi:waypoint>
         <bpmndi:BPMNLabel>
-          <omgdc:Bounds height="12" width="100" x="-33" y="-12"></omgdc:Bounds>
+          <omgdc:Bounds height="12.0" width="100.0" x="-33.0" y="-12.0"></omgdc:Bounds>
         </bpmndi:BPMNLabel>
       </bpmndi:BPMNEdge>
       <bpmndi:BPMNEdge bpmnElement="flow17" id="BPMNEdge_flow17">
-        <omgdi:waypoint x="253" y="308"></omgdi:waypoint>
-        <omgdi:waypoint x="152" y="308"></omgdi:waypoint>
-        <omgdi:waypoint x="152" y="245"></omgdi:waypoint>
+        <omgdi:waypoint x="253.0" y="308.0"></omgdi:waypoint>
+        <omgdi:waypoint x="152.0" y="308.0"></omgdi:waypoint>
+        <omgdi:waypoint x="152.0" y="245.0"></omgdi:waypoint>
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge bpmnElement="flow18" id="BPMNEdge_flow18">
+        <omgdi:waypoint x="576.0" y="217.0"></omgdi:waypoint>
+        <omgdi:waypoint x="610.0" y="217.0"></omgdi:waypoint>
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge bpmnElement="flow19" id="BPMNEdge_flow19">
+        <omgdi:waypoint x="650.0" y="217.0"></omgdi:waypoint>
+        <omgdi:waypoint x="945.0" y="217.0"></omgdi:waypoint>
+        <bpmndi:BPMNLabel>
+          <omgdc:Bounds height="12.0" width="100.0" x="10.0" y="0.0"></omgdc:Bounds>
+        </bpmndi:BPMNLabel>
       </bpmndi:BPMNEdge>
-      <bpmndi:BPMNShape bpmnElement="textannotation1" id="BPMNShape_textannotation1">
-        <omgdc:Bounds height="50" width="100" x="160" y="110"></omgdc:Bounds>
-      </bpmndi:BPMNShape>
     </bpmndi:BPMNPlane>
   </bpmndi:BPMNDiagram>
 </definitions>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-provisionr/blob/6559ede8/providers/amazon/src/main/resources/com/axemblr/provisionr/amazon/userdata.sh
----------------------------------------------------------------------
diff --git a/providers/amazon/src/main/resources/com/axemblr/provisionr/amazon/userdata.sh b/providers/amazon/src/main/resources/com/axemblr/provisionr/amazon/userdata.sh
index fe2e088..9009fd6 100644
--- a/providers/amazon/src/main/resources/com/axemblr/provisionr/amazon/userdata.sh
+++ b/providers/amazon/src/main/resources/com/axemblr/provisionr/amazon/userdata.sh
@@ -10,7 +10,7 @@ wget http://apt.puppetlabs.com/puppetlabs-release-$DISTRIB_CODENAME.deb
 dpkg -i puppetlabs-release-$DISTRIB_CODENAME.deb
 
 apt-get update
-apt-get install puppet-common
+apt-get install -y puppet-common
 
 # TODO implement a special action for global package upgrades 
 # apt-get upgrade -y
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-provisionr/blob/6559ede8/providers/amazon/src/test/java/com/axemblr/provisionr/amazon/activities/CreatePoolLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/amazon/src/test/java/com/axemblr/provisionr/amazon/activities/CreatePoolLiveTest.java b/providers/amazon/src/test/java/com/axemblr/provisionr/amazon/activities/CreatePoolLiveTest.java
index 168f9b4..2bda59c 100644
--- a/providers/amazon/src/test/java/com/axemblr/provisionr/amazon/activities/CreatePoolLiveTest.java
+++ b/providers/amazon/src/test/java/com/axemblr/provisionr/amazon/activities/CreatePoolLiveTest.java
@@ -9,6 +9,7 @@ import com.axemblr.provisionr.api.hardware.Hardware;
 import com.axemblr.provisionr.api.network.Network;
 import com.axemblr.provisionr.api.network.Rule;
 import com.axemblr.provisionr.api.pool.Pool;
+import com.axemblr.provisionr.api.software.Software;
 import com.axemblr.provisionr.core.CoreProcessVariables;
 
 import java.util.ArrayList;
@@ -20,6 +21,7 @@ public abstract class CreatePoolLiveTest<T extends AmazonActivity> extends Amazo
     protected DelegateExecution execution;
     protected Pool pool;
     protected Hardware hardware;
+    protected Software software;
 
     @SuppressWarnings("unchecked")
     @Override
@@ -41,6 +43,8 @@ public abstract class CreatePoolLiveTest<T extends AmazonActivity> extends Amazo
         when(hardware.getType()).thenReturn("t1.micro");
         when(hardware.getBlockDevices()).thenReturn(new ArrayList<BlockDevice>());
 
+        software = mock(Software.class);
+
         when(pool.getProvider()).thenReturn(provider);
         when(pool.getAdminAccess()).thenReturn(adminAccess);
         when(pool.getNetwork()).thenReturn(network);

http://git-wip-us.apache.org/repos/asf/incubator-provisionr/blob/6559ede8/providers/amazon/src/test/java/com/axemblr/provisionr/amazon/activities/RunOnDemandInstancesLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/amazon/src/test/java/com/axemblr/provisionr/amazon/activities/RunOnDemandInstancesLiveTest.java b/providers/amazon/src/test/java/com/axemblr/provisionr/amazon/activities/RunOnDemandInstancesLiveTest.java
index e413825..d5bb4b1 100644
--- a/providers/amazon/src/test/java/com/axemblr/provisionr/amazon/activities/RunOnDemandInstancesLiveTest.java
+++ b/providers/amazon/src/test/java/com/axemblr/provisionr/amazon/activities/RunOnDemandInstancesLiveTest.java
@@ -45,6 +45,7 @@ import org.junit.Test;
 
 public class RunOnDemandInstancesLiveTest extends CreatePoolLiveTest<RunOnDemandInstances> {
 
+    private static final String UBUNTU_AMI_ID = "ami-1e831d77"; // Ubuntu 13.04 amd64
     private ProcessVariablesCollector collector;
 
     @Override
@@ -114,6 +115,21 @@ public class RunOnDemandInstancesLiveTest extends CreatePoolLiveTest<RunOnDemand
         assertThat(volumesResult.getVolumes().get(0).getSize()).isNotEqualTo(volumesResult.getVolumes().get(1).getSize());
     }
 
+    @Test
+    public void testRunInstancesWithABaseImageId() throws Exception {
+        when(software.getImageId()).thenReturn(UBUNTU_AMI_ID);
+        when(pool.getSoftware()).thenReturn(software);
+        activity.execute(execution);
+
+        @SuppressWarnings("unchecked")
+        List<String> instanceIds = (List<String>) collector.getVariable(ProcessVariables.INSTANCE_IDS);
+        DescribeInstancesResult result = client.describeInstances(new DescribeInstancesRequest()
+            .withInstanceIds(instanceIds));
+
+        Instance instance = result.getReservations().get(0).getInstances().get(0);
+        assertThat(instance.getImageId()).isEqualTo(UBUNTU_AMI_ID);
+    }
+
     @Override
     public void tearDown() throws Exception {
         @SuppressWarnings("unchecked")

http://git-wip-us.apache.org/repos/asf/incubator-provisionr/blob/6559ede8/providers/cloudstack-tests/src/test/java/com/axemblr/provisionr/cloudstack/CloudStackProvisionrLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/cloudstack-tests/src/test/java/com/axemblr/provisionr/cloudstack/CloudStackProvisionrLiveTest.java b/providers/cloudstack-tests/src/test/java/com/axemblr/provisionr/cloudstack/CloudStackProvisionrLiveTest.java
index 8de8f83..2a892ed 100644
--- a/providers/cloudstack-tests/src/test/java/com/axemblr/provisionr/cloudstack/CloudStackProvisionrLiveTest.java
+++ b/providers/cloudstack-tests/src/test/java/com/axemblr/provisionr/cloudstack/CloudStackProvisionrLiveTest.java
@@ -76,7 +76,7 @@ public class CloudStackProvisionrLiveTest extends ProvisionrLiveTestSupport {
             .addRules(Rule.builder().anySource().tcp().port(22).createRule())
             .createNetwork();
 
-        final Software software = Software.builder().baseOperatingSystem("ubuntu-10.04")
+        final Software software = Software.builder().imageId("ubuntu-10.04")
             .packages("nginx").createSoftware();
 
         final AdminAccess adminAccess = AdminAccess.builder().asCurrentUser().createAdminAccess();

http://git-wip-us.apache.org/repos/asf/incubator-provisionr/blob/6559ede8/providers/cloudstack/src/main/java/com/axemblr/provisionr/cloudstack/activities/RunInstances.java
----------------------------------------------------------------------
diff --git a/providers/cloudstack/src/main/java/com/axemblr/provisionr/cloudstack/activities/RunInstances.java b/providers/cloudstack/src/main/java/com/axemblr/provisionr/cloudstack/activities/RunInstances.java
index 94d78df..f419f3e 100644
--- a/providers/cloudstack/src/main/java/com/axemblr/provisionr/cloudstack/activities/RunInstances.java
+++ b/providers/cloudstack/src/main/java/com/axemblr/provisionr/cloudstack/activities/RunInstances.java
@@ -39,7 +39,7 @@ public class RunInstances extends CloudStackActivity {
         final String keyPairName = KeyPairs.formatNameFromBusinessKey(businessKey);
 
         final String zoneId = pool.getOptions().get(ProviderOptions.ZONE_ID);
-        final String templateId = pool.getSoftware().getBaseOperatingSystem();
+        final String templateId = pool.getSoftware().getImageId();
         final String serviceOffering = pool.getHardware().getType();
 
         LOG.info("Starting instances!");

http://git-wip-us.apache.org/repos/asf/incubator-provisionr/blob/6559ede8/providers/cloudstack/src/test/java/com/axemblr/provisionr/cloudstack/activities/RunInstancesLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/cloudstack/src/test/java/com/axemblr/provisionr/cloudstack/activities/RunInstancesLiveTest.java b/providers/cloudstack/src/test/java/com/axemblr/provisionr/cloudstack/activities/RunInstancesLiveTest.java
index 8620526..02e7806 100644
--- a/providers/cloudstack/src/test/java/com/axemblr/provisionr/cloudstack/activities/RunInstancesLiveTest.java
+++ b/providers/cloudstack/src/test/java/com/axemblr/provisionr/cloudstack/activities/RunInstancesLiveTest.java
@@ -65,7 +65,7 @@ public class RunInstancesLiveTest extends CloudStackActivityLiveTest<RunInstance
 
         final Hardware hardware = Hardware.builder().type(getProviderProperty("serviceOffering")).createHardware();
         final Software software = Software.builder()
-            .baseOperatingSystem(getProviderProperty("templateId"))
+            .imageId(getProviderProperty("templateId"))
             .createSoftware();
 
         Map<String, String> options = ImmutableMap.of(ProviderOptions.ZONE_ID,


Mime
View raw message