Issue 814:move openstack-nova to org.jclouds.labs groupId

This commit is contained in:
Adrian Cole 2012-01-17 22:07:21 -08:00
parent 55c12680a3
commit de720b6da3
37 changed files with 1406 additions and 940 deletions

View File

@ -27,23 +27,23 @@
<version>1.4.0-SNAPSHOT</version> <version>1.4.0-SNAPSHOT</version>
<relativePath>../../project/pom.xml</relativePath> <relativePath>../../project/pom.xml</relativePath>
</parent> </parent>
<groupId>org.jclouds.api</groupId> <groupId>org.jclouds.labs</groupId>
<artifactId>openstack-nova</artifactId> <artifactId>openstack-nova</artifactId>
<name>jcloud openstack-nova api</name> <name>jcloud openstack-nova api</name>
<description>jclouds components to access an implementation of OpenStack Nova</description> <description>jclouds components to access an implementation of OpenStack Nova</description>
<packaging>bundle</packaging> <packaging>bundle</packaging>
<properties> <properties>
<test.openstack-nova.endpoint>http://localhost:8774/v1.1/</test.openstack-nova.endpoint> <!-- keystone endpoint -->
<test.openstack-nova.api-version>v1.1</test.openstack-nova.api-version> <test.openstack-nova.endpoint>http://localhost:5000</test.openstack-nova.endpoint>
<!-- keystone version -->
<test.openstack-nova.api-version>1.1</test.openstack-nova.api-version>
<test.openstack-nova.build-version></test.openstack-nova.build-version> <test.openstack-nova.build-version></test.openstack-nova.build-version>
<test.openstack-nova.identity>FIXME_IDENTITY</test.openstack-nova.identity> <test.openstack-nova.identity>FIXME_IDENTITY</test.openstack-nova.identity>
<test.openstack-nova.credential>FIXME_CREDENTIALS</test.openstack-nova.credential> <test.openstack-nova.credential>FIXME_CREDENTIALS</test.openstack-nova.credential>
<test.openstack-nova.image-id></test.openstack-nova.image-id> <test.openstack-nova.image-id></test.openstack-nova.image-id>
<test.openstack-nova.image.login-user></test.openstack-nova.image.login-user> <test.openstack-nova.image.login-user></test.openstack-nova.image.login-user>
<test.openstack-nova.image.authenticate-sudo></test.openstack-nova.image.authenticate-sudo> <test.openstack-nova.image.authenticate-sudo></test.openstack-nova.image.authenticate-sudo>
<test.ssh.keyfile.public></test.ssh.keyfile.public>
<test.ssh.keyfile.private></test.ssh.keyfile.private>
</properties> </properties>
<dependencies> <dependencies>
@ -86,10 +86,16 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.jclouds.driver</groupId> <groupId>org.jclouds.driver</groupId>
<artifactId>jclouds-log4j</artifactId> <artifactId>jclouds-slf4j</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>0.9.29</version>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<profiles> <profiles>
@ -100,12 +106,6 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId> <artifactId>maven-surefire-plugin</artifactId>
<dependencies>
<dependency>
<groupId>org.apache.maven.surefire</groupId>
<artifactId>surefire-testng</artifactId>
</dependency>
</dependencies>
<executions> <executions>
<execution> <execution>
<id>integration</id> <id>integration</id>
@ -123,8 +123,6 @@
<test.openstack-nova.image-id>${test.openstack-nova.image-id}</test.openstack-nova.image-id> <test.openstack-nova.image-id>${test.openstack-nova.image-id}</test.openstack-nova.image-id>
<test.openstack-nova.image.login-user>${test.openstack-nova.image.login-user}</test.openstack-nova.image.login-user> <test.openstack-nova.image.login-user>${test.openstack-nova.image.login-user}</test.openstack-nova.image.login-user>
<test.openstack-nova.image.authenticate-sudo>${test.openstack-nova.image.authenticate-sudo}</test.openstack-nova.image.authenticate-sudo> <test.openstack-nova.image.authenticate-sudo>${test.openstack-nova.image.authenticate-sudo}</test.openstack-nova.image.authenticate-sudo>
<test.ssh.keyfile.public>${test.ssh.keyfile.public}</test.ssh.keyfile.public>
<test.ssh.keyfile.private>${test.ssh.keyfile.private}</test.ssh.keyfile.private>
</systemPropertyVariables> </systemPropertyVariables>
</configuration> </configuration>
</execution> </execution>
@ -144,7 +142,12 @@
<instructions> <instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName> <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>org.jclouds.openstack.nova.v1_1.*;version="${project.version}"</Export-Package> <Export-Package>org.jclouds.openstack.nova.v1_1.*;version="${project.version}"</Export-Package>
<Import-Package>org.jclouds.*;version="${project.version}",*</Import-Package> <Import-Package>
org.jclouds.compute.internal;version="${project.version}",
org.jclouds.rest.internal;version="${project.version}",
org.jclouds.*;version="${project.version}",
*
</Import-Package>
</instructions> </instructions>
</configuration> </configuration>
</plugin> </plugin>

View File

