Issue 77: added shared ip functionality

git-svn-id: http://jclouds.googlecode.com/svn/trunk@1827 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
adrian.f.cole 2009-07-21 17:02:05 +00:00
parent feb0385c0a
commit 8d124e8b7e
18 changed files with 875 additions and 39 deletions

View File

@ -23,6 +23,7 @@
*/
package org.jclouds.rackspace.cloudservers;
import java.net.InetAddress;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
@ -37,14 +38,19 @@ import javax.ws.rs.PathParam;
import org.jclouds.http.functions.ReturnFalseOn404;
import org.jclouds.rackspace.cloudservers.binders.ChangeAdminPassBinder;
import org.jclouds.rackspace.cloudservers.binders.ChangeServerNameBinder;
import org.jclouds.rackspace.cloudservers.binders.ShareIpBinder;
import org.jclouds.rackspace.cloudservers.domain.Addresses;
import org.jclouds.rackspace.cloudservers.domain.Flavor;
import org.jclouds.rackspace.cloudservers.domain.Image;
import org.jclouds.rackspace.cloudservers.domain.Server;
import org.jclouds.rackspace.cloudservers.domain.SharedIpGroup;
import org.jclouds.rackspace.cloudservers.functions.IpAddress;
import org.jclouds.rackspace.cloudservers.functions.ParseAddressesFromGsonResponse;
import org.jclouds.rackspace.cloudservers.functions.ParseFlavorFromGsonResponse;
import org.jclouds.rackspace.cloudservers.functions.ParseFlavorListFromGsonResponse;
import org.jclouds.rackspace.cloudservers.functions.ParseImageFromGsonResponse;
import org.jclouds.rackspace.cloudservers.functions.ParseImageListFromGsonResponse;
import org.jclouds.rackspace.cloudservers.functions.ParseInetAddressListFromGsonResponse;
import org.jclouds.rackspace.cloudservers.functions.ParseServerFromGsonResponse;
import org.jclouds.rackspace.cloudservers.functions.ParseServerListFromGsonResponse;
import org.jclouds.rackspace.cloudservers.functions.ParseSharedIpGroupFromGsonResponse;
@ -59,8 +65,9 @@ import org.jclouds.rackspace.cloudservers.options.ListOptions;
import org.jclouds.rackspace.filters.AuthenticateRequest;
import org.jclouds.rest.EntityParam;
import org.jclouds.rest.ExceptionParser;
import org.jclouds.rest.PostBinder;
import org.jclouds.rest.PostParam;
import org.jclouds.rest.MapBinder;
import org.jclouds.rest.MapEntityParam;
import org.jclouds.rest.ParamParser;
import org.jclouds.rest.Query;
import org.jclouds.rest.RequestFilters;
import org.jclouds.rest.ResponseParser;
@ -163,11 +170,61 @@ public interface CloudServersConnection {
@ResponseParser(ParseServerFromGsonResponse.class)
@Query(key = "format", value = "json")
@Path("/servers")
@PostBinder(CreateServerOptions.class)
@MapBinder(CreateServerOptions.class)
// TODO:cloudServersFault (400, 500), serviceUnavailable (503), unauthorized (401),
// badMediaType(415), badRequest (400), serverCapacityUnavailable (503), overLimit (413)
Server createServer(@PostParam("name") String name, @PostParam("imageId") int imageId,
@PostParam("flavorId") int flavorId, CreateServerOptions... options);
Server createServer(@MapEntityParam("name") String name, @MapEntityParam("imageId") int imageId,
@MapEntityParam("flavorId") int flavorId, CreateServerOptions... options);
/**
* /** This operation allows you share an IP address to the specified server
* <p/>
* This operation shares an IP from an existing server in the specified shared IP group to
* another specified server in the same group. The operation modifies cloud network restrictions
* to allow IP traffic for the given IP to/from the server specified.
*
* <p/>
* Status Transition: ACTIVE - SHARE_IP - ACTIVE (if configureServer is true) ACTIVE -
* SHARE_IP_NO_CONFIG - ACTIVE
*
* @param configureServer
* <p/>
* if set to true, the server is configured with the new address, though the address is
* not enabled. Note that configuring the server does require a reboot.
* <p/>
* If set to false, does not bind the IP to the server itself. A heartbeat facility
* (e.g. keepalived) can then be used within the servers to perform health checks and
* manage IP failover.
* @return false if the server is not found
*/
@PUT
@ExceptionParser(ReturnFalseOn404.class)
@Path("/servers/{id}/ips/public/{address}")
@MapBinder(ShareIpBinder.class)
// TODO: cloudServersFault (400, 500), serviceUnavailable (503), unauthorized (401), badRequest
// (400), badMediaType(415), buildInProgress (409), overLimit (413)
boolean shareIp(@PathParam("address") @ParamParser(IpAddress.class) InetAddress addressToShare,
@PathParam("id") int serverToAssignAddressTo,
@MapEntityParam("sharedIpGroupId") int sharedIpGroup,
@MapEntityParam("configureServer") boolean configureServer);
/**
* This operation removes a shared IP address from the specified server.
* <p/>
* Status Transition: ACTIVE - DELETE_IP - ACTIVE
*
* @param addressToShare
* @param serverToAssignAddressTo
* @return
*/
@DELETE
@ExceptionParser(ReturnFalseOn404.class)
@Path("/servers/{id}/ips/public/{address}")
// TODO: cloudServersFault (400, 500), serviceUnavailable (503), unauthorized(401), badRequest (400),
// badMediaType(415), overLimit (413)
boolean unshareIp(
@PathParam("address") @ParamParser(IpAddress.class) InetAddress addressToShare,
@PathParam("id") int serverToAssignAddressTo);
/**
* This operation allows you to change the administrative password.
@ -303,10 +360,10 @@ public interface CloudServersConnection {
@ResponseParser(ParseSharedIpGroupFromGsonResponse.class)
@Query(key = "format", value = "json")
@Path("/shared_ip_groups")
@PostBinder(CreateSharedIpGroupOptions.class)
@MapBinder(CreateSharedIpGroupOptions.class)
// TODO: cloudSharedIpGroupsFault (400, 500), serviceUnavailable (503), unauthorized (401),
// badRequest (400), badMediaType(415), overLimit (413)
SharedIpGroup createSharedIpGroup(@PostParam("name") String name,
SharedIpGroup createSharedIpGroup(@MapEntityParam("name") String name,
CreateSharedIpGroupOptions... options);
/**
@ -323,4 +380,38 @@ public interface CloudServersConnection {
// TODO:cloudServersFault (400, 500), serviceUnavailable (503), unauthorized (401), badRequest
// (400)
boolean deleteSharedIpGroup(@PathParam("id") int id);
/**
* List all server addresses
*/
@GET
@ResponseParser(ParseAddressesFromGsonResponse.class)
@Query(key = "format", value = "json")
@Path("/servers/{id}/ips")
// TODO: cloudServersFault (400, 500), serviceUnavailable (503), unauthorized (401), badRequest
// (400), overLimit (413)
Addresses listAddresses(@PathParam("id") int serverId);
/**
* List all public server addresses
*/
@GET
@ResponseParser(ParseInetAddressListFromGsonResponse.class)
@Query(key = "format", value = "json")
@Path("/servers/{id}/ips/public")
// TODO: cloudServersFault (400, 500), serviceUnavailable (503), unauthorized (401), badRequest
// (400), overLimit (413)
List<InetAddress> listPublicAddresses(@PathParam("id") int serverId);
/**
* List all private server addresses
*/
@GET
@ResponseParser(ParseInetAddressListFromGsonResponse.class)
@Query(key = "format", value = "json")
@Path("/servers/{id}/ips/private")
// TODO: cloudServersFault (400, 500), serviceUnavailable (503), unauthorized (401), badRequest
// (400), overLimit (413)
List<InetAddress> listPrivateAddresses(@PathParam("id") int serverId);
}

