You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@whirr.apache.org by as...@apache.org on 2012/02/06 00:10:03 UTC

svn commit: r1240854 [1/2] - in /whirr/trunk: ./ cli/ cli/src/main/java/org/apache/whirr/cli/command/ core/ core/src/main/java/org/apache/whirr/ core/src/main/java/org/apache/whirr/service/ core/src/main/java/org/apache/whirr/util/ core/src/main/resour...

Author: asavu
Date: Sun Feb  5 23:09:59 2012
New Revision: 1240854

URL: http://svn.apache.org/viewvc?rev=1240854&view=rev
Log:
WHIRR-436. Allow Whirr to run from inside OSGi (Ioannis Canellos via asavu)

Added:
    whirr/trunk/core/src/main/java/org/apache/whirr/DynamicClusterControllerFactory.java
    whirr/trunk/core/src/main/java/org/apache/whirr/DynamicHandlerMapFactory.java
    whirr/trunk/core/src/main/resources/OSGI-INF/
    whirr/trunk/core/src/main/resources/OSGI-INF/blueprint/
    whirr/trunk/core/src/main/resources/OSGI-INF/blueprint/blueprint.xml
    whirr/trunk/platforms/
    whirr/trunk/platforms/karaf/   (with props)
    whirr/trunk/platforms/karaf/commands/   (with props)
    whirr/trunk/platforms/karaf/commands/pom.xml
    whirr/trunk/platforms/karaf/commands/src/
    whirr/trunk/platforms/karaf/commands/src/main/
    whirr/trunk/platforms/karaf/commands/src/main/java/
    whirr/trunk/platforms/karaf/commands/src/main/java/org/
    whirr/trunk/platforms/karaf/commands/src/main/java/org/apache/
    whirr/trunk/platforms/karaf/commands/src/main/java/org/apache/whirr/
    whirr/trunk/platforms/karaf/commands/src/main/java/org/apache/whirr/karaf/
    whirr/trunk/platforms/karaf/commands/src/main/java/org/apache/whirr/karaf/command/
    whirr/trunk/platforms/karaf/commands/src/main/java/org/apache/whirr/karaf/command/DestroyCluster.java
    whirr/trunk/platforms/karaf/commands/src/main/java/org/apache/whirr/karaf/command/DestroyInstance.java
    whirr/trunk/platforms/karaf/commands/src/main/java/org/apache/whirr/karaf/command/LaunchCluster.java
    whirr/trunk/platforms/karaf/commands/src/main/java/org/apache/whirr/karaf/command/ListCluster.java
    whirr/trunk/platforms/karaf/commands/src/main/java/org/apache/whirr/karaf/command/RunScript.java
    whirr/trunk/platforms/karaf/commands/src/main/java/org/apache/whirr/karaf/command/support/
    whirr/trunk/platforms/karaf/commands/src/main/java/org/apache/whirr/karaf/command/support/ConfigurationReader.java
    whirr/trunk/platforms/karaf/commands/src/main/java/org/apache/whirr/karaf/command/support/WhirrCommandSupport.java
    whirr/trunk/platforms/karaf/commands/src/main/resources/
    whirr/trunk/platforms/karaf/commands/src/main/resources/OSGI-INF/
    whirr/trunk/platforms/karaf/commands/src/main/resources/OSGI-INF/blueprint/
    whirr/trunk/platforms/karaf/commands/src/main/resources/OSGI-INF/blueprint/blueprint.xml
    whirr/trunk/platforms/karaf/feature/   (with props)
    whirr/trunk/platforms/karaf/feature/pom.xml
    whirr/trunk/platforms/karaf/feature/src/
    whirr/trunk/platforms/karaf/feature/src/main/
    whirr/trunk/platforms/karaf/feature/src/main/resources/
    whirr/trunk/platforms/karaf/feature/src/main/resources/features.xml
    whirr/trunk/platforms/karaf/itests/   (with props)
    whirr/trunk/platforms/karaf/itests/pom.xml
    whirr/trunk/platforms/karaf/itests/src/
    whirr/trunk/platforms/karaf/itests/src/test/
    whirr/trunk/platforms/karaf/itests/src/test/java/
    whirr/trunk/platforms/karaf/itests/src/test/java/org/
    whirr/trunk/platforms/karaf/itests/src/test/java/org/apache/
    whirr/trunk/platforms/karaf/itests/src/test/java/org/apache/whirr/
    whirr/trunk/platforms/karaf/itests/src/test/java/org/apache/whirr/karaf/
    whirr/trunk/platforms/karaf/itests/src/test/java/org/apache/whirr/karaf/itest/
    whirr/trunk/platforms/karaf/itests/src/test/java/org/apache/whirr/karaf/itest/WhirrInstallationTest.java
    whirr/trunk/platforms/karaf/itests/src/test/java/org/apache/whirr/karaf/itest/WhirrKarafTestSupport.java
    whirr/trunk/platforms/karaf/itests/src/test/java/org/apache/whirr/karaf/itest/WhirrServicesTest.java
    whirr/trunk/platforms/karaf/pom.xml
    whirr/trunk/services/cassandra/src/main/resources/OSGI-INF/
    whirr/trunk/services/cassandra/src/main/resources/OSGI-INF/blueprint/
    whirr/trunk/services/cassandra/src/main/resources/OSGI-INF/blueprint/blueprint.xml
    whirr/trunk/services/chef/src/main/resources/OSGI-INF/
    whirr/trunk/services/chef/src/main/resources/OSGI-INF/blueprint/
    whirr/trunk/services/chef/src/main/resources/OSGI-INF/blueprint/blueprint.xml
    whirr/trunk/services/elasticsearch/src/main/resources/OSGI-INF/
    whirr/trunk/services/elasticsearch/src/main/resources/OSGI-INF/blueprint/
    whirr/trunk/services/elasticsearch/src/main/resources/OSGI-INF/blueprint/blueprint.xml
    whirr/trunk/services/ganglia/src/main/resources/OSGI-INF/
    whirr/trunk/services/ganglia/src/main/resources/OSGI-INF/blueprint/
    whirr/trunk/services/ganglia/src/main/resources/OSGI-INF/blueprint/blueprint.xml
    whirr/trunk/services/hadoop/src/main/resources/OSGI-INF/
    whirr/trunk/services/hadoop/src/main/resources/OSGI-INF/blueprint/
    whirr/trunk/services/hadoop/src/main/resources/OSGI-INF/blueprint/blueprint.xml
    whirr/trunk/services/hama/src/main/resources/OSGI-INF/
    whirr/trunk/services/hama/src/main/resources/OSGI-INF/blueprint/
    whirr/trunk/services/hama/src/main/resources/OSGI-INF/blueprint/blueprint.xml
    whirr/trunk/services/hbase/src/main/resources/OSGI-INF/
    whirr/trunk/services/hbase/src/main/resources/OSGI-INF/blueprint/
    whirr/trunk/services/hbase/src/main/resources/OSGI-INF/blueprint/blueprint.xml
    whirr/trunk/services/mahout/src/main/resources/OSGI-INF/
    whirr/trunk/services/mahout/src/main/resources/OSGI-INF/blueprint/
    whirr/trunk/services/mahout/src/main/resources/OSGI-INF/blueprint/blueprint.xml
    whirr/trunk/services/puppet/src/main/resources/OSGI-INF/
    whirr/trunk/services/puppet/src/main/resources/OSGI-INF/blueprint/
    whirr/trunk/services/puppet/src/main/resources/OSGI-INF/blueprint/blueprint.xml
    whirr/trunk/services/voldemort/src/main/resources/OSGI-INF/
    whirr/trunk/services/voldemort/src/main/resources/OSGI-INF/blueprint/
    whirr/trunk/services/voldemort/src/main/resources/OSGI-INF/blueprint/blueprint.xml
    whirr/trunk/services/zookeeper/src/main/resources/OSGI-INF/
    whirr/trunk/services/zookeeper/src/main/resources/OSGI-INF/blueprint/
    whirr/trunk/services/zookeeper/src/main/resources/OSGI-INF/blueprint/blueprint.xml
Modified:
    whirr/trunk/   (props changed)
    whirr/trunk/CHANGES.txt
    whirr/trunk/cli/pom.xml
    whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/DestroyClusterCommand.java
    whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/DestroyInstanceCommand.java
    whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/LaunchClusterCommand.java
    whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/ListClusterCommand.java
    whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/ListProvidersCommand.java
    whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/RunScriptCommand.java
    whirr/trunk/core/pom.xml
    whirr/trunk/core/src/main/java/org/apache/whirr/ByonClusterController.java
    whirr/trunk/core/src/main/java/org/apache/whirr/ClusterController.java
    whirr/trunk/core/src/main/java/org/apache/whirr/ClusterSpec.java
    whirr/trunk/core/src/main/java/org/apache/whirr/HandlerMapFactory.java
    whirr/trunk/core/src/main/java/org/apache/whirr/service/ClusterActionHandler.java
    whirr/trunk/core/src/main/java/org/apache/whirr/service/ClusterActionHandlerSupport.java
    whirr/trunk/core/src/main/java/org/apache/whirr/util/Utils.java
    whirr/trunk/core/src/test/java/org/apache/whirr/actions/BootstrapClusterActionTest.java
    whirr/trunk/core/src/test/java/org/apache/whirr/actions/ScriptBasedClusterActionTest.java
    whirr/trunk/core/src/test/java/org/apache/whirr/util/UtilsTest.java
    whirr/trunk/examples/pom.xml
    whirr/trunk/pom.xml
    whirr/trunk/services/cassandra/pom.xml
    whirr/trunk/services/cdh/pom.xml
    whirr/trunk/services/chef/pom.xml
    whirr/trunk/services/elasticsearch/pom.xml
    whirr/trunk/services/ganglia/pom.xml
    whirr/trunk/services/hadoop/pom.xml
    whirr/trunk/services/hama/pom.xml
    whirr/trunk/services/hbase/pom.xml
    whirr/trunk/services/mahout/pom.xml
    whirr/trunk/services/puppet/pom.xml
    whirr/trunk/services/puppet/src/test/java/org/apache/whirr/service/puppet/PuppetClusterActionHandlerFactoryTest.java
    whirr/trunk/services/voldemort/pom.xml
    whirr/trunk/services/zookeeper/pom.xml