@ -0,0 +1,38 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.openstack.nova.v1_1;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.inject.Qualifier;
/**
* @see <a href="http://docs.openstack.org/incubation/identity-dev-guide/content/Authenticate-Service-API-d1e1166.html"
* />
*
*/
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = { ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
@Qualifier
public @interface Compute {
}

View File

@ -20,13 +20,10 @@ package org.jclouds.openstack.nova.v1_1;
import static org.jclouds.Constants.PROPERTY_API_VERSION; import static org.jclouds.Constants.PROPERTY_API_VERSION;
import static org.jclouds.Constants.PROPERTY_ENDPOINT; import static org.jclouds.Constants.PROPERTY_ENDPOINT;
import static org.jclouds.Constants.PROPERTY_IDENTITY;
import java.util.Properties; import java.util.Properties;
import java.util.regex.Pattern;
import org.jclouds.PropertiesBuilder; import org.jclouds.PropertiesBuilder;
import org.jclouds.util.Strings2;
/** /**
* Builds properties used in Nova Clients * Builds properties used in Nova Clients
@ -37,8 +34,9 @@ public class NovaPropertiesBuilder extends PropertiesBuilder {
@Override @Override
protected Properties defaultProperties() { protected Properties defaultProperties() {
Properties properties = super.defaultProperties(); Properties properties = super.defaultProperties();
properties.setProperty(PROPERTY_ENDPOINT, "http://localhost:8774/{api-version}/{identity}"); // TODO: keystone
properties.setProperty(PROPERTY_API_VERSION, "v1.1"); properties.setProperty(PROPERTY_ENDPOINT, "http://localhost:5000");
properties.setProperty(PROPERTY_API_VERSION, "1.1");
return properties; return properties;
} }
@ -46,20 +44,4 @@ public class NovaPropertiesBuilder extends PropertiesBuilder {
super(properties); super(properties);
} }
public static final Pattern IDENTITY_PATTERN = Pattern.compile("\\{identity\\}");
public static final Pattern API_VERSION_PATTERN = Pattern.compile("\\{api-version\\}");
@Override
public Properties build() {
// TODO determine if we can more elegantly do this. right now we have to
// because URI.create() doesn't allow us to build a URi with an illegal
// character '{'
String endpoint = properties.getProperty(PROPERTY_ENDPOINT);
String identity = properties.getProperty(PROPERTY_IDENTITY);
String apiVersion = properties.getProperty(PROPERTY_API_VERSION);
String withIdentity = Strings2.replaceAll(endpoint, IDENTITY_PATTERN, identity);
String withVersion = Strings2.replaceAll(withIdentity, API_VERSION_PATTERN, apiVersion);
properties.setProperty(PROPERTY_ENDPOINT, withVersion);
return super.build();
}
} }

View File

@ -18,8 +18,11 @@
*/ */
package org.jclouds.openstack.nova.v1_1.config; package org.jclouds.openstack.nova.v1_1.config;
import java.net.URI;
import java.util.Map; import java.util.Map;
import javax.inject.Singleton;
import org.jclouds.http.HttpErrorHandler; import org.jclouds.http.HttpErrorHandler;
import org.jclouds.http.HttpRetryHandler; import org.jclouds.http.HttpRetryHandler;
import org.jclouds.http.RequiresHttp; import org.jclouds.http.RequiresHttp;
@ -27,16 +30,20 @@ import org.jclouds.http.annotation.ClientError;
import org.jclouds.http.annotation.Redirection; import org.jclouds.http.annotation.Redirection;
import org.jclouds.http.annotation.ServerError; import org.jclouds.http.annotation.ServerError;
import org.jclouds.http.handlers.BackoffLimitedRetryHandler; import org.jclouds.http.handlers.BackoffLimitedRetryHandler;
import org.jclouds.openstack.OpenStackAuthAsyncClient.AuthenticationResponse;
import org.jclouds.openstack.config.OpenStackAuthenticationModule; import org.jclouds.openstack.config.OpenStackAuthenticationModule;
import org.jclouds.openstack.nova.v1_1.Compute;
import org.jclouds.openstack.nova.v1_1.NovaAsyncClient; import org.jclouds.openstack.nova.v1_1.NovaAsyncClient;
import org.jclouds.openstack.nova.v1_1.NovaClient; import org.jclouds.openstack.nova.v1_1.NovaClient;
import org.jclouds.openstack.nova.v1_1.features.ServerAsyncClient; import org.jclouds.openstack.nova.v1_1.features.ServerAsyncClient;
import org.jclouds.openstack.nova.v1_1.features.ServerClient; import org.jclouds.openstack.nova.v1_1.features.ServerClient;
import org.jclouds.openstack.nova.v1_1.handlers.NovaErrorHandler; import org.jclouds.openstack.nova.v1_1.handlers.NovaErrorHandler;
import org.jclouds.openstack.reference.AuthHeaders;
import org.jclouds.rest.ConfiguresRestClient; import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.config.RestClientModule; import org.jclouds.rest.config.RestClientModule;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.inject.Provides;
/** /**
* Configures the Nova connection. * Configures the Nova connection.
@ -48,16 +55,23 @@ import com.google.common.collect.ImmutableMap;
public class NovaRestClientModule extends RestClientModule<NovaClient, NovaAsyncClient> { public class NovaRestClientModule extends RestClientModule<NovaClient, NovaAsyncClient> {
public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap.<Class<?>, Class<?>> builder()// public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap.<Class<?>, Class<?>> builder()//
.put(ServerClient.class, ServerAsyncClient.class)// .put(ServerClient.class, ServerAsyncClient.class)//
.build(); .build();
private final OpenStackAuthenticationModule authModule;
public NovaRestClientModule() { public NovaRestClientModule() {
this(new OpenStackAuthenticationModule());
}
public NovaRestClientModule(OpenStackAuthenticationModule authModule) {
super(NovaClient.class, NovaAsyncClient.class, DELEGATE_MAP); super(NovaClient.class, NovaAsyncClient.class, DELEGATE_MAP);
this.authModule = authModule;
} }
@Override @Override
protected void configure() { protected void configure() {
install(new OpenStackAuthenticationModule()); install(authModule);
install(new NovaParserModule()); install(new NovaParserModule());
super.configure(); super.configure();
} }
@ -74,4 +88,13 @@ public class NovaRestClientModule extends RestClientModule<NovaClient, NovaAsync
bind(HttpRetryHandler.class).annotatedWith(ClientError.class).to(BackoffLimitedRetryHandler.class); bind(HttpRetryHandler.class).annotatedWith(ClientError.class).to(BackoffLimitedRetryHandler.class);
} }
// TODO: get this from Keystone!!
// http://docs.openstack.org/incubation/identity-dev-guide/content/Authenticate-Service-API-d1e1166.html
@Provides
@Singleton
@Compute
protected URI provideServerUrl(AuthenticationResponse response) {
return response.getServices().get(AuthHeaders.SERVER_MANAGEMENT_URL);
}
} }

View File

@ -0,0 +1,155 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.openstack.nova.v1_1.domain;
import static com.google.common.base.Objects.equal;
import static com.google.common.base.Objects.toStringHelper;
import com.google.common.base.Objects;
/**
* IP address
*
* @author AdrianCole
*/
public class Address {
/**
* Relations associated with resources.
*/
public static enum Type {
/**
* publically routable address
*/
PUBLIC,
/**
* address that is not publicly routable.
*/
PRIVATE,
/**
* the value returned by the OpenStack service was not recognized.
*/
UNRECOGNIZED;
public String value() {
return name().toLowerCase();
}
public static Type fromValue(String v) {
try {
return valueOf(v.toUpperCase());
} catch (IllegalArgumentException e) {
return UNRECOGNIZED;
}
}
}
public static Builder builder() {
return new Builder();
}
public Builder toBuilder() {
return builder().fromAddress(this);
}
public static Address createV4(String addr) {
return builder().version(4).addr(addr).build();
}
public static Address createV6(String addr) {
return builder().version(6).addr(addr).build();
}
public static class Builder {
protected String addr;
protected int version;
/**
* @see Address#getVersion()
*/
protected Builder version(int version) {
this.version = version;
return this;
}
/**
* @see Address#getAddr()
*/
public Builder addr(String addr) {
this.addr = addr;
return this;
}
public Address build() {
return new Address(addr, version);
}
public Builder fromAddress(Address from) {
return addr(from.getAddr()).version(from.getVersion());
}
}
protected final String addr;
protected final int version;
public Address(String addr, int version) {
this.addr = addr;
this.version = version;
}
/**
* @return the ip address
*/
public String getAddr() {
return addr;
}
/**
* @return the IP version, ex. 4
*/
public int getVersion() {
return version;
}
@Override
public boolean equals(Object object) {
if (this == object) {
return true;
}
if (object instanceof Address) {
final Address other = Address.class.cast(object);
return equal(addr, other.addr) && equal(version, other.version);
} else {
return false;
}
}
@Override
public int hashCode() {
return Objects.hashCode(addr, version);
}
@Override
public String toString() {
return toStringHelper("").add("addr", addr).add("version", version).toString();
}
}

View File

@ -0,0 +1,168 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Href 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.openstack.nova.v1_1.domain;
import static com.google.common.base.Objects.equal;
import static com.google.common.base.Objects.toStringHelper;
import static com.google.common.base.Preconditions.checkNotNull;
import java.net.URI;
import com.google.common.base.Objects;
import com.google.gson.annotations.SerializedName;
/**
* For convenience, resources contain links to themselves. This allows a client to easily obtain a
* resource URIs rather than to construct them.
*
* @author AdrianCole
* @see <a href= "http://docs.openstack.org/api/openstack-compute/1.1/content/LinksReferences.html"
* />
*/
public class Link {
/**
* Relations associated with resources.
*/
public static enum Relation {
/**
* a versioned link to the resource. These links should be used in cases where the link will
* be followed immediately.
*/
SELF,
/**
* a permanent link to a resource that is appropriate for long term storage.
*/
BOOKMARK,
/**
* an alternate representation of the resource. For example, an OpenStack Compute image may
* have an alternate representation in the OpenStack Image service.
*/
ALTERNATE,
/**
* the value returned by the OpenStack service was not recognized.
*/
UNRECOGNIZED;
public String value() {
return name().toLowerCase();
}
public static Relation fromValue(String v) {
try {
return valueOf(v.toUpperCase());
} catch (IllegalArgumentException e) {
return UNRECOGNIZED;
}
}
}
public static Link create(Relation relation, URI href) {
return new Link(relation, href);
}
public static Builder builder() {
return new Builder();
}
public Builder toBuilder() {
return builder().fromLink(this);
}
public static class Builder {
protected Relation relation;
protected URI href;
/**
* @see Link#getRelation()
*/
public Builder relation(Relation relation) {
this.relation = checkNotNull(relation, "relation");
return this;
}
/**
* @see Link#getHref()
*/
protected Builder href(URI href) {
this.href = checkNotNull(href, "href");
return this;
}
public Builder fromLink(Link from) {
return relation(from.getRelation()).href(from.getHref());
}
}
@SerializedName("rel")
protected final Relation relation;
protected final URI href;
protected Link(Relation relation, URI href) {
this.relation = checkNotNull(relation, "relation");
this.href = checkNotNull(href, "href");
}
/**
* There are three kinds of link relations associated with resources. A self link contains a
* versioned link to the resource. These links should be used in cases where the link will be
* followed immediately. A bookmark link provides a permanent link to a resource that is
* appropriate for long term storage. An alternate link can contain an alternate representation
* of the resource. For example, an OpenStack Compute image may have an alternate representation
* in the OpenStack Image service. Note that the type attribute here is used to provide a hint as
* to the type of representation to expect when following the link.
*
* @return the relation of the resource in the current OpenStack deployment
*/
public Relation getRelation() {
return relation;
}
/**
* @return the href of the resource
*/
public URI getHref() {
return href;
}
@Override
public boolean equals(Object object) {
if (this == object) {
return true;
}
if (object instanceof Link) {
final Link other = Link.class.cast(object);
return equal(relation, other.relation) && equal(href, other.href);
} else {
return false;
}
}
@Override
public int hashCode() {
return Objects.hashCode(relation, href);
}
@Override
public String toString() {
return toStringHelper("").add("relation", relation).add("href", href).toString();
}
}

View File

@ -0,0 +1,160 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Name 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.openstack.nova.v1_1.domain;
import static com.google.common.base.Objects.equal;
import static com.google.common.base.Objects.toStringHelper;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Set;
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableSet;
/**
* Resource found in a paginated collection
*
* @author AdrianCole
* @see <a href=
* "http://docs.openstack.org/api/openstack-compute/1.1/content/Paginated_Collections-d1e664.html"
* />
*/
public class Resource implements Comparable<Resource> {
public static Builder builder() {
return new Builder();
}
public Builder toBuilder() {
return builder().fromResource(this);
}
public static class Builder {
protected String id;
protected String name;
protected Set<Link> links = ImmutableSet.of();
/**
* @see Resource#getId()
*/
public Builder id(String id) {
this.id = checkNotNull(id, "id");
return this;
}
/**
* @see Resource#getName()
*/
public Builder name(String name) {
this.name = checkNotNull(name, "name");
return this;
}
/**
* @see Resource#getLinks()
*/
public Builder links(Link... links) {
return links(ImmutableSet.copyOf(checkNotNull(links, "links")));
}
/**
* @see Resource#getLinks()
*/
public Builder links(Set<Link> links) {
this.links = ImmutableSet.copyOf(checkNotNull(links, "links"));
return this;
}
public Resource build() {
return new Resource(id, name, links);
}
public Builder fromResource(Resource from) {
return id(from.getId()).name(from.getName()).links(from.getLinks());
}
}
protected final String id;
protected final String name;
protected final Set<Link> links;
public Resource(String id, String name, Set<Link> links) {
this.id = checkNotNull(id, "id");
this.name = checkNotNull(name, "name");
this.links = ImmutableSet.copyOf(checkNotNull(links, "links"));
}
/**
* When providing an ID, it is assumed that the resource exists in the current OpenStack
* deployment
*
* @return the id of the resource in the current OpenStack deployment
*/
public String getId() {
return id;
}
/**
* @return the name of the resource
*/
public String getName() {
return name;
}
/**
* @return the links of the id address allocated to the new server
*/
public Set<Link> getLinks() {
return links;
}
@Override
public boolean equals(Object object) {
if (this == object) {
return true;
}
if (object instanceof Resource) {
final Resource other = Resource.class.cast(object);
return equal(id, other.id) && equal(name, other.name) && equal(links, other.links);
} else {
return false;
}
}
@Override
public int hashCode() {
return Objects.hashCode(id, name, links);
}
@Override
public String toString() {
return toStringHelper("").add("id", id).add("name", name).add("links", links).toString();
}
@Override
public int compareTo(Resource that) {
if (that == null)
return 1;
if (this == that)
return 0;
return this.id.compareTo(that.id);
}
}

View File

@ -0,0 +1,172 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.openstack.nova.v1_1.domain;
import static com.google.common.base.Objects.toStringHelper;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map;
import java.util.Set;
import org.jclouds.openstack.nova.v1_1.domain.Address.Type;
import org.jclouds.openstack.nova.v1_1.util.NovaUtils;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Multimap;
/**
* A server is a virtual machine instance in the compute system. Flavor and image are requisite
* elements when creating a server.
*
* @author Adrian Cole
* @see <a href=
* "http://docs.openstack.org/api/openstack-compute/1.1/content/Get_Server_Details-d1e2623.html"
* />
*/
public class Server extends Resource {
public static Builder builder() {
return new Builder();
}
public Builder toBuilder() {
return builder().fromServer(this);
}
public static class Builder extends Resource.Builder {
private Multimap<Address.Type, Address> addresses = LinkedHashMultimap.create();
/**
* @see Server#getAddresses()
*/
public Builder addresses(Multimap<Address.Type, Address> addresses) {
this.addresses = ImmutableMultimap.copyOf(checkNotNull(addresses, "addresses"));
return this;
}
/**
* @see Server#getPrivateAddresses()
*/
public Builder privateAddresses(Address... privateAddresses) {
return privateAddresses(ImmutableSet.copyOf(checkNotNull(privateAddresses, "privateAddresses")));
}
/**
* @see Server#getPrivateAddresses()
*/
public Builder privateAddresses(Set<Address> privateAddresses) {
this.addresses.replaceValues(Address.Type.PRIVATE, ImmutableSet.copyOf(checkNotNull(privateAddresses,
"privateAddresses")));
return this;
}
/**
* @see Server#getPublicAddresses()
*/
public Builder publicAddresses(Address... publicAddresses) {
return publicAddresses(ImmutableSet.copyOf(checkNotNull(publicAddresses, "publicAddresses")));
}
/**
* @see Server#getPublicAddresses()
*/
public Builder publicAddresses(Set<Address> publicAddresses) {
this.addresses.replaceValues(Address.Type.PUBLIC, ImmutableSet.copyOf(checkNotNull(publicAddresses,
"publicAddresses")));
return this;
}
public Server build() {
return new Server(id, name, links, addresses);
}
public Builder fromServer(Server in) {
return fromResource(in).addresses(in.getAddresses());
}
/**
* {@inheritDoc}
*/
@Override
public Builder id(String id) {
return Builder.class.cast(super.id(id));
}
/**
* {@inheritDoc}
*/
@Override
public Builder name(String name) {
return Builder.class.cast(super.name(name));
}
/**
* {@inheritDoc}
*/
@Override
public Builder links(Set<Link> links) {
return Builder.class.cast(super.links(links));
}
/**
* {@inheritDoc}
*/
@Override
public Builder fromResource(Resource in) {
return Builder.class.cast(super.fromResource(in));
}
}
// TODO: get gson multimap adapter!
protected final Map<Address.Type, Set<Address>> addresses;
protected Server(String id, String name, Set<Link> links, Multimap<Address.Type, Address> addresses) {
super(id, name, links);
this.addresses = NovaUtils.toOldSchool(ImmutableMultimap.copyOf(checkNotNull(addresses, "addresses")));
}
/**
* @return the private ip addresses assigned to the server
*/
public Set<Address> getPrivateAddresses() {
return ImmutableSet.copyOf(addresses.get(Address.Type.PRIVATE));
}
/**
* @return the public ip addresses assigned to the server
*/
public Set<Address> getPublicAddresses() {
return ImmutableSet.copyOf(addresses.get(Address.Type.PUBLIC));
}
/**
* @return the ip addresses assigned to the server
*/
public Multimap<Type, Address> getAddresses() {
return NovaUtils.fromOldSchool(addresses);
}
@Override
public String toString() {
return toStringHelper("").add("id", id).add("name", name).add("links", links).add("addresses", addresses)
.toString();
}
}

View File

@ -27,11 +27,14 @@ import javax.ws.rs.PathParam;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import org.jclouds.openstack.filters.AuthenticateRequest; import org.jclouds.openstack.filters.AuthenticateRequest;
import org.jclouds.openstack.nova.v1_1.Compute;
import org.jclouds.openstack.nova.v1_1.domain.Resource;
import org.jclouds.openstack.nova.v1_1.domain.Server; import org.jclouds.openstack.nova.v1_1.domain.Server;
import org.jclouds.openstack.nova.v1_1.domain.ServerDetails; import org.jclouds.rest.annotations.Endpoint;
import org.jclouds.rest.annotations.ExceptionParser; import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson; import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.annotations.SkipEncoding;
import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404; import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404;
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
@ -42,10 +45,13 @@ import com.google.common.util.concurrent.ListenableFuture;
* <p/> * <p/>
* *
* @see ServerClient * @see ServerClient
* @see <a href="http://docs.openstack.org/api/openstack-compute/1.1/content/" /> * @see <a href="http://docs.openstack.org/api/openstack-compute/1.1/content/Servers-d1e2073.html"
* />
* @author Adrian Cole * @author Adrian Cole
*/ */
@SkipEncoding({ '/', '=' })
@RequestFilters(AuthenticateRequest.class) @RequestFilters(AuthenticateRequest.class)
@Endpoint(Compute.class)
public interface ServerAsyncClient { public interface ServerAsyncClient {
/** /**
@ -56,16 +62,26 @@ public interface ServerAsyncClient {
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
@Path("/servers") @Path("/servers")
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
ListenableFuture<Set<Server>> listServers(); ListenableFuture<Set<Resource>> listServers();
/** /**
* @see ServerClient#getServerDetails * @see ServerClient#listServersInDetail
*/
@GET
@SelectJson("servers")
@Consumes(MediaType.APPLICATION_JSON)
@Path("/servers/detail")
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
ListenableFuture<Set<Server>> listServersInDetail();
/**
* @see ServerClient#getServer
*/ */
@GET @GET
@SelectJson("server") @SelectJson("server")
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
@Path("/servers/{id}") @Path("/servers/{id}")
@ExceptionParser(ReturnNullOnNotFoundOr404.class) @ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<ServerDetails> getServerDetails(@PathParam("id") String id); ListenableFuture<Server> getServer(@PathParam("id") String id);
} }

View File

@ -22,37 +22,42 @@ import java.util.Set;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.jclouds.concurrent.Timeout; import org.jclouds.concurrent.Timeout;
import org.jclouds.openstack.nova.v1_1.domain.Resource;
import org.jclouds.openstack.nova.v1_1.domain.Server; import org.jclouds.openstack.nova.v1_1.domain.Server;
import org.jclouds.openstack.nova.v1_1.domain.ServerDetails;
/** /**
* Provides synchronous access to Server. * Provides synchronous access to Server.
* <p/> * <p/>
* *
* @see ServerAsyncClient * @see ServerAsyncClient
* @see <a href="http://docs.openstack.org/api/openstack-compute/1.1/content/" /> * @see <a href="http://docs.openstack.org/api/openstack-compute/1.1/content/Servers-d1e2073.html"
* />
* @author Adrian Cole * @author Adrian Cole
*/ */
@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS) @Timeout(duration = 30, timeUnit = TimeUnit.SECONDS)
public interface ServerClient { public interface ServerClient {
/** /**
* Get a list of all servers on this account. * List all servers (IDs, names, links)
* *
* @return an account's associated server objects. * @return all servers (IDs, names, links)
*/ */
Set<Server> listServers(); Set<Resource> listServers();
/** /**
* Get detailed information about a server such as hostname, hardware * List all servers (all details)
* configuration (cpu, memory and disk), ip adresses, cost, transfer, os and *
* more. * @return all servers (all details)
*/
Set<Server> listServersInDetail();
/**
* List details of the specified server
* *
* @param id * @param id
* id of the server * id of the server
* @return server or null if not found * @return server or null if not found
*/ */
ServerDetails getServerDetails(String id); Server getServer(String id);
} }