View File

@ -1,3 +1,26 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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.rackspace.cloudservers.binders;
import static com.google.common.base.Preconditions.checkArgument;

View File

@ -1,3 +1,26 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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.rackspace.cloudservers.binders;
import static com.google.common.base.Preconditions.checkArgument;

View File

@ -0,0 +1,67 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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.rackspace.cloudservers.binders;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.binders.JsonBinder;
import com.google.common.collect.ImmutableMap;
/**
*
* @author Adrian Cole
*
*/
public class ShareIpBinder extends JsonBinder {
@SuppressWarnings("unused")
private class ShareIpRequest {
final int sharedIpGroupId;
Boolean configureServer;
private ShareIpRequest(int sharedIpGroupId) {
this.sharedIpGroupId = sharedIpGroupId;
}
}
@Override
public void addEntityToRequest(Map<String, String> postParams, HttpRequest request) {
ShareIpRequest createRequest = new ShareIpRequest(Integer.parseInt(checkNotNull(postParams
.get("sharedIpGroupId"))));
if (Boolean.parseBoolean(checkNotNull(postParams.get("configureServer")))) {
createRequest.configureServer = new Boolean(true);
}
super.addEntityToRequest(ImmutableMap.of("shareIp", createRequest), request);
}
@Override
public void addEntityToRequest(Object toBind, HttpRequest request) {
throw new IllegalStateException("shareIp is needs parameters");
}
}