Propchange: whirr/trunk/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Sun Feb  5 23:09:59 2012
@@ -1,3 +1,4 @@
+.idea
 .git
 .project
 .classpath

Modified: whirr/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/whirr/trunk/CHANGES.txt?rev=1240854&r1=1240853&r2=1240854&view=diff
==============================================================================
--- whirr/trunk/CHANGES.txt (original)
+++ whirr/trunk/CHANGES.txt Sun Feb  5 23:09:59 2012
@@ -43,6 +43,8 @@ Trunk (unreleased changes)
 
     WHIRR-498. Update the list of known limitations (asavu)
 
+    WHIRR-436. Allow Whirr to run from inside OSGi (Ioannis Canellos via asavu)
+
   BUG FIXES
 
     WHIRR-367. Wrong groupId for zookeeper (Joe Crobak via asavu)

Modified: whirr/trunk/cli/pom.xml
URL: http://svn.apache.org/viewvc/whirr/trunk/cli/pom.xml?rev=1240854&r1=1240853&r2=1240854&view=diff
==============================================================================
--- whirr/trunk/cli/pom.xml (original)
+++ whirr/trunk/cli/pom.xml Sun Feb  5 23:09:59 2012
@@ -25,9 +25,20 @@
   </parent>
   <groupId>org.apache.whirr</groupId>
   <artifactId>whirr-cli</artifactId>
-  <packaging>jar</packaging>
-  <version>0.8.0-SNAPSHOT</version>
+  <packaging>bundle</packaging>
   <name>Apache Whirr CLI</name>
+  <properties>
+    <osgi.import>
+      !org.apache.whirr.cli*,
+      org.apache.commons.configuration*;version="[1.6,2)",
+      *
+    </osgi.import>
+    <osgi.dynamic.import>javax.*,org.jclouds.*</osgi.dynamic.import>
+    <osgi.export>
+      org.apache.whirr.cli*;version="${project.version}"
+    </osgi.export>
+    <osgi.spi.consumer>*</osgi.spi.consumer>
+  </properties>
   <dependencies>
     <dependency>
       <groupId>${project.groupId}</groupId>

Modified: whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/DestroyClusterCommand.java
URL: http://svn.apache.org/viewvc/whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/DestroyClusterCommand.java?rev=1240854&r1=1240853&r2=1240854&view=diff
==============================================================================
--- whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/DestroyClusterCommand.java (original)
+++ whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/DestroyClusterCommand.java Sun Feb  5 23:09:59 2012
@@ -18,18 +18,17 @@
 
 package org.apache.whirr.cli.command;
 
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.PrintStream;
-import java.util.List;
-
 import joptsimple.OptionSet;
-
 import org.apache.whirr.ClusterController;
 import org.apache.whirr.ClusterControllerFactory;
 import org.apache.whirr.ClusterSpec;
 import org.apache.whirr.command.AbstractClusterCommand;
 
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintStream;
+import java.util.List;
+
 /**
  * A command to destroy a running cluster (terminate and cleanup).
  */
@@ -42,11 +41,11 @@ public class DestroyClusterCommand exten
   public DestroyClusterCommand(ClusterControllerFactory factory) {
     super("destroy-cluster", "Terminate and cleanup resources for a running cluster.", factory);
   }
-  
+
   @Override
   public int run(InputStream in, PrintStream out, PrintStream err,
-      List<String> args) throws Exception {
-    
+                 List<String> args) throws Exception {
+
     OptionSet optionSet = parser.parse(args.toArray(new String[0]));
 
     if (!optionSet.nonOptionArguments().isEmpty()) {
@@ -55,14 +54,19 @@ public class DestroyClusterCommand exten
     }
     try {
       ClusterSpec clusterSpec = getClusterSpec(optionSet);
+      return run(in, out, err, clusterSpec);
 
-      ClusterController controller = createClusterController(clusterSpec.getServiceName());
-      controller.destroyCluster(clusterSpec);
-      return 0;
     } catch (IllegalArgumentException e) {
       printErrorAndHelpHint(err, e);
       return -1;
     }
   }
 
+  public int run(InputStream in, PrintStream out, PrintStream err,
+                 ClusterSpec clusterSpec) throws Exception {
+    ClusterController controller = createClusterController(clusterSpec.getServiceName());
+    controller.destroyCluster(clusterSpec);
+    return 0;
+  }
+
 }

Modified: whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/DestroyInstanceCommand.java
URL: http://svn.apache.org/viewvc/whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/DestroyInstanceCommand.java?rev=1240854&r1=1240853&r2=1240854&view=diff
==============================================================================
--- whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/DestroyInstanceCommand.java (original)
+++ whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/DestroyInstanceCommand.java Sun Feb  5 23:09:59 2012
@@ -18,28 +18,27 @@
 
 package org.apache.whirr.cli.command;
 
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.PrintStream;
-import java.util.List;
-
 import joptsimple.OptionSet;
 import joptsimple.OptionSpec;
-
 import org.apache.whirr.ClusterController;
 import org.apache.whirr.ClusterControllerFactory;
 import org.apache.whirr.ClusterSpec;
 import org.apache.whirr.command.AbstractClusterCommand;
 
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintStream;
+import java.util.List;
+
 /**
  * A command to destroy an instance from a cluster
  */
 public class DestroyInstanceCommand extends AbstractClusterCommand {
 
   private OptionSpec<String> instanceOption = parser
-      .accepts("instance-id", "Cluster instance ID")
-      .withRequiredArg()
-      .ofType(String.class);
+    .accepts("instance-id", "Cluster instance ID")
+    .withRequiredArg()
+    .ofType(String.class);
 
   public DestroyInstanceCommand() throws IOException {
     this(new ClusterControllerFactory());
@@ -47,14 +46,14 @@ public class DestroyInstanceCommand exte
 
   public DestroyInstanceCommand(ClusterControllerFactory factory) {
     super("destroy-instance", "Terminate and cleanup resources " +
-        "for a single instance.", factory);
+      "for a single instance.", factory);
   }
 
   @Override
   public int run(InputStream in, PrintStream out,
                  PrintStream err, List<String> args) throws Exception {
 
-    OptionSet optionSet = parser.parse(args.toArray(new String[0]));
+    OptionSet optionSet = parser.parse(args.toArray(new String[args.size()]));
     if (!optionSet.nonOptionArguments().isEmpty()) {
       printUsage(err);
       return -1;
@@ -64,19 +63,23 @@ public class DestroyInstanceCommand exte
         throw new IllegalArgumentException("--instance-id is a mandatory argument");
       }
       ClusterSpec clusterSpec = getClusterSpec(optionSet);
-      ClusterController controller = createClusterController(clusterSpec.getServiceName());
-
       String instanceId = optionSet.valueOf(instanceOption);
-      controller.destroyInstance(clusterSpec, instanceId);
+      return run(in, out, err, clusterSpec, instanceId);
 
-      return 0;
-
-    } catch(IllegalArgumentException e) {
+    } catch (IllegalArgumentException e) {
       printErrorAndHelpHint(err, e);
       return -1;
     }
   }
 
+  public int run(InputStream in, PrintStream out, PrintStream err,
+                 ClusterSpec clusterSpec, String instanceId) throws Exception {
+    ClusterController controller = createClusterController(clusterSpec.getServiceName());
+    controller.destroyInstance(clusterSpec, instanceId);
+    return 0;
+  }
+
+
   @Override
   public void printUsage(PrintStream stream) throws IOException {
     stream.println("Usage: whirr destroy-instance --instance-id <region/ID> [OPTIONS]");

Modified: whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/LaunchClusterCommand.java
URL: http://svn.apache.org/viewvc/whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/LaunchClusterCommand.java?rev=1240854&r1=1240853&r2=1240854&view=diff
==============================================================================
--- whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/LaunchClusterCommand.java (original)
+++ whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/LaunchClusterCommand.java Sun Feb  5 23:09:59 2012
@@ -18,13 +18,7 @@
 
 package org.apache.whirr.cli.command;
 
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.PrintStream;
-import java.util.List;
-
 import joptsimple.OptionSet;
-
 import org.apache.whirr.Cluster;
 import org.apache.whirr.ClusterController;
 import org.apache.whirr.ClusterControllerFactory;
@@ -32,6 +26,11 @@ import org.apache.whirr.ClusterSpec;
 import org.apache.whirr.command.AbstractClusterCommand;
 import org.apache.whirr.util.Utils;
 
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintStream;
+import java.util.List;
+
 /**
  * A command to launch a new cluster.
  */
@@ -47,31 +46,34 @@ public class LaunchClusterCommand extend
 
   @Override
   public int run(InputStream in, PrintStream out, PrintStream err,
-      List<String> args) throws Exception {
-    
+                 List<String> args) throws Exception {
+
     OptionSet optionSet = parser.parse(args.toArray(new String[args.size()]));
 
     if (!optionSet.nonOptionArguments().isEmpty()) {
       printUsage(err);
       return -1;
     }
-    
+
     try {
       ClusterSpec clusterSpec = getClusterSpec(optionSet);
-      ClusterController controller = createClusterController(clusterSpec.getServiceName());
-      Cluster cluster = controller.launchCluster(clusterSpec);
-      out.printf("Started cluster of %s instances\n",
-          cluster.getInstances().size());
-      out.println(cluster);
-      
-      // print ssh command. do it for the first 20 instances so that the console
-      // won't be overflooded when launching a 1000 node cluster
-      Utils.printAccess(out, clusterSpec, cluster, 20);
-      
-      return 0;
+      return run(in, out, err, clusterSpec);
+
     } catch (IllegalArgumentException e) {
       printErrorAndHelpHint(err, e);
       return -1;
     }
   }
+
+  public int run(InputStream in, PrintStream out, PrintStream err, ClusterSpec clusterSpec) throws Exception {
+    ClusterController controller = createClusterController(clusterSpec.getServiceName());
+    Cluster cluster = controller.launchCluster(clusterSpec);
+    out.printf("Started cluster of %s instances\n",
+      cluster.getInstances().size());
+    out.println(cluster);
+
+    Utils.printSSHConnectionDetails(out, clusterSpec, cluster, 20);
+
+    return 0;
+  }
 }

