merge with upstream master, resolving conflicts in SecurityGroupClientExpectTest

This commit is contained in:
Mike Arnold 2012-03-15 09:06:28 -05:00
commit d3f0e64de1
57 changed files with 1086 additions and 371 deletions

View File

@ -0,0 +1,77 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.openstack.services;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.inject.Qualifier;
/**
* An extension of a {@link ServiceType service}. In order for us to understand
* the context of the extension, we must consider the <a href=
* "http://docs.openstack.org/api/openstack-compute/2/content/Extensions-d1e1444.html"
* >extensions call</a>.
*
* <br/>
* For our purposes, the minimal context of an extension is the type of the
* service it extends ex. {@link ServiceType#COMPUTE}, and its namespace ex. <a
* href
* ="http://docs.openstack.org/ext/keypairs/api/v1.1">http://docs.openstack.org
* /ext/keypairs/api/v1.1</a>.
*
* @author Adrian Cole
*
* @see ServiceType
* @see <a href=
* "http://docs.openstack.org/api/openstack-compute/2/content/Extensions-d1e1444.html"
* />
* @see <a href="http://nova.openstack.org/api_ext" />
* @see <a href="http://nova.openstack.org/api_ext/ext_keypairs.html" />
*/
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = { ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
@Qualifier
public @interface Extension {
/**
* the service type this is an extension of.
*
* <h3>note</h3>
*
* This isn't necessarily one of the built-in {@link ServiceType services},
* it could be an extension of a custom service.
*
* @return the service type this is an extension of.
*
*/
String of();
/**
* namespace ex. <a href
* ="http://docs.openstack.org/ext/keypairs/api/v1.1">http
* ://docs.openstack.org /ext/keypairs/api/v1.1</a>.
*
* @return the namespace of the extension
*/
String namespace();
}

View File

@ -35,8 +35,11 @@ import javax.inject.Named;
import org.jclouds.concurrent.Timeout;
import org.jclouds.internal.ClassMethodArgs;
import org.jclouds.rest.annotations.Delegate;
import org.jclouds.util.Optionals2;
import org.jclouds.util.Throwables2;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
@ -51,14 +54,15 @@ import com.google.inject.ProvisionException;
public class SyncProxy implements InvocationHandler {
@SuppressWarnings("unchecked")
public static <T> T proxy(Class<T> clazz, Object async,
public static <T> T proxy(Function<Object, Optional<Object>> optionalConverter, Class<T> clazz, Object async,
@Named("sync") LoadingCache<ClassMethodArgs, Object> delegateMap,
Map<Class<?>, Class<?>> sync2Async, Map<String, Long> timeouts) throws IllegalArgumentException, SecurityException,
NoSuchMethodException {
return (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class<?>[] { clazz },
new SyncProxy(clazz, async, delegateMap, sync2Async, timeouts));
new SyncProxy(optionalConverter, clazz, async, delegateMap, sync2Async, timeouts));
}
private final Function<Object, Optional<Object>> optionalConverter;
private final Object delegate;
private final Class<?> declaring;
private final Map<Method, Method> methodMap;
@ -69,10 +73,11 @@ public class SyncProxy implements InvocationHandler {
private static final Set<Method> objectMethods = ImmutableSet.copyOf(Object.class.getMethods());
@Inject
private SyncProxy(Class<?> declaring, Object async,
private SyncProxy(Function<Object, Optional<Object>> optionalConverter, Class<?> declaring, Object async,
@Named("sync") LoadingCache<ClassMethodArgs, Object> delegateMap, Map<Class<?>,
Class<?>> sync2Async, final Map<String, Long> timeouts)
throws SecurityException, NoSuchMethodException {
this.optionalConverter = optionalConverter;
this.delegateMap = delegateMap;
this.delegate = async;
this.declaring = declaring;
@ -125,10 +130,19 @@ public class SyncProxy implements InvocationHandler {
} else if (method.getName().equals("toString")) {
return this.toString();
} else if (method.isAnnotationPresent(Delegate.class)) {
Class<?> asyncClass = sync2Async.get(method.getReturnType());
checkState(asyncClass != null, "please configure corresponding async class for " + method.getReturnType()
Class<?> syncClass = Optionals2.returnTypeOrTypeOfOptional(method);
// get the return type of the asynchronous class associated with this client
// ex. FloatingIPClient is associated with FloatingIPAsyncClient
Class<?> asyncClass = sync2Async.get(syncClass);
checkState(asyncClass != null, "please configure corresponding async class for " + syncClass
+ " in your RestClientModule");
// pass any parameters necessary to get a relevant instance of that async class
// ex. getClientForRegion("north") might return an instance whose endpoint is
// different that "south"
Object returnVal = delegateMap.get(new ClassMethodArgs(asyncClass, method, args));
if (Optionals2.isReturnTypeOptional(method)){
return optionalConverter.apply(returnVal);
}
return returnVal;
} else if (syncMethodMap.containsKey(method)) {
return syncMethodMap.get(method).invoke(delegate, args);

View File

@ -71,19 +71,19 @@ public class BinderUtils {
* interface for the sync client (ex. LoginClient)
* @param asyncClientType
* interface for the async client (ex. LoginAsyncClient)
* @param delegates
* @param sync2Async
* presuming your clients are annotated with @Delegate, contains the sync to async
* classes relating to these methods
*/
public static <S, A> void bindClientAndAsyncClient(Binder binder, Class<S> syncClientType, Class<A> asyncClientType,
Map<Class<?>, Class<?>> delegates) {
bindClient(binder, syncClientType, asyncClientType, delegates);
Map<Class<?>, Class<?>> sync2Async) {
bindClient(binder, syncClientType, asyncClientType, sync2Async);
bindAsyncClient(binder, asyncClientType);
}
public static <K, V> void bindClient(Binder binder, Class<K> syncClientType, Class<V> asyncClientType,
Map<Class<?>, Class<?>> delegates) {
Provider<K> asyncProvider = new ClientProvider<K, V>(syncClientType, asyncClientType, delegates);
Map<Class<?>, Class<?>> sync2Async) {
Provider<K> asyncProvider = new ClientProvider<K, V>(syncClientType, asyncClientType, sync2Async);
binder.requestInjection(asyncProvider);
binder.bind(syncClientType).toProvider(asyncProvider);
}

View File

@ -26,6 +26,8 @@ import javax.inject.Singleton;
import org.jclouds.concurrent.internal.SyncProxy;
import org.jclouds.internal.ClassMethodArgs;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Throwables;
import com.google.common.cache.LoadingCache;
import com.google.inject.Injector;
@ -59,17 +61,18 @@ public class ClientProvider<S, A> implements Provider<S> {
@Singleton
public S get() {
A client = (A) injector.getInstance(Key.get(asyncClientType));
Function<Object, Optional<Object>> optionalConverter = injector.getInstance(Key.get(new TypeLiteral<Function<Object, Optional<Object>>>() {
}));
LoadingCache<ClassMethodArgs, Object> delegateMap = injector.getInstance(Key.get(
new TypeLiteral<LoadingCache<ClassMethodArgs, Object>>() {
}, Names.named("sync")));
Map<String, Long> timeoutsMap = injector.getInstance(Key.get(new TypeLiteral<Map<String, Long>>() {
}, Names.named("TIMEOUTS")));
try {
return (S) SyncProxy.proxy(syncClientType, client, delegateMap, sync2Async,
injector.getInstance(Key.get(new TypeLiteral<Map<String, Long>>() {
}, Names.named("TIMEOUTS"))));
return (S) SyncProxy.proxy(optionalConverter, syncClientType, client, delegateMap, sync2Async,
timeoutsMap);
} catch (Exception e) {
Throwables.propagate(e);
assert false : "should have propagated";
return null;
throw Throwables.propagate(e);
}
}
}

View File

@ -33,7 +33,10 @@ import com.google.inject.TypeLiteral;
import com.google.inject.name.Names;
import org.jclouds.concurrent.internal.SyncProxy;
import org.jclouds.internal.ClassMethodArgs;
import org.jclouds.util.Optionals2;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Throwables;
import com.google.common.cache.LoadingCache;
import com.google.common.cache.CacheLoader;
@ -61,19 +64,19 @@ public class CreateClientForCaller extends CacheLoader<ClassMethodArgs, Object>
@Override
public Object load(ClassMethodArgs from) throws ExecutionException {
Class<?> syncClass = from.getMethod().getReturnType();
Class<?> syncClass = Optionals2.returnTypeOrTypeOfOptional(from.getMethod());
Class<?> asyncClass = sync2Async.get(syncClass);
checkState(asyncClass != null, "configuration error, sync class " + syncClass + " not mapped to an async class");
Object asyncClient = asyncMap.get(from);
checkState(asyncClient != null, "configuration error, sync client for " + from + " not found");
Function<Object, Optional<Object>> optionalConverter = injector.getInstance(Key.get(new TypeLiteral<Function<Object, Optional<Object>>>() {
}));
Map<String, Long> timeoutsMap = injector.getInstance(Key.get(new TypeLiteral<Map<String, Long>>() {
}, Names.named("TIMEOUTS")));
try {
return SyncProxy.proxy(syncClass, asyncClient, delegateMap.get(), sync2Async,
injector.getInstance(Key.get(new TypeLiteral<Map<String, Long>>() {
}, Names.named("TIMEOUTS"))));
return SyncProxy.proxy(optionalConverter, syncClass, asyncClient, delegateMap.get(), sync2Async, timeoutsMap);
} catch (Exception e) {
Throwables.propagate(e);
assert false : "should have propagated";
return null;
throw Throwables.propagate(e);
}
}

View File

@ -31,8 +31,11 @@ import org.jclouds.location.config.LocationModule;
import org.jclouds.rest.AuthorizationException;
import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.RestContext;
import org.jclouds.rest.functions.ImplicitOptionalConverter;
import org.jclouds.rest.internal.RestContextImpl;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Supplier;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.LoadingCache;
@ -55,14 +58,14 @@ public class RestClientModule<S, A> extends AbstractModule {
protected final Class<A> asyncClientType;
protected final Class<S> syncClientType;
protected final Map<Class<?>, Class<?>> delegates;
protected final Map<Class<?>, Class<?>> sync2Async;
protected final AtomicReference<AuthorizationException> authException = new AtomicReference<AuthorizationException>();
public RestClientModule(Class<S> syncClientType, Class<A> asyncClientType,
Map<Class<?>, Class<?>> delegates) {
Map<Class<?>, Class<?>> sync2Async) {
this.asyncClientType = asyncClientType;
this.syncClientType = syncClientType;
this.delegates = delegates;
this.sync2Async = sync2Async;
}
public RestClientModule(Class<S> syncClientType, Class<A> asyncClientType) {
@ -77,6 +80,7 @@ public class RestClientModule<S, A> extends AbstractModule {
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
protected void configure() {
bind(new TypeLiteral<Function<Object, Optional<Object>>>(){}).to(ImplicitOptionalConverter.class);
// this will help short circuit scenarios that can otherwise lock out users
bind(new TypeLiteral<AtomicReference<AuthorizationException>>(){}).toInstance(authException);
// Ensures the restcontext can be looked up without generic types.
@ -136,7 +140,7 @@ public class RestClientModule<S, A> extends AbstractModule {
protected void bindClient() {
BinderUtils.bindClient(binder(), syncClientType, asyncClientType,
delegates);
sync2Async);
}
@ -145,7 +149,7 @@ public class RestClientModule<S, A> extends AbstractModule {
@Named("sync")
LoadingCache<ClassMethodArgs, Object> provideSyncDelegateMap(
CreateClientForCaller createClientForCaller) {
createClientForCaller.sync2Async = delegates;
createClientForCaller.sync2Async = sync2Async;
return CacheBuilder.newBuilder().build(createClientForCaller);
}

View File

@ -0,0 +1,34 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.rest.functions;
import com.google.common.base.Optional;
/**
*
* @author Adrian Cole
*/
public class AlwaysPresentImplicitOptionalConverter implements ImplicitOptionalConverter {
@Override
public Optional<Object> apply(Object input) {
return Optional.of(input);
}
}

View File

@ -0,0 +1,32 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.rest.functions;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.inject.ImplementedBy;
/**
*
* @author Adrian Cole
*/
@ImplementedBy(AlwaysPresentImplicitOptionalConverter.class)
public interface ImplicitOptionalConverter extends Function<Object, Optional<Object>> {
}

View File

@ -41,9 +41,11 @@ import org.jclouds.logging.Logger;
import org.jclouds.rest.AuthorizationException;
import org.jclouds.rest.InvocationContext;
import org.jclouds.rest.annotations.Delegate;
import org.jclouds.util.Optionals2;
import org.jclouds.util.Throwables2;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.cache.LoadingCache;
@ -97,6 +99,7 @@ public class AsyncRestClientProxy<T> implements InvocationHandler {
@Resource
protected Logger logger = Logger.NULL;
private final Function<Object, Optional<Object>> optionalConverter;
private final LoadingCache<ClassMethodArgs, Object> delegateMap;
@SuppressWarnings("unchecked")
@ -104,6 +107,8 @@ public class AsyncRestClientProxy<T> implements InvocationHandler {
public AsyncRestClientProxy(Injector injector, Factory factory, RestAnnotationProcessor<T> util,
TypeLiteral<T> typeLiteral, @Named("async") LoadingCache<ClassMethodArgs, Object> delegateMap) {
this.injector = injector;
this.optionalConverter = injector.getInstance(Key.get(new TypeLiteral<Function<Object, Optional<Object>>>() {
}));
this.annotationProcessor = util;
this.declaring = (Class<T>) typeLiteral.getRawType();
this.commandFactory = factory;
@ -144,7 +149,12 @@ public class AsyncRestClientProxy<T> implements InvocationHandler {
}
public Object propagateContextToDelegate(Method method, Object[] args) throws ExecutionException {
return delegateMap.get(new ClassMethodArgs(method.getReturnType(), method, args));
Class<?> asyncClass = Optionals2.returnTypeOrTypeOfOptional(method);
Object returnVal = delegateMap.get(new ClassMethodArgs(asyncClass, method, args));
if (Optionals2.isReturnTypeOptional(method)){
return optionalConverter.apply(returnVal);
}
return returnVal;
}
public Object lookupValueFromGuice(Method method) {

View File

@ -0,0 +1,50 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.util;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import com.google.common.base.Optional;
/**
*
* @author Adrian Cole
*/
public class Optionals2 {
public static Class<?> returnTypeOrTypeOfOptional(Method method) {
boolean optional = isReturnTypeOptional(method);
Class<?> syncClass;
if (optional) {
ParameterizedType futureType = ParameterizedType.class.cast(method.getGenericReturnType());
// TODO: error checking in case this is a type, not a class.
syncClass = Class.class.cast(futureType.getActualTypeArguments()[0]);
} else {
syncClass = method.getReturnType();
}
return syncClass;
}
public static boolean isReturnTypeOptional(Method method) {
boolean optional = method.getReturnType().isAssignableFrom(Optional.class);
return optional;
}
}

View File

@ -32,13 +32,14 @@ import java.util.concurrent.TimeUnit;
import org.jclouds.concurrent.Futures;
import org.jclouds.concurrent.Timeout;
import org.jclouds.internal.ClassMethodArgs;
import org.jclouds.rest.functions.AlwaysPresentImplicitOptionalConverter;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import com.google.common.base.Functions;
import com.google.common.cache.LoadingCache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.util.concurrent.ListenableFuture;
@ -185,7 +186,7 @@ public class SyncProxyTest {
public void setUp() throws IllegalArgumentException, SecurityException, NoSuchMethodException {
LoadingCache<ClassMethodArgs, Object> cache = CacheBuilder.newBuilder().build(
CacheLoader.from(Functions.<Object> constant(null)));
sync = SyncProxy.proxy(Sync.class, new Async(), cache, ImmutableMap.<Class<?>, Class<?>> of(),
sync = SyncProxy.proxy(new AlwaysPresentImplicitOptionalConverter(), Sync.class, new Async(), cache, ImmutableMap.<Class<?>, Class<?>> of(),
ImmutableMap.of("Sync.takeXMillisecondsPropOverride", 250L));
// just to warm up
sync.string();
@ -260,7 +261,7 @@ public class SyncProxyTest {
IOException {
LoadingCache<ClassMethodArgs, Object> cache = CacheBuilder.newBuilder().build(
CacheLoader.from(Functions.<Object> constant(null)));
SyncProxy.proxy(SyncWrongException.class, new Async(), cache, ImmutableMap.<Class<?>, Class<?>> of(),
SyncProxy.proxy(new AlwaysPresentImplicitOptionalConverter(), SyncWrongException.class, new Async(), cache, ImmutableMap.<Class<?>, Class<?>> of(),
ImmutableMap.<String, Long> of());
}
@ -280,7 +281,7 @@ public class SyncProxyTest {
IOException {
LoadingCache<ClassMethodArgs, Object> cache = CacheBuilder.newBuilder().build(
CacheLoader.from(Functions.<Object> constant(null)));
SyncProxy.proxy(SyncNoTimeOut.class, new Async(), cache, ImmutableMap.<Class<?>, Class<?>> of(),
SyncProxy.proxy(new AlwaysPresentImplicitOptionalConverter(), SyncNoTimeOut.class, new Async(), cache, ImmutableMap.<Class<?>, Class<?>> of(),
ImmutableMap.<String, Long> of());
}
@ -301,7 +302,7 @@ public class SyncProxyTest {
public void testClassOverridePropTimeout() throws Exception {
LoadingCache<ClassMethodArgs, Object> cache = CacheBuilder.newBuilder().build(
CacheLoader.from(Functions.<Object> constant(null)));
final SyncClassOverride sync2 = SyncProxy.proxy(SyncClassOverride.class, new Async(), cache,
final SyncClassOverride sync2 = SyncProxy.proxy(new AlwaysPresentImplicitOptionalConverter(), SyncClassOverride.class, new Async(), cache,
ImmutableMap.<Class<?>, Class<?>> of(), ImmutableMap.<String, Long> of("SyncClassOverride", 100L));
assertEquals(sync2.takeXMillisecondsPropOverride(200), "foo");

View File

@ -135,6 +135,7 @@ import org.jclouds.rest.binders.BindMapToMatrixParams;
import org.jclouds.rest.binders.BindToJsonPayload;
import org.jclouds.rest.binders.BindToStringPayload;
import org.jclouds.rest.config.RestClientModule;
import org.jclouds.rest.functions.ImplicitOptionalConverter;
import org.jclouds.util.Strings2;
import org.jclouds.xml.XMLParser;
import org.testng.Assert;
@ -144,6 +145,7 @@ import org.testng.annotations.Test;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Optional;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableMap;
@ -184,8 +186,7 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
protected void configure() {
super.configure();
bind(new TypeLiteral<Supplier<URI>>() {
}).annotatedWith(Localhost2.class).toInstance(
Suppliers.ofInstance(URI.create("http://localhost:1111")));
}).annotatedWith(Localhost2.class).toInstance(Suppliers.ofInstance(URI.create("http://localhost:1111")));
bind(IOExceptionRetryHandler.class).toInstance(IOExceptionRetryHandler.NEVER_RETRY);
}
@ -212,6 +213,9 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
@Delegate
public Callee getCallee(@EndpointParam URI endpoint);
@Delegate
public Optional<Callee> getOptionalCallee(@EndpointParam URI endpoint);
}
@Timeout(duration = 10, timeUnit = TimeUnit.NANOSECONDS)
@ -230,15 +234,19 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
@Delegate
public AsyncCallee getCallee(@EndpointParam URI endpoint);
@Delegate
public Optional<AsyncCallee> getOptionalCallee(@EndpointParam URI endpoint);
}
public void testAsyncDelegateIsLazyLoadedAndRequestIncludesVersionAndPath() throws InterruptedException, ExecutionException {
public void testAsyncDelegateIsLazyLoadedAndRequestIncludesVersionAndPath() throws InterruptedException,
ExecutionException {
Injector child = injectorForCaller(new HttpCommandExecutorService() {
@Override
public Future<HttpResponse> submit(HttpCommand command) {
assertEquals(command.getCurrentRequest().getRequestLine(),
"GET http://localhost:9999/client/1/foo HTTP/1.1");
"GET http://localhost:9999/client/1/foo HTTP/1.1");
return Futures.immediateFuture(HttpResponse.builder().build());
}
@ -255,13 +263,14 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
}
public void testDelegateIsLazyLoadedAndRequestIncludesVersionAndPath() throws InterruptedException, ExecutionException {
public void testDelegateIsLazyLoadedAndRequestIncludesVersionAndPath() throws InterruptedException,
ExecutionException {
Injector child = injectorForCaller(new HttpCommandExecutorService() {
@Override
public Future<HttpResponse> submit(HttpCommand command) {
assertEquals(command.getCurrentRequest().getRequestLine(),
"GET http://localhost:1111/client/1/foo HTTP/1.1");
"GET http://localhost:1111/client/1/foo HTTP/1.1");
return Futures.immediateFuture(HttpResponse.builder().build());
}
@ -279,14 +288,13 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
}
public void testAsyncDelegateIsLazyLoadedAndRequestIncludesEndpointVersionAndPath() throws InterruptedException, ExecutionException {
public void testAsyncDelegateIsLazyLoadedAndRequestIncludesEndpointVersionAndPath() throws InterruptedException,
ExecutionException {
Injector child = injectorForCaller(new HttpCommandExecutorService() {
@Override
public Future<HttpResponse> submit(HttpCommand command) {
assertEquals(command.getCurrentRequest().getRequestLine(),
"GET http://howdyboys/client/1/foo HTTP/1.1");
assertEquals(command.getCurrentRequest().getRequestLine(), "GET http://howdyboys/client/1/foo HTTP/1.1");
return Futures.immediateFuture(HttpResponse.builder().build());
}
@ -305,13 +313,77 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
}
public void testDelegateIsLazyLoadedAndRequestIncludesEndpointVersionAndPath() throws InterruptedException, ExecutionException {
public void testAsyncDelegateIsLazyLoadedAndRequestIncludesEndpointVersionAndPathOptionalPresent()
throws InterruptedException, ExecutionException {
Injector child = injectorForCaller(new HttpCommandExecutorService() {
@Override
public Future<HttpResponse> submit(HttpCommand command) {
assertEquals(command.getCurrentRequest().getRequestLine(),
"GET http://howdyboys/client/1/foo HTTP/1.1");
assertEquals(command.getCurrentRequest().getRequestLine(), "GET http://howdyboys/client/1/foo HTTP/1.1");
return Futures.immediateFuture(HttpResponse.builder().build());
}
});
try {
child.getInstance(AsyncCallee.class);
assert false : "Callee shouldn't be bound yet";
} catch (ConfigurationException e) {
}
child.getInstance(AsyncCaller.class).getOptionalCallee(URI.create("http://howdyboys")).get().onePath("foo").get();
assertEquals(child.getInstance(AsyncCaller.class).getURI(), URI.create("http://localhost:1111"));
}
public void testAsyncDelegateIsLazyLoadedAndRequestIncludesEndpointVersionAndPathCanOverrideOptionalBehaviour()
throws InterruptedException, ExecutionException {
Injector child = injectorForCaller(new HttpCommandExecutorService() {
@Override
public Future<HttpResponse> submit(HttpCommand command) {
assertEquals(command.getCurrentRequest().getRequestLine(), "GET http://howdyboys/client/1/foo HTTP/1.1");
return Futures.immediateFuture(HttpResponse.builder().build());
}
}, new AbstractModule() {
@Override
protected void configure() {
bind(ImplicitOptionalConverter.class).toInstance(new ImplicitOptionalConverter() {
@Override
public Optional<Object> apply(Object input) {
return Optional.absent();
}
});
}
});
try {
child.getInstance(AsyncCallee.class);
assert false : "Callee shouldn't be bound yet";
} catch (ConfigurationException e) {
}
assert !child.getInstance(AsyncCaller.class).getOptionalCallee(URI.create("http://howdyboys")).isPresent();
assertEquals(child.getInstance(AsyncCaller.class).getURI(), URI.create("http://localhost:1111"));
}
public void testDelegateIsLazyLoadedAndRequestIncludesEndpointVersionAndPath() throws InterruptedException,
ExecutionException {
Injector child = injectorForCaller(new HttpCommandExecutorService() {
@Override
public Future<HttpResponse> submit(HttpCommand command) {
assertEquals(command.getCurrentRequest().getRequestLine(), "GET http://howdyboys/client/1/foo HTTP/1.1");
return Futures.immediateFuture(HttpResponse.builder().build());
}
@ -328,11 +400,20 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
}
private Injector injectorForCaller(HttpCommandExecutorService service) {
private Injector injectorForCaller(HttpCommandExecutorService service, Module... modules) {
RestContextSpec<Caller, AsyncCaller> contextSpec = contextSpec("test", "http://localhost:9999", "1", "", "",
"userfoo", null, Caller.class, AsyncCaller.class, ImmutableSet.<Module> of(new MockModule(service),
new NullLoggingModule(), new CallerModule()));
RestContextSpec<Caller, AsyncCaller> contextSpec = contextSpec(
"test",
"http://localhost:9999",
"1",
"",
"",
"userfoo",
null,
Caller.class,
AsyncCaller.class,
ImmutableSet.<Module> builder().add(new MockModule(service)).add(new NullLoggingModule())
.add(new CallerModule()).addAll(ImmutableSet.<Module> copyOf(modules)).build());
return createContextBuilder(contextSpec).buildInjector();
@ -1822,9 +1903,9 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
public void oneTransformerWithContext() throws SecurityException, NoSuchMethodException {
RestAnnotationProcessor<TestTransformers> processor = factory(TestTransformers.class);
Method method = TestTransformers.class.getMethod("oneTransformerWithContext");
GeneratedHttpRequest<TestTransformers> request = GeneratedHttpRequest.<TestTransformers>requestBuilder().method("GET")
.endpoint(URI.create("http://localhost")).declaring(TestTransformers.class).javaMethod(method)
.args(new Object[] {}).build();
GeneratedHttpRequest<TestTransformers> request = GeneratedHttpRequest.<TestTransformers> requestBuilder()
.method("GET").endpoint(URI.create("http://localhost")).declaring(TestTransformers.class)
.javaMethod(method).args(new Object[] {}).build();
Function<HttpResponse, ?> transformer = processor.createResponseParser(method, request);
assertEquals(transformer.getClass(), ReturnStringIf200Context.class);
assertEquals(((ReturnStringIf200Context) transformer).request, request);
@ -2354,9 +2435,9 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
public void testCreateJAXBResponseParserWithAnnotation() throws SecurityException, NoSuchMethodException {
RestAnnotationProcessor<TestJAXBResponseParser> processor = factory(TestJAXBResponseParser.class);
Method method = TestJAXBResponseParser.class.getMethod("jaxbGetWithAnnotation");
GeneratedHttpRequest<TestJAXBResponseParser> request = GeneratedHttpRequest.<TestJAXBResponseParser>requestBuilder()
.method("GET").endpoint(URI.create("http://localhost")).declaring(TestJAXBResponseParser.class)
.javaMethod(method).args(new Object[] {}).build();
GeneratedHttpRequest<TestJAXBResponseParser> request = GeneratedHttpRequest
.<TestJAXBResponseParser> requestBuilder().method("GET").endpoint(URI.create("http://localhost"))
.declaring(TestJAXBResponseParser.class).javaMethod(method).args(new Object[] {}).build();
Function<HttpResponse, ?> transformer = processor.createResponseParser(method, request);
assertEquals(transformer.getClass(), ParseXMLWithJAXB.class);
}
@ -2365,9 +2446,9 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
public void testCreateJAXBResponseParserWithAcceptHeader() throws SecurityException, NoSuchMethodException {
RestAnnotationProcessor<TestJAXBResponseParser> processor = factory(TestJAXBResponseParser.class);
Method method = TestJAXBResponseParser.class.getMethod("jaxbGetWithAcceptHeader");
GeneratedHttpRequest<TestJAXBResponseParser> request = GeneratedHttpRequest.<TestJAXBResponseParser>requestBuilder()
.method("GET").endpoint(URI.create("http://localhost")).declaring(TestJAXBResponseParser.class)
.javaMethod(method).args(new Object[] {}).build();
GeneratedHttpRequest<TestJAXBResponseParser> request = GeneratedHttpRequest
.<TestJAXBResponseParser> requestBuilder().method("GET").endpoint(URI.create("http://localhost"))
.declaring(TestJAXBResponseParser.class).javaMethod(method).args(new Object[] {}).build();
Function<HttpResponse, ?> transformer = processor.createResponseParser(method, request);
assertEquals(transformer.getClass(), ParseXMLWithJAXB.class);
}
@ -2409,40 +2490,40 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
}
@Test(expectedExceptions = NullPointerException.class)
public void testAddHostNullWithHost() throws Exception{
assertNull(RestAnnotationProcessor.addHostIfMissing(null,null));
public void testAddHostNullWithHost() throws Exception {
assertNull(RestAnnotationProcessor.addHostIfMissing(null, null));
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void testAddHostWithHostHasNoHost() throws Exception{
assertNull(RestAnnotationProcessor.addHostIfMissing(null,new URI("/no/host")));
public void testAddHostWithHostHasNoHost() throws Exception {
assertNull(RestAnnotationProcessor.addHostIfMissing(null, new URI("/no/host")));
}
@Test
public void testAddHostNullOriginal() throws Exception{
assertNull(RestAnnotationProcessor.addHostIfMissing(null,new URI("http://foo")));
public void testAddHostNullOriginal() throws Exception {
assertNull(RestAnnotationProcessor.addHostIfMissing(null, new URI("http://foo")));
}
@Test
public void testAddHostOriginalHasHost() throws Exception{
public void testAddHostOriginalHasHost() throws Exception {
URI original = new URI("http://hashost/foo");
URI result = RestAnnotationProcessor.addHostIfMissing(original,new URI("http://foo"));
assertEquals(original,result);
URI original = new URI("http://hashost/foo");
URI result = RestAnnotationProcessor.addHostIfMissing(original, new URI("http://foo"));
assertEquals(original, result);
}
@Test
public void testAddHostIfMissing() throws Exception{
URI result = RestAnnotationProcessor.addHostIfMissing(new URI("/bar"),new URI("http://foo"));
assertEquals(new URI("http://foo/bar"),result);
public void testAddHostIfMissing() throws Exception {
URI result = RestAnnotationProcessor.addHostIfMissing(new URI("/bar"), new URI("http://foo"));
assertEquals(new URI("http://foo/bar"), result);
}
DateService dateService = new SimpleDateFormatDateService();
@BeforeClass
void setupFactory() {
RestContextSpec<Callee, AsyncCallee> contextSpec = contextSpec("test", "http://localhost:9999", "1", "", "", "userfoo",
null, Callee.class, AsyncCallee.class,
RestContextSpec<Callee, AsyncCallee> contextSpec = contextSpec("test", "http://localhost:9999", "1", "", "",
"userfoo", null, Callee.class, AsyncCallee.class,
ImmutableSet.<Module> of(new MockModule(), new NullLoggingModule(), new AbstractModule() {
@Override
@ -2453,7 +2534,7 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
}).annotatedWith(Names.named("bar")).toInstance(ImmutableSet.of("bar"));
bind(new TypeLiteral<Supplier<URI>>() {
}).annotatedWith(Localhost2.class).toInstance(
Suppliers.ofInstance(URI.create("http://localhost:1111")));
Suppliers.ofInstance(URI.create("http://localhost:1111")));
}
@SuppressWarnings("unused")

View File

@ -0,0 +1,66 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.util;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
import java.lang.reflect.Method;
import org.testng.annotations.Test;
import com.google.common.base.Optional;
/**
* @author Adrian Cole
*/
@Test
public class Optionals2Test {
public static interface Test {
Optional<String> getOptional();
String getNotOptional();
}
public void testReturnTypeOrTypeOfOptionalWhenOptional() throws SecurityException, NoSuchMethodException {
Method method = Test.class.getMethod("getOptional");
assertEquals(Optionals2.returnTypeOrTypeOfOptional(method), String.class);
}
public void testReturnTypeOrTypeOfOptionalWhenNotOptional() throws SecurityException, NoSuchMethodException {
Method method = Test.class.getMethod("getNotOptional");
assertEquals(Optionals2.returnTypeOrTypeOfOptional(method), String.class);
}
public void testIsReturnTypeOptionalWhenOptional() throws SecurityException, NoSuchMethodException {
Method method = Test.class.getMethod("getOptional");
assertTrue(Optionals2.isReturnTypeOptional(method));
}
public void testIsReturnTypeOptionalWhenNotOptional() throws SecurityException, NoSuchMethodException {
Method method = Test.class.getMethod("getNotOptional");
assertFalse(Optionals2.isReturnTypeOptional(method));
}
}

View File

@ -33,6 +33,7 @@ import org.jclouds.openstack.nova.v1_1.features.ServerAsyncClient;
import org.jclouds.rest.annotations.Delegate;
import org.jclouds.rest.annotations.EndpointParam;
import com.google.common.base.Optional;
import com.google.inject.Provides;
/**
@ -85,7 +86,7 @@ public interface NovaAsyncClient {
* Provides asynchronous access to Floating IP features.
*/
@Delegate
FloatingIPAsyncClient getFloatingIPClientForRegion(
Optional<FloatingIPAsyncClient> getFloatingIPExtensionForRegion(
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region);
/**

View File

@ -35,6 +35,7 @@ import org.jclouds.openstack.nova.v1_1.features.ServerClient;
import org.jclouds.rest.annotations.Delegate;
import org.jclouds.rest.annotations.EndpointParam;
import com.google.common.base.Optional;
import com.google.inject.Provides;
/**
@ -87,7 +88,7 @@ public interface NovaClient {
* Provides synchronous access to Floating IP features.
*/
@Delegate
FloatingIPClient getFloatingIPClientForRegion(
Optional<FloatingIPClient> getFloatingIPExtensionForRegion(
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region);
/**

View File

@ -18,7 +18,6 @@
*/
package org.jclouds.openstack.nova.v1_1.extensions;
import java.net.URI;
/**
* Extension namespaces
@ -27,8 +26,8 @@ import java.net.URI;
* @see <a href= "http://nova.openstack.org/api_ext/" />
*/
public interface ExtensionNamespaces {
public static URI KEYPAIRS = URI.create("http://docs.openstack.org/ext/keypairs/api/v1.1");
public static URI VOLUMES = URI.create("http://docs.openstack.org/ext/volumes/api/v1.1");
public static URI SECURITY_GROUPS = URI.create("http://docs.openstack.org/ext/securitygroups/api/v1.1");
public static URI FLOATING_IPS = URI.create("http://docs.openstack.org/ext/floating_ips/api/v1.1");
public static final String KEYPAIRS = "http://docs.openstack.org/ext/keypairs/api/v1.1";
public static final String VOLUMES = "http://docs.openstack.org/ext/volumes/api/v1.1";
public static final String SECURITY_GROUPS = "http://docs.openstack.org/ext/securitygroups/api/v1.1";
public static final String FLOATING_IPS = "http://docs.openstack.org/ext/floating_ips/api/v1.1";
}

View File

@ -32,6 +32,8 @@ import javax.ws.rs.core.MediaType;
import org.jclouds.openstack.filters.AuthenticateRequest;
import org.jclouds.openstack.nova.v1_1.domain.FloatingIP;
import org.jclouds.openstack.nova.v1_1.features.ExtensionAsyncClient;
import org.jclouds.openstack.services.Extension;
import org.jclouds.openstack.services.ServiceType;
import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.annotations.Payload;
import org.jclouds.rest.annotations.PayloadParam;
@ -50,10 +52,13 @@ import com.google.common.util.concurrent.ListenableFuture;
* @see FloatingIPClient
* @author Jeremy Daggett
* @see ExtensionAsyncClient
* @see <a href="http://docs.openstack.org/api/openstack-compute/2/content/Extensions-d1e1444.html" />
* @see <a href=
* "http://docs.openstack.org/api/openstack-compute/2/content/Extensions-d1e1444.html"
* />
* @see <a href="http://nova.openstack.org/api_ext" />
* @see <a href="http://wiki.openstack.org/os_api_floating_ip"/>
*/
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.FLOATING_IPS)
@SkipEncoding({ '/', '=' })
@RequestFilters(AuthenticateRequest.class)
public interface FloatingIPAsyncClient {
@ -107,9 +112,7 @@ public interface FloatingIPAsyncClient {
@Consumes
@Produces(MediaType.APPLICATION_JSON)
@Payload("%7B\"addFloatingIp\":%7B\"address\":\"{address}\"%7D%7D")
ListenableFuture<Void> addFloatingIP(
@PathParam("server") String serverId,
@PayloadParam("address") String address);
ListenableFuture<Void> addFloatingIP(@PathParam("server") String serverId, @PayloadParam("address") String address);
/**
* @see FloatingIPClient#removeFloatingIP
@ -119,8 +122,6 @@ public interface FloatingIPAsyncClient {
@Consumes
@Produces(MediaType.APPLICATION_JSON)
@Payload("%7B\"removeFloatingIp\":%7B\"address\":\"{address}\"%7D%7D")
ListenableFuture<Void> removeFloatingIP(
@PathParam("server") String serverId,
@PayloadParam("address") String address);
ListenableFuture<Void> removeFloatingIP(@PathParam("server") String serverId, @PayloadParam("address") String address);
}

View File

@ -23,6 +23,8 @@ import java.util.concurrent.TimeUnit;
import org.jclouds.concurrent.Timeout;
import org.jclouds.openstack.nova.v1_1.domain.FloatingIP;
import org.jclouds.openstack.services.Extension;
import org.jclouds.openstack.services.ServiceType;
/**
* Provides synchronous access to Floating IPs.
@ -31,6 +33,7 @@ import org.jclouds.openstack.nova.v1_1.domain.FloatingIP;
* @see FloatingIPAsyncClient
* @author Jeremy Daggett
*/
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.FLOATING_IPS)
@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS)
public interface FloatingIPClient {

View File

@ -33,6 +33,8 @@ import javax.ws.rs.core.MediaType;
import org.jclouds.openstack.filters.AuthenticateRequest;
import org.jclouds.openstack.nova.v1_1.domain.KeyPair;
import org.jclouds.openstack.nova.v1_1.features.ExtensionAsyncClient;
import org.jclouds.openstack.services.Extension;
import org.jclouds.openstack.services.ServiceType;
import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.annotations.Payload;
import org.jclouds.rest.annotations.PayloadParam;
@ -55,6 +57,7 @@ import com.google.common.util.concurrent.ListenableFuture;
* @see <a href="http://nova.openstack.org/api_ext" />
* @see <a href="http://nova.openstack.org/api_ext/ext_keypairs.html" />
*/
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.KEYPAIRS)
@SkipEncoding({ '/', '=' })
@RequestFilters(AuthenticateRequest.class)
public interface KeyPairAsyncClient {

View File

@ -24,6 +24,8 @@ import java.util.concurrent.TimeUnit;
import org.jclouds.concurrent.Timeout;
import org.jclouds.openstack.nova.v1_1.domain.KeyPair;
import org.jclouds.openstack.services.Extension;
import org.jclouds.openstack.services.ServiceType;
/**
* Provides synchronous access to Security Groups.
@ -32,6 +34,7 @@ import org.jclouds.openstack.nova.v1_1.domain.KeyPair;
* @see KeyPairAsyncClient
* @author Jeremy Daggett
*/
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.KEYPAIRS)
@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS)
public interface KeyPairClient {

View File

@ -32,6 +32,8 @@ import javax.ws.rs.core.MediaType;
import org.jclouds.openstack.filters.AuthenticateRequest;
import org.jclouds.openstack.nova.v1_1.domain.SecurityGroup;
import org.jclouds.openstack.nova.v1_1.domain.SecurityGroupRule;
import org.jclouds.openstack.services.Extension;
import org.jclouds.openstack.services.ServiceType;
import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.annotations.Payload;
import org.jclouds.rest.annotations.PayloadParam;
@ -54,6 +56,7 @@ import com.google.common.util.concurrent.ListenableFuture;
* @see <a href="http://nova.openstack.org/api_ext" />
* @see <a href="http://wiki.openstack.org/os-security-groups" />
*/
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.SECURITY_GROUPS)
@SkipEncoding({ '/', '=' })
@RequestFilters(AuthenticateRequest.class)
public interface SecurityGroupAsyncClient {

View File

@ -24,6 +24,8 @@ import java.util.concurrent.TimeUnit;
import org.jclouds.concurrent.Timeout;
import org.jclouds.openstack.nova.v1_1.domain.SecurityGroup;
import org.jclouds.openstack.nova.v1_1.domain.SecurityGroupRule;
import org.jclouds.openstack.services.Extension;
import org.jclouds.openstack.services.ServiceType;
/**
* Provides synchronous access to Security Groups.
@ -32,6 +34,7 @@ import org.jclouds.openstack.nova.v1_1.domain.SecurityGroupRule;
* @see SecurityGroupAsyncClient
* @author Jeremy Daggett
*/
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.SECURITY_GROUPS)
@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS)
public interface SecurityGroupClient {

View File

@ -26,7 +26,7 @@ import java.util.Properties;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties;
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaRestClientExpectTest;
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaClientExpectTest;
import org.jclouds.openstack.nova.v1_1.parse.ParseServerListTest;
import org.testng.annotations.Test;
@ -39,7 +39,7 @@ import com.google.common.collect.ImmutableSet;
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "PasswordAuthenticationExpectTest")
public class PasswordAuthenticationExpectTest extends BaseNovaRestClientExpectTest {
public class PasswordAuthenticationExpectTest extends BaseNovaClientExpectTest {
/**
* this reflects the properties that a user would pass to createContext

View File

@ -0,0 +1,160 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.openstack.nova.v1_1.extensions;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
import java.net.URI;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.openstack.nova.v1_1.NovaAsyncClient;
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaAsyncClientExpectTest;
import org.jclouds.openstack.nova.v1_1.parse.ParseFloatingIPListTest;
import org.jclouds.openstack.nova.v1_1.parse.ParseFloatingIPTest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
/**
* Tests annotation parsing of {@code FloatingIPAsyncClient}
*
* @author Michael Arnold
*/
@Test(groups = "unit", testName = "FloatingIPAsyncClientExpectTest")
public class FloatingIPAsyncClientExpectTest extends BaseNovaAsyncClientExpectTest {
public void testListFloatingIPsWhenResponseIs2xx() throws Exception {
HttpRequest listFloatingIPs = HttpRequest
.builder()
.method("GET")
.endpoint(URI.create("https://compute.north.host/v1.1/3456/os-floating-ips"))
.headers(
ImmutableMultimap.<String, String> builder().put("Accept", "application/json")
.put("X-Auth-Token", authToken).build()).build();
HttpResponse listFloatingIPsResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/floatingip_list.json")).build();
NovaAsyncClient clientWhenFloatingIPsExist = requestsSendResponses(keystoneAuthWithAccessKeyAndSecretKey,
responseWithKeystoneAccess, listFloatingIPs, listFloatingIPsResponse);
assertEquals(clientWhenFloatingIPsExist.getConfiguredRegions(), ImmutableSet.of("North"));
assertEquals(clientWhenFloatingIPsExist.getFloatingIPExtensionForRegion("North").get().listFloatingIPs().get()
.toString(), new ParseFloatingIPListTest().expected().toString());
}
public void testListFloatingIPsWhenResponseIs404() throws Exception {
HttpRequest listFloatingIPs = HttpRequest
.builder()
.method("GET")
.endpoint(URI.create("https://compute.north.host/v1.1/3456/os-floating-ips"))
.headers(
ImmutableMultimap.<String, String> builder().put("Accept", "application/json")
.put("X-Auth-Token", authToken).build()).build();
HttpResponse listFloatingIPsResponse = HttpResponse.builder().statusCode(404).build();
NovaAsyncClient clientWhenNoServersExist = requestsSendResponses(keystoneAuthWithAccessKeyAndSecretKey,
responseWithKeystoneAccess, listFloatingIPs, listFloatingIPsResponse);
assertTrue(clientWhenNoServersExist.getFloatingIPExtensionForRegion("North").get().listFloatingIPs().get()
.isEmpty());
}
public void testGetFloatingIPWhenResponseIs2xx() throws Exception {
HttpRequest getFloatingIP = HttpRequest
.builder()
.method("GET")
.endpoint(URI.create("https://compute.north.host/v1.1/3456/os-floating-ips/1"))
.headers(
ImmutableMultimap.<String, String> builder().put("Accept", "application/json")
.put("X-Auth-Token", authToken).build()).build();
HttpResponse getFloatingIPResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/floatingip_details.json")).build();
NovaAsyncClient clientWhenFloatingIPsExist = requestsSendResponses(keystoneAuthWithAccessKeyAndSecretKey,
responseWithKeystoneAccess, getFloatingIP, getFloatingIPResponse);
assertEquals(clientWhenFloatingIPsExist.getFloatingIPExtensionForRegion("North").get().getFloatingIP("1").get()
.toString(), new ParseFloatingIPTest().expected().toString());
}
public void testGetFloatingIPWhenResponseIs404() throws Exception {
HttpRequest getFloatingIP = HttpRequest
.builder()
.method("GET")
.endpoint(URI.create("https://compute.north.host/v1.1/3456/os-floating-ips/1"))
.headers(
ImmutableMultimap.<String, String> builder().put("Accept", "application/json")
.put("X-Auth-Token", authToken).build()).build();
HttpResponse getFloatingIPResponse = HttpResponse.builder().statusCode(404).build();
NovaAsyncClient clientWhenNoServersExist = requestsSendResponses(keystoneAuthWithAccessKeyAndSecretKey,
responseWithKeystoneAccess, getFloatingIP, getFloatingIPResponse);
assertNull(clientWhenNoServersExist.getFloatingIPExtensionForRegion("North").get().getFloatingIP("1").get());
}
public void testAllocateWhenResponseIs2xx() throws Exception {
HttpRequest allocateFloatingIP = HttpRequest
.builder()
.method("POST")
.endpoint(URI.create("https://compute.north.host/v1.1/3456/os-floating-ips"))
.headers(
ImmutableMultimap.<String, String> builder().put("Accept", "application/json")
.put("X-Auth-Token", authToken).build())
.payload(payloadFromStringWithContentType("{}", "application/json")).build();
HttpResponse allocateFloatingIPResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/floatingip_details.json")).build();
NovaAsyncClient clientWhenFloatingIPsExist = requestsSendResponses(keystoneAuthWithAccessKeyAndSecretKey,
responseWithKeystoneAccess, allocateFloatingIP, allocateFloatingIPResponse);
assertEquals(clientWhenFloatingIPsExist.getFloatingIPExtensionForRegion("North").get().allocate().get()
.toString(), new ParseFloatingIPTest().expected().toString());
}
public void testAllocateWhenResponseIs404() throws Exception {
HttpRequest allocateFloatingIP = HttpRequest
.builder()
.method("POST")
.endpoint(URI.create("https://compute.north.host/v1.1/3456/os-floating-ips"))
.headers(
ImmutableMultimap.<String, String> builder().put("Accept", "application/json")
.put("X-Auth-Token", authToken).build())
.payload(payloadFromStringWithContentType("{}", "application/json")).build();
HttpResponse allocateFloatingIPResponse = HttpResponse.builder().statusCode(404).build();
NovaAsyncClient clientWhenNoServersExist = requestsSendResponses(keystoneAuthWithAccessKeyAndSecretKey,
responseWithKeystoneAccess, allocateFloatingIP, allocateFloatingIPResponse);
assertNull(clientWhenNoServersExist.getFloatingIPExtensionForRegion("North").get().allocate().get());
}
}

View File

@ -27,7 +27,7 @@ import java.net.URI;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.openstack.nova.v1_1.NovaClient;
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaRestClientExpectTest;
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaClientExpectTest;
import org.jclouds.openstack.nova.v1_1.parse.ParseFloatingIPListTest;
import org.jclouds.openstack.nova.v1_1.parse.ParseFloatingIPTest;
import org.testng.annotations.Test;
@ -41,7 +41,7 @@ import com.google.common.collect.ImmutableSet;
* @author Michael Arnold
*/
@Test(groups = "unit", testName = "FloatingIPClientExpectTest")
public class FloatingIPClientExpectTest extends BaseNovaRestClientExpectTest {
public class FloatingIPClientExpectTest extends BaseNovaClientExpectTest {
public void testListFloatingIPsWhenResponseIs2xx() throws Exception {
HttpRequest listFloatingIPs = HttpRequest
@ -64,7 +64,7 @@ public class FloatingIPClientExpectTest extends BaseNovaRestClientExpectTest {
assertEquals(clientWhenFloatingIPsExist.getConfiguredRegions(),
ImmutableSet.of("North"));
assertEquals(clientWhenFloatingIPsExist.getFloatingIPClientForRegion("North")
assertEquals(clientWhenFloatingIPsExist.getFloatingIPExtensionForRegion("North").get()
.listFloatingIPs().toString(), new ParseFloatingIPListTest().expected()
.toString());
}
@ -87,7 +87,7 @@ public class FloatingIPClientExpectTest extends BaseNovaRestClientExpectTest {
keystoneAuthWithAccessKeyAndSecretKey, responseWithKeystoneAccess,
listFloatingIPs, listFloatingIPsResponse);
assertTrue(clientWhenNoServersExist.getFloatingIPClientForRegion("North")
assertTrue(clientWhenNoServersExist.getFloatingIPExtensionForRegion("North").get()
.listFloatingIPs().isEmpty());
}
@ -109,7 +109,7 @@ public class FloatingIPClientExpectTest extends BaseNovaRestClientExpectTest {
keystoneAuthWithAccessKeyAndSecretKey, responseWithKeystoneAccess,
getFloatingIP, getFloatingIPResponse);
assertEquals(clientWhenFloatingIPsExist.getFloatingIPClientForRegion("North")
assertEquals(clientWhenFloatingIPsExist.getFloatingIPExtensionForRegion("North").get()
.getFloatingIP("1").toString(),
new ParseFloatingIPTest().expected().toString());
}
@ -131,7 +131,7 @@ public class FloatingIPClientExpectTest extends BaseNovaRestClientExpectTest {
keystoneAuthWithAccessKeyAndSecretKey, responseWithKeystoneAccess,
getFloatingIP, getFloatingIPResponse);
assertNull(clientWhenNoServersExist.getFloatingIPClientForRegion("North")
assertNull(clientWhenNoServersExist.getFloatingIPExtensionForRegion("North").get()
.getFloatingIP("1"));
}
@ -154,7 +154,7 @@ public class FloatingIPClientExpectTest extends BaseNovaRestClientExpectTest {
keystoneAuthWithAccessKeyAndSecretKey, responseWithKeystoneAccess,
allocateFloatingIP, allocateFloatingIPResponse);
assertEquals(clientWhenFloatingIPsExist.getFloatingIPClientForRegion("North")
assertEquals(clientWhenFloatingIPsExist.getFloatingIPExtensionForRegion("North").get()
.allocate().toString(),
new ParseFloatingIPTest().expected().toString());
@ -178,7 +178,7 @@ public class FloatingIPClientExpectTest extends BaseNovaRestClientExpectTest {
keystoneAuthWithAccessKeyAndSecretKey, responseWithKeystoneAccess,
allocateFloatingIP, allocateFloatingIPResponse);
assertNull(clientWhenNoServersExist.getFloatingIPClientForRegion("North")
assertNull(clientWhenNoServersExist.getFloatingIPExtensionForRegion("North").get()
.allocate());
}

View File

@ -25,6 +25,7 @@ import static org.testng.Assert.assertTrue;
import java.util.Set;
import com.google.common.base.Optional;
import com.google.common.collect.Iterables;
import org.jclouds.openstack.nova.v1_1.domain.Address;
import org.jclouds.openstack.nova.v1_1.domain.FloatingIP;
@ -52,8 +53,10 @@ public class FloatingIPClientLiveTest extends BaseNovaClientLiveTest {
@Test
public void testListFloatingIPs() throws Exception {
for (String regionId : context.getApi().getConfiguredRegions()) {
FloatingIPClient client = context.getApi().getFloatingIPClientForRegion(regionId);
Optional<FloatingIPClient> clientOption = context.getApi().getFloatingIPExtensionForRegion(regionId);
if (!clientOption.isPresent())
continue;
FloatingIPClient client = clientOption.get();
Set<FloatingIP> response = client.listFloatingIPs();
assert null != response;
assertTrue(response.size() >= 0);
@ -73,7 +76,10 @@ public class FloatingIPClientLiveTest extends BaseNovaClientLiveTest {
@Test
public void testAllocateAndDeallocateFloatingIPs() throws Exception {
for (String regionId : context.getApi().getConfiguredRegions()) {
FloatingIPClient client = context.getApi().getFloatingIPClientForRegion(regionId);
Optional<FloatingIPClient> clientOption = context.getApi().getFloatingIPExtensionForRegion(regionId);
if (!clientOption.isPresent())
continue;
FloatingIPClient client = clientOption.get();
FloatingIP floatingIP = client.allocate();
assertNotNull(floatingIP);
@ -101,7 +107,10 @@ public class FloatingIPClientLiveTest extends BaseNovaClientLiveTest {
@Test
public void testAddAndRemoveFloatingIp() throws Exception {
for (String regionId : context.getApi().getConfiguredRegions()) {
FloatingIPClient client = context.getApi().getFloatingIPClientForRegion(regionId);
Optional<FloatingIPClient> clientOption = context.getApi().getFloatingIPExtensionForRegion(regionId);
if (!clientOption.isPresent())
continue;
FloatingIPClient client = clientOption.get();
ServerClient serverClient = context.getApi().getServerClientForRegion(regionId);
Server server = serverClient.createServer("test", imageIdForRegion(regionId), flavorRefForRegion(regionId));
blockUntilServerActive(server.getId(), serverClient);

View File

@ -23,7 +23,7 @@ import com.google.common.collect.ImmutableSet;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.openstack.nova.v1_1.NovaClient;
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaRestClientExpectTest;
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaClientExpectTest;
import org.jclouds.openstack.nova.v1_1.parse.ParseKeyPairListTest;
import org.jclouds.openstack.nova.v1_1.parse.ParseKeyPairTest;
import org.testng.annotations.Test;
@ -40,7 +40,7 @@ import static org.testng.Assert.assertTrue;
* @author Michael Arnold
*/
@Test(groups = "unit", testName = "KeyPairClientExpectTest")
public class KeyPairClientExpectTest extends BaseNovaRestClientExpectTest {
public class KeyPairClientExpectTest extends BaseNovaClientExpectTest {
public void testListKeyPairsWhenResponseIs2xx() throws Exception {
HttpRequest listKeyPairs = HttpRequest

View File

@ -16,17 +16,22 @@
* specific language governing permissions and limitations
* under the License.
*/
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
package org.jclouds.openstack.nova.v1_1.extensions;
import static org.testng.Assert.assertEquals;
import java.net.URI;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.openstack.nova.v1_1.NovaClient;
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaRestClientExpectTest;
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaClientExpectTest;
import org.jclouds.openstack.nova.v1_1.parse.ParseSecurityGroupListTest;
import org.jclouds.openstack.nova.v1_1.parse.ParseSecurityGroupTest;
import org.testng.annotations.Test;
import java.net.URI;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
@ -38,7 +43,7 @@ import static org.testng.Assert.assertTrue;
* @author Michael Arnold
*/
@Test(groups = "unit", testName = "SecurityGroupClientExpectTest")
public class SecurityGroupClientExpectTest extends BaseNovaRestClientExpectTest {
public class SecurityGroupClientExpectTest extends BaseNovaClientExpectTest {
public void testListSecurityGroupsWhenResponseIs2xx() throws Exception {
HttpRequest listSecurityGroups = HttpRequest
.builder()

View File

@ -27,7 +27,7 @@ import java.net.URI;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.openstack.nova.v1_1.NovaClient;
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaRestClientExpectTest;
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaClientExpectTest;
import org.jclouds.openstack.nova.v1_1.parse.ParseExtensionListTest;
import org.jclouds.openstack.nova.v1_1.parse.ParseExtensionTest;
import org.testng.annotations.Test;
@ -41,7 +41,7 @@ import com.google.common.collect.ImmutableSet;
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "ExtensionClientExpectTest")
public class ExtensionClientExpectTest extends BaseNovaRestClientExpectTest {
public class ExtensionClientExpectTest extends BaseNovaClientExpectTest {
public void testListExtensionsWhenResponseIs2xx() throws Exception {
HttpRequest listExtensions = HttpRequest

View File

@ -27,7 +27,7 @@ import java.net.URI;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.openstack.nova.v1_1.NovaClient;
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaRestClientExpectTest;
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaClientExpectTest;
import org.jclouds.openstack.nova.v1_1.parse.ParseFlavorListTest;
import org.jclouds.openstack.nova.v1_1.parse.ParseFlavorTest;
import org.testng.annotations.Test;
@ -41,7 +41,7 @@ import com.google.common.collect.ImmutableSet;
* @author Jeremy Daggett
*/
@Test(groups = "unit", testName = "FlavorClientExpectTest")
public class FlavorClientExpectTest extends BaseNovaRestClientExpectTest {
public class FlavorClientExpectTest extends BaseNovaClientExpectTest {
public void testListFlavorsWhenResponseIs2xx() throws Exception {
HttpRequest listFlavors = HttpRequest

View File

@ -23,7 +23,7 @@ import com.google.common.collect.ImmutableSet;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.openstack.nova.v1_1.NovaClient;
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaRestClientExpectTest;
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaClientExpectTest;
import org.jclouds.openstack.nova.v1_1.parse.ParseImageTest;
import org.jclouds.openstack.nova.v1_1.parse.ParseImageListTest;
import org.testng.annotations.Test;
@ -40,7 +40,7 @@ import static org.testng.Assert.assertTrue;
* @author Michael Arnold
*/
@Test(groups = "unit", testName = "ImageAsyncClientTest")
public class ImageClientExpectTest extends BaseNovaRestClientExpectTest {
public class ImageClientExpectTest extends BaseNovaClientExpectTest {
public void testListImagesWhenResponseIs2xx() throws Exception {
HttpRequest listImages = HttpRequest
.builder()

View File

@ -26,7 +26,7 @@ import java.net.URI;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.openstack.nova.v1_1.NovaClient;
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaRestClientExpectTest;
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaClientExpectTest;
import org.jclouds.openstack.nova.v1_1.parse.ParseServerListTest;
import org.testng.annotations.Test;
@ -39,7 +39,7 @@ import com.google.common.collect.ImmutableSet;
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "ServerAsyncClientTest")
public class ServerClientExpectTest extends BaseNovaRestClientExpectTest {
public class ServerClientExpectTest extends BaseNovaClientExpectTest {
public void testListServersWhenResponseIs2xx() throws Exception {
HttpRequest listServers = HttpRequest.builder().method("GET").endpoint(

View File

@ -18,33 +18,32 @@
*/
package org.jclouds.openstack.nova.v1_1.internal;
import static org.testng.Assert.assertEquals;
import static org.jclouds.rest.RestContextFactory.createContext;
import java.util.Properties;
import org.jclouds.http.HttpRequest;
import org.jclouds.openstack.filters.AuthenticateRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.logging.config.NullLoggingModule;
import org.jclouds.openstack.nova.v1_1.NovaAsyncClient;
import org.jclouds.openstack.nova.v1_1.NovaClient;
import org.jclouds.rest.RestClientTest;
import org.jclouds.rest.RestContextFactory;
import org.jclouds.rest.RestContextSpec;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Module;
/**
* Base class for writing KeyStone Rest Client Expect tests
*
* @author Adrian Cole
*/
public abstract class BaseNovaAsyncClientTest<T> extends RestClientTest<T> {
@Override
protected void checkFilters(HttpRequest request) {
assertEquals(request.getFilters().size(), 1);
assertEquals(request.getFilters().get(0).getClass(), AuthenticateRequest.class);
public class BaseNovaAsyncClientExpectTest extends BaseNovaExpectTest<NovaAsyncClient> {
public NovaAsyncClient createClient(Function<HttpRequest, HttpResponse> fn, Module module, Properties props) {
RestContextSpec<NovaClient, NovaAsyncClient> contextSpec = new RestContextFactory(setupRestProperties())
.createContextSpec(provider, identity, credential, new Properties());
return createContext(contextSpec,
ImmutableSet.<Module> of(new ExpectModule(fn), new NullLoggingModule(), module), props).getAsyncApi();
}
@Override
public RestContextSpec<NovaClient, NovaAsyncClient> createContextSpec() {
Properties props = new Properties();
return new RestContextFactory().createContextSpec("openstack-nova", "accountId", "accessKey", props);
}
}

View File

@ -0,0 +1,30 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.openstack.nova.v1_1.internal;
import org.jclouds.openstack.nova.v1_1.NovaClient;
/**
* Base class for writing KeyStone Rest Client Expect tests
*
* @author Adrian Cole
*/
public class BaseNovaClientExpectTest extends BaseNovaExpectTest<NovaClient> {
}

View File

@ -25,43 +25,22 @@ import org.jclouds.compute.ComputeServiceContextFactory;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.logging.config.NullLoggingModule;
import org.jclouds.openstack.keystone.v2_0.internal.KeystoneFixture;
import org.jclouds.rest.BaseRestClientExpectTest;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Module;
/**
* Base class for writing KeyStone Expect tests with the ComputeService abstraction
* Base class for writing KeyStone Expect tests with the ComputeService
* abstraction
*
* @author Matt Stephenson
*/
public class BaseNovaComputeServiceExpectTest extends BaseRestClientExpectTest<ComputeService>
{
protected HttpRequest keystoneAuthWithUsernameAndPassword;
protected HttpRequest keystoneAuthWithAccessKeyAndSecretKey;
protected String authToken;
protected HttpResponse responseWithKeystoneAccess;
public BaseNovaComputeServiceExpectTest()
{
provider = "openstack-nova";
keystoneAuthWithUsernameAndPassword = KeystoneFixture.INSTANCE.initialAuthWithUsernameAndPassword(identity,
credential);
keystoneAuthWithAccessKeyAndSecretKey = KeystoneFixture.INSTANCE.initialAuthWithAccessKeyAndSecretKey(identity,
credential);
authToken = KeystoneFixture.INSTANCE.getAuthToken();
responseWithKeystoneAccess = KeystoneFixture.INSTANCE.responseWithAccess();
// now, createContext arg will need tenant prefix
identity = KeystoneFixture.INSTANCE.getTenantName() + ":" + identity;
}
public class BaseNovaComputeServiceExpectTest extends BaseNovaExpectTest<ComputeService> {
@Override
public ComputeService createClient(Function<HttpRequest, HttpResponse> fn, Module module, Properties props)
{
public ComputeService createClient(Function<HttpRequest, HttpResponse> fn, Module module, Properties props) {
return new ComputeServiceContextFactory(setupRestProperties()).createContext(provider, identity, credential,
ImmutableSet.<Module>of(new ExpectModule(fn), new NullLoggingModule(), module), props).getComputeService();
ImmutableSet.<Module> of(new ExpectModule(fn), new NullLoggingModule(), module), props).getComputeService();
}
}

View File

@ -21,21 +21,20 @@ package org.jclouds.openstack.nova.v1_1.internal;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.openstack.keystone.v2_0.internal.KeystoneFixture;
import org.jclouds.openstack.nova.v1_1.NovaClient;
import org.jclouds.rest.BaseRestClientExpectTest;
/**
* Base class for writing KeyStone Rest Client Expect tests
* Base class for writing Nova Expect tests
*
* @author Adrian Cole
*/
public class BaseNovaRestClientExpectTest extends BaseRestClientExpectTest<NovaClient> {
public class BaseNovaExpectTest<T> extends BaseRestClientExpectTest<T> {
protected HttpRequest keystoneAuthWithUsernameAndPassword;
protected HttpRequest keystoneAuthWithAccessKeyAndSecretKey;
protected String authToken;
protected HttpResponse responseWithKeystoneAccess;
public BaseNovaRestClientExpectTest() {
public BaseNovaExpectTest() {
provider = "openstack-nova";
keystoneAuthWithUsernameAndPassword = KeystoneFixture.INSTANCE.initialAuthWithUsernameAndPassword(identity,
credential);

View File

@ -74,7 +74,7 @@ public class AdminCatalogClientExpectTest extends BaseVCloudDirectorRestClientEx
assertEquals(client.getAdminCatalogClient().createCatalog(catalogRef.getHref(), source), expected);
}
@Test
@Test(enabled = false)//TODO
public void testGetCatalog() {
VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse,
new VcloudHttpRequestPrimer()
@ -90,7 +90,7 @@ public class AdminCatalogClientExpectTest extends BaseVCloudDirectorRestClientEx
assertEquals(client.getAdminCatalogClient().getCatalog(catalogRef.getHref()), expected);
}
@Test
@Test(enabled = false)//TODO
public void testModifyCatalog() {
VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse,
new VcloudHttpRequestPrimer()
@ -107,7 +107,7 @@ public class AdminCatalogClientExpectTest extends BaseVCloudDirectorRestClientEx
assertEquals(client.getAdminCatalogClient().updateCatalog(catalogRef.getHref(), expected), expected);
}
@Test
@Test(enabled = false)//TODO
public void testGetOwner() {
VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse,
new VcloudHttpRequestPrimer()

View File

@ -51,7 +51,7 @@ import com.google.common.collect.ImmutableSet;
@Test(groups = { "unit", "media" }, singleThreaded = true, testName = "MediaClientExpectTest")
public class MediaClientExpectTest extends BaseVCloudDirectorRestClientExpectTest {
@Test
@Test(enabled = false)//TODO
public void testCreateMedia() {
URI uploadLink = URI.create(endpoint + "/vdc/e9cd3387-ac57-4d27-a481-9bee75e0690f/media");
@ -77,7 +77,7 @@ public class MediaClientExpectTest extends BaseVCloudDirectorRestClientExpectTes
assertEquals(client.getMediaClient().createMedia(uploadLink, source), expected);
}
@Test
@Test(enabled = false)//TODO
public void testCloneMedia() {
URI cloneUri = URI.create(endpoint + "/vdc/e9cd3387-ac57-4d27-a481-9bee75e0690f/action/cloneMedia");
@ -107,7 +107,7 @@ public class MediaClientExpectTest extends BaseVCloudDirectorRestClientExpectTes
assertEquals(client.getMediaClient().cloneMedia(cloneUri, params), expected);
}
@Test
@Test(enabled = false)//TODO
public void testGetMedia() {
URI mediaUri = URI.create(endpoint + "/media/794eb334-754e-4917-b5a0-5df85cbd61d1");
@ -211,7 +211,7 @@ public class MediaClientExpectTest extends BaseVCloudDirectorRestClientExpectTes
}
}
@Test
@Test(enabled = false)//TODO
public void testUpdateMedia() {
URI mediaUri = URI.create(endpoint + "/media/794eb334-754e-4917-b5a0-5df85cbd61d1");
@ -345,7 +345,7 @@ public class MediaClientExpectTest extends BaseVCloudDirectorRestClientExpectTes
assertEquals(client.getMediaClient().getMetadataClient().deleteMetadataEntry(mediaUri, "key"), expectedTask);
}
@Test
@Test(enabled = false)//TODO
public void testGetOwner() {
URI mediaUri = URI.create(endpoint + "/media/794eb334-754e-4917-b5a0-5df85cbd61d1");

View File

@ -120,7 +120,7 @@ public class QueryClientExpectTest extends BaseVCloudDirectorRestClientExpectTes
assertEquals(client.getQueryClient().catalogsQueryAll(), expected);
}
@Test
@Test(enabled = false)//TODO
public void testQueryAllCatalogReferences() {
HttpRequest queryRequest = HttpRequest.builder()
.method("GET")

View File

@ -74,7 +74,7 @@ public class VAppClientExpectTest extends BaseVCloudDirectorRestClientExpectTest
public void before() {
}
@Test
@Test(enabled = false)//TODO
public void testGetVapp() {
VCloudDirectorClient client = orderedRequestsSendResponses(loginRequest, sessionResponse,
new VcloudHttpRequestPrimer()

View File

@ -80,6 +80,7 @@ public class VAppTemplateClientExpectTest extends BaseVCloudDirectorRestClientEx
TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles"));
}
@Test(enabled = false)//TODO
public void testVAppTemplate() {
final String templateId = "/vAppTemplate/vappTemplate-ef4415e6-d413-4cbb-9262-f9bbec5f2ea9";
URI uri = URI.create(endpoint + templateId);
@ -117,7 +118,8 @@ public class VAppTemplateClientExpectTest extends BaseVCloudDirectorRestClientEx
client.getVAppTemplate(uri);
}
@Test(expectedExceptions = VCloudDirectorException.class)
//TODO
@Test(enabled = false, expectedExceptions = VCloudDirectorException.class)
public void testErrorEditVAppTemplate() {
final String templateId = "/vAppTemplate/vappTemplate-ef4415e6-d413-4cbb-9262-f9bbec5f2ea9";
URI uri = URI.create(endpoint + templateId);
@ -252,6 +254,7 @@ public class VAppTemplateClientExpectTest extends BaseVCloudDirectorRestClientEx
client.relocateVappTemplate(uri, params);
}
@Test(enabled = false)//TODO
public void testCustomizationSection() {
final String templateId = "/vAppTemplate/vappTemplate-ef4415e6-d413-4cbb-9262-f9bbec5f2ea9";
URI uri = URI.create(endpoint + templateId);
@ -272,7 +275,8 @@ public class VAppTemplateClientExpectTest extends BaseVCloudDirectorRestClientEx
assertNotNull(task);
}
@Test(expectedExceptions = VCloudDirectorException.class)
//TODO
@Test(enabled = false, expectedExceptions = VCloudDirectorException.class)
public void testErrorGetCustomizationSection() {
final String templateId = "/vAppTemplate/vappTemplate-ef4415e6-d413-4cbb-9262-f9bbec5f2ea9";
URI uri = URI.create(endpoint + templateId);

View File

@ -293,7 +293,7 @@ public class VdcClientExpectTest extends BaseVCloudDirectorRestClientExpectTest
assertEquals(client.getVdcClient().uploadVAppTemplate(vdcURI, params), expected);
}
@Test
@Test(enabled = false)//TODO
public void testCreateMedia() {
URI vdcUri = URI.create(endpoint + "/vdc/e9cd3387-ac57-4d27-a481-9bee75e0690f");
@ -319,7 +319,7 @@ public class VdcClientExpectTest extends BaseVCloudDirectorRestClientExpectTest
assertEquals(client.getVdcClient().createMedia(vdcUri, source), expected);
}
@Test
@Test(enabled = false)//TODO
public void testCloneMedia() {
URI vdcUri = URI.create(endpoint + "/vdc/e9cd3387-ac57-4d27-a481-9bee75e0690f");

View File

@ -19,18 +19,16 @@
package org.jclouds.virtualbox;
import static org.jclouds.Constants.*;
import static org.jclouds.Constants.PROPERTY_API_VERSION;
import static org.jclouds.Constants.PROPERTY_BUILD_VERSION;
import static org.jclouds.Constants.PROPERTY_CREDENTIAL;
import static org.jclouds.Constants.PROPERTY_ENDPOINT;
import static org.jclouds.Constants.PROPERTY_IDENTITY;
import static org.jclouds.compute.reference.ComputeServiceConstants.PROPERTY_IMAGE_AUTHENTICATE_SUDO;
import static org.jclouds.compute.reference.ComputeServiceConstants.PROPERTY_IMAGE_LOGIN_USER;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_DEFAULT_DIR;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_IMAGES_DESCRIPTOR;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_INSTALLATION_KEY_SEQUENCE;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_PRECONFIGURATION_URL;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.*;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_WORKINGDIR;
import java.io.File;
import java.util.Properties;
@ -60,12 +58,10 @@ public class VirtualBoxPropertiesBuilder extends PropertiesBuilder {
properties.put(PROPERTY_API_VERSION, "4.1.4");
properties.put(PROPERTY_BUILD_VERSION, "4.1.8r75467");
properties.put(PROPERTY_IDENTITY, "administrator");
properties.put(PROPERTY_CREDENTIAL, "12345");
properties.put(PROPERTY_IMAGE_LOGIN_USER, "toor:password");
properties.put(PROPERTY_IMAGE_AUTHENTICATE_SUDO, "true");
properties.put(VIRTUALBOX_INSTALLATION_KEY_SEQUENCE, "<Esc><Esc><Enter> "
+ "/install/vmlinuz noapic preseed/url=PRECONFIGURATION_URL "
+ "debian-installer=en_US auto locale=en_US kbd-chooser/method=us " + "hostname=" + "HOSTNAME "
@ -82,7 +78,7 @@ public class VirtualBoxPropertiesBuilder extends PropertiesBuilder {
properties.put(VIRTUALBOX_IMAGES_DESCRIPTOR, yamlDescriptor);
properties.put(VIRTUALBOX_PRECONFIGURATION_URL, "http://10.0.2.2:8080/src/test/resources/preseed.cfg");
properties.put(VIRTUALBOX_PRECONFIGURATION_URL, "http://10.0.2.2:23232/preseed.cfg");
return properties;
}

View File

@ -96,7 +96,7 @@ public class VirtualBoxComputeServiceAdapter implements ComputeServiceAdapter<IM
NodeSpec nodeSpec = NodeSpec.builder().master(master).name(name).tag(tag).template(template).build();
return cloneCreator.apply(nodeSpec);
} catch (Exception e) {
throw new RuntimeException(e);
throw Throwables.propagate(e);
}
}

View File

@ -70,7 +70,7 @@ import org.jclouds.virtualbox.functions.IMachineToHardware;
import org.jclouds.virtualbox.functions.IMachineToImage;
import org.jclouds.virtualbox.functions.IMachineToNodeMetadata;
import org.jclouds.virtualbox.functions.IMachineToSshClient;
import org.jclouds.virtualbox.functions.MastersCache;
import org.jclouds.virtualbox.functions.MastersLoadingCache;
import org.jclouds.virtualbox.functions.NodeCreator;
import org.jclouds.virtualbox.functions.YamlImagesFromFileConfig;
import org.jclouds.virtualbox.functions.admin.FileDownloadFromURI;
@ -141,7 +141,7 @@ public class VirtualBoxComputeServiceContextModule extends
}).to((Class) YamlImagesFromFileConfig.class);
// the master machines cache
bind(new TypeLiteral<LoadingCache<Image, Master>>() {
}).to((Class) MastersCache.class);
}).to((Class) MastersLoadingCache.class);
// the master creating function
bind(new TypeLiteral<Function<MasterSpec, IMachine>>() {
}).to((Class) CreateAndInstallVm.class);

View File

@ -24,7 +24,6 @@ import java.util.List;
import javax.annotation.Resource;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger;
@ -100,6 +99,7 @@ public class CloneAndRegisterMachineFromIMachineIfNotAlreadyExists implements Fu
.getVBox()
.createMachine(settingsFile, vmSpec.getVmName(), vmSpec.getOsTypeId(), vmSpec.getVmId(),
vmSpec.isForceOverwrite());
List<CloneOptions> options = new ArrayList<CloneOptions>();
if (isLinkedClone)
options.add(CloneOptions.Link);

View File

@ -44,12 +44,10 @@ import org.jclouds.virtualbox.util.MachineController;
import org.jclouds.virtualbox.util.MachineUtils;
import org.virtualbox_4_1.IMachine;
import org.virtualbox_4_1.LockType;
import org.virtualbox_4_1.VirtualBoxManager;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Splitter;
import com.google.common.base.Supplier;
import com.google.common.cache.LoadingCache;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
@ -62,7 +60,6 @@ public class CreateAndInstallVm implements Function<MasterSpec, IMachine> {
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
private final Supplier<VirtualBoxManager> manager;
private final CreateAndRegisterMachineFromIsoIfNotAlreadyExists createAndRegisterMachineFromIsoIfNotAlreadyExists;
private final GuestAdditionsInstaller guestAdditionsInstaller;
private final Predicate<SshClient> sshResponds;
@ -75,7 +72,6 @@ public class CreateAndInstallVm implements Function<MasterSpec, IMachine> {
@Inject
public CreateAndInstallVm(
Supplier<VirtualBoxManager> manager,
CreateAndRegisterMachineFromIsoIfNotAlreadyExists CreateAndRegisterMachineFromIsoIfNotAlreadyExists,
GuestAdditionsInstaller guestAdditionsInstaller,
IMachineToNodeMetadata imachineToNodeMetadata,
@ -83,7 +79,6 @@ public class CreateAndInstallVm implements Function<MasterSpec, IMachine> {
Function<IMachine, SshClient> sshClientForIMachine,
MachineUtils machineUtils,
@Preconfiguration LoadingCache<IsoSpec, URI> preConfiguration, MachineController machineController) {
this.manager = manager;
this.createAndRegisterMachineFromIsoIfNotAlreadyExists = CreateAndRegisterMachineFromIsoIfNotAlreadyExists;
this.sshResponds = sshResponds;
this.sshClientForIMachine = sshClientForIMachine;
@ -113,6 +108,7 @@ public class CreateAndInstallVm implements Function<MasterSpec, IMachine> {
configureOsInstallationWithKeyboardSequence(vmName,
installationKeySequence);
SshClient client = sshClientForIMachine.apply(vm);
logger.debug(">> awaiting installation to finish node(%s)", vmName);
@ -121,8 +117,8 @@ public class CreateAndInstallVm implements Function<MasterSpec, IMachine> {
"timed out waiting for guest %s to be accessible via ssh",
vmName);
//logger.debug(">> awaiting installation of guest additions on vm: %s", vmName);
//checkState(guestAdditionsInstaller.apply(vm));
logger.debug(">> awaiting installation of guest additions on vm: %s", vmName);
checkState(guestAdditionsInstaller.apply(vm));
logger.debug(">> awaiting post-installation actions on vm: %s", vmName);

View File

@ -23,17 +23,12 @@ import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static org.jclouds.virtualbox.config.VirtualBoxComputeServiceContextModule.machineToNodeState;
import java.util.HashSet;
import java.util.Set;
import javax.annotation.Resource;
import javax.inject.Named;
import org.jclouds.compute.domain.HardwareBuilder;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.Processor;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.LocationBuilder;
import org.jclouds.domain.LocationScope;

View File

@ -64,17 +64,20 @@ import com.google.common.base.Function;
import com.google.common.base.Splitter;
import com.google.common.base.Supplier;
import com.google.common.cache.AbstractLoadingCache;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
/**
* Does most of the work wrt to creating the master image.
* A {@link LoadingCache} for masters. If the requested master has been previously created this
* returns it, if not it coordinates its creation including downloading isos and creating
* cache/config directories.
*
* @author dralves
*
*/
@Singleton
public class MastersCache extends AbstractLoadingCache<Image, Master> {
public class MastersLoadingCache extends AbstractLoadingCache<Image, Master> {
// TODO parameterize
public static final int MASTER_PORT = 2222;
@ -94,7 +97,7 @@ public class MastersCache extends AbstractLoadingCache<Image, Master> {
private String version;
@Inject
public MastersCache(@Named(Constants.PROPERTY_BUILD_VERSION) String version,
public MastersLoadingCache(@Named(Constants.PROPERTY_BUILD_VERSION) String version,
@Named(VIRTUALBOX_INSTALLATION_KEY_SEQUENCE) String installationKeySequence,
@Named(VIRTUALBOX_WORKINGDIR) String workingDir, Function<MasterSpec, IMachine> masterLoader,
Supplier<Map<Image, YamlImage>> yamlMapper, Supplier<VirtualBoxManager> manager,

View File

@ -43,10 +43,12 @@ import org.jclouds.virtualbox.domain.NetworkInterfaceCard;
import org.jclouds.virtualbox.domain.NetworkSpec;
import org.jclouds.virtualbox.domain.NodeSpec;
import org.jclouds.virtualbox.domain.VmSpec;
import org.jclouds.virtualbox.statements.DeleteGShadowLock;
import org.jclouds.virtualbox.statements.SetIpAddress;
import org.jclouds.virtualbox.util.MachineUtils;
import org.virtualbox_4_1.CleanupMode;
import org.virtualbox_4_1.IMachine;
import org.virtualbox_4_1.IProgress;
import org.virtualbox_4_1.ISession;
import org.virtualbox_4_1.NetworkAttachmentType;
import org.virtualbox_4_1.VirtualBoxManager;
@ -54,149 +56,140 @@ import org.virtualbox_4_1.VirtualBoxManager;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
/**
* Creates nodes, by cloning a master vm and based on the provided {@link NodeSpec}. Must be
* synchronized mainly because of snapshot creation (must be synchronized on a per-master-basis).
*
* @author dralves
*
*/
@Singleton
public class NodeCreator implements
Function<NodeSpec, NodeAndInitialCredentials<IMachine>> {
public class NodeCreator implements Function<NodeSpec, NodeAndInitialCredentials<IMachine>> {
// TODO parameterize
public static final int NODE_PORT_INIT = 3000;
// TODO parameterize
public static final int NODE_PORT_INIT = 3000;
// TODO parameterize
public static final String VMS_NETWORK = "33.33.33.";
// TODO parameterize
public static final String VMS_NETWORK = "33.33.33.";
// TODO parameterize
public static final String HOST_ONLY_IFACE_NAME = "vboxnet0";
// TODO parameterize
public static final String HOST_ONLY_IFACE_NAME = "vboxnet0";
// TODO parameterize
public static final boolean USE_LINKED = true;
// TODO parameterize
public static final boolean USE_LINKED = true;
private final Supplier<VirtualBoxManager> manager;
private final Function<CloneSpec, IMachine> cloner;
private final AtomicInteger nodePorts;
private final AtomicInteger nodeIps;
private MachineUtils machineUtils;
private Function<IMachine, NodeMetadata> imachineToNodeMetadata;
// TODO parameterize
public static final ExecutionType EXECUTION_TYPE = ExecutionType.HEADLESS;
private final RunScriptOnNode.Factory scriptRunnerFactory;
private final Supplier<NodeMetadata> hostSupplier;
private final Supplier<VirtualBoxManager> manager;
private final Function<CloneSpec, IMachine> cloner;
private final AtomicInteger nodePorts;
private final AtomicInteger nodeIps;
private MachineUtils machineUtils;
private Function<IMachine, NodeMetadata> imachineToNodeMetadata;
@Inject
public NodeCreator(Supplier<VirtualBoxManager> manager,
Function<CloneSpec, IMachine> cloner, MachineUtils machineUtils,
Function<IMachine, NodeMetadata> imachineToNodeMetadata,
RunScriptOnNode.Factory scriptRunnerFactory,
Supplier<NodeMetadata> hostSupplier) {
this.manager = manager;
this.cloner = cloner;
this.nodePorts = new AtomicInteger(NODE_PORT_INIT);
this.nodeIps = new AtomicInteger(1);
this.machineUtils = machineUtils;
this.imachineToNodeMetadata = imachineToNodeMetadata;
this.scriptRunnerFactory = scriptRunnerFactory;
this.hostSupplier = hostSupplier;
private final RunScriptOnNode.Factory scriptRunnerFactory;
private final Supplier<NodeMetadata> hostSupplier;
}
@Inject
public NodeCreator(Supplier<VirtualBoxManager> manager, Function<CloneSpec, IMachine> cloner,
MachineUtils machineUtils, Function<IMachine, NodeMetadata> imachineToNodeMetadata,
RunScriptOnNode.Factory scriptRunnerFactory, Supplier<NodeMetadata> hostSupplier) {
this.manager = manager;
this.cloner = cloner;
this.nodePorts = new AtomicInteger(NODE_PORT_INIT + 1);
this.nodeIps = new AtomicInteger(1);
this.machineUtils = machineUtils;
this.imachineToNodeMetadata = imachineToNodeMetadata;
this.scriptRunnerFactory = scriptRunnerFactory;
this.hostSupplier = hostSupplier;
@Override
public NodeAndInitialCredentials<IMachine> apply(NodeSpec nodeSpec) {
}
checkNotNull(nodeSpec, "NodeSpec");
@Override
public synchronized NodeAndInitialCredentials<IMachine> apply(NodeSpec nodeSpec) {
Master master = nodeSpec.getMaster();
checkNotNull(master, "Master");
checkNotNull(nodeSpec, "NodeSpec");
if (master.getMachine().getCurrentSnapshot() != null) {
ISession session;
try {
session = manager.get().openMachineSession(master.getMachine());
} catch (Exception e) {
throw new RuntimeException(
"error opening vbox machine session: " + e.getMessage(),
e);
}
session.getConsole().deleteSnapshot(
master.getMachine().getCurrentSnapshot().getId());
session.unlockMachine();
}
String masterNameWithoutPrefix = master.getSpec().getVmSpec()
.getVmName().replace(VIRTUALBOX_IMAGE_PREFIX, "");
Master master = nodeSpec.getMaster();
checkNotNull(master, "Master");
String cloneName = VIRTUALBOX_NODE_PREFIX + masterNameWithoutPrefix
+ "-" + nodeSpec.getTag() + "-" + nodeSpec.getName();
if (master.getMachine().getCurrentSnapshot() != null) {
ISession session;
try {
session = manager.get().openMachineSession(master.getMachine());
} catch (Exception e) {
throw new RuntimeException("error opening vbox machine session: " + e.getMessage(), e);
}
IProgress progress = session.getConsole().deleteSnapshot(master.getMachine().getCurrentSnapshot().getId());
progress.waitForCompletion(-1);
session.unlockMachine();
}
String masterNameWithoutPrefix = master.getSpec().getVmSpec().getVmName().replace(VIRTUALBOX_IMAGE_PREFIX, "");
VmSpec cloneVmSpec = VmSpec.builder().id(cloneName).name(cloneName)
.memoryMB(512).cleanUpMode(CleanupMode.Full)
.forceOverwrite(true).build();
String cloneName = VIRTUALBOX_NODE_PREFIX + masterNameWithoutPrefix + "-" + nodeSpec.getTag() + "-"
+ nodeSpec.getName();
VmSpec cloneVmSpec = VmSpec.builder().id(cloneName).name(cloneName).memoryMB(512).cleanUpMode(CleanupMode.Full)
.forceOverwrite(true).build();
// CASE NAT + HOST-ONLY
NetworkAdapter natAdapter = NetworkAdapter
.builder()
.networkAttachmentType(NetworkAttachmentType.NAT)
.tcpRedirectRule("127.0.0.1", this.nodePorts.getAndIncrement(),
"", 22).build();
NetworkInterfaceCard natIfaceCard = NetworkInterfaceCard.builder()
.addNetworkAdapter(natAdapter).slot(0L).build();
// CASE NAT + HOST-ONLY
NetworkAdapter natAdapter = NetworkAdapter.builder().networkAttachmentType(NetworkAttachmentType.NAT)
.tcpRedirectRule("127.0.0.1", this.nodePorts.getAndIncrement(), "", 22).build();
NetworkInterfaceCard natIfaceCard = NetworkInterfaceCard.builder().addNetworkAdapter(natAdapter).slot(0L).build();
NetworkAdapter hostOnlyAdapter = NetworkAdapter.builder()
.networkAttachmentType(NetworkAttachmentType.HostOnly)
.staticIp(VMS_NETWORK + this.nodeIps.getAndIncrement()).build();
NetworkAdapter hostOnlyAdapter = NetworkAdapter.builder().networkAttachmentType(NetworkAttachmentType.HostOnly)
.staticIp(VMS_NETWORK + this.nodeIps.getAndIncrement()).build();
NetworkInterfaceCard hostOnlyIfaceCard = NetworkInterfaceCard.builder()
.addNetworkAdapter(hostOnlyAdapter)
.addHostInterfaceName(HOST_ONLY_IFACE_NAME).slot(1L).build();
NetworkInterfaceCard hostOnlyIfaceCard = NetworkInterfaceCard.builder().addNetworkAdapter(hostOnlyAdapter)
.addHostInterfaceName(HOST_ONLY_IFACE_NAME).slot(1L).build();
NetworkSpec networkSpec = createNetworkSpecForHostOnlyNATNICs(natIfaceCard, hostOnlyIfaceCard);
////
NetworkSpec networkSpec = createNetworkSpecForHostOnlyNATNICs(natIfaceCard, hostOnlyIfaceCard);
// //
// CASE BRIDGED
//NetworkSpec networkSpec = createNetworkSpecForBridgedNIC();
// CASE BRIDGED
// NetworkSpec networkSpec = createNetworkSpecForBridgedNIC();
CloneSpec cloneSpec = CloneSpec.builder().linked(USE_LINKED)
.master(master.getMachine()).network(networkSpec)
.vm(cloneVmSpec).build();
CloneSpec cloneSpec = CloneSpec.builder().linked(USE_LINKED).master(master.getMachine()).network(networkSpec)
.vm(cloneVmSpec).build();
IMachine cloned = cloner.apply(cloneSpec);
IMachine cloned = cloner.apply(cloneSpec);
new LaunchMachineIfNotAlreadyRunning(manager.get(), ExecutionType.GUI,
"").apply(cloned);
new LaunchMachineIfNotAlreadyRunning(manager.get(), EXECUTION_TYPE, "").apply(cloned);
// see DeleteGShadowLock for a detailed explanation
machineUtils
.runScriptOnNode(imachineToNodeMetadata.apply(cloned), new DeleteGShadowLock(), RunScriptOptions.NONE);
// CASE NAT + HOST-ONLY
machineUtils.runScriptOnNode(imachineToNodeMetadata.apply(cloned),
new SetIpAddress(hostOnlyIfaceCard), RunScriptOptions.NONE);
////
// CASE NAT + HOST-ONLY
machineUtils.runScriptOnNode(imachineToNodeMetadata.apply(cloned), new SetIpAddress(hostOnlyIfaceCard),
RunScriptOptions.NONE);
// //
// TODO get credentials from somewhere else (they are also HC in
// IMachineToSshClient)
NodeAndInitialCredentials<IMachine> nodeAndInitialCredentials = new NodeAndInitialCredentials<IMachine>(cloned,
cloneName, LoginCredentials.builder().user("toor").password("password").authenticateSudo(true).build());
// TODO get credentials from somewhere else (they are also HC in
// IMachineToSshClient)
NodeAndInitialCredentials<IMachine> nodeAndInitialCredentials = new NodeAndInitialCredentials<IMachine>(
cloned, cloneName, LoginCredentials.builder().user("toor")
.password("password").authenticateSudo(true).build());
return nodeAndInitialCredentials;
}
return nodeAndInitialCredentials;
}
private NetworkSpec createNetworkSpecForHostOnlyNATNICs(NetworkInterfaceCard natIfaceCard,
NetworkInterfaceCard hostOnlyIfaceCard) {
return NetworkSpec.builder().addNIC(natIfaceCard).addNIC(hostOnlyIfaceCard).build();
}
private NetworkSpec createNetworkSpecForHostOnlyNATNICs(NetworkInterfaceCard natIfaceCard, NetworkInterfaceCard hostOnlyIfaceCard) {
return NetworkSpec.builder().addNIC(natIfaceCard)
.addNIC(hostOnlyIfaceCard).build();
}
private NetworkSpec createNetworkSpecForBridgedNIC() {
List<BridgedIf> activeBridgedInterfaces = new RetrieveActiveBridgedInterfaces(scriptRunnerFactory)
.apply(hostSupplier.get());
BridgedIf bridgedActiveInterface = checkNotNull(activeBridgedInterfaces.get(0), "activeBridgedIf");
private NetworkSpec createNetworkSpecForBridgedNIC() {
List<BridgedIf> activeBridgedInterfaces = new RetrieveActiveBridgedInterfaces(
scriptRunnerFactory).apply(hostSupplier.get());
BridgedIf bridgedActiveInterface = checkNotNull(
activeBridgedInterfaces.get(0), "activeBridgedIf");
NetworkAdapter bridgedAdapter = NetworkAdapter.builder().networkAttachmentType(NetworkAttachmentType.Bridged)
.build();
NetworkInterfaceCard bridgedNIC = NetworkInterfaceCard.builder().addNetworkAdapter(bridgedAdapter)
.addHostInterfaceName(bridgedActiveInterface.getName()).slot(0L).build();
NetworkAdapter bridgedAdapter = NetworkAdapter.builder()
.networkAttachmentType(NetworkAttachmentType.Bridged).build();
NetworkInterfaceCard bridgedNIC = NetworkInterfaceCard.builder()
.addNetworkAdapter(bridgedAdapter)
.addHostInterfaceName(bridgedActiveInterface.getName())
.slot(0L).build();
NetworkSpec networkSpec = NetworkSpec.builder().addNIC(bridgedNIC)
.build();
return networkSpec;
}
NetworkSpec networkSpec = NetworkSpec.builder().addNIC(bridgedNIC).build();
return networkSpec;
}
}

View File

@ -40,7 +40,6 @@ import com.google.common.base.Throwables;
*/
public class TakeSnapshotIfNotAlreadyAttached implements Function<IMachine, ISnapshot> {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
@ -49,7 +48,6 @@ public class TakeSnapshotIfNotAlreadyAttached implements Function<IMachine, ISna
private String snapshotName;
private String snapshotDesc;
public TakeSnapshotIfNotAlreadyAttached(Supplier<VirtualBoxManager> manager, String snapshotName, String snapshotDesc) {
this.manager = manager;
this.snapshotName = snapshotName;
@ -60,18 +58,34 @@ public class TakeSnapshotIfNotAlreadyAttached implements Function<IMachine, ISna
public ISnapshot apply(@Nullable IMachine machine) {
// Snapshot a machine
ISession session = null;
if(machine.getCurrentSnapshot() == null ) {
try {
session = manager.get().openMachineSession(machine);
IProgress progress = session.getConsole().takeSnapshot(snapshotName, snapshotDesc);
if (progress.getCompleted())
logger.debug("Snapshot %s (description: %s) taken from %s", snapshotName, snapshotDesc, machine.getName());
} catch (Exception e) {
logger.error(e, "Problem creating snapshot %s (descripton: %s) from machine %s", snapshotName, snapshotDesc, machine.getName());
Throwables.propagate(e);
assert false;
} finally {
session.unlockMachine();
if (machine.getCurrentSnapshot() == null) {
int retries = 10;
while (true) {
try {
session = manager.get().openMachineSession(machine);
IProgress progress = session.getConsole().takeSnapshot(snapshotName, snapshotDesc);
progress.waitForCompletion(-1);
logger.debug("Snapshot %s (description: %s) taken from %s", snapshotName, snapshotDesc,
machine.getName());
break;
} catch (Exception e) {
if (e.getMessage().contains("VirtualBox error: The object is not ready")) {
retries--;
if (retries == 0) {
logger.error(e,
"Problem creating snapshot (too many retries) %s (descripton: %s) from machine %s",
snapshotName, snapshotDesc, machine.getName());
throw Throwables.propagate(e);
}
}
logger.error(e, "Problem creating snapshot %s (descripton: %s) from machine %s", snapshotName,
snapshotDesc, machine.getName());
throw Throwables.propagate(e);
} finally {
if (session != null) {
session.unlockMachine();
}
}
}
}
return machine.getCurrentSnapshot();

View File

@ -19,35 +19,49 @@
package org.jclouds.virtualbox.functions.admin;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.base.Throwables.propagate;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_PRECONFIGURATION_URL;
import java.io.IOException;
import java.net.URI;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.IOUtils;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.DefaultHandler;
import org.eclipse.jetty.server.handler.HandlerList;
import org.eclipse.jetty.server.handler.ResourceHandler;
import org.eclipse.jetty.util.resource.Resource;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger;
import org.jclouds.virtualbox.domain.IsoSpec;
import com.google.common.base.Throwables;
import com.google.common.cache.CacheLoader;
import com.google.inject.Singleton;
/**
* @author Andrea Turli
* Sets up jetty so that it can serve the preseed.cfg file to automate master creation.
*
* TODO - Probably we can make this only start jetty. This has not been used to serve isos.
*
* @author Andrea Turli, David Alves
*/
@Singleton
public class StartJettyIfNotAlreadyRunning extends CacheLoader<IsoSpec, URI> {
@Resource
@javax.annotation.Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
private Server jetty;
@ -60,7 +74,7 @@ public class StartJettyIfNotAlreadyRunning extends CacheLoader<IsoSpec, URI> {
}
@Override
public URI load(IsoSpec isoSpec) throws Exception {
public URI load(IsoSpec isoSpec) throws Exception {
try {
start();
} catch (Exception e) {
@ -74,24 +88,36 @@ public class StartJettyIfNotAlreadyRunning extends CacheLoader<IsoSpec, URI> {
if (jetty.getState().equals(Server.STARTED)) {
logger.debug("not starting jetty, as existing host is serving %s", preconfigurationUrl);
} else {
logger.debug(">> starting jetty to serve %s", preconfigurationUrl);
ResourceHandler resourceHandler = new ResourceHandler();
resourceHandler.setDirectoriesListed(true);
resourceHandler.setWelcomeFiles(new String[]{"index.html"});
resourceHandler.setResourceBase("");
HandlerList handlers = new HandlerList();
handlers.setHandlers(new Handler[]{resourceHandler, new DefaultHandler()});
jetty.setHandler(handlers);
try {
// find the the parent dir inside the jar to serve the file from
final String preseedFile = IOUtils
.toString(Resource.newSystemResource("preseed.cfg").getURL().openStream());
checkState(preseedFile != null);
// since we're only serving the preseed.cfg file respond to all requests with it
jetty.setHandler(new AbstractHandler() {
@Override
public void handle(String target, Request baseRequest, HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
response.setContentType("text/plain;charset=utf-8");
response.setStatus(HttpServletResponse.SC_OK);
baseRequest.setHandled(true);
response.getWriter().println(preseedFile);
}
});
jetty.start();
} catch (Exception e) {
logger.error(e, "Server jetty could not be started for %s", preconfigurationUrl);
throw Throwables.propagate(e);
}
logger.debug("<< serving %s", resourceHandler.getBaseResource());
}
}
@PreDestroy()

View File

@ -25,6 +25,7 @@ import static org.jclouds.compute.options.RunScriptOptions.Builder.runAsRoot;
import java.net.URI;
import javax.annotation.Nullable;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.inject.Inject;
@ -58,8 +59,8 @@ public class StartVBoxIfNotAlreadyRunning implements Supplier<VirtualBoxManager>
private final RetryIfSocketNotYetOpen socketTester;
private final Supplier<NodeMetadata> host;
private final Supplier<URI> providerSupplier;
private final String identity;
private final String credential;
// private final String identity;
// private final String credential;
private final Function<Supplier<NodeMetadata>, VirtualBoxManager> managerForNode;
private transient VirtualBoxManager manager;
@ -67,14 +68,15 @@ public class StartVBoxIfNotAlreadyRunning implements Supplier<VirtualBoxManager>
@Inject
public StartVBoxIfNotAlreadyRunning(Function<Supplier<NodeMetadata>, VirtualBoxManager> managerForNode,
Factory runScriptOnNodeFactory, RetryIfSocketNotYetOpen socketTester, Supplier<NodeMetadata> host,
@Provider Supplier<URI> providerSupplier, @Identity String identity, @Credential String credential) {
@Provider Supplier<URI> providerSupplier, @Nullable @Identity String identity,
@Nullable @Credential String credential) {
this.runScriptOnNodeFactory = checkNotNull(runScriptOnNodeFactory, "runScriptOnNodeFactory");
this.socketTester = checkNotNull(socketTester, "socketTester");
this.socketTester.seconds(3L);
this.host = checkNotNull(host, "host");
this.providerSupplier = checkNotNull(providerSupplier, "endpoint to virtualbox websrvd is needed");
this.identity = checkNotNull(identity, "identity");
this.credential = checkNotNull(credential, "credential");
// this.identity = checkNotNull(identity, "identity");
// this.credential = checkNotNull(credential, "credential");
this.managerForNode = checkNotNull(managerForNode, "managerForNode");
}
@ -99,7 +101,7 @@ public class StartVBoxIfNotAlreadyRunning implements Supplier<VirtualBoxManager>
}
}
manager = managerForNode.apply(host);
manager.connect(provider.toASCIIString(), identity, credential);
manager.connect(provider.toASCIIString(), "", "");
if (logger.isDebugEnabled())
if (manager.getSessionObject().getState() != SessionState.Unlocked)
logger.warn("manager is not in unlocked state " + manager.getSessionObject().getState());

View File

@ -0,0 +1,48 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.virtualbox.statements;
import static com.google.common.base.Preconditions.checkNotNull;
import org.jclouds.scriptbuilder.domain.OsFamily;
import org.jclouds.scriptbuilder.domain.Statement;
import com.google.common.collect.ImmutableList;
/**
* Deletes /etc/gshadow.lock. see https://bugs.launchpad.net/ubuntu/+source/qemu/+bug/732864.
*
* @author dralves
*
*/
public class DeleteGShadowLock implements Statement {
@Override
public Iterable<String> functionDependencies(OsFamily family) {
return ImmutableList.of();
}
@Override
public String render(OsFamily family) {
if (checkNotNull(family, "family") == OsFamily.WINDOWS)
throw new UnsupportedOperationException("windows not yet implemented");
return "rm -f /etc/passwd.lock /etc/group.lock /etc/gshadow.lock";
}
}

View File

@ -0,0 +1,62 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.virtualbox;
import static junit.framework.Assert.assertEquals;
import java.net.URI;
import java.net.URL;
import java.util.Properties;
import org.apache.commons.io.IOUtils;
import org.eclipse.jetty.server.Server;
import org.jclouds.virtualbox.config.VirtualBoxConstants;
import org.jclouds.virtualbox.functions.admin.StartJettyIfNotAlreadyRunning;
import org.testng.annotations.Test;
/**
* Tests that jetty is able to serve the preseed.cfg file. This test is here to have access to the
* defaultProperties() method in {@link VirtualBoxPropertiesBuilder}.
*
* @author dralves
*
*/
@Test(groups = "live", singleThreaded = true, testName = "StartJettyIfNotAlreadyRunningLiveTest")
public class StartJettyIfNotAlreadyRunningLiveTest {
@Test
public void testJettyServerServesPreseedFile() throws Exception {
Properties props = new VirtualBoxPropertiesBuilder().defaultProperties();
String preconfigurationUrl = props.getProperty(VirtualBoxConstants.VIRTUALBOX_PRECONFIGURATION_URL);
int port = URI.create(preconfigurationUrl).getPort();
Server server = new Server(port);
StartJettyIfNotAlreadyRunning starter = new StartJettyIfNotAlreadyRunning(preconfigurationUrl, server);
starter.load(null);
String preseedFileFromJetty = IOUtils.toString(new URL("http://127.0.0.1:" + port + "/preseed.cfg").openStream());
String preseedFileFromFile = IOUtils
.toString(this.getClass().getClassLoader().getResourceAsStream("preseed.cfg")) + "\n";
assertEquals(preseedFileFromFile, preseedFileFromJetty);
}
}

View File

@ -31,9 +31,11 @@ import org.jclouds.compute.ComputeServiceContextFactory;
import org.jclouds.compute.RunNodesException;
import org.jclouds.compute.domain.ExecResponse;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger;
import org.jclouds.logging.slf4j.config.SLF4JLoggingModule;
import org.jclouds.scriptbuilder.statements.login.AdminAccess;
import org.jclouds.ssh.SshClient;
import org.jclouds.sshj.config.SshjSshClientModule;
import org.testng.annotations.BeforeClass;
@ -58,7 +60,7 @@ public class VirtualBoxExperimentLiveTest {
@BeforeClass
public void setUp() {
context = new ComputeServiceContextFactory().createContext("virtualbox", "toor", "password",
context = new ComputeServiceContextFactory().createContext("virtualbox", "", "",
ImmutableSet.<Module> of(new SLF4JLoggingModule(), new SshjSshClientModule()));
}
@ -66,7 +68,8 @@ public class VirtualBoxExperimentLiveTest {
public void testLaunchCluster() throws RunNodesException {
int numNodes = 4;
final String clusterName = "test-launch-cluster";
Set<? extends NodeMetadata> nodes = context.getComputeService().createNodesInGroup(clusterName, numNodes);
Set<? extends NodeMetadata> nodes = context.getComputeService().createNodesInGroup(clusterName, numNodes,
TemplateOptions.Builder.runScript(AdminAccess.standard()));
assertEquals(numNodes, nodes.size(), "wrong number of nodes");
for (NodeMetadata node : nodes) {
logger.debug("Created Node: %s", node);