View File

@ -0,0 +1,36 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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.rackspace.cloudservers.functions;
import java.net.InetAddress;
import com.google.common.base.Function;
public class IpAddress implements Function<Object, String> {
public String apply(Object from) {
return ((InetAddress) from).getHostAddress();
}
}

View File

@ -0,0 +1,60 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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.rackspace.cloudservers.functions;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import org.jclouds.http.functions.ParseJson;
import org.jclouds.rackspace.cloudservers.domain.Addresses;
import com.google.gson.Gson;
import com.google.inject.Inject;
/**
* This parses {@link Addresses} from a gson string.
*
* @author Adrian Cole
*/
public class ParseAddressesFromGsonResponse extends ParseJson<Addresses> {
@Inject
public ParseAddressesFromGsonResponse(Gson gson) {
super(gson);
}
private static class AddressesListResponse {
Addresses addresses;
}
public Addresses apply(InputStream stream) {
try {
return gson.fromJson(new InputStreamReader(stream, "UTF-8"), AddressesListResponse.class).addresses;
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("jclouds requires UTF-8 encoding", e);
}
}
}

View File

@ -0,0 +1,65 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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.rackspace.cloudservers.functions;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Type;
import java.net.InetAddress;
import java.util.List;
import java.util.Map;
import org.jclouds.http.functions.ParseJson;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.google.inject.Inject;
/**
* This parses a list of {@link InetAddress} from a gson string.
*
* @author Adrian Cole
*/
public class ParseInetAddressListFromGsonResponse extends ParseJson<List<InetAddress>> {
@Inject
public ParseInetAddressListFromGsonResponse(Gson gson) {
super(gson);
}
Map<String, List<InetAddress>> addressMap;
public List<InetAddress> apply(InputStream stream) {
Type type = new TypeToken<Map<String, List<InetAddress>>>() {
}.getType();
try {
Map<String, List<InetAddress>> map = gson.fromJson(new InputStreamReader(stream, "UTF-8"),
type);
return map.values().iterator().next();
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("jclouds requires UTF-8 encoding", e);
}
}
}

View File

@ -1,3 +1,26 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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.rackspace.cloudservers.options;
import static com.google.common.base.Preconditions.checkArgument;

View File

@ -1,3 +1,26 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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.rackspace.cloudservers.options;
import static com.google.common.base.Preconditions.checkArgument;

View File

@ -1,3 +1,26 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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.rackspace.cloudservers.options;
import org.jclouds.rackspace.options.BaseListOptions;

View File