Modified: whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/ListClusterCommand.java
URL: http://svn.apache.org/viewvc/whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/ListClusterCommand.java?rev=1240854&r1=1240853&r2=1240854&view=diff
==============================================================================
--- whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/ListClusterCommand.java (original)
+++ whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/ListClusterCommand.java Sun Feb  5 23:09:59 2012
@@ -19,14 +19,7 @@
 package org.apache.whirr.cli.command;
 
 import com.google.common.base.Joiner;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.PrintStream;
-import java.util.List;
-
 import joptsimple.OptionSet;
-
 import org.apache.whirr.Cluster;
 import org.apache.whirr.ClusterController;
 import org.apache.whirr.ClusterControllerFactory;
@@ -35,6 +28,11 @@ import org.apache.whirr.command.Abstract
 import org.apache.whirr.state.ClusterStateStore;
 import org.apache.whirr.state.ClusterStateStoreFactory;
 
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintStream;
+import java.util.List;
+
 /**
  * A command to list the nodes in a cluster.
  */
@@ -52,11 +50,11 @@ public class ListClusterCommand extends 
                             ClusterStateStoreFactory stateStoreFactory) {
     super("list-cluster", "List the nodes in a cluster.", factory, stateStoreFactory);
   }
-  
+
   @Override
   public int run(InputStream in, PrintStream out, PrintStream err,
-      List<String> args) throws Exception {
-    
+                 List<String> args) throws Exception {
+
     OptionSet optionSet = parser.parse(args.toArray(new String[args.size()]));
 
     if (!optionSet.nonOptionArguments().isEmpty()) {
@@ -65,25 +63,30 @@ public class ListClusterCommand extends 
     }
     try {
       ClusterSpec clusterSpec = getClusterSpec(optionSet);
-      ClusterStateStore stateStore = createClusterStateStore(clusterSpec);
-      ClusterController controller = createClusterController(clusterSpec.getServiceName());
+      return run(in, out, err, clusterSpec);
 
-      for (Cluster.Instance instance : controller.getInstances(clusterSpec, stateStore)) {
-        out.println(Joiner.on('\t').useForNull("-").join(
-            instance.getId(),
-            instance.getNodeMetadata().getImageId(),
-            instance.getPublicIp(),
-            instance.getPrivateIp(),
-            instance.getNodeMetadata().getState(),
-            instance.getNodeMetadata().getLocation().getId(),
-            Joiner.on(",").join(instance.getRoles())
-          )
-        );
-      }
-      return 0;
     } catch (IllegalArgumentException e) {
       printErrorAndHelpHint(err, e);
       return -1;
     }
   }
+
+  public int run(InputStream in, PrintStream out, PrintStream err, ClusterSpec clusterSpec) throws Exception {
+    ClusterStateStore stateStore = createClusterStateStore(clusterSpec);
+    ClusterController controller = createClusterController(clusterSpec.getServiceName());
+
+    for (Cluster.Instance instance : controller.getInstances(clusterSpec, stateStore)) {
+      out.println(Joiner.on('\t').useForNull("-").join(
+        instance.getId(),
+        instance.getNodeMetadata().getImageId(),
+        instance.getPublicIp(),
+        instance.getPrivateIp(),
+        instance.getNodeMetadata().getState(),
+        instance.getNodeMetadata().getLocation().getId(),
+        Joiner.on(",").join(instance.getRoles())
+      )
+      );
+    }
+    return 0;
+  }
 }

Modified: whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/ListProvidersCommand.java
URL: http://svn.apache.org/viewvc/whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/ListProvidersCommand.java?rev=1240854&r1=1240853&r2=1240854&view=diff
==============================================================================
--- whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/ListProvidersCommand.java (original)
+++ whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/ListProvidersCommand.java Sun Feb  5 23:09:59 2012
@@ -39,6 +39,10 @@ public class ListProvidersCommand extend
         new ClusterControllerFactory());
   }
 
+  public ListProvidersCommand(ClusterControllerFactory factory) {
+    super("list-providers", "Show a list of the supported providers", factory);
+  }
+
   @Override
   public int run(InputStream in, PrintStream out,
                  PrintStream err, List<String> args) throws Exception {
@@ -64,8 +68,8 @@ public class ListProvidersCommand extend
     out.println("Usage: whirr list-providers <compute OR blobstore>");
   }
 
