mirror of https://github.com/apache/jclouds.git
Issue 77: rackspace server commands
git-svn-id: http://jclouds.googlecode.com/svn/trunk@1651 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
parent
86475e60e7
commit
02b35f2cb0
|
@ -42,7 +42,6 @@ import org.jclouds.aws.s3.domain.S3Object;
|
||||||
import org.jclouds.aws.s3.filters.RequestAuthorizeSignature;
|
import org.jclouds.aws.s3.filters.RequestAuthorizeSignature;
|
||||||
import org.jclouds.aws.s3.functions.ParseMetadataFromHeaders;
|
import org.jclouds.aws.s3.functions.ParseMetadataFromHeaders;
|
||||||
import org.jclouds.aws.s3.functions.ParseObjectFromHeadersAndHttpContent;
|
import org.jclouds.aws.s3.functions.ParseObjectFromHeadersAndHttpContent;
|
||||||
import org.jclouds.aws.s3.functions.ReturnFalseOn404;
|
|
||||||
import org.jclouds.aws.s3.functions.ReturnNotFoundIfBucketDoesntExist;
|
import org.jclouds.aws.s3.functions.ReturnNotFoundIfBucketDoesntExist;
|
||||||
import org.jclouds.aws.s3.functions.ReturnNotFoundIfObjectDoesntExist;
|
import org.jclouds.aws.s3.functions.ReturnNotFoundIfObjectDoesntExist;
|
||||||
import org.jclouds.aws.s3.functions.ReturnS3BucketNotFoundOn404;
|
import org.jclouds.aws.s3.functions.ReturnS3BucketNotFoundOn404;
|
||||||
|
@ -60,6 +59,7 @@ import org.jclouds.aws.s3.xml.CopyObjectHandler;
|
||||||
import org.jclouds.aws.s3.xml.ListAllMyBucketsHandler;
|
import org.jclouds.aws.s3.xml.ListAllMyBucketsHandler;
|
||||||
import org.jclouds.aws.s3.xml.ListBucketHandler;
|
import org.jclouds.aws.s3.xml.ListBucketHandler;
|
||||||
import org.jclouds.http.functions.ParseETagHeader;
|
import org.jclouds.http.functions.ParseETagHeader;
|
||||||
|
import org.jclouds.http.functions.ReturnFalseOn404;
|
||||||
import org.jclouds.http.options.GetOptions;
|
import org.jclouds.http.options.GetOptions;
|
||||||
import org.jclouds.rest.EntityParam;
|
import org.jclouds.rest.EntityParam;
|
||||||
import org.jclouds.rest.ExceptionParser;
|
import org.jclouds.rest.ExceptionParser;
|
||||||
|
|
|
@ -32,7 +32,6 @@ import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URI;
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
|
@ -21,12 +21,17 @@
|
||||||
* under the License.
|
* under the License.
|
||||||
* ====================================================================
|
* ====================================================================
|
||||||
*/
|
*/
|
||||||
package org.jclouds.aws.s3.functions;
|
package org.jclouds.http.functions;
|
||||||
|
|
||||||
import org.jclouds.http.HttpResponseException;
|
import org.jclouds.http.HttpResponseException;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
public class ReturnFalseOn404 implements Function<Exception, Boolean> {
|
public class ReturnFalseOn404 implements Function<Exception, Boolean> {
|
||||||
|
|
||||||
public Boolean apply(Exception from) {
|
public Boolean apply(Exception from) {
|
|
@ -27,10 +27,13 @@ import java.util.List;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
|
import javax.ws.rs.DELETE;
|
||||||
import javax.ws.rs.GET;
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.POST;
|
||||||
import javax.ws.rs.Path;
|
import javax.ws.rs.Path;
|
||||||
import javax.ws.rs.PathParam;
|
import javax.ws.rs.PathParam;
|
||||||
|
|
||||||
|
import org.jclouds.http.functions.ReturnFalseOn404;
|
||||||
import org.jclouds.rackspace.cloudservers.domain.Flavor;
|
import org.jclouds.rackspace.cloudservers.domain.Flavor;
|
||||||
import org.jclouds.rackspace.cloudservers.domain.Image;
|
import org.jclouds.rackspace.cloudservers.domain.Image;
|
||||||
import org.jclouds.rackspace.cloudservers.domain.Server;
|
import org.jclouds.rackspace.cloudservers.domain.Server;
|
||||||
|
@ -38,11 +41,16 @@ import org.jclouds.rackspace.cloudservers.functions.ParseFlavorFromGsonResponse;
|
||||||
import org.jclouds.rackspace.cloudservers.functions.ParseFlavorListFromGsonResponse;
|
import org.jclouds.rackspace.cloudservers.functions.ParseFlavorListFromGsonResponse;
|
||||||
import org.jclouds.rackspace.cloudservers.functions.ParseImageFromGsonResponse;
|
import org.jclouds.rackspace.cloudservers.functions.ParseImageFromGsonResponse;
|
||||||
import org.jclouds.rackspace.cloudservers.functions.ParseImageListFromGsonResponse;
|
import org.jclouds.rackspace.cloudservers.functions.ParseImageListFromGsonResponse;
|
||||||
|
import org.jclouds.rackspace.cloudservers.functions.ParseServerFromGsonResponse;
|
||||||
import org.jclouds.rackspace.cloudservers.functions.ParseServerListFromGsonResponse;
|
import org.jclouds.rackspace.cloudservers.functions.ParseServerListFromGsonResponse;
|
||||||
import org.jclouds.rackspace.cloudservers.functions.ReturnFlavorNotFoundOn404;
|
import org.jclouds.rackspace.cloudservers.functions.ReturnFlavorNotFoundOn404;
|
||||||
import org.jclouds.rackspace.cloudservers.functions.ReturnImageNotFoundOn404;
|
import org.jclouds.rackspace.cloudservers.functions.ReturnImageNotFoundOn404;
|
||||||
|
import org.jclouds.rackspace.cloudservers.functions.ReturnServerNotFoundOn404;
|
||||||
|
import org.jclouds.rackspace.cloudservers.options.CreateServerOptions;
|
||||||
import org.jclouds.rackspace.filters.AuthenticateRequest;
|
import org.jclouds.rackspace.filters.AuthenticateRequest;
|
||||||
import org.jclouds.rest.ExceptionParser;
|
import org.jclouds.rest.ExceptionParser;
|
||||||
|
import org.jclouds.rest.PostBinder;
|
||||||
|
import org.jclouds.rest.PostParam;
|
||||||
import org.jclouds.rest.Query;
|
import org.jclouds.rest.Query;
|
||||||
import org.jclouds.rest.RequestFilters;
|
import org.jclouds.rest.RequestFilters;
|
||||||
import org.jclouds.rest.ResponseParser;
|
import org.jclouds.rest.ResponseParser;
|
||||||
|
@ -87,6 +95,55 @@ public interface CloudServersConnection {
|
||||||
// unauthorized (401), badRequest (400), overLimit (413)
|
// unauthorized (401), badRequest (400), overLimit (413)
|
||||||
List<Server> listServerDetails();
|
List<Server> listServerDetails();
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* This operation returns details of the specified server.
|
||||||
|
*
|
||||||
|
* @see Server
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
@ResponseParser(ParseServerFromGsonResponse.class)
|
||||||
|
@Query(key = "format", value = "json")
|
||||||
|
@ExceptionParser(ReturnServerNotFoundOn404.class)
|
||||||
|
@Path("/servers/{id}")
|
||||||
|
// TODO: cloudServersFault (400, 500), serviceUnavailable (503), unauthorized (401), badRequest
|
||||||
|
// (400)
|
||||||
|
Server getServerDetails(@PathParam("id") int id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* This operation deletes a cloud server instance from the system.
|
||||||
|
* <p/>
|
||||||
|
* Note: When a server is deleted, all images created from that server are also removed.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @see Server
|
||||||
|
*/
|
||||||
|
@DELETE
|
||||||
|
@ExceptionParser(ReturnFalseOn404.class)
|
||||||
|
@Path("/servers/{id}")
|
||||||
|
// TODO:cloudServersFault (400, 500), serviceUnavailable (503), unauthorized (401), badRequest
|
||||||
|
// (400), itemNotFound (404), buildInProgress (409), overLimit (413)
|
||||||
|
boolean deleteServer(@PathParam("id") int id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This operation asynchronously provisions a new server. The progress of this operation depends
|
||||||
|
* on several factors including location of the requested image, network i/o, host load, and the
|
||||||
|
* selected flavor. The progress of the request can be checked by performing a GET on /server/id,
|
||||||
|
* which will return a progress attribute (0-100% completion). A password will be randomly
|
||||||
|
* generated for you and returned in the response object. For security reasons, it will not be
|
||||||
|
* returned in subsequent GET calls against a given server ID.
|
||||||
|
*/
|
||||||
|
@POST
|
||||||
|
@ResponseParser(ParseServerFromGsonResponse.class)
|
||||||
|
@Query(key = "format", value = "json")
|
||||||
|
@Path("/servers")
|
||||||
|
@PostBinder(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);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* List available flavors (IDs and names only)
|
* List available flavors (IDs and names only)
|
||||||
|
|
|
@ -23,10 +23,8 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.rackspace.cloudservers.domain;
|
package org.jclouds.rackspace.cloudservers.domain;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import com.google.inject.internal.Lists;
|
|
||||||
import com.google.inject.internal.Maps;
|
import com.google.inject.internal.Maps;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -37,11 +35,11 @@ import com.google.inject.internal.Maps;
|
||||||
* @since 4.0
|
* @since 4.0
|
||||||
*/
|
*/
|
||||||
public class Server {
|
public class Server {
|
||||||
|
public static final Server NOT_FOUND = new Server(-1, "NOT_FOUND");
|
||||||
private int id;
|
private int id;
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
private Map<String, String> metadata = Maps.newHashMap();
|
private Map<String, String> metadata = Maps.newHashMap();
|
||||||
private List<File> personality = Lists.newArrayList();
|
|
||||||
|
|
||||||
private Addresses addresses;
|
private Addresses addresses;
|
||||||
private String adminPass;
|
private String adminPass;
|
||||||
|
@ -77,14 +75,6 @@ public class Server {
|
||||||
return addresses;
|
return addresses;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPersonality(List<File> personality) {
|
|
||||||
this.personality = personality;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<File> getPersonality() {
|
|
||||||
return personality;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAdminPass(String adminPass) {
|
public void setAdminPass(String adminPass) {
|
||||||
this.adminPass = adminPass;
|
this.adminPass = adminPass;
|
||||||
}
|
}
|
||||||
|
@ -173,7 +163,6 @@ public class Server {
|
||||||
result = prime * result + ((imageId == null) ? 0 : imageId.hashCode());
|
result = prime * result + ((imageId == null) ? 0 : imageId.hashCode());
|
||||||
result = prime * result + ((metadata == null) ? 0 : metadata.hashCode());
|
result = prime * result + ((metadata == null) ? 0 : metadata.hashCode());
|
||||||
result = prime * result + ((getName() == null) ? 0 : getName().hashCode());
|
result = prime * result + ((getName() == null) ? 0 : getName().hashCode());
|
||||||
result = prime * result + ((personality == null) ? 0 : personality.hashCode());
|
|
||||||
result = prime * result + ((progress == null) ? 0 : progress.hashCode());
|
result = prime * result + ((progress == null) ? 0 : progress.hashCode());
|
||||||
result = prime * result + ((sharedIpGroupId == null) ? 0 : sharedIpGroupId.hashCode());
|
result = prime * result + ((sharedIpGroupId == null) ? 0 : sharedIpGroupId.hashCode());
|
||||||
result = prime * result + ((status == null) ? 0 : status.hashCode());
|
result = prime * result + ((status == null) ? 0 : status.hashCode());
|
||||||
|
@ -226,11 +215,6 @@ public class Server {
|
||||||
return false;
|
return false;
|
||||||
} else if (!getName().equals(other.getName()))
|
} else if (!getName().equals(other.getName()))
|
||||||
return false;
|
return false;
|
||||||
if (personality == null) {
|
|
||||||
if (other.personality != null)
|
|
||||||
return false;
|
|
||||||
} else if (!personality.equals(other.personality))
|
|
||||||
return false;
|
|
||||||
if (progress == null) {
|
if (progress == null) {
|
||||||
if (other.progress != null)
|
if (other.progress != null)
|
||||||
return false;
|
return false;
|
||||||
|
@ -251,11 +235,10 @@ public class Server {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Server [addresses=" + addresses + ", adminPass=" + adminPass + ", flavorId="
|
return "Server [addresses=" + addresses + ", isAdminPassSet=" + (adminPass != null)
|
||||||
+ flavorId + ", hostId=" + hostId + ", id=" + id + ", imageId=" + imageId
|
+ ", flavorId=" + flavorId + ", hostId=" + hostId + ", id=" + id + ", imageId="
|
||||||
+ ", metadata=" + metadata + ", name=" + getName() + ", personality=" + personality
|
+ imageId + ", metadata=" + metadata + ", name=" + getName() + ", progress="
|
||||||
+ ", progress=" + progress + ", sharedIpGroupId=" + sharedIpGroupId + ", status="
|
+ progress + ", sharedIpGroupId=" + sharedIpGroupId + ", status=" + status + "]";
|
||||||
+ status + "]";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setName(String name) {
|
public void setName(String name) {
|
||||||
|
|
|
@ -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.Server;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This parses {@link Server} from a gson string.
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class ParseServerFromGsonResponse extends ParseJson<Server> {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public ParseServerFromGsonResponse(Gson gson) {
|
||||||
|
super(gson);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ServerListResponse {
|
||||||
|
Server server;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Server apply(InputStream stream) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
return gson.fromJson(new InputStreamReader(stream, "UTF-8"), ServerListResponse.class).server;
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
throw new RuntimeException("jclouds requires UTF-8 encoding", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,27 +21,28 @@
|
||||||
* under the License.
|
* under the License.
|
||||||
* ====================================================================
|
* ====================================================================
|
||||||
*/
|
*/
|
||||||
package org.jclouds.rackspace.cloudservers.domain;
|
package org.jclouds.rackspace.cloudservers.functions;
|
||||||
|
|
||||||
public class File {
|
import org.jclouds.http.HttpResponseException;
|
||||||
|
import org.jclouds.rackspace.cloudservers.domain.Server;
|
||||||
|
|
||||||
private byte[] value;
|
import com.google.common.base.Function;
|
||||||
private String path;
|
|
||||||
|
|
||||||
public byte[] getValue() {
|
/**
|
||||||
return value;
|
*
|
||||||
}
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class ReturnServerNotFoundOn404 implements Function<Exception, Server> {
|
||||||
|
|
||||||
public void setValue(byte[] value) {
|
public Server apply(Exception from) {
|
||||||
this.value = ((byte[]) value);
|
if (from instanceof HttpResponseException) {
|
||||||
}
|
HttpResponseException responseException = (HttpResponseException) from;
|
||||||
|
if (responseException.getResponse().getStatusCode() == 404) {
|
||||||
public String getPath() {
|
return Server.NOT_FOUND;
|
||||||
return path;
|
}
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
public void setPath(String value) {
|
|
||||||
this.path = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,211 @@
|
||||||
|
package org.jclouds.rackspace.cloudservers.options;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static com.google.common.base.Preconditions.checkState;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.http.HttpUtils;
|
||||||
|
import org.jclouds.http.binders.JsonBinder;
|
||||||
|
import org.jclouds.rackspace.cloudservers.domain.Addresses;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.inject.internal.Lists;
|
||||||
|
import com.google.inject.internal.Maps;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class CreateServerOptions extends JsonBinder {
|
||||||
|
|
||||||
|
static class File {
|
||||||
|
private final String path;
|
||||||
|
private final String contents;
|
||||||
|
|
||||||
|
public File(String path, byte[] contents) {
|
||||||
|
this.path = checkNotNull(path, "path");
|
||||||
|
this.contents = HttpUtils.toBase64String(checkNotNull(contents, "contents"));
|
||||||
|
checkArgument(path.getBytes().length < 255, String.format(
|
||||||
|
"maximum length of path is 255 bytes. Path specified %s is %d bytes", path, path
|
||||||
|
.getBytes().length));
|
||||||
|
checkArgument(contents.length < 10 * 1024, String.format(
|
||||||
|
"maximum size of the file is 10KB. Contents specified is %d bytes",
|
||||||
|
contents.length));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContents() {
|
||||||
|
return contents;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPath() {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private class ServerRequest {
|
||||||
|
final String name;
|
||||||
|
final int imageId;
|
||||||
|
final int flavorId;
|
||||||
|
Map<String, String> metadata;
|
||||||
|
List<File> personality;
|
||||||
|
Integer sharedIpGroupId;
|
||||||
|
Addresses addresses;
|
||||||
|
|
||||||
|
private ServerRequest(String name, int imageId, int flavorId) {
|
||||||
|
this.name = name;
|
||||||
|
this.imageId = imageId;
|
||||||
|
this.flavorId = flavorId;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, String> metadata = Maps.newHashMap();
|
||||||
|
private List<File> files = Lists.newArrayList();
|
||||||
|
private Integer sharedIpGroupId;
|
||||||
|
private InetAddress publicIp;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addEntityToRequest(Map<String, String> postParams, HttpRequest request) {
|
||||||
|
|
||||||
|
ServerRequest server = new ServerRequest(checkNotNull(postParams.get("name"),
|
||||||
|
"name parameter not present"), Integer.parseInt(checkNotNull(postParams
|
||||||
|
.get("imageId"), "imageId parameter not present")), Integer.parseInt(checkNotNull(
|
||||||
|
postParams.get("flavorId"), "flavorId parameter not present")));
|
||||||
|
if (metadata.size() > 0)
|
||||||
|
server.metadata = metadata;
|
||||||
|
if (files.size() > 0)
|
||||||
|
server.personality = files;
|
||||||
|
if (sharedIpGroupId != null)
|
||||||
|
server.sharedIpGroupId = this.sharedIpGroupId;
|
||||||
|
if (publicIp != null) {
|
||||||
|
server.addresses = new Addresses();
|
||||||
|
server.addresses.setPublicAddresses(Collections.singletonList(publicIp));
|
||||||
|
server.addresses.setPrivateAddresses(null);
|
||||||
|
}
|
||||||
|
addEntityToRequest(ImmutableMap.of("server", server), request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* You may further customize a cloud server by injecting data into the file system of the cloud
|
||||||
|
* server itself. This is useful, for example, for inserting ssh keys, setting configuration
|
||||||
|
* files, or storing data that you want to retrieve from within the instance itself. It is
|
||||||
|
* intended to provide a minimal amount of launch-time personalization. If significant
|
||||||
|
* customization is required, a custom image should be created. The max size of the file path
|
||||||
|
* data is 255 bytes while the max size of the file contents is 10KB. Note that the file contents
|
||||||
|
* should be encoded as a Base64 string and the 10KB limit refers to the number of bytes in the
|
||||||
|
* decoded data not the number of characters in the encoded data. The maximum number of file
|
||||||
|
* path/content pairs that can be supplied is 5. Any existing files that match the specified file
|
||||||
|
* will be renamed to include the extension bak followed by a time stamp. For example, the file
|
||||||
|
* /etc/passwd will be backed up as /etc/passwd.bak.1246036261.5785. All files will have root and
|
||||||
|
* the root group as owner and group owner, respectively and will allow user and group read
|
||||||
|
* access only (-r--r-----).
|
||||||
|
*/
|
||||||
|
public CreateServerOptions withFile(String path, byte[] contents) {
|
||||||
|
checkState(files.size() < 5, "maximum number of files allowed is 5");
|
||||||
|
files.add(new File(path, contents));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Servers in the same shared IP group can share public IPs for various high availability and
|
||||||
|
* load balancing configurations. To launch an HA server, include the optional sharedIpGroupId
|
||||||
|
* element and the server will be launched into that shared IP group.
|
||||||
|
* <p />
|
||||||
|
*
|
||||||
|
* Note: sharedIpGroupId is an optional parameter and for optimal performance, should ONLY be
|
||||||
|
* specified when intending to share IPs between servers.
|
||||||
|
*
|
||||||
|
* @see #withSharedIp(InetAddress)
|
||||||
|
*/
|
||||||
|
public CreateServerOptions withSharedIpGroup(int id) {
|
||||||
|
checkArgument(id > 0, "id must be positive or zero. was: " + id);
|
||||||
|
this.sharedIpGroupId = id;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom cloud server metadata can also be supplied at launch time. This metadata is stored in
|
||||||
|
* the API system where it is retrievable by querying the API for server status. The maximum size
|
||||||
|
* of the metadata key and value is each 255 bytes and the maximum number of key-value pairs that
|
||||||
|
* can be supplied per server is 5.
|
||||||
|
*/
|
||||||
|
public CreateServerOptions withMetadata(Map<String, String> metadata) {
|
||||||
|
checkNotNull(metadata, "metadata");
|
||||||
|
checkArgument(metadata.size() <= 5,
|
||||||
|
"you cannot have more then 5 metadata values. You specified: " + metadata.size());
|
||||||
|
for (Entry<String, String> entry : metadata.entrySet()) {
|
||||||
|
checkArgument(entry.getKey().getBytes().length < 255, String.format(
|
||||||
|
"maximum length of metadata key is 255 bytes. Key specified %s is %d bytes",
|
||||||
|
entry.getKey(), entry.getKey().getBytes().length));
|
||||||
|
checkArgument(
|
||||||
|
entry.getKey().getBytes().length < 255,
|
||||||
|
String
|
||||||
|
.format(
|
||||||
|
"maximum length of metadata value is 255 bytes. Value specified for %s (%s) is %d bytes",
|
||||||
|
entry.getKey(), entry.getValue(),
|
||||||
|
entry.getValue().getBytes().length));
|
||||||
|
}
|
||||||
|
this.metadata = metadata;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If you intend to use a shared IP on the server being created and have no need for a separate
|
||||||
|
* public IP address, you may launch the server into a shared IP group and specify an IP address
|
||||||
|
* from that shared IP group to be used as its public IP. You can accomplish this by specifying
|
||||||
|
* the public shared IP address in your request. This is optional and is only valid if
|
||||||
|
* sharedIpGroupId is also supplied.
|
||||||
|
*/
|
||||||
|
public CreateServerOptions withSharedIp(InetAddress publicIp) {
|
||||||
|
checkState(sharedIpGroupId != null,
|
||||||
|
"sharedIp is invalid unless a shared ip group is specified.");
|
||||||
|
this.publicIp = checkNotNull(publicIp, "ip");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see CreateServerOptions#withFile(String,byte [])
|
||||||
|
*/
|
||||||
|
public static CreateServerOptions withFile(String path, byte[] contents) {
|
||||||
|
CreateServerOptions options = new CreateServerOptions();
|
||||||
|
return options.withFile(path, contents);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see CreateServerOptions#withSharedIpGroup(int)
|
||||||
|
*/
|
||||||
|
public static CreateServerOptions withSharedIpGroup(int id) {
|
||||||
|
CreateServerOptions options = new CreateServerOptions();
|
||||||
|
return options.withSharedIpGroup(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see CreateServerOptions#withMetadata(Map<String, String>)
|
||||||
|
*/
|
||||||
|
public static CreateServerOptions withMetadata(Map<String, String> metadata) {
|
||||||
|
CreateServerOptions options = new CreateServerOptions();
|
||||||
|
return options.withMetadata(metadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see CreateServerOptions#withSharedIp(InetAddress)
|
||||||
|
*/
|
||||||
|
public static CreateServerOptions withSharedIp(InetAddress publicIp) {
|
||||||
|
CreateServerOptions options = new CreateServerOptions();
|
||||||
|
return options.withSharedIp(publicIp);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,17 +25,26 @@ package org.jclouds.rackspace.cloudservers;
|
||||||
|
|
||||||
import static org.jclouds.rackspace.reference.RackspaceConstants.PROPERTY_RACKSPACE_KEY;
|
import static org.jclouds.rackspace.reference.RackspaceConstants.PROPERTY_RACKSPACE_KEY;
|
||||||
import static org.jclouds.rackspace.reference.RackspaceConstants.PROPERTY_RACKSPACE_USER;
|
import static org.jclouds.rackspace.reference.RackspaceConstants.PROPERTY_RACKSPACE_USER;
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
import static org.testng.Assert.assertNotNull;
|
||||||
import static org.testng.Assert.assertTrue;
|
import static org.testng.Assert.assertTrue;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
|
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
|
||||||
import org.jclouds.rackspace.cloudservers.domain.Flavor;
|
import org.jclouds.rackspace.cloudservers.domain.Flavor;
|
||||||
import org.jclouds.rackspace.cloudservers.domain.Image;
|
import org.jclouds.rackspace.cloudservers.domain.Image;
|
||||||
import org.jclouds.rackspace.cloudservers.domain.Server;
|
import org.jclouds.rackspace.cloudservers.domain.Server;
|
||||||
|
import org.jclouds.rackspace.cloudservers.domain.ServerStatus;
|
||||||
|
import org.jclouds.ssh.SshConnection;
|
||||||
|
import org.jclouds.ssh.jsch.config.JschSshConnectionModule;
|
||||||
|
import org.jclouds.util.Utils;
|
||||||
import org.testng.annotations.BeforeGroups;
|
import org.testng.annotations.BeforeGroups;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.inject.Injector;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests behavior of {@code CloudServersConnection}
|
* Tests behavior of {@code CloudServersConnection}
|
||||||
*
|
*
|
||||||
|
@ -47,11 +56,16 @@ public class CloudServersConnectionLiveTest {
|
||||||
protected static final String sysRackspaceUser = System.getProperty(PROPERTY_RACKSPACE_USER);
|
protected static final String sysRackspaceUser = System.getProperty(PROPERTY_RACKSPACE_USER);
|
||||||
protected static final String sysRackspaceKey = System.getProperty(PROPERTY_RACKSPACE_KEY);
|
protected static final String sysRackspaceKey = System.getProperty(PROPERTY_RACKSPACE_KEY);
|
||||||
CloudServersConnection connection;
|
CloudServersConnection connection;
|
||||||
|
SshConnection.Factory sshFactory;
|
||||||
|
|
||||||
@BeforeGroups(groups = { "live" })
|
@BeforeGroups(groups = { "live" })
|
||||||
public void setupConnection() {
|
public void setupConnection() {
|
||||||
connection = CloudServersContextBuilder.newBuilder(sysRackspaceUser, sysRackspaceKey)
|
Injector injector = CloudServersContextBuilder.newBuilder(sysRackspaceUser, sysRackspaceKey)
|
||||||
.withModule(new Log4JLoggingModule()).withJsonDebug().buildContext().getConnection();
|
.withModules(new Log4JLoggingModule(), new JschSshConnectionModule())
|
||||||
|
.withJsonDebug().buildInjector();
|
||||||
|
connection = injector.getInstance(CloudServersConnection.class);
|
||||||
|
sshFactory = injector.getInstance(SshConnection.Factory.class);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -137,10 +151,17 @@ public class CloudServersConnectionLiveTest {
|
||||||
assertTrue(imageCount >= 0);
|
assertTrue(imageCount >= 0);
|
||||||
for (Image image : response) {
|
for (Image image : response) {
|
||||||
Image newDetails = connection.getImageDetails(image.getId());
|
Image newDetails = connection.getImageDetails(image.getId());
|
||||||
assert image.equals(newDetails) : String.format("%s doesn't equal %2", newDetails, image);
|
assertEquals(image, newDetails);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(enabled = false)
|
||||||
|
// Rackspace Web Hosting issue #118856
|
||||||
|
public void testGetImageDetailsNotFound() throws Exception {
|
||||||
|
Image newDetails = connection.getImageDetails(12312987);
|
||||||
|
assertEquals(Image.NOT_FOUND, newDetails);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetFlavorDetails() throws Exception {
|
public void testGetFlavorDetails() throws Exception {
|
||||||
List<Flavor> response = connection.listFlavorDetails();
|
List<Flavor> response = connection.listFlavorDetails();
|
||||||
|
@ -149,8 +170,67 @@ public class CloudServersConnectionLiveTest {
|
||||||
assertTrue(flavorCount >= 0);
|
assertTrue(flavorCount >= 0);
|
||||||
for (Flavor flavor : response) {
|
for (Flavor flavor : response) {
|
||||||
Flavor newDetails = connection.getFlavorDetails(flavor.getId());
|
Flavor newDetails = connection.getFlavorDetails(flavor.getId());
|
||||||
assert flavor.equals(newDetails) : String
|
assertEquals(flavor, newDetails);
|
||||||
.format("%s doesn't equal %2", newDetails, flavor);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testGetFlavorDetailsNotFound() throws Exception {
|
||||||
|
Flavor newDetails = connection.getFlavorDetails(12312987);
|
||||||
|
assertEquals(Flavor.NOT_FOUND, newDetails);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetServerDetailsNotFound() throws Exception {
|
||||||
|
Server newDetails = connection.getServerDetails(12312987);
|
||||||
|
assertEquals(Server.NOT_FOUND, newDetails);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetServerDetails() throws Exception {
|
||||||
|
List<Server> response = connection.listServerDetails();
|
||||||
|
assert null != response;
|
||||||
|
long serverCount = response.size();
|
||||||
|
assertTrue(serverCount >= 0);
|
||||||
|
for (Server server : response) {
|
||||||
|
Server newDetails = connection.getServerDetails(server.getId());
|
||||||
|
assertEquals(server, newDetails);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String serverPrefix = System.getProperty("user.name") + ".cs";
|
||||||
|
|
||||||
|
@Test(timeOut = 5 * 60 * 1000)
|
||||||
|
public void testCreateServer() throws Exception {
|
||||||
|
Server newDetails = connection.createServer(serverPrefix + "createserver", 2, 1);
|
||||||
|
System.err.print(newDetails);
|
||||||
|
assertNotNull(newDetails.getAdminPass());
|
||||||
|
assertNotNull(newDetails.getHostId());
|
||||||
|
assertEquals(newDetails.getStatus(), ServerStatus.BUILD);
|
||||||
|
assert newDetails.getProgress() >= 0 : "newDetails.getProgress()" + newDetails.getProgress();
|
||||||
|
assertEquals(new Integer(2), newDetails.getImageId());
|
||||||
|
assertEquals(new Integer(1), newDetails.getFlavorId());
|
||||||
|
assertNotNull(newDetails.getAddresses());
|
||||||
|
assertEquals(newDetails.getAddresses().getPublicAddresses().size(), 1);
|
||||||
|
assertEquals(newDetails.getAddresses().getPrivateAddresses().size(), 1);
|
||||||
|
|
||||||
|
int serverId = newDetails.getId();
|
||||||
|
ServerStatus currentStatus = newDetails.getStatus();
|
||||||
|
Server currentDetails = newDetails;
|
||||||
|
while (currentStatus != ServerStatus.ACTIVE) {
|
||||||
|
Thread.sleep(5 * 1000);
|
||||||
|
currentDetails = connection.getServerDetails(serverId);
|
||||||
|
System.out.println(currentDetails);
|
||||||
|
currentStatus = currentDetails.getStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
InputStream etcPasswd = sshFactory.create(
|
||||||
|
newDetails.getAddresses().getPublicAddresses().get(0), 22, "root",
|
||||||
|
newDetails.getAdminPass()).get("/etc/passwd");
|
||||||
|
String etcPasswdContents = Utils.toStringAndClose(etcPasswd);
|
||||||
|
assert etcPasswdContents.indexOf("root") >= 0 : etcPasswdContents;
|
||||||
|
|
||||||
|
connection.deleteServer(serverId);
|
||||||
|
|
||||||
|
currentDetails = connection.getServerDetails(serverId);
|
||||||
|
assertEquals(ServerStatus.DELETED, currentDetails.getStatus());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,10 @@ import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import javax.ws.rs.core.HttpHeaders;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
|
||||||
import org.jclouds.concurrent.WithinThreadExecutorService;
|
import org.jclouds.concurrent.WithinThreadExecutorService;
|
||||||
import org.jclouds.concurrent.config.ExecutorServiceModule;
|
import org.jclouds.concurrent.config.ExecutorServiceModule;
|
||||||
|
@ -38,6 +42,7 @@ import org.jclouds.rackspace.cloudservers.functions.ParseFlavorFromGsonResponse;
|
||||||
import org.jclouds.rackspace.cloudservers.functions.ParseFlavorListFromGsonResponse;
|
import org.jclouds.rackspace.cloudservers.functions.ParseFlavorListFromGsonResponse;
|
||||||
import org.jclouds.rackspace.cloudservers.functions.ParseImageFromGsonResponse;
|
import org.jclouds.rackspace.cloudservers.functions.ParseImageFromGsonResponse;
|
||||||
import org.jclouds.rackspace.cloudservers.functions.ParseImageListFromGsonResponse;
|
import org.jclouds.rackspace.cloudservers.functions.ParseImageListFromGsonResponse;
|
||||||
|
import org.jclouds.rackspace.cloudservers.functions.ParseServerFromGsonResponse;
|
||||||
import org.jclouds.rackspace.cloudservers.functions.ParseServerListFromGsonResponse;
|
import org.jclouds.rackspace.cloudservers.functions.ParseServerListFromGsonResponse;
|
||||||
import org.jclouds.rest.JaxrsAnnotationProcessor;
|
import org.jclouds.rest.JaxrsAnnotationProcessor;
|
||||||
import org.jclouds.rest.config.JaxrsModule;
|
import org.jclouds.rest.config.JaxrsModule;
|
||||||
|
@ -58,6 +63,27 @@ public class CloudServersConnectionTest {
|
||||||
|
|
||||||
JaxrsAnnotationProcessor.Factory factory;
|
JaxrsAnnotationProcessor.Factory factory;
|
||||||
|
|
||||||
|
public void testCreateServer() throws SecurityException, NoSuchMethodException {
|
||||||
|
Method method = CloudServersConnection.class.getMethod("createServer", String.class,
|
||||||
|
int.class, int.class);
|
||||||
|
URI endpoint = URI.create("http://localhost");
|
||||||
|
HttpRequest httpMethod = factory.create(CloudServersConnection.class).createRequest(endpoint,
|
||||||
|
method, new Object[] { "ralphie", 2, 1 });
|
||||||
|
assertEquals(httpMethod.getEndpoint().getHost(), "localhost");
|
||||||
|
assertEquals(httpMethod.getEndpoint().getPath(), "/servers");
|
||||||
|
assertEquals(httpMethod.getEndpoint().getQuery(), "format=json");
|
||||||
|
assertEquals(httpMethod.getMethod(), HttpMethod.POST);
|
||||||
|
assertEquals("{\"server\":{\"name\":\"ralphie\",\"imageId\":2,\"flavorId\":1}}", httpMethod
|
||||||
|
.getEntity());
|
||||||
|
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(JaxrsAnnotationProcessor.getParserOrThrowException(method),
|
||||||
|
ParseServerFromGsonResponse.class);
|
||||||
|
}
|
||||||
|
|
||||||
public void testListServers() throws SecurityException, NoSuchMethodException {
|
public void testListServers() throws SecurityException, NoSuchMethodException {
|
||||||
Method method = CloudServersConnection.class.getMethod("listServers");
|
Method method = CloudServersConnection.class.getMethod("listServers");
|
||||||
URI endpoint = URI.create("http://localhost");
|
URI endpoint = URI.create("http://localhost");
|
||||||
|
@ -68,7 +94,6 @@ public class CloudServersConnectionTest {
|
||||||
assertEquals(httpMethod.getEndpoint().getQuery(), "format=json");
|
assertEquals(httpMethod.getEndpoint().getQuery(), "format=json");
|
||||||
assertEquals(httpMethod.getMethod(), HttpMethod.GET);
|
assertEquals(httpMethod.getMethod(), HttpMethod.GET);
|
||||||
assertEquals(httpMethod.getHeaders().size(), 0);
|
assertEquals(httpMethod.getHeaders().size(), 0);
|
||||||
factory.create(CloudServersConnection.class);
|
|
||||||
assertEquals(JaxrsAnnotationProcessor.getParserOrThrowException(method),
|
assertEquals(JaxrsAnnotationProcessor.getParserOrThrowException(method),
|
||||||
ParseServerListFromGsonResponse.class);
|
ParseServerListFromGsonResponse.class);
|
||||||
|
|
||||||
|
@ -84,7 +109,6 @@ public class CloudServersConnectionTest {
|
||||||
assertEquals(httpMethod.getEndpoint().getQuery(), "format=json");
|
assertEquals(httpMethod.getEndpoint().getQuery(), "format=json");
|
||||||
assertEquals(httpMethod.getMethod(), HttpMethod.GET);
|
assertEquals(httpMethod.getMethod(), HttpMethod.GET);
|
||||||
assertEquals(httpMethod.getHeaders().size(), 0);
|
assertEquals(httpMethod.getHeaders().size(), 0);
|
||||||
factory.create(CloudServersConnection.class);
|
|
||||||
assertEquals(JaxrsAnnotationProcessor.getParserOrThrowException(method),
|
assertEquals(JaxrsAnnotationProcessor.getParserOrThrowException(method),
|
||||||
ParseServerListFromGsonResponse.class);
|
ParseServerListFromGsonResponse.class);
|
||||||
|
|
||||||
|
@ -100,7 +124,6 @@ public class CloudServersConnectionTest {
|
||||||
assertEquals(httpMethod.getEndpoint().getQuery(), "format=json");
|
assertEquals(httpMethod.getEndpoint().getQuery(), "format=json");
|
||||||
assertEquals(httpMethod.getMethod(), HttpMethod.GET);
|
assertEquals(httpMethod.getMethod(), HttpMethod.GET);
|
||||||
assertEquals(httpMethod.getHeaders().size(), 0);
|
assertEquals(httpMethod.getHeaders().size(), 0);
|
||||||
factory.create(CloudServersConnection.class);
|
|
||||||
assertEquals(JaxrsAnnotationProcessor.getParserOrThrowException(method),
|
assertEquals(JaxrsAnnotationProcessor.getParserOrThrowException(method),
|
||||||
ParseFlavorListFromGsonResponse.class);
|
ParseFlavorListFromGsonResponse.class);
|
||||||
|
|
||||||
|
@ -116,7 +139,6 @@ public class CloudServersConnectionTest {
|
||||||
assertEquals(httpMethod.getEndpoint().getQuery(), "format=json");
|
assertEquals(httpMethod.getEndpoint().getQuery(), "format=json");
|
||||||
assertEquals(httpMethod.getMethod(), HttpMethod.GET);
|
assertEquals(httpMethod.getMethod(), HttpMethod.GET);
|
||||||
assertEquals(httpMethod.getHeaders().size(), 0);
|
assertEquals(httpMethod.getHeaders().size(), 0);
|
||||||
factory.create(CloudServersConnection.class);
|
|
||||||
assertEquals(JaxrsAnnotationProcessor.getParserOrThrowException(method),
|
assertEquals(JaxrsAnnotationProcessor.getParserOrThrowException(method),
|
||||||
ParseFlavorListFromGsonResponse.class);
|
ParseFlavorListFromGsonResponse.class);
|
||||||
|
|
||||||
|
@ -132,7 +154,6 @@ public class CloudServersConnectionTest {
|
||||||
assertEquals(httpMethod.getEndpoint().getQuery(), "format=json");
|
assertEquals(httpMethod.getEndpoint().getQuery(), "format=json");
|
||||||
assertEquals(httpMethod.getMethod(), HttpMethod.GET);
|
assertEquals(httpMethod.getMethod(), HttpMethod.GET);
|
||||||
assertEquals(httpMethod.getHeaders().size(), 0);
|
assertEquals(httpMethod.getHeaders().size(), 0);
|
||||||
factory.create(CloudServersConnection.class);
|
|
||||||
assertEquals(JaxrsAnnotationProcessor.getParserOrThrowException(method),
|
assertEquals(JaxrsAnnotationProcessor.getParserOrThrowException(method),
|
||||||
ParseImageListFromGsonResponse.class);
|
ParseImageListFromGsonResponse.class);
|
||||||
|
|
||||||
|
@ -148,7 +169,6 @@ public class CloudServersConnectionTest {
|
||||||
assertEquals(httpMethod.getEndpoint().getQuery(), "format=json");
|
assertEquals(httpMethod.getEndpoint().getQuery(), "format=json");
|
||||||
assertEquals(httpMethod.getMethod(), HttpMethod.GET);
|
assertEquals(httpMethod.getMethod(), HttpMethod.GET);
|
||||||
assertEquals(httpMethod.getHeaders().size(), 0);
|
assertEquals(httpMethod.getHeaders().size(), 0);
|
||||||
factory.create(CloudServersConnection.class);
|
|
||||||
assertEquals(JaxrsAnnotationProcessor.getParserOrThrowException(method),
|
assertEquals(JaxrsAnnotationProcessor.getParserOrThrowException(method),
|
||||||
ParseImageListFromGsonResponse.class);
|
ParseImageListFromGsonResponse.class);
|
||||||
|
|
||||||
|
@ -164,7 +184,6 @@ public class CloudServersConnectionTest {
|
||||||
assertEquals(httpMethod.getEndpoint().getQuery(), "format=json");
|
assertEquals(httpMethod.getEndpoint().getQuery(), "format=json");
|
||||||
assertEquals(httpMethod.getMethod(), HttpMethod.GET);
|
assertEquals(httpMethod.getMethod(), HttpMethod.GET);
|
||||||
assertEquals(httpMethod.getHeaders().size(), 0);
|
assertEquals(httpMethod.getHeaders().size(), 0);
|
||||||
factory.create(CloudServersConnection.class);
|
|
||||||
assertEquals(JaxrsAnnotationProcessor.getParserOrThrowException(method),
|
assertEquals(JaxrsAnnotationProcessor.getParserOrThrowException(method),
|
||||||
ParseImageFromGsonResponse.class);
|
ParseImageFromGsonResponse.class);
|
||||||
|
|
||||||
|
@ -180,12 +199,38 @@ public class CloudServersConnectionTest {
|
||||||
assertEquals(httpMethod.getEndpoint().getQuery(), "format=json");
|
assertEquals(httpMethod.getEndpoint().getQuery(), "format=json");
|
||||||
assertEquals(httpMethod.getMethod(), HttpMethod.GET);
|
assertEquals(httpMethod.getMethod(), HttpMethod.GET);
|
||||||
assertEquals(httpMethod.getHeaders().size(), 0);
|
assertEquals(httpMethod.getHeaders().size(), 0);
|
||||||
factory.create(CloudServersConnection.class);
|
|
||||||
assertEquals(JaxrsAnnotationProcessor.getParserOrThrowException(method),
|
assertEquals(JaxrsAnnotationProcessor.getParserOrThrowException(method),
|
||||||
ParseFlavorFromGsonResponse.class);
|
ParseFlavorFromGsonResponse.class);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testGetServerDetails() throws SecurityException, NoSuchMethodException {
|
||||||
|
Method method = CloudServersConnection.class.getMethod("getServerDetails", int.class);
|
||||||
|
URI endpoint = URI.create("http://localhost");
|
||||||
|
HttpRequest httpMethod = factory.create(CloudServersConnection.class).createRequest(endpoint,
|
||||||
|
method, new Object[] { 2 });
|
||||||
|
assertEquals(httpMethod.getEndpoint().getHost(), "localhost");
|
||||||
|
assertEquals(httpMethod.getEndpoint().getPath(), "/servers/2");
|
||||||
|
assertEquals(httpMethod.getEndpoint().getQuery(), "format=json");
|
||||||
|
assertEquals(httpMethod.getMethod(), HttpMethod.GET);
|
||||||
|
assertEquals(httpMethod.getHeaders().size(), 0);
|
||||||
|
assertEquals(JaxrsAnnotationProcessor.getParserOrThrowException(method),
|
||||||
|
ParseServerFromGsonResponse.class);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testDeleteServer() throws SecurityException, NoSuchMethodException {
|
||||||
|
Method method = CloudServersConnection.class.getMethod("deleteServer", int.class);
|
||||||
|
URI endpoint = URI.create("http://localhost");
|
||||||
|
HttpRequest httpMethod = factory.create(CloudServersConnection.class).createRequest(endpoint,
|
||||||
|
method, new Object[] { 2 });
|
||||||
|
assertEquals(httpMethod.getEndpoint().getHost(), "localhost");
|
||||||
|
assertEquals(httpMethod.getEndpoint().getPath(), "/servers/2");
|
||||||
|
assertEquals(httpMethod.getMethod(), HttpMethod.DELETE);
|
||||||
|
assertEquals(httpMethod.getHeaders().size(), 0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
void setupFactory() {
|
void setupFactory() {
|
||||||
factory = Guice.createInjector(new AbstractModule() {
|
factory = Guice.createInjector(new AbstractModule() {
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 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.rackspace.cloudservers.domain.Server;
|
||||||
|
import org.jclouds.rackspace.cloudservers.domain.ServerStatus;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.inject.Guice;
|
||||||
|
import com.google.inject.Injector;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests behavior of {@code ParseServerFromGsonResponseTest}
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Test(groups = "unit", testName = "cloudservers.ParseServerFromGsonResponseTest")
|
||||||
|
public class ParseServerFromGsonResponseTest {
|
||||||
|
|
||||||
|
Injector i = Guice.createInjector(new ParserModule());
|
||||||
|
|
||||||
|
public void testApplyInputStreamDetails() throws UnknownHostException {
|
||||||
|
InputStream is = getClass().getResourceAsStream("/test_get_server_detail.json");
|
||||||
|
|
||||||
|
ParseServerFromGsonResponse parser = new ParseServerFromGsonResponse(i
|
||||||
|
.getInstance(Gson.class));
|
||||||
|
Server response = parser.apply(is);
|
||||||
|
assertEquals(response.getId(), 1234);
|
||||||
|
assertEquals(response.getName(), "sample-server");
|
||||||
|
assertEquals(response.getImageId(), new Integer(2));
|
||||||
|
assertEquals(response.getFlavorId(), new Integer(1));
|
||||||
|
assertEquals(response.getHostId(), "e4d909c290d0fb1ca068ffaddf22cbd0");
|
||||||
|
assertEquals(response.getStatus(), ServerStatus.BUILD);
|
||||||
|
assertEquals(response.getProgress(), new Integer(60));
|
||||||
|
List<InetAddress> publicAddresses = Lists.newArrayList(InetAddress.getByName("67.23.10.132"),
|
||||||
|
InetAddress.getByName("67.23.10.131"));
|
||||||
|
List<InetAddress> privateAddresses = Lists
|
||||||
|
.newArrayList(InetAddress.getByName("10.176.42.16"));
|
||||||
|
Addresses addresses1 = new Addresses(publicAddresses, privateAddresses);
|
||||||
|
assertEquals(response.getAddresses(), addresses1);
|
||||||
|
assertEquals(response.getMetadata(), ImmutableMap.of("Server Label", "Web Head 1",
|
||||||
|
"Image Version", "2.1"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,150 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 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.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
|
||||||
|
import org.jclouds.http.HttpMethod;
|
||||||
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.http.functions.config.ParserModule;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.inject.Guice;
|
||||||
|
import com.google.inject.Injector;
|
||||||
|
import static org.jclouds.rackspace.cloudservers.options.CreateServerOptions.Builder.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests behavior of {@code ParseFlavorFromGsonResponse}
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Test(groups = "unit", testName = "cloudservers.CreateServerOptionsTest")
|
||||||
|
public class CreateServerOptionsTest {
|
||||||
|
|
||||||
|
Injector injector = Guice.createInjector(new ParserModule());
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAddEntityToRequestMapOfStringStringHttpRequest() {
|
||||||
|
CreateServerOptions options = new CreateServerOptions();
|
||||||
|
HttpRequest request = buildRequest(options);
|
||||||
|
assertEquals("{\"server\":{\"name\":\"foo\",\"imageId\":1,\"flavorId\":2}}", request
|
||||||
|
.getEntity());
|
||||||
|
}
|
||||||
|
|
||||||
|
private HttpRequest buildRequest(CreateServerOptions options) {
|
||||||
|
injector.injectMembers(options);
|
||||||
|
HttpRequest request = new HttpRequest(HttpMethod.POST, URI.create("/"));
|
||||||
|
options.addEntityToRequest(ImmutableMap.of("name", "foo", "imageId", "1", "flavorId", "2"),
|
||||||
|
request);
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWithFile() {
|
||||||
|
CreateServerOptions options = new CreateServerOptions();
|
||||||
|
options.withFile("/tmp/rhubarb", "foo".getBytes());
|
||||||
|
HttpRequest request = buildRequest(options);
|
||||||
|
assertFile(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWithFileStatic() {
|
||||||
|
CreateServerOptions options = withFile("/tmp/rhubarb", "foo".getBytes());
|
||||||
|
HttpRequest request = buildRequest(options);
|
||||||
|
assertFile(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertFile(HttpRequest request) {
|
||||||
|
assertEquals(
|
||||||
|
"{\"server\":{\"name\":\"foo\",\"imageId\":1,\"flavorId\":2,\"personality\":[{\"path\":\"/tmp/rhubarb\",\"contents\":\"Zm9v\"}]}}",
|
||||||
|
request.getEntity());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWithSharedIpGroup() {
|
||||||
|
CreateServerOptions options = new CreateServerOptions();
|
||||||
|
options.withSharedIpGroup(3);
|
||||||
|
HttpRequest request = buildRequest(options);
|
||||||
|
assertSharedIpGroup(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWithSharedIpGroupStatic() {
|
||||||
|
CreateServerOptions options = withSharedIpGroup(3);
|
||||||
|
HttpRequest request = buildRequest(options);
|
||||||
|
assertSharedIpGroup(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertSharedIpGroup(HttpRequest request) {
|
||||||
|
assertEquals(
|
||||||
|
"{\"server\":{\"name\":\"foo\",\"imageId\":1,\"flavorId\":2,\"sharedIpGroupId\":3}}",
|
||||||
|
request.getEntity());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWithMetadata() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWithSharedIp() throws UnknownHostException {
|
||||||
|
CreateServerOptions options = new CreateServerOptions();
|
||||||
|
options.withSharedIpGroup(3).withSharedIp(
|
||||||
|
InetAddress.getByAddress(new byte[] { 127, 0, 0, 1 }));
|
||||||
|
HttpRequest request = buildRequest(options);
|
||||||
|
assertSharedIp(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWithSharedIpStatic() throws UnknownHostException {
|
||||||
|
CreateServerOptions options = withSharedIpGroup(3).withSharedIp(
|
||||||
|
InetAddress.getByAddress(new byte[] { 127, 0, 0, 1 }));
|
||||||
|
HttpRequest request = buildRequest(options);
|
||||||
|
assertSharedIp(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertSharedIp(HttpRequest request) {
|
||||||
|
assertEquals(
|
||||||
|
"{\"server\":{\"name\":\"foo\",\"imageId\":1,\"flavorId\":2,\"sharedIpGroupId\":3,\"addresses\":{\"public\":[\"127.0.0.1\"]}}}",
|
||||||
|
request.getEntity());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expectedExceptions = IllegalStateException.class)
|
||||||
|
public void testWithSharedIpNoGroup() throws UnknownHostException {
|
||||||
|
CreateServerOptions options = new CreateServerOptions();
|
||||||
|
options.withSharedIp(InetAddress.getByAddress(new byte[] { 127, 0, 0, 1 }));
|
||||||
|
buildRequest(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expectedExceptions = IllegalStateException.class)
|
||||||
|
public void testWithSharedIpNoGroupStatic() throws UnknownHostException {
|
||||||
|
CreateServerOptions options = withSharedIp(InetAddress
|
||||||
|
.getByAddress(new byte[] { 127, 0, 0, 1 }));
|
||||||
|
buildRequest(options);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
{
|
||||||
|
"server" : {
|
||||||
|
"id" : 1234,
|
||||||
|
"name" : "sample-server",
|
||||||
|
"imageId" : 2,
|
||||||
|
"flavorId" : 1,
|
||||||
|
"hostId" : "e4d909c290d0fb1ca068ffaddf22cbd0",
|
||||||
|
"status" : "BUILD",
|
||||||
|
"progress" : 60,
|
||||||
|
"addresses" : {
|
||||||
|
"public" : [
|
||||||
|
"67.23.10.132",
|
||||||
|
"67.23.10.131"
|
||||||
|
],
|
||||||
|
"private" : [
|
||||||
|
"10.176.42.16"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"metadata" : {
|
||||||
|
"Server Label" : "Web Head 1",
|
||||||
|
"Image Version" : "2.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -40,6 +40,12 @@
|
||||||
<module>core</module>
|
<module>core</module>
|
||||||
</modules>
|
</modules>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>${project.groupId}</groupId>
|
||||||
|
<artifactId>jclouds-jsch</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>${project.groupId}</groupId>
|
<groupId>${project.groupId}</groupId>
|
||||||
<artifactId>jclouds-rackspace-core</artifactId>
|
<artifactId>jclouds-rackspace-core</artifactId>
|
||||||
|
|
Loading…
Reference in New Issue