View File

@ -18,7 +18,7 @@
*/ */
package org.jclouds.openstack.nova.v1_1.handlers; package org.jclouds.openstack.nova.v1_1.handlers;
import java.io.IOException; import static org.jclouds.http.HttpUtils.closeClientButKeepContentStream;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -28,10 +28,6 @@ import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpResponseException; import org.jclouds.http.HttpResponseException;
import org.jclouds.rest.AuthorizationException; import org.jclouds.rest.AuthorizationException;
import org.jclouds.rest.ResourceNotFoundException; import org.jclouds.rest.ResourceNotFoundException;
import org.jclouds.util.Strings2;
import com.google.common.base.Throwables;
import com.google.common.io.Closeables;
/** /**
* This will parse and set an appropriate exception on the command object. * This will parse and set an appropriate exception on the command object.
@ -44,47 +40,28 @@ public class NovaErrorHandler implements HttpErrorHandler {
public void handleError(HttpCommand command, HttpResponse response) { public void handleError(HttpCommand command, HttpResponse response) {
// it is important to always read fully and close streams // it is important to always read fully and close streams
String message = parseMessage(response); byte[] data = closeClientButKeepContentStream(response);
String message = data != null ? new String(data) : null;
Exception exception = message != null ? new HttpResponseException(command, response, message) Exception exception = message != null ? new HttpResponseException(command, response, message)
: new HttpResponseException(command, response); : new HttpResponseException(command, response);
try { message = message != null ? message : String.format("%s -> %s", command.getCurrentRequest().getRequestLine(),
message = message != null ? message : String.format("%s -> %s", command.getCurrentRequest().getRequestLine(), response.getStatusLine());
response.getStatusLine()); switch (response.getStatusCode()) {
switch (response.getStatusCode()) { case 401:
case 401: case 403:
case 403: exception = new AuthorizationException(message, exception);
exception = new AuthorizationException(message, exception); break;
break; case 404:
case 404: if (!command.getCurrentRequest().getMethod().equals("DELETE")) {
if (!command.getCurrentRequest().getMethod().equals("DELETE")) { exception = new ResourceNotFoundException(message, exception);
exception = new ResourceNotFoundException(message, exception); }
} break;
break; default:
case 500: exception = new HttpResponseException(command, response, message);
if (message != null && message.indexOf("Unable to determine package for") != -1) { break;
exception = new ResourceNotFoundException(message, exception);
}
}
} finally {
if (response.getPayload() != null)
Closeables.closeQuietly(response.getPayload().getInput());
command.setException(exception);
} }
command.setException(exception);
} }
public String parseMessage(HttpResponse response) {
if (response.getPayload() == null)
return null;
try {
return Strings2.toStringAndClose(response.getPayload().getInput());
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
try {
response.getPayload().getInput().close();
} catch (IOException e) {
Throwables.propagate(e);
}
}
}
} }

View File

@ -0,0 +1,63 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.openstack.nova.v1_1.util;
import java.util.Map;
import java.util.Set;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multimap;
import com.google.common.collect.ImmutableMultimap.Builder;
/**
*
* @author Adrian Cole
*/
public class NovaUtils {
/**
* The traditional way to represent a graph in Java is Map<V, Set<V>>, which is awkward in a
* number of ways. Guava's Multimap framework makes it easy to handle a mapping from keys to
* multiple values.
* <p/>
* Until we write or discover a gson Multimap deserializer, we may be stuck with this.
*
* TODO: ask on stackoverflow and/or jesse wilson
*/
@Deprecated
public static <K, V> Map<K, Set<V>> toOldSchool(Multimap<K, V> in) {
ImmutableMap.Builder<K, Set<V>> out = ImmutableMap.<K, Set<V>> builder();
for (K type : in.keySet())
out.put(type, ImmutableSet.copyOf(in.get(type)));
return out.build();
}
/**
* @see #toOldSchool
*/
@Deprecated
public static <K, V> ImmutableMultimap<K, V> fromOldSchool(Map<K, Set<V>> in) {
Builder<K, V> out = ImmutableMultimap.<K, V> builder();
for (K type : in.keySet())
out.putAll(type, ImmutableSet.copyOf(in.get(type)));
return out.build();
}
}

