mirror of https://github.com/apache/jclouds.git
merge with upstream master, resolving conflicts in SecurityGroupClientExpectTest
This commit is contained in:
commit
d3f0e64de1
|
@ -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();
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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>> {
|
||||||
|
|
||||||
|
}
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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");
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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";
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -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> {
|
||||||
|
|
||||||
|
}
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
|
@ -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()
|
||||||
|
|
|
@ -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");
|
||||||
|
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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");
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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,
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue