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.concurrent.Timeout;
import org.jclouds.internal.ClassMethodArgs; import org.jclouds.internal.ClassMethodArgs;
import org.jclouds.rest.annotations.Delegate; import org.jclouds.rest.annotations.Delegate;
import org.jclouds.util.Optionals2;
import org.jclouds.util.Throwables2; 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.cache.LoadingCache;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
@ -51,14 +54,15 @@ import com.google.inject.ProvisionException;
public class SyncProxy implements InvocationHandler { public class SyncProxy implements InvocationHandler {
@SuppressWarnings("unchecked") @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, @Named("sync") LoadingCache<ClassMethodArgs, Object> delegateMap,
Map<Class<?>, Class<?>> sync2Async, Map<String, Long> timeouts) throws IllegalArgumentException, SecurityException, Map<Class<?>, Class<?>> sync2Async, Map<String, Long> timeouts) throws IllegalArgumentException, SecurityException,
NoSuchMethodException { NoSuchMethodException {
return (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class<?>[] { clazz }, 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 Object delegate;
private final Class<?> declaring; private final Class<?> declaring;
private final Map<Method, Method> methodMap; 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()); private static final Set<Method> objectMethods = ImmutableSet.copyOf(Object.class.getMethods());
@Inject @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<?>, @Named("sync") LoadingCache<ClassMethodArgs, Object> delegateMap, Map<Class<?>,
Class<?>> sync2Async, final Map<String, Long> timeouts) Class<?>> sync2Async, final Map<String, Long> timeouts)
throws SecurityException, NoSuchMethodException { throws SecurityException, NoSuchMethodException {
this.optionalConverter = optionalConverter;
this.delegateMap = delegateMap; this.delegateMap = delegateMap;
this.delegate = async; this.delegate = async;
this.declaring = declaring; this.declaring = declaring;
@ -125,10 +130,19 @@ public class SyncProxy implements InvocationHandler {
} else if (method.getName().equals("toString")) { } else if (method.getName().equals("toString")) {
return this.toString(); return this.toString();
} else if (method.isAnnotationPresent(Delegate.class)) { } else if (method.isAnnotationPresent(Delegate.class)) {
Class<?> asyncClass = sync2Async.get(method.getReturnType()); Class<?> syncClass = Optionals2.returnTypeOrTypeOfOptional(method);
checkState(asyncClass != null, "please configure corresponding async class for " + method.getReturnType() // 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"); + " 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)); Object returnVal = delegateMap.get(new ClassMethodArgs(asyncClass, method, args));
if (Optionals2.isReturnTypeOptional(method)){
return optionalConverter.apply(returnVal);
}
return returnVal; return returnVal;
} else if (syncMethodMap.containsKey(method)) { } else if (syncMethodMap.containsKey(method)) {
return syncMethodMap.get(method).invoke(delegate, args); return syncMethodMap.get(method).invoke(delegate, args);

View File

@ -71,19 +71,19 @@ public class BinderUtils {
* interface for the sync client (ex. LoginClient) * interface for the sync client (ex. LoginClient)
* @param asyncClientType * @param asyncClientType
* interface for the async client (ex. LoginAsyncClient) * interface for the async client (ex. LoginAsyncClient)
* @param delegates * @param sync2Async
* presuming your clients are annotated with @Delegate, contains the sync to async * presuming your clients are annotated with @Delegate, contains the sync to async
* classes relating to these methods * classes relating to these methods
*/ */
public static <S, A> void bindClientAndAsyncClient(Binder binder, Class<S> syncClientType, Class<A> asyncClientType, public static <S, A> void bindClientAndAsyncClient(Binder binder, Class<S> syncClientType, Class<A> asyncClientType,
Map<Class<?>, Class<?>> delegates) { Map<Class<?>, Class<?>> sync2Async) {
bindClient(binder, syncClientType, asyncClientType, delegates); bindClient(binder, syncClientType, asyncClientType, sync2Async);
bindAsyncClient(binder, asyncClientType); bindAsyncClient(binder, asyncClientType);
} }
public static <K, V> void bindClient(Binder binder, Class<K> syncClientType, Class<V> asyncClientType, public static <K, V> void bindClient(Binder binder, Class<K> syncClientType, Class<V> asyncClientType,
Map<Class<?>, Class<?>> delegates) { Map<Class<?>, Class<?>> sync2Async) {
Provider<K> asyncProvider = new ClientProvider<K, V>(syncClientType, asyncClientType, delegates); Provider<K> asyncProvider = new ClientProvider<K, V>(syncClientType, asyncClientType, sync2Async);
binder.requestInjection(asyncProvider); binder.requestInjection(asyncProvider);
binder.bind(syncClientType).toProvider(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.concurrent.internal.SyncProxy;
import org.jclouds.internal.ClassMethodArgs; 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.base.Throwables;
import com.google.common.cache.LoadingCache; import com.google.common.cache.LoadingCache;
import com.google.inject.Injector; import com.google.inject.Injector;
@ -59,17 +61,18 @@ public class ClientProvider<S, A> implements Provider<S> {
@Singleton @Singleton
public S get() { public S get() {
A client = (A) injector.getInstance(Key.get(asyncClientType)); 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( LoadingCache<ClassMethodArgs, Object> delegateMap = injector.getInstance(Key.get(
new TypeLiteral<LoadingCache<ClassMethodArgs, Object>>() { new TypeLiteral<LoadingCache<ClassMethodArgs, Object>>() {
}, Names.named("sync"))); }, Names.named("sync")));
Map<String, Long> timeoutsMap = injector.getInstance(Key.get(new TypeLiteral<Map<String, Long>>() {
}, Names.named("TIMEOUTS")));
try { try {
return (S) SyncProxy.proxy(syncClientType, client, delegateMap, sync2Async, return (S) SyncProxy.proxy(optionalConverter, syncClientType, client, delegateMap, sync2Async,
injector.getInstance(Key.get(new TypeLiteral<Map<String, Long>>() { timeoutsMap);
}, Names.named("TIMEOUTS"))));
} catch (Exception e) { } catch (Exception e) {
Throwables.propagate(e); throw Throwables.propagate(e);
assert false : "should have propagated";
return null;
} }
} }
} }

View File

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

View File

@ -31,8 +31,11 @@ import org.jclouds.location.config.LocationModule;
import org.jclouds.rest.AuthorizationException; import org.jclouds.rest.AuthorizationException;
import org.jclouds.rest.ConfiguresRestClient; import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.RestContext; import org.jclouds.rest.RestContext;
import org.jclouds.rest.functions.ImplicitOptionalConverter;
import org.jclouds.rest.internal.RestContextImpl; 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.base.Supplier;
import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheBuilder;
import com.google.common.cache.LoadingCache; 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<A> asyncClientType;
protected final Class<S> syncClientType; 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>(); protected final AtomicReference<AuthorizationException> authException = new AtomicReference<AuthorizationException>();
public RestClientModule(Class<S> syncClientType, Class<A> asyncClientType, public RestClientModule(Class<S> syncClientType, Class<A> asyncClientType,
Map<Class<?>, Class<?>> delegates) { Map<Class<?>, Class<?>> sync2Async) {
this.asyncClientType = asyncClientType; this.asyncClientType = asyncClientType;
this.syncClientType = syncClientType; this.syncClientType = syncClientType;
this.delegates = delegates; this.sync2Async = sync2Async;
} }
public RestClientModule(Class<S> syncClientType, Class<A> asyncClientType) { public RestClientModule(Class<S> syncClientType, Class<A> asyncClientType) {
@ -77,6 +80,7 @@ public class RestClientModule<S, A> extends AbstractModule {
@SuppressWarnings({ "unchecked", "rawtypes" }) @SuppressWarnings({ "unchecked", "rawtypes" })
@Override @Override
protected void configure() { 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 // this will help short circuit scenarios that can otherwise lock out users
bind(new TypeLiteral<AtomicReference<AuthorizationException>>(){}).toInstance(authException); bind(new TypeLiteral<AtomicReference<AuthorizationException>>(){}).toInstance(authException);
// Ensures the restcontext can be looked up without generic types. // Ensures the restcontext can be looked up without generic types.
@ -136,7 +140,7 @@ public class RestClientModule<S, A> extends AbstractModule {
protected void bindClient() { protected void bindClient() {
BinderUtils.bindClient(binder(), syncClientType, asyncClientType, BinderUtils.bindClient(binder(), syncClientType, asyncClientType,
delegates); sync2Async);
} }
@ -145,7 +149,7 @@ public class RestClientModule<S, A> extends AbstractModule {
@Named("sync") @Named("sync")
LoadingCache<ClassMethodArgs, Object> provideSyncDelegateMap( LoadingCache<ClassMethodArgs, Object> provideSyncDelegateMap(
CreateClientForCaller createClientForCaller) { CreateClientForCaller createClientForCaller) {
createClientForCaller.sync2Async = delegates; createClientForCaller.sync2Async = sync2Async;
return CacheBuilder.newBuilder().build(createClientForCaller); 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.AuthorizationException;
import org.jclouds.rest.InvocationContext; import org.jclouds.rest.InvocationContext;
import org.jclouds.rest.annotations.Delegate; import org.jclouds.rest.annotations.Delegate;
import org.jclouds.util.Optionals2;
import org.jclouds.util.Throwables2; import org.jclouds.util.Throwables2;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.cache.LoadingCache; import com.google.common.cache.LoadingCache;
@ -97,6 +99,7 @@ public class AsyncRestClientProxy<T> implements InvocationHandler {
@Resource @Resource
protected Logger logger = Logger.NULL; protected Logger logger = Logger.NULL;
private final Function<Object, Optional<Object>> optionalConverter;
private final LoadingCache<ClassMethodArgs, Object> delegateMap; private final LoadingCache<ClassMethodArgs, Object> delegateMap;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -104,6 +107,8 @@ public class AsyncRestClientProxy<T> implements InvocationHandler {
public AsyncRestClientProxy(Injector injector, Factory factory, RestAnnotationProcessor<T> util, public AsyncRestClientProxy(Injector injector, Factory factory, RestAnnotationProcessor<T> util,
TypeLiteral<T> typeLiteral, @Named("async") LoadingCache<ClassMethodArgs, Object> delegateMap) { TypeLiteral<T> typeLiteral, @Named("async") LoadingCache<ClassMethodArgs, Object> delegateMap) {
this.injector = injector; this.injector = injector;
this.optionalConverter = injector.getInstance(Key.get(new TypeLiteral<Function<Object, Optional<Object>>>() {
}));
this.annotationProcessor = util; this.annotationProcessor = util;
this.declaring = (Class<T>) typeLiteral.getRawType(); this.declaring = (Class<T>) typeLiteral.getRawType();
this.commandFactory = factory; this.commandFactory = factory;
@ -144,7 +149,12 @@ public class AsyncRestClientProxy<T> implements InvocationHandler {
} }
public Object propagateContextToDelegate(Method method, Object[] args) throws ExecutionException { 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) { 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.Futures;
import org.jclouds.concurrent.Timeout; import org.jclouds.concurrent.Timeout;
import org.jclouds.internal.ClassMethodArgs; import org.jclouds.internal.ClassMethodArgs;
import org.jclouds.rest.functions.AlwaysPresentImplicitOptionalConverter;
import org.testng.annotations.BeforeTest; import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.base.Functions; import com.google.common.base.Functions;
import com.google.common.cache.LoadingCache;
import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader; import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
@ -185,7 +186,7 @@ public class SyncProxyTest {
public void setUp() throws IllegalArgumentException, SecurityException, NoSuchMethodException { public void setUp() throws IllegalArgumentException, SecurityException, NoSuchMethodException {
LoadingCache<ClassMethodArgs, Object> cache = CacheBuilder.newBuilder().build( LoadingCache<ClassMethodArgs, Object> cache = CacheBuilder.newBuilder().build(
CacheLoader.from(Functions.<Object> constant(null))); 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)); ImmutableMap.of("Sync.takeXMillisecondsPropOverride", 250L));
// just to warm up // just to warm up
sync.string(); sync.string();
@ -260,7 +261,7 @@ public class SyncProxyTest {
IOException { IOException {
LoadingCache<ClassMethodArgs, Object> cache = CacheBuilder.newBuilder().build( LoadingCache<ClassMethodArgs, Object> cache = CacheBuilder.newBuilder().build(
CacheLoader.from(Functions.<Object> constant(null))); 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()); ImmutableMap.<String, Long> of());
} }
@ -280,7 +281,7 @@ public class SyncProxyTest {
IOException { IOException {
LoadingCache<ClassMethodArgs, Object> cache = CacheBuilder.newBuilder().build( LoadingCache<ClassMethodArgs, Object> cache = CacheBuilder.newBuilder().build(
CacheLoader.from(Functions.<Object> constant(null))); 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()); ImmutableMap.<String, Long> of());
} }
@ -301,7 +302,7 @@ public class SyncProxyTest {
public void testClassOverridePropTimeout() throws Exception { public void testClassOverridePropTimeout() throws Exception {
LoadingCache<ClassMethodArgs, Object> cache = CacheBuilder.newBuilder().build( LoadingCache<ClassMethodArgs, Object> cache = CacheBuilder.newBuilder().build(
CacheLoader.from(Functions.<Object> constant(null))); 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)); ImmutableMap.<Class<?>, Class<?>> of(), ImmutableMap.<String, Long> of("SyncClassOverride", 100L));
assertEquals(sync2.takeXMillisecondsPropOverride(200), "foo"); 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.BindToJsonPayload;
import org.jclouds.rest.binders.BindToStringPayload; import org.jclouds.rest.binders.BindToStringPayload;
import org.jclouds.rest.config.RestClientModule; import org.jclouds.rest.config.RestClientModule;
import org.jclouds.rest.functions.ImplicitOptionalConverter;
import org.jclouds.util.Strings2; import org.jclouds.util.Strings2;
import org.jclouds.xml.XMLParser; import org.jclouds.xml.XMLParser;
import org.testng.Assert; import org.testng.Assert;
@ -144,6 +145,7 @@ import org.testng.annotations.Test;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Joiner; import com.google.common.base.Joiner;
import com.google.common.base.Optional;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.base.Suppliers; import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
@ -184,8 +186,7 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
protected void configure() { protected void configure() {
super.configure(); super.configure();
bind(new TypeLiteral<Supplier<URI>>() { bind(new TypeLiteral<Supplier<URI>>() {
}).annotatedWith(Localhost2.class).toInstance( }).annotatedWith(Localhost2.class).toInstance(Suppliers.ofInstance(URI.create("http://localhost:1111")));
Suppliers.ofInstance(URI.create("http://localhost:1111")));
bind(IOExceptionRetryHandler.class).toInstance(IOExceptionRetryHandler.NEVER_RETRY); bind(IOExceptionRetryHandler.class).toInstance(IOExceptionRetryHandler.NEVER_RETRY);
} }
@ -212,6 +213,9 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
@Delegate @Delegate
public Callee getCallee(@EndpointParam URI endpoint); public Callee getCallee(@EndpointParam URI endpoint);
@Delegate
public Optional<Callee> getOptionalCallee(@EndpointParam URI endpoint);
} }
@Timeout(duration = 10, timeUnit = TimeUnit.NANOSECONDS) @Timeout(duration = 10, timeUnit = TimeUnit.NANOSECONDS)
@ -230,15 +234,19 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
@Delegate @Delegate
public AsyncCallee getCallee(@EndpointParam URI endpoint); 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() { Injector child = injectorForCaller(new HttpCommandExecutorService() {
@Override @Override
public Future<HttpResponse> submit(HttpCommand command) { public Future<HttpResponse> submit(HttpCommand command) {
assertEquals(command.getCurrentRequest().getRequestLine(), 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()); 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() { Injector child = injectorForCaller(new HttpCommandExecutorService() {
@Override @Override
public Future<HttpResponse> submit(HttpCommand command) { public Future<HttpResponse> submit(HttpCommand command) {
assertEquals(command.getCurrentRequest().getRequestLine(), 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()); return Futures.immediateFuture(HttpResponse.builder().build());
} }
@ -279,14 +288,13 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
} }
public void testAsyncDelegateIsLazyLoadedAndRequestIncludesEndpointVersionAndPath() throws InterruptedException,
public void testAsyncDelegateIsLazyLoadedAndRequestIncludesEndpointVersionAndPath() throws InterruptedException, ExecutionException { ExecutionException {
Injector child = injectorForCaller(new HttpCommandExecutorService() { Injector child = injectorForCaller(new HttpCommandExecutorService() {
@Override @Override
public Future<HttpResponse> submit(HttpCommand command) { public Future<HttpResponse> submit(HttpCommand command) {
assertEquals(command.getCurrentRequest().getRequestLine(), assertEquals(command.getCurrentRequest().getRequestLine(), "GET http://howdyboys/client/1/foo HTTP/1.1");
"GET http://howdyboys/client/1/foo HTTP/1.1");
return Futures.immediateFuture(HttpResponse.builder().build()); 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() { Injector child = injectorForCaller(new HttpCommandExecutorService() {
@Override @Override
public Future<HttpResponse> submit(HttpCommand command) { public Future<HttpResponse> submit(HttpCommand command) {
assertEquals(command.getCurrentRequest().getRequestLine(), assertEquals(command.getCurrentRequest().getRequestLine(), "GET http://howdyboys/client/1/foo HTTP/1.1");
"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()); 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", "", "", RestContextSpec<Caller, AsyncCaller> contextSpec = contextSpec(
"userfoo", null, Caller.class, AsyncCaller.class, ImmutableSet.<Module> of(new MockModule(service), "test",
new NullLoggingModule(), new CallerModule())); "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(); return createContextBuilder(contextSpec).buildInjector();
@ -1822,9 +1903,9 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
public void oneTransformerWithContext() throws SecurityException, NoSuchMethodException { public void oneTransformerWithContext() throws SecurityException, NoSuchMethodException {
RestAnnotationProcessor<TestTransformers> processor = factory(TestTransformers.class); RestAnnotationProcessor<TestTransformers> processor = factory(TestTransformers.class);
Method method = TestTransformers.class.getMethod("oneTransformerWithContext"); Method method = TestTransformers.class.getMethod("oneTransformerWithContext");
GeneratedHttpRequest<TestTransformers> request = GeneratedHttpRequest.<TestTransformers>requestBuilder().method("GET") GeneratedHttpRequest<TestTransformers> request = GeneratedHttpRequest.<TestTransformers> requestBuilder()
.endpoint(URI.create("http://localhost")).declaring(TestTransformers.class).javaMethod(method) .method("GET").endpoint(URI.create("http://localhost")).declaring(TestTransformers.class)
.args(new Object[] {}).build(); .javaMethod(method).args(new Object[] {}).build();
Function<HttpResponse, ?> transformer = processor.createResponseParser(method, request); Function<HttpResponse, ?> transformer = processor.createResponseParser(method, request);
assertEquals(transformer.getClass(), ReturnStringIf200Context.class); assertEquals(transformer.getClass(), ReturnStringIf200Context.class);
assertEquals(((ReturnStringIf200Context) transformer).request, request); assertEquals(((ReturnStringIf200Context) transformer).request, request);
@ -2354,9 +2435,9 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
public void testCreateJAXBResponseParserWithAnnotation() throws SecurityException, NoSuchMethodException { public void testCreateJAXBResponseParserWithAnnotation() throws SecurityException, NoSuchMethodException {
RestAnnotationProcessor<TestJAXBResponseParser> processor = factory(TestJAXBResponseParser.class); RestAnnotationProcessor<TestJAXBResponseParser> processor = factory(TestJAXBResponseParser.class);
Method method = TestJAXBResponseParser.class.getMethod("jaxbGetWithAnnotation"); Method method = TestJAXBResponseParser.class.getMethod("jaxbGetWithAnnotation");
GeneratedHttpRequest<TestJAXBResponseParser> request = GeneratedHttpRequest.<TestJAXBResponseParser>requestBuilder() GeneratedHttpRequest<TestJAXBResponseParser> request = GeneratedHttpRequest
.method("GET").endpoint(URI.create("http://localhost")).declaring(TestJAXBResponseParser.class) .<TestJAXBResponseParser> requestBuilder().method("GET").endpoint(URI.create("http://localhost"))
.javaMethod(method).args(new Object[] {}).build(); .declaring(TestJAXBResponseParser.class).javaMethod(method).args(new Object[] {}).build();
Function<HttpResponse, ?> transformer = processor.createResponseParser(method, request); Function<HttpResponse, ?> transformer = processor.createResponseParser(method, request);
assertEquals(transformer.getClass(), ParseXMLWithJAXB.class); assertEquals(transformer.getClass(), ParseXMLWithJAXB.class);
} }
@ -2365,9 +2446,9 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
public void testCreateJAXBResponseParserWithAcceptHeader() throws SecurityException, NoSuchMethodException { public void testCreateJAXBResponseParserWithAcceptHeader() throws SecurityException, NoSuchMethodException {
RestAnnotationProcessor<TestJAXBResponseParser> processor = factory(TestJAXBResponseParser.class); RestAnnotationProcessor<TestJAXBResponseParser> processor = factory(TestJAXBResponseParser.class);
Method method = TestJAXBResponseParser.class.getMethod("jaxbGetWithAcceptHeader"); Method method = TestJAXBResponseParser.class.getMethod("jaxbGetWithAcceptHeader");
GeneratedHttpRequest<TestJAXBResponseParser> request = GeneratedHttpRequest.<TestJAXBResponseParser>requestBuilder() GeneratedHttpRequest<TestJAXBResponseParser> request = GeneratedHttpRequest
.method("GET").endpoint(URI.create("http://localhost")).declaring(TestJAXBResponseParser.class) .<TestJAXBResponseParser> requestBuilder().method("GET").endpoint(URI.create("http://localhost"))
.javaMethod(method).args(new Object[] {}).build(); .declaring(TestJAXBResponseParser.class).javaMethod(method).args(new Object[] {}).build();
Function<HttpResponse, ?> transformer = processor.createResponseParser(method, request); Function<HttpResponse, ?> transformer = processor.createResponseParser(method, request);
assertEquals(transformer.getClass(), ParseXMLWithJAXB.class); assertEquals(transformer.getClass(), ParseXMLWithJAXB.class);
} }
@ -2409,40 +2490,40 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
} }
@Test(expectedExceptions = NullPointerException.class) @Test(expectedExceptions = NullPointerException.class)
public void testAddHostNullWithHost() throws Exception{ public void testAddHostNullWithHost() throws Exception {
assertNull(RestAnnotationProcessor.addHostIfMissing(null,null)); assertNull(RestAnnotationProcessor.addHostIfMissing(null, null));
} }
@Test(expectedExceptions = IllegalArgumentException.class) @Test(expectedExceptions = IllegalArgumentException.class)
public void testAddHostWithHostHasNoHost() throws Exception{ public void testAddHostWithHostHasNoHost() throws Exception {
assertNull(RestAnnotationProcessor.addHostIfMissing(null,new URI("/no/host"))); assertNull(RestAnnotationProcessor.addHostIfMissing(null, new URI("/no/host")));
} }
@Test @Test
public void testAddHostNullOriginal() throws Exception{ public void testAddHostNullOriginal() throws Exception {
assertNull(RestAnnotationProcessor.addHostIfMissing(null,new URI("http://foo"))); assertNull(RestAnnotationProcessor.addHostIfMissing(null, new URI("http://foo")));
} }
@Test @Test
public void testAddHostOriginalHasHost() throws Exception{ public void testAddHostOriginalHasHost() throws Exception {
URI original = new URI("http://hashost/foo"); URI original = new URI("http://hashost/foo");
URI result = RestAnnotationProcessor.addHostIfMissing(original,new URI("http://foo")); URI result = RestAnnotationProcessor.addHostIfMissing(original, new URI("http://foo"));
assertEquals(original,result); assertEquals(original, result);
} }
@Test @Test
public void testAddHostIfMissing() throws Exception{ public void testAddHostIfMissing() throws Exception {
URI result = RestAnnotationProcessor.addHostIfMissing(new URI("/bar"),new URI("http://foo")); URI result = RestAnnotationProcessor.addHostIfMissing(new URI("/bar"), new URI("http://foo"));
assertEquals(new URI("http://foo/bar"),result); assertEquals(new URI("http://foo/bar"), result);
} }
DateService dateService = new SimpleDateFormatDateService(); DateService dateService = new SimpleDateFormatDateService();
@BeforeClass @BeforeClass
void setupFactory() { void setupFactory() {
RestContextSpec<Callee, AsyncCallee> contextSpec = contextSpec("test", "http://localhost:9999", "1", "", "", "userfoo", RestContextSpec<Callee, AsyncCallee> contextSpec = contextSpec("test", "http://localhost:9999", "1", "", "",
null, Callee.class, AsyncCallee.class, "userfoo", null, Callee.class, AsyncCallee.class,
ImmutableSet.<Module> of(new MockModule(), new NullLoggingModule(), new AbstractModule() { ImmutableSet.<Module> of(new MockModule(), new NullLoggingModule(), new AbstractModule() {
@Override @Override
@ -2453,7 +2534,7 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
}).annotatedWith(Names.named("bar")).toInstance(ImmutableSet.of("bar")); }).annotatedWith(Names.named("bar")).toInstance(ImmutableSet.of("bar"));
bind(new TypeLiteral<Supplier<URI>>() { bind(new TypeLiteral<Supplier<URI>>() {
}).annotatedWith(Localhost2.class).toInstance( }).annotatedWith(Localhost2.class).toInstance(
Suppliers.ofInstance(URI.create("http://localhost:1111"))); Suppliers.ofInstance(URI.create("http://localhost:1111")));
} }
@SuppressWarnings("unused") @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.Delegate;
import org.jclouds.rest.annotations.EndpointParam; import org.jclouds.rest.annotations.EndpointParam;
import com.google.common.base.Optional;
import com.google.inject.Provides; import com.google.inject.Provides;
/** /**
@ -85,7 +86,7 @@ public interface NovaAsyncClient {
* Provides asynchronous access to Floating IP features. * Provides asynchronous access to Floating IP features.
*/ */
@Delegate @Delegate
FloatingIPAsyncClient getFloatingIPClientForRegion( Optional<FloatingIPAsyncClient> getFloatingIPExtensionForRegion(
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region); @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.Delegate;
import org.jclouds.rest.annotations.EndpointParam; import org.jclouds.rest.annotations.EndpointParam;
import com.google.common.base.Optional;
import com.google.inject.Provides; import com.google.inject.Provides;
/** /**
@ -87,7 +88,7 @@ public interface NovaClient {
* Provides synchronous access to Floating IP features. * Provides synchronous access to Floating IP features.
*/ */
@Delegate @Delegate
FloatingIPClient getFloatingIPClientForRegion( Optional<FloatingIPClient> getFloatingIPExtensionForRegion(
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region); @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region);
/** /**

View File

@ -18,7 +18,6 @@
*/ */
package org.jclouds.openstack.nova.v1_1.extensions; package org.jclouds.openstack.nova.v1_1.extensions;
import java.net.URI;
/** /**
* Extension namespaces * Extension namespaces
@ -27,8 +26,8 @@ import java.net.URI;
* @see <a href= "http://nova.openstack.org/api_ext/" /> * @see <a href= "http://nova.openstack.org/api_ext/" />
*/ */
public interface ExtensionNamespaces { public interface ExtensionNamespaces {
public static URI KEYPAIRS = URI.create("http://docs.openstack.org/ext/keypairs/api/v1.1"); public static final String KEYPAIRS = "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 final String VOLUMES = "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 final String SECURITY_GROUPS = "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 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.filters.AuthenticateRequest;
import org.jclouds.openstack.nova.v1_1.domain.FloatingIP; import org.jclouds.openstack.nova.v1_1.domain.FloatingIP;
import org.jclouds.openstack.nova.v1_1.features.ExtensionAsyncClient; 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.ExceptionParser;
import org.jclouds.rest.annotations.Payload; import org.jclouds.rest.annotations.Payload;
import org.jclouds.rest.annotations.PayloadParam; import org.jclouds.rest.annotations.PayloadParam;
@ -50,10 +52,13 @@ import com.google.common.util.concurrent.ListenableFuture;
* @see FloatingIPClient * @see FloatingIPClient
* @author Jeremy Daggett * @author Jeremy Daggett
* @see ExtensionAsyncClient * @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://nova.openstack.org/api_ext" />
* @see <a href="http://wiki.openstack.org/os_api_floating_ip"/> * @see <a href="http://wiki.openstack.org/os_api_floating_ip"/>
*/ */
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.FLOATING_IPS)
@SkipEncoding({ '/', '=' }) @SkipEncoding({ '/', '=' })
@RequestFilters(AuthenticateRequest.class) @RequestFilters(AuthenticateRequest.class)
public interface FloatingIPAsyncClient { public interface FloatingIPAsyncClient {
@ -107,9 +112,7 @@ public interface FloatingIPAsyncClient {
@Consumes @Consumes
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
@Payload("%7B\"addFloatingIp\":%7B\"address\":\"{address}\"%7D%7D") @Payload("%7B\"addFloatingIp\":%7B\"address\":\"{address}\"%7D%7D")
ListenableFuture<Void> addFloatingIP( ListenableFuture<Void> addFloatingIP(@PathParam("server") String serverId, @PayloadParam("address") String address);
@PathParam("server") String serverId,
@PayloadParam("address") String address);
/** /**
* @see FloatingIPClient#removeFloatingIP * @see FloatingIPClient#removeFloatingIP
@ -119,8 +122,6 @@ public interface FloatingIPAsyncClient {
@Consumes @Consumes
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
@Payload("%7B\"removeFloatingIp\":%7B\"address\":\"{address}\"%7D%7D") @Payload("%7B\"removeFloatingIp\":%7B\"address\":\"{address}\"%7D%7D")
ListenableFuture<Void> removeFloatingIP( ListenableFuture<Void> removeFloatingIP(@PathParam("server") String serverId, @PayloadParam("address") String address);
@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.concurrent.Timeout;
import org.jclouds.openstack.nova.v1_1.domain.FloatingIP; 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. * Provides synchronous access to Floating IPs.
@ -31,6 +33,7 @@ import org.jclouds.openstack.nova.v1_1.domain.FloatingIP;
* @see FloatingIPAsyncClient * @see FloatingIPAsyncClient
* @author Jeremy Daggett * @author Jeremy Daggett
*/ */
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.FLOATING_IPS)
@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS) @Timeout(duration = 30, timeUnit = TimeUnit.SECONDS)
public interface FloatingIPClient { 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.filters.AuthenticateRequest;
import org.jclouds.openstack.nova.v1_1.domain.KeyPair; import org.jclouds.openstack.nova.v1_1.domain.KeyPair;
import org.jclouds.openstack.nova.v1_1.features.ExtensionAsyncClient; 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.ExceptionParser;
import org.jclouds.rest.annotations.Payload; import org.jclouds.rest.annotations.Payload;
import org.jclouds.rest.annotations.PayloadParam; 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" />
* @see <a href="http://nova.openstack.org/api_ext/ext_keypairs.html" /> * @see <a href="http://nova.openstack.org/api_ext/ext_keypairs.html" />
*/ */
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.KEYPAIRS)
@SkipEncoding({ '/', '=' }) @SkipEncoding({ '/', '=' })
@RequestFilters(AuthenticateRequest.class) @RequestFilters(AuthenticateRequest.class)
public interface KeyPairAsyncClient { public interface KeyPairAsyncClient {

View File

@ -24,6 +24,8 @@ import java.util.concurrent.TimeUnit;
import org.jclouds.concurrent.Timeout; import org.jclouds.concurrent.Timeout;
import org.jclouds.openstack.nova.v1_1.domain.KeyPair; 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. * Provides synchronous access to Security Groups.
@ -32,6 +34,7 @@ import org.jclouds.openstack.nova.v1_1.domain.KeyPair;
* @see KeyPairAsyncClient * @see KeyPairAsyncClient
* @author Jeremy Daggett * @author Jeremy Daggett
*/ */
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.KEYPAIRS)
@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS) @Timeout(duration = 30, timeUnit = TimeUnit.SECONDS)
public interface KeyPairClient { 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.filters.AuthenticateRequest;
import org.jclouds.openstack.nova.v1_1.domain.SecurityGroup; import org.jclouds.openstack.nova.v1_1.domain.SecurityGroup;
import org.jclouds.openstack.nova.v1_1.domain.SecurityGroupRule; 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.ExceptionParser;
import org.jclouds.rest.annotations.Payload; import org.jclouds.rest.annotations.Payload;
import org.jclouds.rest.annotations.PayloadParam; 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://nova.openstack.org/api_ext" />
* @see <a href="http://wiki.openstack.org/os-security-groups" /> * @see <a href="http://wiki.openstack.org/os-security-groups" />
*/ */
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.SECURITY_GROUPS)
@SkipEncoding({ '/', '=' }) @SkipEncoding({ '/', '=' })
@RequestFilters(AuthenticateRequest.class) @RequestFilters(AuthenticateRequest.class)
public interface SecurityGroupAsyncClient { public interface SecurityGroupAsyncClient {

View File

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

View File

@ -26,7 +26,7 @@ import java.util.Properties;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties; 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.jclouds.openstack.nova.v1_1.parse.ParseServerListTest;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -39,7 +39,7 @@ import com.google.common.collect.ImmutableSet;
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test(groups = "unit", testName = "PasswordAuthenticationExpectTest") @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 * 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.HttpRequest;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.openstack.nova.v1_1.NovaClient; 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.ParseFloatingIPListTest;
import org.jclouds.openstack.nova.v1_1.parse.ParseFloatingIPTest; import org.jclouds.openstack.nova.v1_1.parse.ParseFloatingIPTest;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -41,7 +41,7 @@ import com.google.common.collect.ImmutableSet;
* @author Michael Arnold * @author Michael Arnold
*/ */
@Test(groups = "unit", testName = "FloatingIPClientExpectTest") @Test(groups = "unit", testName = "FloatingIPClientExpectTest")
public class FloatingIPClientExpectTest extends BaseNovaRestClientExpectTest { public class FloatingIPClientExpectTest extends BaseNovaClientExpectTest {
public void testListFloatingIPsWhenResponseIs2xx() throws Exception { public void testListFloatingIPsWhenResponseIs2xx() throws Exception {
HttpRequest listFloatingIPs = HttpRequest HttpRequest listFloatingIPs = HttpRequest
@ -64,7 +64,7 @@ public class FloatingIPClientExpectTest extends BaseNovaRestClientExpectTest {
assertEquals(clientWhenFloatingIPsExist.getConfiguredRegions(), assertEquals(clientWhenFloatingIPsExist.getConfiguredRegions(),
ImmutableSet.of("North")); ImmutableSet.of("North"));
assertEquals(clientWhenFloatingIPsExist.getFloatingIPClientForRegion("North") assertEquals(clientWhenFloatingIPsExist.getFloatingIPExtensionForRegion("North").get()
.listFloatingIPs().toString(), new ParseFloatingIPListTest().expected() .listFloatingIPs().toString(), new ParseFloatingIPListTest().expected()
.toString()); .toString());
} }
@ -87,7 +87,7 @@ public class FloatingIPClientExpectTest extends BaseNovaRestClientExpectTest {
keystoneAuthWithAccessKeyAndSecretKey, responseWithKeystoneAccess, keystoneAuthWithAccessKeyAndSecretKey, responseWithKeystoneAccess,
listFloatingIPs, listFloatingIPsResponse); listFloatingIPs, listFloatingIPsResponse);
assertTrue(clientWhenNoServersExist.getFloatingIPClientForRegion("North") assertTrue(clientWhenNoServersExist.getFloatingIPExtensionForRegion("North").get()
.listFloatingIPs().isEmpty()); .listFloatingIPs().isEmpty());
} }
@ -109,7 +109,7 @@ public class FloatingIPClientExpectTest extends BaseNovaRestClientExpectTest {
keystoneAuthWithAccessKeyAndSecretKey, responseWithKeystoneAccess, keystoneAuthWithAccessKeyAndSecretKey, responseWithKeystoneAccess,
getFloatingIP, getFloatingIPResponse); getFloatingIP, getFloatingIPResponse);
assertEquals(clientWhenFloatingIPsExist.getFloatingIPClientForRegion("North") assertEquals(clientWhenFloatingIPsExist.getFloatingIPExtensionForRegion("North").get()
.getFloatingIP("1").toString(), .getFloatingIP("1").toString(),
new ParseFloatingIPTest().expected().toString()); new ParseFloatingIPTest().expected().toString());
} }
@ -131,7 +131,7 @@ public class FloatingIPClientExpectTest extends BaseNovaRestClientExpectTest {
keystoneAuthWithAccessKeyAndSecretKey, responseWithKeystoneAccess, keystoneAuthWithAccessKeyAndSecretKey, responseWithKeystoneAccess,
getFloatingIP, getFloatingIPResponse); getFloatingIP, getFloatingIPResponse);
assertNull(clientWhenNoServersExist.getFloatingIPClientForRegion("North") assertNull(clientWhenNoServersExist.getFloatingIPExtensionForRegion("North").get()
.getFloatingIP("1")); .getFloatingIP("1"));
} }
@ -154,7 +154,7 @@ public class FloatingIPClientExpectTest extends BaseNovaRestClientExpectTest {
keystoneAuthWithAccessKeyAndSecretKey, responseWithKeystoneAccess, keystoneAuthWithAccessKeyAndSecretKey, responseWithKeystoneAccess,
allocateFloatingIP, allocateFloatingIPResponse); allocateFloatingIP, allocateFloatingIPResponse);
assertEquals(clientWhenFloatingIPsExist.getFloatingIPClientForRegion("North") assertEquals(clientWhenFloatingIPsExist.getFloatingIPExtensionForRegion("North").get()
.allocate().toString(), .allocate().toString(),
new ParseFloatingIPTest().expected().toString()); new ParseFloatingIPTest().expected().toString());
@ -178,7 +178,7 @@ public class FloatingIPClientExpectTest extends BaseNovaRestClientExpectTest {
keystoneAuthWithAccessKeyAndSecretKey, responseWithKeystoneAccess, keystoneAuthWithAccessKeyAndSecretKey, responseWithKeystoneAccess,
allocateFloatingIP, allocateFloatingIPResponse); allocateFloatingIP, allocateFloatingIPResponse);
assertNull(clientWhenNoServersExist.getFloatingIPClientForRegion("North") assertNull(clientWhenNoServersExist.getFloatingIPExtensionForRegion("North").get()
.allocate()); .allocate());
} }

View File

@ -25,6 +25,7 @@ import static org.testng.Assert.assertTrue;
import java.util.Set; import java.util.Set;
import com.google.common.base.Optional;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import org.jclouds.openstack.nova.v1_1.domain.Address; import org.jclouds.openstack.nova.v1_1.domain.Address;
import org.jclouds.openstack.nova.v1_1.domain.FloatingIP; import org.jclouds.openstack.nova.v1_1.domain.FloatingIP;
@ -52,8 +53,10 @@ public class FloatingIPClientLiveTest extends BaseNovaClientLiveTest {
@Test @Test
public void testListFloatingIPs() throws Exception { public void testListFloatingIPs() throws Exception {
for (String regionId : context.getApi().getConfiguredRegions()) { for (String regionId : context.getApi().getConfiguredRegions()) {
Optional<FloatingIPClient> clientOption = context.getApi().getFloatingIPExtensionForRegion(regionId);
FloatingIPClient client = context.getApi().getFloatingIPClientForRegion(regionId); if (!clientOption.isPresent())
continue;
FloatingIPClient client = clientOption.get();
Set<FloatingIP> response = client.listFloatingIPs(); Set<FloatingIP> response = client.listFloatingIPs();
assert null != response; assert null != response;
assertTrue(response.size() >= 0); assertTrue(response.size() >= 0);
@ -73,7 +76,10 @@ public class FloatingIPClientLiveTest extends BaseNovaClientLiveTest {
@Test @Test
public void testAllocateAndDeallocateFloatingIPs() throws Exception { public void testAllocateAndDeallocateFloatingIPs() throws Exception {
for (String regionId : context.getApi().getConfiguredRegions()) { 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(); FloatingIP floatingIP = client.allocate();
assertNotNull(floatingIP); assertNotNull(floatingIP);
@ -101,7 +107,10 @@ public class FloatingIPClientLiveTest extends BaseNovaClientLiveTest {
@Test @Test
public void testAddAndRemoveFloatingIp() throws Exception { public void testAddAndRemoveFloatingIp() throws Exception {
for (String regionId : context.getApi().getConfiguredRegions()) { 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); ServerClient serverClient = context.getApi().getServerClientForRegion(regionId);
Server server = serverClient.createServer("test", imageIdForRegion(regionId), flavorRefForRegion(regionId)); Server server = serverClient.createServer("test", imageIdForRegion(regionId), flavorRefForRegion(regionId));
blockUntilServerActive(server.getId(), serverClient); 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.HttpRequest;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.openstack.nova.v1_1.NovaClient; 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.ParseKeyPairListTest;
import org.jclouds.openstack.nova.v1_1.parse.ParseKeyPairTest; import org.jclouds.openstack.nova.v1_1.parse.ParseKeyPairTest;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -40,7 +40,7 @@ import static org.testng.Assert.assertTrue;
* @author Michael Arnold * @author Michael Arnold
*/ */
@Test(groups = "unit", testName = "KeyPairClientExpectTest") @Test(groups = "unit", testName = "KeyPairClientExpectTest")
public class KeyPairClientExpectTest extends BaseNovaRestClientExpectTest { public class KeyPairClientExpectTest extends BaseNovaClientExpectTest {
public void testListKeyPairsWhenResponseIs2xx() throws Exception { public void testListKeyPairsWhenResponseIs2xx() throws Exception {
HttpRequest listKeyPairs = HttpRequest HttpRequest listKeyPairs = HttpRequest

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -18,33 +18,32 @@
*/ */
package org.jclouds.openstack.nova.v1_1.internal; 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 java.util.Properties;
import org.jclouds.http.HttpRequest; 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.NovaAsyncClient;
import org.jclouds.openstack.nova.v1_1.NovaClient; import org.jclouds.openstack.nova.v1_1.NovaClient;
import org.jclouds.rest.RestClientTest;
import org.jclouds.rest.RestContextFactory; import org.jclouds.rest.RestContextFactory;
import org.jclouds.rest.RestContextSpec; 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 * @author Adrian Cole
*/ */
public abstract class BaseNovaAsyncClientTest<T> extends RestClientTest<T> { public class BaseNovaAsyncClientExpectTest extends BaseNovaExpectTest<NovaAsyncClient> {
public NovaAsyncClient createClient(Function<HttpRequest, HttpResponse> fn, Module module, Properties props) {
@Override RestContextSpec<NovaClient, NovaAsyncClient> contextSpec = new RestContextFactory(setupRestProperties())
protected void checkFilters(HttpRequest request) { .createContextSpec(provider, identity, credential, new Properties());
assertEquals(request.getFilters().size(), 1); return createContext(contextSpec,
assertEquals(request.getFilters().get(0).getClass(), AuthenticateRequest.class); 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.HttpRequest;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.logging.config.NullLoggingModule; 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.base.Function;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.inject.Module; 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 * @author Matt Stephenson
*/ */
public class BaseNovaComputeServiceExpectTest extends BaseRestClientExpectTest<ComputeService> public class BaseNovaComputeServiceExpectTest extends BaseNovaExpectTest<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;
}
@Override @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, 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.HttpRequest;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.openstack.keystone.v2_0.internal.KeystoneFixture; import org.jclouds.openstack.keystone.v2_0.internal.KeystoneFixture;
import org.jclouds.openstack.nova.v1_1.NovaClient;
import org.jclouds.rest.BaseRestClientExpectTest; import org.jclouds.rest.BaseRestClientExpectTest;
/** /**
* Base class for writing KeyStone Rest Client Expect tests * Base class for writing Nova Expect tests
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
public class BaseNovaRestClientExpectTest extends BaseRestClientExpectTest<NovaClient> { public class BaseNovaExpectTest<T> extends BaseRestClientExpectTest<T> {
protected HttpRequest keystoneAuthWithUsernameAndPassword; protected HttpRequest keystoneAuthWithUsernameAndPassword;
protected HttpRequest keystoneAuthWithAccessKeyAndSecretKey; protected HttpRequest keystoneAuthWithAccessKeyAndSecretKey;
protected String authToken; protected String authToken;
protected HttpResponse responseWithKeystoneAccess; protected HttpResponse responseWithKeystoneAccess;
public BaseNovaRestClientExpectTest() { public BaseNovaExpectTest() {
provider = "openstack-nova"; provider = "openstack-nova";
keystoneAuthWithUsernameAndPassword = KeystoneFixture.INSTANCE.initialAuthWithUsernameAndPassword(identity, keystoneAuthWithUsernameAndPassword = KeystoneFixture.INSTANCE.initialAuthWithUsernameAndPassword(identity,
credential); credential);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -19,18 +19,16 @@
package org.jclouds.virtualbox; 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_BUILD_VERSION;
import static org.jclouds.Constants.PROPERTY_CREDENTIAL;
import static org.jclouds.Constants.PROPERTY_ENDPOINT; 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_AUTHENTICATE_SUDO;
import static org.jclouds.compute.reference.ComputeServiceConstants.PROPERTY_IMAGE_LOGIN_USER; 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_DEFAULT_DIR;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_IMAGES_DESCRIPTOR; 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_INSTALLATION_KEY_SEQUENCE;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_PRECONFIGURATION_URL; 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.io.File;
import java.util.Properties; import java.util.Properties;
@ -60,12 +58,10 @@ public class VirtualBoxPropertiesBuilder extends PropertiesBuilder {
properties.put(PROPERTY_API_VERSION, "4.1.4"); properties.put(PROPERTY_API_VERSION, "4.1.4");
properties.put(PROPERTY_BUILD_VERSION, "4.1.8r75467"); 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_LOGIN_USER, "toor:password");
properties.put(PROPERTY_IMAGE_AUTHENTICATE_SUDO, "true"); properties.put(PROPERTY_IMAGE_AUTHENTICATE_SUDO, "true");
properties.put(VIRTUALBOX_INSTALLATION_KEY_SEQUENCE, "<Esc><Esc><Enter> " properties.put(VIRTUALBOX_INSTALLATION_KEY_SEQUENCE, "<Esc><Esc><Enter> "
+ "/install/vmlinuz noapic preseed/url=PRECONFIGURATION_URL " + "/install/vmlinuz noapic preseed/url=PRECONFIGURATION_URL "
+ "debian-installer=en_US auto locale=en_US kbd-chooser/method=us " + "hostname=" + "HOSTNAME " + "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_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; 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(); NodeSpec nodeSpec = NodeSpec.builder().master(master).name(name).tag(tag).template(template).build();
return cloneCreator.apply(nodeSpec); return cloneCreator.apply(nodeSpec);
} catch (Exception e) { } 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.IMachineToImage;
import org.jclouds.virtualbox.functions.IMachineToNodeMetadata; import org.jclouds.virtualbox.functions.IMachineToNodeMetadata;
import org.jclouds.virtualbox.functions.IMachineToSshClient; 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.NodeCreator;
import org.jclouds.virtualbox.functions.YamlImagesFromFileConfig; import org.jclouds.virtualbox.functions.YamlImagesFromFileConfig;
import org.jclouds.virtualbox.functions.admin.FileDownloadFromURI; import org.jclouds.virtualbox.functions.admin.FileDownloadFromURI;
@ -141,7 +141,7 @@ public class VirtualBoxComputeServiceContextModule extends
}).to((Class) YamlImagesFromFileConfig.class); }).to((Class) YamlImagesFromFileConfig.class);
// the master machines cache // the master machines cache
bind(new TypeLiteral<LoadingCache<Image, Master>>() { bind(new TypeLiteral<LoadingCache<Image, Master>>() {
}).to((Class) MastersCache.class); }).to((Class) MastersLoadingCache.class);
// the master creating function // the master creating function
bind(new TypeLiteral<Function<MasterSpec, IMachine>>() { bind(new TypeLiteral<Function<MasterSpec, IMachine>>() {
}).to((Class) CreateAndInstallVm.class); }).to((Class) CreateAndInstallVm.class);

View File

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

View File

@ -44,12 +44,10 @@ import org.jclouds.virtualbox.util.MachineController;
import org.jclouds.virtualbox.util.MachineUtils; import org.jclouds.virtualbox.util.MachineUtils;
import org.virtualbox_4_1.IMachine; import org.virtualbox_4_1.IMachine;
import org.virtualbox_4_1.LockType; import org.virtualbox_4_1.LockType;
import org.virtualbox_4_1.VirtualBoxManager;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Splitter; import com.google.common.base.Splitter;
import com.google.common.base.Supplier;
import com.google.common.cache.LoadingCache; import com.google.common.cache.LoadingCache;
import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
@ -62,7 +60,6 @@ public class CreateAndInstallVm implements Function<MasterSpec, IMachine> {
@Named(ComputeServiceConstants.COMPUTE_LOGGER) @Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL; protected Logger logger = Logger.NULL;
private final Supplier<VirtualBoxManager> manager;
private final CreateAndRegisterMachineFromIsoIfNotAlreadyExists createAndRegisterMachineFromIsoIfNotAlreadyExists; private final CreateAndRegisterMachineFromIsoIfNotAlreadyExists createAndRegisterMachineFromIsoIfNotAlreadyExists;
private final GuestAdditionsInstaller guestAdditionsInstaller; private final GuestAdditionsInstaller guestAdditionsInstaller;
private final Predicate<SshClient> sshResponds; private final Predicate<SshClient> sshResponds;
@ -75,7 +72,6 @@ public class CreateAndInstallVm implements Function<MasterSpec, IMachine> {
@Inject @Inject
public CreateAndInstallVm( public CreateAndInstallVm(
Supplier<VirtualBoxManager> manager,
CreateAndRegisterMachineFromIsoIfNotAlreadyExists CreateAndRegisterMachineFromIsoIfNotAlreadyExists, CreateAndRegisterMachineFromIsoIfNotAlreadyExists CreateAndRegisterMachineFromIsoIfNotAlreadyExists,
GuestAdditionsInstaller guestAdditionsInstaller, GuestAdditionsInstaller guestAdditionsInstaller,
IMachineToNodeMetadata imachineToNodeMetadata, IMachineToNodeMetadata imachineToNodeMetadata,
@ -83,7 +79,6 @@ public class CreateAndInstallVm implements Function<MasterSpec, IMachine> {
Function<IMachine, SshClient> sshClientForIMachine, Function<IMachine, SshClient> sshClientForIMachine,
MachineUtils machineUtils, MachineUtils machineUtils,
@Preconfiguration LoadingCache<IsoSpec, URI> preConfiguration, MachineController machineController) { @Preconfiguration LoadingCache<IsoSpec, URI> preConfiguration, MachineController machineController) {
this.manager = manager;
this.createAndRegisterMachineFromIsoIfNotAlreadyExists = CreateAndRegisterMachineFromIsoIfNotAlreadyExists; this.createAndRegisterMachineFromIsoIfNotAlreadyExists = CreateAndRegisterMachineFromIsoIfNotAlreadyExists;
this.sshResponds = sshResponds; this.sshResponds = sshResponds;
this.sshClientForIMachine = sshClientForIMachine; this.sshClientForIMachine = sshClientForIMachine;
@ -113,6 +108,7 @@ public class CreateAndInstallVm implements Function<MasterSpec, IMachine> {
configureOsInstallationWithKeyboardSequence(vmName, configureOsInstallationWithKeyboardSequence(vmName,
installationKeySequence); installationKeySequence);
SshClient client = sshClientForIMachine.apply(vm); SshClient client = sshClientForIMachine.apply(vm);
logger.debug(">> awaiting installation to finish node(%s)", vmName); 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", "timed out waiting for guest %s to be accessible via ssh",
vmName); vmName);
//logger.debug(">> awaiting installation of guest additions on vm: %s", vmName); logger.debug(">> awaiting installation of guest additions on vm: %s", vmName);
//checkState(guestAdditionsInstaller.apply(vm)); checkState(guestAdditionsInstaller.apply(vm));
logger.debug(">> awaiting post-installation actions on vm: %s", vmName); 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 com.google.common.base.Preconditions.checkState;
import static org.jclouds.virtualbox.config.VirtualBoxComputeServiceContextModule.machineToNodeState; import static org.jclouds.virtualbox.config.VirtualBoxComputeServiceContextModule.machineToNodeState;
import java.util.HashSet;
import java.util.Set;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.inject.Named; import javax.inject.Named;
import org.jclouds.compute.domain.HardwareBuilder;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadataBuilder; import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.domain.NodeState; import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.Processor;
import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.LocationBuilder; import org.jclouds.domain.LocationBuilder;
import org.jclouds.domain.LocationScope; 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.Splitter;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.cache.AbstractLoadingCache; import com.google.common.cache.AbstractLoadingCache;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Maps; 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 * @author dralves
* *
*/ */
@Singleton @Singleton
public class MastersCache extends AbstractLoadingCache<Image, Master> { public class MastersLoadingCache extends AbstractLoadingCache<Image, Master> {
// TODO parameterize // TODO parameterize
public static final int MASTER_PORT = 2222; public static final int MASTER_PORT = 2222;
@ -94,7 +97,7 @@ public class MastersCache extends AbstractLoadingCache<Image, Master> {
private String version; private String version;
@Inject @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_INSTALLATION_KEY_SEQUENCE) String installationKeySequence,
@Named(VIRTUALBOX_WORKINGDIR) String workingDir, Function<MasterSpec, IMachine> masterLoader, @Named(VIRTUALBOX_WORKINGDIR) String workingDir, Function<MasterSpec, IMachine> masterLoader,
Supplier<Map<Image, YamlImage>> yamlMapper, Supplier<VirtualBoxManager> manager, 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.NetworkSpec;
import org.jclouds.virtualbox.domain.NodeSpec; import org.jclouds.virtualbox.domain.NodeSpec;
import org.jclouds.virtualbox.domain.VmSpec; import org.jclouds.virtualbox.domain.VmSpec;
import org.jclouds.virtualbox.statements.DeleteGShadowLock;
import org.jclouds.virtualbox.statements.SetIpAddress; import org.jclouds.virtualbox.statements.SetIpAddress;
import org.jclouds.virtualbox.util.MachineUtils; import org.jclouds.virtualbox.util.MachineUtils;
import org.virtualbox_4_1.CleanupMode; import org.virtualbox_4_1.CleanupMode;
import org.virtualbox_4_1.IMachine; import org.virtualbox_4_1.IMachine;
import org.virtualbox_4_1.IProgress;
import org.virtualbox_4_1.ISession; import org.virtualbox_4_1.ISession;
import org.virtualbox_4_1.NetworkAttachmentType; import org.virtualbox_4_1.NetworkAttachmentType;
import org.virtualbox_4_1.VirtualBoxManager; 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.Function;
import com.google.common.base.Supplier; 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 @Singleton
public class NodeCreator implements public class NodeCreator implements Function<NodeSpec, NodeAndInitialCredentials<IMachine>> {
Function<NodeSpec, NodeAndInitialCredentials<IMachine>> {
// TODO parameterize // TODO parameterize
public static final int NODE_PORT_INIT = 3000; public static final int NODE_PORT_INIT = 3000;
// TODO parameterize // TODO parameterize
public static final String VMS_NETWORK = "33.33.33."; public static final String VMS_NETWORK = "33.33.33.";
// TODO parameterize // TODO parameterize
public static final String HOST_ONLY_IFACE_NAME = "vboxnet0"; public static final String HOST_ONLY_IFACE_NAME = "vboxnet0";
// TODO parameterize // TODO parameterize
public static final boolean USE_LINKED = true; public static final boolean USE_LINKED = true;
private final Supplier<VirtualBoxManager> manager; // TODO parameterize
private final Function<CloneSpec, IMachine> cloner; public static final ExecutionType EXECUTION_TYPE = ExecutionType.HEADLESS;
private final AtomicInteger nodePorts;
private final AtomicInteger nodeIps;
private MachineUtils machineUtils;
private Function<IMachine, NodeMetadata> imachineToNodeMetadata;
private final RunScriptOnNode.Factory scriptRunnerFactory; private final Supplier<VirtualBoxManager> manager;
private final Supplier<NodeMetadata> hostSupplier; private final Function<CloneSpec, IMachine> cloner;
private final AtomicInteger nodePorts;
private final AtomicInteger nodeIps;
private MachineUtils machineUtils;
private Function<IMachine, NodeMetadata> imachineToNodeMetadata;
@Inject private final RunScriptOnNode.Factory scriptRunnerFactory;
public NodeCreator(Supplier<VirtualBoxManager> manager, private final Supplier<NodeMetadata> hostSupplier;
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;
} @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(nodeSpec, "NodeSpec");
checkNotNull(master, "Master");
if (master.getMachine().getCurrentSnapshot() != null) { Master master = nodeSpec.getMaster();
ISession session; checkNotNull(master, "Master");
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, "");
String cloneName = VIRTUALBOX_NODE_PREFIX + masterNameWithoutPrefix if (master.getMachine().getCurrentSnapshot() != null) {
+ "-" + nodeSpec.getTag() + "-" + nodeSpec.getName(); 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) String cloneName = VIRTUALBOX_NODE_PREFIX + masterNameWithoutPrefix + "-" + nodeSpec.getTag() + "-"
.memoryMB(512).cleanUpMode(CleanupMode.Full) + nodeSpec.getName();
.forceOverwrite(true).build();
VmSpec cloneVmSpec = VmSpec.builder().id(cloneName).name(cloneName).memoryMB(512).cleanUpMode(CleanupMode.Full)
.forceOverwrite(true).build();
// CASE NAT + HOST-ONLY // CASE NAT + HOST-ONLY
NetworkAdapter natAdapter = NetworkAdapter NetworkAdapter natAdapter = NetworkAdapter.builder().networkAttachmentType(NetworkAttachmentType.NAT)
.builder() .tcpRedirectRule("127.0.0.1", this.nodePorts.getAndIncrement(), "", 22).build();
.networkAttachmentType(NetworkAttachmentType.NAT) NetworkInterfaceCard natIfaceCard = NetworkInterfaceCard.builder().addNetworkAdapter(natAdapter).slot(0L).build();
.tcpRedirectRule("127.0.0.1", this.nodePorts.getAndIncrement(),
"", 22).build();
NetworkInterfaceCard natIfaceCard = NetworkInterfaceCard.builder()
.addNetworkAdapter(natAdapter).slot(0L).build();
NetworkAdapter hostOnlyAdapter = NetworkAdapter.builder() NetworkAdapter hostOnlyAdapter = NetworkAdapter.builder().networkAttachmentType(NetworkAttachmentType.HostOnly)
.networkAttachmentType(NetworkAttachmentType.HostOnly) .staticIp(VMS_NETWORK + this.nodeIps.getAndIncrement()).build();
.staticIp(VMS_NETWORK + this.nodeIps.getAndIncrement()).build();
NetworkInterfaceCard hostOnlyIfaceCard = NetworkInterfaceCard.builder() NetworkInterfaceCard hostOnlyIfaceCard = NetworkInterfaceCard.builder().addNetworkAdapter(hostOnlyAdapter)
.addNetworkAdapter(hostOnlyAdapter) .addHostInterfaceName(HOST_ONLY_IFACE_NAME).slot(1L).build();
.addHostInterfaceName(HOST_ONLY_IFACE_NAME).slot(1L).build();
NetworkSpec networkSpec = createNetworkSpecForHostOnlyNATNICs(natIfaceCard, hostOnlyIfaceCard); NetworkSpec networkSpec = createNetworkSpecForHostOnlyNATNICs(natIfaceCard, hostOnlyIfaceCard);
//// // //
// CASE BRIDGED // CASE BRIDGED
//NetworkSpec networkSpec = createNetworkSpecForBridgedNIC(); // NetworkSpec networkSpec = createNetworkSpecForBridgedNIC();
CloneSpec cloneSpec = CloneSpec.builder().linked(USE_LINKED) CloneSpec cloneSpec = CloneSpec.builder().linked(USE_LINKED).master(master.getMachine()).network(networkSpec)
.master(master.getMachine()).network(networkSpec) .vm(cloneVmSpec).build();
.vm(cloneVmSpec).build();
IMachine cloned = cloner.apply(cloneSpec); IMachine cloned = cloner.apply(cloneSpec);
new LaunchMachineIfNotAlreadyRunning(manager.get(), ExecutionType.GUI, new LaunchMachineIfNotAlreadyRunning(manager.get(), EXECUTION_TYPE, "").apply(cloned);
"").apply(cloned);
// see DeleteGShadowLock for a detailed explanation
machineUtils
.runScriptOnNode(imachineToNodeMetadata.apply(cloned), new DeleteGShadowLock(), RunScriptOptions.NONE);
// CASE NAT + HOST-ONLY // CASE NAT + HOST-ONLY
machineUtils.runScriptOnNode(imachineToNodeMetadata.apply(cloned), machineUtils.runScriptOnNode(imachineToNodeMetadata.apply(cloned), new SetIpAddress(hostOnlyIfaceCard),
new SetIpAddress(hostOnlyIfaceCard), RunScriptOptions.NONE); 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 return nodeAndInitialCredentials;
// IMachineToSshClient) }
NodeAndInitialCredentials<IMachine> nodeAndInitialCredentials = new NodeAndInitialCredentials<IMachine>(
cloned, cloneName, LoginCredentials.builder().user("toor")
.password("password").authenticateSudo(true).build());
return nodeAndInitialCredentials; private NetworkSpec createNetworkSpecForHostOnlyNATNICs(NetworkInterfaceCard natIfaceCard,
} NetworkInterfaceCard hostOnlyIfaceCard) {
return NetworkSpec.builder().addNIC(natIfaceCard).addNIC(hostOnlyIfaceCard).build();
}
private NetworkSpec createNetworkSpecForHostOnlyNATNICs(NetworkInterfaceCard natIfaceCard, NetworkInterfaceCard hostOnlyIfaceCard) { private NetworkSpec createNetworkSpecForBridgedNIC() {
return NetworkSpec.builder().addNIC(natIfaceCard) List<BridgedIf> activeBridgedInterfaces = new RetrieveActiveBridgedInterfaces(scriptRunnerFactory)
.addNIC(hostOnlyIfaceCard).build(); .apply(hostSupplier.get());
} BridgedIf bridgedActiveInterface = checkNotNull(activeBridgedInterfaces.get(0), "activeBridgedIf");
private NetworkSpec createNetworkSpecForBridgedNIC() { NetworkAdapter bridgedAdapter = NetworkAdapter.builder().networkAttachmentType(NetworkAttachmentType.Bridged)
List<BridgedIf> activeBridgedInterfaces = new RetrieveActiveBridgedInterfaces( .build();
scriptRunnerFactory).apply(hostSupplier.get()); NetworkInterfaceCard bridgedNIC = NetworkInterfaceCard.builder().addNetworkAdapter(bridgedAdapter)
BridgedIf bridgedActiveInterface = checkNotNull( .addHostInterfaceName(bridgedActiveInterface.getName()).slot(0L).build();
activeBridgedInterfaces.get(0), "activeBridgedIf");
NetworkAdapter bridgedAdapter = NetworkAdapter.builder() NetworkSpec networkSpec = NetworkSpec.builder().addNIC(bridgedNIC).build();
.networkAttachmentType(NetworkAttachmentType.Bridged).build(); return networkSpec;
NetworkInterfaceCard bridgedNIC = NetworkInterfaceCard.builder() }
.addNetworkAdapter(bridgedAdapter)
.addHostInterfaceName(bridgedActiveInterface.getName())
.slot(0L).build();
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> { public class TakeSnapshotIfNotAlreadyAttached implements Function<IMachine, ISnapshot> {
@Resource @Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER) @Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL; protected Logger logger = Logger.NULL;
@ -49,7 +48,6 @@ public class TakeSnapshotIfNotAlreadyAttached implements Function<IMachine, ISna
private String snapshotName; private String snapshotName;
private String snapshotDesc; private String snapshotDesc;
public TakeSnapshotIfNotAlreadyAttached(Supplier<VirtualBoxManager> manager, String snapshotName, String snapshotDesc) { public TakeSnapshotIfNotAlreadyAttached(Supplier<VirtualBoxManager> manager, String snapshotName, String snapshotDesc) {
this.manager = manager; this.manager = manager;
this.snapshotName = snapshotName; this.snapshotName = snapshotName;
@ -60,18 +58,34 @@ public class TakeSnapshotIfNotAlreadyAttached implements Function<IMachine, ISna
public ISnapshot apply(@Nullable IMachine machine) { public ISnapshot apply(@Nullable IMachine machine) {
// Snapshot a machine // Snapshot a machine
ISession session = null; ISession session = null;
if(machine.getCurrentSnapshot() == null ) { if (machine.getCurrentSnapshot() == null) {
try { int retries = 10;
session = manager.get().openMachineSession(machine); while (true) {
IProgress progress = session.getConsole().takeSnapshot(snapshotName, snapshotDesc); try {
if (progress.getCompleted()) session = manager.get().openMachineSession(machine);
logger.debug("Snapshot %s (description: %s) taken from %s", snapshotName, snapshotDesc, machine.getName()); IProgress progress = session.getConsole().takeSnapshot(snapshotName, snapshotDesc);
} catch (Exception e) { progress.waitForCompletion(-1);
logger.error(e, "Problem creating snapshot %s (descripton: %s) from machine %s", snapshotName, snapshotDesc, machine.getName()); logger.debug("Snapshot %s (description: %s) taken from %s", snapshotName, snapshotDesc,
Throwables.propagate(e); machine.getName());
assert false; break;
} finally { } catch (Exception e) {
session.unlockMachine(); 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(); return machine.getCurrentSnapshot();

View File

@ -19,35 +19,49 @@
package org.jclouds.virtualbox.functions.admin; package org.jclouds.virtualbox.functions.admin;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.base.Throwables.propagate; import static com.google.common.base.Throwables.propagate;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_PRECONFIGURATION_URL; import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_PRECONFIGURATION_URL;
import java.io.IOException;
import java.net.URI; import java.net.URI;
import javax.annotation.PreDestroy; import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named; 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.Handler;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server; 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.DefaultHandler;
import org.eclipse.jetty.server.handler.HandlerList; import org.eclipse.jetty.server.handler.HandlerList;
import org.eclipse.jetty.server.handler.ResourceHandler; import org.eclipse.jetty.server.handler.ResourceHandler;
import org.eclipse.jetty.util.resource.Resource;
import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.virtualbox.domain.IsoSpec; import org.jclouds.virtualbox.domain.IsoSpec;
import com.google.common.base.Throwables;
import com.google.common.cache.CacheLoader; import com.google.common.cache.CacheLoader;
import com.google.inject.Singleton; 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 @Singleton
public class StartJettyIfNotAlreadyRunning extends CacheLoader<IsoSpec, URI> { public class StartJettyIfNotAlreadyRunning extends CacheLoader<IsoSpec, URI> {
@Resource @javax.annotation.Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER) @Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL; protected Logger logger = Logger.NULL;
private Server jetty; private Server jetty;
@ -60,7 +74,7 @@ public class StartJettyIfNotAlreadyRunning extends CacheLoader<IsoSpec, URI> {
} }
@Override @Override
public URI load(IsoSpec isoSpec) throws Exception { public URI load(IsoSpec isoSpec) throws Exception {
try { try {
start(); start();
} catch (Exception e) { } catch (Exception e) {
@ -74,24 +88,36 @@ public class StartJettyIfNotAlreadyRunning extends CacheLoader<IsoSpec, URI> {
if (jetty.getState().equals(Server.STARTED)) { if (jetty.getState().equals(Server.STARTED)) {
logger.debug("not starting jetty, as existing host is serving %s", preconfigurationUrl); logger.debug("not starting jetty, as existing host is serving %s", preconfigurationUrl);
} else { } 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 { 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(); jetty.start();
} catch (Exception e) { } catch (Exception e) {
logger.error(e, "Server jetty could not be started for %s", preconfigurationUrl); logger.error(e, "Server jetty could not be started for %s", preconfigurationUrl);
throw Throwables.propagate(e);
} }
logger.debug("<< serving %s", resourceHandler.getBaseResource());
} }
} }
@PreDestroy() @PreDestroy()

View File

@ -25,6 +25,7 @@ import static org.jclouds.compute.options.RunScriptOptions.Builder.runAsRoot;
import java.net.URI; import java.net.URI;
import javax.annotation.Nullable;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.inject.Inject; import javax.inject.Inject;
@ -58,8 +59,8 @@ public class StartVBoxIfNotAlreadyRunning implements Supplier<VirtualBoxManager>
private final RetryIfSocketNotYetOpen socketTester; private final RetryIfSocketNotYetOpen socketTester;
private final Supplier<NodeMetadata> host; private final Supplier<NodeMetadata> host;
private final Supplier<URI> providerSupplier; private final Supplier<URI> providerSupplier;
private final String identity; // private final String identity;
private final String credential; // private final String credential;
private final Function<Supplier<NodeMetadata>, VirtualBoxManager> managerForNode; private final Function<Supplier<NodeMetadata>, VirtualBoxManager> managerForNode;
private transient VirtualBoxManager manager; private transient VirtualBoxManager manager;
@ -67,14 +68,15 @@ public class StartVBoxIfNotAlreadyRunning implements Supplier<VirtualBoxManager>
@Inject @Inject
public StartVBoxIfNotAlreadyRunning(Function<Supplier<NodeMetadata>, VirtualBoxManager> managerForNode, public StartVBoxIfNotAlreadyRunning(Function<Supplier<NodeMetadata>, VirtualBoxManager> managerForNode,
Factory runScriptOnNodeFactory, RetryIfSocketNotYetOpen socketTester, Supplier<NodeMetadata> host, 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.runScriptOnNodeFactory = checkNotNull(runScriptOnNodeFactory, "runScriptOnNodeFactory");
this.socketTester = checkNotNull(socketTester, "socketTester"); this.socketTester = checkNotNull(socketTester, "socketTester");
this.socketTester.seconds(3L); this.socketTester.seconds(3L);
this.host = checkNotNull(host, "host"); this.host = checkNotNull(host, "host");
this.providerSupplier = checkNotNull(providerSupplier, "endpoint to virtualbox websrvd is needed"); this.providerSupplier = checkNotNull(providerSupplier, "endpoint to virtualbox websrvd is needed");
this.identity = checkNotNull(identity, "identity"); // this.identity = checkNotNull(identity, "identity");
this.credential = checkNotNull(credential, "credential"); // this.credential = checkNotNull(credential, "credential");
this.managerForNode = checkNotNull(managerForNode, "managerForNode"); this.managerForNode = checkNotNull(managerForNode, "managerForNode");
} }
@ -99,7 +101,7 @@ public class StartVBoxIfNotAlreadyRunning implements Supplier<VirtualBoxManager>
} }
} }
manager = managerForNode.apply(host); manager = managerForNode.apply(host);
manager.connect(provider.toASCIIString(), identity, credential); manager.connect(provider.toASCIIString(), "", "");
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
if (manager.getSessionObject().getState() != SessionState.Unlocked) if (manager.getSessionObject().getState() != SessionState.Unlocked)
logger.warn("manager is not in unlocked state " + manager.getSessionObject().getState()); 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.RunNodesException;
import org.jclouds.compute.domain.ExecResponse; import org.jclouds.compute.domain.ExecResponse;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.logging.slf4j.config.SLF4JLoggingModule; import org.jclouds.logging.slf4j.config.SLF4JLoggingModule;
import org.jclouds.scriptbuilder.statements.login.AdminAccess;
import org.jclouds.ssh.SshClient; import org.jclouds.ssh.SshClient;
import org.jclouds.sshj.config.SshjSshClientModule; import org.jclouds.sshj.config.SshjSshClientModule;
import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeClass;
@ -58,7 +60,7 @@ public class VirtualBoxExperimentLiveTest {
@BeforeClass @BeforeClass
public void setUp() { public void setUp() {
context = new ComputeServiceContextFactory().createContext("virtualbox", "toor", "password", context = new ComputeServiceContextFactory().createContext("virtualbox", "", "",
ImmutableSet.<Module> of(new SLF4JLoggingModule(), new SshjSshClientModule())); ImmutableSet.<Module> of(new SLF4JLoggingModule(), new SshjSshClientModule()));
} }
@ -66,7 +68,8 @@ public class VirtualBoxExperimentLiveTest {
public void testLaunchCluster() throws RunNodesException { public void testLaunchCluster() throws RunNodesException {
int numNodes = 4; int numNodes = 4;
final String clusterName = "test-launch-cluster"; 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"); assertEquals(numNodes, nodes.size(), "wrong number of nodes");
for (NodeMetadata node : nodes) { for (NodeMetadata node : nodes) {
logger.debug("Created Node: %s", node); logger.debug("Created Node: %s", node);