@ -25,7 +25,6 @@ package org.jclouds.rackspace.cloudservers;
import static org.jclouds.rackspace.cloudservers.options.CreateServerOptions.Builder.withFile;
import static org.jclouds.rackspace.cloudservers.options.CreateSharedIpGroupOptions.Builder.withServer;
import static org.jclouds.rackspace.cloudservers.options.ListOptions.Builder.withDetails;
import static org.jclouds.rackspace.reference.RackspaceConstants.PROPERTY_RACKSPACE_KEY;
import static org.jclouds.rackspace.reference.RackspaceConstants.PROPERTY_RACKSPACE_USER;
import static org.testng.Assert.assertEquals;
@ -35,6 +34,7 @@ import static org.testng.Assert.assertTrue;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.UndeclaredThrowableException;
import java.net.InetAddress;
import java.security.SecureRandom;
import java.util.List;
import java.util.Map;
@ -46,13 +46,14 @@ import org.jclouds.rackspace.cloudservers.domain.Image;
import org.jclouds.rackspace.cloudservers.domain.Server;
import org.jclouds.rackspace.cloudservers.domain.ServerStatus;
import org.jclouds.rackspace.cloudservers.domain.SharedIpGroup;
import org.jclouds.ssh.ExecResponse;
import org.jclouds.ssh.SshConnection;
import org.jclouds.ssh.SshException;
import org.jclouds.ssh.jsch.config.JschSshConnectionModule;
import org.jclouds.util.Utils;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Injector;
@ -119,8 +120,7 @@ public class CloudServersConnectionLiveTest {
for (Image image : response) {
assertTrue(image.getId() >= 1);
assert null != image.getName() : image;
// sometimes this is not present per: Web Hosting #118820
// assert null != image.getCreated() : image;
assert null != image.getCreated() : image;
assert null != image.getUpdated() : image;
assert null != image.getStatus() : image;
}
@ -266,16 +266,8 @@ public class CloudServersConnectionLiveTest {
}
assertNotNull(sharedIpGroup.getName());
sharedIpGroupId = sharedIpGroup.getId();
assertEquals(sharedIpGroup.getServers(), ImmutableList.of(serverId));
}
@Test(timeOut = 5 * 60 * 1000, dependsOnMethods = { "testCreateSharedIpGroup" })
void testDeleteSharedIpGroup() {
if (sharedIpGroupId > 0) {
connection.deleteSharedIpGroup(sharedIpGroupId);
SharedIpGroup server = connection.getSharedIpGroup(sharedIpGroupId);
assertEquals(server, SharedIpGroup.NOT_FOUND);
}
// Response doesn't include the server id Web Hosting #119311
// assertEquals(sharedIpGroup.getServers(), ImmutableList.of(serverId));
}
private int sharedIpGroupId;
@ -284,6 +276,9 @@ public class CloudServersConnectionLiveTest {
private int serverId;
private String adminPass;
Map<String, String> metadata = ImmutableMap.of("jclouds", "rackspace");
private InetAddress ip;
private int serverId2;
private String adminPass2;
@Test(timeOut = 5 * 60 * 1000)
public void testCreateServer() throws Exception {
@ -305,18 +300,16 @@ public class CloudServersConnectionLiveTest {
assertNotNull(server.getAdminPass());
serverId = server.getId();
adminPass = server.getAdminPass();
ip = server.getAddresses().getPublicAddresses().iterator().next();
assertEquals(server.getStatus(), ServerStatus.BUILD);
blockUntilActive(server);
blockUntilActive(serverId);
}
private void blockUntilActive(Server server) throws InterruptedException {
ServerStatus currentStatus = server.getStatus();
Server currentDetails = server;
while (currentStatus != ServerStatus.ACTIVE) {
private void blockUntilActive(int serverId) throws InterruptedException {
for (Server currentDetails = connection.getServer(serverId); currentDetails.getStatus() != ServerStatus.ACTIVE; currentDetails = connection
.getServer(serverId)) {
System.out.printf("blocking on status active%n%s%n", currentDetails);
Thread.sleep(5 * 1000);
currentDetails = connection.getServer(serverId);
System.out.println(currentDetails);
currentStatus = currentDetails.getStatus();
}
}
@ -330,8 +323,14 @@ public class CloudServersConnectionLiveTest {
assertEquals(new Integer(2), server.getImageId());
assertEquals(new Integer(1), server.getFlavorId());
assertNotNull(server.getAddresses());
// listAddresses tests..
assertEquals(connection.listAddresses(serverId), server.getAddresses());
assertEquals(server.getAddresses().getPublicAddresses().size(), 1);
assertEquals(connection.listPublicAddresses(serverId), server.getAddresses()
.getPublicAddresses());
assertEquals(server.getAddresses().getPrivateAddresses().size(), 1);
assertEquals(connection.listPrivateAddresses(serverId), server.getAddresses()
.getPrivateAddresses());
// check metadata
assertEquals(server.getMetadata(), metadata);
@ -342,6 +341,14 @@ public class CloudServersConnectionLiveTest {
* this tests "personality" as the file looked up was sent during server creation
*/
private void checkPassOk(Server newDetails, String pass) throws IOException {
try {
doCheckPass(newDetails, pass);
} catch (SshException e) {// try twice in case there is a network timeout
doCheckPass(newDetails, pass);
}
}
private void doCheckPass(Server newDetails, String pass) throws IOException {
SshConnection connection = sshFactory.create(newDetails.getAddresses().getPublicAddresses()
.get(0), 22, "root", pass);
try {
@ -355,35 +362,137 @@ public class CloudServersConnectionLiveTest {
}
}
private ExecResponse exec(Server details, String pass, String command) throws IOException {
SshConnection connection = sshFactory.create(details.getAddresses().getPublicAddresses().get(
0), 22, "root", pass);
try {
connection.connect();
return connection.exec(command);
} finally {
if (connection != null)
connection.disconnect();
}
}
@Test(timeOut = 5 * 60 * 1000, dependsOnMethods = "testCreateServer")
public void testRenameServer() throws Exception {
Server server = connection.getServer(serverId);
String oldName = server.getName();
assertTrue(connection.renameServer(serverId, oldName + "new"));
blockUntilActive(server);
blockUntilActive(serverId);
assertEquals(oldName + "new", connection.getServer(serverId).getName());
}
@Test(timeOut = 5 * 60 * 1000, dependsOnMethods = "testCreateServer")
public void testChangePassword() throws Exception {
Server server = connection.getServer(serverId);
assertTrue(connection.changeAdminPass(serverId, "elmo"));
blockUntilActive(server);
blockUntilActive(serverId);
checkPassOk(connection.getServer(serverId), "elmo");
this.adminPass = "elmo";
}
// TODO test createServer.withSharedIpGroup
// TODO test createServer.withSharedIp
@Test(timeOut = 5 * 60 * 1000, dependsOnMethods = "testCreateSharedIpGroup")
public void testCreateServerIp() throws Exception {
int imageId = 2;
int flavorId = 1;
Server server = null;
while (server == null) {
String serverName = serverPrefix + "createserver" + new SecureRandom().nextInt();
try {
server = connection.createServer(serverName, imageId, flavorId, withFile(
"/etc/jclouds.txt", "rackspace".getBytes()).withMetadata(metadata)
.withSharedIpGroup(sharedIpGroupId).withSharedIp(ip));
} catch (UndeclaredThrowableException e) {
HttpResponseException htpe = (HttpResponseException) e.getCause().getCause();
if (htpe.getResponse().getStatusCode() == 400)
continue;
throw e;
}
}
assertNotNull(server.getAdminPass());
serverId2 = server.getId();
adminPass2 = server.getAdminPass();
blockUntilActive(serverId2);
assertIpConfigured(server, adminPass2);
assert server.getAddresses().getPublicAddresses().contains(ip) : server.getAddresses()
+ " doesn't contain " + ip;
assertEquals(server.getSharedIpGroupId(), new Integer(sharedIpGroupId));
}
// must be last!
@Test(timeOut = 5 * 60 * 1000, dependsOnMethods = { "testChangePassword", "testRenameServer" })
void deleteServer() {
private void assertIpConfigured(Server server, String password) {
try {
ExecResponse response = exec(server, password, "ifconfig -a");
assert response.getOutput().indexOf(ip.getHostAddress()) > 0 : String.format(
"server %s didn't get ip %s%n%s", server, ip, response);
} catch (Exception e) {
e.printStackTrace();
} catch (AssertionError e) {
e.printStackTrace();
}
}
@Test(timeOut = 5 * 60 * 1000, dependsOnMethods = "testCreateServerIp")
public void testUnshare() throws Exception {
connection.unshareIp(ip, serverId2);
blockUntilActive(serverId2);
Server server = connection.getServer(serverId2);
assert !server.getAddresses().getPublicAddresses().contains(ip) : server.getAddresses();
assertIpNotConfigured(server, adminPass2);
}
private void assertIpNotConfigured(Server server, String password) {
try {
ExecResponse response = exec(server, password, "ifconfig -a");
assert response.getOutput().indexOf(ip.getHostAddress()) == -1 : String.format(
"server %s still has get ip %s%n%s", server, ip, response);
} catch (Exception e) {
e.printStackTrace();
} catch (AssertionError e) {
e.printStackTrace();
}
}
@Test(timeOut = 5 * 60 * 1000, dependsOnMethods = "testUnshare")
public void testShareConfig() throws Exception {
connection.shareIp(ip, serverId2, sharedIpGroupId, true);
blockUntilActive(serverId2);
Server server = connection.getServer(serverId2);
assert server.getAddresses().getPublicAddresses().contains(ip) : server.getAddresses();
assertIpConfigured(server, adminPass2);
testUnshare();
}
@Test(timeOut = 5 * 60 * 1000, dependsOnMethods = "testShareConfig")
public void testShareNoConfig() throws Exception {
connection.shareIp(ip, serverId2, sharedIpGroupId, false);
blockUntilActive(serverId2);
Server server = connection.getServer(serverId2);
assert server.getAddresses().getPublicAddresses().contains(ip) : server.getAddresses();
assertIpNotConfigured(server, adminPass2);
testUnshare();
}
// must be last!. current order is only positionally guaranteed when in sequential mode.
@Test
void deleteServers() {
if (serverId > 0) {
connection.deleteServer(serverId);
Server server = connection.getServer(serverId);
assertEquals(server, Server.NOT_FOUND);
}
if (serverId2 > 0) {
connection.deleteServer(serverId2);
Server server = connection.getServer(serverId2);
assertEquals(server, Server.NOT_FOUND);
}
}
@Test(timeOut = 5 * 60 * 1000, dependsOnMethods = { "deleteServers" })
void testDeleteSharedIpGroup() {
if (sharedIpGroupId > 0) {
connection.deleteSharedIpGroup(sharedIpGroupId);
SharedIpGroup server = connection.getSharedIpGroup(sharedIpGroupId);
assertEquals(server, SharedIpGroup.NOT_FOUND);
}
}
}

View File

@ -49,10 +49,12 @@ import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.http.functions.ReturnFalseOn404;
import org.jclouds.http.functions.ReturnTrueIf2xx;
import org.jclouds.rackspace.Authentication;
import org.jclouds.rackspace.cloudservers.functions.ParseAddressesFromGsonResponse;
import org.jclouds.rackspace.cloudservers.functions.ParseFlavorFromGsonResponse;
import org.jclouds.rackspace.cloudservers.functions.ParseFlavorListFromGsonResponse;
import org.jclouds.rackspace.cloudservers.functions.ParseImageFromGsonResponse;
import org.jclouds.rackspace.cloudservers.functions.ParseImageListFromGsonResponse;
import org.jclouds.rackspace.cloudservers.functions.ParseInetAddressListFromGsonResponse;
import org.jclouds.rackspace.cloudservers.functions.ParseServerFromGsonResponse;
import org.jclouds.rackspace.cloudservers.functions.ParseServerListFromGsonResponse;
import org.jclouds.rackspace.cloudservers.functions.ParseSharedIpGroupFromGsonResponse;
@ -168,7 +170,7 @@ public class CloudServersConnectionTest {
assertEquals(processor.createResponseParser(method).getClass(),
ParseServerFromGsonResponse.class);
assertEquals(processor.createExceptionParserOrNullIfNotFound(method), null);
assertNotNull(processor.getPostEntityBinderOrNull(method, new Object[] { "", 1, 2,
assertNotNull(processor.getMapEntityBinderOrNull(method, new Object[] { "", 1, 2,
new CreateServerOptions[] { CreateServerOptions.Builder.withSharedIpGroup(1) } }));
}
@ -406,6 +408,65 @@ public class CloudServersConnectionTest {
assertEquals(processor.createResponseParser(method).getClass(), ReturnTrueIf2xx.class);
}
public void testShareIpNoConfig() throws SecurityException, NoSuchMethodException,
UnknownHostException {
Method method = CloudServersConnection.class.getMethod("shareIp", InetAddress.class,
int.class, int.class, boolean.class);
URI endpoint = URI.create("http://localhost");
HttpRequest httpMethod = processor.createRequest(endpoint, method, new Object[] {
InetAddress.getByAddress(new byte[] { 127, 0, 0, 1 }), 2, 3, false });
assertEquals(httpMethod.getEndpoint().getHost(), "localhost");
assertEquals(httpMethod.getEndpoint().getPath(), "/servers/2/ips/public/127.0.0.1");
assertEquals(httpMethod.getMethod(), HttpMethod.PUT);
assertEquals(httpMethod.getHeaders().size(), 2);
assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_LENGTH), Collections
.singletonList(httpMethod.getEntity().toString().getBytes().length + ""));
assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_TYPE), Collections
.singletonList(MediaType.APPLICATION_JSON));
assertEquals("{\"shareIp\":{\"sharedIpGroupId\":3}}", httpMethod.getEntity());
assertEquals(processor.createExceptionParserOrNullIfNotFound(method).getClass(),
ReturnFalseOn404.class);
assertEquals(processor.createResponseParser(method).getClass(), ReturnTrueIf2xx.class);
}
public void testShareIpConfig() throws SecurityException, NoSuchMethodException,
UnknownHostException {
Method method = CloudServersConnection.class.getMethod("shareIp", InetAddress.class,
int.class, int.class, boolean.class);
URI endpoint = URI.create("http://localhost");
HttpRequest httpMethod = processor.createRequest(endpoint, method, new Object[] {
InetAddress.getByAddress(new byte[] { 127, 0, 0, 1 }), 2, 3, true });
assertEquals(httpMethod.getEndpoint().getHost(), "localhost");
assertEquals(httpMethod.getEndpoint().getPath(), "/servers/2/ips/public/127.0.0.1");
assertEquals(httpMethod.getMethod(), HttpMethod.PUT);
assertEquals(httpMethod.getHeaders().size(), 2);
assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_LENGTH), Collections
.singletonList(httpMethod.getEntity().toString().getBytes().length + ""));
assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_TYPE), Collections
.singletonList(MediaType.APPLICATION_JSON));
assertEquals("{\"shareIp\":{\"sharedIpGroupId\":3,\"configureServer\":true}}", httpMethod
.getEntity());
assertEquals(processor.createExceptionParserOrNullIfNotFound(method).getClass(),
ReturnFalseOn404.class);
assertEquals(processor.createResponseParser(method).getClass(), ReturnTrueIf2xx.class);
}
public void testUnshareIpNoConfig() throws SecurityException, NoSuchMethodException,
UnknownHostException {
Method method = CloudServersConnection.class.getMethod("unshareIp", InetAddress.class,
int.class);
URI endpoint = URI.create("http://localhost");
HttpRequest httpMethod = processor.createRequest(endpoint, method, new Object[] {
InetAddress.getByAddress(new byte[] { 127, 0, 0, 1 }), 2, 3, false });
assertEquals(httpMethod.getEndpoint().getHost(), "localhost");
assertEquals(httpMethod.getEndpoint().getPath(), "/servers/2/ips/public/127.0.0.1");
assertEquals(httpMethod.getMethod(), HttpMethod.DELETE);
assertEquals(httpMethod.getHeaders().size(), 0);
assertEquals(processor.createExceptionParserOrNullIfNotFound(method).getClass(),
ReturnFalseOn404.class);
assertEquals(processor.createResponseParser(method).getClass(), ReturnTrueIf2xx.class);
}
public void testChangeAdminPass() throws SecurityException, NoSuchMethodException {
Method method = CloudServersConnection.class.getMethod("changeAdminPass", int.class,
String.class);
@ -562,7 +623,7 @@ public class CloudServersConnectionTest {
assertEquals(processor.createResponseParser(method).getClass(),
ParseSharedIpGroupFromGsonResponse.class);
assertEquals(processor.createExceptionParserOrNullIfNotFound(method), null);
assertNotNull(processor.getPostEntityBinderOrNull(method, new Object[] { "",
assertNotNull(processor.getMapEntityBinderOrNull(method, new Object[] { "",
new CreateSharedIpGroupOptions[] { withServer(2) } }));
}
@ -579,6 +640,45 @@ public class CloudServersConnectionTest {
assertEquals(processor.createResponseParser(method).getClass(), ReturnTrueIf2xx.class);
}
public void testListAddresses() throws SecurityException, NoSuchMethodException {
Method method = CloudServersConnection.class.getMethod("listAddresses", int.class);
URI endpoint = URI.create("http://localhost");
HttpRequest httpMethod = processor.createRequest(endpoint, method, new Object[] { 2 });
assertEquals(httpMethod.getEndpoint().getHost(), "localhost");
assertEquals(httpMethod.getEndpoint().getPath(), "/servers/2/ips");
assertEquals(httpMethod.getEndpoint().getQuery(), "format=json");
assertEquals(httpMethod.getMethod(), HttpMethod.GET);
assertEquals(httpMethod.getHeaders().size(), 0);
assertEquals(processor.createResponseParser(method).getClass(),
ParseAddressesFromGsonResponse.class);
}
public void testListPublicAddresses() throws SecurityException, NoSuchMethodException {
Method method = CloudServersConnection.class.getMethod("listPublicAddresses", int.class);
URI endpoint = URI.create("http://localhost");
HttpRequest httpMethod = processor.createRequest(endpoint, method, new Object[] { 2 });
assertEquals(httpMethod.getEndpoint().getHost(), "localhost");
assertEquals(httpMethod.getEndpoint().getPath(), "/servers/2/ips/public");
assertEquals(httpMethod.getEndpoint().getQuery(), "format=json");
assertEquals(httpMethod.getMethod(), HttpMethod.GET);
assertEquals(httpMethod.getHeaders().size(), 0);
assertEquals(processor.createResponseParser(method).getClass(),
ParseInetAddressListFromGsonResponse.class);
}
public void testListPrivateAddresses() throws SecurityException, NoSuchMethodException {
Method method = CloudServersConnection.class.getMethod("listPrivateAddresses", int.class);
URI endpoint = URI.create("http://localhost");
HttpRequest httpMethod = processor.createRequest(endpoint, method, new Object[] { 2 });
assertEquals(httpMethod.getEndpoint().getHost(), "localhost");
assertEquals(httpMethod.getEndpoint().getPath(), "/servers/2/ips/private");
assertEquals(httpMethod.getEndpoint().getQuery(), "format=json");
assertEquals(httpMethod.getMethod(), HttpMethod.GET);
assertEquals(httpMethod.getHeaders().size(), 0);
assertEquals(processor.createResponseParser(method).getClass(),
ParseInetAddressListFromGsonResponse.class);
}
JaxrsAnnotationProcessor processor;
@BeforeClass

View File

@ -0,0 +1,71 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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.rackspace.cloudservers.functions;
import static org.testng.Assert.assertEquals;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.List;
import org.jclouds.http.functions.config.ParserModule;
import org.jclouds.rackspace.cloudservers.domain.Addresses;
import org.jclouds.util.DateService;
import org.testng.annotations.Test;
import com.google.gson.Gson;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.internal.ImmutableList;
/**
* Tests behavior of {@code ParseAddressesFromGsonResponse}
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "cloudservers.ParseAddressesFromGsonResponseTest")
public class ParseAddressesFromGsonResponseTest {
Injector i = Guice.createInjector(new ParserModule());
DateService dateService = new DateService();
public void testApplyInputStreamDetails() throws UnknownHostException {
InputStream is = getClass().getResourceAsStream("/test_list_addresses.json");
ParseAddressesFromGsonResponse parser = new ParseAddressesFromGsonResponse(i
.getInstance(Gson.class));
Addresses response = parser.apply(is);
List<InetAddress> publicAddresses = ImmutableList.of(InetAddress.getByAddress(new byte[] {
67, 23, 10, (byte) 132 }), InetAddress.getByAddress(new byte[] { 67, 23, 10,
(byte) 131 }));
List<InetAddress> privateAddresses = ImmutableList.of(InetAddress.getByAddress(new byte[] {
10, (byte) 176, 42, 16 }));
assertEquals(response.getPublicAddresses(), publicAddresses);
assertEquals(response.getPrivateAddresses(), privateAddresses);
}
}

View File

@ -0,0 +1,72 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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.rackspace.cloudservers.functions;
import static org.testng.Assert.assertEquals;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.List;
import org.jclouds.http.functions.config.ParserModule;
import org.jclouds.util.DateService;
import org.testng.annotations.Test;
import com.google.gson.Gson;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.internal.ImmutableList;
/**
* Tests behavior of {@code ParseInetAddressListFromGsonResponse}
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "cloudservers.ParseInetAddressListFromGsonResponseTest")
public class ParseInetAddressListFromGsonResponseTest {
Injector i = Guice.createInjector(new ParserModule());
DateService dateService = new DateService();
public void testPublic() throws UnknownHostException {
InputStream is = getClass().getResourceAsStream("/test_list_addresses_public.json");
ParseInetAddressListFromGsonResponse parser = new ParseInetAddressListFromGsonResponse(i
.getInstance(Gson.class));
List<InetAddress> response = parser.apply(is);
assertEquals(response, ImmutableList.of(InetAddress.getByAddress(new byte[] { 67, 23, 10,
(byte) 132 }), InetAddress.getByAddress(new byte[] { 67, 23, 10, (byte) 131 })));
}
public void testPrivate() throws UnknownHostException {
InputStream is = getClass().getResourceAsStream("/test_list_addresses_private.json");
ParseInetAddressListFromGsonResponse parser = new ParseInetAddressListFromGsonResponse(i
.getInstance(Gson.class));
List<InetAddress> response = parser.apply(is);
assertEquals(response, ImmutableList.of(InetAddress.getByAddress(new byte[] { 10, (byte) 176,
42, 16 })));
}
}

View File

@ -1,3 +1,26 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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.rackspace.cloudservers.options;
import static org.jclouds.rackspace.cloudservers.options.ListOptions.Builder.*;

View File

@ -0,0 +1,12 @@
{
"addresses" : {
"public" : [
"67.23.10.132",
"67.23.10.131"
],
"private" : [
"10.176.42.16"
]
}
}

View File

@ -0,0 +1,8 @@
{
"private" : [
"10.176.42.16"
]
}

View File

@ -0,0 +1,7 @@
{
"public" : [
"67.23.10.132",
"67.23.10.131"
]
}