mirror of https://github.com/apache/jclouds.git
Issue 312: introductory support for clojure native compute provider
This commit is contained in:
parent
49b88183d2
commit
176f528572
|
@ -0,0 +1,121 @@
|
||||||
|
;
|
||||||
|
;
|
||||||
|
; Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
;
|
||||||
|
; ====================================================================
|
||||||
|
; Licensed 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.
|
||||||
|
; ====================================================================
|
||||||
|
;
|
||||||
|
(ns org.jclouds.modules
|
||||||
|
(:require
|
||||||
|
[clojure.contrib.logging :as logging])
|
||||||
|
(:import
|
||||||
|
[org.jclouds.ssh SshClient ExecResponse]
|
||||||
|
com.google.inject.Module
|
||||||
|
org.jclouds.net.IPSocket
|
||||||
|
[org.jclouds.compute ComputeService ComputeServiceContextFactory]
|
||||||
|
java.util.Set
|
||||||
|
[org.jclouds.compute.domain NodeMetadata Template]
|
||||||
|
[com.google.common.base Supplier Predicate]
|
||||||
|
[org.jclouds.compute.strategy AddNodeWithTagStrategy DestroyNodeStrategy RebootNodeStrategy GetNodeMetadataStrategy ListNodesStrategy]
|
||||||
|
org.jclouds.compute.domain.NodeMetadataBuilder))
|
||||||
|
|
||||||
|
|
||||||
|
(defn compute-module
|
||||||
|
[]
|
||||||
|
(.. (org.jclouds.compute.config.StandaloneComputeServiceContextModule$Builder.)
|
||||||
|
(defineAddNodeWithTagStrategy (defrecord ClojureAddNodeWithTagStrategy []
|
||||||
|
AddNodeWithTagStrategy
|
||||||
|
(^NodeMetadata execute [this ^String tag ^String name ^Template template]
|
||||||
|
())))
|
||||||
|
(defineDestroyNodeStrategy (defrecord ClojureDestroyNodeStrategy []
|
||||||
|
DestroyNodeStrategy
|
||||||
|
(^NodeMetadata execute [this ^String id]
|
||||||
|
())))
|
||||||
|
(defineRebootNodeStrategy (defrecord ClojureRebootNodeStrategy []
|
||||||
|
RebootNodeStrategy
|
||||||
|
(^NodeMetadata execute [this ^String id]
|
||||||
|
())))
|
||||||
|
(defineGetNodeMetadataStrategy (defrecord ClojureGetNodeMetadataStrategy []
|
||||||
|
GetNodeMetadataStrategy
|
||||||
|
(^NodeMetadata execute [this ^String id]
|
||||||
|
())))
|
||||||
|
(defineListNodesStrategy (defrecord ClojureListNodesStrategy []
|
||||||
|
ListNodesStrategy
|
||||||
|
(^Iterable list [this ]
|
||||||
|
())
|
||||||
|
(^Iterable listDetailsOnNodesMatching [this ^Predicate filter]
|
||||||
|
())
|
||||||
|
))
|
||||||
|
;; this needs to return Set<Hardware>
|
||||||
|
|
||||||
|
(defineHardwareSupplier
|
||||||
|
(defrecord HardwareSupplier []
|
||||||
|
Supplier
|
||||||
|
(get [this]
|
||||||
|
())
|
||||||
|
))
|
||||||
|
;; this needs to return Set<Image>
|
||||||
|
|
||||||
|
(defineImageSupplier (defrecord ImageSupplier []
|
||||||
|
Supplier
|
||||||
|
( get [this]
|
||||||
|
())
|
||||||
|
))
|
||||||
|
;; this needs to return Set<Location>
|
||||||
|
(defineLocationSupplier (defrecord LocationSupplier []
|
||||||
|
Supplier
|
||||||
|
( get [this]
|
||||||
|
())
|
||||||
|
))
|
||||||
|
(build)
|
||||||
|
|
||||||
|
))
|
||||||
|
|
||||||
|
(defn compute-context [module]
|
||||||
|
(ComputeServiceContextFactory/createStandaloneContext module))
|
||||||
|
|
||||||
|
(defrecord NodeListComputeService
|
||||||
|
[node-list]
|
||||||
|
org.jclouds.compute.ComputeService
|
||||||
|
(listNodes [_] node-list)
|
||||||
|
(getNodeMetadata
|
||||||
|
[_ id]
|
||||||
|
(some #(= (.getId %) id) node-list))
|
||||||
|
(listNodesDetailsMatching
|
||||||
|
[_ predicate]
|
||||||
|
(filter #(.apply predicate %) node-list)))
|
||||||
|
|
||||||
|
(defn ssh-client-factory
|
||||||
|
"Pass in a function that reifies org.jclouds.ssh.SshClient"
|
||||||
|
[ctor]
|
||||||
|
(reify
|
||||||
|
org.jclouds.ssh.SshClient$Factory
|
||||||
|
(^org.jclouds.ssh.SshClient create
|
||||||
|
[_ ^IPSocket socket ^String username ^String password-or-key]
|
||||||
|
(ctor socket username password-or-key))
|
||||||
|
(^org.jclouds.ssh.SshClient create
|
||||||
|
[_ ^IPSocket socket ^String username ^bytes password-or-key]
|
||||||
|
(ctor socket username password-or-key))))
|
||||||
|
|
||||||
|
(defn ssh-module
|
||||||
|
"Create a module that specifies the factory for creating an ssh service"
|
||||||
|
[^org.jclouds.ssh.SshClient$Factory factory]
|
||||||
|
(let [binder (atom nil)]
|
||||||
|
(reify
|
||||||
|
com.google.inject.Module
|
||||||
|
(configure
|
||||||
|
[this abinder]
|
||||||
|
(reset! binder abinder)
|
||||||
|
(.. @binder (bind org.jclouds.ssh.SshClient$Factory)
|
||||||
|
(toInstance factory))))))
|
|
@ -19,12 +19,25 @@
|
||||||
|
|
||||||
package org.jclouds.compute.config;
|
package org.jclouds.compute.config;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.jclouds.compute.ComputeService;
|
import org.jclouds.compute.ComputeService;
|
||||||
import org.jclouds.compute.ComputeServiceContext;
|
import org.jclouds.compute.ComputeServiceContext;
|
||||||
|
import org.jclouds.compute.domain.Hardware;
|
||||||
|
import org.jclouds.compute.domain.Image;
|
||||||
import org.jclouds.compute.internal.ComputeServiceContextImpl;
|
import org.jclouds.compute.internal.ComputeServiceContextImpl;
|
||||||
|
import org.jclouds.compute.strategy.AddNodeWithTagStrategy;
|
||||||
|
import org.jclouds.compute.strategy.DestroyNodeStrategy;
|
||||||
|
import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
|
||||||
|
import org.jclouds.compute.strategy.ListNodesStrategy;
|
||||||
|
import org.jclouds.compute.strategy.RebootNodeStrategy;
|
||||||
|
|
||||||
|
import com.google.common.base.Supplier;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
import com.google.inject.Module;
|
||||||
import com.google.inject.Scopes;
|
import com.google.inject.Scopes;
|
||||||
import com.google.inject.TypeLiteral;
|
import com.google.inject.TypeLiteral;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
|
@ -37,4 +50,107 @@ public abstract class StandaloneComputeServiceContextModule extends BaseComputeS
|
||||||
}).to(new TypeLiteral<ComputeServiceContextImpl<ComputeService, ComputeService>>() {
|
}).to(new TypeLiteral<ComputeServiceContextImpl<ComputeService, ComputeService>>() {
|
||||||
}).in(Scopes.SINGLETON);
|
}).in(Scopes.SINGLETON);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Builder builder() {
|
||||||
|
return new Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
private Set<Module> modules = Sets.newLinkedHashSet();
|
||||||
|
private Class<? extends AddNodeWithTagStrategy> addNodeWithTagStrategy;
|
||||||
|
private Class<? extends DestroyNodeStrategy> destroyNodeStrategy;
|
||||||
|
private Class<? extends GetNodeMetadataStrategy> getNodeMetadataStrategy;
|
||||||
|
private Class<? extends ListNodesStrategy> listNodesStrategy;
|
||||||
|
private Class<? extends RebootNodeStrategy> rebootNodeStrategy;
|
||||||
|
private Class<? extends Supplier<Set<? extends Hardware>>> hardwareSupplier;
|
||||||
|
private Class<? extends Supplier<Set<? extends Image>>> imageSupplier;
|
||||||
|
|
||||||
|
public Builder install(Module module) {
|
||||||
|
this.modules.add(module);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder defineAddNodeWithTagStrategy(Class<? extends AddNodeWithTagStrategy> addNodeWithTagStrategy) {
|
||||||
|
this.addNodeWithTagStrategy = addNodeWithTagStrategy;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder defineDestroyNodeStrategy(Class<? extends DestroyNodeStrategy> destroyNodeStrategy) {
|
||||||
|
this.destroyNodeStrategy = destroyNodeStrategy;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder defineGetNodeMetadataStrategy(Class<? extends GetNodeMetadataStrategy> getNodeMetadataStrategy) {
|
||||||
|
this.getNodeMetadataStrategy = getNodeMetadataStrategy;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder defineListNodesStrategy(Class<? extends ListNodesStrategy> listNodesStrategy) {
|
||||||
|
this.listNodesStrategy = listNodesStrategy;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder defineRebootNodeStrategy(Class<? extends RebootNodeStrategy> rebootNodeStrategy) {
|
||||||
|
this.rebootNodeStrategy = rebootNodeStrategy;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder defineHardwareSupplier(Class<? extends Supplier<Set<? extends Hardware>>> hardwareSupplier) {
|
||||||
|
this.hardwareSupplier = hardwareSupplier;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder defineImageSupplier(Class<? extends Supplier<Set<? extends Image>>> imageSupplier) {
|
||||||
|
this.imageSupplier = imageSupplier;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StandaloneComputeServiceContextModule build() {
|
||||||
|
return new StandaloneComputeServiceContextModule() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<? extends AddNodeWithTagStrategy> defineAddNodeWithTagStrategy() {
|
||||||
|
return addNodeWithTagStrategy;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<? extends DestroyNodeStrategy> defineDestroyNodeStrategy() {
|
||||||
|
return destroyNodeStrategy;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<? extends GetNodeMetadataStrategy> defineGetNodeMetadataStrategy() {
|
||||||
|
return getNodeMetadataStrategy;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<? extends Supplier<Set<? extends Hardware>>> defineHardwareSupplier() {
|
||||||
|
return hardwareSupplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<? extends Supplier<Set<? extends Image>>> defineImageSupplier() {
|
||||||
|
return imageSupplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<? extends ListNodesStrategy> defineListNodesStrategy() {
|
||||||
|
return listNodesStrategy;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<? extends RebootNodeStrategy> defineRebootNodeStrategy() {
|
||||||
|
return rebootNodeStrategy;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure() {
|
||||||
|
for (Module module : modules)
|
||||||
|
install(module);
|
||||||
|
super.configure();
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -313,7 +313,7 @@ public class StubComputeServiceDependenciesModule extends AbstractModule {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
static class StubImageSupplier implements Supplier<Set<? extends Image>> {
|
public static class StubImageSupplier implements Supplier<Set<? extends Image>> {
|
||||||
private final Supplier<Location> defaultLocation;
|
private final Supplier<Location> defaultLocation;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
|
@ -359,7 +359,7 @@ public class StubComputeServiceDependenciesModule extends AbstractModule {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
static class StubHardwareSupplier implements Supplier<Set<? extends Hardware>> {
|
public static class StubHardwareSupplier implements Supplier<Set<? extends Hardware>> {
|
||||||
|
|
||||||
static Hardware stub(String type, int cores, int ram, float disk) {
|
static Hardware stub(String type, int cores, int ram, float disk) {
|
||||||
return new org.jclouds.compute.domain.HardwareBuilder().id(type).providerId(type).name(type).processors(
|
return new org.jclouds.compute.domain.HardwareBuilder().id(type).providerId(type).name(type).processors(
|
||||||
|
|
|
@ -0,0 +1,107 @@
|
||||||
|
;
|
||||||
|
;
|
||||||
|
; Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
;
|
||||||
|
; ====================================================================
|
||||||
|
; Licensed 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.
|
||||||
|
; ====================================================================
|
||||||
|
;
|
||||||
|
(ns org.jclouds.ssh-test
|
||||||
|
(:require
|
||||||
|
[clojure.contrib.logging :as logging]
|
||||||
|
[org.jclouds.modules :as modules])
|
||||||
|
(:import
|
||||||
|
[org.jclouds.ssh SshClient ExecResponse]
|
||||||
|
org.jclouds.io.Payload
|
||||||
|
org.jclouds.net.IPSocket))
|
||||||
|
|
||||||
|
(defn instantiate [impl-class & args]
|
||||||
|
(let [constructor (first
|
||||||
|
(filter
|
||||||
|
(fn [c] (= (count args) (count (.getParameterTypes c))))
|
||||||
|
(.getDeclaredConstructors impl-class)))]
|
||||||
|
(.newInstance impl-class (object-array args))))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
;; define an instance or implementation of the following interfaces:
|
||||||
|
|
||||||
|
(defn maybe-invoke [f & args]
|
||||||
|
(when f
|
||||||
|
(apply f args)))
|
||||||
|
|
||||||
|
(defn default-exec
|
||||||
|
"Default exec function - replies to ./runscript status by returning 1"
|
||||||
|
[cmd]
|
||||||
|
(merge
|
||||||
|
{:exit 0 :err "stderr" :out "stdout"}
|
||||||
|
(condp = cmd
|
||||||
|
"./bootstrap status" {:exit 1 :out "[]"}
|
||||||
|
{})))
|
||||||
|
|
||||||
|
|
||||||
|
(deftype NoOpClient
|
||||||
|
[socket username password]
|
||||||
|
SshClient
|
||||||
|
(connect [this])
|
||||||
|
(disconnect [this])
|
||||||
|
(exec [this cmd]
|
||||||
|
(logging/info (format "ssh cmd: %s" cmd))
|
||||||
|
(let [response (default-exec cmd)]
|
||||||
|
(ExecResponse. (:out response) (:err response) (:exit response))))
|
||||||
|
(get [this path] )
|
||||||
|
(^void put [this ^String path ^String content])
|
||||||
|
(^void put [this ^String path ^org.jclouds.io.Payload content])
|
||||||
|
(getUsername [this] username)
|
||||||
|
(getHostAddress [this] (.getAddress socket)) )
|
||||||
|
|
||||||
|
(defn no-op-ssh-client
|
||||||
|
[socket username password]
|
||||||
|
(NoOpClient. socket username password))
|
||||||
|
|
||||||
|
|
||||||
|
(deftype SshClientFactory
|
||||||
|
[factory-fn]
|
||||||
|
org.jclouds.ssh.SshClient$Factory
|
||||||
|
(^org.jclouds.ssh.SshClient
|
||||||
|
create
|
||||||
|
[_ ^IPSocket socket ^String username ^String password-or-key]
|
||||||
|
(factory-fn socket username password-or-key))
|
||||||
|
(^org.jclouds.ssh.SshClient
|
||||||
|
create
|
||||||
|
[_ ^IPSocket socket ^String username ^bytes password-or-key]
|
||||||
|
(factory-fn socket username password-or-key)))
|
||||||
|
|
||||||
|
(deftype Module
|
||||||
|
[factory binder]
|
||||||
|
com.google.inject.Module
|
||||||
|
(configure
|
||||||
|
[this abinder]
|
||||||
|
(reset! binder abinder)
|
||||||
|
(.. @binder (bind org.jclouds.ssh.SshClient$Factory)
|
||||||
|
(toInstance factory))))
|
||||||
|
|
||||||
|
(defn ssh-test-module
|
||||||
|
"Create a module that specifies the factory for creating a test service"
|
||||||
|
[factory]
|
||||||
|
(let [binder (atom nil)]
|
||||||
|
(Module. factory binder)))
|
||||||
|
|
||||||
|
(defn ssh-test-client
|
||||||
|
"Create a module that can be passed to a compute-context, and which implements
|
||||||
|
an ssh client with the provided map of function implementations. Keys are
|
||||||
|
clojurefied versions of org.jclouds.ssh.SshClient's methods"
|
||||||
|
[factory-fn]
|
||||||
|
(ssh-test-module (SshClientFactory. factory-fn)))
|
||||||
|
|
|
@ -19,7 +19,16 @@
|
||||||
|
|
||||||
package org.jclouds.compute;
|
package org.jclouds.compute;
|
||||||
|
|
||||||
|
import org.jclouds.compute.config.StandaloneComputeServiceContextModule;
|
||||||
import org.jclouds.compute.stub.config.StubComputeServiceContextModule;
|
import org.jclouds.compute.stub.config.StubComputeServiceContextModule;
|
||||||
|
import org.jclouds.compute.stub.config.StubComputeServiceDependenciesModule;
|
||||||
|
import org.jclouds.compute.stub.config.StubComputeServiceDependenciesModule.StubAddNodeWithTagStrategy;
|
||||||
|
import org.jclouds.compute.stub.config.StubComputeServiceDependenciesModule.StubDestroyNodeStrategy;
|
||||||
|
import org.jclouds.compute.stub.config.StubComputeServiceDependenciesModule.StubGetNodeMetadataStrategy;
|
||||||
|
import org.jclouds.compute.stub.config.StubComputeServiceDependenciesModule.StubHardwareSupplier;
|
||||||
|
import org.jclouds.compute.stub.config.StubComputeServiceDependenciesModule.StubImageSupplier;
|
||||||
|
import org.jclouds.compute.stub.config.StubComputeServiceDependenciesModule.StubListNodesStrategy;
|
||||||
|
import org.jclouds.compute.stub.config.StubComputeServiceDependenciesModule.StubRebootNodeStrategy;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -32,8 +41,21 @@ public class ComputeServiceContextFactoryTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testStandalone() {
|
public void testStandalone() {
|
||||||
ComputeServiceContext context = ComputeServiceContextFactory.createStandaloneContext(new StubComputeServiceContextModule());
|
ComputeServiceContext context = ComputeServiceContextFactory
|
||||||
|
.createStandaloneContext(new StubComputeServiceContextModule());
|
||||||
context.getComputeService().listNodes();
|
context.getComputeService().listNodes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStandaloneWithBuilder() {
|
||||||
|
ComputeServiceContext context = ComputeServiceContextFactory
|
||||||
|
.createStandaloneContext(StandaloneComputeServiceContextModule.builder().install(
|
||||||
|
new StubComputeServiceDependenciesModule()).defineAddNodeWithTagStrategy(
|
||||||
|
StubAddNodeWithTagStrategy.class).defineDestroyNodeStrategy(StubDestroyNodeStrategy.class)
|
||||||
|
.defineGetNodeMetadataStrategy(StubGetNodeMetadataStrategy.class).defineListNodesStrategy(
|
||||||
|
StubListNodesStrategy.class).defineRebootNodeStrategy(StubRebootNodeStrategy.class)
|
||||||
|
.defineHardwareSupplier(StubHardwareSupplier.class)
|
||||||
|
.defineImageSupplier(StubImageSupplier.class).build());
|
||||||
|
context.getComputeService().listNodes();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue