merged changes master

This commit is contained in:
Adrian Cole 2012-06-11 17:30:43 -07:00
commit 3114b652fc
923 changed files with 19050 additions and 8125 deletions

View File

@ -18,6 +18,7 @@
*/ */
package org.jclouds.tools.ant.taskdefs.compute; package org.jclouds.tools.ant.taskdefs.compute;
import static org.jclouds.compute.util.ComputeServiceUtils.formatStatus;
import static org.jclouds.compute.util.ComputeServiceUtils.getCores; import static org.jclouds.compute.util.ComputeServiceUtils.getCores;
import static org.jclouds.tools.ant.taskdefs.compute.ComputeTaskUtils.buildComputeMap; import static org.jclouds.tools.ant.taskdefs.compute.ComputeTaskUtils.buildComputeMap;
import static org.jclouds.tools.ant.taskdefs.compute.ComputeTaskUtils.createTemplateFromElement; import static org.jclouds.tools.ant.taskdefs.compute.ComputeTaskUtils.createTemplateFromElement;
@ -253,8 +254,7 @@ public class ComputeTask extends Task {
NodeMetadata metadata = node instanceof NodeMetadata ? NodeMetadata.class.cast(node) : computeService NodeMetadata metadata = node instanceof NodeMetadata ? NodeMetadata.class.cast(node) : computeService
.getNodeMetadata(node.getId()); .getNodeMetadata(node.getId());
log(String.format(" node id=%s, name=%s, group=%s, location=%s, state=%s, publicIp=%s, privateIp=%s, hardware=%s", log(String.format(" node id=%s, name=%s, group=%s, location=%s, state=%s, publicIp=%s, privateIp=%s, hardware=%s",
metadata.getProviderId(), metadata.getName(), metadata.getGroup(), metadata.getLocation(), metadata metadata.getProviderId(), metadata.getName(), metadata.getGroup(), metadata.getLocation(), formatStatus(metadata), ComputeTaskUtils.ipOrEmptyString(metadata.getPublicAddresses()),
.getState(), ComputeTaskUtils.ipOrEmptyString(metadata.getPublicAddresses()),
ipOrEmptyString(metadata.getPrivateAddresses()), metadata.getHardware())); ipOrEmptyString(metadata.getPrivateAddresses()), metadata.getHardware()));
} }

View File

@ -39,6 +39,9 @@
<test.atmos.build-version /> <test.atmos.build-version />
<test.atmos.identity>FIXME</test.atmos.identity> <test.atmos.identity>FIXME</test.atmos.identity>
<test.atmos.credential>FIXME</test.atmos.credential> <test.atmos.credential>FIXME</test.atmos.credential>
<jclouds.osgi.import>*</jclouds.osgi.import>
<jclouds.osgi.export>org.jclouds.atmos*;version="${project.version}";-noimport:=true</jclouds.osgi.export>
</properties> </properties>
<dependencies> <dependencies>
@ -109,20 +112,4 @@
</profile> </profile>
</profiles> </profiles>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>org.jclouds.atmos*;version="${project.version}"</Export-Package>
<Import-Package>org.jclouds*;version="${project.version}",*</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project> </project>

View File

@ -35,7 +35,14 @@
<properties> <properties>
<test.byon.endpoint>file://c:/test.txt</test.byon.endpoint> <test.byon.endpoint>file://c:/test.txt</test.byon.endpoint>
<test.byon.sudo-password /> <test.byon.sudo-password></test.byon.sudo-password>
<jclouds.osgi.export>org.jclouds.byon*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>
org.jclouds.compute.internal;version="${project.version}",
org.jclouds.rest.internal;version="${project.version}",
org.jclouds*;version="${project.version}",
*
</jclouds.osgi.import>
</properties> </properties>
<dependencies> <dependencies>
<dependency> <dependency>
@ -105,25 +112,4 @@
</profile> </profile>
</profiles> </profiles>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>org.jclouds.byon*;version="${project.version}"</Export-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>
</configuration>
</plugin>
</plugins>
</build>
</project> </project>

View File

