added compute service support and a basic test. fixed template builder bug (see comment).

This commit is contained in:
Alex Yarmula 2010-03-06 10:34:12 -08:00
parent c76ebb43bb
commit eff1de764c
12 changed files with 492 additions and 42 deletions

View File

@ -128,7 +128,8 @@ public class TemplateBuilderImpl implements TemplateBuilder {
if (input.getOsDescription() == null) if (input.getOsDescription() == null)
returnVal = false; returnVal = false;
else else
returnVal = input.getOsDescription().matches(osDescription); returnVal = input.getOsDescription().contains(osDescription) ||
input.getOsDescription().matches(osDescription); /*note: matches() expects a regex!*/
} }
return returnVal; return returnVal;
} }

View File

@ -30,7 +30,7 @@ cloudservers.contextbuilder=org.jclouds.rackspace.cloudservers.CloudServersConte
cloudservers.propertiesbuilder=org.jclouds.rackspace.RackspacePropertiesBuilder cloudservers.propertiesbuilder=org.jclouds.rackspace.RackspacePropertiesBuilder
bluelock.contextbuilder=org.jclouds.vcloud.bluelock.BlueLockVCloudContextBuilder bluelock.contextbuilder=org.jclouds.vcloud.bluelock.BlueLockVCloudContextBuilder
bluelock.propertiesbuilder=org.jclouds.vcloud.bluelock.BlueLockVCloudPropertiesBuilder bluelock.propertiesbuilder=org.jclouds.vcloud.bluelock.BlueLockVCloudPropertiesBuilder
gogrid.propertiesbuilder=org.jclouds.gogrid.GoGridContextBuilder gogrid.propertiesbuilder=org.jclouds.gogrid.GoGridPropertiesBuilder
gogrid.contextbuilder=org.jclouds.gogrid.GoGridPropertiesBuilder gogrid.contextbuilder=org.jclouds.gogrid.GoGridContextBuilder
# example of where to change your endpoint # example of where to change your endpoint
# bluelock.endpoint=https://express3.bluelock.com/api # bluelock.endpoint=https://express3.bluelock.com/api

View File