-  private void listBlobstoreProviders(PrintStream out) {
-    for(ProviderMetadata blobstore : Providers.allBlobStore()) {
+  public void listBlobstoreProviders(Iterable<ProviderMetadata> blobstoreProviders, PrintStream out) {
+    for(ProviderMetadata blobstore : blobstoreProviders) {
       out.println("* " + blobstore.getName());
 
       out.println("\tHomepage: " + blobstore.getHomepage());
@@ -80,8 +84,12 @@ public class ListProvidersCommand extend
     }
   }
 
-  private void listComputeProviders(PrintStream out) {
-    for(ProviderMetadata provider : Providers.allCompute()) {
+  private void listBlobstoreProviders(PrintStream out) {
+    listBlobstoreProviders(Providers.allBlobStore(),out);
+  }
+
+  public void listComputeProviders(Iterable<ProviderMetadata> computeProviders,PrintStream out) {
+    for(ProviderMetadata provider : computeProviders) {
       if (testedComputeProviders.contains(provider.getId())) {
         out.println("* " + provider.getName() + " - tested");
       } else {
@@ -99,4 +107,8 @@ public class ListProvidersCommand extend
       out.println("\t\twhirr.credential = <" + provider.getCredentialName() + ">\n");
     }
   }
+
+  private void listComputeProviders(PrintStream out) {
+    listComputeProviders(Providers.allCompute(),out);
+  }
 }

Modified: whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/RunScriptCommand.java
URL: http://svn.apache.org/viewvc/whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/RunScriptCommand.java?rev=1240854&r1=1240853&r2=1240854&view=diff
==============================================================================
--- whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/RunScriptCommand.java (original)
+++ whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/RunScriptCommand.java Sun Feb  5 23:09:59 2012
@@ -76,7 +76,7 @@ public class RunScriptCommand extends Ab
   }
 
   public RunScriptCommand(ClusterControllerFactory factory,
-      ClusterStateStoreFactory stateStoreFactory) {
+                          ClusterStateStoreFactory stateStoreFactory) {
     super("run-script", "Run a script on a specific instance or a " +
       "group of instances matching a role name", factory, stateStoreFactory);
   }
@@ -97,47 +97,58 @@ public class RunScriptCommand extends Ab
       err.println("Get more help: whirr help " + getName());
       return -2;
     }
-
     try {
-      ClusterSpec spec = getClusterSpec(optionSet);
-      ClusterController controller = createClusterController(spec.getServiceName());
-
-      Predicate<NodeMetadata> condition = buildFilterPredicate(optionSet, spec);
-
-      return handleScriptOutput(out, err, controller.runScriptOnNodesMatching(
-        spec, condition, execFile(optionSet.valueOf(scriptOption))));
+      ClusterSpec clusterSpec = getClusterSpec(optionSet);
+      String[] ids = null;
+      String[] roles = null;
+      if (optionSet.has(instancesOption)) {
+        ids = optionSet.valueOf(instancesOption).split(",");
+      }
+      if (optionSet.has(rolesOption)) {
+        roles = optionSet.valueOf(rolesOption).split(",");
+      }
+      return run(in, out, err, clusterSpec, ids, roles, optionSet.valueOf(scriptOption));
 
-    } catch(IllegalArgumentException e) {
+    } catch (IllegalArgumentException e) {
       printErrorAndHelpHint(err, e);
       return -3;
     }
   }
 
-  private Predicate<NodeMetadata> buildFilterPredicate(OptionSet optionSet, ClusterSpec spec)
-      throws IOException {
+  public int run(InputStream in, PrintStream out, PrintStream err,
+                 ClusterSpec clusterSpec, String[] instances, String[] roles,
+                 String fileName) throws Exception {
+    ClusterController controller = createClusterController(clusterSpec.getServiceName());
+    Predicate<NodeMetadata> condition = buildFilterPredicate(instances, roles, clusterSpec);
+
+    return handleScriptOutput(out, err, controller.runScriptOnNodesMatching(
+      clusterSpec, condition, execFile(fileName)));
+  }
+
+  private Predicate<NodeMetadata> buildFilterPredicate(String[] ids, String[] roles, ClusterSpec spec)
+    throws IOException {
 
     Predicate<NodeMetadata> condition = Predicates.alwaysTrue();
-
-    if (optionSet.has(instancesOption)) {
-      String[] ids = optionSet.valueOf(instancesOption).split(",");
+    if (ids != null && ids.length > 0) {
       return Predicates.and(condition, withIds(ids));
-
-    } else if(optionSet.has(rolesOption)) {
-      String[] roles = optionSet.valueOf(rolesOption).split(",");
-      List<String> ids = Lists.newArrayList();
+    } else if (roles != null && roles.length > 0) {
+      List<String> instanceIds = Lists.newArrayList();
 
       Cluster cluster = createClusterStateStore(spec).load();
       for (Cluster.Instance instance : cluster.getInstancesMatching(
         anyRoleIn(Sets.<String>newHashSet(roles)))) {
-        ids.add(instance.getId());
+        instanceIds.add(instance.getId());
       }
 
       condition = Predicates.and(condition,
-        withIds(ids.toArray(new String[0])));
+        withIds(instanceIds.toArray(new String[0])));
+      return condition;
+    } else {
+      return condition;
     }
-    return condition;
   }
 
+
   private int handleScriptOutput(PrintStream out, PrintStream err,
                                  Map<? extends NodeMetadata, ExecResponse> responses) {
     int rc = 0;
@@ -162,7 +173,7 @@ public class RunScriptCommand extends Ab
 
   private String getFileContent(String filePath) throws IOException {
     return StringUtils.join(Files.readLines(new File(filePath),
-        Charset.defaultCharset()),
+      Charset.defaultCharset()),
       "\n");
   }
 

Modified: whirr/trunk/core/pom.xml
URL: http://svn.apache.org/viewvc/whirr/trunk/core/pom.xml?rev=1240854&r1=1240853&r2=1240854&view=diff
==============================================================================
--- whirr/trunk/core/pom.xml (original)
+++ whirr/trunk/core/pom.xml Sun Feb  5 23:09:59 2012
@@ -25,8 +25,19 @@
   </parent>
   <groupId>org.apache.whirr</groupId>
   <artifactId>whirr-core</artifactId>
-  <packaging>jar</packaging>
+  <packaging>bundle</packaging>
   <version>0.8.0-SNAPSHOT</version>
+  <properties>
+    <osgi.import>
+      !org.apache.whirr*,
+      org.apache.commons.configuration*;version="[1.6,2)",
+      *
+    </osgi.import>
+    <osgi.fragment.host>jclouds-scriptbuilder;bundle-version="${jclouds.version}"</osgi.fragment.host>
+    <osgi.export>
+      org.apache.whirr*;version="${project.version}"
+    </osgi.export>
+  </properties>
   <name>Apache Whirr Core</name>
   <dependencies>
     <dependency>
@@ -55,6 +66,11 @@
     </dependency>
     <dependency>
       <groupId>org.jclouds.driver</groupId>
+      <artifactId>jclouds-jsch</artifactId>
+      <version>${jclouds.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.jclouds.driver</groupId>
       <artifactId>jclouds-slf4j</artifactId>
     </dependency>
     <dependency>
@@ -132,7 +148,7 @@
     <dependency>
       <groupId>net.sf.jopt-simple</groupId>
       <artifactId>jopt-simple</artifactId>
-      <version>3.2</version>
+      <version>${jopt.simple.version}</version>
     </dependency>
   </dependencies>
   <build>

Modified: whirr/trunk/core/src/main/java/org/apache/whirr/ByonClusterController.java
URL: http://svn.apache.org/viewvc/whirr/trunk/core/src/main/java/org/apache/whirr/ByonClusterController.java?rev=1240854&r1=1240853&r2=1240854&view=diff
==============================================================================
--- whirr/trunk/core/src/main/java/org/apache/whirr/ByonClusterController.java (original)
+++ whirr/trunk/core/src/main/java/org/apache/whirr/ByonClusterController.java Sun Feb  5 23:09:59 2012
@@ -62,7 +62,7 @@ public class ByonClusterController exten
   public Cluster launchCluster(ClusterSpec clusterSpec) throws IOException,
       InterruptedException {
 
-    Map<String, ClusterActionHandler> handlerMap = new HandlerMapFactory()
+    Map<String, ClusterActionHandler> handlerMap = handlerMapFactory
         .create();
 
     ClusterAction bootstrapper = new ByonClusterAction(BOOTSTRAP_ACTION, getCompute(), handlerMap);
@@ -78,7 +78,7 @@ public class ByonClusterController exten
 
   public void destroyCluster(ClusterSpec clusterSpec) throws IOException,
       InterruptedException {
-    Map<String, ClusterActionHandler> handlerMap = new HandlerMapFactory()
+    Map<String, ClusterActionHandler> handlerMap = handlerMapFactory
         .create();
 
     ClusterAction destroyer = new ByonClusterAction(DESTROY_ACTION, getCompute(), handlerMap);

Modified: whirr/trunk/core/src/main/java/org/apache/whirr/ClusterController.java
URL: http://svn.apache.org/viewvc/whirr/trunk/core/src/main/java/org/apache/whirr/ClusterController.java?rev=1240854&r1=1240853&r2=1240854&view=diff
==============================================================================
--- whirr/trunk/core/src/main/java/org/apache/whirr/ClusterController.java (original)
+++ whirr/trunk/core/src/main/java/org/apache/whirr/ClusterController.java Sun Feb  5 23:09:59 2012
@@ -30,7 +30,6 @@ import org.apache.whirr.actions.Configur
 import org.apache.whirr.actions.DestroyClusterAction;
 import org.apache.whirr.actions.StartServicesAction;
 import org.apache.whirr.actions.StopServicesAction;
-import org.apache.whirr.service.ClusterActionHandler;
 import org.apache.whirr.state.ClusterStateStore;
 import org.apache.whirr.state.ClusterStateStoreFactory;
 import org.apache.whirr.service.ComputeCache;
@@ -62,12 +61,13 @@ public class ClusterController {
 
   private static final Logger LOG = LoggerFactory.getLogger(ClusterController.class);
 
-  private static final Map<String, ClusterActionHandler> HANDLERS = HandlerMapFactory.create();
   private static final ImmutableSet<String> EMPTYSET = ImmutableSet.of();
 
   private final Function<ClusterSpec, ComputeServiceContext> getCompute;
   private final ClusterStateStoreFactory stateStoreFactory;
 
+  protected HandlerMapFactory handlerMapFactory = new HandlerMapFactory();
+
 
   public ClusterController() {
     this(ComputeCache.INSTANCE, new ClusterStateStoreFactory());
@@ -131,7 +131,7 @@ public class ClusterController {
    * Provision the hardware resources needed for running services
    */
   public Cluster bootstrapCluster(ClusterSpec clusterSpec) throws IOException, InterruptedException {
-    BootstrapClusterAction bootstrapper = new BootstrapClusterAction(getCompute(), HANDLERS);
+    BootstrapClusterAction bootstrapper = new BootstrapClusterAction(getCompute(), handlerMapFactory.create());
     Cluster cluster = bootstrapper.execute(clusterSpec, null);
     getClusterStateStore(clusterSpec).save(cluster);
     return cluster;
@@ -151,7 +151,7 @@ public class ClusterController {
   
   public Cluster configureServices(ClusterSpec clusterSpec, Cluster cluster, Set<String> targetRoles,
         Set<String> targetInstanceIds) throws IOException, InterruptedException {
-    ConfigureServicesAction configurer = new ConfigureServicesAction(getCompute(), HANDLERS,
+    ConfigureServicesAction configurer = new ConfigureServicesAction(getCompute(), handlerMapFactory.create(),
         targetRoles, targetInstanceIds);
     return configurer.execute(clusterSpec, cluster);
   }
@@ -170,7 +170,7 @@ public class ClusterController {
   
   public Cluster startServices(ClusterSpec clusterSpec, Cluster cluster,
       Set<String> targetRoles, Set<String> targetInstanceIds) throws IOException, InterruptedException {
-    StartServicesAction starter = new StartServicesAction(getCompute(), HANDLERS, targetRoles, targetInstanceIds);
+    StartServicesAction starter = new StartServicesAction(getCompute(), handlerMapFactory.create(), targetRoles, targetInstanceIds);
     return starter.execute(clusterSpec, cluster);
   }
 
@@ -189,7 +189,7 @@ public class ClusterController {
   
   public Cluster stopServices(ClusterSpec clusterSpec, Cluster cluster, Set<String> targetRoles,
     Set<String> targetInstanceIds) throws IOException, InterruptedException {
-    StopServicesAction stopper = new StopServicesAction(getCompute(), HANDLERS, targetRoles, targetInstanceIds);
+    StopServicesAction stopper = new StopServicesAction(getCompute(), handlerMapFactory.create(), targetRoles, targetInstanceIds);
     return stopper.execute(clusterSpec, cluster);
   }
 
@@ -202,7 +202,7 @@ public class ClusterController {
 
   public Cluster cleanupCluster(ClusterSpec clusterSpec, Cluster cluster)
     throws IOException, InterruptedException {
-    CleanupClusterAction cleanner = new CleanupClusterAction(getCompute(), HANDLERS);
+    CleanupClusterAction cleanner = new CleanupClusterAction(getCompute(), handlerMapFactory.create());
     return cleanner.execute(clusterSpec, cluster);
   }
   
@@ -222,7 +222,7 @@ public class ClusterController {
 
   public void destroyCluster(ClusterSpec clusterSpec, Cluster cluster)
     throws IOException, InterruptedException {
-    DestroyClusterAction destroyer = new DestroyClusterAction(getCompute(), HANDLERS);
+    DestroyClusterAction destroyer = new DestroyClusterAction(getCompute(), handlerMapFactory.create());
     destroyer.execute(clusterSpec, cluster);
   }
 
@@ -304,6 +304,14 @@ public class ClusterController {
     return instances;
   }
 
+  public HandlerMapFactory getHandlerMapFactory() {
+    return handlerMapFactory;
+  }
+
+  public void setHandlerMapFactory(HandlerMapFactory handlerMapFactory) {
+    this.handlerMapFactory = handlerMapFactory;
+  }
+
   private Cluster.Instance toInstance(NodeMetadata metadata, Cluster cluster, ClusterSpec spec) {
     Credentials credentials = new Credentials(spec.getClusterUser(), spec.getPrivateKey());
 

Modified: whirr/trunk/core/src/main/java/org/apache/whirr/ClusterSpec.java
URL: http://svn.apache.org/viewvc/whirr/trunk/core/src/main/java/org/apache/whirr/ClusterSpec.java?rev=1240854&r1=1240853&r2=1240854&view=diff
==============================================================================
--- whirr/trunk/core/src/main/java/org/apache/whirr/ClusterSpec.java (original)
+++ whirr/trunk/core/src/main/java/org/apache/whirr/ClusterSpec.java Sun Feb  5 23:09:59 2012
@@ -434,8 +434,7 @@ public class ClusterSpec {
       throws ConfigurationException {
     CompositeConfiguration composed = new CompositeConfiguration();
     composed.addConfiguration(userConfig);
-    composed.addConfiguration(
-      new PropertiesConfiguration(DEFAULT_PROPERTIES));
+    composed.addConfiguration(new PropertiesConfiguration(getClass().getClassLoader().getResource(DEFAULT_PROPERTIES)));
     return composed;
   }
 

Added: whirr/trunk/core/src/main/java/org/apache/whirr/DynamicClusterControllerFactory.java
URL: http://svn.apache.org/viewvc/whirr/trunk/core/src/main/java/org/apache/whirr/DynamicClusterControllerFactory.java?rev=1240854&view=auto
==============================================================================
--- whirr/trunk/core/src/main/java/org/apache/whirr/DynamicClusterControllerFactory.java (added)
+++ whirr/trunk/core/src/main/java/org/apache/whirr/DynamicClusterControllerFactory.java Sun Feb  5 23:09:59 2012
@@ -0,0 +1,81 @@
+/*
+ * 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.apache.whirr;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import com.google.common.collect.Sets;
+
+/**
+ * A Dynamic Controller Factory.
+ * This Factory can be used inside dynamic environments and leverage their dynamic nature.
+ */
+public class DynamicClusterControllerFactory extends ClusterControllerFactory {
+
+  private static final String BASIC_CONTROLLER = "basic";
+  private final Map<String, ClusterController> clusterControllerMap = new ConcurrentHashMap<String, ClusterController>();
+
+   /**
+   * Create an instance of a {@link ClusterController} according to the given
+   * name. If the name is <code>null</code> then the default {@link ClusterController}
+   * is returned.
+   */
+  @Override
+  public ClusterController create(String serviceName) {
+    if (serviceName == null) {
+      return clusterControllerMap.get(BASIC_CONTROLLER);
+    } else return clusterControllerMap.get(serviceName);
+  }
+
+  /**
+   * Return a collection of available {@link ClusterController} names.
+   * @return the available service names
+   */
+  @Override
+  public Set<String> availableServices() {
+    Set<String> result = Sets.newLinkedHashSet();
+    for (Map.Entry<String,ClusterController> entry: clusterControllerMap.entrySet()) {
+      result.add(entry.getKey());
+    }
+    return result;
+  }
+
+  public void bind(ClusterController clusterController) {
+    if (clusterController != null) {
+      String name = null;
+      try{
+        name = clusterController.getName();
+      } catch (UnsupportedOperationException ex) {
+        name = BASIC_CONTROLLER;
+      }
+      clusterControllerMap.put(name, clusterController);
+    }
+  }
+
+  public void unbind(ClusterController clusterController) {
+    if (clusterController != null)  {
+      try {
+       clusterControllerMap.remove(clusterController.getName());
+      }catch(UnsupportedOperationException ex) {
+        //Ignore
+      }
+    }
+  }
+}

Added: whirr/trunk/core/src/main/java/org/apache/whirr/DynamicHandlerMapFactory.java
URL: http://svn.apache.org/viewvc/whirr/trunk/core/src/main/java/org/apache/whirr/DynamicHandlerMapFactory.java?rev=1240854&view=auto
==============================================================================
--- whirr/trunk/core/src/main/java/org/apache/whirr/DynamicHandlerMapFactory.java (added)
+++ whirr/trunk/core/src/main/java/org/apache/whirr/DynamicHandlerMapFactory.java Sun Feb  5 23:09:59 2012
@@ -0,0 +1,45 @@
+/*
+ * 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.apache.whirr;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import org.apache.whirr.service.ClusterActionHandler;
+
+public class DynamicHandlerMapFactory extends HandlerMapFactory {
+
+  protected final Map<String, ClusterActionHandler> clusterActionHandlerMap = new ConcurrentHashMap<String, ClusterActionHandler>();
+
+  @Override
+  public Map<String, ClusterActionHandler> create() {
+    return clusterActionHandlerMap;
+  }
+
+  public void bind(ClusterActionHandler clusterActionHandler) {
+     if (clusterActionHandler != null && clusterActionHandler.getRole() != null) {
+      clusterActionHandlerMap.put(clusterActionHandler.getRole(), clusterActionHandler);
+    }
+  }
+
+  public void unbind(ClusterActionHandler clusterActionHandler) {
+    if (clusterActionHandler != null && clusterActionHandler.getRole() != null) {
+      clusterActionHandlerMap.remove(clusterActionHandler.getRole());
+    }
+  }
+}

Modified: whirr/trunk/core/src/main/java/org/apache/whirr/HandlerMapFactory.java
URL: http://svn.apache.org/viewvc/whirr/trunk/core/src/main/java/org/apache/whirr/HandlerMapFactory.java?rev=1240854&r1=1240853&r2=1240854&view=diff
==============================================================================
--- whirr/trunk/core/src/main/java/org/apache/whirr/HandlerMapFactory.java (original)
+++ whirr/trunk/core/src/main/java/org/apache/whirr/HandlerMapFactory.java Sun Feb  5 23:09:59 2012
@@ -67,12 +67,12 @@ public class HandlerMapFactory {
       }
    }
 
-   public static Map<String, ClusterActionHandler> create() {
+   public Map<String, ClusterActionHandler> create() {
       return create(ServiceLoader.load(ClusterActionHandlerFactory.class),
         ServiceLoader.load(ClusterActionHandler.class));
    }
 
-   public static Map<String, ClusterActionHandler> create(
+   public Map<String, ClusterActionHandler> create(
       Iterable<ClusterActionHandlerFactory> factories,
       Iterable<ClusterActionHandler> handlers
    ) {

Modified: whirr/trunk/core/src/main/java/org/apache/whirr/service/ClusterActionHandler.java
URL: http://svn.apache.org/viewvc/whirr/trunk/core/src/main/java/org/apache/whirr/service/ClusterActionHandler.java?rev=1240854&r1=1240853&r2=1240854&view=diff
==============================================================================
--- whirr/trunk/core/src/main/java/org/apache/whirr/service/ClusterActionHandler.java (original)
+++ whirr/trunk/core/src/main/java/org/apache/whirr/service/ClusterActionHandler.java Sun Feb  5 23:09:59 2012
@@ -20,8 +20,6 @@ package org.apache.whirr.service;
 
 import java.io.IOException;
 
-import com.google.common.base.Objects;
-
 /**
  * A callback interface for cluster actions that apply to instances in a
  * given role.
@@ -30,54 +28,29 @@ import com.google.common.base.Objects;
  * discovered using a Service Provider Interface (SPI), described in
  * {@link java.util.ServiceLoader}.
  */
-public abstract class ClusterActionHandler {
+public interface ClusterActionHandler {
   
-  public static final String BOOTSTRAP_ACTION = "bootstrap";
-  public static final String CONFIGURE_ACTION = "configure";
-  public static final String START_ACTION  = "start";
-  public static final String STOP_ACTION = "stop";
-  public static final String CLEANUP_ACTION = "cleanup";
-  public static final String DESTROY_ACTION = "destroy";
+  String BOOTSTRAP_ACTION = "bootstrap";
+  String CONFIGURE_ACTION = "configure";
+  String START_ACTION  = "start";
+  String STOP_ACTION = "stop";
+  String CLEANUP_ACTION = "cleanup";
+  String DESTROY_ACTION = "destroy";
+
+  String getRole();
 
-  public abstract String getRole();
-  
   /**
    * Called before the action is performed, giving the implementation an
    * opportunity to specify scripts that should be run as a part of this
    * action.
    * @param event
    */
-  public void beforeAction(ClusterActionEvent event)
-      throws IOException, InterruptedException {
-  }
-  
+  void beforeAction(ClusterActionEvent event) throws IOException, InterruptedException;
+
   /**
    * Called after the action has been performed.
    * @param event
    */
-  public void afterAction(ClusterActionEvent event)
-      throws IOException, InterruptedException {
-  }
-
-  /**
-   * this uses the inefficient {@link Objects} implementation as the object count will be
-   * relatively small and therefore efficiency is not a concern.
-   */
-  @Override
-  public int hashCode() {
-     return Objects.hashCode(getRole());
-  }
-
-  @Override
-  public boolean equals(Object that) {
-     if (that == null)
-        return false;
-     return Objects.equal(this.toString(), that.toString());
-  }
-
-  @Override
-  public String toString() {
-     return Objects.toStringHelper(this).add("role", getRole()).toString();
-  }
+  void afterAction(ClusterActionEvent event) throws IOException, InterruptedException;
 
 }

Modified: whirr/trunk/core/src/main/java/org/apache/whirr/service/ClusterActionHandlerSupport.java
URL: http://svn.apache.org/viewvc/whirr/trunk/core/src/main/java/org/apache/whirr/service/ClusterActionHandlerSupport.java?rev=1240854&r1=1240853&r2=1240854&view=diff
==============================================================================
--- whirr/trunk/core/src/main/java/org/apache/whirr/service/ClusterActionHandlerSupport.java (original)
+++ whirr/trunk/core/src/main/java/org/apache/whirr/service/ClusterActionHandlerSupport.java Sun Feb  5 23:09:59 2012
@@ -23,6 +23,7 @@ import java.io.IOException;
 import java.net.URI;
 import java.net.URISyntaxException;
 
+import com.google.common.base.Objects;
 import org.apache.commons.configuration.CompositeConfiguration;
 import org.apache.commons.configuration.Configuration;
 import org.apache.commons.configuration.ConfigurationException;
@@ -39,12 +40,11 @@ import org.slf4j.LoggerFactory;
  * {@link ClusterActionHandler}. For each 'before' and 'after' action type there
  * is a corresponding method that implementations may override.
  */
-public abstract class ClusterActionHandlerSupport extends ClusterActionHandler {
+public abstract class ClusterActionHandlerSupport implements ClusterActionHandler {
 
   private static final Logger LOG =
     LoggerFactory.getLogger(ClusterActionHandler.class);
 
-  @Override
   public void beforeAction(ClusterActionEvent event)
       throws IOException, InterruptedException{
     if (event.getAction().equals(BOOTSTRAP_ACTION)) {
@@ -64,7 +64,6 @@ public abstract class ClusterActionHandl
     }
   }
 
-  @Override
   public void afterAction(ClusterActionEvent event)
       throws IOException, InterruptedException {
     if (event.getAction().equals(BOOTSTRAP_ACTION)) {
@@ -146,7 +145,7 @@ public abstract class ClusterActionHandl
       String defaultsPropertiesFile) throws IOException {
     try {
       return getConfiguration(clusterSpec,
-          new PropertiesConfiguration(defaultsPropertiesFile));
+          new PropertiesConfiguration(getClass().getClassLoader().getResource(defaultsPropertiesFile)));
     } catch(ConfigurationException e) {
       throw new IOException("Error loading " + defaultsPropertiesFile, e);
     }
@@ -247,5 +246,26 @@ public abstract class ClusterActionHandl
 
     return config.getString(key, defaultFunction);
   }
+  /**
+    * this uses the inefficient {@link com.google.common.base.Objects} implementation as the object count will be
+    * relatively small and therefore efficiency is not a concern.
+    */
+   @Override
+   public int hashCode() {
+      return Objects.hashCode(getRole());
+   }
+
+   @Override
+   public boolean equals(Object that) {
+      if (that == null)
+         return false;
+      return Objects.equal(this.toString(), that.toString());
+   }
+
+   @Override
+   public String toString() {
+      return Objects.toStringHelper(this).add("role", getRole()).toString();
+   }
+
 
 }

Modified: whirr/trunk/core/src/main/java/org/apache/whirr/util/Utils.java
URL: http://svn.apache.org/viewvc/whirr/trunk/core/src/main/java/org/apache/whirr/util/Utils.java?rev=1240854&r1=1240853&r2=1240854&view=diff
==============================================================================
--- whirr/trunk/core/src/main/java/org/apache/whirr/util/Utils.java (original)
+++ whirr/trunk/core/src/main/java/org/apache/whirr/util/Utils.java Sun Feb  5 23:09:59 2012
@@ -18,27 +18,27 @@
 
 package org.apache.whirr.util;
 
-import java.io.PrintStream;
-
 import org.apache.whirr.Cluster;
 import org.apache.whirr.Cluster.Instance;
 import org.apache.whirr.ClusterSpec;
 
+import java.io.PrintStream;
+
 public class Utils {
 
   /**
    * Prints ssh commands that can be used to login into the nodes
-   * 
+   *
    * @param out
    * @param clusterSpec
    * @param cluster
    */
-  public static void printAccess(PrintStream out, ClusterSpec clusterSpec,
+  public static void printSSHConnectionDetails(PrintStream out, ClusterSpec clusterSpec,
       Cluster cluster, int maxPrint) {
-    out.println("You can log into instances using the following ssh commands:");
+    out.println("\nYou can log into instances using the following ssh commands:");
 
     String user = clusterSpec.getBootstrapUser() != null ? clusterSpec
-        .getBootstrapUser() : clusterSpec.getClusterUser();
+      .getBootstrapUser() : clusterSpec.getClusterUser();
 
     String pkFile = clusterSpec.getPrivateKeyFile().getAbsolutePath();
 
@@ -46,8 +46,8 @@ public class Utils {
     for (Instance instance : cluster.getInstances()) {
 
       out.printf(
-          "'ssh -i %s -o \"UserKnownHostsFile /dev/null\" -o StrictHostKeyChecking=no %s@%s'\n",
-          pkFile, user, instance.getPublicIp());
+        "'ssh -i %s -o \"UserKnownHostsFile /dev/null\" -o StrictHostKeyChecking=no %s@%s'\n",
+        pkFile, user, instance.getPublicIp());
 
       if (counter > maxPrint) {
         out.println("... Too many instances, truncating.");

Added: whirr/trunk/core/src/main/resources/OSGI-INF/blueprint/blueprint.xml
URL: http://svn.apache.org/viewvc/whirr/trunk/core/src/main/resources/OSGI-INF/blueprint/blueprint.xml?rev=1240854&view=auto
==============================================================================
--- whirr/trunk/core/src/main/resources/OSGI-INF/blueprint/blueprint.xml (added)
+++ whirr/trunk/core/src/main/resources/OSGI-INF/blueprint/blueprint.xml Sun Feb  5 23:09:59 2012
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<!--
+  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.
+  -->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+
+  <bean id="dynamicHandlerMapFactory" class="org.apache.whirr.DynamicHandlerMapFactory"/>
+  <bean id="dynamicClusterControllerFactory" class="org.apache.whirr.DynamicClusterControllerFactory"/>
+
+  <!-- Dynamic Factories -->
+  <service ref="dynamicHandlerMapFactory" auto-export="all-classes"/>
+  <service ref="dynamicClusterControllerFactory" auto-export="all-classes"/>
+
+  <!-- Service Listeners -->
+  <reference-list id="clusterContollers" availability="optional" interface="org.apache.whirr.ClusterController">
+    <reference-listener ref="dynamicClusterControllerFactory" bind-method="bind" unbind-method="unbind"/>
+  </reference-list>
+
+  <reference-list id="clusterActionHandlers" availability="optional" interface="org.apache.whirr.service.ClusterActionHandler">
+    <reference-listener ref="dynamicHandlerMapFactory" bind-method="bind" unbind-method="unbind"/>
+  </reference-list>
+
+  <!-- Services -->
+  <service auto-export="all-classes">
+    <service-properties>
+        <entry key="name" value="default"/>
+    </service-properties>
+    <bean class="org.apache.whirr.ClusterController">
+      <property name="handlerMapFactory" ref="dynamicHandlerMapFactory"/>
+    </bean>
+  </service>
+  <service auto-export="all-classes">
+    <service-properties>
+        <entry key="name" value="byon"/>
+    </service-properties>
+    <bean class="org.apache.whirr.ByonClusterController">
+      <property name="handlerMapFactory" ref="dynamicHandlerMapFactory"/>
+    </bean>
+  </service>
+</blueprint>
\ No newline at end of file

Modified: whirr/trunk/core/src/test/java/org/apache/whirr/actions/BootstrapClusterActionTest.java
URL: http://svn.apache.org/viewvc/whirr/trunk/core/src/test/java/org/apache/whirr/actions/BootstrapClusterActionTest.java?rev=1240854&r1=1240853&r2=1240854&view=diff
==============================================================================
--- whirr/trunk/core/src/test/java/org/apache/whirr/actions/BootstrapClusterActionTest.java (original)
+++ whirr/trunk/core/src/test/java/org/apache/whirr/actions/BootstrapClusterActionTest.java Sun Feb  5 23:09:59 2012
@@ -350,7 +350,7 @@ public class BootstrapClusterActionTest 
     when(puppetHandlerFactory.create("module::manifest")).thenReturn(handler);
     when(handler.getRole()).thenReturn("something-else");
 
-    Map<String, ClusterActionHandler> handlerMap = HandlerMapFactory.create(ImmutableSet.of(puppetHandlerFactory),
+    Map<String, ClusterActionHandler> handlerMap = new HandlerMapFactory().create(ImmutableSet.of(puppetHandlerFactory),
           ImmutableSet.of(handler));
 
     Function<ClusterSpec, ComputeServiceContext> getCompute = mock(Function.class);
@@ -410,7 +410,7 @@ public class BootstrapClusterActionTest 
     when(puppetHandlerFactory.getRolePrefix()).thenReturn("puppet");
     when(handler.getRole()).thenReturn("something-else");
 
-    Map<String, ClusterActionHandler> handlerMap = HandlerMapFactory.create(
+    Map<String, ClusterActionHandler> handlerMap = new HandlerMapFactory().create(
       ImmutableSet.of(puppetHandlerFactory), ImmutableSet.of(handler));
 
     Function<ClusterSpec, ComputeServiceContext> getCompute = mock(Function.class);

Modified: whirr/trunk/core/src/test/java/org/apache/whirr/actions/ScriptBasedClusterActionTest.java
URL: http://svn.apache.org/viewvc/whirr/trunk/core/src/test/java/org/apache/whirr/actions/ScriptBasedClusterActionTest.java?rev=1240854&r1=1240853&r2=1240854&view=diff
==============================================================================
--- whirr/trunk/core/src/test/java/org/apache/whirr/actions/ScriptBasedClusterActionTest.java (original)
+++ whirr/trunk/core/src/test/java/org/apache/whirr/actions/ScriptBasedClusterActionTest.java Sun Feb  5 23:09:59 2012
@@ -87,7 +87,8 @@ public abstract class ScriptBasedCluster
     }
   }
 
-  private final static Map<String, ClusterActionHandler> HANDLERMAP = HandlerMapFactory.create();
+  private final static HandlerMapFactory HANDLER_MAP_FACTORY = new HandlerMapFactory();
+  private final static Map<String, ClusterActionHandler> HANDLERMAP = HANDLER_MAP_FACTORY.create();
   private final static Set<String> EMPTYSET = ImmutableSet.of();
 
   private ClusterSpec clusterSpec;

Modified: whirr/trunk/core/src/test/java/org/apache/whirr/util/UtilsTest.java
URL: http://svn.apache.org/viewvc/whirr/trunk/core/src/test/java/org/apache/whirr/util/UtilsTest.java?rev=1240854&r1=1240853&r2=1240854&view=diff
==============================================================================
--- whirr/trunk/core/src/test/java/org/apache/whirr/util/UtilsTest.java (original)
+++ whirr/trunk/core/src/test/java/org/apache/whirr/util/UtilsTest.java Sun Feb  5 23:09:59 2012
@@ -18,23 +18,23 @@
 
 package org.apache.whirr.util;
 
-import static junit.framework.Assert.assertEquals;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
+import org.apache.whirr.Cluster;
+import org.apache.whirr.Cluster.Instance;
+import org.apache.whirr.ClusterSpec;
+import org.junit.Test;
 
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.PrintStream;
 import java.util.HashSet;
 
-import org.apache.whirr.Cluster;
-import org.apache.whirr.Cluster.Instance;
-import org.apache.whirr.ClusterSpec;
-import org.junit.Test;
+import static junit.framework.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
 public class UtilsTest {
 
-  public static final String EXPECTED_SSH_COMMAND = "You can log into instances using the following ssh commands:\n"
+  public static final String EXPECTED_SSH_COMMAND = "\nYou can log into instances using the following ssh commands:\n"
       + "'ssh -i /test/key/path -o \"UserKnownHostsFile /dev/null\" -o StrictHostKeyChecking=no test-identity@test-public-ip'\n";
 
   @Test
@@ -57,7 +57,7 @@ public class UtilsTest {
 
     ByteArrayOutputStream baos = new ByteArrayOutputStream();
     PrintStream ps = new PrintStream(baos);
-    Utils.printAccess(ps, spec, cluster, 20);
+    Utils.printSSHConnectionDetails(ps, spec, cluster, 20);
 
     assertEquals("The ssh command did not match", EXPECTED_SSH_COMMAND,
         new String(baos.toByteArray()));

Modified: whirr/trunk/examples/pom.xml
URL: http://svn.apache.org/viewvc/whirr/trunk/examples/pom.xml?rev=1240854&r1=1240853&r2=1240854&view=diff
==============================================================================
--- whirr/trunk/examples/pom.xml (original)
+++ whirr/trunk/examples/pom.xml Sun Feb  5 23:09:59 2012
@@ -25,9 +25,18 @@
   </parent>
   <groupId>org.apache.whirr</groupId>
   <artifactId>whirr-examples</artifactId>
-  <packaging>jar</packaging>
+  <packaging>bundle</packaging>
   <version>0.8.0-SNAPSHOT</version>
   <name>Apache Whirr Examples</name>
+  <properties>
+    <osgi.import>
+      !org.apache.whirr.examples*,
+      *
+    </osgi.import>
+    <osgi.export>
+      org.apache.whirr.examples*;version="${project.version}"
+    </osgi.export>
+  </properties>
   <dependencies>
     <dependency>
       <groupId>${project.groupId}</groupId>

Propchange: whirr/trunk/platforms/karaf/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Sun Feb  5 23:09:59 2012
@@ -0,0 +1 @@
+target

Propchange: whirr/trunk/platforms/karaf/commands/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Sun Feb  5 23:09:59 2012
@@ -0,0 +1 @@
+target

Added: whirr/trunk/platforms/karaf/commands/pom.xml
URL: http://svn.apache.org/viewvc/whirr/trunk/platforms/karaf/commands/pom.xml?rev=1240854&view=auto
==============================================================================
--- whirr/trunk/platforms/karaf/commands/pom.xml (added)
+++ whirr/trunk/platforms/karaf/commands/pom.xml Sun Feb  5 23:09:59 2012
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <parent>
+    <groupId>org.apache.whirr</groupId>
+    <artifactId>karaf</artifactId>
+    <version>0.8.0-SNAPSHOT</version>
+    <relativePath>../pom.xml</relativePath>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>org.apache.whirr.karaf</groupId>
+  <artifactId>org.apache.whirr.karaf.commands</artifactId>
+  <name>Apache Whirr Karaf Commands</name>
+  <packaging>bundle</packaging>
+  <properties>
+    <osgi.import>
+      !org.apache.whirr.karaf.command*,
+      org.apache.commons.configuration*;version="[1.6,2)",
+      *
+    </osgi.import>
+    <osgi.dynamic.import>javax.*,org.jclouds.*</osgi.dynamic.import>
+    <osgi.export>org.apache.whirr.karaf.command*;version="${project.version}"</osgi.export>
+  </properties>
+  <dependencies>
+    <dependency>
+      <groupId>org.osgi</groupId>
+      <artifactId>org.osgi.compendium</artifactId>
+      <version>${osgi.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.karaf.shell</groupId>
+      <artifactId>org.apache.karaf.shell.console</artifactId>
+      <version>${karaf.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.whirr</groupId>
+      <artifactId>whirr-cli</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+  </dependencies>
+</project>

Added: whirr/trunk/platforms/karaf/commands/src/main/java/org/apache/whirr/karaf/command/DestroyCluster.java
URL: http://svn.apache.org/viewvc/whirr/trunk/platforms/karaf/commands/src/main/java/org/apache/whirr/karaf/command/DestroyCluster.java?rev=1240854&view=auto
==============================================================================
--- whirr/trunk/platforms/karaf/commands/src/main/java/org/apache/whirr/karaf/command/DestroyCluster.java (added)
+++ whirr/trunk/platforms/karaf/commands/src/main/java/org/apache/whirr/karaf/command/DestroyCluster.java Sun Feb  5 23:09:59 2012
@@ -0,0 +1,38 @@
+/*
+ * 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.apache.whirr.karaf.command;
+
+import org.apache.felix.gogo.commands.Command;
+import org.apache.whirr.ClusterSpec;
+import org.apache.whirr.cli.command.DestroyClusterCommand;
+import org.apache.whirr.karaf.command.support.WhirrCommandSupport;
+
+@Command(scope = "whirr", name = "destory-cluster", description = "Terminate and cleanup resources for a running cluster.")
+public class DestroyCluster extends WhirrCommandSupport {
+
+  @Override
+  protected Object doExecute() throws Exception {
+    DestroyClusterCommand command = new DestroyClusterCommand(clusterControllerFactory);
+    ClusterSpec clusterSpec = getClusterSpec();
+    if (clusterSpec != null) {
+      command.run(System.in, System.out, System.err, clusterSpec);
+    }
+    return null;
+  }
+}

Added: whirr/trunk/platforms/karaf/commands/src/main/java/org/apache/whirr/karaf/command/DestroyInstance.java
URL: http://svn.apache.org/viewvc/whirr/trunk/platforms/karaf/commands/src/main/java/org/apache/whirr/karaf/command/DestroyInstance.java?rev=1240854&view=auto
==============================================================================
--- whirr/trunk/platforms/karaf/commands/src/main/java/org/apache/whirr/karaf/command/DestroyInstance.java (added)
+++ whirr/trunk/platforms/karaf/commands/src/main/java/org/apache/whirr/karaf/command/DestroyInstance.java Sun Feb  5 23:09:59 2012
@@ -0,0 +1,42 @@
+/*
+ * 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.apache.whirr.karaf.command;
+
+import org.apache.felix.gogo.commands.Command;
+import org.apache.felix.gogo.commands.Option;
+import org.apache.whirr.ClusterSpec;
+import org.apache.whirr.cli.command.DestroyInstanceCommand;
+import org.apache.whirr.karaf.command.support.WhirrCommandSupport;
+
+@Command(scope = "whirr", name = "destory-instance", description = "Terminate and cleanup resources for a single instance.")
+public class DestroyInstance extends WhirrCommandSupport {
+
+  @Option(required = false, name = "--instance", description = "The instance to destroy")
+  protected String instance;
+
+  @Override
+  protected Object doExecute() throws Exception {
+    DestroyInstanceCommand command = new DestroyInstanceCommand(clusterControllerFactory);
+    ClusterSpec clusterSpec = getClusterSpec();
+    if (clusterSpec != null) {
+      command.run(System.in, System.out, System.err, clusterSpec, instance);
+    }
+    return null;
+  }
+}

Added: whirr/trunk/platforms/karaf/commands/src/main/java/org/apache/whirr/karaf/command/LaunchCluster.java
URL: http://svn.apache.org/viewvc/whirr/trunk/platforms/karaf/commands/src/main/java/org/apache/whirr/karaf/command/LaunchCluster.java?rev=1240854&view=auto
==============================================================================
--- whirr/trunk/platforms/karaf/commands/src/main/java/org/apache/whirr/karaf/command/LaunchCluster.java (added)
+++ whirr/trunk/platforms/karaf/commands/src/main/java/org/apache/whirr/karaf/command/LaunchCluster.java Sun Feb  5 23:09:59 2012
@@ -0,0 +1,39 @@
+/*
+ * 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.apache.whirr.karaf.command;
+
+import org.apache.felix.gogo.commands.Command;
+import org.apache.whirr.ClusterSpec;
+import org.apache.whirr.cli.command.LaunchClusterCommand;
+import org.apache.whirr.karaf.command.support.WhirrCommandSupport;
+
+@Command(scope = "whirr", name = "launch-cluster", description = "Launch a new cluster running a service.")
+public class LaunchCluster extends WhirrCommandSupport {
+
+  @Override
+  protected Object doExecute() throws Exception {
+    Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
+    LaunchClusterCommand command = new LaunchClusterCommand(clusterControllerFactory);
+    ClusterSpec clusterSpec = getClusterSpec();
+    if (clusterSpec != null) {
+      command.run(System.in, System.out, System.err, clusterSpec);
+    }
+    return null;
+  }
+}

Added: whirr/trunk/platforms/karaf/commands/src/main/java/org/apache/whirr/karaf/command/ListCluster.java
URL: http://svn.apache.org/viewvc/whirr/trunk/platforms/karaf/commands/src/main/java/org/apache/whirr/karaf/command/ListCluster.java?rev=1240854&view=auto
==============================================================================
--- whirr/trunk/platforms/karaf/commands/src/main/java/org/apache/whirr/karaf/command/ListCluster.java (added)
+++ whirr/trunk/platforms/karaf/commands/src/main/java/org/apache/whirr/karaf/command/ListCluster.java Sun Feb  5 23:09:59 2012
@@ -0,0 +1,38 @@
+/*
+ * 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.apache.whirr.karaf.command;
+
+import org.apache.felix.gogo.commands.Command;
+import org.apache.whirr.ClusterSpec;
+import org.apache.whirr.cli.command.ListClusterCommand;
+import org.apache.whirr.karaf.command.support.WhirrCommandSupport;
+
+@Command(scope = "whirr", name = "list-cluster", description = "List the nodes in a cluster.")
+public class ListCluster extends WhirrCommandSupport {
+
+  @Override
+  protected Object doExecute() throws Exception {
+    ListClusterCommand command = new ListClusterCommand(clusterControllerFactory);
+    ClusterSpec clusterSpec = getClusterSpec();
+    if (clusterSpec != null) {
+      command.run(System.in, System.out, System.err, clusterSpec);
+    }
+    return null;
+  }
+}

Added: whirr/trunk/platforms/karaf/commands/src/main/java/org/apache/whirr/karaf/command/RunScript.java
URL: http://svn.apache.org/viewvc/whirr/trunk/platforms/karaf/commands/src/main/java/org/apache/whirr/karaf/command/RunScript.java?rev=1240854&view=auto
==============================================================================
--- whirr/trunk/platforms/karaf/commands/src/main/java/org/apache/whirr/karaf/command/RunScript.java (added)
+++ whirr/trunk/platforms/karaf/commands/src/main/java/org/apache/whirr/karaf/command/RunScript.java Sun Feb  5 23:09:59 2012
@@ -0,0 +1,53 @@
+/*
+ * 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.apache.whirr.karaf.command;
+
+import org.apache.felix.gogo.commands.Argument;
+import org.apache.felix.gogo.commands.Command;
+import org.apache.felix.gogo.commands.Option;
+import org.apache.whirr.ClusterSpec;
+import org.apache.whirr.cli.command.RunScriptCommand;
+import org.apache.whirr.karaf.command.support.WhirrCommandSupport;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Command(scope = "whirr", name = "run-script", description = "Run a script on a specific instance or a group of instances matching a role name")
+public class RunScript extends WhirrCommandSupport {
+
+  @Option(required = false, name = "--instances", description = "The instance ids")
+  protected List<String> instances = new ArrayList<String>();
+
+  @Option(required = false, name = "--roles", description = "The roles")
+  protected List<String> roles = new ArrayList<String>();
+
+  @Argument(index = 0, name = "script", description = "The url of the sciprt to execute")
+  protected String script;
+
+  @Override
+  protected Object doExecute() throws Exception {
+    RunScriptCommand command = new RunScriptCommand(clusterControllerFactory);
+    ClusterSpec clusterSpec = getClusterSpec();
+    if (clusterSpec != null) {
+      command.run(System.in, System.out, System.err, clusterSpec,
+        instances.toArray(new String[instances.size()]), roles.toArray(new String[roles.size()]), script);
+    }
+    return null;
+  }
+}

Added: whirr/trunk/platforms/karaf/commands/src/main/java/org/apache/whirr/karaf/command/support/ConfigurationReader.java
URL: http://svn.apache.org/viewvc/whirr/trunk/platforms/karaf/commands/src/main/java/org/apache/whirr/karaf/command/support/ConfigurationReader.java?rev=1240854&view=auto
==============================================================================
--- whirr/trunk/platforms/karaf/commands/src/main/java/org/apache/whirr/karaf/command/support/ConfigurationReader.java (added)
+++ whirr/trunk/platforms/karaf/commands/src/main/java/org/apache/whirr/karaf/command/support/ConfigurationReader.java Sun Feb  5 23:09:59 2012
@@ -0,0 +1,88 @@
+/*
+ * 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.apache.whirr.karaf.command.support;
+
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.commons.configuration.PropertiesConfiguration;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.List;
+
+public class ConfigurationReader {
+
+  public static final String WHIRR_IDENTIY = "whirr.identity";
+  public static final String WHIRR_CREDENTIAL = "whirr.credential";
+  public static final String WHIRR_PROVIDER = "whirr.provider";
+  public static final String WHIRR_CLUSTER_NAME = "whirr.cluster-name";
+  public static final String DEFAULT_CLUSTER_NAME = "default";
+
+  private ConfigurationReader() {
+    //Utility Class
+  }
+
+
+   /**
+   * Builds Configuration from a File.
+   *
+   * @param fileName
+   * @return
+   * @throws org.apache.commons.configuration.ConfigurationException
+   */
+  public static PropertiesConfiguration fromFile(String fileName) {
+    PropertiesConfiguration config = null;
+    try {
+      config = new PropertiesConfiguration(fileName);
+    } catch (ConfigurationException e) {
+      System.err.println(String.format("Failed to read configuration from file:%s.%s.", fileName, e.getMessage()));
+    }
+    return config;
+  }
+
+  /**
+   * Builds the Configuration from Configuration Admin.
+   *
+   * @param pid
+   * @return
+   */
+  public static PropertiesConfiguration fromConfigAdmin(ConfigurationAdmin configurationAdmin, String pid) {
+    List<String> ignoredKeys = Arrays.asList("service.pid", "felix.fileinstall.filename");
+    PropertiesConfiguration propertiesConfiguration = new PropertiesConfiguration();
+    try {
+      Configuration configuration = configurationAdmin.getConfiguration(pid);
+      Dictionary properties = configuration.getProperties();
+      Enumeration keys = properties.keys();
+      while (keys.hasMoreElements()) {
+        Object key = keys.nextElement();
+        Object value = properties.get(key);
+        if (!ignoredKeys.contains(key)) {
+          propertiesConfiguration.addProperty(String.valueOf(key), value);
+        }
+      }
+    } catch (IOException e) {
+      System.err.println(String.format("No configuration found for pid:%s.", pid));
+      return null;
+    }
+    return propertiesConfiguration;
+  }
+}

Added: whirr/trunk/platforms/karaf/commands/src/main/java/org/apache/whirr/karaf/command/support/WhirrCommandSupport.java
URL: http://svn.apache.org/viewvc/whirr/trunk/platforms/karaf/commands/src/main/java/org/apache/whirr/karaf/command/support/WhirrCommandSupport.java?rev=1240854&view=auto
==============================================================================
--- whirr/trunk/platforms/karaf/commands/src/main/java/org/apache/whirr/karaf/command/support/WhirrCommandSupport.java (added)
+++ whirr/trunk/platforms/karaf/commands/src/main/java/org/apache/whirr/karaf/command/support/WhirrCommandSupport.java Sun Feb  5 23:09:59 2012
@@ -0,0 +1,111 @@
+/*
+ * 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.apache.whirr.karaf.command.support;
+
+import org.apache.commons.configuration.PropertiesConfiguration;
+import org.apache.felix.gogo.commands.Option;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.apache.whirr.ClusterControllerFactory;
+import org.apache.whirr.ClusterSpec;
+import org.jclouds.compute.ComputeService;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+import java.util.List;
+
+public abstract class WhirrCommandSupport extends OsgiCommandSupport {
+
+  @Option(required = false, name = "--config", description = "The configuration file")
+  protected String fileName;
+
+  @Option(required = false, name = "--pid", description = "The PID of the configuration")
+  protected String pid;
+
+  @Option(required = false, name = "--cluster-name", description = "The name of the cluster")
+  protected String clusterName;
+
+  @Option(required = false, name = "--private-key-file", description = "The private ssh key")
+  protected String privateKey;
+
+  protected ClusterControllerFactory clusterControllerFactory;
+  protected ConfigurationAdmin configurationAdmin;
+  protected List<ComputeService> computeServices;
+
+  /**
+   * Returns the {@link ClusterSpec}
+   *
+   * @return
+   * @throws Exception
+   */
+  protected ClusterSpec getClusterSpec() throws Exception {
+    ClusterSpec clusterSpec = null;
+    PropertiesConfiguration properties = getConfiguration(pid, fileName);
+    if (properties != null) {
+      clusterSpec = new ClusterSpec(properties);
+      if (privateKey != null) {
+        clusterSpec.setPrivateKey(privateKey);
+      }
+      if (clusterName != null) {
+        clusterSpec.setClusterName(clusterName);
+      }
+    }
+    return clusterSpec;
+  }
+
+  /**
+   * Retrieves the configuration from a pid or a file.
+   *
+   * @param pid
+   * @param fileName
+   * @return
+   */
+  protected PropertiesConfiguration getConfiguration(String pid, String fileName) {
+    if (pid != null) {
+      return ConfigurationReader.fromConfigAdmin(configurationAdmin, pid);
+    } else if (fileName != null) {
+      return ConfigurationReader.fromFile(fileName);
+    } else {
+      System.err.println("A valid pid or a file must be specified for configuration");
+    }
+    return null;
+  }
+
+  public ClusterControllerFactory getClusterControllerFactory() {
+    return clusterControllerFactory;
+  }
+
+  public void setClusterControllerFactory(ClusterControllerFactory clusterControllerFactory) {
+    this.clusterControllerFactory = clusterControllerFactory;
+  }
+
+  public ConfigurationAdmin getConfigurationAdmin() {
+    return configurationAdmin;
+  }
+
+  public void setConfigurationAdmin(ConfigurationAdmin configurationAdmin) {
+    this.configurationAdmin = configurationAdmin;
+  }
+
+  public List<ComputeService> getComputeServices() {
+    return computeServices;
+  }
+
+  public void setComputeServices(List<ComputeService> computeServices) {
+    this.computeServices = computeServices;
+  }
+}

Added: whirr/trunk/platforms/karaf/commands/src/main/resources/OSGI-INF/blueprint/blueprint.xml
URL: http://svn.apache.org/viewvc/whirr/trunk/platforms/karaf/commands/src/main/resources/OSGI-INF/blueprint/blueprint.xml?rev=1240854&view=auto
==============================================================================
--- whirr/trunk/platforms/karaf/commands/src/main/resources/OSGI-INF/blueprint/blueprint.xml (added)
+++ whirr/trunk/platforms/karaf/commands/src/main/resources/OSGI-INF/blueprint/blueprint.xml Sun Feb  5 23:09:59 2012
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<!--
+  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.
+  -->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+
+  <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.0.0">
+    <command name="whirr/launch-cluster">
+      <action class="org.apache.whirr.karaf.command.LaunchCluster">
+        <property name="clusterControllerFactory" ref="clusterControllerFactory"/>
+        <property name="configurationAdmin" ref="configurationAdmin"/>
+      </action>
+    </command>
+    <command name="whirr/list-cluster">
+      <action class="org.apache.whirr.karaf.command.ListCluster">
+        <property name="clusterControllerFactory" ref="clusterControllerFactory"/>
+        <property name="configurationAdmin" ref="configurationAdmin"/>
+      </action>
+    </command>
+    <command name="whirr/destroy-cluster">
+      <action class="org.apache.whirr.karaf.command.DestroyCluster">
+        <property name="clusterControllerFactory" ref="clusterControllerFactory"/>
+        <property name="configurationAdmin" ref="configurationAdmin"/>
+      </action>
+    </command>
+    <command name="whirr/destroy-instance">
+      <action class="org.apache.whirr.karaf.command.DestroyInstance">
+        <property name="clusterControllerFactory" ref="clusterControllerFactory"/>
+        <property name="configurationAdmin" ref="configurationAdmin"/>
+      </action>
+    </command>
+    <command name="whirr/run-script">
+      <action class="org.apache.whirr.karaf.command.RunScript">
+        <property name="clusterControllerFactory" ref="clusterControllerFactory"/>
+        <property name="configurationAdmin" ref="configurationAdmin"/>
+      </action>
+    </command>
+  </command-bundle>
+
+  <reference id="clusterControllerFactory" interface="org.apache.whirr.ClusterControllerFactory"/>
+  <reference id="configurationAdmin" interface="org.osgi.service.cm.ConfigurationAdmin"/>
+</blueprint>
\ No newline at end of file

Propchange: whirr/trunk/platforms/karaf/feature/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Sun Feb  5 23:09:59 2012
@@ -0,0 +1 @@
+target