View File

@ -18,11 +18,11 @@
*/ */
package org.jclouds.openstack.nova.v1_1; package org.jclouds.openstack.nova.v1_1;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.reportMatcher; import static org.easymock.EasyMock.reportMatcher;
import static org.easymock.classextension.EasyMock.createMock; import static org.easymock.EasyMock.verify;
import static org.easymock.classextension.EasyMock.replay;
import static org.easymock.classextension.EasyMock.verify;
import java.net.URI; import java.net.URI;
@ -31,9 +31,9 @@ import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.io.Payloads; import org.jclouds.io.Payloads;
import org.jclouds.openstack.nova.v1_1.handlers.NovaErrorHandler;
import org.jclouds.rest.AuthorizationException; import org.jclouds.rest.AuthorizationException;
import org.jclouds.rest.ResourceNotFoundException; import org.jclouds.rest.ResourceNotFoundException;
import org.jclouds.openstack.nova.v1_1.handlers.NovaErrorHandler;
import org.jclouds.util.Strings2; import org.jclouds.util.Strings2;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -46,26 +46,15 @@ import com.google.inject.Guice;
@Test(groups = { "unit" }) @Test(groups = { "unit" })
public class NovaErrorHandlerTest { public class NovaErrorHandlerTest {
@Test
public void test500MakesResourceNotFoundExceptionOnUnableToDeterminePackage() {
assertCodeMakes(
"GET",
URI.create("https://api.openstack.nova.v1_1.com/foo"),
500,
"",
"{\"error\":\"Unable to determine package for 'node2102835255.me.org'.\"}",
ResourceNotFoundException.class);
}
@Test @Test
public void test401MakesAuthorizationException() { public void test401MakesAuthorizationException() {
assertCodeMakes("GET", URI.create("https://api.openstack.nova.v1_1.com/foo"), 401, "", "Unauthorized", assertCodeMakes("GET", URI.create("https://api.openstack.nova.com/foo"), 401, "", "Unauthorized",
AuthorizationException.class); AuthorizationException.class);
} }
@Test @Test
public void test404MakesResourceNotFoundException() { public void test404MakesResourceNotFoundException() {
assertCodeMakes("GET", URI.create("https://api.openstack.nova.v1_1.com/foo"), 404, "", "Not Found", assertCodeMakes("GET", URI.create("https://api.openstack.nova.com/foo"), 404, "", "Not Found",
ResourceNotFoundException.class); ResourceNotFoundException.class);
} }

View File

@ -0,0 +1,78 @@
package org.jclouds.openstack.nova.v1_1.features;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import java.net.URI;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaRestClientExpectTest;
import org.jclouds.openstack.nova.v1_1.parse.ParseServerListTest;
import org.jclouds.openstack.nova.v1_1.parse.ParseServerTest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMultimap;
/**
* Tests annotation parsing of {@code ServerAsyncClient}
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "ServerAsyncClientTest")
public class ServerClientExpectTest extends BaseNovaRestClientExpectTest {
public ServerClientExpectTest() {
provider = "openstack-nova";
}
public void testListServersWhenResponseIs2xx() throws Exception {
HttpRequest listServers = HttpRequest.builder().method("GET")
.endpoint(URI.create("http://localhost:8774/v1.1/identity/servers"))
.headers(ImmutableMultimap.<String, String> builder()
.put("Accept", "application/json")
.put("X-Auth-Token", authToken).build()).build();
HttpResponse listServersResponse = HttpResponse.builder().statusCode(200).payload(
payloadFromResource("/server_list.json")).build();
ServerClient clientWhenServersExist = requestsSendResponses(initialAuth, responseWithUrls, listServers,
listServersResponse).getServerClient();
assertEquals(clientWhenServersExist.listServers().toString(), new ParseServerListTest().expected().toString());
}
public void testListServersWhenReponseIs404IsEmpty() throws Exception {
HttpRequest listServers = HttpRequest.builder().method("GET")
.endpoint(URI.create("http://localhost:8774/v1.1/identity/servers"))
.headers(ImmutableMultimap.<String, String> builder()
.put("Accept", "application/json")
.put("X-Auth-Token", authToken).build()).build();
HttpResponse listServersResponse = HttpResponse.builder().statusCode(404).build();
ServerClient clientWhenServersExist = requestsSendResponses(initialAuth, responseWithUrls, listServers,
listServersResponse).getServerClient();
assertTrue(clientWhenServersExist.listServers().isEmpty());
}
//TODO: gson deserializer for Multimap
@Test
public void testGetServerWhenResponseIs2xx() throws Exception {
HttpRequest listServers = HttpRequest.builder().method("GET")
.endpoint(URI.create("http://localhost:8774/v1.1/identity/servers/foo"))
.headers(ImmutableMultimap.<String, String> builder()
.put("Accept", "application/json")
.put("X-Auth-Token", authToken).build()).build();
HttpResponse listServersResponse = HttpResponse.builder().statusCode(200).payload(
payloadFromResource("/server_details.json")).build();
ServerClient clientWhenServersExist = requestsSendResponses(initialAuth, responseWithUrls, listServers,
listServersResponse).getServerClient();
assertEquals(clientWhenServersExist.getServer("foo").toString(), new ParseServerTest().expected().toString());
}
}

View File

@ -23,8 +23,9 @@ import static org.testng.Assert.assertTrue;
import java.util.Set; import java.util.Set;
import org.jclouds.openstack.nova.v1_1.domain.Resource;
import org.jclouds.openstack.nova.v1_1.domain.Server; import org.jclouds.openstack.nova.v1_1.domain.Server;
import org.jclouds.openstack.nova.v1_1.domain.ServerDetails; import org.jclouds.openstack.nova.v1_1.internal.BaseNovaClientLiveTest;
import org.testng.annotations.BeforeGroups; import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -36,7 +37,7 @@ import org.testng.annotations.Test;
@Test(groups = "live", testName = "ServerClientLiveTest") @Test(groups = "live", testName = "ServerClientLiveTest")
public class ServerClientLiveTest extends BaseNovaClientLiveTest { public class ServerClientLiveTest extends BaseNovaClientLiveTest {
@BeforeGroups(groups = {"live"}) @BeforeGroups(groups = { "live" })
public void setupClient() { public void setupClient() {
super.setupClient(); super.setupClient();
client = context.getApi().getServerClient(); client = context.getApi().getServerClient();
@ -45,24 +46,20 @@ public class ServerClientLiveTest extends BaseNovaClientLiveTest {
private ServerClient client; private ServerClient client;
@Test @Test
public void testListServers() throws Exception { public void testListServersInDetail() throws Exception {
Set<Server> response = client.listServers(); Set<Resource> response = client.listServers();
assert null != response; assert null != response;
assertTrue(response.size() >= 0); assertTrue(response.size() >= 0);
for (Server server : response) { for (Resource server : response) {
ServerDetails newDetails = client.getServerDetails(server.getId()); Server newDetails = client.getServer(server.getId());
assertEquals(newDetails.getId(), server.getId()); assertEquals(newDetails.getId(), server.getId());
assertEquals(newDetails.getHostname(), server.getHostname()); assertEquals(newDetails.getName(), server.getName());
assertEquals(newDetails.getPlatform(), server.getPlatform()); assertEquals(newDetails.getLinks(), server.getLinks());
assertEquals(newDetails.getDatacenter(), server.getDatacenter());
checkServer(newDetails); checkServer(newDetails);
} }
} }
private void checkServer(ServerDetails server) { private void checkServer(Server server) {
// description can be null assert server.getAddresses().size() > 0 : server;
assert server.getCpuCores() > 0 : server;
assert server.getDisk() > 0 : server;
assert server.getMemory() > 0 : server;
} }
} }

View File

@ -16,7 +16,7 @@
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*/ */
package org.jclouds.openstack.nova.v1_1.features; package org.jclouds.openstack.nova.v1_1.internal;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;

View File

@ -16,13 +16,14 @@
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*/ */
package org.jclouds.openstack.nova.v1_1.features; package org.jclouds.openstack.nova.v1_1.internal;
import static com.google.common.base.Preconditions.checkNotNull; import java.util.Properties;
import org.jclouds.compute.BaseVersionedServiceLiveTest;
import org.jclouds.logging.slf4j.config.SLF4JLoggingModule;
import org.jclouds.openstack.nova.v1_1.NovaAsyncClient; import org.jclouds.openstack.nova.v1_1.NovaAsyncClient;
import org.jclouds.openstack.nova.v1_1.NovaClient; import org.jclouds.openstack.nova.v1_1.NovaClient;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.rest.RestContext; import org.jclouds.rest.RestContext;
import org.jclouds.rest.RestContextFactory; import org.jclouds.rest.RestContextFactory;
import org.jclouds.sshj.config.SshjSshClientModule; import org.jclouds.sshj.config.SshjSshClientModule;
@ -39,18 +40,20 @@ import com.google.inject.Module;
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test(groups = "live") @Test(groups = "live")
public class BaseNovaClientLiveTest { public class BaseNovaClientLiveTest extends BaseVersionedServiceLiveTest {
public BaseNovaClientLiveTest() {
provider = "openstack-nova";
}
protected RestContext<NovaClient, NovaAsyncClient> context; protected RestContext<NovaClient, NovaAsyncClient> context;
@BeforeGroups(groups = { "live" }) @BeforeGroups(groups = { "live" })
public void setupClient() { public void setupClient() {
String identity = checkNotNull(System.getProperty("test.openstack.nova.v1_1.identity"), "test.openstack.nova.v1_1.identity"); setupCredentials();
String credential = checkNotNull(System.getProperty("test.openstack.nova.v1_1.credential"), "test.openstack.nova.v1_1.credential"); Properties overrides = setupProperties();
context = new RestContextFactory().createContext(provider, identity, credential,
context = new RestContextFactory().createContext("openstack-nova", identity, credential, ImmutableSet.<Module> of(new SLF4JLoggingModule(), new SshjSshClientModule()), overrides);
ImmutableSet.<Module> of(new Log4JLoggingModule(), new SshjSshClientModule()));
} }
@AfterGroups(groups = "live") @AfterGroups(groups = "live")

View File

@ -0,0 +1,115 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.openstack.nova.v1_1.internal;
import java.net.URI;
import java.util.Date;
import org.jclouds.date.internal.SimpleDateFormatDateService;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.RequiresHttp;
import org.jclouds.openstack.config.OpenStackAuthenticationModule;
import org.jclouds.openstack.filters.AddTimestampQuery;
import org.jclouds.openstack.nova.v1_1.NovaClient;
import org.jclouds.openstack.nova.v1_1.config.NovaRestClientModule;
import org.jclouds.rest.BaseRestClientExpectTest;
import org.jclouds.rest.ConfiguresRestClient;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableMultimap;
import com.google.inject.Module;
/**
* Base class for writing Nova Rest Client Expect tests
*
* @author Adrian Cole
*/
public class BaseNovaRestClientExpectTest extends BaseRestClientExpectTest<NovaClient> {
public BaseNovaRestClientExpectTest() {
provider = "openstack-nova";
}
//TODO: change to keystone
protected HttpRequest initialAuth = HttpRequest.builder().method("GET").endpoint(URI.create("http://localhost:5000/v1.1"))
.headers(
ImmutableMultimap.<String, String> builder()
.put("X-Auth-User", "identity")
.put("X-Auth-Key", "credential")
.put("Accept", "*/*").build()).build();
protected String authToken = "d6245d35-22a0-47c0-9770-2c5097da25fc";
// FIXME: KeyStone
protected HttpResponse responseWithUrls = HttpResponse
.builder()
.statusCode(204)
.message("HTTP/1.1 204 No Content")
.headers(ImmutableMultimap.<String,String>builder()
.put("Server", "Apache/2.2.3 (Red Hat)")
.put("vary", "X-Auth-Token,X-Auth-Key,X-Storage-User,X-Storage-Pass")
.put("Cache-Control", "s-maxage=86399")
.put("Content-Type", "text/xml")
.put("Date", "Tue, 10 Jan 2012 22:08:47 GMT")
.put("X-Auth-Token", authToken)
.put("X-Server-Management-Url","http://localhost:8774/v1.1/identity")
.put("Connection", "Keep-Alive")
.put("Content-Length", "0")
.build()).build();
protected static final String CONSTANT_DATE = "2009-11-08T15:54:08.897Z";
/**
* override so that we can control the timestamp used in {@link AddTimestampQuery}
*/
static class TestOpenStackAuthenticationModule extends OpenStackAuthenticationModule {
@Override
protected void configure() {
super.configure();
}
@Override
public Supplier<Date> provideCacheBusterDate() {
return new Supplier<Date>() {
public Date get() {
return new SimpleDateFormatDateService().iso8601DateParse(CONSTANT_DATE);
}
};
}
}
@Override
protected Module createModule() {
return new TestNovaRestClientModule();
}
@ConfiguresRestClient
@RequiresHttp
protected static class TestNovaRestClientModule extends NovaRestClientModule {
private TestNovaRestClientModule() {
super(new TestOpenStackAuthenticationModule());
}
}
}

View File

@ -0,0 +1,96 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.openstack.nova.v1_1.parse;
import java.net.URI;
import java.util.Set;
import javax.ws.rs.Consumes;
import javax.ws.rs.core.MediaType;
import org.jclouds.json.BaseSetParserTest;
import org.jclouds.json.config.GsonModule;
import org.jclouds.openstack.nova.v1_1.config.NovaParserModule;
import org.jclouds.openstack.nova.v1_1.domain.Link;
import org.jclouds.openstack.nova.v1_1.domain.Resource;
import org.jclouds.openstack.nova.v1_1.domain.Link.Relation;
import org.jclouds.rest.annotations.SelectJson;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Guice;
import com.google.inject.Injector;
/**
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "ParseServerListTest")
public class ParseServerListTest extends BaseSetParserTest<Resource> {
@Override
public String resource() {
return "/server_list.json";
}
@Override
@SelectJson("servers")
@Consumes(MediaType.APPLICATION_JSON)
public Set<Resource> expected() {
return ImmutableSet
.of(
Resource
.builder()
.id("52415800-8b69-11e0-9b19-734f6af67565")
.name("sample-server")
.links(
Link
.create(
Relation.SELF,
URI
.create("http://servers.api.openstack.org/v1.1/1234/servers/52415800-8b69-11e0-9b19-734f6af67565")),
Link
.create(
Relation.BOOKMARK,
URI
.create("http://servers.api.openstack.org/1234/servers/52415800-8b69-11e0-9b19-734f6af67565")))
.build(),
Resource
.builder()
.id("52415800-8b69-11e0-9b19-734f1f1350e5")
.name("sample-server2")
.links(
Link
.create(
Relation.SELF,
URI
.create("http://servers.api.openstack.org/v1.1/1234/servers/52415800-8b69-11e0-9b19-734f1f1350e5")),
Link
.create(
Relation.BOOKMARK,
URI
.create("http://servers.api.openstack.org/1234/servers/52415800-8b69-11e0-9b19-734f1f1350e5")))
.build());
}
protected Injector injector() {
return Guice.createInjector(new NovaParserModule(), new GsonModule());
}
}

View File

@ -24,7 +24,8 @@ import javax.ws.rs.core.MediaType;
import org.jclouds.json.BaseItemParserTest; import org.jclouds.json.BaseItemParserTest;
import org.jclouds.json.config.GsonModule; import org.jclouds.json.config.GsonModule;
import org.jclouds.openstack.nova.v1_1.config.NovaParserModule; import org.jclouds.openstack.nova.v1_1.config.NovaParserModule;
import org.jclouds.openstack.nova.v1_1.domain.ServerDetails; import org.jclouds.openstack.nova.v1_1.domain.Address;
import org.jclouds.openstack.nova.v1_1.domain.Server;
import org.jclouds.rest.annotations.SelectJson; import org.jclouds.rest.annotations.SelectJson;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -32,27 +33,31 @@ import com.google.inject.Guice;
import com.google.inject.Injector; import com.google.inject.Injector;
/** /**
*
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test(groups = "unit", testName = "ParseServerDetailsTest") @Test(groups = "unit", testName = "ParseServerTest")
public class ParseServerDetailsTest extends BaseItemParserTest<ServerDetails> { public class ParseServerTest extends BaseItemParserTest<Server> {
@Override @Override
public String resource() { public String resource() {
return "/server.json"; return "/server_details.json";
} }
@Override @Override
@SelectJson("server") @SelectJson("server")
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
public ServerDetails expected() { public Server expected() {
return ServerDetails.builder().id("vz1541880").hostname("mammamia").datacenter("Falkenberg").platform("OpenVZ") return Server
.description("description").cpuCores(1).memory(128).disk(5).build(); .builder()
.id("52415800-8b69-11e0-9b19-734f000004d2")
.name("sample-server")
.publicAddresses(Address.createV4("67.23.10.132"), Address.createV6("::babe:67.23.10.132"),
Address.createV4("67.23.10.131"), Address.createV6("::babe:4317:0A83")).privateAddresses(
Address.createV4("10.176.42.16"), Address.createV6("::babe:10.176.42.16")).build();
} }
protected Injector injector() { protected Injector injector() {
return Guice.createInjector(new NovaParserModule(), new GsonModule()); return Guice.createInjector(new NovaParserModule(), new GsonModule());
} }
} }

View File

@ -0,0 +1,64 @@
<?xml version="1.0"?>
<configuration scan="false">
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>target/test-data/jclouds.log</file>
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%d %-5p [%c] (%t) %m%n</Pattern>
</layout>
</appender>
<appender name="WIREFILE" class="ch.qos.logback.core.FileAppender">
<file>target/test-data/jclouds-wire.log</file>
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%d %-5p [%c] (%t) %m%n</Pattern>
</layout>
</appender>
<appender name="COMPUTEFILE" class="ch.qos.logback.core.FileAppender">
<file>target/test-data/jclouds-compute.log</file>
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%d %-5p [%c] (%t) %m%n</Pattern>
</layout>
</appender>
<appender name="SSHFILE" class="ch.qos.logback.core.FileAppender">
<file>target/test-data/jclouds-ssh.log</file>
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%d %-5p [%c] (%t) %m%n</Pattern>
</layout>
</appender>
<root>
<level value="warn" />
</root>
<logger name="org.jclouds">
<level value="DEBUG" />
<appender-ref ref="FILE" />
</logger>
<logger name="jclouds.wire">
<level value="DEBUG" />
<appender-ref ref="WIREFILE" />
</logger>
<logger name="jclouds.headers">
<level value="DEBUG" />
<appender-ref ref="WIREFILE" />
</logger>
<logger name="jclouds.compute">
<level value="DEBUG" />
<appender-ref ref="COMPUTEFILE" />
</logger>
<logger name="jclouds.ssh">
<level value="DEBUG" />
<appender-ref ref="SSHFILE" />
</logger>
</configuration>

View File

@ -0,0 +1,77 @@
{
"server": {
"id": "52415800-8b69-11e0-9b19-734f000004d2",
"tenant_id": "1234",
"user_id": "5678",
"name": "sample-server",
"updated": "2010-10-10T12:00:00Z",
"created": "2010-08-10T12:00:00Z",
"hostId": "e4d909c290d0fb1ca068ffaddf22cbd0",
"accessIPv4" : "67.23.10.132",
"accessIPv6" : "::babe:67.23.10.132",
"status": "BUILD",
"progress": 60,
"image" : {
"id": "52415800-8b69-11e0-9b19-734f6f006e54",
"links": [
{
"rel": "self",
"href": "http://servers.api.openstack.org/v1.1/1234/images/52415800-8b69-11e0-9b19-734f6f006e54"
},
{
"rel": "bookmark",
"href": "http://servers.api.openstack.org/1234/images/52415800-8b69-11e0-9b19-734f6f006e54"
}
]
},
"flavor" : {
"id": "52415800-8b69-11e0-9b19-734f216543fd",
"links": [
{
"rel": "self",
"href": "http://servers.api.openstack.org/v1.1/1234/flavors/52415800-8b69-11e0-9b19-734f216543fd"
},
{
"rel": "bookmark",
"href": "http://servers.api.openstack.org/1234/flavors/52415800-8b69-11e0-9b19-734f216543fd"
}
]
},
"addresses": {
"public" : [
{
"version": 4,
"addr": "67.23.10.132"
},
{
"version": 6,
"addr": "::babe:67.23.10.132"
},
{
"version": 4,
"addr": "67.23.10.131"
},
{
"version": 6,
"addr": "::babe:4317:0A83"
}
],
"private" : [
{
"version": 4,
"addr": "10.176.42.16"
},
{
"version": 6,
"addr": "::babe:10.176.42.16"
}
]
},
"metadata": {
"Server Label": "Web Head 1",
"Image Version": "2.1"
},
"links": [
]
}
}

View File

@ -0,0 +1,32 @@
{
"servers": [
{
"id": "52415800-8b69-11e0-9b19-734f6af67565",
"name": "sample-server",
"links": [
{
"rel": "self",
"href": "http://servers.api.openstack.org/v1.1/1234/servers/52415800-8b69-11e0-9b19-734f6af67565"
},
{
"rel": "bookmark",
"href": "http://servers.api.openstack.org/1234/servers/52415800-8b69-11e0-9b19-734f6af67565"
}
]
},
{
"id": "52415800-8b69-11e0-9b19-734f1f1350e5",
"name": "sample-server2",
"links": [
{
"rel": "self",
"href": "http://servers.api.openstack.org/v1.1/1234/servers/52415800-8b69-11e0-9b19-734f1f1350e5"
},
{
"rel": "bookmark",
"href": "http://servers.api.openstack.org/1234/servers/52415800-8b69-11e0-9b19-734f1f1350e5"
}
]
}
]
}

37
labs/pom.xml Normal file
View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to jclouds, Inc. (jclouds) under one or more
contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. jclouds licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>jclouds-project</artifactId>
<groupId>org.jclouds</groupId>
<version>1.4.0-SNAPSHOT</version>
<relativePath>../project/pom.xml</relativePath>
</parent>
<groupId>org.jclouds.labs</groupId>
<artifactId>jclouds-labs-project</artifactId>
<packaging>pom</packaging>
<name>jclouds labs project</name>
<modules>
<module>openstack-nova</module>
</modules>
</project>

View File

@ -40,6 +40,7 @@
<module>compute</module> <module>compute</module>
<module>loadbalancer</module> <module>loadbalancer</module>
<module>apis</module> <module>apis</module>
<module>labs</module>
<module>providers</module> <module>providers</module>
<module>blobstore</module> <module>blobstore</module>
<module>skeletons</module> <module>skeletons</module>

View File

@ -1,160 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.openstack.nova.v1_1.domain;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.gson.annotations.SerializedName;
/**
* Listing of a server.
*
* @author Adrian Cole
* @see <a href= "http://docs.openstack.org/api/openstack-compute/1.1/content/?a=doc#server_list" />
*/
public class Server {
public static Builder builder() {
return new Builder();
}
public static class Builder {
protected String id;
protected String hostname;
protected String datacenter;
protected String platform;
public Builder id(String id) {
this.id = id;
return this;
}
public Builder hostname(String hostname) {
this.hostname = hostname;
return this;
}
public Builder datacenter(String datacenter) {
this.datacenter = datacenter;
return this;
}
public Builder platform(String platform) {
this.platform = platform;
return this;
}
public Server build() {
return new Server(id, hostname, datacenter, platform);
}
public Builder fromServer(Server in) {
return datacenter(in.getDatacenter()).platform(in.getPlatform()).hostname(in.getHostname()).id(in.getId());
}
}
@SerializedName("serverid")
protected final String id;
protected final String hostname;
protected final String datacenter;
protected final String platform;
public Server(String id, String hostname, String datacenter, String platform) {
this.id = checkNotNull(id, "id");
this.hostname = checkNotNull(hostname, "hostname");
this.datacenter = checkNotNull(datacenter, "datacenter");
this.platform = checkNotNull(platform, "platform");
}
/**
* @return the generated id of the server
*/
public String getId() {
return id;
}
/**
* @return the hostname of the server
*/
public String getHostname() {
return hostname;
}
/**
* @return platform running the server (ex. {@code OpenVZ})
*/
public String getPlatform() {
return platform;
}
/**
* @return the datacenter the server exists in (ex. {@code Falkenberg})
*/
public String getDatacenter() {
return datacenter;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((datacenter == null) ? 0 : datacenter.hashCode());
result = prime * result + ((hostname == null) ? 0 : hostname.hashCode());
result = prime * result + ((id == null) ? 0 : id.hashCode());
result = prime * result + ((platform == null) ? 0 : platform.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Server other = (Server) obj;
if (datacenter == null) {
if (other.datacenter != null)
return false;
} else if (!datacenter.equals(other.datacenter))
return false;
if (hostname == null) {
if (other.hostname != null)
return false;
} else if (!hostname.equals(other.hostname))
return false;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
if (platform == null) {
if (other.platform != null)
return false;
} else if (!platform.equals(other.platform))
return false;
return true;
}
@Override
public String toString() {
return String.format("[id=%s, hostname=%s, datacenter=%s, platform=%s]", id, hostname, datacenter, platform);
}
}

View File

@ -1,150 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.openstack.nova.v1_1.domain;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.gson.annotations.SerializedName;
/**
* Detailed information about a server such as cpuCores, hardware configuration
* (cpu, memory and disk), ip adresses, cost, transfer, os and more.
*
* @author Adrian Cole
* @see <a href=
* "http://docs.openstack.org/api/openstack-compute/1.1/content/?a=doc#server_details"
* />
*/
public class ServerDetails extends Server {
public static Builder builder() {
return new Builder();
}
public static class Builder extends Server.Builder {
private String description;
private int cpuCores;
private int memory;
private int disk;
public Builder description(String description) {
this.description = description;
return this;
}
public Builder cpuCores(int cpuCores) {
this.cpuCores = cpuCores;
return this;
}
public Builder memory(int memory) {
this.memory = memory;
return this;
}
public Builder disk(int disk) {
this.disk = disk;
return this;
}
public ServerDetails build() {
return new ServerDetails(id, hostname, datacenter, platform, description, cpuCores, memory, disk);
}
public Builder fromServerDetails(ServerDetails in) {
return fromServer(in).memory(in.getMemory()).disk(in.getDisk()).cpuCores(in.getCpuCores())
.description(in.getDescription());
}
@Override
public Builder id(String id) {
return Builder.class.cast(super.id(id));
}
@Override
public Builder hostname(String hostname) {
return Builder.class.cast(super.hostname(hostname));
}
@Override
public Builder datacenter(String datacenter) {
return Builder.class.cast(super.datacenter(datacenter));
}
@Override
public Builder platform(String platform) {
return Builder.class.cast(super.platform(platform));
}
@Override
public Builder fromServer(Server in) {
return Builder.class.cast(super.fromServer(in));
}
}
private final String description;
@SerializedName("cpucores")
private final int cpuCores;
private final int memory;
private final int disk;
public ServerDetails(String id, String hostname, String datacenter, String platform, String description,
int cpuCores, int memory, int disk) {
super(id, hostname, datacenter, platform);
this.description = checkNotNull(description, "description");
this.cpuCores = cpuCores;
this.memory = memory;
this.disk = disk;
}
/**
* @return the user-specified description of the server
*/
public String getDescription() {
return description;
}
/**
* @return number of cores on the server
*/
public int getCpuCores() {
return cpuCores;
}
/**
* @return the disk of the server in GB
*/
public int getDisk() {
return disk;
}
/**
* @return the memory of the server in MB
*/
public int getMemory() {
return memory;
}
@Override
public String toString() {
return String.format(
"[id=%s, hostname=%s, datacenter=%s, platform=%s, description=%s, cpuCores=%s, memory=%s, disk=%s]", id,
hostname, datacenter, platform, description, cpuCores, memory, disk);
}
}

View File

@ -1,71 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.openstack.nova.v1_1;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import org.jclouds.http.HttpRequest;
import org.jclouds.openstack.nova.v1_1.features.BaseNovaAsyncClientTest;
import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import com.google.inject.TypeLiteral;
/**
* Tests behavior of {@code NovaAsyncClient}
*
* @author Adrian Cole
*/
// NOTE:without testName, this will not call @Before* and fail w/NPE during
// surefire
@Test(groups = "unit", testName = "NovaAsyncClientTest")
public class NovaAsyncClientTest extends BaseNovaAsyncClientTest<NovaAsyncClient> {
private NovaAsyncClient asyncClient;
private NovaClient syncClient;
public void testSync() throws SecurityException, NoSuchMethodException, InterruptedException, ExecutionException {
assert syncClient.getServerClient() != null;
}
public void testAsync() throws SecurityException, NoSuchMethodException, InterruptedException, ExecutionException {
assert asyncClient.getServerClient() != null;
}
@Override
protected TypeLiteral<RestAnnotationProcessor<NovaAsyncClient>> createTypeLiteral() {
return new TypeLiteral<RestAnnotationProcessor<NovaAsyncClient>>() {
};
}
@BeforeClass
@Override
protected void setupFactory() throws IOException {
super.setupFactory();
asyncClient = injector.getInstance(NovaAsyncClient.class);
syncClient = injector.getInstance(NovaClient.class);
}
@Override
protected void checkFilters(HttpRequest request) {
}
}

View File

@ -1,79 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.openstack.nova.v1_1.features;
import java.io.IOException;
import java.lang.reflect.Method;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.functions.ParseFirstJsonValueNamed;
import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404;
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.testng.annotations.Test;
import com.google.inject.TypeLiteral;
/**
* Tests annotation parsing of {@code ServerAsyncClient}
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "ServerAsyncClientTest")
public class ServerAsyncClientTest extends BaseNovaAsyncClientTest<ServerAsyncClient> {
public void testListServers() throws SecurityException, NoSuchMethodException, IOException {
Method method = ServerAsyncClient.class.getMethod("listServers");
HttpRequest httpRequest = processor.createRequest(method);
assertRequestLineEquals(httpRequest, "GET http://localhost:8774/v1.1/accountId/servers HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null, null, false);
assertResponseParserClassEquals(method, httpRequest, ParseFirstJsonValueNamed.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, ReturnEmptySetOnNotFoundOr404.class);
checkFilters(httpRequest);
}
public void testGetServer() throws SecurityException, NoSuchMethodException, IOException {
Method method = ServerAsyncClient.class.getMethod("getServerDetails", String.class);
HttpRequest httpRequest = processor.createRequest(method, "abcd");
assertRequestLineEquals(httpRequest,
"GET http://localhost:8774/v1.1/accountId/servers/abcd HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null, null, false);
assertResponseParserClassEquals(method, httpRequest, ParseFirstJsonValueNamed.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
checkFilters(httpRequest);
}
@Override
protected TypeLiteral<RestAnnotationProcessor<ServerAsyncClient>> createTypeLiteral() {
return new TypeLiteral<RestAnnotationProcessor<ServerAsyncClient>>() {
};
}
}

View File

@ -1,61 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.openstack.nova.v1_1.parse;
import java.util.Set;
import javax.ws.rs.Consumes;
import javax.ws.rs.core.MediaType;
import org.jclouds.json.BaseSetParserTest;
import org.jclouds.json.config.GsonModule;
import org.jclouds.openstack.nova.v1_1.config.NovaParserModule;
import org.jclouds.openstack.nova.v1_1.domain.Server;
import org.jclouds.rest.annotations.SelectJson;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Guice;
import com.google.inject.Injector;
/**
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "ParseServerListTest")
public class ParseServerListTest extends BaseSetParserTest<Server> {
@Override
public String resource() {
return "/server_list.json";
}
@Override
@SelectJson("servers")
@Consumes(MediaType.APPLICATION_JSON)
public Set<Server> expected() {
return ImmutableSet.of(Server.builder().id("vz1541880").hostname("mammamia").datacenter("Falkenberg")
.platform("OpenVZ").build());
}
protected Injector injector() {
return Guice.createInjector(new NovaParserModule(), new GsonModule());
}
}

View File

@ -1,151 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<!--
For more configuration infromation and examples see the Apache
Log4j website: http://logging.apache.org/log4j/
-->
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"
debug="false">
<!-- A time/date based rolling appender -->
<appender name="WIREFILE" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="target/test-data/jclouds-wire.log" />
<param name="Append" value="true" />
<!-- Rollover at midnight each day -->
<param name="DatePattern" value="'.'yyyy-MM-dd" />
<param name="Threshold" value="TRACE" />
<layout class="org.apache.log4j.PatternLayout">
<!-- The default pattern: Date Priority [Category] Message\n -->
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n" />
<!--
The full pattern: Date MS Priority [Category]
(Thread:NDC) Message\n <param name="ConversionPattern"
value="%d %-5r %-5p [%c] (%t:%x) %m%n"/>
-->
</layout>
</appender>
<!-- A time/date based rolling appender -->
<appender name="FILE" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="target/test-data/jclouds.log" />
<param name="Append" value="true" />
<!-- Rollover at midnight each day -->
<param name="DatePattern" value="'.'yyyy-MM-dd" />
<param name="Threshold" value="TRACE" />
<layout class="org.apache.log4j.PatternLayout">
<!-- The default pattern: Date Priority [Category] Message\n -->
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n" />
<!--
The full pattern: Date MS Priority [Category]
(Thread:NDC) Message\n <param name="ConversionPattern"
value="%d %-5r %-5p [%c] (%t:%x) %m%n"/>
-->
</layout>
</appender>
<!-- A time/date based rolling appender -->
<appender name="COMPUTEFILE" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="target/test-data/jclouds-compute.log" />
<param name="Append" value="true" />
<!-- Rollover at midnight each day -->
<param name="DatePattern" value="'.'yyyy-MM-dd" />
<param name="Threshold" value="TRACE" />
<layout class="org.apache.log4j.PatternLayout">
<!-- The default pattern: Date Priority [Category] Message\n -->
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n" />
<!--
The full pattern: Date MS Priority [Category]
(Thread:NDC) Message\n <param name="ConversionPattern"
value="%d %-5r %-5p [%c] (%t:%x) %m%n"/>
-->
</layout>
</appender>
<!-- A time/date based rolling appender -->
<appender name="SSHFILE" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="target/test-data/jclouds-ssh.log" />
<param name="Append" value="true" />
<!-- Rollover at midnight each day -->
<param name="DatePattern" value="'.'yyyy-MM-dd" />
<param name="Threshold" value="TRACE" />
<layout class="org.apache.log4j.PatternLayout">
<!-- The default pattern: Date Priority [Category] Message\n -->
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n" />
<!--
The full pattern: Date MS Priority [Category]
(Thread:NDC) Message\n <param name="ConversionPattern"
value="%d %-5r %-5p [%c] (%t:%x) %m%n"/>
-->
</layout>
</appender>
<appender name="ASYNCCOMPUTE" class="org.apache.log4j.AsyncAppender">
<appender-ref ref="COMPUTEFILE" />
</appender>
<appender name="ASYNCSSH" class="org.apache.log4j.AsyncAppender">
<appender-ref ref="SSHFILE" />
</appender>
<appender name="ASYNC" class="org.apache.log4j.AsyncAppender">
<appender-ref ref="FILE" />
</appender>
<appender name="ASYNCWIRE" class="org.apache.log4j.AsyncAppender">
<appender-ref ref="WIREFILE" />
</appender>
<!-- ================ -->
<!-- Limit categories -->
<!-- ================ -->
<category name="org.jclouds">
<priority value="DEBUG" />
<appender-ref ref="ASYNC" />
</category>
<category name="jclouds.headers">
<priority value="DEBUG" />
<appender-ref ref="ASYNCWIRE" />
</category>
<category name="jclouds.ssh">
<priority value="DEBUG" />
<appender-ref ref="ASYNCSSH" />
</category>
<category name="jclouds.wire">
<priority value="DEBUG" />
<appender-ref ref="ASYNCWIRE" />
</category>
<category name="jclouds.compute">
<priority value="TRACE" />
<appender-ref ref="ASYNCCOMPUTE" />
</category>
<!-- ======================= -->
<!-- Setup the Root category -->
<!-- ======================= -->
<root>
<priority value="WARN" />
</root>
</log4j:configuration>

View File

@ -1,54 +0,0 @@
{
"server": {
"status": "REBOOT",
"updated": "2011-12-06T22:37:44Z",
"hostId": "3852db942cbeb5e840d759de11bdef403e2a0149c66f06a5d7caa61e",
"user_id": "dev_41247879706381",
"name": "jd-test-tiny",
"links": [
{
"href": "http://se1.devex.me:8774/v1.1/dev_16767499955063/servers/804",
"rel": "self"
},
{
"href": "http://se1.devex.me:8774/dev_16767499955063/servers/804",
"rel": "bookmark"
}
],
"addresses": {
"novanet_7": [
{
"version": 4,
"addr": "10.0.0.229"
}
]
},
"tenant_id": "dev_16767499955063",
"image": {
"id": "146",
"links": [
{
"href": "http://se1.devex.me:8774/dev_16767499955063/images/146",
"rel": "bookmark"
}
]
},
"created": "2011-12-02T16:04:54Z",
"uuid": "0bab236f-f5c4-46ef-93c2-a8e2bcfffff6",
"accessIPv4": "",
"accessIPv6": "",
"key_name": null,
"flavor": {
"id": "1",
"links": [
{
"href": "http://se1.devex.me:8774/dev_16767499955063/flavors/1",
"rel": "bookmark"
}
]
},
"config_drive": "",
"id": 804,
"metadata": {}
}
}

View File

@ -1,64 +0,0 @@
{
"servers": [
{
"uuid": "0bab236f-f5c4-46ef-93c2-a8e2bcfffff6",
"name": "jd-test-tiny",
"links": [
{
"href": "http://se1.devex.me:8774/v1.1/dev_16767499955063/servers/804",
"rel": "self"
},
{
"href": "http://se1.devex.me:8774/dev_16767499955063/servers/804",
"rel": "bookmark"
}
],
"id": 804
},
{
"uuid": "488eac65-84ab-4f10-b2a4-555c23613428",
"name": "rgtest2",
"links": [
{
"href": "http://se1.devex.me:8774/v1.1/dev_16767499955063/servers/528",
"rel": "self"
},
{
"href": "http://se1.devex.me:8774/dev_16767499955063/servers/528",
"rel": "bookmark"
}
],
"id": 528
},
{
"uuid": "df891742-4ecb-4f9f-b206-b2a4d821a100",
"name": "rgtest",
"links": [
{
"href": "http://se1.devex.me:8774/v1.1/dev_16767499955063/servers/507",
"rel": "self"
},
{
"href": "http://se1.devex.me:8774/dev_16767499955063/servers/507",
"rel": "bookmark"
}
],
"id": 507
},
{
"uuid": "42cded93-1ade-4da2-b39f-70e6577c2b82",
"name": "fog_hprgmac.local_1320358100_server",
"links": [
{
"href": "http://se1.devex.me:8774/v1.1/dev_16767499955063/servers/430",
"rel": "self"
},
{
"href": "http://se1.devex.me:8774/dev_16767499955063/servers/430",
"rel": "bookmark"
}
],
"id": 430
}
]
}