@ -49,8 +49,6 @@ public class GoGridContextBuilder extends ComputeServiceContextBuilder<GoGridAsy
super(new TypeLiteral<GoGridAsyncClient>() { super(new TypeLiteral<GoGridAsyncClient>() {
}, new TypeLiteral<GoGridClient>() { }, new TypeLiteral<GoGridClient>() {
}, props); }, props);
checkNotNull(properties.getProperty(GoGridConstants.PROPERTY_GOGRID_USER));
checkNotNull(properties.getProperty(GoGridConstants.PROPERTY_GOGRID_PASSWORD));
} }
protected void addClientModule(List<Module> modules) { protected void addClientModule(List<Module> modules) {

View File

@ -42,10 +42,10 @@ import com.google.inject.Module;
* <p/> * <p/>
* If no <code>Module</code>s are specified, the default {@link JDKLoggingModule logging} and * If no <code>Module</code>s are specified, the default {@link JDKLoggingModule logging} and
* {@link JavaUrlHttpCommandExecutorServiceModule http transports} will be installed. * {@link JavaUrlHttpCommandExecutorServiceModule http transports} will be installed.
* *
* @author Adrian Cole * @author Adrian Cole
* @author Oleksiy Yarmula * @author Oleksiy Yarmula
* *
* @see RestContext * @see RestContext
* @see GridServerClient * @see GridServerClient
* @see GridServerAsyncClient * @see GridServerAsyncClient

View File

@ -19,31 +19,53 @@
package org.jclouds.gogrid.config; package org.jclouds.gogrid.config;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.collect.ImmutableList; import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableMap; import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.*;
import com.google.common.collect.Iterables;
import com.google.inject.Provides; import com.google.inject.Provides;
import com.google.inject.TypeLiteral; import com.google.inject.TypeLiteral;
import org.jclouds.Constants;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.domain.*; import org.jclouds.compute.domain.*;
import org.jclouds.compute.domain.internal.ImageImpl;
import org.jclouds.compute.domain.internal.NodeMetadataImpl; import org.jclouds.compute.domain.internal.NodeMetadataImpl;
import org.jclouds.compute.domain.internal.SizeImpl;
import org.jclouds.compute.internal.ComputeServiceContextImpl;
import org.jclouds.compute.predicates.RunScriptRunning;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.strategy.*; import org.jclouds.compute.strategy.*;
import org.jclouds.domain.Credentials; import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationScope;
import org.jclouds.domain.internal.LocationImpl;
import org.jclouds.gogrid.GoGridAsyncClient;
import org.jclouds.gogrid.GoGridClient; import org.jclouds.gogrid.GoGridClient;
import org.jclouds.gogrid.domain.Ip; import org.jclouds.gogrid.domain.Ip;
import org.jclouds.gogrid.domain.PowerCommand; import org.jclouds.gogrid.domain.PowerCommand;
import org.jclouds.gogrid.domain.Server; import org.jclouds.gogrid.domain.Server;
import org.jclouds.gogrid.domain.ServerImage;
import org.jclouds.gogrid.predicates.ServerLatestJobCompleted; import org.jclouds.gogrid.predicates.ServerLatestJobCompleted;
import org.jclouds.logging.Logger;
import org.jclouds.predicates.RetryablePredicate; import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.rest.RestContext;
import org.jclouds.ssh.SshClient;
import javax.annotation.Resource;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
@ -74,19 +96,16 @@ public class GoGridComputeServiceContextModule extends GoGridContextModule {
@Singleton @Singleton
public static class GoGridAddNodeWithTagStrategy implements AddNodeWithTagStrategy { public static class GoGridAddNodeWithTagStrategy implements AddNodeWithTagStrategy {
private final GoGridClient client; private final GoGridClient client;
private final Function<String, InetAddress> stringIpToInetAddress;
private final Function<Size, String> sizeToRam; private final Function<Size, String> sizeToRam;
private final Map<String, NodeState> serverStateToNodeState; private final Function<Server, NodeMetadata> serverToNodeMetadata;
private RetryablePredicate<Server> serverLatestJobCompleted; private RetryablePredicate<Server> serverLatestJobCompleted;
@Inject @Inject
protected GoGridAddNodeWithTagStrategy(GoGridClient client, protected GoGridAddNodeWithTagStrategy(GoGridClient client,
Function<String, InetAddress> stringIpToInetAddress, Function<Server, NodeMetadata> serverToNodeMetadata,
Map<String, NodeState> serverStateToNodeState,
Function<Size, String> sizeToRam) { Function<Size, String> sizeToRam) {
this.client = client; this.client = client;
this.stringIpToInetAddress = stringIpToInetAddress; this.serverToNodeMetadata = serverToNodeMetadata;
this.serverStateToNodeState = serverStateToNodeState;
this.sizeToRam = sizeToRam; this.sizeToRam = sizeToRam;
this.serverLatestJobCompleted = new RetryablePredicate<Server>( this.serverLatestJobCompleted = new RetryablePredicate<Server>(
new ServerLatestJobCompleted(client.getJobServices()), new ServerLatestJobCompleted(client.getJobServices()),
@ -100,19 +119,15 @@ public class GoGridComputeServiceContextModule extends GoGridContextModule {
Server addedServer = client.getServerServices().addServer(name, checkNotNull(template.getImage().getId()), Server addedServer = client.getServerServices().addServer(name, checkNotNull(template.getImage().getId()),
sizeToRam.apply(template.getSize()), availableIp.getIp()); sizeToRam.apply(template.getSize()), availableIp.getIp());
serverLatestJobCompleted.apply(addedServer); serverLatestJobCompleted.apply(addedServer);
client.getServerServices().power(addedServer.getName(), PowerCommand.START);
serverLatestJobCompleted.apply(addedServer);
addedServer = Iterables.getOnlyElement( addedServer = Iterables.getOnlyElement(
client.getServerServices().getServersByName(addedServer.getName()) client.getServerServices().getServersByName(addedServer.getName())
); );
return serverToNodeMetadata.apply(addedServer);
NodeMetadata node = new NodeMetadataImpl(String.valueOf(addedServer.getId()), addedServer.getName(),
template.getLocation().getId(), null, ImmutableMap.<String, String> of(), tag,
serverStateToNodeState.get(addedServer.getState().getName()),
ImmutableSet.<InetAddress>of(stringIpToInetAddress.apply(addedServer.getIp().getIp())),
ImmutableList.<InetAddress> of(), ImmutableMap.<String, String> of(),
/*todo give proper credentials*/ new Credentials("root", ""));
return node;
} }
} }
@Singleton @Singleton
@ -133,6 +148,8 @@ public class GoGridComputeServiceContextModule extends GoGridContextModule {
Server server = Server server =
Iterables.getOnlyElement(client.getServerServices().getServersByName(node.getName())); Iterables.getOnlyElement(client.getServerServices().getServersByName(node.getName()));
client.getServerServices().power(server.getName(), PowerCommand.RESTART); client.getServerServices().power(server.getName(), PowerCommand.RESTART);
serverLatestJobCompleted.apply(server);
client.getServerServices().power(server.getName(), PowerCommand.START);
return serverLatestJobCompleted.apply(server); return serverLatestJobCompleted.apply(server);
} }
} }
@ -205,8 +222,8 @@ public class GoGridComputeServiceContextModule extends GoGridContextModule {
Map<String, NodeState> provideServerToNodeState() { Map<String, NodeState> provideServerToNodeState() {
return ImmutableMap.<String, NodeState> builder() return ImmutableMap.<String, NodeState> builder()
.put("On", NodeState.RUNNING) .put("On", NodeState.RUNNING)
.put("Starting", NodeState.SUSPENDED) .put("Starting", NodeState.PENDING)
.put("Off", NodeState.TERMINATED) .put("Off", NodeState.SUSPENDED)
.put("Saving", NodeState.PENDING) .put("Saving", NodeState.PENDING)
.put("Restarting", NodeState.PENDING) .put("Restarting", NodeState.PENDING)
.put("Stopping", NodeState.PENDING) .put("Stopping", NodeState.PENDING)
@ -236,10 +253,10 @@ public class GoGridComputeServiceContextModule extends GoGridContextModule {
@Override @Override
public String apply(Size size) { public String apply(Size size) {
int ramRequired = size.getRam(); int ramRequired = size.getRam();
if(ramRequired > 8 * 1024) return "8GB"; if(ramRequired >= 8 * 1024) return "8GB";
if(ramRequired > 4 * 1024) return "4GB"; if(ramRequired >= 4 * 1024) return "4GB";
if(ramRequired > 2 * 1024) return "2GB"; if(ramRequired >= 2 * 1024) return "2GB";
if(ramRequired > 1024) return "1GB"; if(ramRequired >= 1024) return "1GB";
return "512MB"; /*smallest*/ return "512MB"; /*smallest*/
} }
}; };
@ -249,19 +266,22 @@ public class GoGridComputeServiceContextModule extends GoGridContextModule {
private static class ServerToNodeMetadata implements Function<Server, NodeMetadata> { private static class ServerToNodeMetadata implements Function<Server, NodeMetadata> {
private final Map<String, NodeState> serverStateToNodeState; private final Map<String, NodeState> serverStateToNodeState;
private final Function<String, InetAddress> stringIpToInetAddress; private final Function<String, InetAddress> stringIpToInetAddress;
private final GoGridClient client;
@Inject @Inject
ServerToNodeMetadata(Map<String, NodeState> serverStateToNodeState, ServerToNodeMetadata(Map<String, NodeState> serverStateToNodeState,
Function<String, InetAddress> stringIpToInetAddress) { Function<String, InetAddress> stringIpToInetAddress,
GoGridClient client) {
this.serverStateToNodeState = serverStateToNodeState; this.serverStateToNodeState = serverStateToNodeState;
this.stringIpToInetAddress = stringIpToInetAddress; this.stringIpToInetAddress = stringIpToInetAddress;
this.client = client;
} }
@Override @Override
public NodeMetadata apply(Server from) { public NodeMetadata apply(Server from) {
String locationId = "Unavailable"; String locationId = "Unavailable";
String tag = from.getName(); String tag = from.getName();
Credentials creds = null; //todo use password service to get the password Credentials creds = client.getServerServices().getServerCredentialsList().get(from.getName());
Set<InetAddress> ipSet = Set<InetAddress> ipSet =
ImmutableSet.of(stringIpToInetAddress.apply(from.getIp().getIp())); ImmutableSet.of(stringIpToInetAddress.apply(from.getIp().getIp()));
NodeState state = serverStateToNodeState.get(from.getState().getName()); NodeState state = serverStateToNodeState.get(from.getState().getName());
@ -274,5 +294,128 @@ public class GoGridComputeServiceContextModule extends GoGridContextModule {
} }
} }
@Provides
@Singleton
ComputeServiceContext provideContext(ComputeService computeService,
RestContext<GoGridAsyncClient, GoGridClient> context) {
return new ComputeServiceContextImpl<GoGridAsyncClient, GoGridClient>(
computeService, context);
}
@Provides
@Singleton
@Named("NOT_RUNNING")
protected Predicate<SshClient> runScriptRunning(RunScriptRunning stateRunning) {
return new RetryablePredicate<SshClient>(Predicates.not(stateRunning), 600, 3,
TimeUnit.SECONDS);
}
@Provides
@Singleton
Location getDefaultLocation(Map<String, ? extends Location> locations) {
return locations.get("SANJOSE");
}
@Provides
@Singleton
Map<String, ? extends Location> getDefaultLocations(GoGridClient sync, LogHolder holder,
Function<ComputeMetadata, String> indexer) {
final Set<Location> locations = Sets.newHashSet();
holder.logger.debug(">> providing empty locations because gogrid doesnt have any");
locations.add(new LocationImpl(LocationScope.REGION, "SANJOSE", "GoGrid doesnt support locations so using " +
"a made up one to comply with API", "Santa Clara County", true));
holder.logger.debug("<< locations(%d)", locations.size());
return Maps.uniqueIndex(locations, new Function<Location, String>() {
@Override
public String apply(Location from) {
return from.getId();
}
});
}
@Provides
@Singleton
protected Function<ComputeMetadata, String> indexer() {
return new Function<ComputeMetadata, String>() {
@Override
public String apply(ComputeMetadata from) {
return from.getId();
}
};
}
@Provides
@Singleton
protected Map<String, ? extends Size> provideSizes(GoGridClient sync,
Map<String, ? extends Image> images, LogHolder holder,
Function<ComputeMetadata, String> indexer) throws InterruptedException,
TimeoutException, ExecutionException {
final Set<Size> sizes = Sets.newHashSet();
holder.logger.debug(">> providing sizes");
sizes.add(new SizeImpl("1", "1", null, null,
ImmutableMap.<String, String> of(), 0, 512, 0,
ImmutableSet.<Architecture> of(Architecture.X86_32,
Architecture.X86_64)));
sizes.add(new SizeImpl("2", "2", null, null,
ImmutableMap.<String, String> of(), 0, 1024, 0,
ImmutableSet.<Architecture> of(Architecture.X86_32,
Architecture.X86_64)));
sizes.add(new SizeImpl("3", "3", null, null,
ImmutableMap.<String, String> of(), 0, 2048, 0,
ImmutableSet.<Architecture> of(Architecture.X86_32,
Architecture.X86_64)));
sizes.add(new SizeImpl("4", "4", null, null,
ImmutableMap.<String, String> of(), 0, 4096, 0,
ImmutableSet.<Architecture> of(Architecture.X86_32,
Architecture.X86_64)));
sizes.add(new SizeImpl("5", "5", null, null,
ImmutableMap.<String, String> of(), 0, 8192, 0,
ImmutableSet.<Architecture> of(Architecture.X86_32,
Architecture.X86_64)));
holder.logger.debug("<< sizes(%d)", sizes.size());
return Maps.uniqueIndex(sizes, indexer);
}
private static class LogHolder {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
}
public static final Pattern GOGRID_PATTERN = Pattern.compile("([a-zA-Z]*)(.*)");
@Provides
@Singleton
protected Map<String, ? extends Image> provideImages(final GoGridClient sync,
LogHolder holder, Function<ComputeMetadata, String> indexer)
throws InterruptedException, ExecutionException, TimeoutException {
final Set<Image> images = Sets.newHashSet();
holder.logger.debug(">> providing images");
Set<ServerImage> allImages = sync.getImageServices().getImageList();
for (ServerImage from : allImages) {
OsFamily os = null;
Architecture arch = from.getDescription().indexOf("64") == -1 ? Architecture.X86_32
: Architecture.X86_64;
String osDescription;
String version = "";
osDescription = from.getOs().getName();
Matcher matcher = GOGRID_PATTERN.matcher(from.getOs().getName());
if (matcher.find()) {
try {
os = OsFamily.fromValue(matcher.group(1).toLowerCase());
} catch (IllegalArgumentException e) {
holder.logger.debug("<< didn't match os(%s)", matcher.group(2));
}
}
images.add(new ImageImpl(from.getName(), from.getDescription(), null, null, ImmutableMap
.<String, String> of(), from.getDescription(), version, os, osDescription, arch));
}
holder.logger.debug("<< images(%d)", images.size());
return Maps.uniqueIndex(images, indexer);
}
} }

View File

@ -41,6 +41,7 @@
*/ */
package org.jclouds.gogrid.config; package org.jclouds.gogrid.config;
import java.net.InetSocketAddress;
import java.net.URI; import java.net.URI;
import java.util.Map; import java.util.Map;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -48,6 +49,7 @@ import java.util.concurrent.TimeUnit;
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import org.jclouds.Constants; import org.jclouds.Constants;
@ -63,6 +65,8 @@ import org.jclouds.http.RequiresHttp;
import org.jclouds.http.annotation.ClientError; import org.jclouds.http.annotation.ClientError;
import org.jclouds.http.annotation.Redirection; import org.jclouds.http.annotation.Redirection;
import org.jclouds.http.annotation.ServerError; import org.jclouds.http.annotation.ServerError;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.predicates.SocketOpen;
import org.jclouds.rest.ConfiguresRestClient; import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.RestClientFactory; import org.jclouds.rest.RestClientFactory;
@ -168,6 +172,12 @@ public class GoGridRestClientModule extends AbstractModule {
return cache.get(); return cache.get();
} }
@Provides
@Singleton
protected Predicate<InetSocketAddress> socketTester(SocketOpen open) {
return new RetryablePredicate<InetSocketAddress>(open, 130, 1, TimeUnit.SECONDS);
}
@Provides @Provides
@Singleton @Singleton
@com.google.inject.name.Named(Constants.PROPERTY_GSON_ADAPTERS) @com.google.inject.name.Named(Constants.PROPERTY_GSON_ADAPTERS)
@ -184,7 +194,7 @@ public class GoGridRestClientModule extends AbstractModule {
bindings.put(ServerImageType.class, new CustomDeserializers.ServerImageTypeAdapter()); bindings.put(ServerImageType.class, new CustomDeserializers.ServerImageTypeAdapter());
return bindings; return bindings;
} }
/** /**
* borrowing concurrency code to ensure that caching takes place properly * borrowing concurrency code to ensure that caching takes place properly
@ -202,11 +212,11 @@ public class GoGridRestClientModule extends AbstractModule {
protected void bindErrorHandlers() { protected void bindErrorHandlers() {
bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to( bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(
GoGridErrorHandler.class); GoGridErrorHandler.class);
bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to( bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(
GoGridErrorHandler.class); GoGridErrorHandler.class);
bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to( bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(
GoGridErrorHandler.class); GoGridErrorHandler.class);
} }
protected void bindRetryHandlers() { protected void bindRetryHandlers() {

View File

@ -0,0 +1,117 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.gogrid.functions;
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;
import com.google.gson.reflect.TypeToken;
import com.google.inject.internal.ImmutableMap;
import org.jclouds.domain.Credentials;
import org.jclouds.gogrid.domain.Server;
import org.jclouds.gogrid.domain.internal.GenericResponseContainer;
import org.jclouds.http.functions.ParseJson;
import javax.annotation.Nullable;
import javax.inject.Inject;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
import java.util.SortedSet;
/**
* @author Oleksiy Yarmula
*/
public class ParseServerNameToCredentialsMapFromJsonResponse extends ParseJson<Map<String, Credentials>> {
@Inject
public ParseServerNameToCredentialsMapFromJsonResponse(Gson gson) {
super(gson);
}
public Map<String, Credentials> apply(InputStream stream) {
Type setType = new TypeToken<GenericResponseContainer<Password>>() {
}.getType();
GenericResponseContainer<Password> response;
try {
response = gson.fromJson(new InputStreamReader(stream, "UTF-8"), setType);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("jclouds requires UTF-8 encoding", e);
}
Map<String, Credentials> serverNameToCredentials = Maps.newHashMap();
for(Password password : response.getList()) {
serverNameToCredentials.put(password.getServer().getName(),
new Credentials(password.getUserName(), password.getPassword()));
}
return serverNameToCredentials;
}
public static class Password implements Comparable<Password> {
@SerializedName("username")
private String userName;
private String password;
private Server server;
public String getUserName() {
return userName;
}
public String getPassword() {
return password;
}
public Server getServer() {
return server;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Password password1 = (Password) o;
if (password != null ? !password.equals(password1.password) : password1.password != null) return false;
if (server != null ? !server.equals(password1.server) : password1.server != null) return false;
if (userName != null ? !userName.equals(password1.userName) : password1.userName != null) return false;
return true;
}
@Override
public int hashCode() {
int result = userName != null ? userName.hashCode() : 0;
result = 31 * result + (password != null ? password.hashCode() : 0);
result = 31 * result + (server != null ? server.hashCode() : 0);
return result;
}
@Override
public int compareTo(Password o) {
return userName.compareTo(o.getUserName());
}
}
}

View File

@ -29,6 +29,7 @@ import javax.ws.rs.GET;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.QueryParam; import javax.ws.rs.QueryParam;
import org.jclouds.domain.Credentials;
import org.jclouds.gogrid.GoGrid; import org.jclouds.gogrid.GoGrid;
import org.jclouds.gogrid.binders.BindIdsToQueryParams; import org.jclouds.gogrid.binders.BindIdsToQueryParams;
import org.jclouds.gogrid.binders.BindNamesToQueryParams; import org.jclouds.gogrid.binders.BindNamesToQueryParams;
@ -37,10 +38,12 @@ import org.jclouds.gogrid.domain.Server;
import org.jclouds.gogrid.filters.SharedKeyLiteAuthentication; import org.jclouds.gogrid.filters.SharedKeyLiteAuthentication;
import org.jclouds.gogrid.functions.ParseServerFromJsonResponse; import org.jclouds.gogrid.functions.ParseServerFromJsonResponse;
import org.jclouds.gogrid.functions.ParseServerListFromJsonResponse; import org.jclouds.gogrid.functions.ParseServerListFromJsonResponse;
import org.jclouds.gogrid.functions.ParseServerNameToCredentialsMapFromJsonResponse;
import org.jclouds.gogrid.options.AddServerOptions; import org.jclouds.gogrid.options.AddServerOptions;
import org.jclouds.gogrid.options.GetServerListOptions; import org.jclouds.gogrid.options.GetServerListOptions;
import org.jclouds.rest.annotations.*; import org.jclouds.rest.annotations.*;
import java.util.Map;
import java.util.Set; import java.util.Set;
import static org.jclouds.gogrid.reference.GoGridQueryParams.*; import static org.jclouds.gogrid.reference.GoGridQueryParams.*;
@ -84,6 +87,14 @@ public interface GridServerAsyncClient {
@Path("/grid/server/get") @Path("/grid/server/get")
ListenableFuture<Set<Server>> getServersById(@BinderParam(BindIdsToQueryParams.class) Long... ids); ListenableFuture<Set<Server>> getServersById(@BinderParam(BindIdsToQueryParams.class) Long... ids);
/**
* @see GridServerClient#getServerCredentialsList
*/
@GET
@ResponseParser(ParseServerNameToCredentialsMapFromJsonResponse.class)
@Path("/support/password/list")
ListenableFuture<Map<String, Credentials>> getServerCredentialsList();
/** /**
* @see GridServerClient#addServer(String, String, String, String, org.jclouds.gogrid.options.AddServerOptions...) * @see GridServerClient#addServer(String, String, String, String, org.jclouds.gogrid.options.AddServerOptions...)
*/ */

View File

@ -23,10 +23,12 @@
*/ */
package org.jclouds.gogrid.services; package org.jclouds.gogrid.services;
import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.jclouds.concurrent.Timeout; import org.jclouds.concurrent.Timeout;
import org.jclouds.domain.Credentials;
import org.jclouds.gogrid.domain.PowerCommand; import org.jclouds.gogrid.domain.PowerCommand;
import org.jclouds.gogrid.domain.Server; import org.jclouds.gogrid.domain.Server;
import org.jclouds.gogrid.options.AddServerOptions; import org.jclouds.gogrid.options.AddServerOptions;
@ -74,6 +76,13 @@ public interface GridServerClient {
*/ */
Set<Server> getServersById(Long... ids); Set<Server> getServersById(Long... ids);
/**
* Returns a map of running servers' names to the
* log in credentials.
* @return map <String server name => Credentials>
*/
Map<String, Credentials> getServerCredentialsList();
/** /**
* Adds a server with specified attributes * Adds a server with specified attributes
* *

View File

@ -0,0 +1,78 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.gogrid;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.ComputeServiceContextFactory;
import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.Template;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.ssh.jsch.config.JschSshClientModule;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import static org.testng.Assert.*;
import java.io.IOException;
import java.util.Map;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* @author Oleksiy Yarmula
*/
public class GoGridComputeServiceLiveTest {
private ComputeServiceContext context;
@BeforeTest
public void setupClient() throws IOException {
String user = checkNotNull(System.getProperty("jclouds.test.user"), "jclouds.test.user");
String password = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key");
context = new ComputeServiceContextFactory().createContext("gogrid", user, password,
ImmutableSet.of(new Log4JLoggingModule(), new JschSshClientModule()));
}
@Test(enabled=false)
public void endToEndComputeServiceTest() {
ComputeService service = context.getComputeService();
Template t = service.templateBuilder().minRam(1024).imageId("GSI-6890f8b6-c8fb-4ac1-bc33-2563eb4e29d2").build();
assertEquals(t.getImage().getId(), "GSI-6890f8b6-c8fb-4ac1-bc33-2563eb4e29d2");
service.runNodesWithTag("testTag", 1, t);
Map<String, ? extends ComputeMetadata> nodes = service.getNodes();
assertEquals(nodes.size(), 1);
NodeMetadata nodeMetadata = service.getNodeMetadata(Iterables.getOnlyElement(nodes.values()));
assertEquals(nodeMetadata.getPublicAddresses().size(), 1, "There must be 1 public address for the node");
assertTrue(nodeMetadata.getName().startsWith("testTag"));
service.rebootNode(nodeMetadata); // blocks until finished
assertEquals(service.getNodeMetadata(nodeMetadata).getState(), NodeState.RUNNING);
service.destroyNode(nodeMetadata);
}
}

View File

@ -20,6 +20,7 @@ package org.jclouds.gogrid;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import org.jclouds.domain.Credentials;
import org.jclouds.gogrid.domain.*; import org.jclouds.gogrid.domain.*;
import org.jclouds.gogrid.options.AddLoadBalancerOptions; import org.jclouds.gogrid.options.AddLoadBalancerOptions;
import org.jclouds.gogrid.options.GetImageListOptions; import org.jclouds.gogrid.options.GetImageListOptions;
@ -28,6 +29,9 @@ import org.jclouds.gogrid.predicates.LoadBalancerLatestJobCompleted;
import org.jclouds.gogrid.predicates.ServerLatestJobCompleted; import org.jclouds.gogrid.predicates.ServerLatestJobCompleted;
import org.jclouds.logging.log4j.config.Log4JLoggingModule; import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.predicates.RetryablePredicate; import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.predicates.SocketOpen;
import org.jclouds.ssh.SshClient;
import org.jclouds.ssh.jsch.JschSshClient;
import org.testng.SkipException; import org.testng.SkipException;
import org.testng.TestException; import org.testng.TestException;
import org.testng.annotations.AfterTest; import org.testng.annotations.AfterTest;
@ -35,6 +39,9 @@ import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.*; import java.util.*;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -271,6 +278,50 @@ public class GoGridLiveTest {
} }
@Test(enabled=false)
private void testShellAccess() throws IOException {
final String nameOfServer = "Server" + String.valueOf(new Date().getTime()).substring(6);
serversToDeleteAfterTheTests.add(nameOfServer);
Set<Ip> availableIps = client.getIpServices().getUnassignedIpList();
Ip availableIp = Iterables.getLast(availableIps);
Server createdServer = client.getServerServices().addServer(nameOfServer,
"GSI-f8979644-e646-4711-ad58-d98a5fa3612c",
"1",
availableIp.getIp());
assertNotNull(createdServer);
assert serverLatestJobCompleted.apply(createdServer);
//get server by name
Set<Server> response = client.getServerServices().getServersByName(nameOfServer);
assert (response.size() == 1);
createdServer = Iterables.getOnlyElement(response);
Map<String, Credentials> credsMap = client.getServerServices().getServerCredentialsList();
Credentials instanceCredentials = credsMap.get(createdServer.getName());
assertNotNull(instanceCredentials);
InetSocketAddress socket = new InetSocketAddress(InetAddress.getByName(createdServer.getIp().getIp()), 22);
Predicate<InetSocketAddress> socketOpen =
new RetryablePredicate<InetSocketAddress>(new SocketOpen(), 180, 5, TimeUnit.SECONDS);
socketOpen.apply(socket);
SshClient sshClient =
new JschSshClient(socket, 60000,
instanceCredentials.account, instanceCredentials.key);
sshClient.connect();
String output = sshClient.exec("df").getOutput();
assertTrue(output.contains("Filesystem"),
"The output should've contained filesystem information, but it didn't. Output: " + output);
sshClient.disconnect();
//delete the server
client.getServerServices().deleteByName(nameOfServer);
}
/** /**
* In case anything went wrong during the tests, removes the objects * In case anything went wrong during the tests, removes the objects
* created in the tests. * created in the tests.

View File

@ -28,6 +28,32 @@
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"
debug="false"> debug="false">
<!-- A time/date based rolling appender -->
<appender name="COMPUTEFILE" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="target/test-data/jclouds-compute.log" />
<param name="Append" value="true" />
<!-- Rollover at midnight each day -->
<param name="DatePattern" value="'.'yyyy-MM-dd" />
<param name="Threshold" value="TRACE" />
<layout class="org.apache.log4j.PatternLayout">
<!-- The default pattern: Date Priority [Category] Message\n -->
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n" />
<!--
The full pattern: Date MS Priority [Category]
(Thread:NDC) Message\n <param name="ConversionPattern"
value="%d %-5r %-5p [%c] (%t:%x) %m%n"/>
-->
</layout>
</appender>
<appender name="ASYNCCOMPUTE" class="org.apache.log4j.AsyncAppender">
<appender-ref ref="COMPUTEFILE" />
</appender>
<!-- A time/date based rolling appender --> <!-- A time/date based rolling appender -->
<appender name="WIREFILE" class="org.apache.log4j.DailyRollingFileAppender"> <appender name="WIREFILE" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="target/test-data/jclouds-wire.log" /> <param name="File" value="target/test-data/jclouds-wire.log" />
@ -92,14 +118,20 @@
<category name="jclouds.headers"> <category name="jclouds.headers">
<priority value="DEBUG" /> <priority value="DEBUG" />
<appender-ref ref="ASYNCWIRE" /> <appender-ref ref="ASYNCWIRE" />
</category><!-- </category>
<category name="jclouds.wire"> <category name="jclouds.wire">
<priority value="DEBUG" /> <priority value="DEBUG" />
<appender-ref ref="ASYNCWIRE" /> <appender-ref ref="ASYNCWIRE" />
</category> </category>
<category name="jclouds.compute">
<priority value="TRACE" />
<appender-ref ref="ASYNCCOMPUTE" />
</category>
--><!-- ======================= --> <!-- ======================= -->
<!-- Setup the Root category --> <!-- Setup the Root category -->
<!-- ======================= --> <!-- ======================= -->