@ -36,9 +36,9 @@ import org.jclouds.byon.Node;
import org.jclouds.collect.Memoized; import org.jclouds.collect.Memoized;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadataBuilder; import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.OperatingSystem; import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.OsFamily; import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.NodeMetadata.Status;
import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.Credentials; import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
@ -90,7 +90,7 @@ public class NodeToNodeMetadata implements Function<Node, NodeMetadata> {
builder.operatingSystem(OperatingSystem.builder().arch(from.getOsArch()).family( builder.operatingSystem(OperatingSystem.builder().arch(from.getOsArch()).family(
OsFamily.fromValue(from.getOsFamily())).description(from.getOsDescription()) OsFamily.fromValue(from.getOsFamily())).description(from.getOsDescription())
.version(from.getOsVersion()).build()); .version(from.getOsVersion()).build());
builder.state(NodeState.RUNNING); builder.status(Status.RUNNING);
builder.publicAddresses(ImmutableSet.<String> of(from.getHostname())); builder.publicAddresses(ImmutableSet.<String> of(from.getHostname()));
if (from.getUsername() != null) { if (from.getUsername() != null) {

View File

@ -45,7 +45,6 @@ import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.ImmutableSet.Builder; import com.google.common.collect.ImmutableSet.Builder;
import com.google.common.util.concurrent.UncheckedExecutionException; import com.google.common.util.concurrent.UncheckedExecutionException;
/** /**
* *
* @author Adrian Cole * @author Adrian Cole
@ -118,6 +117,11 @@ public class BYONComputeServiceAdapter implements JCloudsNativeComputeServiceAda
return node != null ? converter.apply(node) : null; return node != null ? converter.apply(node) : null;
} }
@Override
public Image getImage(final String id) {
throw new UnsupportedOperationException();
}
@Override @Override
public void destroyNode(final String id) { public void destroyNode(final String id) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();

View File

@ -27,9 +27,9 @@ import java.util.Set;
import org.jclouds.byon.suppliers.SupplyFromProviderURIOrNodesProperty; import org.jclouds.byon.suppliers.SupplyFromProviderURIOrNodesProperty;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadataBuilder; import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.OperatingSystem; import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.OsFamily; import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.NodeMetadata.Status;
import org.jclouds.domain.Credentials; import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.domain.LocationBuilder; import org.jclouds.domain.LocationBuilder;
@ -88,7 +88,7 @@ public class NodeToNodeMetadataTest {
.location(location) .location(location)
.userMetadata(ImmutableMap.of("Name", "foo")) .userMetadata(ImmutableMap.of("Name", "foo"))
.tags(ImmutableSet.of("vanilla")) .tags(ImmutableSet.of("vanilla"))
.state(NodeState.RUNNING) .status(Status.RUNNING)
.operatingSystem( .operatingSystem(
OperatingSystem.builder().description("redhat").family(OsFamily.RHEL).arch("x86").version("5.3") OperatingSystem.builder().description("redhat").family(OsFamily.RHEL).arch("x86").version("5.3")
.build()) .build())

View File

@ -39,6 +39,12 @@
<test.cloudfiles.build-version /> <test.cloudfiles.build-version />
<test.cloudfiles.identity>${test.rackspace.identity}</test.cloudfiles.identity> <test.cloudfiles.identity>${test.rackspace.identity}</test.cloudfiles.identity>
<test.cloudfiles.credential>${test.rackspace.credential}</test.cloudfiles.credential> <test.cloudfiles.credential>${test.rackspace.credential}</test.cloudfiles.credential>
<jclouds.osgi.export>org.jclouds.cloudfiles*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>
org.jclouds*;version="${project.version}",
org.jclouds.openstack.swift.options;version="${project.version}",
*
</jclouds.osgi.import>
</properties> </properties>
<dependencies> <dependencies>
@ -123,25 +129,5 @@
</profile> </profile>
</profiles> </profiles>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>org.jclouds.cloudfiles*;version="${project.version}"</Export-Package>
<Import-Package>
org.jclouds*;version="${project.version}",
org.jclouds.openstack.swift.options;version="${project.version}",
*
</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project> </project>

View File

@ -18,19 +18,15 @@
*/ */
package org.jclouds.cloudfiles; package org.jclouds.cloudfiles;
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS;
import java.net.URI; import java.net.URI;
import java.util.Properties; import java.util.Properties;
import org.jclouds.apis.ApiMetadata; import org.jclouds.apis.ApiMetadata;
import org.jclouds.blobstore.BlobStoreContext;
import org.jclouds.cloudfiles.blobstore.config.CloudFilesBlobStoreContextModule; import org.jclouds.cloudfiles.blobstore.config.CloudFilesBlobStoreContextModule;
import org.jclouds.cloudfiles.config.CloudFilesRestClientModule; import org.jclouds.cloudfiles.config.CloudFilesRestClientModule;
import org.jclouds.openstack.OpenStackAuthAsyncClient; import org.jclouds.cloudfiles.config.CloudFilesRestClientModule.StorageAndCDNManagementEndpointModule;
import org.jclouds.openstack.swift.SwiftApiMetadata;
import org.jclouds.rest.RestContext; import org.jclouds.rest.RestContext;
import org.jclouds.rest.internal.BaseRestApiMetadata;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.reflect.TypeToken; import com.google.common.reflect.TypeToken;
@ -41,9 +37,10 @@ import com.google.inject.Module;
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
public class CloudFilesApiMetadata extends BaseRestApiMetadata { public class CloudFilesApiMetadata extends SwiftApiMetadata {
/** The serialVersionUID */ /** The serialVersionUID */
private static final long serialVersionUID = 820062881469203616L; private static final long serialVersionUID = -1572520638079261710L;
public static final TypeToken<RestContext<CloudFilesClient, CloudFilesAsyncClient>> CONTEXT_TOKEN = new TypeToken<RestContext<CloudFilesClient, CloudFilesAsyncClient>>() { public static final TypeToken<RestContext<CloudFilesClient, CloudFilesAsyncClient>> CONTEXT_TOKEN = new TypeToken<RestContext<CloudFilesClient, CloudFilesAsyncClient>>() {
private static final long serialVersionUID = -5070937833892503232L; private static final long serialVersionUID = -5070937833892503232L;
@ -67,13 +64,11 @@ public class CloudFilesApiMetadata extends BaseRestApiMetadata {
} }
public static Properties defaultProperties() { public static Properties defaultProperties() {
Properties properties = BaseRestApiMetadata.defaultProperties(); Properties properties = SwiftApiMetadata.defaultProperties();
properties.setProperty(PROPERTY_REGIONS, "DEFAULT");
properties.setProperty(PROPERTY_USER_METADATA_PREFIX, "X-Object-Meta-");
return properties; return properties;
} }
public static class Builder extends BaseRestApiMetadata.Builder { public static class Builder extends SwiftApiMetadata.Builder {
protected Builder(){ protected Builder(){
super(CloudFilesClient.class, CloudFilesAsyncClient.class); super(CloudFilesClient.class, CloudFilesAsyncClient.class);
id("cloudfiles") id("cloudfiles")
@ -81,10 +76,9 @@ public class CloudFilesApiMetadata extends BaseRestApiMetadata {
.identityName("Username") .identityName("Username")
.credentialName("API Key") .credentialName("API Key")
.documentation(URI.create("http://docs.rackspacecloud.com/files/api/v1/cfdevguide_d5/content/ch01.html")) .documentation(URI.create("http://docs.rackspacecloud.com/files/api/v1/cfdevguide_d5/content/ch01.html"))
.version(OpenStackAuthAsyncClient.VERSION)
.defaultProperties(CloudFilesApiMetadata.defaultProperties()) .defaultProperties(CloudFilesApiMetadata.defaultProperties())
.view(TypeToken.of(BlobStoreContext.class)) .context(CONTEXT_TOKEN)
.defaultModules(ImmutableSet.<Class<? extends Module>>of(CloudFilesRestClientModule.class, CloudFilesBlobStoreContextModule.class)); .defaultModules(ImmutableSet.<Class<? extends Module>>of(StorageAndCDNManagementEndpointModule.class, CloudFilesRestClientModule.class, CloudFilesBlobStoreContextModule.class));
} }
@Override @Override
@ -98,4 +92,5 @@ public class CloudFilesApiMetadata extends BaseRestApiMetadata {
return this; return this;
} }
} }
} }

View File

@ -27,65 +27,38 @@ import javax.inject.Singleton;
import org.jclouds.cloudfiles.CDNManagement; import org.jclouds.cloudfiles.CDNManagement;
import org.jclouds.cloudfiles.CloudFilesAsyncClient; import org.jclouds.cloudfiles.CloudFilesAsyncClient;
import org.jclouds.cloudfiles.CloudFilesClient; import org.jclouds.cloudfiles.CloudFilesClient;
import org.jclouds.http.HttpErrorHandler;
import org.jclouds.http.annotation.ClientError;
import org.jclouds.http.annotation.Redirection;
import org.jclouds.http.annotation.ServerError;
import org.jclouds.json.config.GsonModule.DateAdapter;
import org.jclouds.json.config.GsonModule.Iso8601DateAdapter;
import org.jclouds.location.suppliers.RegionIdToURISupplier; import org.jclouds.location.suppliers.RegionIdToURISupplier;
import org.jclouds.openstack.keystone.v1_1.config.AuthenticationServiceModule; import org.jclouds.openstack.keystone.v1_1.config.AuthenticationServiceModule;
import org.jclouds.openstack.swift.CommonSwiftAsyncClient; import org.jclouds.openstack.swift.CommonSwiftAsyncClient;
import org.jclouds.openstack.swift.CommonSwiftClient; import org.jclouds.openstack.swift.CommonSwiftClient;
import org.jclouds.openstack.swift.Storage; import org.jclouds.openstack.swift.Storage;
import org.jclouds.openstack.swift.config.SwiftObjectModule; import org.jclouds.openstack.swift.config.SwiftRestClientModule;
import org.jclouds.openstack.swift.handlers.ParseSwiftErrorFromHttpResponse;
import org.jclouds.rest.ConfiguresRestClient; import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.annotations.ApiVersion; import org.jclouds.rest.annotations.ApiVersion;
import org.jclouds.rest.config.RestClientModule;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableMap;
import com.google.common.reflect.TypeToken;
import com.google.inject.Provides; import com.google.inject.Provides;
import com.google.inject.Scopes;
/** /**
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@ConfiguresRestClient @ConfiguresRestClient
public class CloudFilesRestClientModule extends RestClientModule<CloudFilesClient, CloudFilesAsyncClient> { public class CloudFilesRestClientModule extends SwiftRestClientModule<CloudFilesClient, CloudFilesAsyncClient> {
public CloudFilesRestClientModule() {
@Provides super(TypeToken.of(CloudFilesClient.class), TypeToken.of(CloudFilesAsyncClient.class), ImmutableMap
@Singleton .<Class<?>, Class<?>> of());
CommonSwiftClient provideCommonSwiftClient(CloudFilesClient in) {
return in;
} }
@Provides protected void bindResolvedClientsToCommonSwift() {
@Singleton bind(CommonSwiftClient.class).to(CloudFilesClient.class).in(Scopes.SINGLETON);
CommonSwiftAsyncClient provideCommonSwiftClient(CloudFilesAsyncClient in) { bind(CommonSwiftAsyncClient.class).to(CloudFilesAsyncClient.class).in(Scopes.SINGLETON);
return in;
}
@Override
protected void configure() {
install(new SwiftObjectModule());
bind(DateAdapter.class).to(Iso8601DateAdapter.class);
super.configure();
}
@Override
protected void bindErrorHandlers() {
bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(ParseSwiftErrorFromHttpResponse.class);
bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(ParseSwiftErrorFromHttpResponse.class);
bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(ParseSwiftErrorFromHttpResponse.class);
}
@Override
protected void installLocations() {
super.installLocations();
install(new AuthenticationServiceModule());
} }
public static class StorageAndCDNManagementEndpointModule extends AuthenticationServiceModule {
@Provides @Provides
@Singleton @Singleton
@CDNManagement @CDNManagement
@ -99,5 +72,6 @@ public class CloudFilesRestClientModule extends RestClientModule<CloudFilesClien
protected Supplier<URI> provideStorageUrl(RegionIdToURISupplier.Factory factory, @ApiVersion String apiVersion) { protected Supplier<URI> provideStorageUrl(RegionIdToURISupplier.Factory factory, @ApiVersion String apiVersion) {
return getLastValueInMap(factory.createForApiTypeAndVersion("cloudFiles", apiVersion)); return getLastValueInMap(factory.createForApiTypeAndVersion("cloudFiles", apiVersion));
} }
}
} }

View File

@ -39,6 +39,9 @@
<test.cloudloadbalancers.build-version /> <test.cloudloadbalancers.build-version />
<test.cloudloadbalancers.identity>${test.rackspace.identity}</test.cloudloadbalancers.identity> <test.cloudloadbalancers.identity>${test.rackspace.identity}</test.cloudloadbalancers.identity>
<test.cloudloadbalancers.credential>${test.rackspace.credential}</test.cloudloadbalancers.credential> <test.cloudloadbalancers.credential>${test.rackspace.credential}</test.cloudloadbalancers.credential>
<jclouds.osgi.export>org.jclouds.cloudloadbalancers*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>org.jclouds*;version="${project.version}",*</jclouds.osgi.import>
</properties> </properties>
<dependencies> <dependencies>
<dependency> <dependency>
@ -111,19 +114,4 @@
</profile> </profile>
</profiles> </profiles>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>org.jclouds.cloudloadbalancers*;version="${project.version}"</Export-Package>
<Import-Package>org.jclouds*;version="${project.version}",*</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project> </project>

View File

@ -25,7 +25,6 @@ import org.jclouds.apis.ApiMetadata;
import org.jclouds.cloudloadbalancers.config.CloudLoadBalancersRestClientModule; import org.jclouds.cloudloadbalancers.config.CloudLoadBalancersRestClientModule;
import org.jclouds.cloudloadbalancers.loadbalancer.config.CloudLoadBalancersLoadBalancerContextModule; import org.jclouds.cloudloadbalancers.loadbalancer.config.CloudLoadBalancersLoadBalancerContextModule;
import org.jclouds.loadbalancer.LoadBalancerServiceContext; import org.jclouds.loadbalancer.LoadBalancerServiceContext;
import org.jclouds.openstack.OpenStackAuthAsyncClient;
import org.jclouds.rest.RestContext; import org.jclouds.rest.RestContext;
import org.jclouds.rest.internal.BaseRestApiMetadata; import org.jclouds.rest.internal.BaseRestApiMetadata;
@ -75,7 +74,7 @@ public class CloudLoadBalancersApiMetadata extends BaseRestApiMetadata {
.identityName("Username") .identityName("Username")
.credentialName("API Key") .credentialName("API Key")
.documentation(URI.create("http://docs.rackspacecloud.com/loadbalancers/api/v1.0/clb-devguide/content/ch01.html")) .documentation(URI.create("http://docs.rackspacecloud.com/loadbalancers/api/v1.0/clb-devguide/content/ch01.html"))
.version(OpenStackAuthAsyncClient.VERSION) .version("1.0")
.defaultEndpoint("https://auth.api.rackspacecloud.com") .defaultEndpoint("https://auth.api.rackspacecloud.com")
.defaultProperties(CloudLoadBalancersApiMetadata.defaultProperties()) .defaultProperties(CloudLoadBalancersApiMetadata.defaultProperties())
.view(TypeToken.of(LoadBalancerServiceContext.class)) .view(TypeToken.of(LoadBalancerServiceContext.class))

View File

@ -37,12 +37,19 @@
<properties> <properties>
<test.cloudservers.endpoint>https://auth.api.rackspacecloud.com</test.cloudservers.endpoint> <test.cloudservers.endpoint>https://auth.api.rackspacecloud.com</test.cloudservers.endpoint>
<test.cloudservers.api-version>1.0</test.cloudservers.api-version> <test.cloudservers.api-version>1.0</test.cloudservers.api-version>
<test.cloudservers.build-version /> <test.cloudservers.build-version></test.cloudservers.build-version>
<test.cloudservers.identity>${test.rackspace.identity}</test.cloudservers.identity> <test.cloudservers.identity>${test.rackspace.identity}</test.cloudservers.identity>
<test.cloudservers.credential>${test.rackspace.credential}</test.cloudservers.credential> <test.cloudservers.credential>${test.rackspace.credential}</test.cloudservers.credential>
<test.cloudservers.image-id /> <test.cloudservers.image-id></test.cloudservers.image-id>
<test.cloudservers.image.login-user /> <test.cloudservers.image.login-user></test.cloudservers.image.login-user>
<test.cloudservers.image.authenticate-sudo /> <test.cloudservers.image.authenticate-sudo></test.cloudservers.image.authenticate-sudo>
<jclouds.osgi.export>org.jclouds.cloudservers*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>
org.jclouds.compute.internal;version="${project.version}",
org.jclouds.rest.internal;version="${project.version}",
org.jclouds*;version="${project.version}",
*
</jclouds.osgi.import>
</properties> </properties>
<dependencies> <dependencies>
@ -126,26 +133,5 @@
</profile> </profile>
</profiles> </profiles>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>org.jclouds.cloudservers*;version="${project.version}"</Export-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>
</configuration>
</plugin>
</plugins>
</build>
</project> </project>

View File

@ -25,7 +25,6 @@ import org.jclouds.apis.ApiMetadata;
import org.jclouds.cloudservers.compute.config.CloudServersComputeServiceContextModule; import org.jclouds.cloudservers.compute.config.CloudServersComputeServiceContextModule;
import org.jclouds.cloudservers.config.CloudServersRestClientModule; import org.jclouds.cloudservers.config.CloudServersRestClientModule;
import org.jclouds.compute.ComputeServiceContext; import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.openstack.OpenStackAuthAsyncClient;
import org.jclouds.rest.RestContext; import org.jclouds.rest.RestContext;
import org.jclouds.rest.internal.BaseRestApiMetadata; import org.jclouds.rest.internal.BaseRestApiMetadata;
@ -74,7 +73,7 @@ public class CloudServersApiMetadata extends BaseRestApiMetadata {
.identityName("Username") .identityName("Username")
.credentialName("API Key") .credentialName("API Key")
.documentation(URI.create("http://docs.rackspacecloud.com/servers/api/v1.0/cs-devguide/content/ch01.html")) .documentation(URI.create("http://docs.rackspacecloud.com/servers/api/v1.0/cs-devguide/content/ch01.html"))
.version(OpenStackAuthAsyncClient.VERSION) .version("1.0")
.defaultEndpoint("https://auth.api.rackspacecloud.com") .defaultEndpoint("https://auth.api.rackspacecloud.com")
.defaultProperties(CloudServersApiMetadata.defaultProperties()) .defaultProperties(CloudServersApiMetadata.defaultProperties())
.view(TypeToken.of(ComputeServiceContext.class)) .view(TypeToken.of(ComputeServiceContext.class))

View File

@ -30,6 +30,7 @@ import org.jclouds.cloudservers.compute.functions.ServerToNodeMetadata;
import org.jclouds.cloudservers.compute.predicates.GetImageWhenStatusActivePredicateWithResult; import org.jclouds.cloudservers.compute.predicates.GetImageWhenStatusActivePredicateWithResult;
import org.jclouds.cloudservers.compute.strategy.CloudServersComputeServiceAdapter; import org.jclouds.cloudservers.compute.strategy.CloudServersComputeServiceAdapter;
import org.jclouds.cloudservers.domain.Flavor; import org.jclouds.cloudservers.domain.Flavor;
import org.jclouds.cloudservers.domain.ImageStatus;
import org.jclouds.cloudservers.domain.Server; import org.jclouds.cloudservers.domain.Server;
import org.jclouds.cloudservers.domain.ServerStatus; import org.jclouds.cloudservers.domain.ServerStatus;
import org.jclouds.compute.ComputeServiceAdapter; import org.jclouds.compute.ComputeServiceAdapter;
@ -37,7 +38,6 @@ import org.jclouds.compute.config.ComputeServiceAdapterContextModule;
import org.jclouds.compute.domain.Hardware; import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.OperatingSystem; import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.extensions.ImageExtension; import org.jclouds.compute.extensions.ImageExtension;
import org.jclouds.compute.internal.BaseComputeService; import org.jclouds.compute.internal.BaseComputeService;
@ -93,36 +93,54 @@ public class CloudServersComputeServiceContextModule extends
} }
@VisibleForTesting @VisibleForTesting
public static final Map<ServerStatus, NodeState> serverToNodeState = ImmutableMap public static final Map<ServerStatus, NodeMetadata.Status> toPortableNodeStatus = ImmutableMap
.<ServerStatus, NodeState> builder().put(ServerStatus.ACTIVE, NodeState.RUNNING)// .<ServerStatus, NodeMetadata.Status> builder()
.put(ServerStatus.SUSPENDED, NodeState.SUSPENDED)// .put(ServerStatus.ACTIVE, NodeMetadata.Status.RUNNING)
.put(ServerStatus.DELETED, NodeState.TERMINATED)// .put(ServerStatus.SUSPENDED, NodeMetadata.Status.SUSPENDED)
.put(ServerStatus.QUEUE_RESIZE, NodeState.PENDING)// .put(ServerStatus.DELETED, NodeMetadata.Status.TERMINATED)
.put(ServerStatus.PREP_RESIZE, NodeState.PENDING)// .put(ServerStatus.QUEUE_RESIZE, NodeMetadata.Status.PENDING)
.put(ServerStatus.RESIZE, NodeState.PENDING)// .put(ServerStatus.PREP_RESIZE, NodeMetadata.Status.PENDING)
.put(ServerStatus.VERIFY_RESIZE, NodeState.PENDING)// .put(ServerStatus.RESIZE, NodeMetadata.Status.PENDING)
.put(ServerStatus.QUEUE_MOVE, NodeState.PENDING)// .put(ServerStatus.VERIFY_RESIZE, NodeMetadata.Status.PENDING)
.put(ServerStatus.PREP_MOVE, NodeState.PENDING)// .put(ServerStatus.QUEUE_MOVE, NodeMetadata.Status.PENDING)
.put(ServerStatus.MOVE, NodeState.PENDING)// .put(ServerStatus.PREP_MOVE, NodeMetadata.Status.PENDING)
.put(ServerStatus.VERIFY_MOVE, NodeState.PENDING)// .put(ServerStatus.MOVE, NodeMetadata.Status.PENDING)
.put(ServerStatus.RESCUE, NodeState.PENDING)// .put(ServerStatus.VERIFY_MOVE, NodeMetadata.Status.PENDING)
.put(ServerStatus.ERROR, NodeState.ERROR)// .put(ServerStatus.RESCUE, NodeMetadata.Status.PENDING)
.put(ServerStatus.BUILD, NodeState.PENDING)// .put(ServerStatus.ERROR, NodeMetadata.Status.ERROR)
.put(ServerStatus.RESTORING, NodeState.PENDING)// .put(ServerStatus.BUILD, NodeMetadata.Status.PENDING)
.put(ServerStatus.PASSWORD, NodeState.PENDING)// .put(ServerStatus.RESTORING, NodeMetadata.Status.PENDING)
.put(ServerStatus.REBUILD, NodeState.PENDING)// .put(ServerStatus.PASSWORD, NodeMetadata.Status.PENDING)
.put(ServerStatus.DELETE_IP, NodeState.PENDING)// .put(ServerStatus.REBUILD, NodeMetadata.Status.PENDING)
.put(ServerStatus.SHARE_IP_NO_CONFIG, NodeState.PENDING)// .put(ServerStatus.DELETE_IP, NodeMetadata.Status.PENDING)
.put(ServerStatus.SHARE_IP, NodeState.PENDING)// .put(ServerStatus.SHARE_IP_NO_CONFIG, NodeMetadata.Status.PENDING)
.put(ServerStatus.REBOOT, NodeState.PENDING)// .put(ServerStatus.SHARE_IP, NodeMetadata.Status.PENDING)
.put(ServerStatus.HARD_REBOOT, NodeState.PENDING)// .put(ServerStatus.REBOOT, NodeMetadata.Status.PENDING)
.put(ServerStatus.UNKNOWN, NodeState.UNRECOGNIZED)// .put(ServerStatus.HARD_REBOOT, NodeMetadata.Status.PENDING)
.put(ServerStatus.UNRECOGNIZED, NodeState.UNRECOGNIZED).build(); .put(ServerStatus.UNKNOWN, NodeMetadata.Status.UNRECOGNIZED)
.put(ServerStatus.UNRECOGNIZED, NodeMetadata.Status.UNRECOGNIZED).build();
@Singleton @Singleton
@Provides @Provides
Map<ServerStatus, NodeState> provideServerToNodeState() { Map<ServerStatus, NodeMetadata.Status> toPortableNodeStatus() {
return serverToNodeState; return toPortableNodeStatus;
}
@VisibleForTesting
public static final Map<ImageStatus, Image.Status> toPortableImageStatus = ImmutableMap
.<ImageStatus, Image.Status> builder()
.put(ImageStatus.ACTIVE, Image.Status.AVAILABLE)
.put(ImageStatus.SAVING, Image.Status.PENDING)
.put(ImageStatus.PREPARING, Image.Status.PENDING)
.put(ImageStatus.QUEUED, Image.Status.PENDING)
.put(ImageStatus.FAILED, Image.Status.ERROR)
.put(ImageStatus.UNKNOWN, Image.Status.UNRECOGNIZED)
.put(ImageStatus.UNRECOGNIZED, Image.Status.UNRECOGNIZED).build();
@Singleton
@Provides
Map<ImageStatus, Image.Status> toPortableImageStatus() {
return toPortableImageStatus;
} }
@Override @Override

View File

@ -52,7 +52,7 @@ import com.google.common.util.concurrent.ListenableFuture;
* CloudServers implementation of {@link ImageExtension} * CloudServers implementation of {@link ImageExtension}
* *
* @author David Alves * @author David Alves
* * @see <a href="http://docs.rackspace.com/servers/api/v1.0/cs-devguide/content/Images-d1e4062.html">docs</a>
*/ */
@Singleton @Singleton
public class CloudServersImageExtension implements ImageExtension { public class CloudServersImageExtension implements ImageExtension {

View File

@ -18,12 +18,16 @@
*/ */
package org.jclouds.cloudservers.compute.functions; package org.jclouds.cloudservers.compute.functions;
import java.util.Map;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.cloudservers.domain.ImageStatus;
import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.ImageBuilder; import org.jclouds.compute.domain.ImageBuilder;
import org.jclouds.compute.domain.OperatingSystem; import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.Image.Status;
import com.google.common.base.Function; import com.google.common.base.Function;
@ -33,10 +37,12 @@ import com.google.common.base.Function;
*/ */
@Singleton @Singleton
public class CloudServersImageToImage implements Function<org.jclouds.cloudservers.domain.Image, Image> { public class CloudServersImageToImage implements Function<org.jclouds.cloudservers.domain.Image, Image> {
private final Map<ImageStatus, Status> toPortableImageStatus;
private final Function<org.jclouds.cloudservers.domain.Image, OperatingSystem> imageToOs; private final Function<org.jclouds.cloudservers.domain.Image, OperatingSystem> imageToOs;
@Inject @Inject
CloudServersImageToImage(Function<org.jclouds.cloudservers.domain.Image, OperatingSystem> imageToOs) { CloudServersImageToImage(Map<ImageStatus, Image.Status> toPortableImageStatus, Function<org.jclouds.cloudservers.domain.Image, OperatingSystem> imageToOs) {
this.toPortableImageStatus=toPortableImageStatus;
this.imageToOs = imageToOs; this.imageToOs = imageToOs;
} }
@ -47,6 +53,7 @@ public class CloudServersImageToImage implements Function<org.jclouds.cloudserve
builder.description(from.getName()); builder.description(from.getName());
builder.version(from.getUpdated().getTime() + ""); builder.version(from.getUpdated().getTime() + "");
builder.operatingSystem(imageToOs.apply(from)); builder.operatingSystem(imageToOs.apply(from));
builder.status(toPortableImageStatus.get(from.getStatus()));
Image image = builder.build(); Image image = builder.build();
return image; return image;
} }

View File

@ -37,8 +37,8 @@ import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadataBuilder; import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.OperatingSystem; import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.NodeMetadata.Status;
import org.jclouds.compute.functions.GroupNamingConvention; import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
@ -61,7 +61,7 @@ public class ServerToNodeMetadata implements Function<Server, NodeMetadata> {
protected Logger logger = Logger.NULL; protected Logger logger = Logger.NULL;
protected final Supplier<Location> location; protected final Supplier<Location> location;
protected final Map<ServerStatus, NodeState> serverToNodeState; protected final Map<ServerStatus, Status> serverToNodeStatus;
protected final Supplier<Set<? extends Image>> images; protected final Supplier<Set<? extends Image>> images;
protected final Supplier<Set<? extends Hardware>> hardwares; protected final Supplier<Set<? extends Hardware>> hardwares;
protected final GroupNamingConvention nodeNamingConvention; protected final GroupNamingConvention nodeNamingConvention;
@ -93,12 +93,12 @@ public class ServerToNodeMetadata implements Function<Server, NodeMetadata> {
} }
@Inject @Inject
ServerToNodeMetadata(Map<ServerStatus, NodeState> serverStateToNodeState, ServerToNodeMetadata(Map<ServerStatus, Status> serverStateToNodeStatus,
@Memoized Supplier<Set<? extends Image>> images, Supplier<Location> location, @Memoized Supplier<Set<? extends Image>> images, Supplier<Location> location,
@Memoized Supplier<Set<? extends Hardware>> hardwares, @Memoized Supplier<Set<? extends Hardware>> hardwares,
GroupNamingConvention.Factory namingConvention) { GroupNamingConvention.Factory namingConvention) {
this.nodeNamingConvention = checkNotNull(namingConvention, "namingConvention").createWithoutPrefix(); this.nodeNamingConvention = checkNotNull(namingConvention, "namingConvention").createWithoutPrefix();
this.serverToNodeState = checkNotNull(serverStateToNodeState, "serverStateToNodeState"); this.serverToNodeStatus = checkNotNull(serverStateToNodeStatus, "serverStateToNodeStatus");
this.images = checkNotNull(images, "images"); this.images = checkNotNull(images, "images");
this.location = checkNotNull(location, "location"); this.location = checkNotNull(location, "location");
this.hardwares = checkNotNull(hardwares, "hardwares"); this.hardwares = checkNotNull(hardwares, "hardwares");
@ -117,7 +117,7 @@ public class ServerToNodeMetadata implements Function<Server, NodeMetadata> {
builder.imageId(from.getImageId() + ""); builder.imageId(from.getImageId() + "");
builder.operatingSystem(parseOperatingSystem(from)); builder.operatingSystem(parseOperatingSystem(from));
builder.hardware(parseHardware(from)); builder.hardware(parseHardware(from));
builder.state(serverToNodeState.get(from.getStatus())); builder.status(serverToNodeStatus.get(from.getStatus()));
builder.publicAddresses(from.getAddresses().getPublicAddresses()); builder.publicAddresses(from.getAddresses().getPublicAddresses());
builder.privateAddresses(from.getAddresses().getPrivateAddresses()); builder.privateAddresses(from.getAddresses().getPrivateAddresses());
return builder.build(); return builder.build();

View File

@ -96,6 +96,12 @@ public class CloudServersComputeServiceAdapter implements ComputeServiceAdapter<
return client.getServer(serverId); return client.getServer(serverId);
} }
@Override
public Image getImage(String id) {
int imageId = Integer.parseInt(id);
return client.getImage(imageId);
}
@Override @Override
public void destroyNode(String id) { public void destroyNode(String id) {
int serverId = Integer.parseInt(id); int serverId = Integer.parseInt(id);

View File

@ -30,7 +30,7 @@ public class CloudServersComputeServiceContextModuleTest {
public void testAllStatusCovered() { public void testAllStatusCovered() {
for (ServerStatus state : ServerStatus.values()) { for (ServerStatus state : ServerStatus.values()) {
assert CloudServersComputeServiceContextModule.serverToNodeState.containsKey(state) : state; assert CloudServersComputeServiceContextModule.toPortableNodeStatus.containsKey(state) : state;
} }
} }

View File

@ -20,8 +20,7 @@ package org.jclouds.cloudservers.compute.functions;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import java.net.UnknownHostException; import org.jclouds.cloudservers.compute.config.CloudServersComputeServiceContextModule;
import org.jclouds.cloudservers.functions.ParseImageFromJsonResponseTest; import org.jclouds.cloudservers.functions.ParseImageFromJsonResponseTest;
import org.jclouds.compute.config.BaseComputeServiceContextModule; import org.jclouds.compute.config.BaseComputeServiceContextModule;
import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.Image;
@ -38,23 +37,27 @@ import com.google.inject.Guice;
/** /**
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test(groups = "unit") @Test(groups = "unit", testName = "CloudServersImageToImageTest")
public class CloudServersImageToImageTest { public class CloudServersImageToImageTest {
@Test @Test
public void testApplyWhereImageNotFound() throws UnknownHostException { public void test() {
assertEquals(convertImage(), new ImageBuilder().name("CentOS 5.2").operatingSystem( Image toTest = convertImage();
assertEquals(toTest, new ImageBuilder().name("CentOS 5.2").operatingSystem(
new OperatingSystem.Builder().family(OsFamily.CENTOS).version("5.2").description("CentOS 5.2").is64Bit( new OperatingSystem.Builder().family(OsFamily.CENTOS).version("5.2").description("CentOS 5.2").is64Bit(
true).build()).description("CentOS 5.2").ids("2").version("1286712000000").build()); true).build()).description("CentOS 5.2").ids("2").status(Image.Status.PENDING).version(
"1286712000000").build());
assertEquals(toTest.getStatus(), Image.Status.PENDING);
} }
public static Image convertImage() { public static Image convertImage() {
org.jclouds.cloudservers.domain.Image image = ParseImageFromJsonResponseTest.parseImage(); org.jclouds.cloudservers.domain.Image image = ParseImageFromJsonResponseTest.parseImage();
CloudServersImageToImage parser = new CloudServersImageToImage(new CloudServersImageToOperatingSystem( CloudServersImageToImage parser = new CloudServersImageToImage(
CloudServersComputeServiceContextModule.toPortableImageStatus, new CloudServersImageToOperatingSystem(
new BaseComputeServiceContextModule() { new BaseComputeServiceContextModule() {
}.provideOsVersionMap(new ComputeServiceConstants.ReferenceData(), Guice }.provideOsVersionMap(new ComputeServiceConstants.ReferenceData(), Guice.createInjector(
.createInjector(new GsonModule()).getInstance(Json.class)))); new GsonModule()).getInstance(Json.class))));
return parser.apply(image); return parser.apply(image);
} }

View File

@ -32,12 +32,12 @@ import org.jclouds.compute.domain.HardwareBuilder;
import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadataBuilder; import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.OperatingSystem; import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.OsFamily; import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.Processor; import org.jclouds.compute.domain.Processor;
import org.jclouds.compute.domain.Volume; import org.jclouds.compute.domain.Volume;
import org.jclouds.compute.domain.VolumeBuilder; import org.jclouds.compute.domain.VolumeBuilder;
import org.jclouds.compute.domain.NodeMetadata.Status;
import org.jclouds.compute.functions.GroupNamingConvention; import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.domain.LocationBuilder; import org.jclouds.domain.LocationBuilder;
@ -60,12 +60,12 @@ public class ServerToNodeMetadataTest {
@Test @Test
public void testApplyWhereImageAndHardwareNotFound() { public void testApplyWhereImageAndHardwareNotFound() {
Map<ServerStatus, NodeState> serverStateToNodeState = CloudServersComputeServiceContextModule.serverToNodeState; Map<ServerStatus, Status> serverStateToNodeStatus = CloudServersComputeServiceContextModule.toPortableNodeStatus;
Set<org.jclouds.compute.domain.Image> images = ImmutableSet.of(); Set<org.jclouds.compute.domain.Image> images = ImmutableSet.of();
Set<org.jclouds.compute.domain.Hardware> hardwares = ImmutableSet.of(); Set<org.jclouds.compute.domain.Hardware> hardwares = ImmutableSet.of();
Server server = ParseServerFromJsonResponseTest.parseServer(); Server server = ParseServerFromJsonResponseTest.parseServer();
ServerToNodeMetadata parser = new ServerToNodeMetadata(serverStateToNodeState, Suppliers.<Set<? extends Image>> ofInstance(images), Suppliers ServerToNodeMetadata parser = new ServerToNodeMetadata(serverStateToNodeStatus, Suppliers.<Set<? extends Image>> ofInstance(images), Suppliers
.ofInstance(provider), Suppliers.<Set<? extends Hardware>> ofInstance(hardwares), namingConvention); .ofInstance(provider), Suppliers.<Set<? extends Hardware>> ofInstance(hardwares), namingConvention);
NodeMetadata metadata = parser.apply(server); NodeMetadata metadata = parser.apply(server);
@ -73,7 +73,7 @@ public class ServerToNodeMetadataTest {
assertEquals( assertEquals(
metadata, metadata,
new NodeMetadataBuilder() new NodeMetadataBuilder()
.state(NodeState.PENDING) .status(Status.PENDING)
.publicAddresses(ImmutableSet.of("67.23.10.132", "67.23.10.131")) .publicAddresses(ImmutableSet.of("67.23.10.132", "67.23.10.131"))
.privateAddresses(ImmutableSet.of("10.176.42.16")) .privateAddresses(ImmutableSet.of("10.176.42.16"))
.imageId("2") .imageId("2")
@ -91,13 +91,13 @@ public class ServerToNodeMetadataTest {
@Test @Test
public void testApplyWhereImageFoundAndHardwareNotFound() { public void testApplyWhereImageFoundAndHardwareNotFound() {
Map<ServerStatus, NodeState> serverStateToNodeState = CloudServersComputeServiceContextModule.serverToNodeState; Map<ServerStatus, Status> serverStateToNodeStatus = CloudServersComputeServiceContextModule.toPortableNodeStatus;
org.jclouds.compute.domain.Image jcImage = CloudServersImageToImageTest.convertImage(); org.jclouds.compute.domain.Image jcImage = CloudServersImageToImageTest.convertImage();
Set<org.jclouds.compute.domain.Image> images = ImmutableSet.of(jcImage); Set<org.jclouds.compute.domain.Image> images = ImmutableSet.of(jcImage);
Set<org.jclouds.compute.domain.Hardware> hardwares = ImmutableSet.of(); Set<org.jclouds.compute.domain.Hardware> hardwares = ImmutableSet.of();
Server server = ParseServerFromJsonResponseTest.parseServer(); Server server = ParseServerFromJsonResponseTest.parseServer();
ServerToNodeMetadata parser = new ServerToNodeMetadata(serverStateToNodeState, Suppliers.<Set<? extends Image>> ofInstance(images), Suppliers ServerToNodeMetadata parser = new ServerToNodeMetadata(serverStateToNodeStatus, Suppliers.<Set<? extends Image>> ofInstance(images), Suppliers
.ofInstance(provider), Suppliers.<Set<? extends Hardware>> ofInstance(hardwares), namingConvention); .ofInstance(provider), Suppliers.<Set<? extends Hardware>> ofInstance(hardwares), namingConvention);
NodeMetadata metadata = parser.apply(server); NodeMetadata metadata = parser.apply(server);
@ -105,7 +105,7 @@ public class ServerToNodeMetadataTest {
assertEquals( assertEquals(
metadata, metadata,
new NodeMetadataBuilder() new NodeMetadataBuilder()
.state(NodeState.PENDING) .status(Status.PENDING)
.publicAddresses(ImmutableSet.of("67.23.10.132", "67.23.10.131")) .publicAddresses(ImmutableSet.of("67.23.10.132", "67.23.10.131"))
.privateAddresses(ImmutableSet.of("10.176.42.16")) .privateAddresses(ImmutableSet.of("10.176.42.16"))
.imageId("2") .imageId("2")
@ -126,12 +126,12 @@ public class ServerToNodeMetadataTest {
@Test @Test
public void testApplyWhereImageAndHardwareFound() { public void testApplyWhereImageAndHardwareFound() {
Map<ServerStatus, NodeState> serverStateToNodeState = CloudServersComputeServiceContextModule.serverToNodeState; Map<ServerStatus, Status> serverStateToNodeStatus = CloudServersComputeServiceContextModule.toPortableNodeStatus;
Set<org.jclouds.compute.domain.Image> images = ImmutableSet.of(CloudServersImageToImageTest.convertImage()); Set<org.jclouds.compute.domain.Image> images = ImmutableSet.of(CloudServersImageToImageTest.convertImage());
Set<org.jclouds.compute.domain.Hardware> hardwares = ImmutableSet.of(FlavorToHardwareTest.convertFlavor()); Set<org.jclouds.compute.domain.Hardware> hardwares = ImmutableSet.of(FlavorToHardwareTest.convertFlavor());
Server server = ParseServerFromJsonResponseTest.parseServer(); Server server = ParseServerFromJsonResponseTest.parseServer();
ServerToNodeMetadata parser = new ServerToNodeMetadata(serverStateToNodeState, Suppliers.<Set<? extends Image>> ofInstance(images), Suppliers ServerToNodeMetadata parser = new ServerToNodeMetadata(serverStateToNodeStatus, Suppliers.<Set<? extends Image>> ofInstance(images), Suppliers
.ofInstance(provider), Suppliers.<Set<? extends Hardware>> ofInstance(hardwares), namingConvention); .ofInstance(provider), Suppliers.<Set<? extends Hardware>> ofInstance(hardwares), namingConvention);
NodeMetadata metadata = parser.apply(server); NodeMetadata metadata = parser.apply(server);
@ -139,7 +139,7 @@ public class ServerToNodeMetadataTest {
assertEquals( assertEquals(
metadata, metadata,
new NodeMetadataBuilder() new NodeMetadataBuilder()
.state(NodeState.PENDING) .status(Status.PENDING)
.publicAddresses(ImmutableSet.of("67.23.10.132", "67.23.10.131")) .publicAddresses(ImmutableSet.of("67.23.10.132", "67.23.10.131"))
.privateAddresses(ImmutableSet.of("10.176.42.16")) .privateAddresses(ImmutableSet.of("10.176.42.16"))
.imageId("2") .imageId("2")

View File

@ -18,8 +18,8 @@
*/ */
package org.jclouds.cloudservers.compute.predicates; package org.jclouds.cloudservers.compute.predicates;
import static junit.framework.Assert.assertFalse; import static org.testng.Assert.assertFalse;
import static junit.framework.Assert.assertTrue; import static org.testng.Assert.assertTrue;
import java.net.URI; import java.net.URI;
import java.util.Map; import java.util.Map;

View File

@ -36,12 +36,20 @@
<properties> <properties>
<test.cloudsigma.endpoint>https://api.cloudsigma.com</test.cloudsigma.endpoint> <test.cloudsigma.endpoint>https://api.cloudsigma.com</test.cloudsigma.endpoint>
<test.cloudsigma.api-version>1.0</test.cloudsigma.api-version> <test.cloudsigma.api-version>1.0</test.cloudsigma.api-version>
<test.cloudsigma.build-version /> <test.cloudsigma.build-version></test.cloudsigma.build-version>
<test.cloudsigma.identity>FIXME</test.cloudsigma.identity> <test.cloudsigma.identity>FIXME</test.cloudsigma.identity>
<test.cloudsigma.credential>FIXME</test.cloudsigma.credential> <test.cloudsigma.credential>FIXME</test.cloudsigma.credential>
<test.cloudsigma.image-id>f3c7c665-cd54-4a78-8fd2-7ec2f028cf29</test.cloudsigma.image-id> <test.cloudsigma.image-id>f3c7c665-cd54-4a78-8fd2-7ec2f028cf29</test.cloudsigma.image-id>
<test.cloudsigma.image.login-user /> <test.cloudsigma.image.login-user></test.cloudsigma.image.login-user>
<test.cloudsigma.image.authenticate-sudo /> <test.cloudsigma.image.authenticate-sudo></test.cloudsigma.image.authenticate-sudo>
<jclouds.osgi.export>org.jclouds.cloudsigma*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>
org.jclouds.compute.internal;version="${project.version}",
org.jclouds.rest.internal;version="${project.version}",
org.jclouds*;version="${project.version}",
*
</jclouds.osgi.import>
</properties> </properties>
<dependencies> <dependencies>
@ -112,25 +120,4 @@
</profile> </profile>
</profiles> </profiles>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>org.jclouds.cloudsigma*;version="${project.version}"</Export-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>
</configuration>
</plugin>
</plugins>
</build>
</project> </project>

View File

@ -211,6 +211,11 @@ public class CloudSigmaComputeServiceAdapter implements
return client.getServerInfo(id); return client.getServerInfo(id);
} }
@Override
public DriveInfo getImage(String id) {
return client.getDriveInfo(id);
}
@Override @Override
public void destroyNode(String id) { public void destroyNode(String id) {
ServerInfo server = getNode(id); ServerInfo server = getNode(id);

View File

@ -26,6 +26,7 @@ import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.ImageBuilder; import org.jclouds.compute.domain.ImageBuilder;
import org.jclouds.compute.domain.OperatingSystem; import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.OsFamilyVersion64Bit; import org.jclouds.compute.domain.OsFamilyVersion64Bit;
import org.jclouds.compute.domain.Image.Status;
import org.jclouds.compute.domain.OperatingSystem.Builder; import org.jclouds.compute.domain.OperatingSystem.Builder;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
@ -61,6 +62,6 @@ public class PreinstalledDiskToImage implements Function<DriveInfo, Image> {
return new ImageBuilder().ids(drive.getUuid()) return new ImageBuilder().ids(drive.getUuid())
.userMetadata(ImmutableMap.<String, String> of("size", drive.getSize() / 1024 / 1024 / 1024 + "")) .userMetadata(ImmutableMap.<String, String> of("size", drive.getSize() / 1024 / 1024 / 1024 + ""))
.location(locationSupplier.get()).name(drive.getName()).description(description) .location(locationSupplier.get()).name(drive.getName()).description(description)
.operatingSystem(builder.build()).version("").build(); .operatingSystem(builder.build()).status(Status.AVAILABLE).version("").build();
} }
} }

View File

@ -38,10 +38,10 @@ import org.jclouds.compute.domain.HardwareBuilder;
import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadataBuilder; import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.Processor; import org.jclouds.compute.domain.Processor;
import org.jclouds.compute.domain.Volume; import org.jclouds.compute.domain.Volume;
import org.jclouds.compute.domain.VolumeBuilder; import org.jclouds.compute.domain.VolumeBuilder;
import org.jclouds.compute.domain.NodeMetadata.Status;
import org.jclouds.compute.functions.GroupNamingConvention; import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
@ -60,13 +60,13 @@ import com.google.common.util.concurrent.UncheckedExecutionException;
*/ */
@Singleton @Singleton
public class ServerInfoToNodeMetadata implements Function<ServerInfo, NodeMetadata> { public class ServerInfoToNodeMetadata implements Function<ServerInfo, NodeMetadata> {
public static final Map<ServerStatus, NodeState> serverStatusToNodeState = ImmutableMap public static final Map<ServerStatus, Status> serverStatusToNodeStatus = ImmutableMap
.<ServerStatus, NodeState> builder().put(ServerStatus.ACTIVE, NodeState.RUNNING)// .<ServerStatus, Status> builder().put(ServerStatus.ACTIVE, Status.RUNNING)//
.put(ServerStatus.STOPPED, NodeState.SUSPENDED)// .put(ServerStatus.STOPPED, Status.SUSPENDED)//
.put(ServerStatus.PAUSED, NodeState.SUSPENDED)// .put(ServerStatus.PAUSED, Status.SUSPENDED)//
.put(ServerStatus.DUMPED, NodeState.PENDING)// .put(ServerStatus.DUMPED, Status.PENDING)//
.put(ServerStatus.DEAD, NodeState.TERMINATED)// .put(ServerStatus.DEAD, Status.TERMINATED)//
.put(ServerStatus.UNRECOGNIZED, NodeState.UNRECOGNIZED)// .put(ServerStatus.UNRECOGNIZED, Status.UNRECOGNIZED)//
.build(); .build();
private final Function<Server, String> getImageIdFromServer; private final Function<Server, String> getImageIdFromServer;
@ -104,7 +104,7 @@ public class ServerInfoToNodeMetadata implements Function<ServerInfo, NodeMetada
builder.hardware(new HardwareBuilder().ids(from.getUuid()).hypervisor("kvm") builder.hardware(new HardwareBuilder().ids(from.getUuid()).hypervisor("kvm")
.processors(ImmutableList.of(new Processor(1, from.getCpu()))).ram(from.getMem()) .processors(ImmutableList.of(new Processor(1, from.getCpu()))).ram(from.getMem())
.volumes(Iterables.transform(from.getDevices().values(), deviceToVolume)).build()); .volumes(Iterables.transform(from.getDevices().values(), deviceToVolume)).build());
builder.state(serverStatusToNodeState.get(from.getStatus())); builder.status(serverStatusToNodeStatus.get(from.getStatus()));
builder.publicAddresses(ImmutableSet.<String> of(from.getVnc().getIp())); builder.publicAddresses(ImmutableSet.<String> of(from.getVnc().getIp()));
builder.privateAddresses(ImmutableSet.<String> of()); builder.privateAddresses(ImmutableSet.<String> of());
return builder.build(); return builder.build();

View File

@ -50,16 +50,24 @@
<properties> <properties>
<test.cloudstack.endpoint>http://localhost:8080/client/api</test.cloudstack.endpoint> <test.cloudstack.endpoint>http://localhost:8080/client/api</test.cloudstack.endpoint>
<test.cloudstack.api-version>2.2.12</test.cloudstack.api-version> <test.cloudstack.api-version>2.2.12</test.cloudstack.api-version>
<test.cloudstack.build-version /> <test.cloudstack.build-version></test.cloudstack.build-version>
<test.cloudstack.identity>FIXME_apiKey</test.cloudstack.identity> <test.cloudstack.identity>FIXME_apiKey</test.cloudstack.identity>
<test.cloudstack.credential>FIXME_secretKey</test.cloudstack.credential> <test.cloudstack.credential>FIXME_secretKey</test.cloudstack.credential>
<test.cloudstack.domainAdminIdentity /> <test.cloudstack.domainAdminIdentity></test.cloudstack.domainAdminIdentity>
<test.cloudstack.domainAdminCredential /> <test.cloudstack.domainAdminCredential></test.cloudstack.domainAdminCredential>
<test.cloudstack.globalAdminIdentity /> <test.cloudstack.globalAdminIdentity></test.cloudstack.globalAdminIdentity>
<test.cloudstack.globalAdminCredential /> <test.cloudstack.globalAdminCredential></test.cloudstack.globalAdminCredential>
<test.cloudstack.image-id /> <test.cloudstack.image-id></test.cloudstack.image-id>
<test.cloudstack.image.login-user /> <test.cloudstack.image.login-user></test.cloudstack.image.login-user>
<test.cloudstack.image.authenticate-sudo /> <test.cloudstack.image.authenticate-sudo></test.cloudstack.image.authenticate-sudo>
<jclouds.osgi.export>org.jclouds.cloudstack*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>
org.jclouds.compute.internal;version="${project.version}",
org.jclouds.rest.internal;version="${project.version}",
org.jclouds*;version="${project.version}",
*
</jclouds.osgi.import>
</properties> </properties>
<dependencies> <dependencies>
<dependency> <dependency>
@ -146,24 +154,4 @@
</profile> </profile>
</profiles> </profiles>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>org.jclouds.cloudstack*;version="${project.version}"</Export-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>
</configuration>
</plugin>
</plugins>
</build>
</project> </project>

View File

@ -41,6 +41,7 @@ import org.jclouds.cloudstack.compute.strategy.AdvancedNetworkOptionsConverter;
import org.jclouds.cloudstack.compute.strategy.BasicNetworkOptionsConverter; import org.jclouds.cloudstack.compute.strategy.BasicNetworkOptionsConverter;
import org.jclouds.cloudstack.compute.strategy.CloudStackComputeServiceAdapter; import org.jclouds.cloudstack.compute.strategy.CloudStackComputeServiceAdapter;
import org.jclouds.cloudstack.compute.strategy.OptionsConverter; import org.jclouds.cloudstack.compute.strategy.OptionsConverter;
import org.jclouds.cloudstack.domain.FirewallRule;
import org.jclouds.cloudstack.domain.IPForwardingRule; import org.jclouds.cloudstack.domain.IPForwardingRule;
import org.jclouds.cloudstack.domain.Network; import org.jclouds.cloudstack.domain.Network;
import org.jclouds.cloudstack.domain.NetworkType; import org.jclouds.cloudstack.domain.NetworkType;
@ -51,8 +52,11 @@ import org.jclouds.cloudstack.domain.User;
import org.jclouds.cloudstack.domain.VirtualMachine; import org.jclouds.cloudstack.domain.VirtualMachine;
import org.jclouds.cloudstack.domain.Zone; import org.jclouds.cloudstack.domain.Zone;
import org.jclouds.cloudstack.features.GuestOSClient; import org.jclouds.cloudstack.features.GuestOSClient;
import org.jclouds.cloudstack.functions.GetFirewallRulesByVirtualMachine;
import org.jclouds.cloudstack.functions.GetIPForwardingRulesByVirtualMachine;
import org.jclouds.cloudstack.functions.StaticNATVirtualMachineInNetwork; import org.jclouds.cloudstack.functions.StaticNATVirtualMachineInNetwork;
import org.jclouds.cloudstack.functions.ZoneIdToZone; import org.jclouds.cloudstack.functions.ZoneIdToZone;
import org.jclouds.cloudstack.options.ListFirewallRulesOptions;
import org.jclouds.cloudstack.predicates.JobComplete; import org.jclouds.cloudstack.predicates.JobComplete;
import org.jclouds.cloudstack.suppliers.GetCurrentUser; import org.jclouds.cloudstack.suppliers.GetCurrentUser;
import org.jclouds.cloudstack.suppliers.NetworksForCurrentUser; import org.jclouds.cloudstack.suppliers.NetworksForCurrentUser;
@ -108,6 +112,8 @@ public class CloudStackComputeServiceContextModule extends
install(new FactoryModuleBuilder().build(StaticNATVirtualMachineInNetwork.Factory.class)); install(new FactoryModuleBuilder().build(StaticNATVirtualMachineInNetwork.Factory.class));
bind(new TypeLiteral<CacheLoader<String, Set<IPForwardingRule>>>() { bind(new TypeLiteral<CacheLoader<String, Set<IPForwardingRule>>>() {
}).to(GetIPForwardingRulesByVirtualMachine.class); }).to(GetIPForwardingRulesByVirtualMachine.class);
bind(new TypeLiteral<CacheLoader<String, Set<FirewallRule>>>() {
}).to(GetFirewallRulesByVirtualMachine.class);
bind(new TypeLiteral<CacheLoader<String, Zone>>() { bind(new TypeLiteral<CacheLoader<String, Zone>>() {
}).to(ZoneIdToZone.class); }).to(ZoneIdToZone.class);
bind(new TypeLiteral<Supplier<LoadingCache<String, Zone>>>() { bind(new TypeLiteral<Supplier<LoadingCache<String, Zone>>>() {
@ -184,24 +190,12 @@ public class CloudStackComputeServiceContextModule extends
return CacheBuilder.newBuilder().build(getIPForwardingRules); return CacheBuilder.newBuilder().build(getIPForwardingRules);
} }
@Provides
@Singleton @Singleton
public static class GetIPForwardingRulesByVirtualMachine extends CacheLoader<String, Set<IPForwardingRule>> { protected LoadingCache<String, Set<FirewallRule>> getFirewallRulesByVirtualMachine(
private final CloudStackClient client; CacheLoader<String, Set<FirewallRule>> getFirewallRules) {
return CacheBuilder.newBuilder().build(getFirewallRules);
@Inject
public GetIPForwardingRulesByVirtualMachine(CloudStackClient client) {
this.client = checkNotNull(client, "client");
}
/**
* @throws ResourceNotFoundException
* when there is no ip forwarding rule available for the VM
*/
@Override
public Set<IPForwardingRule> load(String input) {
Set<IPForwardingRule> rules = client.getNATClient().getIPForwardingRulesForVirtualMachine(input);
return rules != null ? rules : ImmutableSet.<IPForwardingRule>of();
}
} }
@Provides @Provides

View File

@ -31,6 +31,7 @@ import org.jclouds.collect.Memoized;
import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.ImageBuilder; import org.jclouds.compute.domain.ImageBuilder;
import org.jclouds.compute.domain.OperatingSystem; import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.Image.Status;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import com.google.common.base.Function; import com.google.common.base.Function;
@ -62,6 +63,8 @@ public class TemplateToImage implements Function<Template, Image> {
if (!template.isCrossZones()) if (!template.isCrossZones())
builder.location(findLocationForTemplate.apply(template)); builder.location(findLocationForTemplate.apply(template));
//TODO: implement status mapping!!!
builder.status(Status.AVAILABLE);
return builder.build(); return builder.build();
} }

View File

@ -41,8 +41,8 @@ import org.jclouds.compute.domain.HardwareBuilder;
import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadataBuilder; import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.Processor; import org.jclouds.compute.domain.Processor;
import org.jclouds.compute.domain.NodeMetadata.Status;
import org.jclouds.compute.functions.GroupNamingConvention; import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.rest.ResourceNotFoundException; import org.jclouds.rest.ResourceNotFoundException;
@ -64,17 +64,17 @@ import com.google.common.util.concurrent.UncheckedExecutionException;
@Singleton @Singleton
public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, NodeMetadata> { public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, NodeMetadata> {
public static final Map<VirtualMachine.State, NodeState> vmStateToNodeState = ImmutableMap public static final Map<VirtualMachine.State, Status> vmStateToNodeStatus = ImmutableMap
.<VirtualMachine.State, NodeState> builder().put(VirtualMachine.State.STARTING, NodeState.PENDING) .<VirtualMachine.State, Status> builder().put(VirtualMachine.State.STARTING, Status.PENDING)
.put(VirtualMachine.State.RUNNING, NodeState.RUNNING).put(VirtualMachine.State.STOPPING, NodeState.PENDING) .put(VirtualMachine.State.RUNNING, Status.RUNNING).put(VirtualMachine.State.STOPPING, Status.PENDING)
.put(VirtualMachine.State.STOPPED, NodeState.SUSPENDED) .put(VirtualMachine.State.STOPPED, Status.SUSPENDED)
.put(VirtualMachine.State.DESTROYED, NodeState.TERMINATED) .put(VirtualMachine.State.DESTROYED, Status.TERMINATED)
.put(VirtualMachine.State.EXPUNGING, NodeState.TERMINATED) .put(VirtualMachine.State.EXPUNGING, Status.TERMINATED)
.put(VirtualMachine.State.MIGRATING, NodeState.PENDING).put(VirtualMachine.State.ERROR, NodeState.ERROR) .put(VirtualMachine.State.MIGRATING, Status.PENDING).put(VirtualMachine.State.ERROR, Status.ERROR)
.put(VirtualMachine.State.UNKNOWN, NodeState.UNRECOGNIZED) .put(VirtualMachine.State.UNKNOWN, Status.UNRECOGNIZED)
// TODO: is this really a state? // TODO: is this really a state?
.put(VirtualMachine.State.SHUTDOWNED, NodeState.PENDING) .put(VirtualMachine.State.SHUTDOWNED, Status.PENDING)
.put(VirtualMachine.State.UNRECOGNIZED, NodeState.UNRECOGNIZED).build(); .put(VirtualMachine.State.UNRECOGNIZED, Status.UNRECOGNIZED).build();
private final FindLocationForVirtualMachine findLocationForVirtualMachine; private final FindLocationForVirtualMachine findLocationForVirtualMachine;
private final FindImageForVirtualMachine findImageForVirtualMachine; private final FindImageForVirtualMachine findImageForVirtualMachine;
@ -123,7 +123,7 @@ public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, No
.hypervisor(from.getHypervisor())// .hypervisor(from.getHypervisor())//
.build()); .build());
builder.state(vmStateToNodeState.get(from.getState())); builder.status(vmStateToNodeStatus.get(from.getState()));
Set<String> publicAddresses = newHashSet(), privateAddresses = newHashSet(); Set<String> publicAddresses = newHashSet(), privateAddresses = newHashSet();
if (from.getIPAddress() != null) { if (from.getIPAddress() != null) {
@ -134,6 +134,9 @@ public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, No
publicAddresses.add(from.getIPAddress()); publicAddresses.add(from.getIPAddress());
} }
} }
if (from.getPublicIP() != null) {
publicAddresses.add(from.getPublicIP());
}
for (NIC nic : from.getNICs()) { for (NIC nic : from.getNICs()) {
if (nic.getIPAddress() != null) { if (nic.getIPAddress() != null) {
if (isPrivateIPAddress(nic.getIPAddress())) { if (isPrivateIPAddress(nic.getIPAddress())) {

View File

@ -20,9 +20,11 @@ package org.jclouds.cloudstack.compute.strategy;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Predicates.and; import static com.google.common.base.Predicates.and;
import static com.google.common.base.Predicates.not;
import static com.google.common.collect.Iterables.filter; import static com.google.common.collect.Iterables.filter;
import static org.jclouds.cloudstack.predicates.NetworkPredicates.defaultNetworkInZone; import static org.jclouds.cloudstack.predicates.NetworkPredicates.defaultNetworkInZone;
import static org.jclouds.cloudstack.predicates.NetworkPredicates.supportsStaticNAT; import static org.jclouds.cloudstack.predicates.NetworkPredicates.supportsStaticNAT;
import static org.jclouds.cloudstack.predicates.NetworkPredicates.isIsolatedNetwork;
import java.util.Map; import java.util.Map;
@ -49,6 +51,9 @@ public class AdvancedNetworkOptionsConverter implements OptionsConverter {
} else { } else {
checkArgument(!networks.isEmpty(), "please setup a network for zone: " + zoneId); checkArgument(!networks.isEmpty(), "please setup a network for zone: " + zoneId);
Network defaultNetworkInZone = Iterables.getFirst(filter(networks.values(), and(defaultNetworkInZone(zoneId), supportsStaticNAT())), null); Network defaultNetworkInZone = Iterables.getFirst(filter(networks.values(), and(defaultNetworkInZone(zoneId), supportsStaticNAT())), null);
if(defaultNetworkInZone == null) {
defaultNetworkInZone = Iterables.getFirst(filter(networks.values(), isIsolatedNetwork()), null);
}
if (defaultNetworkInZone == null) { if (defaultNetworkInZone == null) {
throw new IllegalArgumentException("please choose a specific network in zone " + zoneId + ": " + networks); throw new IllegalArgumentException("please choose a specific network in zone " + zoneId + ": " + networks);
} else { } else {

View File

@ -22,6 +22,9 @@ import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.Iterables.filter; import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.get;
import static org.jclouds.cloudstack.options.DeployVirtualMachineOptions.Builder.displayName;
import static org.jclouds.cloudstack.options.ListTemplatesOptions.Builder.id;
import static org.jclouds.cloudstack.predicates.TemplatePredicates.isReady; import static org.jclouds.cloudstack.predicates.TemplatePredicates.isReady;
import java.util.List; import java.util.List;
@ -37,6 +40,8 @@ import javax.inject.Singleton;
import org.jclouds.cloudstack.CloudStackClient; import org.jclouds.cloudstack.CloudStackClient;
import org.jclouds.cloudstack.compute.options.CloudStackTemplateOptions; import org.jclouds.cloudstack.compute.options.CloudStackTemplateOptions;
import org.jclouds.cloudstack.domain.AsyncCreateResponse; import org.jclouds.cloudstack.domain.AsyncCreateResponse;
import org.jclouds.cloudstack.domain.Capabilities;
import org.jclouds.cloudstack.domain.FirewallRule;
import org.jclouds.cloudstack.domain.IPForwardingRule; import org.jclouds.cloudstack.domain.IPForwardingRule;
import org.jclouds.cloudstack.domain.Network; import org.jclouds.cloudstack.domain.Network;
import org.jclouds.cloudstack.domain.NetworkType; import org.jclouds.cloudstack.domain.NetworkType;
@ -45,10 +50,12 @@ import org.jclouds.cloudstack.domain.ServiceOffering;
import org.jclouds.cloudstack.domain.Template; import org.jclouds.cloudstack.domain.Template;
import org.jclouds.cloudstack.domain.VirtualMachine; import org.jclouds.cloudstack.domain.VirtualMachine;
import org.jclouds.cloudstack.domain.Zone; import org.jclouds.cloudstack.domain.Zone;
import org.jclouds.cloudstack.functions.CreateFirewallRulesForIP;
import org.jclouds.cloudstack.functions.CreatePortForwardingRulesForIP; import org.jclouds.cloudstack.functions.CreatePortForwardingRulesForIP;
import org.jclouds.cloudstack.functions.StaticNATVirtualMachineInNetwork; import org.jclouds.cloudstack.functions.StaticNATVirtualMachineInNetwork;
import org.jclouds.cloudstack.functions.StaticNATVirtualMachineInNetwork.Factory; import org.jclouds.cloudstack.functions.StaticNATVirtualMachineInNetwork.Factory;
import org.jclouds.cloudstack.options.DeployVirtualMachineOptions; import org.jclouds.cloudstack.options.DeployVirtualMachineOptions;
import org.jclouds.cloudstack.options.ListFirewallRulesOptions;
import org.jclouds.cloudstack.strategy.BlockUntilJobCompletesAndReturnResult; import org.jclouds.cloudstack.strategy.BlockUntilJobCompletesAndReturnResult;
import org.jclouds.collect.Memoized; import org.jclouds.collect.Memoized;
import org.jclouds.compute.ComputeService; import org.jclouds.compute.ComputeService;
@ -70,7 +77,6 @@ import com.google.common.primitives.Ints;
/** /**
* defines the connection between the {@link CloudStackClient} implementation * defines the connection between the {@link CloudStackClient} implementation
* and the jclouds {@link ComputeService} * and the jclouds {@link ComputeService}
*
*/ */
@Singleton @Singleton
public class CloudStackComputeServiceAdapter implements public class CloudStackComputeServiceAdapter implements
@ -86,6 +92,7 @@ public class CloudStackComputeServiceAdapter implements
private final BlockUntilJobCompletesAndReturnResult blockUntilJobCompletesAndReturnResult; private final BlockUntilJobCompletesAndReturnResult blockUntilJobCompletesAndReturnResult;
private final Factory staticNATVMInNetwork; private final Factory staticNATVMInNetwork;
private final CreatePortForwardingRulesForIP setupPortForwardingRulesForIP; private final CreatePortForwardingRulesForIP setupPortForwardingRulesForIP;
private final CreateFirewallRulesForIP setupFirewallRulesForIP;
private final LoadingCache<String, Set<IPForwardingRule>> vmToRules; private final LoadingCache<String, Set<IPForwardingRule>> vmToRules;
private final Map<String, Credentials> credentialStore; private final Map<String, Credentials> credentialStore;
private final Map<NetworkType, ? extends OptionsConverter> optionsConverters; private final Map<NetworkType, ? extends OptionsConverter> optionsConverters;
@ -96,8 +103,11 @@ public class CloudStackComputeServiceAdapter implements
@Memoized Supplier<Map<String, Network>> networkSupplier, @Memoized Supplier<Map<String, Network>> networkSupplier,
BlockUntilJobCompletesAndReturnResult blockUntilJobCompletesAndReturnResult, BlockUntilJobCompletesAndReturnResult blockUntilJobCompletesAndReturnResult,
StaticNATVirtualMachineInNetwork.Factory staticNATVMInNetwork, StaticNATVirtualMachineInNetwork.Factory staticNATVMInNetwork,
CreatePortForwardingRulesForIP setupPortForwardingRulesForIP, LoadingCache<String, Set<IPForwardingRule>> vmToRules, CreatePortForwardingRulesForIP setupPortForwardingRulesForIP,
Map<String, Credentials> credentialStore, Map<NetworkType, ? extends OptionsConverter> optionsConverters, CreateFirewallRulesForIP setupFirewallRulesForIP,
LoadingCache<String, Set<IPForwardingRule>> vmToRules,
Map<String, Credentials> credentialStore,
Map<NetworkType, ? extends OptionsConverter> optionsConverters,
Supplier<LoadingCache<String, Zone>> zoneIdToZone) { Supplier<LoadingCache<String, Zone>> zoneIdToZone) {
this.client = checkNotNull(client, "client"); this.client = checkNotNull(client, "client");
this.jobComplete = checkNotNull(jobComplete, "jobComplete"); this.jobComplete = checkNotNull(jobComplete, "jobComplete");
@ -106,6 +116,7 @@ public class CloudStackComputeServiceAdapter implements
"blockUntilJobCompletesAndReturnResult"); "blockUntilJobCompletesAndReturnResult");
this.staticNATVMInNetwork = checkNotNull(staticNATVMInNetwork, "staticNATVMInNetwork"); this.staticNATVMInNetwork = checkNotNull(staticNATVMInNetwork, "staticNATVMInNetwork");
this.setupPortForwardingRulesForIP = checkNotNull(setupPortForwardingRulesForIP, "setupPortForwardingRulesForIP"); this.setupPortForwardingRulesForIP = checkNotNull(setupPortForwardingRulesForIP, "setupPortForwardingRulesForIP");
this.setupFirewallRulesForIP = checkNotNull(setupFirewallRulesForIP, "setupFirewallRulesForIP");
this.vmToRules = checkNotNull(vmToRules, "vmToRules"); this.vmToRules = checkNotNull(vmToRules, "vmToRules");
this.credentialStore = checkNotNull(credentialStore, "credentialStore"); this.credentialStore = checkNotNull(credentialStore, "credentialStore");
this.optionsConverters = optionsConverters; this.optionsConverters = optionsConverters;
@ -133,7 +144,7 @@ public class CloudStackComputeServiceAdapter implements
CloudStackTemplateOptions templateOptions = template.getOptions().as(CloudStackTemplateOptions.class); CloudStackTemplateOptions templateOptions = template.getOptions().as(CloudStackTemplateOptions.class);
checkState(optionsConverters.containsKey(zone.getNetworkType()), "no options converter configured for network type %s", zone.getNetworkType()); checkState(optionsConverters.containsKey(zone.getNetworkType()), "no options converter configured for network type %s", zone.getNetworkType());
DeployVirtualMachineOptions options = DeployVirtualMachineOptions.Builder.displayName(name).name(name); DeployVirtualMachineOptions options = displayName(name).name(name);
OptionsConverter optionsConverter = optionsConverters.get(zone.getNetworkType()); OptionsConverter optionsConverter = optionsConverters.get(zone.getNetworkType());
options = optionsConverter.apply(templateOptions, networks, zoneId, options); options = optionsConverter.apply(templateOptions, networks, zoneId, options);
@ -163,6 +174,7 @@ public class CloudStackComputeServiceAdapter implements
AsyncCreateResponse job = client.getVirtualMachineClient().deployVirtualMachineInZone(zoneId, serviceOfferingId, AsyncCreateResponse job = client.getVirtualMachineClient().deployVirtualMachineInZone(zoneId, serviceOfferingId,
templateId, options); templateId, options);
VirtualMachine vm = blockUntilJobCompletesAndReturnResult.<VirtualMachine>apply(job); VirtualMachine vm = blockUntilJobCompletesAndReturnResult.<VirtualMachine>apply(job);
logger.debug("--- virtualmachine: %s", vm);
LoginCredentials credentials = null; LoginCredentials credentials = null;
if (vm.isPasswordEnabled()) { if (vm.isPasswordEnabled()) {
assert vm.getPassword() != null : vm; assert vm.getPassword() != null : vm;
@ -171,15 +183,23 @@ public class CloudStackComputeServiceAdapter implements
credentials = LoginCredentials.fromCredentials(credentialStore.get("keypair#" + templateOptions.getKeyPair())); credentials = LoginCredentials.fromCredentials(credentialStore.get("keypair#" + templateOptions.getKeyPair()));
} }
if (templateOptions.shouldSetupStaticNat()) { if (templateOptions.shouldSetupStaticNat()) {
Capabilities capabilities = client.getConfigurationClient().listCapabilities();
// TODO: possibly not all network ids, do we want to do this // TODO: possibly not all network ids, do we want to do this
for (String networkId : options.getNetworkIds()) { for (String networkId : options.getNetworkIds()) {
logger.debug(">> creating static NAT for virtualMachine(%s) in network(%s)", vm.getId(), networkId); logger.debug(">> creating static NAT for virtualMachine(%s) in network(%s)", vm.getId(), networkId);
PublicIPAddress ip = staticNATVMInNetwork.create(networks.get(networkId)).apply(vm); PublicIPAddress ip = staticNATVMInNetwork.create(networks.get(networkId)).apply(vm);
logger.trace("<< static NATed IPAddress(%s) to virtualMachine(%s)", ip.getId(), vm.getId()); logger.trace("<< static NATed IPAddress(%s) to virtualMachine(%s)", ip.getId(), vm.getId());
vm = client.getVirtualMachineClient().getVirtualMachine(vm.getId());
List<Integer> ports = Ints.asList(templateOptions.getInboundPorts()); List<Integer> ports = Ints.asList(templateOptions.getInboundPorts());
if (capabilities.getCloudStackVersion().startsWith("2")) {
logger.debug(">> setting up IP forwarding for IPAddress(%s) rules(%s)", ip.getId(), ports); logger.debug(">> setting up IP forwarding for IPAddress(%s) rules(%s)", ip.getId(), ports);
Set<IPForwardingRule> rules = setupPortForwardingRulesForIP.apply(ip, ports); Set<IPForwardingRule> rules = setupPortForwardingRulesForIP.apply(ip, ports);
logger.trace("<< setup %d IP forwarding rules on IPAddress(%s)", rules.size(), ip.getId()); logger.trace("<< setup %d IP forwarding rules on IPAddress(%s)", rules.size(), ip.getId());
} else {
logger.debug(">> setting up firewall rules for IPAddress(%s) rules(%s)", ip.getId(), ports);
Set<FirewallRule> rules = setupFirewallRulesForIP.apply(ip, ports);
logger.trace("<< setup %d firewall rules on IPAddress(%s)", rules.size(), ip.getId());
}
} }
} }
return new NodeAndInitialCredentials<VirtualMachine>(vm, vm.getId() + "", credentials); return new NodeAndInitialCredentials<VirtualMachine>(vm, vm.getId() + "", credentials);
@ -198,6 +218,11 @@ public class CloudStackComputeServiceAdapter implements
return filter(client.getTemplateClient().listTemplates(), isReady()); return filter(client.getTemplateClient().listTemplates(), isReady());
} }
@Override
public Template getImage(String id) {
return get(client.getTemplateClient().listTemplates(id(id)), 0, null);
}
@Override @Override
public Iterable<VirtualMachine> listNodes() { public Iterable<VirtualMachine> listNodes() {
return client.getVirtualMachineClient().listVirtualMachines(); return client.getVirtualMachineClient().listVirtualMachines();
@ -233,10 +258,13 @@ public class CloudStackComputeServiceAdapter implements
// 1) Delete IP forwarding rules associated with IP. // 1) Delete IP forwarding rules associated with IP.
Set<String> ipAddresses = deleteIPForwardingRulesForVMAndReturnDistinctIPs(virtualMachineId); Set<String> ipAddresses = deleteIPForwardingRulesForVMAndReturnDistinctIPs(virtualMachineId);
// 2) Disable static nat rule for the IP. // 2) Delete firewall rules associated with IP.
ipAddresses.addAll(deleteFirewallRulesForVMAndReturnDistinctIPs(virtualMachineId));
// 3) Disable static nat rule for the IP.
disableStaticNATOnIPAddresses(ipAddresses); disableStaticNATOnIPAddresses(ipAddresses);
// 3) Only after 1 and 2 release the IP address. // 4) Only after 1 and 2 release the IP address.
disassociateIPAddresses(ipAddresses); disassociateIPAddresses(ipAddresses);
destroyVirtualMachine(virtualMachineId); destroyVirtualMachine(virtualMachineId);
@ -297,6 +325,26 @@ public class CloudStackComputeServiceAdapter implements
return ipAddresses; return ipAddresses;
} }
public Set<String> deleteFirewallRulesForVMAndReturnDistinctIPs(String virtualMachineId) {
// immutable doesn't permit duplicates
Set<String> ipAddresses = Sets.newLinkedHashSet();
String publicIpId = client.getVirtualMachineClient().getVirtualMachine(virtualMachineId).getPublicIPId();
if (publicIpId != null) {
Set<FirewallRule> firewallRules = client.getFirewallClient()
.listFirewallRules(ListFirewallRulesOptions.Builder.ipAddressId(client.getVirtualMachineClient().getVirtualMachine(virtualMachineId).getPublicIPId()));
for (FirewallRule rule : firewallRules) {
if (rule.getState() != FirewallRule.State.DELETING) {
ipAddresses.add(rule.getIpAddressId());
client.getFirewallClient().deleteFirewallRule(rule.getId());
logger.debug(">> deleting FirewallRule(%s)", rule.getId());
}
}
}
return ipAddresses;
}
public void awaitCompletion(Iterable<String> jobs) { public void awaitCompletion(Iterable<String> jobs) {
logger.debug(">> awaiting completion of jobs(%s)", jobs); logger.debug(">> awaiting completion of jobs(%s)", jobs);
for (String job : jobs) for (String job : jobs)

View File

@ -55,7 +55,7 @@ public class FirewallRule implements Comparable<FirewallRule> {
// Rules in this state can not be sent to network elements. // Rules in this state can not be sent to network elements.
ADD, // Add means the rule has been created and has gone through network rule conflict detection. ADD, // Add means the rule has been created and has gone through network rule conflict detection.
ACTIVE, // Rule has been sent to the network elements and reported to be active. ACTIVE, // Rule has been sent to the network elements and reported to be active.
DELETEING, // Revoke means this rule has been revoked. If this rule has been sent to the DELETING, // Revoke means this rule has been revoked. If this rule has been sent to the
// network elements, the rule will be deleted from database. // network elements, the rule will be deleted from database.
UNKNOWN; UNKNOWN;

View File

@ -34,12 +34,19 @@ public enum GuestIPType {
* network. Dhcp role is played by domain router. * network. Dhcp role is played by domain router.
*/ */
VIRTUAL, VIRTUAL,
/** /**
* traffic directly to the network and VMs created here are assigned an IP * traffic directly to the network and VMs created here are assigned an IP
* directly from the network as configured * directly from the network as configured
*/ */
DIRECT, DIRECT,
/**
* TODO: add comments to explain the meaning (cs3 only)
*/
SHARED,
ISOLATED,
UNRECOGNIZED; UNRECOGNIZED;
@Override @Override

View File

@ -55,7 +55,7 @@ public class PortForwardingRule implements Comparable<PortForwardingRule> {
// Rules in this state can not be sent to network elements. // Rules in this state can not be sent to network elements.
ADD, // Add means the rule has been created and has gone through network rule conflict detection. ADD, // Add means the rule has been created and has gone through network rule conflict detection.
ACTIVE, // Rule has been sent to the network elements and reported to be active. ACTIVE, // Rule has been sent to the network elements and reported to be active.
DELETEING, // Revoke means this rule has been revoked. If this rule has been sent to the DELETING, // Revoke means this rule has been revoked. If this rule has been sent to the
// network elements, the rule will be deleted from database. // network elements, the rule will be deleted from database.
UNKNOWN; UNKNOWN;

View File

@ -31,6 +31,67 @@ import com.google.gson.annotations.SerializedName;
* @author Adrian Cole * @author Adrian Cole
*/ */
public class Template implements Comparable<Template> { public class Template implements Comparable<Template> {
public static enum Status {
/**
* status of download is not known. Example - When the job for downloading doesn't exist
* during progress check.
*/
UNKNOWN,
/**
* the download has been cancelled/aborted.
*/
ABANDONED,
/**
* the download has reached an error state. Example - there is not route to ssvm agent
*/
DOWNLOAD_ERROR,
/**
* the download hasn't started.
*/
NOT_DOWNLOADED,
/**
* the download is in progress
*/
DOWNLOAD_IN_PROGRESS,
/**
* the resource has been downloaded on secondary storage.
*/
DOWNLOADED,
// These states are specifically used for extraction of resources out of CS(ironically shown
// as download template in the UI, API - extractTemplate ). Some of the generic states (like
// abandoned, unknown) above are used for the extraction tasks as well.
/**
* the resource has been uploaded
*/
UPLOADED,
/**
* the resource upload work hasn't started yet
*/
NOT_UPLOADED,
/**
* the resource upload has reached error.
*/
UPLOAD_ERROR,
/**
* the resource upload is in progress.
*/
UPLOAD_IN_PROGRESS, UNRECOGNIZED;
public static Status fromValue(String state) {
if (state.equals("Download Complete")) {
return DOWNLOADED;
}
try {
return valueOf(checkNotNull(state, "state"));
} catch (IllegalArgumentException e) {
return UNRECOGNIZED;
}
}
}
public static Builder builder() { public static Builder builder() {
return new Builder(); return new Builder();
} }
@ -48,7 +109,7 @@ public class Template implements Comparable<Template> {
private String OSTypeId; private String OSTypeId;
private String name; private String name;
private Type type; private Type type;
private String status; private Status status;
private Format format; private Format format;
private String hypervisor; private String hypervisor;
private Long size; private Long size;
@ -129,7 +190,7 @@ public class Template implements Comparable<Template> {
return this; return this;
} }
public Builder status(String status) { public Builder status(Status status) {
this.status = status; this.status = status;
return this; return this;
} }
@ -287,7 +348,7 @@ public class Template implements Comparable<Template> {
@SerializedName("templatetype") @SerializedName("templatetype")
private Type type; private Type type;
//TODO: this should be a type //TODO: this should be a type
private String status; private Status status;
private Format format; private Format format;
private String hypervisor; private String hypervisor;
private Long size; private Long size;
@ -326,7 +387,7 @@ public class Template implements Comparable<Template> {
public Template(String id, String displayText, String domain, String domainId, String account, String accountId, public Template(String id, String displayText, String domain, String domainId, String account, String accountId,
String zone, String zoneId, String oSType, String oSTypeId, String name, Type type, String status, Format format, String zone, String zoneId, String oSType, String oSTypeId, String name, Type type, Status status, Format format,
String hypervisor, Long size, Date created, Date removed, boolean crossZones, boolean bootable, String hypervisor, Long size, Date created, Date removed, boolean crossZones, boolean bootable,
boolean extractable, boolean featured, boolean ispublic, boolean ready, boolean passwordEnabled, String jobId, boolean extractable, boolean featured, boolean ispublic, boolean ready, boolean passwordEnabled, String jobId,
String jobStatus, String checksum, String hostId, String hostName, String sourceTemplateId, String jobStatus, String checksum, String hostId, String hostName, String sourceTemplateId,
@ -451,9 +512,9 @@ public class Template implements Comparable<Template> {
} }
/** /**
* @return * @return status of the template
*/ */
public String getStatus() { public Status getStatus() {
return status; return status;
} }

View File

@ -71,6 +71,8 @@ public class VirtualMachine implements Comparable<VirtualMachine> {
private Long networkKbsWrite; private Long networkKbsWrite;
private String password; private String password;
private boolean passwordEnabled; private boolean passwordEnabled;
private String publicIP;
private String publicIPId;
private String rootDeviceId; private String rootDeviceId;
private String rootDeviceType; private String rootDeviceType;
private String serviceOfferingId; private String serviceOfferingId;
@ -225,6 +227,16 @@ public class VirtualMachine implements Comparable<VirtualMachine> {
return this; return this;
} }
public Builder publicIP(String publicIP) {
this.publicIP = publicIP;
return this;
}
public Builder publicIPId(String publicIPId) {
this.publicIPId = publicIPId;
return this;
}
public Builder rootDeviceId(String rootDeviceId) { public Builder rootDeviceId(String rootDeviceId) {
this.rootDeviceId = rootDeviceId; this.rootDeviceId = rootDeviceId;
return this; return this;
@ -294,7 +306,7 @@ public class VirtualMachine implements Comparable<VirtualMachine> {
return new VirtualMachine(id, account, cpuCount, cpuSpeed, cpuUsed, displayName, created, domain, domainId, return new VirtualMachine(id, account, cpuCount, cpuSpeed, cpuUsed, displayName, created, domain, domainId,
usesVirtualNetwork, group, groupId, guestOSId, HAEnabled, hostId, hostname, IPAddress, ISODisplayText, usesVirtualNetwork, group, groupId, guestOSId, HAEnabled, hostId, hostname, IPAddress, ISODisplayText,
ISOId, ISOName, jobId, jobStatus, memory, name, networkKbsRead, networkKbsWrite, password, ISOId, ISOName, jobId, jobStatus, memory, name, networkKbsRead, networkKbsWrite, password,
passwordEnabled, rootDeviceId, rootDeviceType, securityGroups, serviceOfferingId, serviceOfferingName, passwordEnabled, publicIP, publicIPId, rootDeviceId, rootDeviceType, securityGroups, serviceOfferingId, serviceOfferingName,
state, templateDisplayText, templateId, templateName, zoneId, zoneName, nics, hypervisor); state, templateDisplayText, templateId, templateName, zoneId, zoneName, nics, hypervisor);
} }
} }
@ -366,6 +378,10 @@ public class VirtualMachine implements Comparable<VirtualMachine> {
private String password; private String password;
@SerializedName("passwordenabled") @SerializedName("passwordenabled")
private boolean passwordEnabled; private boolean passwordEnabled;
@SerializedName("publicip")
private String publicIP;
@SerializedName("publicipid")
private String publicIPId;
@SerializedName("rootdeviceid") @SerializedName("rootdeviceid")
private String rootDeviceId; private String rootDeviceId;
@SerializedName("rootdevicetype") @SerializedName("rootdevicetype")
@ -395,7 +411,7 @@ public class VirtualMachine implements Comparable<VirtualMachine> {
Date created, String domain, String domainId, boolean usesVirtualNetwork, String group, String groupId, Date created, String domain, String domainId, boolean usesVirtualNetwork, String group, String groupId,
String guestOSId, boolean hAEnabled, String hostId, String hostname, String iPAddress, String iSODisplayText, String guestOSId, boolean hAEnabled, String hostId, String hostname, String iPAddress, String iSODisplayText,
String iSOId, String iSOName, String jobId, Integer jobStatus, long memory, String name, Long networkKbsRead, String iSOId, String iSOName, String jobId, Integer jobStatus, long memory, String name, Long networkKbsRead,
Long networkKbsWrite, String password, boolean passwordEnabled, String rootDeviceId, String rootDeviceType, Long networkKbsWrite, String password, boolean passwordEnabled, String publicIP, String publicIPId, String rootDeviceId, String rootDeviceType,
Set<SecurityGroup> securityGroups, String serviceOfferingId, String serviceOfferingName, State state, Set<SecurityGroup> securityGroups, String serviceOfferingId, String serviceOfferingName, State state,
String templateDisplayText, String templateId, String templateName, String zoneId, String zoneName, Set<NIC> nics, String templateDisplayText, String templateId, String templateName, String zoneId, String zoneName, Set<NIC> nics,
String hypervisor) { String hypervisor) {
@ -428,6 +444,8 @@ public class VirtualMachine implements Comparable<VirtualMachine> {
this.networkKbsWrite = networkKbsWrite; this.networkKbsWrite = networkKbsWrite;
this.password = password; this.password = password;
this.passwordEnabled = passwordEnabled; this.passwordEnabled = passwordEnabled;
this.publicIP = publicIP;
this.publicIPId = publicIPId;
this.rootDeviceId = rootDeviceId; this.rootDeviceId = rootDeviceId;
this.rootDeviceType = rootDeviceType; this.rootDeviceType = rootDeviceType;
this.securityGroups = ImmutableSet.copyOf(checkNotNull(securityGroups, "securityGroups")); this.securityGroups = ImmutableSet.copyOf(checkNotNull(securityGroups, "securityGroups"));
@ -659,6 +677,20 @@ public class VirtualMachine implements Comparable<VirtualMachine> {
return passwordEnabled; return passwordEnabled;
} }
/**
* @return public IP of this virtual machine
*/
public String getPublicIP() {
return publicIP;
}
/**
* @return ID of the public IP of this virtual machine
*/
public String getPublicIPId() {
return publicIPId;
}
/** /**
* @return device ID of the root volume * @return device ID of the root volume
*/ */
@ -786,6 +818,8 @@ public class VirtualMachine implements Comparable<VirtualMachine> {
if (!Objects.equal(networkKbsWrite, that.networkKbsWrite)) return false; if (!Objects.equal(networkKbsWrite, that.networkKbsWrite)) return false;
if (!Objects.equal(password, that.password)) return false; if (!Objects.equal(password, that.password)) return false;
if (!Objects.equal(passwordEnabled, that.passwordEnabled)) return false; if (!Objects.equal(passwordEnabled, that.passwordEnabled)) return false;
if (!Objects.equal(publicIP, that.publicIP)) return false;
if (!Objects.equal(publicIPId, that.publicIPId)) return false;
if (!Objects.equal(rootDeviceId, that.rootDeviceId)) return false; if (!Objects.equal(rootDeviceId, that.rootDeviceId)) return false;
if (!Objects.equal(rootDeviceType, that.rootDeviceType)) return false; if (!Objects.equal(rootDeviceType, that.rootDeviceType)) return false;
if (!Objects.equal(securityGroups, that.securityGroups)) return false; if (!Objects.equal(securityGroups, that.securityGroups)) return false;
@ -809,7 +843,7 @@ public class VirtualMachine implements Comparable<VirtualMachine> {
domain, domainId, usesVirtualNetwork, group, groupId, guestOSId, domain, domainId, usesVirtualNetwork, group, groupId, guestOSId,
HAEnabled, hostId, hostname, IPAddress, ISODisplayText, ISOId, HAEnabled, hostId, hostname, IPAddress, ISODisplayText, ISOId,
ISOName, jobId, jobStatus, memory, name, networkKbsRead, ISOName, jobId, jobStatus, memory, name, networkKbsRead,
networkKbsWrite, password, passwordEnabled, rootDeviceId, networkKbsWrite, password, passwordEnabled, publicIP, publicIPId, rootDeviceId,
rootDeviceType, securityGroups, serviceOfferingId, rootDeviceType, securityGroups, serviceOfferingId,
serviceOfferingName, state, templateDisplayText, templateId, serviceOfferingName, state, templateDisplayText, templateId,
templateName, zoneId, zoneName, nics, hypervisor); templateName, zoneId, zoneName, nics, hypervisor);
@ -846,6 +880,8 @@ public class VirtualMachine implements Comparable<VirtualMachine> {
", networkKbsWrite=" + networkKbsWrite + ", networkKbsWrite=" + networkKbsWrite +
", password='" + password + '\'' + ", password='" + password + '\'' +
", passwordEnabled=" + passwordEnabled + ", passwordEnabled=" + passwordEnabled +
", publicIP='" + publicIP + '\'' +
", publicIPId='" + publicIPId + '\'' +
", rootDeviceId=" + rootDeviceId + ", rootDeviceId=" + rootDeviceId +
", rootDeviceType='" + rootDeviceType + '\'' + ", rootDeviceType='" + rootDeviceType + '\'' +
", serviceOfferingId=" + serviceOfferingId + ", serviceOfferingId=" + serviceOfferingId +

View File

@ -87,6 +87,19 @@ public interface FirewallAsyncClient {
ListenableFuture<AsyncCreateResponse> createFirewallRuleForIpAndProtocol(@QueryParam("ipaddressid") String ipAddressId, ListenableFuture<AsyncCreateResponse> createFirewallRuleForIpAndProtocol(@QueryParam("ipaddressid") String ipAddressId,
@QueryParam("protocol") FirewallRule.Protocol protocol, CreateFirewallRuleOptions... options); @QueryParam("protocol") FirewallRule.Protocol protocol, CreateFirewallRuleOptions... options);
/**
* @see FirewallClient#createFirewallRuleForIpProtocolAndPort
*/
@GET
@QueryParams(keys = "command", values = "createFirewallRule")
@Unwrap
@Consumes(MediaType.APPLICATION_JSON)
ListenableFuture<AsyncCreateResponse> createFirewallRuleForIpProtocolAndPort(@QueryParam("ipaddressid") String ipAddressId,
@QueryParam("protocol") FirewallRule.Protocol protocol,
@QueryParam("startPort") int startPort,
@QueryParam("endPort") int endPort);
/** /**
* @see FirewallClient#deleteFirewallRule * @see FirewallClient#deleteFirewallRule
*/ */

View File

@ -74,6 +74,13 @@ public interface FirewallClient {
AsyncCreateResponse createFirewallRuleForIpAndProtocol(String ipAddressId, AsyncCreateResponse createFirewallRuleForIpAndProtocol(String ipAddressId,
FirewallRule.Protocol protocol, CreateFirewallRuleOptions... options); FirewallRule.Protocol protocol, CreateFirewallRuleOptions... options);
AsyncCreateResponse createFirewallRuleForIpProtocolAndPort(String ipAddressId,
FirewallRule.Protocol protocol,
int startPort,
int endPort);
/** /**
* Deletes a firewall rule * Deletes a firewall rule
* *

View File

@ -83,7 +83,6 @@ public interface NATAsyncClient {
@QueryParams(keys = { "command", "listAll" }, values = { "listIpForwardingRules", "true" }) @QueryParams(keys = { "command", "listAll" }, values = { "listIpForwardingRules", "true" })
@SelectJson("ipforwardingrule") @SelectJson("ipforwardingrule")
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<Set<IPForwardingRule>> getIPForwardingRulesForIPAddress(@QueryParam("ipaddressid") String id); ListenableFuture<Set<IPForwardingRule>> getIPForwardingRulesForIPAddress(@QueryParam("ipaddressid") String id);
/** /**
@ -93,7 +92,6 @@ public interface NATAsyncClient {
@QueryParams(keys = { "command", "listAll" }, values = { "listIpForwardingRules", "true" }) @QueryParams(keys = { "command", "listAll" }, values = { "listIpForwardingRules", "true" })
@SelectJson("ipforwardingrule") @SelectJson("ipforwardingrule")
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<Set<IPForwardingRule>> getIPForwardingRulesForVirtualMachine(@QueryParam("virtualmachineid") String id); ListenableFuture<Set<IPForwardingRule>> getIPForwardingRulesForVirtualMachine(@QueryParam("virtualmachineid") String id);
/** /**
@ -133,7 +131,6 @@ public interface NATAsyncClient {
@QueryParams(keys = "command", values = "disableStaticNat") @QueryParams(keys = "command", values = "disableStaticNat")
@SelectJson("jobid") @SelectJson("jobid")
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<String> disableStaticNATOnPublicIP(@QueryParam("ipaddressid") String IPAddressId); ListenableFuture<String> disableStaticNATOnPublicIP(@QueryParam("ipaddressid") String IPAddressId);
} }

View File

@ -31,7 +31,7 @@ import org.jclouds.concurrent.Timeout;
* Provides synchronous access to CloudStack IPForwardingRule features. * Provides synchronous access to CloudStack IPForwardingRule features.
* <p/> * <p/>
* *
* @see IPForwardingRuleAsyncClient * @see NATAsyncClient
* @see <a * @see <a
* href="http://download.cloud.com/releases/2.2.0/api_2.2.12/TOC_User.html" * href="http://download.cloud.com/releases/2.2.0/api_2.2.12/TOC_User.html"
* /> * />

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.cloudstack.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import java.util.Set;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.cloudstack.CloudStackClient;
import org.jclouds.cloudstack.domain.AsyncCreateResponse;
import org.jclouds.cloudstack.domain.FirewallRule;
import org.jclouds.cloudstack.domain.PublicIPAddress;
import org.jclouds.cloudstack.options.CreateFirewallRuleOptions;
import org.jclouds.cloudstack.strategy.BlockUntilJobCompletesAndReturnResult;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.ImmutableSet.Builder;
/**
*
* @author Adrian Cole
*/
@Singleton
public class CreateFirewallRulesForIP {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
private final CloudStackClient client;
private final BlockUntilJobCompletesAndReturnResult blockUntilJobCompletesAndReturnResult;
private final LoadingCache<String, Set<FirewallRule>> getFirewallRulesByVirtualMachine;
@Inject
public CreateFirewallRulesForIP(CloudStackClient client,
BlockUntilJobCompletesAndReturnResult blockUntilJobCompletesAndReturnResult,
LoadingCache<String, Set<FirewallRule>> getFirewallRulesByVirtualMachine) {
this.client = checkNotNull(client, "client");
this.blockUntilJobCompletesAndReturnResult = checkNotNull(blockUntilJobCompletesAndReturnResult,
"blockUntilJobCompletesAndReturnResult");
this.getFirewallRulesByVirtualMachine = checkNotNull(getFirewallRulesByVirtualMachine,
"getFirewallRulesByVirtualMachine");
}
public Set<FirewallRule> apply(PublicIPAddress ip, Iterable<Integer> ports) {
return apply(ip, "tcp", ports);
}
public Set<FirewallRule> apply(PublicIPAddress ip, String protocol, Iterable<Integer> ports) {
checkState(ip.getVirtualMachineId() != null,
"ip %s should be static NATed to a virtual machine before applying rules", ip);
if (Iterables.size(ports) == 0)
return ImmutableSet.<FirewallRule> of();
Builder<AsyncCreateResponse> responses = ImmutableSet.builder();
for (int port : ports) {
AsyncCreateResponse response = client.getFirewallClient().createFirewallRuleForIpAndProtocol(ip.getId(), FirewallRule.Protocol.fromValue(protocol),
CreateFirewallRuleOptions.Builder.startPort(port).endPort(port));
logger.debug(">> creating firewall rule IPAddress(%s) for protocol(%s), port(%s); response(%s)",
ip.getId(), protocol, port, response);
responses.add(response);
}
Builder<FirewallRule> rules = ImmutableSet.builder();
for (AsyncCreateResponse response : responses.build()) {
FirewallRule rule = blockUntilJobCompletesAndReturnResult.<FirewallRule> apply(response);
rules.add(rule);
getFirewallRulesByVirtualMachine.asMap().put(ip.getVirtualMachineId(), ImmutableSet.of(rule));
}
return rules.build();
}
}

View File

@ -0,0 +1,33 @@
package org.jclouds.cloudstack.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.cache.CacheLoader;
import com.google.common.collect.ImmutableSet;
import java.util.Set;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.cloudstack.CloudStackClient;
import org.jclouds.cloudstack.domain.FirewallRule;
import org.jclouds.cloudstack.options.ListFirewallRulesOptions;
@Singleton
public class GetFirewallRulesByVirtualMachine extends CacheLoader<String, Set<FirewallRule>> {
private final CloudStackClient client;
@Inject
public GetFirewallRulesByVirtualMachine(CloudStackClient client) {
this.client = checkNotNull(client, "client");
}
/**
* @throws org.jclouds.rest.ResourceNotFoundException
* when there is no ip forwarding rule available for the VM
*/
@Override
public Set<FirewallRule> load(String input) {
String publicIPId = client.getVirtualMachineClient().getVirtualMachine(input).getPublicIPId();
Set<FirewallRule> rules = client.getFirewallClient()
.listFirewallRules(ListFirewallRulesOptions.Builder.ipAddressId(publicIPId));
return rules != null ? rules : ImmutableSet.<FirewallRule>of();
}
}

View File

@ -0,0 +1,32 @@
package org.jclouds.cloudstack.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Set;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.cloudstack.CloudStackClient;
import org.jclouds.cloudstack.domain.IPForwardingRule;
import com.google.common.cache.CacheLoader;
@Singleton
public class GetIPForwardingRulesByVirtualMachine extends CacheLoader<String, Set<IPForwardingRule>> {
private final CloudStackClient client;
@Inject
public GetIPForwardingRulesByVirtualMachine(CloudStackClient client) {
this.client = checkNotNull(client, "client");
}
/**
* @throws org.jclouds.rest.ResourceNotFoundException
* when there is no ip forwarding rule available for the VM
*/
@Override
public Set<IPForwardingRule> load(String input) {
return client.getNATClient().getIPForwardingRulesForVirtualMachine(input);
}
}

View File

@ -71,8 +71,7 @@ public class CloudStackErrorHandler implements HttpErrorHandler {
break; break;
case 409: case 409:
case 431: case 431:
if (command.getCurrentRequest().getRequestLine().indexOf("delete") != -1 if (message.contains("does not exist")) {
&& message.indexOf("does not exist") != -1) {
exception = new ResourceNotFoundException(message, exception); exception = new ResourceNotFoundException(message, exception);
} else { } else {
exception = new IllegalStateException(message, exception); exception = new IllegalStateException(message, exception);

View File

@ -93,6 +93,37 @@ public class NetworkPredicates {
} }
} }
public static enum IsSharedNetwork implements Predicate<Network> {
INSTANCE;
@Override
public boolean apply(Network arg0) {
boolean network = isSharedNetwork.apply(checkNotNull(arg0, "network").getGuestIPType());
return network;
}
@Override
public String toString() {
return isSharedNetwork.toString();
}
}
public static enum IsIsolatedNetwork implements Predicate<Network> {
INSTANCE;
@Override
public boolean apply(Network arg0) {
boolean network = isIsolatedNetwork.apply(checkNotNull(arg0, "network").getGuestIPType());
return network;
}
@Override
public String toString() {
return isIsolatedNetwork.toString();
}
}
private static class DefaultNetworkInZone implements Predicate<Network> { private static class DefaultNetworkInZone implements Predicate<Network> {
private final String zoneId; private final String zoneId;
@ -170,6 +201,10 @@ public class NetworkPredicates {
public static Predicate<GuestIPType> isVirtualNetwork = new GuestIPTypeIs(GuestIPType.VIRTUAL); public static Predicate<GuestIPType> isVirtualNetwork = new GuestIPTypeIs(GuestIPType.VIRTUAL);
public static Predicate<GuestIPType> isIsolatedNetwork = new GuestIPTypeIs(GuestIPType.ISOLATED);
public static Predicate<GuestIPType> isSharedNetwork = new GuestIPTypeIs(GuestIPType.SHARED);
/** /**
* *
* @return true, if the network supports static NAT. * @return true, if the network supports static NAT.
@ -202,6 +237,22 @@ public class NetworkPredicates {
return IsVirtualNetwork.INSTANCE; return IsVirtualNetwork.INSTANCE;
} }
/**
*
* @return true, if the network is an isolated network.
*/
public static Predicate<Network> isIsolatedNetwork() {
return IsIsolatedNetwork.INSTANCE;
}
/**
*
* @return true, if the network is a shared network.
*/
public static Predicate<Network> isSharedNetwork() {
return IsSharedNetwork.INSTANCE;
}
/** /**
* Filters for default networks in a specific zone. * Filters for default networks in a specific zone.
* *

View File

@ -21,6 +21,9 @@ package org.jclouds.cloudstack.compute;
import static com.google.common.collect.Iterables.getFirst; import static com.google.common.collect.Iterables.getFirst;
import static com.google.inject.name.Names.bindProperties; import static com.google.inject.name.Names.bindProperties;
import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL; import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
import org.jclouds.cloudstack.domain.FirewallRule;
import org.jclouds.cloudstack.functions.GetFirewallRulesByVirtualMachine;
import org.jclouds.cloudstack.functions.GetIPForwardingRulesByVirtualMachine;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertFalse;
@ -33,7 +36,6 @@ import javax.inject.Singleton;
import org.jclouds.cloudstack.CloudStackClient; import org.jclouds.cloudstack.CloudStackClient;
import org.jclouds.cloudstack.compute.config.CloudStackComputeServiceContextModule; import org.jclouds.cloudstack.compute.config.CloudStackComputeServiceContextModule;
import org.jclouds.cloudstack.compute.config.CloudStackComputeServiceContextModule.GetIPForwardingRulesByVirtualMachine;
import org.jclouds.cloudstack.compute.options.CloudStackTemplateOptions; import org.jclouds.cloudstack.compute.options.CloudStackTemplateOptions;
import org.jclouds.cloudstack.compute.strategy.CloudStackComputeServiceAdapter; import org.jclouds.cloudstack.compute.strategy.CloudStackComputeServiceAdapter;
import org.jclouds.cloudstack.compute.strategy.OptionsConverter; import org.jclouds.cloudstack.compute.strategy.OptionsConverter;
@ -113,6 +115,10 @@ public class CloudStackComputeServiceAdapterLiveTest extends BaseCloudStackClien
bind(new TypeLiteral<Map<NetworkType, ? extends OptionsConverter>>() {}). bind(new TypeLiteral<Map<NetworkType, ? extends OptionsConverter>>() {}).
toInstance(new CloudStackComputeServiceContextModule().optionsConverters()); toInstance(new CloudStackComputeServiceContextModule().optionsConverters());
bind(String.class).annotatedWith(Names.named(PROPERTY_SESSION_INTERVAL)).toInstance("60"); bind(String.class).annotatedWith(Names.named(PROPERTY_SESSION_INTERVAL)).toInstance("60");
bind(new TypeLiteral<CacheLoader<String, Set<IPForwardingRule>>>() {
}).to(GetIPForwardingRulesByVirtualMachine.class);
bind(new TypeLiteral<CacheLoader<String, Set<FirewallRule>>>() {
}).to(GetFirewallRulesByVirtualMachine.class);
bind(new TypeLiteral<CacheLoader<String, Zone>>() {}). bind(new TypeLiteral<CacheLoader<String, Zone>>() {}).
to(ZoneIdToZone.class); to(ZoneIdToZone.class);
bind(new TypeLiteral<Supplier<LoadingCache<String, Zone>>>() {}). bind(new TypeLiteral<Supplier<LoadingCache<String, Zone>>>() {}).
@ -127,12 +133,19 @@ public class CloudStackComputeServiceAdapterLiveTest extends BaseCloudStackClien
return new RetryablePredicate<String>(jobComplete, 1200, 1, 5, TimeUnit.SECONDS); return new RetryablePredicate<String>(jobComplete, 1200, 1, 5, TimeUnit.SECONDS);
} }
@SuppressWarnings("unused")
@Provides @Provides
@Singleton @Singleton
protected LoadingCache<String, Set<IPForwardingRule>> getIPForwardingRuleByVirtualMachine( protected LoadingCache<String, Set<IPForwardingRule>> getIPForwardingRulesByVirtualMachine(
GetIPForwardingRulesByVirtualMachine getIPForwardingRule) { GetIPForwardingRulesByVirtualMachine getIPForwardingRules) {
return CacheBuilder.newBuilder().build(getIPForwardingRule); return CacheBuilder.newBuilder().build(getIPForwardingRules);
}
@Provides
@Singleton
protected LoadingCache<String, Set<FirewallRule>> getFirewallRulesByVirtualMachine(
GetFirewallRulesByVirtualMachine getFirewallRules) {
return CacheBuilder.newBuilder().build(getFirewallRules);
} }
}; };
adapter = Guice.createInjector(module, new SLF4JLoggingModule()).getInstance( adapter = Guice.createInjector(module, new SLF4JLoggingModule()).getInstance(

View File

@ -27,6 +27,7 @@ import org.jclouds.cloudstack.domain.Template;
import org.jclouds.cloudstack.parse.ListTemplatesResponseTest; import org.jclouds.cloudstack.parse.ListTemplatesResponseTest;
import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.ImageBuilder; import org.jclouds.compute.domain.ImageBuilder;
import org.jclouds.compute.domain.Image.Status;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -51,20 +52,21 @@ public class TemplateToImageTest {
// location free image // location free image
static Image one = new ImageBuilder().id("2").providerId("2").name("CentOS 5.3(64-bit) no GUI (XenServer)") static Image one = new ImageBuilder().id("2").providerId("2").name("CentOS 5.3(64-bit) no GUI (XenServer)")
.operatingSystem(TemplateToOperatingSystemTest.one).description("CentOS 5.3(64-bit) no GUI (XenServer)") .operatingSystem(TemplateToOperatingSystemTest.one).description("CentOS 5.3(64-bit) no GUI (XenServer)")
.build(); .status(Status.AVAILABLE).build();
// location free image // location free image
static Image two = new ImageBuilder().id("4").providerId("4").name("CentOS 5.5(64-bit) no GUI (KVM)") static Image two = new ImageBuilder().id("4").providerId("4").name("CentOS 5.5(64-bit) no GUI (KVM)")
.operatingSystem(TemplateToOperatingSystemTest.two).description("CentOS 5.5(64-bit) no GUI (KVM)").build(); .operatingSystem(TemplateToOperatingSystemTest.two).description("CentOS 5.5(64-bit) no GUI (KVM)")
.status(Status.AVAILABLE).build();
static Image three = new ImageBuilder().id("203").providerId("203").name("Windows 7 KVM") static Image three = new ImageBuilder().id("203").providerId("203").name("Windows 7 KVM")
.operatingSystem(TemplateToOperatingSystemTest.three).description("Windows 7 KVM") .operatingSystem(TemplateToOperatingSystemTest.three).description("Windows 7 KVM")
.location(ZoneToLocationTest.two).build(); .location(ZoneToLocationTest.two).status(Status.AVAILABLE).build();
// location free image // location free image
static Image four = new ImageBuilder().id("7").providerId("7").name("CentOS 5.3(64-bit) no GUI (vSphere)") static Image four = new ImageBuilder().id("7").providerId("7").name("CentOS 5.3(64-bit) no GUI (vSphere)")
.operatingSystem(TemplateToOperatingSystemTest.four).description("CentOS 5.3(64-bit) no GUI (vSphere)") .operatingSystem(TemplateToOperatingSystemTest.four).description("CentOS 5.3(64-bit) no GUI (vSphere)")
.build(); .status(Status.AVAILABLE).build();
static Image five = new ImageBuilder().id("241").providerId("241").name("kvmdev4") static Image five = new ImageBuilder().id("241").providerId("241").name("kvmdev4")
.operatingSystem(TemplateToOperatingSystemTest.five).description("v5.6.28_Dev4") .operatingSystem(TemplateToOperatingSystemTest.five).description("v5.6.28_Dev4")
.location(ZoneToLocationTest.two).build(); .location(ZoneToLocationTest.two).status(Status.AVAILABLE).build();
@Test @Test
public void test() { public void test() {

View File

@ -36,7 +36,7 @@ import org.jclouds.compute.domain.HardwareBuilder;
import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadataBuilder; import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.domain.NodeState; import org.jclouds.compute.domain.NodeMetadata.Status;
import org.jclouds.compute.functions.GroupNamingConvention; import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.date.internal.SimpleDateFormatDateService; import org.jclouds.date.internal.SimpleDateFormatDateService;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
@ -87,7 +87,7 @@ public class VirtualMachineToNodeMetadataTest {
assertEquals( assertEquals(
node.toString(), node.toString(),
new NodeMetadataBuilder().id("54").providerId("54").name("i-3-54-VM").group("i-3-54") new NodeMetadataBuilder().id("54").providerId("54").name("i-3-54-VM").group("i-3-54")
.location(ZoneToLocationTest.one).state(NodeState.PENDING).hostname("i-3-54-VM") .location(ZoneToLocationTest.one).status(Status.PENDING).hostname("i-3-54-VM")
.privateAddresses(ImmutableSet.of("10.1.1.18")).publicAddresses(ImmutableSet.of("1.1.1.1")) .privateAddresses(ImmutableSet.of("10.1.1.18")).publicAddresses(ImmutableSet.of("1.1.1.1"))
.hardware(addHypervisor(ServiceOfferingToHardwareTest.one, "XenServer")) .hardware(addHypervisor(ServiceOfferingToHardwareTest.one, "XenServer"))
.imageId(TemplateToImageTest.one.getId()) .imageId(TemplateToImageTest.one.getId())
@ -150,7 +150,7 @@ public class VirtualMachineToNodeMetadataTest {
assertEquals( assertEquals(
node.toString(), node.toString(),
new NodeMetadataBuilder().id("54").providerId("54").name("i-3-54-VM").group("i-3-54") new NodeMetadataBuilder().id("54").providerId("54").name("i-3-54-VM").group("i-3-54")
.location(ZoneToLocationTest.one).state(NodeState.PENDING).hostname("i-3-54-VM") .location(ZoneToLocationTest.one).status(Status.PENDING).hostname("i-3-54-VM")
.privateAddresses(ImmutableSet.<String>of()) .privateAddresses(ImmutableSet.<String>of())
.publicAddresses(ImmutableSet.<String>of("1.1.1.5")) .publicAddresses(ImmutableSet.<String>of("1.1.1.5"))
.hardware(addHypervisor(ServiceOfferingToHardwareTest.one, "XenServer")) .hardware(addHypervisor(ServiceOfferingToHardwareTest.one, "XenServer"))
@ -186,7 +186,7 @@ public class VirtualMachineToNodeMetadataTest {
assertEquals( assertEquals(
node.toString(), node.toString(),
new NodeMetadataBuilder().id("54").providerId("54").name("i-3-54-VM").group("i-3-54") new NodeMetadataBuilder().id("54").providerId("54").name("i-3-54-VM").group("i-3-54")
.location(ZoneToLocationTest.one).state(NodeState.PENDING).hostname("i-3-54-VM") .location(ZoneToLocationTest.one).status(Status.PENDING).hostname("i-3-54-VM")
.privateAddresses(ImmutableSet.of("10.1.1.18")) .privateAddresses(ImmutableSet.of("10.1.1.18"))
.hardware(addHypervisor(ServiceOfferingToHardwareTest.one, "XenServer")) .hardware(addHypervisor(ServiceOfferingToHardwareTest.one, "XenServer"))
.imageId(TemplateToImageTest.one.getId()) .imageId(TemplateToImageTest.one.getId())

View File

@ -32,6 +32,7 @@ import org.testng.annotations.Test;
@Test(groups = "live", singleThreaded = true, testName = "AccountClientLiveTest") @Test(groups = "live", singleThreaded = true, testName = "AccountClientLiveTest")
public class AccountClientLiveTest extends BaseCloudStackClientLiveTest { public class AccountClientLiveTest extends BaseCloudStackClientLiveTest {
@Test
public void testListAccounts() throws Exception { public void testListAccounts() throws Exception {
for (Account securityAccount : client.getAccountClient().listAccounts()) for (Account securityAccount : client.getAccountClient().listAccounts())
checkAccount(securityAccount); checkAccount(securityAccount);
@ -49,14 +50,12 @@ public class AccountClientLiveTest extends BaseCloudStackClientLiveTest {
assert user.getName() != null : user; assert user.getName() != null : user;
assert user.getAccountType().equals(account.getType()) : user; assert user.getAccountType().equals(account.getType()) : user;
assert user.getDomain().equals(account.getDomain()) : user; assert user.getDomain().equals(account.getDomain()) : user;
assert user.getDomainId() == account.getDomainId() : user; assert user.getDomainId().equals(account.getDomainId()) : user;
assert user.getApiKey() != null : user;
assert user.getCreated() != null : user; assert user.getCreated() != null : user;
assert user.getEmail() != null : user; assert user.getEmail() != null : user;
assert user.getLastName() != null : user; assert user.getLastName() != null : user;
assert user.getFirstName() != null : user; assert user.getFirstName() != null : user;
assert user.getId() != null : user; assert user.getId() != null : user;
assert user.getSecretKey() != null : user;
assert user.getState() != null : user; assert user.getState() != null : user;
} }
assert account.getIPsAvailable() == null || account.getIPsAvailable() >= 0 : account; assert account.getIPsAvailable() == null || account.getIPsAvailable() >= 0 : account;

View File

@ -57,6 +57,7 @@ import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.rest.RestContext; import org.jclouds.rest.RestContext;
import org.jclouds.ssh.SshClient; import org.jclouds.ssh.SshClient;
import org.jclouds.sshj.config.SshjSshClientModule; import org.jclouds.sshj.config.SshjSshClientModule;
import org.testng.SkipException;
import org.testng.annotations.AfterGroups; import org.testng.annotations.AfterGroups;
import org.testng.annotations.BeforeGroups; import org.testng.annotations.BeforeGroups;
@ -270,6 +271,18 @@ public class BaseCloudStackClientLiveTest extends BaseGenericComputeServiceConte
return currentUser; return currentUser;
} }
protected void skipIfNotDomainAdmin() {
if (!domainAdminEnabled) {
throw new SkipException("Test cannot run without domain admin identity and credentials");
}
}
protected void skipIfNotGlobalAdmin() {
if (!globalAdminEnabled) {
throw new SkipException("Test cannot run without global admin identity and credentials");
}
}
@AfterGroups(groups = "live") @AfterGroups(groups = "live")
protected void tearDown() { protected void tearDown() {
if (cloudStackContext != null) if (cloudStackContext != null)

View File

@ -38,7 +38,7 @@ public class DomainAccountClientLiveTest extends BaseCloudStackClientLiveTest {
@Test @Test
public void testEnableDisableAccount() { public void testEnableDisableAccount() {
assert globalAdminEnabled; skipIfNotGlobalAdmin();
Account testAccount = null; Account testAccount = null;
try { try {

View File

@ -18,9 +18,16 @@
*/ */
package org.jclouds.cloudstack.features; package org.jclouds.cloudstack.features;
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
import static com.google.common.collect.Iterables.find; import static com.google.common.collect.Iterables.find;
import com.google.common.collect.Sets;
import static com.google.common.collect.Sets.newHashSet;
import java.util.NoSuchElementException;
import static org.jclouds.cloudstack.options.ListDomainChildrenOptions.Builder.name;
import static org.jclouds.cloudstack.options.ListDomainChildrenOptions.Builder.parentDomainId; import static org.jclouds.cloudstack.options.ListDomainChildrenOptions.Builder.parentDomainId;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull; import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue; import static org.testng.Assert.assertTrue;
@ -43,55 +50,56 @@ public class DomainDomainClientLiveTest extends BaseCloudStackClientLiveTest {
@Test @Test
public void testListDomains() { public void testListDomains() {
assert domainAdminEnabled; skipIfNotDomainAdmin();
Set<Domain> allDomains = domainAdminClient.getDomainClient().listDomains(); Set<Domain> domains = domainAdminClient.getDomainClient().listDomains();
for (Domain candidate : domains) {
Domain root = find(allDomains, withName("ROOT")); checkDomain(candidate);
assertEquals(root, domainAdminClient.getDomainClient().getDomainById(root.getId())); }
assertEquals(root.getLevel(), 0);
assertEquals(root.getParentDomainId(), 0);
assertNull(root.getParentDomainName());
if (allDomains.size() > 1) {
assertTrue(root.hasChild());
} }
for (Domain domain : allDomains) { private void checkDomain(Domain domain) {
checkDomain(domain, allDomains); assertNotNull(domain.getId());
if (domain.getLevel() == 0 /* global ROOT */) {
assertNull(domain.getParentDomainName());
assertNull(domain.getParentDomainId());
} else {
assertNotNull(domain.getParentDomainName());
assertNotNull(domain.getParentDomainId());
} }
} }
@Test @Test
public void testListDomainChildren() { public void testListDomainChildren() {
assert domainAdminEnabled; skipIfNotDomainAdmin();
Set<Domain> allDomains = domainAdminClient.getDomainClient().listDomains(); Set<Domain> domains = domainAdminClient.getDomainClient().listDomains();
Domain root = find(allDomains, withName("ROOT")); Domain root = findRootOfVisibleTree(domains);
if (domains.size() > 1) {
assertTrue(root.hasChild());
}
Set<Domain> children = domainAdminClient.getDomainClient() Set<Domain> children = domainAdminClient.getDomainClient()
.listDomainChildren(parentDomainId(root.getId()).isRecursive(true)); .listDomainChildren(parentDomainId(root.getId()).isRecursive(true));
assertEquals(allDomains.size() - 1, children.size()); assertEquals(domains.size() - 1, children.size());
assertTrue(Sets.difference(domains, children).contains(root));
for (Domain domain : children) {
checkDomain(domain, allDomains);
}
} }
private Predicate<Domain> withName(final String name) { private Domain findRootOfVisibleTree(Set<Domain> domains) {
return new Predicate<Domain>() { final Set<String> names = newHashSet(Iterables.transform(domains,
new Function<Domain, String>() {
@Override @Override
public boolean apply(@Nullable Domain domain) { public String apply(Domain domain) {
return domain != null && domain.getName().equals(name); return domain.getName();
}
};
} }
}));
private void checkDomain(Domain domain, Set<Domain> allDomains) { for (Domain candidate : domains) {
assert domain.getId() != null : domain; if (candidate.getParentDomainId() == null ||
if (domain.getParentDomainName() != null) { !names.contains(candidate.getParentDomainName())) {
Domain parent = find(allDomains, withName(domain.getParentDomainName())); return candidate;
assertEquals(parent.getId(), domain.getParentDomainId());
assertTrue(parent.hasChild());
} }
} }
throw new NoSuchElementException("No root node found in this tree");
}
} }

View File

@ -40,7 +40,7 @@ public class DomainUserClientLiveTest extends BaseCloudStackClientLiveTest {
@Test @Test
public void testListUsers() { public void testListUsers() {
assert domainAdminEnabled; skipIfNotDomainAdmin();
Set<User> users = domainAdminClient.getUserClient().listUsers(); Set<User> users = domainAdminClient.getUserClient().listUsers();
@ -60,7 +60,7 @@ public class DomainUserClientLiveTest extends BaseCloudStackClientLiveTest {
@Test @Test
public void testEnableDisableUser() { public void testEnableDisableUser() {
assert globalAdminEnabled && domainAdminEnabled; skipIfNotGlobalAdmin();
Account testAccount = null; Account testAccount = null;
User testUser = null; User testUser = null;

View File

@ -42,7 +42,7 @@ public class GlobalAccountClientLiveTest extends BaseCloudStackClientLiveTest {
@Test @Test
public void testCreateAndRemoveAccount() { public void testCreateAndRemoveAccount() {
assert globalAdminEnabled; skipIfNotGlobalAdmin();
Account account = null; Account account = null;
try { try {

View File

@ -38,7 +38,7 @@ public class GlobalAlertClientLiveTest extends BaseCloudStackClientLiveTest {
@Test(groups = "live", enabled = true) @Test(groups = "live", enabled = true)
public void testListAlerts() throws Exception { public void testListAlerts() throws Exception {
assertTrue(globalAdminEnabled, "Test cannot run without global admin identity and credentials"); skipIfNotGlobalAdmin();
final Set<Alert> response = globalAdminClient.getAlertClient().listAlerts(ListAlertsOptions.Builder.id("20")); final Set<Alert> response = globalAdminClient.getAlertClient().listAlerts(ListAlertsOptions.Builder.id("20"));
assert null != response; assert null != response;

View File

@ -36,7 +36,7 @@ public class GlobalCapacityClientLiveTest extends BaseCloudStackClientLiveTest {
@Test(groups = "live", enabled = true) @Test(groups = "live", enabled = true)
public void testListCapacity() throws Exception { public void testListCapacity() throws Exception {
assertTrue(globalAdminEnabled, "Test cannot run without global admin identity and credentials"); skipIfNotGlobalAdmin();
final Set<Capacity> response = globalAdminClient.getCapacityClient().listCapacity(); final Set<Capacity> response = globalAdminClient.getCapacityClient().listCapacity();
assert null != response; assert null != response;

View File

@ -45,7 +45,7 @@ public class GlobalConfigurationClientLiveTest extends BaseCloudStackClientLiveT
@Test @Test
public void testListConfigurationEntries() { public void testListConfigurationEntries() {
assert globalAdminEnabled; skipIfNotGlobalAdmin();
Set<ConfigurationEntry> entries = globalAdminClient Set<ConfigurationEntry> entries = globalAdminClient
.getConfigurationClient().listConfigurationEntries(); .getConfigurationClient().listConfigurationEntries();
@ -62,7 +62,7 @@ public class GlobalConfigurationClientLiveTest extends BaseCloudStackClientLiveT
@Test @Test
public void testUpdateConfigurationEntry() { public void testUpdateConfigurationEntry() {
assert globalAdminEnabled; skipIfNotGlobalAdmin();
Set<ConfigurationEntry> entries = globalAdminClient Set<ConfigurationEntry> entries = globalAdminClient
.getConfigurationClient().listConfigurationEntries(); .getConfigurationClient().listConfigurationEntries();

View File

@ -55,7 +55,7 @@ public class GlobalDomainClientLiveTest extends BaseCloudStackClientLiveTest {
@Test @Test
public void testCreateUpdateDeleteDomain() { public void testCreateUpdateDeleteDomain() {
assert globalAdminEnabled; skipIfNotDomainAdmin();
Domain domain = null; Domain domain = null;
try { try {

View File

@ -40,7 +40,7 @@ public class GlobalHostClientLiveTest extends BaseCloudStackClientLiveTest {
@Test(groups = "live", enabled = true) @Test(groups = "live", enabled = true)
public void testListHosts() throws Exception { public void testListHosts() throws Exception {
assertTrue(globalAdminEnabled, "Test cannot run without global admin identity and credentials"); skipIfNotGlobalAdmin();
Set<Host> hosts = globalAdminClient.getHostClient().listHosts(); Set<Host> hosts = globalAdminClient.getHostClient().listHosts();
assert hosts.size() > 0 : hosts; assert hosts.size() > 0 : hosts;
@ -68,7 +68,7 @@ public class GlobalHostClientLiveTest extends BaseCloudStackClientLiveTest {
@Test(groups = "live", enabled = true) @Test(groups = "live", enabled = true)
public void testListClusters() throws Exception { public void testListClusters() throws Exception {
assertTrue(globalAdminEnabled, "Test cannot run without global admin identity and credentials"); skipIfNotGlobalAdmin();
Set<Cluster> clusters = globalAdminClient.getHostClient().listClusters(); Set<Cluster> clusters = globalAdminClient.getHostClient().listClusters();
assert clusters.size() > 0 : clusters; assert clusters.size() > 0 : clusters;

View File

@ -50,7 +50,7 @@ public class GlobalOfferingClientLiveTest extends BaseCloudStackClientLiveTest {
@Test(groups = "live", enabled = true) @Test(groups = "live", enabled = true)
public void testCreateServiceOffering() throws Exception { public void testCreateServiceOffering() throws Exception {
assertTrue(globalAdminEnabled, "Test cannot run without global admin identity and credentials"); skipIfNotGlobalAdmin();
String name = prefix + "-test-create-service-offering"; String name = prefix + "-test-create-service-offering";
String displayText = name + "-display"; String displayText = name + "-display";
@ -90,7 +90,7 @@ public class GlobalOfferingClientLiveTest extends BaseCloudStackClientLiveTest {
@Test(groups = "live", enabled = true) @Test(groups = "live", enabled = true)
public void testCreateDiskOffering() throws Exception { public void testCreateDiskOffering() throws Exception {
assertTrue(globalAdminEnabled, "Test cannot run without global admin identity and credentials"); skipIfNotGlobalAdmin();
String name = prefix + "-test-create-disk-offering"; String name = prefix + "-test-create-disk-offering";
String displayText = name + "-display"; String displayText = name + "-display";
@ -127,7 +127,7 @@ public class GlobalOfferingClientLiveTest extends BaseCloudStackClientLiveTest {
@Test(groups = "live", enabled = true) @Test(groups = "live", enabled = true)
public void testUpdateNetworkOffering() throws Exception { public void testUpdateNetworkOffering() throws Exception {
assertTrue(globalAdminEnabled, "Test cannot run without global admin identity and credentials"); skipIfNotGlobalAdmin();
NetworkOffering offering = getFirst(globalAdminClient.getOfferingClient().listNetworkOfferings(), null); NetworkOffering offering = getFirst(globalAdminClient.getOfferingClient().listNetworkOfferings(), null);
assertNotNull(offering, "Unable to test, no network offering found."); assertNotNull(offering, "Unable to test, no network offering found.");

View File

@ -51,10 +51,13 @@ public class GlobalPodClientLiveTest extends BaseCloudStackClientLiveTest {
private Pod pod; private Pod pod;
public void testListPods() throws Exception { public void testListPods() throws Exception {
skipIfNotGlobalAdmin();
Set<Pod> response = globalAdminClient.getPodClient().listPods(); Set<Pod> response = globalAdminClient.getPodClient().listPods();
assert null != response; assert null != response;
long podCount = response.size(); long podCount = response.size();
assertTrue(podCount >= 0); assertTrue(podCount >= 0);
for (Pod pod : response) { for (Pod pod : response) {
Pod newDetails = Iterables.getOnlyElement(globalAdminClient.getPodClient().listPods( Pod newDetails = Iterables.getOnlyElement(globalAdminClient.getPodClient().listPods(
ListPodsOptions.Builder.id(pod.getId()))); ListPodsOptions.Builder.id(pod.getId())));
@ -74,7 +77,7 @@ public class GlobalPodClientLiveTest extends BaseCloudStackClientLiveTest {
@Test @Test
public void testCreatePod() { public void testCreatePod() {
assertTrue(globalAdminEnabled, "Global admin credentials must be given"); skipIfNotGlobalAdmin();
zone = globalAdminClient.getZoneClient().createZone(prefix + "-zone", NetworkType.BASIC, "8.8.8.8", "10.10.10.10"); zone = globalAdminClient.getZoneClient().createZone(prefix + "-zone", NetworkType.BASIC, "8.8.8.8", "10.10.10.10");
pod = globalAdminClient.getPodClient().createPod(prefix + "-pod", zone.getId(), "172.20.0.1", "172.20.0.250", "172.20.0.254", "255.255.255.0", pod = globalAdminClient.getPodClient().createPod(prefix + "-pod", zone.getId(), "172.20.0.1", "172.20.0.250", "172.20.0.254", "255.255.255.0",

View File

@ -39,7 +39,7 @@ public class GlobalStoragePoolClientLiveTest extends BaseCloudStackClientLiveTes
@Test(groups = "live", enabled = true) @Test(groups = "live", enabled = true)
public void testListStoragePools() throws Exception { public void testListStoragePools() throws Exception {
assertTrue(globalAdminEnabled, "Test cannot run without global admin identity and credentials"); skipIfNotGlobalAdmin();
Set<StoragePool> result = globalAdminClient.getStoragePoolClient().listStoragePools(); Set<StoragePool> result = globalAdminClient.getStoragePoolClient().listStoragePools();
assertNotNull(result); assertNotNull(result);

View File

@ -42,6 +42,8 @@ public class GlobalUsageClientLiveTest extends BaseCloudStackClientLiveTest {
@Test(groups = "live", enabled = true) @Test(groups = "live", enabled = true)
public void testListUsage() { public void testListUsage() {
skipIfNotGlobalAdmin();
Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT")); Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
Date end = c.getTime(); Date end = c.getTime();
c.add(Calendar.MONTH, -1); c.add(Calendar.MONTH, -1);

View File

@ -50,7 +50,7 @@ public class GlobalUserClientLiveTest extends BaseCloudStackClientLiveTest {
@Test @Test
public void testCreateUser() { public void testCreateUser() {
assert globalAdminEnabled; skipIfNotGlobalAdmin();
Account testAccount = createTestAccount(globalAdminClient, prefix); Account testAccount = createTestAccount(globalAdminClient, prefix);
User testUser = null; User testUser = null;

View File

@ -18,7 +18,7 @@
*/ */
package org.jclouds.cloudstack.features; package org.jclouds.cloudstack.features;
import static junit.framework.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import java.net.URI; import java.net.URI;

View File

@ -56,11 +56,15 @@ public class GlobalVlanClientLiveTest extends BaseCloudStackClientLiveTest {
private VlanIPRange range; private VlanIPRange range;
@Test
public void testListVlanIPRanges() throws Exception { public void testListVlanIPRanges() throws Exception {
skipIfNotGlobalAdmin();
Set<VlanIPRange> response = globalAdminClient.getVlanClient().listVlanIPRanges(); Set<VlanIPRange> response = globalAdminClient.getVlanClient().listVlanIPRanges();
assert null != response; assert null != response;
long rangeCount = response.size(); long rangeCount = response.size();
assertTrue(rangeCount >= 0); assertTrue(rangeCount >= 0);
for (VlanIPRange range : response) { for (VlanIPRange range : response) {
VlanIPRange newDetails = Iterables.getOnlyElement(globalAdminClient.getVlanClient().listVlanIPRanges( VlanIPRange newDetails = Iterables.getOnlyElement(globalAdminClient.getVlanClient().listVlanIPRanges(
ListVlanIPRangesOptions.Builder.id(range.getId()))); ListVlanIPRangesOptions.Builder.id(range.getId())));
@ -80,7 +84,10 @@ public class GlobalVlanClientLiveTest extends BaseCloudStackClientLiveTest {
} }
} }
@Test
public void testCreateVlanIPRange() { public void testCreateVlanIPRange() {
skipIfNotGlobalAdmin();
final Zone zone = Iterables.find(client.getZoneClient().listZones(), ZonePredicates.supportsAdvancedNetworks()); final Zone zone = Iterables.find(client.getZoneClient().listZones(), ZonePredicates.supportsAdvancedNetworks());
final NetworkOffering offering = find(client.getOfferingClient().listNetworkOfferings(), final NetworkOffering offering = find(client.getOfferingClient().listNetworkOfferings(),
NetworkOfferingPredicates.supportsGuestVirtualNetworks()); NetworkOfferingPredicates.supportsGuestVirtualNetworks());
@ -90,7 +97,7 @@ public class GlobalVlanClientLiveTest extends BaseCloudStackClientLiveTest {
new Predicate<Network>() { new Predicate<Network>() {
@Override @Override
public boolean apply(Network network) { public boolean apply(Network network) {
return network.getNetworkOfferingId() == offering.getId(); return network.getNetworkOfferingId().equals(offering.getId());
} }
}); });

View File

@ -38,7 +38,7 @@ public class GlobalZoneClientLiveTest extends BaseCloudStackClientLiveTest {
@Test @Test
public void testCreateUpdateDeleteZone() { public void testCreateUpdateDeleteZone() {
assert globalAdminEnabled; skipIfNotGlobalAdmin();
Zone zone = null; Zone zone = null;
String zoneName = prefix + "-zone"; String zoneName = prefix + "-zone";

View File

@ -164,7 +164,7 @@ public class NATAsyncClientTest extends BaseCloudStackAsyncClientTest<NATAsyncCl
assertResponseParserClassEquals(method, httpRequest, ParseFirstJsonValueNamed.class); assertResponseParserClassEquals(method, httpRequest, ParseFirstJsonValueNamed.class);
assertSaxResponseParserClassEquals(method, null); assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class); assertExceptionParserClassEquals(method, MapHttp4xxCodesToExceptions.class);
checkFilters(httpRequest); checkFilters(httpRequest);

View File

@ -65,6 +65,7 @@ public class NetworkClientLiveTest extends BaseCloudStackClientLiveTest {
} }
} }
@Test
public void testCreateGuestVirtualNetwork() { public void testCreateGuestVirtualNetwork() {
if (!networksSupported) if (!networksSupported)
return; return;
@ -94,13 +95,12 @@ public class NetworkClientLiveTest extends BaseCloudStackClientLiveTest {
} }
} }
@Test
public void testCreateVLANNetwork() { public void testCreateVLANNetwork() {
skipIfNotDomainAdmin();
if (!networksSupported) if (!networksSupported)
return; return;
if (!domainAdminEnabled) {
Logger.getAnonymousLogger().log(Level.SEVERE, "domainAdmin credentials not present, skipping test");
return;
}
final NetworkOffering offering; final NetworkOffering offering;
try { try {
offering = get( offering = get(
@ -130,6 +130,7 @@ public class NetworkClientLiveTest extends BaseCloudStackClientLiveTest {
} }
} }
@Test
public void testListNetworks() throws Exception { public void testListNetworks() throws Exception {
if (!networksSupported) if (!networksSupported)
return; return;

View File

@ -44,11 +44,12 @@ public class SessionClientLiveTest extends BaseCloudStackClientLiveTest {
@Test @Test
public void testCreateContextUsingUserAndPasswordAuthentication() { public void testCreateContextUsingUserAndPasswordAuthentication() {
String endpoint = cloudStackContext.getProviderMetadata().getEndpoint(); skipIfNotGlobalAdmin();
assert globalAdminEnabled;
String endpoint = cloudStackContext.getProviderMetadata().getEndpoint();
Account testAccount = null; Account testAccount = null;
User testUser = null; User testUser = null;
String prefix = this.prefix + "-session"; String prefix = this.prefix + "-session";
try { try {
testAccount = createTestAccount(globalAdminClient, prefix); testAccount = createTestAccount(globalAdminClient, prefix);

View File

@ -147,7 +147,7 @@ public class SnapshotClientLiveTest extends BaseCloudStackClientLiveTest {
return find(client.getSnapshotClient().listSnapshots(), new Predicate<Snapshot>() { return find(client.getSnapshotClient().listSnapshots(), new Predicate<Snapshot>() {
@Override @Override
public boolean apply(Snapshot arg0) { public boolean apply(Snapshot arg0) {
return arg0.getId() == id; return arg0.getId().equals(id);
} }
}); });
} }

View File

@ -90,7 +90,7 @@ public class TemplateClientLiveTest extends BaseCloudStackClientLiveTest {
assert template.getZone() != null : template; assert template.getZone() != null : template;
assert template.getZoneId() != null : template; assert template.getZoneId() != null : template;
assert (template.getStatus() == null || assert (template.getStatus() == null ||
template.getStatus().equals("Download Complete")) : template; template.getStatus() == Template.Status.DOWNLOADED) : template;
assert template.getType() != null && template.getType() != Template.Type.UNRECOGNIZED : template; assert template.getType() != null && template.getType() != Template.Type.UNRECOGNIZED : template;
assert template.getHypervisor() != null : template; assert template.getHypervisor() != null : template;
assert template.getDomain() != null : template; assert template.getDomain() != null : template;
@ -110,8 +110,8 @@ public class TemplateClientLiveTest extends BaseCloudStackClientLiveTest {
return network != null && network.getState().equals("Implemented"); return network != null && network.getState().equals("Implemented");
} }
}); });
assertEquals(Iterables.size(networks), 1); assertTrue(Iterables.size(networks) >= 1);
Network network = Iterables.getOnlyElement(networks, null); Network network = Iterables.get(networks, 0);
assertNotNull(network); assertNotNull(network);
// Create a VM and stop it // Create a VM and stop it
@ -160,7 +160,7 @@ public class TemplateClientLiveTest extends BaseCloudStackClientLiveTest {
networks = Iterables.filter(networks, new Predicate<Network>() { networks = Iterables.filter(networks, new Predicate<Network>() {
@Override @Override
public boolean apply(@Nullable Network network) { public boolean apply(@Nullable Network network) {
return network != null && network.getState().equals("Implemented"); return network != null && network.getName().equals("Virtual Network");
} }
}); });
assertEquals(Iterables.size(networks), 1); assertEquals(Iterables.size(networks), 1);
@ -184,7 +184,7 @@ public class TemplateClientLiveTest extends BaseCloudStackClientLiveTest {
if (template == null) return false; if (template == null) return false;
Template t2 = client.getTemplateClient().getTemplateInZone(template.getId(), zoneId); Template t2 = client.getTemplateClient().getTemplateInZone(template.getId(), zoneId);
Logger.CONSOLE.info("%s", t2.getStatus()); Logger.CONSOLE.info("%s", t2.getStatus());
return "Download Complete".equals(t2.getStatus()); return t2.getStatus() == Template.Status.DOWNLOADED;
} }
}; };
assertTrue(new RetryablePredicate<Template>(templateReadyPredicate, 60000).apply(registeredTemplate)); assertTrue(new RetryablePredicate<Template>(templateReadyPredicate, 60000).apply(registeredTemplate));

View File

@ -91,7 +91,12 @@ public class VirtualMachineClientLiveTest extends BaseCloudStackClientLiveTest {
RetryablePredicate<String> jobComplete, RetryablePredicate<VirtualMachine> virtualMachineRunning) { RetryablePredicate<String> jobComplete, RetryablePredicate<VirtualMachine> virtualMachineRunning) {
Set<Network> networks = client.getNetworkClient().listNetworks(isDefault(true)); Set<Network> networks = client.getNetworkClient().listNetworks(isDefault(true));
if (networks.size() > 0) { if (networks.size() > 0) {
Network network = get(networks, 0); Network network = get(filter(networks, new Predicate<Network>() {
@Override
public boolean apply(@Nullable Network network) {
return network != null && network.getState().equals("Implemented");
}
}), 0);
return createVirtualMachineInNetwork(network, return createVirtualMachineInNetwork(network,
defaultTemplateOrPreferredInZone(defaultTemplate, client, network.getZoneId()), client, jobComplete, defaultTemplateOrPreferredInZone(defaultTemplate, client, network.getZoneId()), client, jobComplete,
virtualMachineRunning); virtualMachineRunning);
@ -174,6 +179,7 @@ public class VirtualMachineClientLiveTest extends BaseCloudStackClientLiveTest {
return vm; return vm;
} }
@Test
public void testCreateVirtualMachine() throws Exception { public void testCreateVirtualMachine() throws Exception {
String templateId = (imageId != null && !"".equals(imageId)) ? imageId : null; String templateId = (imageId != null && !"".equals(imageId)) ? imageId : null;
vm = createVirtualMachine(client, templateId, jobComplete, virtualMachineRunning); vm = createVirtualMachine(client, templateId, jobComplete, virtualMachineRunning);
@ -185,7 +191,10 @@ public class VirtualMachineClientLiveTest extends BaseCloudStackClientLiveTest {
checkVm(vm); checkVm(vm);
} }
@Test
public void testCreateVirtualMachineWithSpecificIp() throws Exception { public void testCreateVirtualMachineWithSpecificIp() throws Exception {
skipIfNotGlobalAdmin();
String templateId = (imageId != null && !"".equals(imageId)) ? imageId : null; String templateId = (imageId != null && !"".equals(imageId)) ? imageId : null;
Network network = null; Network network = null;
@ -327,6 +336,7 @@ public class VirtualMachineClientLiveTest extends BaseCloudStackClientLiveTest {
super.tearDown(); super.tearDown();
} }
@Test
public void testListVirtualMachines() throws Exception { public void testListVirtualMachines() throws Exception {
Set<VirtualMachine> response = client.getVirtualMachineClient().listVirtualMachines(); Set<VirtualMachine> response = client.getVirtualMachineClient().listVirtualMachines();
assert null != response; assert null != response;

View File

@ -246,7 +246,7 @@ public class VolumeClientLiveTest extends BaseCloudStackClientLiveTest {
static Volume findVolumeWithId(final CloudStackClient client, final String id) { static Volume findVolumeWithId(final CloudStackClient client, final String id) {
for (Volume v: client.getVolumeClient().listVolumes()) for (Volume v: client.getVolumeClient().listVolumes())
if (v.getId()==id) return v; if (v.getId().equals(id)) return v;
throw new NoSuchElementException("no volume with id "+id); throw new NoSuchElementException("no volume with id "+id);
} }

View File

@ -28,7 +28,6 @@ import java.util.Set;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import org.jclouds.cloudstack.compute.config.CloudStackComputeServiceContextModule.GetIPForwardingRulesByVirtualMachine;
import org.jclouds.cloudstack.domain.IPForwardingRule; import org.jclouds.cloudstack.domain.IPForwardingRule;
import org.jclouds.cloudstack.domain.Network; import org.jclouds.cloudstack.domain.Network;
import org.jclouds.cloudstack.domain.PublicIPAddress; import org.jclouds.cloudstack.domain.PublicIPAddress;

View File

@ -0,0 +1,82 @@
/**
* 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.cloudstack.parse;
import java.util.Set;
import org.jclouds.cloudstack.domain.GuestIPType;
import org.jclouds.cloudstack.domain.NIC;
import org.jclouds.cloudstack.domain.TrafficType;
import org.jclouds.cloudstack.domain.VirtualMachine;
import org.jclouds.date.internal.SimpleDateFormatDateService;
import org.jclouds.json.BaseSetParserTest;
import org.jclouds.rest.annotations.SelectJson;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
/**
*
* @author Adrian Cole
*/
@Test(groups = "unit")
public class ListVirtualMachinesResponse3xTest extends BaseSetParserTest<VirtualMachine> {
@Override
public String resource() {
return "/listvirtualmachinesresponse3x.json";
}
@Override
@SelectJson("virtualmachine")
public Set<VirtualMachine> expected() {
return ImmutableSet.of(VirtualMachine
.builder()
.id("fee2ccb3-c1f2-4e7b-8465-42b390e10dff")
.name("cloudstack-r-611")
.displayName("cloudstack-r-611")
.account("jcloud2")
.domainId("ea66e3a5-d007-42e8-a0de-ec5ce778a1d7")
.domain("jCloud")
.created(new SimpleDateFormatDateService().iso8601SecondsDateParse("2012-05-22T09:18:28-0700"))
.state(VirtualMachine.State.RUNNING)
.isHAEnabled(false)
.zoneId("1")
.zoneName("Santa Clara Zone")
.templateId("5c65f152-a4bc-4405-a756-fd10841a9aa7")
.templateName("jclouds-6d4bdc29")
.templateDisplayText("jclouds live testCreateTemplate")
.passwordEnabled(false)
.serviceOfferingId("5305750d-df71-4da9-8cd0-e23c2236a6e2")
.serviceOfferingName("Micro Instance")
.cpuCount(1)
.cpuSpeed(500)
.memory(256)
.guestOSId("6dcd58ce-1ec6-432c-af0b-9ab4ca9207d9")
.rootDeviceId("0")
.rootDeviceType("IscsiLUN")
.publicIP("72.52.126.110")
.publicIPId("e202aafb-ab41-4dc0-80e9-9fcd64fbf45c")
.nics(ImmutableSet.of(NIC.builder().id("48640c5e-90f3-45bd-abd2-a108ca8957ac").
networkId("c0d5db5b-f7d5-44e1-b854-21ecd1a09dbf").netmask("255.255.255.0").gateway("10.1.1.1")
.IPAddress("10.1.1.227").trafficType(TrafficType.GUEST).guestIPType(GuestIPType.ISOLATED)
.isDefault(true).build())).build());
}
}

View File

@ -0,0 +1 @@
{ "listvirtualmachinesresponse" : { "count":1 ,"virtualmachine" : [ {"id":"fee2ccb3-c1f2-4e7b-8465-42b390e10dff","name":"cloudstack-r-611","displayname":"cloudstack-r-611","account":"jcloud2","domainid":"ea66e3a5-d007-42e8-a0de-ec5ce778a1d7","domain":"jCloud","created":"2012-05-22T09:18:28-0700","state":"Running","haenable":false,"zoneid":"1","zonename":"Santa Clara Zone","templateid":"5c65f152-a4bc-4405-a756-fd10841a9aa7","templatename":"jclouds-6d4bdc29","templatedisplaytext":"jclouds live testCreateTemplate","passwordenabled":false,"serviceofferingid":"5305750d-df71-4da9-8cd0-e23c2236a6e2","serviceofferingname":"Micro Instance","cpunumber":1,"cpuspeed":500,"memory":256,"guestosid":"6dcd58ce-1ec6-432c-af0b-9ab4ca9207d9","rootdeviceid":0,"rootdevicetype":"IscsiLUN","securitygroup":[],"nic":[{"id":"48640c5e-90f3-45bd-abd2-a108ca8957ac","networkid":"c0d5db5b-f7d5-44e1-b854-21ecd1a09dbf","netmask":"255.255.255.0","gateway":"10.1.1.1","ipaddress":"10.1.1.227","traffictype":"Guest","type":"Isolated","isdefault":true}],"publicipid":"e202aafb-ab41-4dc0-80e9-9fcd64fbf45c","publicip":"72.52.126.110"} ] } }"

View File

@ -39,6 +39,9 @@
<test.cloudwatch.build-version /> <test.cloudwatch.build-version />
<test.cloudwatch.identity>${test.aws.identity}</test.cloudwatch.identity> <test.cloudwatch.identity>${test.aws.identity}</test.cloudwatch.identity>
<test.cloudwatch.credential>${test.aws.credential}</test.cloudwatch.credential> <test.cloudwatch.credential>${test.aws.credential}</test.cloudwatch.credential>
<jclouds.osgi.export>org.jclouds.cloudwatch*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>org.jclouds*;version="${project.version}",*</jclouds.osgi.import>
</properties> </properties>
<dependencies> <dependencies>
@ -101,21 +104,5 @@
</profile> </profile>
</profiles> </profiles>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>org.jclouds.cloudwatch*;version="${project.version}"</Export-Package>
<Import-Package>org.jclouds*;version="${project.version}",*</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project> </project>

View File

@ -18,13 +18,17 @@
*/ */
package org.jclouds.cloudwatch; package org.jclouds.cloudwatch;
import com.google.common.collect.AbstractIterator; import java.util.Iterator;
import java.util.List;
import org.jclouds.cloudwatch.domain.ListMetricsResponse; import org.jclouds.cloudwatch.domain.ListMetricsResponse;
import org.jclouds.cloudwatch.domain.Metric; import org.jclouds.cloudwatch.domain.Metric;
import org.jclouds.cloudwatch.domain.MetricDatum;
import org.jclouds.cloudwatch.features.MetricClient; import org.jclouds.cloudwatch.features.MetricClient;
import org.jclouds.cloudwatch.options.ListMetricsOptions; import org.jclouds.cloudwatch.options.ListMetricsOptions;
import java.util.Iterator; import com.google.common.collect.AbstractIterator;
import com.google.common.collect.Iterables;
/** /**
* Utilities for using CloudWatch. * Utilities for using CloudWatch.
@ -58,10 +62,10 @@ public class CloudWatch {
while (true) { while (true) {
if (iterator == null) { if (iterator == null) {
lastOptions = ListMetricsOptions.builder() lastOptions = ListMetricsOptions.builder()
.dimensions(lastOptions.getDimensions())
.metricName(lastOptions.getMetricName())
.namespace(lastOptions.getNamespace()) .namespace(lastOptions.getNamespace())
.nextToken(response.getNextToken()) .metricName(lastOptions.getMetricName())
.dimensions(lastOptions.getDimensions())
.nextToken(lastOptions.getNextToken())
.build(); .build();
response = metricClient.listMetrics(lastOptions); response = metricClient.listMetrics(lastOptions);
iterator = response.iterator(); iterator = response.iterator();
@ -95,4 +99,21 @@ public class CloudWatch {
return listMetrics(cloudWatchClient.getMetricClientForRegion(region), options); return listMetrics(cloudWatchClient.getMetricClientForRegion(region), options);
} }
/**
* Pushes metrics to CloudWatch.
*
* @param cloudWatchClient the {@link CloudWatchClient} to use for the request
* @param region the region to put the metrics in
* @param metrics the metrics to publish
* @param namespace the namespace to publish the metrics in
*/
public static void putMetricData(CloudWatchClient cloudWatchClient, String region, Iterable<MetricDatum> metrics,
String namespace) {
MetricClient metricClient = cloudWatchClient.getMetricClientForRegion(region);
for (List<MetricDatum> slice : Iterables.partition(metrics, 10)) {
metricClient.putMetricData(slice, namespace);
}
}
} }

View File

@ -18,10 +18,7 @@
*/ */
package org.jclouds.cloudwatch; package org.jclouds.cloudwatch;
import java.util.Date; import com.google.inject.Provides;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.jclouds.cloudwatch.domain.Datapoint; import org.jclouds.cloudwatch.domain.Datapoint;
import org.jclouds.cloudwatch.domain.Statistics; import org.jclouds.cloudwatch.domain.Statistics;
import org.jclouds.cloudwatch.features.MetricClient; import org.jclouds.cloudwatch.features.MetricClient;
@ -33,7 +30,9 @@ import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
import org.jclouds.rest.annotations.Delegate; import org.jclouds.rest.annotations.Delegate;
import org.jclouds.rest.annotations.EndpointParam; import org.jclouds.rest.annotations.EndpointParam;
import com.google.inject.Provides; import java.util.Date;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/** /**
* Provides access to Amazon CloudWatch via the Query API * Provides access to Amazon CloudWatch via the Query API
@ -90,7 +89,7 @@ public interface CloudWatchClient {
* The statistics to be returned for the given metric. ex. Average * The statistics to be returned for the given metric. ex. Average
* @param options * @param options
* more filtering options (e.g. instance ID) * more filtering options (e.g. instance ID)
* @see MetricsClient#getMetricStatistics * @see MetricClient#getMetricStatistics(org.jclouds.cloudwatch.domain.GetMetricStatistics)
*/ */
@Deprecated @Deprecated
Set<Datapoint> getMetricStatisticsInRegion(@Nullable String region, String metricName, String namespace, Set<Datapoint> getMetricStatisticsInRegion(@Nullable String region, String metricName, String namespace,

View File

@ -18,6 +18,8 @@
*/ */
package org.jclouds.cloudwatch.binders; package org.jclouds.cloudwatch.binders;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.inject.Inject; import javax.inject.Inject;
import org.jclouds.cloudwatch.domain.Dimension; import org.jclouds.cloudwatch.domain.Dimension;
@ -50,31 +52,39 @@ public class GetMetricStatisticsBinder implements org.jclouds.rest.Binder {
@Override @Override
public <R extends HttpRequest> R bindToRequest(R request, Object payload) { public <R extends HttpRequest> R bindToRequest(R request, Object payload) {
GetMetricStatistics getRequest = GetMetricStatistics.class.cast(payload); GetMetricStatistics getRequest = GetMetricStatistics.class.cast(checkNotNull(payload,
"GetMetricStatistics must be set!"));
int dimensionIndex = 1; int dimensionIndex = 1;
int statisticIndex = 1; int statisticIndex = 1;
ImmutableMultimap.Builder<String, String> formParameters = ImmutableMultimap.builder();
ImmutableMultimap.Builder<String, String> formParameters = ImmutableMultimap.<String, String> builder();
for (Dimension dimension : getRequest.getDimensions()) { for (Dimension dimension : getRequest.getDimensions()) {
formParameters.put("Dimensions.member." + dimensionIndex + ".Name", dimension.getName()); formParameters.put("Dimensions.member." + dimensionIndex + ".Name", dimension.getName());
formParameters.put("Dimensions.member." + dimensionIndex + ".Value", dimension.getValue()); formParameters.put("Dimensions.member." + dimensionIndex + ".Value", dimension.getValue());
dimensionIndex++; dimensionIndex++;
} }
formParameters.put("EndTime", dateService.iso8601SecondsDateFormat(getRequest.getEndTime())); if (getRequest.getEndTime().isPresent()) {
formParameters.put("EndTime", dateService.iso8601SecondsDateFormat(getRequest.getEndTime().get()));
}
formParameters.put("MetricName", getRequest.getMetricName()); formParameters.put("MetricName", getRequest.getMetricName());
formParameters.put("Namespace", getRequest.getNamespace()); formParameters.put("Namespace", getRequest.getNamespace());
formParameters.put("Period", Integer.toString(getRequest.getPeriod())); formParameters.put("Period", Integer.toString(getRequest.getPeriod()));
if (getRequest.getStartTime().isPresent()) {
formParameters.put("StartTime", dateService.iso8601SecondsDateFormat(getRequest formParameters.put("StartTime", dateService.iso8601SecondsDateFormat(getRequest
.getStartTime())); .getStartTime().get()));
}
for (Statistics statistic : getRequest.getStatistics()) { for (Statistics statistic : getRequest.getStatistics()) {
formParameters.put("Statistics.member." + statisticIndex, statistic.toString()); formParameters.put("Statistics.member." + statisticIndex, statistic.toString());
statisticIndex++; statisticIndex++;
} }
formParameters.put("Unit", getRequest.getUnit().toString()); if (getRequest.getUnit().isPresent()) {
formParameters.put("Unit", getRequest.getUnit().get().toString());
}
return ModifyRequest.putFormParams(request, formParameters.build()); return ModifyRequest.putFormParams(request, formParameters.build());
} }
} }

View File

@ -0,0 +1,106 @@
/**
* 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.cloudwatch.binders;
import static com.google.common.base.Preconditions.checkNotNull;
import org.jclouds.cloudwatch.domain.Dimension;
import org.jclouds.cloudwatch.domain.MetricDatum;
import org.jclouds.cloudwatch.domain.StatisticValues;
import org.jclouds.date.DateService;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.utils.ModifyRequest;
import com.google.common.annotations.Beta;
import com.google.common.collect.ImmutableMultimap;
import com.google.inject.Inject;
/**
* Binds the metrics request to the http request
*
* @see <a href="http://docs.amazonwebservices.com/AmazonCloudWatch/latest/APIReference/API_PutMetricData.html" />
*
* @author Jeremy Whitlock
*/
@Beta
public class MetricDataBinder implements org.jclouds.rest.Binder {
private final DateService dateService;
@Inject
protected MetricDataBinder(DateService dateService) {
this.dateService = dateService;
}
/**
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
Iterable<MetricDatum> metrics = (Iterable<MetricDatum>) checkNotNull(input, "metrics must be set!");
ImmutableMultimap.Builder<String, String> formParameters = ImmutableMultimap.builder();
int metricDatumIndex = 1;
for (MetricDatum metricDatum : metrics) {
int dimensionIndex = 1;
for (Dimension dimension : metricDatum.getDimensions()) {
formParameters.put("MetricData.member." + metricDatumIndex + ".Dimensions.member." + dimensionIndex +
".Name", dimension.getName());
formParameters.put("MetricData.member." + metricDatumIndex + ".Dimensions.member." + dimensionIndex +
".Value", dimension.getValue());
dimensionIndex++;
}
formParameters.put("MetricData.member." + metricDatumIndex + ".MetricName", metricDatum.getMetricName());
if (metricDatum.getStatisticValues().isPresent()) {
StatisticValues statisticValues = metricDatum.getStatisticValues().get();
formParameters.put("MetricData.member." + metricDatumIndex + ".StatisticValues.Maximum",
String.valueOf(statisticValues.getMaximum()));
formParameters.put("MetricData.member." + metricDatumIndex + ".StatisticValues.Minimum",
String.valueOf(statisticValues.getMinimum()));
formParameters.put("MetricData.member." + metricDatumIndex + ".StatisticValues.SampleCount",
String.valueOf(statisticValues.getSampleCount()));
formParameters.put("MetricData.member." + metricDatumIndex + ".StatisticValues.Sum",
String.valueOf(statisticValues.getSum()));
}
if (metricDatum.getTimestamp().isPresent()) {
formParameters.put("MetricData.member." + metricDatumIndex + ".Timestamp",
dateService.iso8601SecondsDateFormat(metricDatum.getTimestamp().get()));
}
formParameters.put("MetricData.member." + metricDatumIndex + ".Unit",
String.valueOf(metricDatum.getUnit()));
formParameters.put("MetricData.member." + metricDatumIndex + ".Value",
String.valueOf(metricDatum.getValue()));
metricDatumIndex++;
}
return ModifyRequest.putFormParams(request, formParameters.build());
}
}

View File

@ -18,14 +18,16 @@
*/ */
package org.jclouds.cloudwatch.domain; package org.jclouds.cloudwatch.domain;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Date; import java.util.Date;
import java.util.Set; import java.util.Set;
import org.jclouds.cloudwatch.options.ListMetricsOptions; import org.jclouds.cloudwatch.options.ListMetricsOptions;
import org.jclouds.javax.annotation.Nullable;
import com.google.common.annotations.Beta; import com.google.common.annotations.Beta;
import com.google.common.base.Preconditions; import com.google.common.base.Optional;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
/** /**
@ -39,34 +41,32 @@ import com.google.common.collect.Sets;
public class GetMetricStatistics { public class GetMetricStatistics {
private final Set<Dimension> dimensions; private final Set<Dimension> dimensions;
private final Date endTime; private final Optional<Date> endTime;
private final String metricName; private final String metricName;
private final String namespace; private final String namespace;
private final int period; private final int period;
private final Date startTime; private final Optional<Date> startTime;
private final Set<Statistics> statistics; private final Set<Statistics> statistics;
private final Unit unit; private final Optional<Unit> unit;
/** /**
* Private constructor to enforce using {@link Builder}. * Private constructor to enforce using {@link Builder}.
*/ */
private GetMetricStatistics(@Nullable Set<Dimension> dimensions, Date endTime, String metricName, protected GetMetricStatistics(Set<Dimension> dimensions, Date endTime, String metricName, String namespace, int period,
String namespace, int period, Date startTime, Set<Statistics> statistics, Date startTime, Set<Statistics> statistics, Unit unit) {
Unit unit) { this.dimensions = ImmutableSet.<Dimension>copyOf(checkNotNull(dimensions, "dimensions"));
this.dimensions = dimensions; this.endTime = Optional.fromNullable(endTime);
this.endTime = endTime; this.metricName = checkNotNull(metricName, "metricName");
this.metricName = metricName; this.namespace = checkNotNull(namespace, "namespace");
this.namespace = namespace;
this.period = period; this.period = period;
this.startTime = startTime; this.startTime = Optional.fromNullable(startTime);
this.statistics = statistics; this.statistics = ImmutableSet.<Statistics>copyOf(checkNotNull(statistics, "statistics"));
this.unit = unit; this.unit = Optional.fromNullable(unit);
} }
/** /**
* return the set of dimensions for this request * return the set of dimensions for this request
*/ */
@Nullable
public Set<Dimension> getDimensions() { public Set<Dimension> getDimensions() {
return dimensions; return dimensions;
} }
@ -74,7 +74,7 @@ public class GetMetricStatistics {
/** /**
* return the end time for this request * return the end time for this request
*/ */
public Date getEndTime() { public Optional<Date> getEndTime() {
return endTime; return endTime;
} }
@ -102,7 +102,7 @@ public class GetMetricStatistics {
/** /**
* return the start time for this request * return the start time for this request
*/ */
public Date getStartTime() { public Optional<Date> getStartTime() {
return startTime; return startTime;
} }
@ -116,7 +116,7 @@ public class GetMetricStatistics {
/** /**
* return the unit for this request * return the unit for this request
*/ */
public Unit getUnit() { public Optional<Unit> getUnit() {
return unit; return unit;
} }
@ -130,12 +130,14 @@ public class GetMetricStatistics {
public static class Builder { public static class Builder {
// this builder is set to be additive on dimension calls, so make this mutable
private Set<Dimension> dimensions = Sets.newLinkedHashSet(); private Set<Dimension> dimensions = Sets.newLinkedHashSet();
private Date endTime; private Date endTime;
private String metricName; private String metricName;
private String namespace; private String namespace;
private int period; private int period = 60;
private Date startTime; private Date startTime;
// this builder is set to be additive on dimension calls, so make this mutable
private Set<Statistics> statistics = Sets.newLinkedHashSet(); private Set<Statistics> statistics = Sets.newLinkedHashSet();
private Unit unit; private Unit unit;
@ -146,143 +148,100 @@ public class GetMetricStatistics {
public Builder() {} public Builder() {}
/** /**
* A list of dimensions describing qualities of the metric. (Set can be 10 or less items.) * A list of dimensions describing qualities of the metric.
* *
* @param dimensions the dimensions describing the qualities of the metric * @param dimensions the dimensions describing the qualities of the metric
* *
* @return this {@code Builder} object * @return this {@code Builder} object
*
* @throws IllegalArgumentException if this is invoked more than 10 times
*/ */
public Builder dimensions(Set<Dimension> dimensions) { public Builder dimensions(Set<Dimension> dimensions) {
if (dimensions != null) { this.dimensions.addAll(checkNotNull(dimensions, "dimensions"));
Preconditions.checkArgument(dimensions.size() <= 10, "dimensions can have 10 or fewer members.");
this.dimensions = dimensions;
}
return this; return this;
} }
/** /**
* A dimension describing qualities of the metric. (Can be called multiple times up to a maximum of 10 times.) * A dimension describing qualities of the metric.
* *
* @param dimension the dimension describing the qualities of the metric * @param dimension the dimension describing the qualities of the metric
* *
* @return this {@code Builder} object * @return this {@code Builder} object
*
* @throws IllegalArgumentException if the number of dimensions would be greater than 10 after adding
*/ */
public Builder dimension(Dimension dimension) { public Builder dimension(Dimension dimension) {
if (dimension != null) { this.dimensions.add(checkNotNull(dimension, "dimension"));
Preconditions.checkArgument(dimensions.size() < 10, "dimension member maximum count of 10 exceeded.");
this.dimensions.add(dimension);
}
return this; return this;
} }
/** /**
* The time stamp to use for determining the last datapoint to return. The value specified is exclusive so * The time stamp to use for determining the last datapoint to return. The value specified is exclusive so
* results will include datapoints up to the time stamp specified. (Should be called once. Subsequent calls * results will include datapoints up to the time stamp specified.
* will overwrite the previous value.)
* *
* @param endTime the timestamp to use for determining the last datapoint to return * @param endTime the timestamp to use for determining the last datapoint to return
* *
* @return this {@code Builder} object * @return this {@code Builder} object
*
* @throws NullPointerException if endTime is null
*/ */
public Builder endTime(Date endTime) { public Builder endTime(Date endTime) {
Preconditions.checkNotNull(endTime, "endTime cannot be null.");
this.endTime = endTime; this.endTime = endTime;
return this; return this;
} }
/** /**
* The name of the metric. (Should be called once. Subsequent calls will overwrite the previous value.) * The name of the metric.
* *
* @param metricName the metric name to filter against * @param metricName the metric name to filter against
* *
* @return this {@code Builder} object * @return this {@code Builder} object
*
* @throws NullPointerException if metricName is null
* @throws IllegalArgumentException if metricName is empty
*/ */
public Builder metricName(String metricName) { public Builder metricName(String metricName) {
Preconditions.checkNotNull(metricName, "metricName cannot be null.");
Preconditions.checkArgument(metricName.length() > 1, "metricName must not be empty.");
this.metricName = metricName; this.metricName = metricName;
return this; return this;
} }
/** /**
* The namespace of the metric. (Should be called once. Subsequent calls will overwrite the previous value. * The namespace of the metric.
* See {@link org.jclouds.cloudwatch.domain.Namespaces} for the known list of namespaces.)
* *
* @param namespace the namespace to filter against * @param namespace the namespace to filter against
* *
* @return this {@code Builder} object * @return this {@code Builder} object
*
* @throws NullPointerException if namespace is null
* @throws IllegalArgumentException if namespace is empty
*/ */
public Builder namespace(String namespace) { public Builder namespace(String namespace) {
Preconditions.checkNotNull(namespace, "namespace cannot be null.");
Preconditions.checkArgument(namespace.length() > 1, "namespace must not be empty.");
this.namespace = namespace; this.namespace = namespace;
return this; return this;
} }
/** /**
* The granularity, in seconds, of the returned datapoints. Period must be at least 60 seconds and must be a * The granularity, in seconds, of the returned datapoints.
* multiple of 60. The default value is 60. (Should be called once. Subsequent calls will overwrite the
* previous value.)
* *
* @param period the granularity, in seconds, of the returned datapoints * @param period the granularity, in seconds, of the returned datapoints
* *
* @return this {@code Builder} object * @return this {@code Builder} object
*
* @throws NullPointerException if period is null
* @throws IllegalArgumentException if period is less than 60 or not a multiple of 60
*/ */
public Builder period(int period) { public Builder period(int period) {
Preconditions.checkNotNull(period, "period cannot be null.");
Preconditions.checkArgument(period >= 60 && period % 60 == 0, "period must be greater than 60 and as a " +
"multiple of 60.");
this.period = period; this.period = period;
return this; return this;
} }
/** /**
* The time stamp to use for determining the first datapoint to return. The value specified is inclusive so * The time stamp to use for determining the first datapoint to return. The value specified is inclusive so
* results include datapoints with the time stamp specified. (Should be called once. Subsequent calls will * results include datapoints with the time stamp specified.
* overwrite the previous value.)
* *
* @param startTime The time stamp to use for determining the first datapoint to return * @param startTime The time stamp to use for determining the first datapoint to return
* *
* @return this {@code Builder} object * @return this {@code Builder} object
*
* @throws NullPointerException if startTime is null
*/ */
public Builder startTime(Date startTime) { public Builder startTime(Date startTime) {
Preconditions.checkNotNull(startTime, "startTime cannot be null.");
this.startTime = startTime; this.startTime = startTime;
return this; return this;
} }
/** /**
* The metric statistics to return. (Should be called once. Subsequent calls will overwrite the previous * The metric statistics to return.
* value.)
* *
* @param statistics the metric statistics to return. * @param statistics the metric statistics to return.
* *
* @return this {@code Builder} object * @return this {@code Builder} object
*
* @throws IllegalArgumentException if the number of statistics is greater than 5
* @throws NullPointerException if statistics is null
*/ */
public Builder statistics(Set<Statistics> statistics) { public Builder statistics(Set<Statistics> statistics) {
Preconditions.checkNotNull(statistics, "statistics cannot be null."); this.statistics.addAll(checkNotNull(statistics, "statistics"));
Preconditions.checkArgument(statistics.size() <= 5, "statistics can have 5 or fewer members.");
this.statistics = statistics;
return this; return this;
} }
@ -292,28 +251,20 @@ public class GetMetricStatistics {
* @param statistic the metric statistic to return * @param statistic the metric statistic to return
* *
* @return this {@code Builder} object * @return this {@code Builder} object
*
* @throws IllegalArgumentException if the number of statistics would be greater than 5 after adding
* @throws NullPointerException if statistic is null
*/ */
public Builder statistic(Statistics statistic) { public Builder statistic(Statistics statistic) {
Preconditions.checkNotNull(statistic, "statistic cannot be null."); this.statistics.add(checkNotNull(statistic, "statistic"));
Preconditions.checkArgument(statistics.size() < 5, "statistics member maximum count of 5 exceeded.");
this.statistics.add(statistic);
return this; return this;
} }
/** /**
* The unit for the metric. (Should be called once. Subsequent calls will overwrite the previous value.) * The unit for the metric.
* *
* @param unit the unit for the metric * @param unit the unit for the metric
* *
* @return this {@code Builder} object * @return this {@code Builder} object
*
* @throws NullPointerException if unit is null
*/ */
public Builder unit(Unit unit) { public Builder unit(Unit unit) {
Preconditions.checkNotNull(unit, "unit cannot be null.");
this.unit = unit; this.unit = unit;
return this; return this;
} }
@ -321,22 +272,12 @@ public class GetMetricStatistics {
/** /**
* Returns a newly-created {@code GetMetricStatisticsOptionsV2} based on the contents of * Returns a newly-created {@code GetMetricStatisticsOptionsV2} based on the contents of
* the {@code Builder}. * the {@code Builder}.
*
* @throws NullPointerException if any of the required fields are null
* @throws IllegalArgumentException if any of the provided fields don't meet required criteria
*/ */
public GetMetricStatistics build() { public GetMetricStatistics build() {
Preconditions.checkNotNull(endTime, "endTime cannot be null."); return new GetMetricStatistics(dimensions, endTime, metricName,namespace, period, startTime, statistics,
Preconditions.checkNotNull(metricName, "metricName cannot be null."); unit);
Preconditions.checkNotNull(namespace, "namespace cannot be null."); }
Preconditions.checkNotNull(period, "period cannot be null.");
Preconditions.checkNotNull(startTime, "startTime cannot be null.");
Preconditions.checkNotNull(statistics, "statistics cannot be null.");
Preconditions.checkNotNull(unit, "unit cannot be null.");
Preconditions.checkArgument(statistics.size() >= 1, "statistics must have at least one member");
return new GetMetricStatistics(dimensions, endTime, metricName,namespace, period, startTime, statistics, unit);
}
} }
} }

View File

@ -0,0 +1,246 @@
/**
* 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.cloudwatch.domain;
import static com.google.common.base.Objects.equal;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Date;
import java.util.Set;
import com.google.common.base.Objects;
import com.google.common.base.Optional;
import com.google.common.base.Objects.ToStringHelper;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
/**
* @see <a href="http://docs.amazonwebservices.com/AmazonCloudWatch/latest/APIReference/API_MetricDatum.html" />
*
* @author Jeremy Whitlock
*/
public class MetricDatum {
private final Set<Dimension> dimensions;
private final String metricName;
private final Optional<StatisticValues> statisticValues;
private final Optional<Date> timestamp;
private final Unit unit;
private final double value;
/**
* Private constructor to enforce using {@link Builder}.
*/
protected MetricDatum(Set<Dimension> dimensions, String metricName, StatisticValues statisticValues, Date timestamp,
Unit unit, double value) {
this.dimensions = ImmutableSet.<Dimension>copyOf(checkNotNull(dimensions, "dimensions"));
this.metricName = checkNotNull(metricName, "metricName");
this.statisticValues = Optional.fromNullable(statisticValues);
this.timestamp = Optional.fromNullable(timestamp);
this.unit = checkNotNull(unit, "unit");
this.value = checkNotNull(value, "value");
}
/**
* return the list of dimensions describing the the metric.
*/
public Set<Dimension> getDimensions() {
return dimensions;
}
/**
* return the metric name for the metric.
*/
public String getMetricName() {
return metricName;
}
/**
* return the object describing the set of statistical values for the metric
*/
public Optional<StatisticValues> getStatisticValues() {
return statisticValues;
}
/**
* return the time stamp used for the metric
*/
public Optional<Date> getTimestamp() {
return timestamp;
}
/**
* return Standard unit used for the metric.
*/
public Unit getUnit() {
return unit;
}
/**
* return the actual value of the metric
*/
public double getValue() {
return value;
}
/**
* Returns a new builder. The generated builder is equivalent to the builder
* created by the {@link Builder} constructor.
*/
public static Builder builder() {
return new Builder();
}
public static class Builder {
// this builder is set to be additive on dimension calls, so make this mutable
private Set<Dimension> dimensions = Sets.newLinkedHashSet();
private String metricName;
private StatisticValues statisticValues;
private Date timestamp;
private Unit unit = Unit.NONE;
private double value;
/**
* Creates a new builder. The returned builder is equivalent to the builder
* generated by {@link org.jclouds.cloudwatch.domain.MetricDatum#builder}.
*/
public Builder() {}
/**
* A list of dimensions describing qualities of the metric.
*
* @param dimensions the dimensions describing the qualities of the metric
*
* @return this {@code Builder} object
*/
public Builder dimensions(Set<Dimension> dimensions) {
this.dimensions.addAll(checkNotNull(dimensions, "dimensions"));
return this;
}
/**
* A dimension describing qualities of the metric.
*
* @param dimension the dimension describing the qualities of the metric
*
* @return this {@code Builder} object
*/
public Builder dimension(Dimension dimension) {
this.dimensions.add(checkNotNull(dimension, "dimension"));
return this;
}
/**
* The name of the metric.
*
* @param metricName the metric name
*
* @return this {@code Builder} object
*/
public Builder metricName(String metricName) {
this.metricName = metricName;
return this;
}
/**
* The object describing the set of statistical values describing the metric.
*
* @param statisticValues the object describing the set of statistical values for the metric
*
* @return this {@code Builder} object
*/
public Builder statisticValues(StatisticValues statisticValues) {
this.statisticValues = statisticValues;
return this;
}
/**
* The time stamp used for the metric. If not specified, the default value is set to the time the metric data was
* received.
*
* @param timestamp the time stamp used for the metric
*
* @return this {@code Builder} object
*/
public Builder timestamp(Date timestamp) {
this.timestamp = timestamp;
return this;
}
/**
* The unit for the metric.
*
* @param unit the unit for the metric
*
* @return this {@code Builder} object
*/
public Builder unit(Unit unit) {
this.unit = unit;
return this;
}
/**
* The value for the metric.
*
* @param value the value for the metric
*
* @return this {@code Builder} object
*/
public Builder value(double value) {
this.value = value;
return this;
}
/**
* Returns a newly-created {@code MetricDatum} based on the contents of the {@code Builder}.
*/
public MetricDatum build() {
return new MetricDatum(dimensions, metricName, statisticValues, timestamp, unit, value);
}
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
MetricDatum that = MetricDatum.class.cast(o);
return equal(this.dimensions, that.dimensions) && equal(this.metricName, that.metricName)
&& equal(this.statisticValues, that.statisticValues) && equal(this.timestamp, that.timestamp)
&& equal(this.unit, that.unit) && equal(this.value, that.value);
}
@Override
public int hashCode() {
return Objects.hashCode(dimensions, metricName, statisticValues, timestamp, unit, value);
}
@Override
public String toString() {
return string().toString();
}
protected ToStringHelper string() {
return Objects.toStringHelper("").add("dimensions", dimensions).add("metricName", metricName).add(
"statisticValues", statisticValues).add("timestamp", timestamp).add("unit", unit).add("value", value);
}
}

View File

@ -0,0 +1,152 @@
/**
* 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.cloudwatch.domain;
import org.jclouds.javax.annotation.Nullable;
/**
* @see <a href="http://docs.amazonwebservices.com/AmazonCloudWatch/latest/APIReference/API_StatisticSet.html" />
*
* @author Jeremy Whitlock
*/
public class StatisticValues {
private final double maximum;
private final double minimum;
private final double sampleCount;
private final double sum;
public StatisticValues(double maximum, double minimum, double sampleCount, double sum) {
this.maximum = maximum;
this.minimum = minimum;
this.sampleCount = sampleCount;
this.sum = sum;
}
/**
* return the maximum value of the sample set
*/
@Nullable
public double getMaximum() {
return maximum;
}
/**
* return the minimum value of the sample set
*/
@Nullable
public double getMinimum() {
return minimum;
}
/**
* return the number of samples used for the statistic set
*/
@Nullable
public double getSampleCount() {
return sampleCount;
}
/**
* return the sum of values for the sample set
*/
@Nullable
public double getSum() {
return sum;
}
/**
* Returns a new builder. The generated builder is equivalent to the builder
* created by the {@link Builder} constructor.
*/
public static Builder builder() {
return new Builder();
}
public static class Builder {
private double maximum;
private double minimum;
private double sampleCount;
private double sum;
/**
* Creates a new builder. The returned builder is equivalent to the builder
* generated by {@link org.jclouds.cloudwatch.domain.StatisticValues#builder}.
*/
public Builder() {}
/**
* The maximum value of the sample set.
*
* @param maximum the maximum value of the sample set
*
* @return this {@code Builder} object
*/
public Builder maximum(double maximum) {
this.maximum = maximum;
return this;
}
/**
* The minimum value of the sample set.
*
* @param minimum the minimum value of the sample set
*
* @return this {@code Builder} object
*/
public Builder minimum(double minimum) {
this.minimum = minimum;
return this;
}
/**
* The the number of samples used for the statistic set.
*
* @param sampleCount the number of samples used for the statistic set
*
* @return this {@code Builder} object
*/
public Builder sampleCount(double sampleCount) {
this.sampleCount = sampleCount;
return this;
}
/**
* The sum of values for the sample set.
*
* @param sum the sum of values for the sample set
*
* @return this {@code Builder} object
*/
public Builder sum(double sum) {
this.sum = sum;
return this;
}
/**
* Returns a newly-created {@code StatisticSet} based on the contents of the {@code Builder}.
*/
public StatisticValues build() {
return new StatisticValues(maximum, minimum, sampleCount, sum);
}
}
}

View File

@ -18,14 +18,14 @@
*/ */
package org.jclouds.cloudwatch.features; package org.jclouds.cloudwatch.features;
import javax.ws.rs.POST; import com.google.common.util.concurrent.ListenableFuture;
import javax.ws.rs.Path;
import org.jclouds.aws.filters.FormSigner; import org.jclouds.aws.filters.FormSigner;
import org.jclouds.cloudwatch.binders.GetMetricStatisticsBinder; import org.jclouds.cloudwatch.binders.GetMetricStatisticsBinder;
import org.jclouds.cloudwatch.binders.MetricDataBinder;
import org.jclouds.cloudwatch.domain.GetMetricStatistics; import org.jclouds.cloudwatch.domain.GetMetricStatistics;
import org.jclouds.cloudwatch.domain.GetMetricStatisticsResponse; import org.jclouds.cloudwatch.domain.GetMetricStatisticsResponse;
import org.jclouds.cloudwatch.domain.ListMetricsResponse; import org.jclouds.cloudwatch.domain.ListMetricsResponse;
import org.jclouds.cloudwatch.domain.MetricDatum;
import org.jclouds.cloudwatch.options.GetMetricStatisticsOptions; import org.jclouds.cloudwatch.options.GetMetricStatisticsOptions;
import org.jclouds.cloudwatch.options.ListMetricsOptions; import org.jclouds.cloudwatch.options.ListMetricsOptions;
import org.jclouds.cloudwatch.xml.GetMetricStatisticsResponseHandlerV2; import org.jclouds.cloudwatch.xml.GetMetricStatisticsResponseHandlerV2;
@ -36,7 +36,9 @@ import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.VirtualHost; import org.jclouds.rest.annotations.VirtualHost;
import org.jclouds.rest.annotations.XMLResponseParser; import org.jclouds.rest.annotations.XMLResponseParser;
import com.google.common.util.concurrent.ListenableFuture; import javax.ws.rs.FormParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
/** /**
* Provides access to Amazon CloudWatch via the Query API * Provides access to Amazon CloudWatch via the Query API
@ -88,4 +90,13 @@ public interface MetricAsyncClient {
@BinderParam(GetMetricStatisticsBinder.class) GetMetricStatistics statistics, @BinderParam(GetMetricStatisticsBinder.class) GetMetricStatistics statistics,
GetMetricStatisticsOptions options); GetMetricStatisticsOptions options);
/**
* @see MetricClient#putMetricData(Iterable, String)
*/
@POST
@Path("/")
@FormParams(keys = "Action", values = "PutMetricData")
ListenableFuture<Void> putMetricData(@BinderParam(MetricDataBinder.class) Iterable<MetricDatum> metrics,
@FormParam("Namespace") String namespace);
} }

View File

@ -18,15 +18,16 @@
*/ */
package org.jclouds.cloudwatch.features; package org.jclouds.cloudwatch.features;
import java.util.concurrent.TimeUnit;
import org.jclouds.cloudwatch.domain.GetMetricStatistics; import org.jclouds.cloudwatch.domain.GetMetricStatistics;
import org.jclouds.cloudwatch.domain.GetMetricStatisticsResponse; import org.jclouds.cloudwatch.domain.GetMetricStatisticsResponse;
import org.jclouds.cloudwatch.domain.ListMetricsResponse; import org.jclouds.cloudwatch.domain.ListMetricsResponse;
import org.jclouds.cloudwatch.domain.MetricDatum;
import org.jclouds.cloudwatch.options.GetMetricStatisticsOptions; import org.jclouds.cloudwatch.options.GetMetricStatisticsOptions;
import org.jclouds.cloudwatch.options.ListMetricsOptions; import org.jclouds.cloudwatch.options.ListMetricsOptions;
import org.jclouds.concurrent.Timeout; import org.jclouds.concurrent.Timeout;
import java.util.concurrent.TimeUnit;
/** /**
* Provides access to Amazon CloudWatch via the Query API * Provides access to Amazon CloudWatch via the Query API
* <p/> * <p/>
@ -45,10 +46,10 @@ public interface MetricClient {
* use returned NextToken ( * use returned NextToken (
* {@link org.jclouds.cloudwatch.domain.ListMetricsResponse#getNextToken()}) value with * {@link org.jclouds.cloudwatch.domain.ListMetricsResponse#getNextToken()}) value with
* subsequent calls .To retrieve all available metrics with one call, use * subsequent calls .To retrieve all available metrics with one call, use
* {@link #list(MetricsClient, String, org.jclouds.cloudwatch.options.ListMetricsOptions)}. * {@link org.jclouds.cloudwatch.CloudWatch#listMetrics(MetricClient,
* org.jclouds.cloudwatch.options.ListMetricsOptions)}
* *
* @param options * @param options the options describing the metrics query
* the options describing the metrics query
* *
* @return the response object * @return the response object
*/ */
@ -59,10 +60,8 @@ public interface MetricClient {
/** /**
* Gets statistics for the specified metric. * Gets statistics for the specified metric.
* *
* @param statistics * @param statistics the statistics to gather
* the statistics to gather * @param options the options describing the metric statistics query
* @param options
* the options describing the metric statistics query
* *
* @return the response object * @return the response object
*/ */
@ -70,4 +69,12 @@ public interface MetricClient {
GetMetricStatisticsResponse getMetricStatistics(GetMetricStatistics statistics); GetMetricStatisticsResponse getMetricStatistics(GetMetricStatistics statistics);
/**
* Publishes metric data points to Amazon CloudWatch.
*
* @param metrics the metrics to publish
* @param namespace the namespace to publish the metrics to
*/
void putMetricData(Iterable<MetricDatum> metrics, String namespace);
} }

View File

@ -18,19 +18,16 @@
*/ */
package org.jclouds.cloudwatch.options; package org.jclouds.cloudwatch.options;
import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import java.util.Set;
import org.jclouds.aws.util.AWSUtils; import org.jclouds.aws.util.AWSUtils;
import org.jclouds.cloudwatch.domain.Dimension; import org.jclouds.cloudwatch.domain.Dimension;
import org.jclouds.cloudwatch.domain.Unit; import org.jclouds.cloudwatch.domain.Unit;
import org.jclouds.http.options.BaseHttpRequestOptions; import org.jclouds.http.options.BaseHttpRequestOptions;
import com.google.common.base.Preconditions; import java.util.Set;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multimap; import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.collect.Sets;
/** /**
* Options used to control metric statistics are returned * Options used to control metric statistics are returned
@ -42,39 +39,32 @@ import com.google.common.collect.Sets;
*/ */
public class GetMetricStatisticsOptions extends BaseHttpRequestOptions { public class GetMetricStatisticsOptions extends BaseHttpRequestOptions {
private Set<Dimension> dimensions = Sets.newLinkedHashSet(); private Set<Dimension> dimensions;
/** /**
* A dimension describing qualities of the metric. (Can be called multiple times up to a maximum of 10 times.) * A dimension describing qualities of the metric.
* *
* @param dimension the dimension describing the qualities of the metric * @param dimension the dimension describing the qualities of the metric
* *
* @return this {@code Builder} object * @return this {@code Builder} object
*
* @throws IllegalArgumentException if the number of dimensions would be greater than 10 after adding
*/ */
public GetMetricStatisticsOptions dimension(Dimension dimension) { public GetMetricStatisticsOptions dimension(Dimension dimension) {
if (dimension != null) { if (dimensions == null) {
Preconditions.checkArgument(dimensions.size() < 10, "dimension member maximum count of 10 exceeded."); dimensions = Sets.newLinkedHashSet();
this.dimensions.add(dimension);
} }
this.dimensions.add(dimension);
return this; return this;
} }
/** /**
* A list of dimensions describing qualities of the metric. (Set can be 10 or less items.) * A list of dimensions describing qualities of the metric.
* *
* @param dimensions the dimensions describing the qualities of the metric * @param dimensions the dimensions describing the qualities of the metric
* *
* @return this {@code Builder} object * @return this {@code Builder} object
*
* @throws IllegalArgumentException if this is invoked more than 10 times
*/ */
public GetMetricStatisticsOptions dimensions(Set<Dimension> dimensions) { public GetMetricStatisticsOptions dimensions(Set<Dimension> dimensions) {
if (dimensions != null) { this.dimensions = dimensions;
Preconditions.checkArgument(dimensions.size() <= 10, "dimensions can have 10 or fewer members.");
this.dimensions = ImmutableSet.<Dimension>copyOf(dimensions);
}
return this; return this;
} }
@ -137,11 +127,13 @@ public class GetMetricStatisticsOptions extends BaseHttpRequestOptions {
public Multimap<String, String> buildFormParameters() { public Multimap<String, String> buildFormParameters() {
Multimap<String, String> formParameters = super.buildFormParameters(); Multimap<String, String> formParameters = super.buildFormParameters();
int dimensionIndex = 1; int dimensionIndex = 1;
if (dimensions != null) {
for (Dimension dimension : dimensions) { for (Dimension dimension : dimensions) {
formParameters.put("Dimensions.member." + dimensionIndex + ".Name", dimension.getName()); formParameters.put("Dimensions.member." + dimensionIndex + ".Name", dimension.getName());
formParameters.put("Dimensions.member." + dimensionIndex + ".Value", dimension.getValue()); formParameters.put("Dimensions.member." + dimensionIndex + ".Value", dimension.getValue());
dimensionIndex++; dimensionIndex++;
} }
}
return formParameters; return formParameters;
} }

View File

@ -18,7 +18,6 @@
*/ */
package org.jclouds.cloudwatch.options; package org.jclouds.cloudwatch.options;
import com.google.common.base.Preconditions;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import org.jclouds.cloudwatch.domain.Dimension; import org.jclouds.cloudwatch.domain.Dimension;
import org.jclouds.http.options.BaseHttpRequestOptions; import org.jclouds.http.options.BaseHttpRequestOptions;
@ -105,72 +104,50 @@ public class ListMetricsOptions extends BaseHttpRequestOptions {
public Builder() {} public Builder() {}
/** /**
* The namespace to filter against. (Should be called once. Subsequent calls will overwrite the previous value. * The namespace to filter against.
* See {@link org.jclouds.cloudwatch.domain.Namespaces} for the known list of namespaces.)
* *
* @param namespace the namespace to filter against * @param namespace the namespace to filter against
* *
* @return this {@code Builder} object * @return this {@code Builder} object
*
* @throws IllegalArgumentException if namespace is empty
*/ */
public Builder namespace(String namespace) { public Builder namespace(String namespace) {
if (namespace != null) {
Preconditions.checkArgument(namespace.length() > 1, "namespace must not be empty.");
}
this.namespace = namespace; this.namespace = namespace;
return this; return this;
} }
/** /**
* The name of the metric to filter against. (Should be called once. Subsequent calls will overwrite the * The name of the metric to filter against.
* previous value.)
* *
* @param metricName the metric name to filter against * @param metricName the metric name to filter against
* *
* @return this {@code Builder} object * @return this {@code Builder} object
*
* @throws IllegalArgumentException if metricName is empty
*/ */
public Builder metricName(String metricName) { public Builder metricName(String metricName) {
if (metricName != null) {
Preconditions.checkArgument(metricName.length() > 1, "metricName must not be empty.");
}
this.metricName = metricName; this.metricName = metricName;
return this; return this;
} }
/** /**
* A list of dimensions to filter against. (Set can be 10 or less items.) * A list of dimensions to filter against.
* *
* @param dimensions the dimensions to filter against * @param dimensions the dimensions to filter against
* *
* @return this {@code Builder} object * @return this {@code Builder} object
*
* @throws IllegalArgumentException if the number of dimensions would be greater than 10 after adding
*/ */
public Builder dimensions(Set<Dimension> dimensions) { public Builder dimensions(Set<Dimension> dimensions) {
if (dimensions != null) {
Preconditions.checkArgument(dimensions.size() <= 10, "dimensions can have 10 or fewer members.");
this.dimensions = dimensions; this.dimensions = dimensions;
}
return this; return this;
} }
/** /**
* A dimension to filter the available metrics by. (Can be called multiple times up to a maximum of 10 times.) * A dimension to filter the available metrics by.
* *
* @param dimension a dimension to filter the returned metrics by * @param dimension a dimension to filter the returned metrics by
* *
* @return this {@code Builder} object * @return this {@code Builder} object
*
* @throws IllegalArgumentException if this is invoked more than 10 times
*/ */
public Builder dimension(Dimension dimension) { public Builder dimension(Dimension dimension) {
if (dimension != null) {
Preconditions.checkArgument(dimensions.size() < 10, "dimension member maximum count of 10 exceeded.");
this.dimensions.add(dimension); this.dimensions.add(dimension);
}
return this; return this;
} }
@ -194,20 +171,25 @@ public class ListMetricsOptions extends BaseHttpRequestOptions {
ListMetricsOptions lmo = new ListMetricsOptions(namespace, metricName, dimensions, nextToken); ListMetricsOptions lmo = new ListMetricsOptions(namespace, metricName, dimensions, nextToken);
int dimensionIndex = 1; int dimensionIndex = 1;
// If namespace isn't specified, don't include it
if (namespace != null) { if (namespace != null) {
lmo.formParameters.put("Namespace", namespace); lmo.formParameters.put("Namespace", namespace);
} }
// If metricName isn't specified, don't include it
if (metricName != null) { if (metricName != null) {
lmo.formParameters.put("MetricName", metricName); lmo.formParameters.put("MetricName", metricName);
} }
// If dimensions isn't specified, don't include it
if (dimensions != null) {
for (Dimension dimension : dimensions) { for (Dimension dimension : dimensions) {
lmo.formParameters.put("Dimensions.member." + dimensionIndex + ".Name", dimension.getName()); lmo.formParameters.put("Dimensions.member." + dimensionIndex + ".Name", dimension.getName());
lmo.formParameters.put("Dimensions.member." + dimensionIndex + ".Value", dimension.getValue()); lmo.formParameters.put("Dimensions.member." + dimensionIndex + ".Value", dimension.getValue());
dimensionIndex++; dimensionIndex++;
} }
}
// If nextToken isn't specified, don't include it
if (nextToken != null) { if (nextToken != null) {
lmo.formParameters.put("NextToken", nextToken); lmo.formParameters.put("NextToken", nextToken);
} }

View File

@ -18,15 +18,14 @@
*/ */
package org.jclouds.cloudwatch.xml; package org.jclouds.cloudwatch.xml;
import java.util.Date;
import javax.inject.Inject;
import org.jclouds.cloudwatch.domain.Datapoint; import org.jclouds.cloudwatch.domain.Datapoint;
import org.jclouds.cloudwatch.domain.Unit; import org.jclouds.cloudwatch.domain.Unit;
import org.jclouds.date.DateService; import org.jclouds.date.DateService;
import org.jclouds.http.functions.ParseSax; import org.jclouds.http.functions.ParseSax;
import javax.inject.Inject;
import java.util.Date;
/** /**
* *
* @author Adrian Cole * @author Adrian Cole
@ -71,7 +70,7 @@ public class DatapointHandler extends ParseSax.HandlerForGeneratedRequestWithRes
minimum = doubleOrNull(); minimum = doubleOrNull();
} else if (qName.equals("Timestamp")) { } else if (qName.equals("Timestamp")) {
timestamp = dateService.iso8601SecondsDateParse(currentText.toString().trim()); timestamp = dateService.iso8601SecondsDateParse(currentText.toString().trim());
} else if (qName.equals("Samples")) { } else if (qName.equals("SampleCount")) {
samples = doubleOrNull(); samples = doubleOrNull();
} else if (qName.equals("Sum")) { } else if (qName.equals("Sum")) {
sum = doubleOrNull(); sum = doubleOrNull();

View File

@ -18,13 +18,25 @@
*/ */
package org.jclouds.cloudwatch; package org.jclouds.cloudwatch;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import com.google.common.reflect.TypeToken; import com.google.common.reflect.TypeToken;
import org.jclouds.apis.BaseContextLiveTest; import org.jclouds.apis.BaseContextLiveTest;
import org.jclouds.cloudwatch.domain.Dimension;
import org.jclouds.cloudwatch.domain.MetricDatum;
import org.jclouds.cloudwatch.domain.Unit;
import org.jclouds.cloudwatch.options.ListMetricsOptions; import org.jclouds.cloudwatch.options.ListMetricsOptions;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.rest.RestContext; import org.jclouds.rest.RestContext;
import org.testng.Assert;
import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import java.util.Date;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;
/** /**
@ -58,4 +70,38 @@ public class CloudWatchLiveTest extends BaseContextLiveTest<RestContext<CloudWat
checkArgument(CloudWatch.listMetrics(client, null, ListMetricsOptions.builder().build()).iterator().hasNext()); checkArgument(CloudWatch.listMetrics(client, null, ListMetricsOptions.builder().build()).iterator().hasNext());
} }
@Test
protected void testCloudWatchPutMetrics() {
String metricName = "TestMetricName" + System.currentTimeMillis();
String namespace = "JCLOUDS/Test";
Date metricTimestamp = new Date();
Set<MetricDatum> metrics = Sets.newLinkedHashSet();
for (int i = 0; i < 11; i++) {
metrics.add(MetricDatum.builder()
.metricName(metricName + "_" + i)
.dimension(new Dimension("BaseMetricName", metricName))
.unit(Unit.COUNT)
.timestamp(metricTimestamp)
.value((double) i)
.build());
}
CloudWatch.putMetricData(client, null, metrics, namespace);
ListMetricsOptions lmo = ListMetricsOptions.builder().namespace(namespace)
.dimension(new Dimension("BaseMetricName", metricName))
.build();
boolean success = new RetryablePredicate<ListMetricsOptions>(new Predicate<ListMetricsOptions>() {
@Override
public boolean apply(ListMetricsOptions options) {
return Iterables.size(CloudWatch.listMetrics(client, null, options)) == 11;
}
}, 20, 1, TimeUnit.MINUTES).apply(lmo);
if (!success) {
Assert.fail("Unable to gather the created CloudWatch data within the time (20m) allotted.");
}
}
} }

View File

@ -22,9 +22,13 @@ import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.expect;
import java.util.List;
import java.util.Set;
import org.easymock.EasyMock; import org.easymock.EasyMock;
import org.jclouds.cloudwatch.domain.ListMetricsResponse; import org.jclouds.cloudwatch.domain.ListMetricsResponse;
import org.jclouds.cloudwatch.domain.Metric; import org.jclouds.cloudwatch.domain.Metric;
import org.jclouds.cloudwatch.domain.MetricDatum;
import org.jclouds.cloudwatch.features.MetricClient; import org.jclouds.cloudwatch.features.MetricClient;
import org.jclouds.cloudwatch.options.ListMetricsOptions; import org.jclouds.cloudwatch.options.ListMetricsOptions;
import org.testng.Assert; import org.testng.Assert;
@ -32,12 +36,14 @@ import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
/** /**
* Tests behavior of {@code CloudWatch}. * Tests behavior of {@code CloudWatch}.
* *
* @author Jeremy Whitlock * @author Jeremy Whitlock
*/ */
@Test(testName = "CloudWatchTest")
public class CloudWatchTest { public class CloudWatchTest {
/** /**
@ -97,4 +103,37 @@ public class CloudWatchTest {
Assert.assertEquals(2, Iterables.size(CloudWatch.listMetrics(client, "", options))); Assert.assertEquals(2, Iterables.size(CloudWatch.listMetrics(client, "", options)));
} }
/**
* Tests {@link CloudWatch#putMetricData(CloudWatchClient, String, Iterable, String)} where the set of metrics is
* greater than 10.
*
* @throws Exception if anything goes wrong
*/
@Test
public void testPutMetricData() throws Exception {
CloudWatchClient client = createMock(CloudWatchClient.class);
MetricClient metricClient = createMock(MetricClient.class);
Set<MetricDatum> metrics = Sets.newLinkedHashSet();
String namespace = "JCLOUDS/Test";
for (int i = 0; i < 11; i++) {
metrics.add(MetricDatum.builder().metricName("foo").build());
}
// Using EasyMock.eq("") because EasyMock makes it impossible to pass null as a String value here
expect(client.getMetricClientForRegion(EasyMock.eq("")))
.andReturn(metricClient)
.atLeastOnce();
for (List<MetricDatum> slice : Iterables.partition(metrics, 10)) {
metricClient.putMetricData(slice, namespace);
}
EasyMock.replay(client, metricClient);
CloudWatch.putMetricData(client, "", metrics, namespace);
EasyMock.verify(metricClient);
}
} }

View File

@ -0,0 +1,150 @@
/**
* 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.cloudwatch.binders;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Guice;
import com.google.inject.Injector;
import org.jclouds.cloudwatch.domain.Dimension;
import org.jclouds.cloudwatch.domain.MetricDatum;
import org.jclouds.cloudwatch.domain.StatisticValues;
import org.jclouds.cloudwatch.domain.Unit;
import org.jclouds.http.HttpRequest;
import org.testng.Assert;
import org.testng.annotations.Test;
import java.net.URI;
import java.util.Date;
/**
* Tests behavior of {@link MetricDataBinder}.
*
* @author Jeremy Whitlock
*/
@Test(groups = "unit", testName = "MetricDataBinderTest")
public class MetricDataBinderTest {
Injector injector = Guice.createInjector();
MetricDataBinder binder = injector.getInstance(MetricDataBinder.class);
HttpRequest request() {
return HttpRequest.builder().method("POST").endpoint(URI.create("http://localhost")).build();
}
public void testMetricWithoutTimestamp() throws Exception {
StatisticValues ss = StatisticValues.builder()
.maximum(4.0)
.minimum(1.0)
.sampleCount(4.0)
.sum(10.0)
.build();
MetricDatum metricDatum = MetricDatum.builder()
.metricName("TestMetricName")
.statisticValues(ss)
.dimension(new Dimension("TestDimension", "FAKE"))
.unit(Unit.COUNT)
.value(2)
.build();
HttpRequest request = binder.bindToRequest(request(), ImmutableSet.of(metricDatum));
Assert.assertEquals(request.getPayload().getRawContent(),
"MetricData.member.1.Dimensions.member.1.Name=TestDimension" +
"&MetricData.member.1.Dimensions.member.1.Value=FAKE" +
"&MetricData.member.1.MetricName=TestMetricName" +
"&MetricData.member.1.StatisticValues.Maximum=4.0" +
"&MetricData.member.1.StatisticValues.Minimum=1.0" +
"&MetricData.member.1.StatisticValues.SampleCount=4.0" +
"&MetricData.member.1.StatisticValues.Sum=10.0" +
"&MetricData.member.1.Unit=" + Unit.COUNT.toString() +
"&MetricData.member.1.Value=2.0");
}
public void testMetricWithMultipleDimensions() throws Exception {
MetricDatum metricDatum = MetricDatum.builder()
.metricName("TestMetricName")
.dimension(new Dimension("TestDimension", "FAKE"))
.dimension(new Dimension("TestDimension2", "FAKE2"))
.unit(Unit.COUNT)
.timestamp(new Date(10000000l))
.value(5.0)
.build();
HttpRequest request = binder.bindToRequest(request(), ImmutableSet.of(metricDatum));
Assert.assertEquals(request.getPayload().getRawContent(),
"MetricData.member.1.Dimensions.member.1.Name=TestDimension" +
"&MetricData.member.1.Dimensions.member.1.Value=FAKE" +
"&MetricData.member.1.Dimensions.member.2.Name=TestDimension2" +
"&MetricData.member.1.Dimensions.member.2.Value=FAKE2" +
"&MetricData.member.1.MetricName=TestMetricName" +
"&MetricData.member.1.Timestamp=1970-01-01T02%3A46%3A40Z" +
"&MetricData.member.1.Unit=" + Unit.COUNT.toString() +
"&MetricData.member.1.Value=5.0");
}
public void testMetricWithMultipleDatum() throws Exception {
StatisticValues ss = StatisticValues.builder()
.maximum(4.0)
.minimum(1.0)
.sampleCount(4.0)
.sum(10.0)
.build();
MetricDatum metricDatum = MetricDatum.builder()
.metricName("TestMetricName")
.statisticValues(ss)
.dimension(new Dimension("TestDimension", "FAKE"))
.dimension(new Dimension("TestDimension2", "FAKE2"))
.unit(Unit.COUNT)
.timestamp(new Date(10000000l))
.value(2.0)
.build();
MetricDatum metricDatum2 = MetricDatum.builder()
.metricName("TestMetricName")
.dimension(new Dimension("TestDimension", "FAKE"))
.unit(Unit.COUNT)
.timestamp(new Date(10000000l))
.value(5.0)
.build();
HttpRequest request = binder.bindToRequest(request(), ImmutableSet.of(metricDatum, metricDatum2));
Assert.assertEquals(request.getPayload().getRawContent(),
"MetricData.member.1.Dimensions.member.1.Name=TestDimension" +
"&MetricData.member.1.Dimensions.member.1.Value=FAKE" +
"&MetricData.member.1.Dimensions.member.2.Name=TestDimension2" +
"&MetricData.member.1.Dimensions.member.2.Value=FAKE2" +
"&MetricData.member.1.MetricName=TestMetricName" +
"&MetricData.member.1.StatisticValues.Maximum=4.0" +
"&MetricData.member.1.StatisticValues.Minimum=1.0" +
"&MetricData.member.1.StatisticValues.SampleCount=4.0" +
"&MetricData.member.1.StatisticValues.Sum=10.0" +
"&MetricData.member.1.Timestamp=1970-01-01T02%3A46%3A40Z" +
"&MetricData.member.1.Unit=" + Unit.COUNT.toString() +
"&MetricData.member.1.Value=2.0" +
"&MetricData.member.2.Dimensions.member.1.Name=TestDimension" +
"&MetricData.member.2.Dimensions.member.1.Value=FAKE" +
"&MetricData.member.2.MetricName=TestMetricName" +
"&MetricData.member.2.Timestamp=1970-01-01T02%3A46%3A40Z" +
"&MetricData.member.2.Unit=" + Unit.COUNT.toString() +
"&MetricData.member.2.Value=5.0");
}
}

View File

@ -18,12 +18,7 @@
*/ */
package org.jclouds.cloudwatch.features; package org.jclouds.cloudwatch.features;
import static org.testng.Assert.assertEquals; import com.google.common.collect.ImmutableMultimap;
import java.net.URI;
import java.util.Date;
import java.util.TimeZone;
import org.jclouds.cloudwatch.CloudWatchClient; import org.jclouds.cloudwatch.CloudWatchClient;
import org.jclouds.cloudwatch.domain.Dimension; import org.jclouds.cloudwatch.domain.Dimension;
import org.jclouds.cloudwatch.domain.EC2Constants; import org.jclouds.cloudwatch.domain.EC2Constants;
@ -39,7 +34,11 @@ import org.jclouds.http.HttpResponse;
import org.jclouds.rest.ResourceNotFoundException; import org.jclouds.rest.ResourceNotFoundException;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMultimap; import java.net.URI;
import java.util.Date;
import java.util.TimeZone;
import static org.testng.Assert.assertEquals;
/** /**
* @author Jeremy Whitlock, Adrian Cole * @author Jeremy Whitlock, Adrian Cole
@ -59,14 +58,14 @@ public class MetricClientExpectTest extends BaseCloudWatchClientExpectTest {
.build()) .build())
.payload( .payload(
payloadFromStringWithContentType( payloadFromStringWithContentType(
new StringBuilder() "Action=ListMetrics" +
.append("Action=ListMetrics").append('&') "&Signature=KSh9oQydCR0HMAV6QPYwDzqwQIpxs8I%2Fig7brYgHVZU%3D" +
.append("Signature=KSh9oQydCR0HMAV6QPYwDzqwQIpxs8I%2Fig7brYgHVZU%3D").append('&') "&SignatureMethod=HmacSHA256" +
.append("SignatureMethod=HmacSHA256").append('&') "&SignatureVersion=2" +
.append("SignatureVersion=2").append('&') "&Timestamp=2009-11-08T15%3A54%3A08.897Z" +
.append("Timestamp=2009-11-08T15%3A54%3A08.897Z").append('&') "&Version=2010-08-01" +
.append("Version=2010-08-01").append('&') "&AWSAccessKeyId=identity",
.append("AWSAccessKeyId=identity").toString(), "application/x-www-form-urlencoded")) "application/x-www-form-urlencoded"))
.build(); .build();
public void testListMetricsWhenResponseIs2xx() throws Exception { public void testListMetricsWhenResponseIs2xx() throws Exception {
@ -78,7 +77,8 @@ public class MetricClientExpectTest extends BaseCloudWatchClientExpectTest {
listMetrics, listMetricsResponse); listMetrics, listMetricsResponse);
assertEquals(clientWhenMetricsExist.getMetricClientForRegion(null).listMetrics().toString(), assertEquals(clientWhenMetricsExist.getMetricClientForRegion(null).listMetrics().toString(),
"ListMetricsResponse{metrics=[Metric{namespace=AWS/EC2, metricName=CPUUtilization, dimension=[Dimension{name=InstanceId, value=i-689fcf0f}]}], nextToken=null}"); "ListMetricsResponse{metrics=[Metric{namespace=AWS/EC2, metricName=CPUUtilization, " +
"dimension=[Dimension{name=InstanceId, value=i-689fcf0f}]}], nextToken=null}");
} }
// TODO: this should really be an empty set // TODO: this should really be an empty set
@ -94,27 +94,27 @@ public class MetricClientExpectTest extends BaseCloudWatchClientExpectTest {
} }
public void testListMetricsWithOptionsWhenResponseIs2xx() throws Exception { public void testListMetricsWithOptionsWhenResponseIs2xx() throws Exception {
HttpRequest listMetricsWithOptions = HttpRequest.builder() HttpRequest listMetricsWithOptions =
HttpRequest.builder()
.method("POST") .method("POST")
.endpoint(URI.create("https://monitoring.us-east-1.amazonaws.com/")) .endpoint(URI.create("https://monitoring.us-east-1.amazonaws.com/"))
.headers(ImmutableMultimap.<String, String>builder() .headers(ImmutableMultimap.<String, String>builder()
.put("Host", "monitoring.us-east-1.amazonaws.com") .put("Host", "monitoring.us-east-1.amazonaws.com")
.build()) .build())
.payload( .payload(payloadFromStringWithContentType(
payloadFromStringWithContentType( "Action=ListMetrics" +
new StringBuilder() "&Dimensions.member.1.Name=InstanceId" +
.append("Action=ListMetrics").append('&') "&Dimensions.member.1.Value=SOMEINSTANCEID" +
.append("Dimensions.member.1.Name=InstanceId").append('&') "&MetricName=CPUUtilization" +
.append("Dimensions.member.1.Value=SOMEINSTANCEID").append('&') "&Namespace=SOMENEXTTOKEN" +
.append("MetricName=CPUUtilization").append('&') "&NextToken=AWS%2FEC2" +
.append("Namespace=SOMENEXTTOKEN").append('&') "&Signature=G05HKEx9FJpGZBk02OVYwt3u4g%2FilAY9nU5hJI9LDXA%3D" +
.append("NextToken=AWS%2FEC2").append('&') "&SignatureMethod=HmacSHA256" +
.append("Signature=G05HKEx9FJpGZBk02OVYwt3u4g%2FilAY9nU5hJI9LDXA%3D").append('&') "&SignatureVersion=2" +
.append("SignatureMethod=HmacSHA256").append('&') "&Timestamp=2009-11-08T15%3A54%3A08.897Z" +
.append("SignatureVersion=2").append('&') "&Version=2010-08-01" +
.append("Timestamp=2009-11-08T15%3A54%3A08.897Z").append('&') "&AWSAccessKeyId=identity",
.append("Version=2010-08-01").append('&') "application/x-www-form-urlencoded"))
.append("AWSAccessKeyId=identity").toString(), "application/x-www-form-urlencoded"))
.build(); .build();
HttpResponse listMetricsWithOptionsResponse = HttpResponse.builder().statusCode(200) HttpResponse listMetricsWithOptionsResponse = HttpResponse.builder().statusCode(200)
@ -126,12 +126,14 @@ public class MetricClientExpectTest extends BaseCloudWatchClientExpectTest {
assertEquals( assertEquals(
clientWhenMetricsWithOptionsExist.getMetricClientForRegion(null).listMetrics( clientWhenMetricsWithOptionsExist.getMetricClientForRegion(null).listMetrics(
ListMetricsOptions.builder() ListMetricsOptions.builder()
.dimension(new Dimension(EC2Constants.Dimension.INSTANCE_ID, "SOMEINSTANCEID")) .dimension(new Dimension(EC2Constants.Dimension.INSTANCE_ID,
"SOMEINSTANCEID"))
.metricName(EC2Constants.MetricName.CPU_UTILIZATION) .metricName(EC2Constants.MetricName.CPU_UTILIZATION)
.namespace("SOMENEXTTOKEN") .namespace("SOMENEXTTOKEN")
.nextToken( Namespaces.EC2) .nextToken( Namespaces.EC2)
.build()).toString(), .build()).toString(),
"ListMetricsResponse{metrics=[Metric{namespace=AWS/EC2, metricName=CPUUtilization, dimension=[Dimension{name=InstanceId, value=i-689fcf0f}]}], nextToken=null}"); "ListMetricsResponse{metrics=[Metric{namespace=AWS/EC2, metricName=CPUUtilization, " +
"dimension=[Dimension{name=InstanceId, value=i-689fcf0f}]}], nextToken=null}");
} }
GetMetricStatistics stats = GetMetricStatistics.builder() GetMetricStatistics stats = GetMetricStatistics.builder()
@ -152,21 +154,22 @@ public class MetricClientExpectTest extends BaseCloudWatchClientExpectTest {
.build()) .build())
.payload( .payload(
payloadFromStringWithContentType( payloadFromStringWithContentType(
new StringBuilder() "Action=GetMetricStatistics" +
.append("Action=GetMetricStatistics").append('&') "&EndTime=1970-01-01T02%3A46%3A40Z" +
.append("EndTime=1970-01-01T02%3A46%3A40Z").append('&') "&MetricName=CPUUtilization" +
.append("MetricName=CPUUtilization").append('&') "&Namespace=AWS%2FEC2" +
.append("Namespace=AWS%2FEC2").append('&') "&Period=60" +
.append("Period=60").append('&') "&Signature=rmg8%2Ba7w4ycy%2FKfO8rnuj6rDL0jNE96m8GKfjh3SWcw%3D" +
.append("Signature=rmg8%2Ba7w4ycy%2FKfO8rnuj6rDL0jNE96m8GKfjh3SWcw%3D").append('&') "&SignatureMethod=HmacSHA256" +
.append("SignatureMethod=HmacSHA256").append('&') "&SignatureVersion=2" +
.append("SignatureVersion=2").append('&') "&StartTime=1970-01-01T02%3A46%3A40Z" +
.append("StartTime=1970-01-01T02%3A46%3A40Z").append('&') "&Statistics.member.1=Maximum" +
.append("Statistics.member.1=Maximum").append('&') "&Statistics.member.2=Minimum" +
.append("Statistics.member.2=Minimum").append('&') "&Timestamp=2009-11-08T15%3A54%3A08.897Z" +
.append("Timestamp=2009-11-08T15%3A54%3A08.897Z").append('&') "&Unit=Percent" +
.append("Unit=Percent").append('&').append("Version=2010-08-01").append('&') "&Version=2010-08-01" +
.append("AWSAccessKeyId=identity").toString(), "application/x-www-form-urlencoded")) "&AWSAccessKeyId=identity",
"application/x-www-form-urlencoded"))
.build(); .build();
public void testGetMetricStatisticsWhenResponseIs2xx() throws Exception { public void testGetMetricStatisticsWhenResponseIs2xx() throws Exception {
@ -179,7 +182,11 @@ public class MetricClientExpectTest extends BaseCloudWatchClientExpectTest {
assertEquals( assertEquals(
clientWhenMetricsExist.getMetricClientForRegion(null).getMetricStatistics(stats).toString(), clientWhenMetricsExist.getMetricClientForRegion(null).getMetricStatistics(stats).toString(),
// TODO: make an object for this // TODO: make an object for this
"GetMetricStatisticsResponse{label=CPUUtilization, datapoints=[Datapoint{timestamp=Thu Jan 15 16:00:00 PST 2009, customUnit=null, maximum=null, minimum=null, average=0.17777777777777778, sum=null, samples=9.0, unit=Percent}, Datapoint{timestamp=Thu Jan 15 16:01:00 PST 2009, customUnit=null, maximum=null, minimum=null, average=0.1, sum=null, samples=8.0, unit=Percent}]}"); "GetMetricStatisticsResponse{label=CPUUtilization, " +
"datapoints=[Datapoint{timestamp=Thu Jan 15 16:00:00 PST 2009, customUnit=null, maximum=null, " +
"minimum=null, average=0.17777777777777778, sum=null, samples=9.0, unit=Percent}, " +
"Datapoint{timestamp=Thu Jan 15 16:01:00 PST 2009, customUnit=null, maximum=null, minimum=null, " +
"average=0.1, sum=null, samples=8.0, unit=Percent}]}");
} }
// TODO: this should really be an empty set // TODO: this should really be an empty set
@ -194,34 +201,34 @@ public class MetricClientExpectTest extends BaseCloudWatchClientExpectTest {
} }
public void testGetMetricStatisticsWithOptionsWhenResponseIs2xx() throws Exception { public void testGetMetricStatisticsWithOptionsWhenResponseIs2xx() throws Exception {
HttpRequest getMetricStatistics = HttpRequest.builder() HttpRequest getMetricStatistics =
HttpRequest.builder()
.method("POST") .method("POST")
.endpoint(URI.create("https://monitoring.us-east-1.amazonaws.com/")) .endpoint(URI.create("https://monitoring.us-east-1.amazonaws.com/"))
.headers(ImmutableMultimap.<String, String> builder() .headers(ImmutableMultimap.<String, String> builder()
.put("Host", "monitoring.us-east-1.amazonaws.com") .put("Host", "monitoring.us-east-1.amazonaws.com")
.build()) .build())
.payload( .payload(payloadFromStringWithContentType(
payloadFromStringWithContentType( "Action=GetMetricStatistics" +
new StringBuilder() "&Dimensions.member.1.Name=InstanceId" +
.append("Action=GetMetricStatistics").append('&') "&Dimensions.member.1.Value=SOMEINSTANCEID" +
.append("Dimensions.member.1.Name=InstanceId").append('&') "&Dimensions.member.2.Name=InstanceType" +
.append("Dimensions.member.1.Value=SOMEINSTANCEID").append('&') "&Dimensions.member.2.Value=t1.micro" +
.append("Dimensions.member.2.Name=InstanceType").append('&') "&EndTime=1970-01-01T02%3A46%3A40Z" +
.append("Dimensions.member.2.Value=t1.micro").append('&') "&MetricName=CPUUtilization" +
.append("EndTime=1970-01-01T02%3A46%3A40Z").append('&') "&Namespace=AWS%2FEC2" +
.append("MetricName=CPUUtilization").append('&') "&Period=60" +
.append("Namespace=AWS%2FEC2").append('&') "&Signature=e0WyI%2FNm4hN2%2BMEm1mjRUzsvgvMCdFXbVJWi4ORpwic%3D" +
.append("Period=60").append('&') "&SignatureMethod=HmacSHA256" +
.append("Signature=e0WyI%2FNm4hN2%2BMEm1mjRUzsvgvMCdFXbVJWi4ORpwic%3D").append('&') "&SignatureVersion=2" +
.append("SignatureMethod=HmacSHA256").append('&') "&StartTime=1970-01-01T02%3A46%3A40Z" +
.append("SignatureVersion=2").append('&') "&Statistics.member.1=Maximum" +
.append("StartTime=1970-01-01T02%3A46%3A40Z").append('&') "&Statistics.member.2=Minimum" +
.append("Statistics.member.1=Maximum").append('&') "&Timestamp=2009-11-08T15%3A54%3A08.897Z" +
.append("Statistics.member.2=Minimum").append('&') "&Unit=Percent" +
.append("Timestamp=2009-11-08T15%3A54%3A08.897Z").append('&') "&Version=2010-08-01" +
.append("Unit=Percent").append('&') "&AWSAccessKeyId=identity",
.append("Version=2010-08-01").append('&') "application/x-www-form-urlencoded"))
.append("AWSAccessKeyId=identity").toString(), "application/x-www-form-urlencoded"))
.build(); .build();
HttpResponse getMetricStatisticsResponse = HttpResponse.builder().statusCode(200).payload( HttpResponse getMetricStatisticsResponse = HttpResponse.builder().statusCode(200).payload(
@ -236,7 +243,11 @@ public class MetricClientExpectTest extends BaseCloudWatchClientExpectTest {
clientWhenMetricsExist.getMetricClientForRegion(null).getMetricStatistics(stats, clientWhenMetricsExist.getMetricClientForRegion(null).getMetricStatistics(stats,
GetMetricStatisticsOptions.Builder.dimension(dimension1).dimension(dimension2)).toString(), GetMetricStatisticsOptions.Builder.dimension(dimension1).dimension(dimension2)).toString(),
// TODO: make an object for this // TODO: make an object for this
"GetMetricStatisticsResponse{label=CPUUtilization, datapoints=[Datapoint{timestamp=Thu Jan 15 16:00:00 PST 2009, customUnit=null, maximum=null, minimum=null, average=0.17777777777777778, sum=null, samples=9.0, unit=Percent}, Datapoint{timestamp=Thu Jan 15 16:01:00 PST 2009, customUnit=null, maximum=null, minimum=null, average=0.1, sum=null, samples=8.0, unit=Percent}]}"); "GetMetricStatisticsResponse{label=CPUUtilization, " +
"datapoints=[Datapoint{timestamp=Thu Jan 15 16:00:00 PST 2009, customUnit=null, maximum=null, " +
"minimum=null, average=0.17777777777777778, sum=null, samples=9.0, unit=Percent}, " +
"Datapoint{timestamp=Thu Jan 15 16:01:00 PST 2009, customUnit=null, maximum=null, minimum=null, " +
"average=0.1, sum=null, samples=8.0, unit=Percent}]}");
} }
} }

View File

@ -24,6 +24,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.Set; import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.jclouds.cloudwatch.domain.Datapoint; import org.jclouds.cloudwatch.domain.Datapoint;
import org.jclouds.cloudwatch.domain.Dimension; import org.jclouds.cloudwatch.domain.Dimension;
@ -32,14 +33,20 @@ import org.jclouds.cloudwatch.domain.GetMetricStatistics;
import org.jclouds.cloudwatch.domain.GetMetricStatisticsResponse; import org.jclouds.cloudwatch.domain.GetMetricStatisticsResponse;
import org.jclouds.cloudwatch.domain.ListMetricsResponse; import org.jclouds.cloudwatch.domain.ListMetricsResponse;
import org.jclouds.cloudwatch.domain.Metric; import org.jclouds.cloudwatch.domain.Metric;
import org.jclouds.cloudwatch.domain.MetricDatum;
import org.jclouds.cloudwatch.domain.Namespaces; import org.jclouds.cloudwatch.domain.Namespaces;
import org.jclouds.cloudwatch.domain.StatisticValues;
import org.jclouds.cloudwatch.domain.Statistics; import org.jclouds.cloudwatch.domain.Statistics;
import org.jclouds.cloudwatch.domain.Unit; import org.jclouds.cloudwatch.domain.Unit;
import org.jclouds.cloudwatch.internal.BaseCloudWatchClientLiveTest; import org.jclouds.cloudwatch.internal.BaseCloudWatchClientLiveTest;
import org.jclouds.cloudwatch.options.ListMetricsOptions; import org.jclouds.cloudwatch.options.ListMetricsOptions;
import org.jclouds.predicates.RetryablePredicate;
import org.testng.Assert;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
/** /**
* @author Jeremy Whitlock, Adrian Cole * @author Jeremy Whitlock, Adrian Cole
@ -47,6 +54,95 @@ import com.google.common.collect.ImmutableSet;
@Test(groups = "live", testName = "MetricClientLiveTest") @Test(groups = "live", testName = "MetricClientLiveTest")
public class MetricClientLiveTest extends BaseCloudWatchClientLiveTest { public class MetricClientLiveTest extends BaseCloudWatchClientLiveTest {
@Test
protected void testPutMetricData() throws Exception {
String metricName = "TestMetricName" + System.currentTimeMillis();
String namespace = "JCLOUDS/Test";
Date metricTimestamp = new Date();
// CloudWatch rounds metric timestamps down to the closest minute
Date metricTimestampInCloudWatch =
new Date(metricTimestamp.getTime() - (metricTimestamp.getTime() % (60 * 1000)));
StatisticValues ss = StatisticValues.builder()
.maximum(4.0)
.minimum(1.0)
.sampleCount(4.0)
.sum(10.0)
.build();
MetricDatum metricDatum = MetricDatum.builder()
.metricName(metricName + "_1")
.statisticValues(ss)
.dimension(new Dimension("BaseMetricName", metricName))
.dimension(new Dimension("TestDimension2", "TEST2"))
.unit(Unit.COUNT)
.timestamp(metricTimestamp)
.build();
MetricDatum metricDatum2 = MetricDatum.builder()
.metricName(metricName + "_2")
.dimension(new Dimension("BaseMetricName", metricName))
.unit(Unit.COUNT)
.timestamp(metricTimestamp)
.value(10.0)
.build();
client().putMetricData(ImmutableSet.of(metricDatum, metricDatum2), namespace);
ListMetricsOptions lmo = ListMetricsOptions.builder().namespace(namespace)
.dimension(new Dimension("BaseMetricName", metricName))
.build();
boolean success = new RetryablePredicate<ListMetricsOptions>(new Predicate<ListMetricsOptions>() {
@Override
public boolean apply(ListMetricsOptions options) {
return Iterables.size(client().listMetrics(options)) == 2;
}
}, 20, 1, TimeUnit.MINUTES).apply(lmo);
if (!success) {
Assert.fail("Unable to gather the created CloudWatch data within the time (20m) allotted.");
}
ListMetricsResponse lmr = client().listMetrics(lmo);
Date endTime = new Date(metricTimestampInCloudWatch.getTime() + (60 * 1000)); // Pad a minute just in case
Date startTime = new Date(metricTimestampInCloudWatch.getTime() - (60 * 1000)); // Pad a minute just in case
for (Metric m : lmr) {
GetMetricStatistics gms = GetMetricStatistics.builder()
.dimensions(m.getDimensions())
.namespace(namespace)
.metricName(m.getMetricName())
.endTime(endTime)
.statistic(Statistics.MAXIMUM)
.statistic(Statistics.MINIMUM)
.statistic(Statistics.SAMPLE_COUNT)
.statistic(Statistics.SUM)
.period(60)
.startTime(startTime)
.unit(Unit.COUNT)
.build();
GetMetricStatisticsResponse gmr = client().getMetricStatistics(gms);
Assert.assertEquals(1, Iterables.size(gmr));
Datapoint datapoint = gmr.iterator().next();
Assert.assertEquals(datapoint.getTimestamp(), metricTimestampInCloudWatch);
Assert.assertNull(datapoint.getCustomUnit());
Assert.assertEquals(Unit.COUNT, datapoint.getUnit());
Assert.assertNull(datapoint.getAverage());
if (m.getDimensions().size() == 1) {
Assert.assertEquals(10.0, datapoint.getMaximum());
Assert.assertEquals(10.0, datapoint.getMinimum());
Assert.assertEquals(10.0, datapoint.getSum());
Assert.assertEquals(1.0, datapoint.getSamples());
} else {
Assert.assertEquals(4.0, datapoint.getMaximum());
Assert.assertEquals(1.0, datapoint.getMinimum());
Assert.assertEquals(10.0, datapoint.getSum());
Assert.assertEquals(4.0, datapoint.getSamples());
}
}
}
// TODO: change this test to retrieve pre-seeded custom metrics // TODO: change this test to retrieve pre-seeded custom metrics
@Test @Test
protected void testGetMetricStatistics() { protected void testGetMetricStatistics() {

View File

@ -4,13 +4,13 @@
<member> <member>
<Timestamp>2009-01-16T00:00:00Z</Timestamp> <Timestamp>2009-01-16T00:00:00Z</Timestamp>
<Unit>Percent</Unit> <Unit>Percent</Unit>
<Samples>9.0</Samples> <SampleCount>9.0</SampleCount>
<Average>0.17777777777777778</Average> <Average>0.17777777777777778</Average>
</member> </member>
<member> <member>
<Timestamp>2009-01-16T00:01:00Z</Timestamp> <Timestamp>2009-01-16T00:01:00Z</Timestamp>
<Unit>Percent</Unit> <Unit>Percent</Unit>
<Samples>8.0</Samples> <SampleCount>8.0</SampleCount>
<Average>0.1</Average> <Average>0.1</Average>
</member> </member>
</Datapoints> </Datapoints>

View File

@ -50,12 +50,20 @@
<properties> <properties>
<test.deltacloud.endpoint>http://localhost:3001/api</test.deltacloud.endpoint> <test.deltacloud.endpoint>http://localhost:3001/api</test.deltacloud.endpoint>
<test.deltacloud.api-version>0.3.0</test.deltacloud.api-version> <test.deltacloud.api-version>0.3.0</test.deltacloud.api-version>
<test.deltacloud.build-version /> <test.deltacloud.build-version></test.deltacloud.build-version>
<test.deltacloud.identity>mockuser</test.deltacloud.identity> <test.deltacloud.identity>mockuser</test.deltacloud.identity>
<test.deltacloud.credential>mockpassword</test.deltacloud.credential> <test.deltacloud.credential>mockpassword</test.deltacloud.credential>
<test.deltacloud.image-id /> <test.deltacloud.image-id></test.deltacloud.image-id>
<test.deltacloud.image.login-user /> <test.deltacloud.image.login-user></test.deltacloud.image.login-user>
<test.deltacloud.image.authenticate-sudo /> <test.deltacloud.image.authenticate-sudo></test.deltacloud.image.authenticate-sudo>
<jclouds.osgi.export>org.jclouds.deltacloud*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>
org.jclouds.compute.internal;version="${project.version}",
org.jclouds.rest.internal;version="${project.version}",
org.jclouds*;version="${project.version}",
*
</jclouds.osgi.import>
</properties> </properties>
<dependencies> <dependencies>
<dependency> <dependency>
@ -125,25 +133,4 @@
</profile> </profile>
</profiles> </profiles>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>org.jclouds.deltacloud*;version="${project.version}"</Export-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>
</configuration>
</plugin>
</plugins>
</build>
</project> </project>

View File

@ -23,6 +23,7 @@ import javax.inject.Singleton;
import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.ImageBuilder; import org.jclouds.compute.domain.ImageBuilder;
import org.jclouds.compute.domain.Image.Status;
import com.google.common.base.Function; import com.google.common.base.Function;
@ -47,6 +48,7 @@ public class DeltacloudImageToImage implements Function<org.jclouds.deltacloud.d
builder.name(from.getName()); builder.name(from.getName());
builder.description(from.getDescription()); builder.description(from.getDescription());
builder.operatingSystem(imageToOperatingSystem.apply(from)); builder.operatingSystem(imageToOperatingSystem.apply(from));
builder.status(Status.AVAILABLE);
return builder.build(); return builder.build();
} }
} }

View File

@ -34,8 +34,8 @@ import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadataBuilder; import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.OperatingSystem; import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.NodeMetadata.Status;
import org.jclouds.compute.functions.GroupNamingConvention; import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.deltacloud.domain.Instance; import org.jclouds.deltacloud.domain.Instance;
@ -54,11 +54,11 @@ import com.google.common.collect.Iterables;
@Singleton @Singleton
public class InstanceToNodeMetadata implements Function<Instance, NodeMetadata> { public class InstanceToNodeMetadata implements Function<Instance, NodeMetadata> {
public static final Map<Instance.State, NodeState> instanceToNodeState = ImmutableMap public static final Map<Instance.State, Status> instanceToNodeStatus = ImmutableMap
.<Instance.State, NodeState> builder().put(Instance.State.STOPPED, NodeState.SUSPENDED) .<Instance.State, Status> builder().put(Instance.State.STOPPED, Status.SUSPENDED)
.put(Instance.State.RUNNING, NodeState.RUNNING).put(Instance.State.PENDING, NodeState.PENDING) .put(Instance.State.RUNNING, Status.RUNNING).put(Instance.State.PENDING, Status.PENDING)
.put(Instance.State.UNRECOGNIZED, NodeState.UNRECOGNIZED).put(Instance.State.SHUTTING_DOWN, NodeState.PENDING) .put(Instance.State.UNRECOGNIZED, Status.UNRECOGNIZED).put(Instance.State.SHUTTING_DOWN, Status.PENDING)
.put(Instance.State.START, NodeState.PENDING).build(); .put(Instance.State.START, Status.PENDING).build();
@Resource @Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER) @Named(ComputeServiceConstants.COMPUTE_LOGGER)
@ -155,7 +155,7 @@ public class InstanceToNodeMetadata implements Function<Instance, NodeMetadata>
builder.imageId(from.getImage().toASCIIString()); builder.imageId(from.getImage().toASCIIString());
builder.operatingSystem(parseOperatingSystem(from)); builder.operatingSystem(parseOperatingSystem(from));
builder.hardware(parseHardware(from)); builder.hardware(parseHardware(from));
builder.state(instanceToNodeState.get(from.getState())); builder.status(instanceToNodeStatus.get(from.getState()));
builder.publicAddresses(from.getPublicAddresses()); builder.publicAddresses(from.getPublicAddresses());
builder.privateAddresses(from.getPrivateAddresses()); builder.privateAddresses(from.getPrivateAddresses());
return builder.build(); return builder.build();

Some files were not shown because too many files have changed in this diff Show More