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;
import static org.jclouds.compute.util.ComputeServiceUtils.formatStatus;
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.createTemplateFromElement;
@ -253,8 +254,7 @@ public class ComputeTask extends Task {
NodeMetadata metadata = node instanceof NodeMetadata ? NodeMetadata.class.cast(node) : computeService
.getNodeMetadata(node.getId());
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
.getState(), ComputeTaskUtils.ipOrEmptyString(metadata.getPublicAddresses()),
metadata.getProviderId(), metadata.getName(), metadata.getGroup(), metadata.getLocation(), formatStatus(metadata), ComputeTaskUtils.ipOrEmptyString(metadata.getPublicAddresses()),
ipOrEmptyString(metadata.getPrivateAddresses()), metadata.getHardware()));
}

View File

@ -39,6 +39,9 @@
<test.atmos.build-version />
<test.atmos.identity>FIXME</test.atmos.identity>
<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>
<dependencies>
@ -108,21 +111,5 @@
</build>
</profile>
</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>

View File

@ -35,7 +35,14 @@
<properties>
<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>
<dependencies>
<dependency>
@ -105,25 +112,4 @@
</profile>
</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>

View File

@ -36,9 +36,9 @@ import org.jclouds.byon.Node;
import org.jclouds.collect.Memoized;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.NodeMetadata.Status;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location;
@ -90,7 +90,7 @@ public class NodeToNodeMetadata implements Function<Node, NodeMetadata> {
builder.operatingSystem(OperatingSystem.builder().arch(from.getOsArch()).family(
OsFamily.fromValue(from.getOsFamily())).description(from.getOsDescription())
.version(from.getOsVersion()).build());
builder.state(NodeState.RUNNING);
builder.status(Status.RUNNING);
builder.publicAddresses(ImmutableSet.<String> of(from.getHostname()));
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.ImmutableSet.Builder;
import com.google.common.util.concurrent.UncheckedExecutionException;
/**
*
* @author Adrian Cole
@ -118,6 +117,11 @@ public class BYONComputeServiceAdapter implements JCloudsNativeComputeServiceAda
return node != null ? converter.apply(node) : null;
}
@Override
public Image getImage(final String id) {
throw new UnsupportedOperationException();
}
@Override
public void destroyNode(final String id) {
throw new UnsupportedOperationException();

View File

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

View File

@ -39,6 +39,12 @@
<test.cloudfiles.build-version />
<test.cloudfiles.identity>${test.rackspace.identity}</test.cloudfiles.identity>
<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>
<dependencies>
@ -123,25 +129,5 @@
</profile>
</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>

View File

@ -18,19 +18,15 @@
*/
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.util.Properties;
import org.jclouds.apis.ApiMetadata;
import org.jclouds.blobstore.BlobStoreContext;
import org.jclouds.cloudfiles.blobstore.config.CloudFilesBlobStoreContextModule;
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.internal.BaseRestApiMetadata;
import com.google.common.collect.ImmutableSet;
import com.google.common.reflect.TypeToken;
@ -41,9 +37,10 @@ import com.google.inject.Module;
*
* @author Adrian Cole
*/
public class CloudFilesApiMetadata extends BaseRestApiMetadata {
public class CloudFilesApiMetadata extends SwiftApiMetadata {
/** 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>>() {
private static final long serialVersionUID = -5070937833892503232L;
@ -65,28 +62,25 @@ public class CloudFilesApiMetadata extends BaseRestApiMetadata {
protected CloudFilesApiMetadata(Builder builder) {
super(builder);
}
public static Properties defaultProperties() {
Properties properties = BaseRestApiMetadata.defaultProperties();
properties.setProperty(PROPERTY_REGIONS, "DEFAULT");
properties.setProperty(PROPERTY_USER_METADATA_PREFIX, "X-Object-Meta-");
Properties properties = SwiftApiMetadata.defaultProperties();
return properties;
}
public static class Builder extends BaseRestApiMetadata.Builder {
protected Builder() {
public static class Builder extends SwiftApiMetadata.Builder {
protected Builder(){
super(CloudFilesClient.class, CloudFilesAsyncClient.class);
id("cloudfiles")
.name("Rackspace Cloud Files API")
.identityName("Username")
.credentialName("API Key")
.documentation(URI.create("http://docs.rackspacecloud.com/files/api/v1/cfdevguide_d5/content/ch01.html"))
.version(OpenStackAuthAsyncClient.VERSION)
.defaultProperties(CloudFilesApiMetadata.defaultProperties())
.view(TypeToken.of(BlobStoreContext.class))
.defaultModules(ImmutableSet.<Class<? extends Module>>of(CloudFilesRestClientModule.class, CloudFilesBlobStoreContextModule.class));
.context(CONTEXT_TOKEN)
.defaultModules(ImmutableSet.<Class<? extends Module>>of(StorageAndCDNManagementEndpointModule.class, CloudFilesRestClientModule.class, CloudFilesBlobStoreContextModule.class));
}
@Override
public CloudFilesApiMetadata build() {
return new CloudFilesApiMetadata(this);
@ -98,4 +92,5 @@ public class CloudFilesApiMetadata extends BaseRestApiMetadata {
return this;
}
}
}

View File

@ -27,77 +27,51 @@ import javax.inject.Singleton;
import org.jclouds.cloudfiles.CDNManagement;
import org.jclouds.cloudfiles.CloudFilesAsyncClient;
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.openstack.keystone.v1_1.config.AuthenticationServiceModule;
import org.jclouds.openstack.swift.CommonSwiftAsyncClient;
import org.jclouds.openstack.swift.CommonSwiftClient;
import org.jclouds.openstack.swift.Storage;
import org.jclouds.openstack.swift.config.SwiftObjectModule;
import org.jclouds.openstack.swift.handlers.ParseSwiftErrorFromHttpResponse;
import org.jclouds.openstack.swift.config.SwiftRestClientModule;
import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.annotations.ApiVersion;
import org.jclouds.rest.config.RestClientModule;
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.Scopes;
/**
*
* @author Adrian Cole
*/
@ConfiguresRestClient
public class CloudFilesRestClientModule extends RestClientModule<CloudFilesClient, CloudFilesAsyncClient> {
@Provides
@Singleton
CommonSwiftClient provideCommonSwiftClient(CloudFilesClient in) {
return in;
public class CloudFilesRestClientModule extends SwiftRestClientModule<CloudFilesClient, CloudFilesAsyncClient> {
public CloudFilesRestClientModule() {
super(TypeToken.of(CloudFilesClient.class), TypeToken.of(CloudFilesAsyncClient.class), ImmutableMap
.<Class<?>, Class<?>> of());
}
@Provides
@Singleton
CommonSwiftAsyncClient provideCommonSwiftClient(CloudFilesAsyncClient in) {
return in;
protected void bindResolvedClientsToCommonSwift() {
bind(CommonSwiftClient.class).to(CloudFilesClient.class).in(Scopes.SINGLETON);
bind(CommonSwiftAsyncClient.class).to(CloudFilesAsyncClient.class).in(Scopes.SINGLETON);
}
@Override
protected void configure() {
install(new SwiftObjectModule());
bind(DateAdapter.class).to(Iso8601DateAdapter.class);
super.configure();
}
public static class StorageAndCDNManagementEndpointModule extends AuthenticationServiceModule {
@Provides
@Singleton
@CDNManagement
protected Supplier<URI> provideCDNUrl(RegionIdToURISupplier.Factory factory, @ApiVersion String apiVersion) {
return getLastValueInMap(factory.createForApiTypeAndVersion("cloudFilesCDN", apiVersion));
}
@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());
}
@Provides
@Singleton
@CDNManagement
protected Supplier<URI> provideCDNUrl(RegionIdToURISupplier.Factory factory, @ApiVersion String apiVersion) {
return getLastValueInMap(factory.createForApiTypeAndVersion("cloudFilesCDN", apiVersion));
}
@Provides
@Singleton
@Storage
protected Supplier<URI> provideStorageUrl(RegionIdToURISupplier.Factory factory, @ApiVersion String apiVersion) {
return getLastValueInMap(factory.createForApiTypeAndVersion("cloudFiles", apiVersion));
@Provides
@Singleton
@Storage
protected Supplier<URI> provideStorageUrl(RegionIdToURISupplier.Factory factory, @ApiVersion String apiVersion) {
return getLastValueInMap(factory.createForApiTypeAndVersion("cloudFiles", apiVersion));
}
}
}

View File

@ -39,7 +39,10 @@
<test.cloudloadbalancers.build-version />
<test.cloudloadbalancers.identity>${test.rackspace.identity}</test.cloudloadbalancers.identity>
<test.cloudloadbalancers.credential>${test.rackspace.credential}</test.cloudloadbalancers.credential>
</properties>
<jclouds.osgi.export>org.jclouds.cloudloadbalancers*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>org.jclouds*;version="${project.version}",*</jclouds.osgi.import>
</properties>
<dependencies>
<dependency>
<groupId>org.jclouds</groupId>
@ -111,19 +114,4 @@
</profile>
</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>

View File

@ -25,7 +25,6 @@ import org.jclouds.apis.ApiMetadata;
import org.jclouds.cloudloadbalancers.config.CloudLoadBalancersRestClientModule;
import org.jclouds.cloudloadbalancers.loadbalancer.config.CloudLoadBalancersLoadBalancerContextModule;
import org.jclouds.loadbalancer.LoadBalancerServiceContext;
import org.jclouds.openstack.OpenStackAuthAsyncClient;
import org.jclouds.rest.RestContext;
import org.jclouds.rest.internal.BaseRestApiMetadata;
@ -75,7 +74,7 @@ public class CloudLoadBalancersApiMetadata extends BaseRestApiMetadata {
.identityName("Username")
.credentialName("API Key")
.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")
.defaultProperties(CloudLoadBalancersApiMetadata.defaultProperties())
.view(TypeToken.of(LoadBalancerServiceContext.class))

View File

@ -37,12 +37,19 @@
<properties>
<test.cloudservers.endpoint>https://auth.api.rackspacecloud.com</test.cloudservers.endpoint>
<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.credential>${test.rackspace.credential}</test.cloudservers.credential>
<test.cloudservers.image-id />
<test.cloudservers.image.login-user />
<test.cloudservers.image.authenticate-sudo />
<test.cloudservers.image-id></test.cloudservers.image-id>
<test.cloudservers.image.login-user></test.cloudservers.image.login-user>
<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>
<dependencies>
@ -126,26 +133,5 @@
</profile>
</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>

View File

@ -25,7 +25,6 @@ import org.jclouds.apis.ApiMetadata;
import org.jclouds.cloudservers.compute.config.CloudServersComputeServiceContextModule;
import org.jclouds.cloudservers.config.CloudServersRestClientModule;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.openstack.OpenStackAuthAsyncClient;
import org.jclouds.rest.RestContext;
import org.jclouds.rest.internal.BaseRestApiMetadata;
@ -74,7 +73,7 @@ public class CloudServersApiMetadata extends BaseRestApiMetadata {
.identityName("Username")
.credentialName("API Key")
.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")
.defaultProperties(CloudServersApiMetadata.defaultProperties())
.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.strategy.CloudServersComputeServiceAdapter;
import org.jclouds.cloudservers.domain.Flavor;
import org.jclouds.cloudservers.domain.ImageStatus;
import org.jclouds.cloudservers.domain.Server;
import org.jclouds.cloudservers.domain.ServerStatus;
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.Image;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.extensions.ImageExtension;
import org.jclouds.compute.internal.BaseComputeService;
@ -93,36 +93,54 @@ public class CloudServersComputeServiceContextModule extends
}
@VisibleForTesting
public static final Map<ServerStatus, NodeState> serverToNodeState = ImmutableMap
.<ServerStatus, NodeState> builder().put(ServerStatus.ACTIVE, NodeState.RUNNING)//
.put(ServerStatus.SUSPENDED, NodeState.SUSPENDED)//
.put(ServerStatus.DELETED, NodeState.TERMINATED)//
.put(ServerStatus.QUEUE_RESIZE, NodeState.PENDING)//
.put(ServerStatus.PREP_RESIZE, NodeState.PENDING)//
.put(ServerStatus.RESIZE, NodeState.PENDING)//
.put(ServerStatus.VERIFY_RESIZE, NodeState.PENDING)//
.put(ServerStatus.QUEUE_MOVE, NodeState.PENDING)//
.put(ServerStatus.PREP_MOVE, NodeState.PENDING)//
.put(ServerStatus.MOVE, NodeState.PENDING)//
.put(ServerStatus.VERIFY_MOVE, NodeState.PENDING)//
.put(ServerStatus.RESCUE, NodeState.PENDING)//
.put(ServerStatus.ERROR, NodeState.ERROR)//
.put(ServerStatus.BUILD, NodeState.PENDING)//
.put(ServerStatus.RESTORING, NodeState.PENDING)//
.put(ServerStatus.PASSWORD, NodeState.PENDING)//
.put(ServerStatus.REBUILD, NodeState.PENDING)//
.put(ServerStatus.DELETE_IP, NodeState.PENDING)//
.put(ServerStatus.SHARE_IP_NO_CONFIG, NodeState.PENDING)//
.put(ServerStatus.SHARE_IP, NodeState.PENDING)//
.put(ServerStatus.REBOOT, NodeState.PENDING)//
.put(ServerStatus.HARD_REBOOT, NodeState.PENDING)//
.put(ServerStatus.UNKNOWN, NodeState.UNRECOGNIZED)//
.put(ServerStatus.UNRECOGNIZED, NodeState.UNRECOGNIZED).build();
public static final Map<ServerStatus, NodeMetadata.Status> toPortableNodeStatus = ImmutableMap
.<ServerStatus, NodeMetadata.Status> builder()
.put(ServerStatus.ACTIVE, NodeMetadata.Status.RUNNING)
.put(ServerStatus.SUSPENDED, NodeMetadata.Status.SUSPENDED)
.put(ServerStatus.DELETED, NodeMetadata.Status.TERMINATED)
.put(ServerStatus.QUEUE_RESIZE, NodeMetadata.Status.PENDING)
.put(ServerStatus.PREP_RESIZE, NodeMetadata.Status.PENDING)
.put(ServerStatus.RESIZE, NodeMetadata.Status.PENDING)
.put(ServerStatus.VERIFY_RESIZE, NodeMetadata.Status.PENDING)
.put(ServerStatus.QUEUE_MOVE, NodeMetadata.Status.PENDING)
.put(ServerStatus.PREP_MOVE, NodeMetadata.Status.PENDING)
.put(ServerStatus.MOVE, NodeMetadata.Status.PENDING)
.put(ServerStatus.VERIFY_MOVE, NodeMetadata.Status.PENDING)
.put(ServerStatus.RESCUE, NodeMetadata.Status.PENDING)
.put(ServerStatus.ERROR, NodeMetadata.Status.ERROR)
.put(ServerStatus.BUILD, NodeMetadata.Status.PENDING)
.put(ServerStatus.RESTORING, NodeMetadata.Status.PENDING)
.put(ServerStatus.PASSWORD, NodeMetadata.Status.PENDING)
.put(ServerStatus.REBUILD, NodeMetadata.Status.PENDING)
.put(ServerStatus.DELETE_IP, NodeMetadata.Status.PENDING)
.put(ServerStatus.SHARE_IP_NO_CONFIG, NodeMetadata.Status.PENDING)
.put(ServerStatus.SHARE_IP, NodeMetadata.Status.PENDING)
.put(ServerStatus.REBOOT, NodeMetadata.Status.PENDING)
.put(ServerStatus.HARD_REBOOT, NodeMetadata.Status.PENDING)
.put(ServerStatus.UNKNOWN, NodeMetadata.Status.UNRECOGNIZED)
.put(ServerStatus.UNRECOGNIZED, NodeMetadata.Status.UNRECOGNIZED).build();
@Singleton
@Provides
Map<ServerStatus, NodeState> provideServerToNodeState() {
return serverToNodeState;
Map<ServerStatus, NodeMetadata.Status> toPortableNodeStatus() {
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

View File

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

View File

@ -18,12 +18,16 @@
*/
package org.jclouds.cloudservers.compute.functions;
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.cloudservers.domain.ImageStatus;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.ImageBuilder;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.Image.Status;
import com.google.common.base.Function;
@ -33,13 +37,15 @@ import com.google.common.base.Function;
*/
@Singleton
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;
@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;
}
public Image apply(org.jclouds.cloudservers.domain.Image from) {
ImageBuilder builder = new ImageBuilder();
builder.ids(from.getId() + "");
@ -47,6 +53,7 @@ public class CloudServersImageToImage implements Function<org.jclouds.cloudserve
builder.description(from.getName());
builder.version(from.getUpdated().getTime() + "");
builder.operatingSystem(imageToOs.apply(from));
builder.status(toPortableImageStatus.get(from.getStatus()));
Image image = builder.build();
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.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.NodeMetadata.Status;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.Location;
@ -61,7 +61,7 @@ public class ServerToNodeMetadata implements Function<Server, NodeMetadata> {
protected Logger logger = Logger.NULL;
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 Hardware>> hardwares;
protected final GroupNamingConvention nodeNamingConvention;
@ -93,12 +93,12 @@ public class ServerToNodeMetadata implements Function<Server, NodeMetadata> {
}
@Inject
ServerToNodeMetadata(Map<ServerStatus, NodeState> serverStateToNodeState,
ServerToNodeMetadata(Map<ServerStatus, Status> serverStateToNodeStatus,
@Memoized Supplier<Set<? extends Image>> images, Supplier<Location> location,
@Memoized Supplier<Set<? extends Hardware>> hardwares,
GroupNamingConvention.Factory namingConvention) {
this.nodeNamingConvention = checkNotNull(namingConvention, "namingConvention").createWithoutPrefix();
this.serverToNodeState = checkNotNull(serverStateToNodeState, "serverStateToNodeState");
this.serverToNodeStatus = checkNotNull(serverStateToNodeStatus, "serverStateToNodeStatus");
this.images = checkNotNull(images, "images");
this.location = checkNotNull(location, "location");
this.hardwares = checkNotNull(hardwares, "hardwares");
@ -117,7 +117,7 @@ public class ServerToNodeMetadata implements Function<Server, NodeMetadata> {
builder.imageId(from.getImageId() + "");
builder.operatingSystem(parseOperatingSystem(from));
builder.hardware(parseHardware(from));
builder.state(serverToNodeState.get(from.getStatus()));
builder.status(serverToNodeStatus.get(from.getStatus()));
builder.publicAddresses(from.getAddresses().getPublicAddresses());
builder.privateAddresses(from.getAddresses().getPrivateAddresses());
return builder.build();

View File

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

View File

@ -30,7 +30,7 @@ public class CloudServersComputeServiceContextModuleTest {
public void testAllStatusCovered() {
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 java.net.UnknownHostException;
import org.jclouds.cloudservers.compute.config.CloudServersComputeServiceContextModule;
import org.jclouds.cloudservers.functions.ParseImageFromJsonResponseTest;
import org.jclouds.compute.config.BaseComputeServiceContextModule;
import org.jclouds.compute.domain.Image;
@ -38,23 +37,27 @@ import com.google.inject.Guice;
/**
* @author Adrian Cole
*/
@Test(groups = "unit")
@Test(groups = "unit", testName = "CloudServersImageToImageTest")
public class CloudServersImageToImageTest {
@Test
public void testApplyWhereImageNotFound() throws UnknownHostException {
assertEquals(convertImage(), new ImageBuilder().name("CentOS 5.2").operatingSystem(
public void test() {
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(
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() {
org.jclouds.cloudservers.domain.Image image = ParseImageFromJsonResponseTest.parseImage();
CloudServersImageToImage parser = new CloudServersImageToImage(new CloudServersImageToOperatingSystem(
new BaseComputeServiceContextModule() {
}.provideOsVersionMap(new ComputeServiceConstants.ReferenceData(), Guice
.createInjector(new GsonModule()).getInstance(Json.class))));
CloudServersImageToImage parser = new CloudServersImageToImage(
CloudServersComputeServiceContextModule.toPortableImageStatus, new CloudServersImageToOperatingSystem(
new BaseComputeServiceContextModule() {
}.provideOsVersionMap(new ComputeServiceConstants.ReferenceData(), Guice.createInjector(
new GsonModule()).getInstance(Json.class))));
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.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.Processor;
import org.jclouds.compute.domain.Volume;
import org.jclouds.compute.domain.VolumeBuilder;
import org.jclouds.compute.domain.NodeMetadata.Status;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationBuilder;
@ -60,12 +60,12 @@ public class ServerToNodeMetadataTest {
@Test
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.Hardware> hardwares = ImmutableSet.of();
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);
NodeMetadata metadata = parser.apply(server);
@ -73,7 +73,7 @@ public class ServerToNodeMetadataTest {
assertEquals(
metadata,
new NodeMetadataBuilder()
.state(NodeState.PENDING)
.status(Status.PENDING)
.publicAddresses(ImmutableSet.of("67.23.10.132", "67.23.10.131"))
.privateAddresses(ImmutableSet.of("10.176.42.16"))
.imageId("2")
@ -91,13 +91,13 @@ public class ServerToNodeMetadataTest {
@Test
public void testApplyWhereImageFoundAndHardwareNotFound() {
Map<ServerStatus, NodeState> serverStateToNodeState = CloudServersComputeServiceContextModule.serverToNodeState;
Map<ServerStatus, Status> serverStateToNodeStatus = CloudServersComputeServiceContextModule.toPortableNodeStatus;
org.jclouds.compute.domain.Image jcImage = CloudServersImageToImageTest.convertImage();
Set<org.jclouds.compute.domain.Image> images = ImmutableSet.of(jcImage);
Set<org.jclouds.compute.domain.Hardware> hardwares = ImmutableSet.of();
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);
NodeMetadata metadata = parser.apply(server);
@ -105,7 +105,7 @@ public class ServerToNodeMetadataTest {
assertEquals(
metadata,
new NodeMetadataBuilder()
.state(NodeState.PENDING)
.status(Status.PENDING)
.publicAddresses(ImmutableSet.of("67.23.10.132", "67.23.10.131"))
.privateAddresses(ImmutableSet.of("10.176.42.16"))
.imageId("2")
@ -126,12 +126,12 @@ public class ServerToNodeMetadataTest {
@Test
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.Hardware> hardwares = ImmutableSet.of(FlavorToHardwareTest.convertFlavor());
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);
NodeMetadata metadata = parser.apply(server);
@ -139,7 +139,7 @@ public class ServerToNodeMetadataTest {
assertEquals(
metadata,
new NodeMetadataBuilder()
.state(NodeState.PENDING)
.status(Status.PENDING)
.publicAddresses(ImmutableSet.of("67.23.10.132", "67.23.10.131"))
.privateAddresses(ImmutableSet.of("10.176.42.16"))
.imageId("2")

View File

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

View File

@ -36,12 +36,20 @@
<properties>
<test.cloudsigma.endpoint>https://api.cloudsigma.com</test.cloudsigma.endpoint>
<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.credential>FIXME</test.cloudsigma.credential>
<test.cloudsigma.image-id>f3c7c665-cd54-4a78-8fd2-7ec2f028cf29</test.cloudsigma.image-id>
<test.cloudsigma.image.login-user />
<test.cloudsigma.image.authenticate-sudo />
<test.cloudsigma.image.login-user></test.cloudsigma.image.login-user>
<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>
<dependencies>
@ -112,25 +120,4 @@
</profile>
</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>

View File

@ -210,7 +210,12 @@ public class CloudSigmaComputeServiceAdapter implements
public ServerInfo getNode(String id) {
return client.getServerInfo(id);
}
@Override
public DriveInfo getImage(String id) {
return client.getDriveInfo(id);
}
@Override
public void destroyNode(String 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.OperatingSystem;
import org.jclouds.compute.domain.OsFamilyVersion64Bit;
import org.jclouds.compute.domain.Image.Status;
import org.jclouds.compute.domain.OperatingSystem.Builder;
import org.jclouds.domain.Location;
@ -61,6 +62,6 @@ public class PreinstalledDiskToImage implements Function<DriveInfo, Image> {
return new ImageBuilder().ids(drive.getUuid())
.userMetadata(ImmutableMap.<String, String> of("size", drive.getSize() / 1024 / 1024 / 1024 + ""))
.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.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.Processor;
import org.jclouds.compute.domain.Volume;
import org.jclouds.compute.domain.VolumeBuilder;
import org.jclouds.compute.domain.NodeMetadata.Status;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.domain.Location;
import org.jclouds.logging.Logger;
@ -60,13 +60,13 @@ import com.google.common.util.concurrent.UncheckedExecutionException;
*/
@Singleton
public class ServerInfoToNodeMetadata implements Function<ServerInfo, NodeMetadata> {
public static final Map<ServerStatus, NodeState> serverStatusToNodeState = ImmutableMap
.<ServerStatus, NodeState> builder().put(ServerStatus.ACTIVE, NodeState.RUNNING)//
.put(ServerStatus.STOPPED, NodeState.SUSPENDED)//
.put(ServerStatus.PAUSED, NodeState.SUSPENDED)//
.put(ServerStatus.DUMPED, NodeState.PENDING)//
.put(ServerStatus.DEAD, NodeState.TERMINATED)//
.put(ServerStatus.UNRECOGNIZED, NodeState.UNRECOGNIZED)//
public static final Map<ServerStatus, Status> serverStatusToNodeStatus = ImmutableMap
.<ServerStatus, Status> builder().put(ServerStatus.ACTIVE, Status.RUNNING)//
.put(ServerStatus.STOPPED, Status.SUSPENDED)//
.put(ServerStatus.PAUSED, Status.SUSPENDED)//
.put(ServerStatus.DUMPED, Status.PENDING)//
.put(ServerStatus.DEAD, Status.TERMINATED)//
.put(ServerStatus.UNRECOGNIZED, Status.UNRECOGNIZED)//
.build();
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")
.processors(ImmutableList.of(new Processor(1, from.getCpu()))).ram(from.getMem())
.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.privateAddresses(ImmutableSet.<String> of());
return builder.build();

View File

@ -50,16 +50,24 @@
<properties>
<test.cloudstack.endpoint>http://localhost:8080/client/api</test.cloudstack.endpoint>
<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.credential>FIXME_secretKey</test.cloudstack.credential>
<test.cloudstack.domainAdminIdentity />
<test.cloudstack.domainAdminCredential />
<test.cloudstack.globalAdminIdentity />
<test.cloudstack.globalAdminCredential />
<test.cloudstack.image-id />
<test.cloudstack.image.login-user />
<test.cloudstack.image.authenticate-sudo />
<test.cloudstack.domainAdminIdentity></test.cloudstack.domainAdminIdentity>
<test.cloudstack.domainAdminCredential></test.cloudstack.domainAdminCredential>
<test.cloudstack.globalAdminIdentity></test.cloudstack.globalAdminIdentity>
<test.cloudstack.globalAdminCredential></test.cloudstack.globalAdminCredential>
<test.cloudstack.image-id></test.cloudstack.image-id>
<test.cloudstack.image.login-user></test.cloudstack.image.login-user>
<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>
<dependencies>
<dependency>
@ -146,24 +154,4 @@
</profile>
</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>

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.CloudStackComputeServiceAdapter;
import org.jclouds.cloudstack.compute.strategy.OptionsConverter;
import org.jclouds.cloudstack.domain.FirewallRule;
import org.jclouds.cloudstack.domain.IPForwardingRule;
import org.jclouds.cloudstack.domain.Network;
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.Zone;
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.ZoneIdToZone;
import org.jclouds.cloudstack.options.ListFirewallRulesOptions;
import org.jclouds.cloudstack.predicates.JobComplete;
import org.jclouds.cloudstack.suppliers.GetCurrentUser;
import org.jclouds.cloudstack.suppliers.NetworksForCurrentUser;
@ -108,6 +112,8 @@ public class CloudStackComputeServiceContextModule extends
install(new FactoryModuleBuilder().build(StaticNATVirtualMachineInNetwork.Factory.class));
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>>() {
}).to(ZoneIdToZone.class);
bind(new TypeLiteral<Supplier<LoadingCache<String, Zone>>>() {
@ -184,24 +190,12 @@ public class CloudStackComputeServiceContextModule extends
return CacheBuilder.newBuilder().build(getIPForwardingRules);
}
@Provides
@Singleton
public static class GetIPForwardingRulesByVirtualMachine extends CacheLoader<String, Set<IPForwardingRule>> {
private final CloudStackClient client;
@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();
}
protected LoadingCache<String, Set<FirewallRule>> getFirewallRulesByVirtualMachine(
CacheLoader<String, Set<FirewallRule>> getFirewallRules) {
return CacheBuilder.newBuilder().build(getFirewallRules);
}
@Provides

View File

@ -31,6 +31,7 @@ import org.jclouds.collect.Memoized;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.ImageBuilder;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.Image.Status;
import org.jclouds.domain.Location;
import com.google.common.base.Function;
@ -62,6 +63,8 @@ public class TemplateToImage implements Function<Template, Image> {
if (!template.isCrossZones())
builder.location(findLocationForTemplate.apply(template));
//TODO: implement status mapping!!!
builder.status(Status.AVAILABLE);
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.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.Processor;
import org.jclouds.compute.domain.NodeMetadata.Status;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.domain.Location;
import org.jclouds.rest.ResourceNotFoundException;
@ -64,17 +64,17 @@ import com.google.common.util.concurrent.UncheckedExecutionException;
@Singleton
public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, NodeMetadata> {
public static final Map<VirtualMachine.State, NodeState> vmStateToNodeState = ImmutableMap
.<VirtualMachine.State, NodeState> builder().put(VirtualMachine.State.STARTING, NodeState.PENDING)
.put(VirtualMachine.State.RUNNING, NodeState.RUNNING).put(VirtualMachine.State.STOPPING, NodeState.PENDING)
.put(VirtualMachine.State.STOPPED, NodeState.SUSPENDED)
.put(VirtualMachine.State.DESTROYED, NodeState.TERMINATED)
.put(VirtualMachine.State.EXPUNGING, NodeState.TERMINATED)
.put(VirtualMachine.State.MIGRATING, NodeState.PENDING).put(VirtualMachine.State.ERROR, NodeState.ERROR)
.put(VirtualMachine.State.UNKNOWN, NodeState.UNRECOGNIZED)
public static final Map<VirtualMachine.State, Status> vmStateToNodeStatus = ImmutableMap
.<VirtualMachine.State, Status> builder().put(VirtualMachine.State.STARTING, Status.PENDING)
.put(VirtualMachine.State.RUNNING, Status.RUNNING).put(VirtualMachine.State.STOPPING, Status.PENDING)
.put(VirtualMachine.State.STOPPED, Status.SUSPENDED)
.put(VirtualMachine.State.DESTROYED, Status.TERMINATED)
.put(VirtualMachine.State.EXPUNGING, Status.TERMINATED)
.put(VirtualMachine.State.MIGRATING, Status.PENDING).put(VirtualMachine.State.ERROR, Status.ERROR)
.put(VirtualMachine.State.UNKNOWN, Status.UNRECOGNIZED)
// TODO: is this really a state?
.put(VirtualMachine.State.SHUTDOWNED, NodeState.PENDING)
.put(VirtualMachine.State.UNRECOGNIZED, NodeState.UNRECOGNIZED).build();
.put(VirtualMachine.State.SHUTDOWNED, Status.PENDING)
.put(VirtualMachine.State.UNRECOGNIZED, Status.UNRECOGNIZED).build();
private final FindLocationForVirtualMachine findLocationForVirtualMachine;
private final FindImageForVirtualMachine findImageForVirtualMachine;
@ -123,7 +123,7 @@ public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, No
.hypervisor(from.getHypervisor())//
.build());
builder.state(vmStateToNodeState.get(from.getState()));
builder.status(vmStateToNodeStatus.get(from.getState()));
Set<String> publicAddresses = newHashSet(), privateAddresses = newHashSet();
if (from.getIPAddress() != null) {
@ -134,6 +134,9 @@ public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, No
publicAddresses.add(from.getIPAddress());
}
}
if (from.getPublicIP() != null) {
publicAddresses.add(from.getPublicIP());
}
for (NIC nic : from.getNICs()) {
if (nic.getIPAddress() != null) {
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.Predicates.and;
import static com.google.common.base.Predicates.not;
import static com.google.common.collect.Iterables.filter;
import static org.jclouds.cloudstack.predicates.NetworkPredicates.defaultNetworkInZone;
import static org.jclouds.cloudstack.predicates.NetworkPredicates.supportsStaticNAT;
import static org.jclouds.cloudstack.predicates.NetworkPredicates.isIsolatedNetwork;
import java.util.Map;
@ -50,9 +52,12 @@ public class AdvancedNetworkOptionsConverter implements OptionsConverter {
checkArgument(!networks.isEmpty(), "please setup a network for zone: " + zoneId);
Network defaultNetworkInZone = Iterables.getFirst(filter(networks.values(), and(defaultNetworkInZone(zoneId), supportsStaticNAT())), null);
if(defaultNetworkInZone == null) {
throw new IllegalArgumentException("please choose a specific network in zone " + zoneId + ": " + networks);
defaultNetworkInZone = Iterables.getFirst(filter(networks.values(), isIsolatedNetwork()), null);
}
if (defaultNetworkInZone == null) {
throw new IllegalArgumentException("please choose a specific network in zone " + zoneId + ": " + networks);
} else {
options.networkId(defaultNetworkInZone.getId());
options.networkId(defaultNetworkInZone.getId());
}
}
return options;

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.checkState;
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 java.util.List;
@ -37,6 +40,8 @@ import javax.inject.Singleton;
import org.jclouds.cloudstack.CloudStackClient;
import org.jclouds.cloudstack.compute.options.CloudStackTemplateOptions;
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.Network;
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.VirtualMachine;
import org.jclouds.cloudstack.domain.Zone;
import org.jclouds.cloudstack.functions.CreateFirewallRulesForIP;
import org.jclouds.cloudstack.functions.CreatePortForwardingRulesForIP;
import org.jclouds.cloudstack.functions.StaticNATVirtualMachineInNetwork;
import org.jclouds.cloudstack.functions.StaticNATVirtualMachineInNetwork.Factory;
import org.jclouds.cloudstack.options.DeployVirtualMachineOptions;
import org.jclouds.cloudstack.options.ListFirewallRulesOptions;
import org.jclouds.cloudstack.strategy.BlockUntilJobCompletesAndReturnResult;
import org.jclouds.collect.Memoized;
import org.jclouds.compute.ComputeService;
@ -70,11 +77,10 @@ import com.google.common.primitives.Ints;
/**
* defines the connection between the {@link CloudStackClient} implementation
* and the jclouds {@link ComputeService}
*
*/
@Singleton
public class CloudStackComputeServiceAdapter implements
ComputeServiceAdapter<VirtualMachine, ServiceOffering, Template, Zone> {
ComputeServiceAdapter<VirtualMachine, ServiceOffering, Template, Zone> {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
@ -86,6 +92,7 @@ public class CloudStackComputeServiceAdapter implements
private final BlockUntilJobCompletesAndReturnResult blockUntilJobCompletesAndReturnResult;
private final Factory staticNATVMInNetwork;
private final CreatePortForwardingRulesForIP setupPortForwardingRulesForIP;
private final CreateFirewallRulesForIP setupFirewallRulesForIP;
private final LoadingCache<String, Set<IPForwardingRule>> vmToRules;
private final Map<String, Credentials> credentialStore;
private final Map<NetworkType, ? extends OptionsConverter> optionsConverters;
@ -93,19 +100,23 @@ public class CloudStackComputeServiceAdapter implements
@Inject
public CloudStackComputeServiceAdapter(CloudStackClient client, Predicate<String> jobComplete,
@Memoized Supplier<Map<String, Network>> networkSupplier,
BlockUntilJobCompletesAndReturnResult blockUntilJobCompletesAndReturnResult,
StaticNATVirtualMachineInNetwork.Factory staticNATVMInNetwork,
CreatePortForwardingRulesForIP setupPortForwardingRulesForIP, LoadingCache<String, Set<IPForwardingRule>> vmToRules,
Map<String, Credentials> credentialStore, Map<NetworkType, ? extends OptionsConverter> optionsConverters,
Supplier<LoadingCache<String, Zone>> zoneIdToZone) {
@Memoized Supplier<Map<String, Network>> networkSupplier,
BlockUntilJobCompletesAndReturnResult blockUntilJobCompletesAndReturnResult,
StaticNATVirtualMachineInNetwork.Factory staticNATVMInNetwork,
CreatePortForwardingRulesForIP setupPortForwardingRulesForIP,
CreateFirewallRulesForIP setupFirewallRulesForIP,
LoadingCache<String, Set<IPForwardingRule>> vmToRules,
Map<String, Credentials> credentialStore,
Map<NetworkType, ? extends OptionsConverter> optionsConverters,
Supplier<LoadingCache<String, Zone>> zoneIdToZone) {
this.client = checkNotNull(client, "client");
this.jobComplete = checkNotNull(jobComplete, "jobComplete");
this.networkSupplier = checkNotNull(networkSupplier, "networkSupplier");
this.blockUntilJobCompletesAndReturnResult = checkNotNull(blockUntilJobCompletesAndReturnResult,
"blockUntilJobCompletesAndReturnResult");
"blockUntilJobCompletesAndReturnResult");
this.staticNATVMInNetwork = checkNotNull(staticNATVMInNetwork, "staticNATVMInNetwork");
this.setupPortForwardingRulesForIP = checkNotNull(setupPortForwardingRulesForIP, "setupPortForwardingRulesForIP");
this.setupFirewallRulesForIP = checkNotNull(setupFirewallRulesForIP, "setupFirewallRulesForIP");
this.vmToRules = checkNotNull(vmToRules, "vmToRules");
this.credentialStore = checkNotNull(credentialStore, "credentialStore");
this.optionsConverters = optionsConverters;
@ -114,12 +125,12 @@ public class CloudStackComputeServiceAdapter implements
@Override
public NodeAndInitialCredentials<VirtualMachine> createNodeWithGroupEncodedIntoName(String group, String name,
org.jclouds.compute.domain.Template template) {
org.jclouds.compute.domain.Template template) {
checkNotNull(template, "template was null");
checkNotNull(template.getOptions(), "template options was null");
checkArgument(template.getOptions().getClass().isAssignableFrom(CloudStackTemplateOptions.class),
"options class %s should have been assignable from CloudStackTemplateOptions", template.getOptions()
.getClass());
"options class %s should have been assignable from CloudStackTemplateOptions", template.getOptions()
.getClass());
Map<String, Network> networks = networkSupplier.get();
final String zoneId = template.getLocation().getId();
@ -132,8 +143,8 @@ public class CloudStackComputeServiceAdapter implements
CloudStackTemplateOptions templateOptions = template.getOptions().as(CloudStackTemplateOptions.class);
checkState(optionsConverters.containsKey(zone.getNetworkType()), "no options converter configured for network type %s",zone.getNetworkType());
DeployVirtualMachineOptions options = DeployVirtualMachineOptions.Builder.displayName(name).name(name);
checkState(optionsConverters.containsKey(zone.getNetworkType()), "no options converter configured for network type %s", zone.getNetworkType());
DeployVirtualMachineOptions options = displayName(name).name(name);
OptionsConverter optionsConverter = optionsConverters.get(zone.getNetworkType());
options = optionsConverter.apply(templateOptions, networks, zoneId, options);
@ -149,9 +160,9 @@ public class CloudStackComputeServiceAdapter implements
options.keyPair(templateOptions.getKeyPair());
if (templateOptions.getRunScript() != null) {
checkArgument(
credentialStore.containsKey("keypair#" + templateOptions.getKeyPair()),
"no private key configured for: %s; please use options.overrideLoginCredentialWith(rsa_private_text)",
templateOptions.getKeyPair());
credentialStore.containsKey("keypair#" + templateOptions.getKeyPair()),
"no private key configured for: %s; please use options.overrideLoginCredentialWith(rsa_private_text)",
templateOptions.getKeyPair());
}
}
@ -159,10 +170,11 @@ public class CloudStackComputeServiceAdapter implements
String serviceOfferingId = template.getHardware().getId();
logger.info("serviceOfferingId %s, templateId %s, zoneId %s, options %s%n", serviceOfferingId, templateId,
zoneId, options);
zoneId, options);
AsyncCreateResponse job = client.getVirtualMachineClient().deployVirtualMachineInZone(zoneId, serviceOfferingId,
templateId, options);
VirtualMachine vm = blockUntilJobCompletesAndReturnResult.<VirtualMachine> apply(job);
templateId, options);
VirtualMachine vm = blockUntilJobCompletesAndReturnResult.<VirtualMachine>apply(job);
logger.debug("--- virtualmachine: %s", vm);
LoginCredentials credentials = null;
if (vm.isPasswordEnabled()) {
assert vm.getPassword() != null : vm;
@ -171,15 +183,23 @@ public class CloudStackComputeServiceAdapter implements
credentials = LoginCredentials.fromCredentials(credentialStore.get("keypair#" + templateOptions.getKeyPair()));
}
if (templateOptions.shouldSetupStaticNat()) {
Capabilities capabilities = client.getConfigurationClient().listCapabilities();
// TODO: possibly not all network ids, do we want to do this
for (String networkId : options.getNetworkIds()) {
logger.debug(">> creating static NAT for virtualMachine(%s) in network(%s)", vm.getId(), networkId);
PublicIPAddress ip = staticNATVMInNetwork.create(networks.get(networkId)).apply(vm);
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());
logger.debug(">> setting up IP forwarding for IPAddress(%s) rules(%s)", ip.getId(), ports);
Set<IPForwardingRule> rules = setupPortForwardingRulesForIP.apply(ip, ports);
logger.trace("<< setup %d IP forwarding rules on IPAddress(%s)", rules.size(), ip.getId());
if (capabilities.getCloudStackVersion().startsWith("2")) {
logger.debug(">> setting up IP forwarding for IPAddress(%s) rules(%s)", ip.getId(), ports);
Set<IPForwardingRule> rules = setupPortForwardingRulesForIP.apply(ip, ports);
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);
@ -198,6 +218,11 @@ public class CloudStackComputeServiceAdapter implements
return filter(client.getTemplateClient().listTemplates(), isReady());
}
@Override
public Template getImage(String id) {
return get(client.getTemplateClient().listTemplates(id(id)), 0, null);
}
@Override
public Iterable<VirtualMachine> listNodes() {
return client.getVirtualMachineClient().listVirtualMachines();
@ -233,10 +258,13 @@ public class CloudStackComputeServiceAdapter implements
// 1) Delete IP forwarding rules associated with IP.
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);
// 3) Only after 1 and 2 release the IP address.
// 4) Only after 1 and 2 release the IP address.
disassociateIPAddresses(ipAddresses);
destroyVirtualMachine(virtualMachineId);
@ -282,7 +310,7 @@ public class CloudStackComputeServiceAdapter implements
Set<String> ipAddresses = Sets.newLinkedHashSet();
Set<IPForwardingRule> forwardingRules = client.getNATClient().getIPForwardingRulesForVirtualMachine(
virtualMachineId);
virtualMachineId);
for (IPForwardingRule rule : forwardingRules) {
if (!"Deleting".equals(rule.getState())) {
ipAddresses.add(rule.getIPAddressId());
@ -297,6 +325,26 @@ public class CloudStackComputeServiceAdapter implements
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) {
logger.debug(">> awaiting completion of jobs(%s)", 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.
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.
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.
UNKNOWN;

View File

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

View File

@ -55,7 +55,7 @@ public class PortForwardingRule implements Comparable<PortForwardingRule> {
// 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.
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.
UNKNOWN;

View File

@ -31,6 +31,67 @@ import com.google.gson.annotations.SerializedName;
* @author Adrian Cole
*/
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() {
return new Builder();
}
@ -48,7 +109,7 @@ public class Template implements Comparable<Template> {
private String OSTypeId;
private String name;
private Type type;
private String status;
private Status status;
private Format format;
private String hypervisor;
private Long size;
@ -129,7 +190,7 @@ public class Template implements Comparable<Template> {
return this;
}
public Builder status(String status) {
public Builder status(Status status) {
this.status = status;
return this;
}
@ -287,7 +348,7 @@ public class Template implements Comparable<Template> {
@SerializedName("templatetype")
private Type type;
//TODO: this should be a type
private String status;
private Status status;
private Format format;
private String hypervisor;
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,
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,
boolean extractable, boolean featured, boolean ispublic, boolean ready, boolean passwordEnabled, String jobId,
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;
}

View File

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

View File

@ -87,6 +87,19 @@ public interface FirewallAsyncClient {
ListenableFuture<AsyncCreateResponse> createFirewallRuleForIpAndProtocol(@QueryParam("ipaddressid") String ipAddressId,
@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
*/

View File

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

View File

@ -83,7 +83,6 @@ public interface NATAsyncClient {
@QueryParams(keys = { "command", "listAll" }, values = { "listIpForwardingRules", "true" })
@SelectJson("ipforwardingrule")
@Consumes(MediaType.APPLICATION_JSON)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<Set<IPForwardingRule>> getIPForwardingRulesForIPAddress(@QueryParam("ipaddressid") String id);
/**
@ -93,7 +92,6 @@ public interface NATAsyncClient {
@QueryParams(keys = { "command", "listAll" }, values = { "listIpForwardingRules", "true" })
@SelectJson("ipforwardingrule")
@Consumes(MediaType.APPLICATION_JSON)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<Set<IPForwardingRule>> getIPForwardingRulesForVirtualMachine(@QueryParam("virtualmachineid") String id);
/**
@ -133,7 +131,6 @@ public interface NATAsyncClient {
@QueryParams(keys = "command", values = "disableStaticNat")
@SelectJson("jobid")
@Consumes(MediaType.APPLICATION_JSON)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
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.
* <p/>
*
* @see IPForwardingRuleAsyncClient
* @see NATAsyncClient
* @see <a
* 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;
case 409:
case 431:
if (command.getCurrentRequest().getRequestLine().indexOf("delete") != -1
&& message.indexOf("does not exist") != -1) {
if (message.contains("does not exist")) {
exception = new ResourceNotFoundException(message, exception);
} else {
exception = new IllegalStateException(message, exception);

View File

@ -92,7 +92,38 @@ public class NetworkPredicates {
return isVirtualNetwork.toString();
}
}
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 final String zoneId;
@ -170,6 +201,10 @@ public class NetworkPredicates {
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.
@ -202,6 +237,22 @@ public class NetworkPredicates {
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.
*

View File

@ -21,6 +21,9 @@ package org.jclouds.cloudstack.compute;
import static com.google.common.collect.Iterables.getFirst;
import static com.google.inject.name.Names.bindProperties;
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.assertFalse;
@ -33,7 +36,6 @@ import javax.inject.Singleton;
import org.jclouds.cloudstack.CloudStackClient;
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.strategy.CloudStackComputeServiceAdapter;
import org.jclouds.cloudstack.compute.strategy.OptionsConverter;
@ -113,6 +115,10 @@ public class CloudStackComputeServiceAdapterLiveTest extends BaseCloudStackClien
bind(new TypeLiteral<Map<NetworkType, ? extends OptionsConverter>>() {}).
toInstance(new CloudStackComputeServiceContextModule().optionsConverters());
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>>() {}).
to(ZoneIdToZone.class);
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);
}
@SuppressWarnings("unused")
@Provides
@Singleton
protected LoadingCache<String, Set<IPForwardingRule>> getIPForwardingRuleByVirtualMachine(
GetIPForwardingRulesByVirtualMachine getIPForwardingRule) {
return CacheBuilder.newBuilder().build(getIPForwardingRule);
protected LoadingCache<String, Set<IPForwardingRule>> getIPForwardingRulesByVirtualMachine(
GetIPForwardingRulesByVirtualMachine getIPForwardingRules) {
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(
@ -176,9 +189,9 @@ public class CloudStackComputeServiceAdapterLiveTest extends BaseCloudStackClien
client.getNATClient().getIPForwardingRulesForVirtualMachine(vm.getNode().getId()), null);
String address = rule != null ? rule.getIPAddress() : vm.getNode().getIPAddress();
loginCredentials = prioritizeCredentialsFromTemplate.apply(template, vm.getCredentials());
assert InetAddresses.isInetAddress(address) : vm;
HostAndPort socket = HostAndPort.fromParts(address, 22);
checkSSH(socket);

View File

@ -27,6 +27,7 @@ import org.jclouds.cloudstack.domain.Template;
import org.jclouds.cloudstack.parse.ListTemplatesResponseTest;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.ImageBuilder;
import org.jclouds.compute.domain.Image.Status;
import org.jclouds.domain.Location;
import org.testng.annotations.Test;
@ -51,20 +52,21 @@ public class TemplateToImageTest {
// location free image
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)")
.build();
.status(Status.AVAILABLE).build();
// location free image
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")
.operatingSystem(TemplateToOperatingSystemTest.three).description("Windows 7 KVM")
.location(ZoneToLocationTest.two).build();
.location(ZoneToLocationTest.two).status(Status.AVAILABLE).build();
// location free image
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)")
.build();
.status(Status.AVAILABLE).build();
static Image five = new ImageBuilder().id("241").providerId("241").name("kvmdev4")
.operatingSystem(TemplateToOperatingSystemTest.five).description("v5.6.28_Dev4")
.location(ZoneToLocationTest.two).build();
.location(ZoneToLocationTest.two).status(Status.AVAILABLE).build();
@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.NodeMetadata;
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.date.internal.SimpleDateFormatDateService;
import org.jclouds.domain.Location;
@ -87,7 +87,7 @@ public class VirtualMachineToNodeMetadataTest {
assertEquals(
node.toString(),
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"))
.hardware(addHypervisor(ServiceOfferingToHardwareTest.one, "XenServer"))
.imageId(TemplateToImageTest.one.getId())
@ -150,7 +150,7 @@ public class VirtualMachineToNodeMetadataTest {
assertEquals(
node.toString(),
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())
.publicAddresses(ImmutableSet.<String>of("1.1.1.5"))
.hardware(addHypervisor(ServiceOfferingToHardwareTest.one, "XenServer"))
@ -186,7 +186,7 @@ public class VirtualMachineToNodeMetadataTest {
assertEquals(
node.toString(),
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"))
.hardware(addHypervisor(ServiceOfferingToHardwareTest.one, "XenServer"))
.imageId(TemplateToImageTest.one.getId())

View File

@ -32,6 +32,7 @@ import org.testng.annotations.Test;
@Test(groups = "live", singleThreaded = true, testName = "AccountClientLiveTest")
public class AccountClientLiveTest extends BaseCloudStackClientLiveTest {
@Test
public void testListAccounts() throws Exception {
for (Account securityAccount : client.getAccountClient().listAccounts())
checkAccount(securityAccount);
@ -49,14 +50,12 @@ public class AccountClientLiveTest extends BaseCloudStackClientLiveTest {
assert user.getName() != null : user;
assert user.getAccountType().equals(account.getType()) : user;
assert user.getDomain().equals(account.getDomain()) : user;
assert user.getDomainId() == account.getDomainId() : user;
assert user.getApiKey() != null : user;
assert user.getDomainId().equals(account.getDomainId()) : user;
assert user.getCreated() != null : user;
assert user.getEmail() != null : user;
assert user.getLastName() != null : user;
assert user.getFirstName() != null : user;
assert user.getId() != null : user;
assert user.getSecretKey() != null : user;
assert user.getState() != null : user;
}
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.ssh.SshClient;
import org.jclouds.sshj.config.SshjSshClientModule;
import org.testng.SkipException;
import org.testng.annotations.AfterGroups;
import org.testng.annotations.BeforeGroups;
@ -270,6 +271,18 @@ public class BaseCloudStackClientLiveTest extends BaseGenericComputeServiceConte
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")
protected void tearDown() {
if (cloudStackContext != null)

View File

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

View File

@ -18,9 +18,16 @@
*/
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 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.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
@ -43,55 +50,56 @@ public class DomainDomainClientLiveTest extends BaseCloudStackClientLiveTest {
@Test
public void testListDomains() {
assert domainAdminEnabled;
skipIfNotDomainAdmin();
Set<Domain> allDomains = domainAdminClient.getDomainClient().listDomains();
Domain root = find(allDomains, withName("ROOT"));
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());
Set<Domain> domains = domainAdminClient.getDomainClient().listDomains();
for (Domain candidate : domains) {
checkDomain(candidate);
}
}
for (Domain domain : allDomains) {
checkDomain(domain, allDomains);
private void checkDomain(Domain domain) {
assertNotNull(domain.getId());
if (domain.getLevel() == 0 /* global ROOT */) {
assertNull(domain.getParentDomainName());
assertNull(domain.getParentDomainId());
} else {
assertNotNull(domain.getParentDomainName());
assertNotNull(domain.getParentDomainId());
}
}
@Test
public void testListDomainChildren() {
assert domainAdminEnabled;
skipIfNotDomainAdmin();
Set<Domain> allDomains = domainAdminClient.getDomainClient().listDomains();
Domain root = find(allDomains, withName("ROOT"));
Set<Domain> domains = domainAdminClient.getDomainClient().listDomains();
Domain root = findRootOfVisibleTree(domains);
if (domains.size() > 1) {
assertTrue(root.hasChild());
}
Set<Domain> children = domainAdminClient.getDomainClient()
.listDomainChildren(parentDomainId(root.getId()).isRecursive(true));
assertEquals(allDomains.size() - 1, children.size());
for (Domain domain : children) {
checkDomain(domain, allDomains);
}
assertEquals(domains.size() - 1, children.size());
assertTrue(Sets.difference(domains, children).contains(root));
}
private Predicate<Domain> withName(final String name) {
return new Predicate<Domain>() {
@Override
public boolean apply(@Nullable Domain domain) {
return domain != null && domain.getName().equals(name);
private Domain findRootOfVisibleTree(Set<Domain> domains) {
final Set<String> names = newHashSet(Iterables.transform(domains,
new Function<Domain, String>() {
@Override
public String apply(Domain domain) {
return domain.getName();
}
}));
for (Domain candidate : domains) {
if (candidate.getParentDomainId() == null ||
!names.contains(candidate.getParentDomainName())) {
return candidate;
}
};
}
private void checkDomain(Domain domain, Set<Domain> allDomains) {
assert domain.getId() != null : domain;
if (domain.getParentDomainName() != null) {
Domain parent = find(allDomains, withName(domain.getParentDomainName()));
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
public void testListUsers() {
assert domainAdminEnabled;
skipIfNotDomainAdmin();
Set<User> users = domainAdminClient.getUserClient().listUsers();
@ -60,7 +60,7 @@ public class DomainUserClientLiveTest extends BaseCloudStackClientLiveTest {
@Test
public void testEnableDisableUser() {
assert globalAdminEnabled && domainAdminEnabled;
skipIfNotGlobalAdmin();
Account testAccount = null;
User testUser = null;

View File

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

View File

@ -38,7 +38,7 @@ public class GlobalAlertClientLiveTest extends BaseCloudStackClientLiveTest {
@Test(groups = "live", enabled = true)
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"));
assert null != response;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -51,10 +51,13 @@ public class GlobalPodClientLiveTest extends BaseCloudStackClientLiveTest {
private Pod pod;
public void testListPods() throws Exception {
skipIfNotGlobalAdmin();
Set<Pod> response = globalAdminClient.getPodClient().listPods();
assert null != response;
long podCount = response.size();
assertTrue(podCount >= 0);
for (Pod pod : response) {
Pod newDetails = Iterables.getOnlyElement(globalAdminClient.getPodClient().listPods(
ListPodsOptions.Builder.id(pod.getId())));
@ -74,7 +77,7 @@ public class GlobalPodClientLiveTest extends BaseCloudStackClientLiveTest {
@Test
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");
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)
public void testListStoragePools() throws Exception {
assertTrue(globalAdminEnabled, "Test cannot run without global admin identity and credentials");
skipIfNotGlobalAdmin();
Set<StoragePool> result = globalAdminClient.getStoragePoolClient().listStoragePools();
assertNotNull(result);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -147,7 +147,7 @@ public class SnapshotClientLiveTest extends BaseCloudStackClientLiveTest {
return find(client.getSnapshotClient().listSnapshots(), new Predicate<Snapshot>() {
@Override
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.getZoneId() != null : template;
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.getHypervisor() != null : template;
assert template.getDomain() != null : template;
@ -110,8 +110,8 @@ public class TemplateClientLiveTest extends BaseCloudStackClientLiveTest {
return network != null && network.getState().equals("Implemented");
}
});
assertEquals(Iterables.size(networks), 1);
Network network = Iterables.getOnlyElement(networks, null);
assertTrue(Iterables.size(networks) >= 1);
Network network = Iterables.get(networks, 0);
assertNotNull(network);
// Create a VM and stop it
@ -160,7 +160,7 @@ public class TemplateClientLiveTest extends BaseCloudStackClientLiveTest {
networks = Iterables.filter(networks, new Predicate<Network>() {
@Override
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);
@ -184,7 +184,7 @@ public class TemplateClientLiveTest extends BaseCloudStackClientLiveTest {
if (template == null) return false;
Template t2 = client.getTemplateClient().getTemplateInZone(template.getId(), zoneId);
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));

View File

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

View File

@ -246,7 +246,7 @@ public class VolumeClientLiveTest extends BaseCloudStackClientLiveTest {
static Volume findVolumeWithId(final CloudStackClient client, final String id) {
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);
}

View File

@ -28,7 +28,6 @@ import java.util.Set;
import javax.annotation.Nullable;
import org.jclouds.cloudstack.compute.config.CloudStackComputeServiceContextModule.GetIPForwardingRulesByVirtualMachine;
import org.jclouds.cloudstack.domain.IPForwardingRule;
import org.jclouds.cloudstack.domain.Network;
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.identity>${test.aws.identity}</test.cloudwatch.identity>
<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>
<dependencies>
@ -101,21 +104,5 @@
</profile>
</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>

View File

@ -18,13 +18,17 @@
*/
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.Metric;
import org.jclouds.cloudwatch.domain.MetricDatum;
import org.jclouds.cloudwatch.features.MetricClient;
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.
@ -58,10 +62,10 @@ public class CloudWatch {
while (true) {
if (iterator == null) {
lastOptions = ListMetricsOptions.builder()
.dimensions(lastOptions.getDimensions())
.metricName(lastOptions.getMetricName())
.namespace(lastOptions.getNamespace())
.nextToken(response.getNextToken())
.metricName(lastOptions.getMetricName())
.dimensions(lastOptions.getDimensions())
.nextToken(lastOptions.getNextToken())
.build();
response = metricClient.listMetrics(lastOptions);
iterator = response.iterator();
@ -95,4 +99,21 @@ public class CloudWatch {
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;
import java.util.Date;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import com.google.inject.Provides;
import org.jclouds.cloudwatch.domain.Datapoint;
import org.jclouds.cloudwatch.domain.Statistics;
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.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
@ -90,7 +89,7 @@ public interface CloudWatchClient {
* The statistics to be returned for the given metric. ex. Average
* @param options
* more filtering options (e.g. instance ID)
* @see MetricsClient#getMetricStatistics
* @see MetricClient#getMetricStatistics(org.jclouds.cloudwatch.domain.GetMetricStatistics)
*/
@Deprecated
Set<Datapoint> getMetricStatisticsInRegion(@Nullable String region, String metricName, String namespace,

View File

@ -18,6 +18,8 @@
*/
package org.jclouds.cloudwatch.binders;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.inject.Inject;
import org.jclouds.cloudwatch.domain.Dimension;
@ -45,36 +47,44 @@ public class GetMetricStatisticsBinder implements org.jclouds.rest.Binder {
@Inject
protected GetMetricStatisticsBinder(DateService dateService){
this.dateService =dateService;
this.dateService = dateService;
}
@Override
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 statisticIndex = 1;
ImmutableMultimap.Builder<String, String> formParameters = ImmutableMultimap.builder();
ImmutableMultimap.Builder<String, String> formParameters = ImmutableMultimap.<String, String> builder();
for (Dimension dimension : getRequest.getDimensions()) {
formParameters.put("Dimensions.member." + dimensionIndex + ".Name", dimension.getName());
formParameters.put("Dimensions.member." + dimensionIndex + ".Value", dimension.getValue());
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("Namespace", getRequest.getNamespace());
formParameters.put("Period", Integer.toString(getRequest.getPeriod()));
formParameters.put("StartTime", dateService.iso8601SecondsDateFormat(getRequest
.getStartTime()));
if (getRequest.getStartTime().isPresent()) {
formParameters.put("StartTime", dateService.iso8601SecondsDateFormat(getRequest
.getStartTime().get()));
}
for (Statistics statistic : getRequest.getStatistics()) {
formParameters.put("Statistics.member." + statisticIndex, statistic.toString());
statisticIndex++;
}
formParameters.put("Unit", getRequest.getUnit().toString());
if (getRequest.getUnit().isPresent()) {
formParameters.put("Unit", getRequest.getUnit().get().toString());
}
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;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Date;
import java.util.Set;
import org.jclouds.cloudwatch.options.ListMetricsOptions;
import org.jclouds.javax.annotation.Nullable;
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;
/**
@ -39,34 +41,32 @@ import com.google.common.collect.Sets;
public class GetMetricStatistics {
private final Set<Dimension> dimensions;
private final Date endTime;
private final Optional<Date> endTime;
private final String metricName;
private final String namespace;
private final int period;
private final Date startTime;
private final Optional<Date> startTime;
private final Set<Statistics> statistics;
private final Unit unit;
private final Optional<Unit> unit;
/**
* Private constructor to enforce using {@link Builder}.
*/
private GetMetricStatistics(@Nullable Set<Dimension> dimensions, Date endTime, String metricName,
String namespace, int period, Date startTime, Set<Statistics> statistics,
Unit unit) {
this.dimensions = dimensions;
this.endTime = endTime;
this.metricName = metricName;
this.namespace = namespace;
protected GetMetricStatistics(Set<Dimension> dimensions, Date endTime, String metricName, String namespace, int period,
Date startTime, Set<Statistics> statistics, Unit unit) {
this.dimensions = ImmutableSet.<Dimension>copyOf(checkNotNull(dimensions, "dimensions"));
this.endTime = Optional.fromNullable(endTime);
this.metricName = checkNotNull(metricName, "metricName");
this.namespace = checkNotNull(namespace, "namespace");
this.period = period;
this.startTime = startTime;
this.statistics = statistics;
this.unit = unit;
this.startTime = Optional.fromNullable(startTime);
this.statistics = ImmutableSet.<Statistics>copyOf(checkNotNull(statistics, "statistics"));
this.unit = Optional.fromNullable(unit);
}
/**
* return the set of dimensions for this request
*/
@Nullable
public Set<Dimension> getDimensions() {
return dimensions;
}
@ -74,7 +74,7 @@ public class GetMetricStatistics {
/**
* return the end time for this request
*/
public Date getEndTime() {
public Optional<Date> getEndTime() {
return endTime;
}
@ -102,7 +102,7 @@ public class GetMetricStatistics {
/**
* return the start time for this request
*/
public Date getStartTime() {
public Optional<Date> getStartTime() {
return startTime;
}
@ -116,7 +116,7 @@ public class GetMetricStatistics {
/**
* return the unit for this request
*/
public Unit getUnit() {
public Optional<Unit> getUnit() {
return unit;
}
@ -130,12 +130,14 @@ public class GetMetricStatistics {
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 Date endTime;
private String metricName;
private String namespace;
private int period;
private int period = 60;
private Date startTime;
// this builder is set to be additive on dimension calls, so make this mutable
private Set<Statistics> statistics = Sets.newLinkedHashSet();
private Unit unit;
@ -146,143 +148,100 @@ public class GetMetricStatistics {
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
*
* @return this {@code Builder} object
*
* @throws IllegalArgumentException if this is invoked more than 10 times
*/
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.addAll(checkNotNull(dimensions, "dimensions"));
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
*
* @return this {@code Builder} object
*
* @throws IllegalArgumentException if the number of dimensions would be greater than 10 after adding
*/
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(checkNotNull(dimension, "dimension"));
return this;
}
/**
* 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
* will overwrite the previous value.)
* results will include datapoints up to the time stamp specified.
*
* @param endTime the timestamp to use for determining the last datapoint to return
*
* @return this {@code Builder} object
*
* @throws NullPointerException if endTime is null
*/
public Builder endTime(Date endTime) {
Preconditions.checkNotNull(endTime, "endTime cannot be null.");
this.endTime = endTime;
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
*
* @return this {@code Builder} object
*
* @throws NullPointerException if metricName is null
* @throws IllegalArgumentException if metricName is empty
*/
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;
return this;
}
/**
* The namespace of the metric. (Should be called once. Subsequent calls will overwrite the previous value.
* See {@link org.jclouds.cloudwatch.domain.Namespaces} for the known list of namespaces.)
* The namespace of the metric.
*
* @param namespace the namespace to filter against
*
* @return this {@code Builder} object
*
* @throws NullPointerException if namespace is null
* @throws IllegalArgumentException if namespace is empty
*/
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;
return this;
}
/**
* The granularity, in seconds, of the returned datapoints. Period must be at least 60 seconds and must be a
* multiple of 60. The default value is 60. (Should be called once. Subsequent calls will overwrite the
* previous value.)
* The granularity, in seconds, of the returned datapoints.
*
* @param period the granularity, in seconds, of the returned datapoints
*
* @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) {
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;
return this;
}
/**
* 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
* overwrite the previous value.)
* results include datapoints with the time stamp specified.
*
* @param startTime The time stamp to use for determining the first datapoint to return
*
* @return this {@code Builder} object
*
* @throws NullPointerException if startTime is null
*/
public Builder startTime(Date startTime) {
Preconditions.checkNotNull(startTime, "startTime cannot be null.");
this.startTime = startTime;
return this;
}
/**
* The metric statistics to return. (Should be called once. Subsequent calls will overwrite the previous
* value.)
* The metric statistics to return.
*
* @param statistics the metric statistics to return.
*
* @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) {
Preconditions.checkNotNull(statistics, "statistics cannot be null.");
Preconditions.checkArgument(statistics.size() <= 5, "statistics can have 5 or fewer members.");
this.statistics = statistics;
this.statistics.addAll(checkNotNull(statistics, "statistics"));
return this;
}
@ -292,28 +251,20 @@ public class GetMetricStatistics {
* @param statistic the metric statistic to return
*
* @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) {
Preconditions.checkNotNull(statistic, "statistic cannot be null.");
Preconditions.checkArgument(statistics.size() < 5, "statistics member maximum count of 5 exceeded.");
this.statistics.add(statistic);
this.statistics.add(checkNotNull(statistic, "statistic"));
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
*
* @return this {@code Builder} object
*
* @throws NullPointerException if unit is null
*/
public Builder unit(Unit unit) {
Preconditions.checkNotNull(unit, "unit cannot be null.");
this.unit = unit;
return this;
}
@ -321,22 +272,12 @@ public class GetMetricStatistics {
/**
* Returns a newly-created {@code GetMetricStatisticsOptionsV2} based on the contents of
* 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() {
Preconditions.checkNotNull(endTime, "endTime cannot be null.");
Preconditions.checkNotNull(metricName, "metricName cannot be null.");
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);
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;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import com.google.common.util.concurrent.ListenableFuture;
import org.jclouds.aws.filters.FormSigner;
import org.jclouds.cloudwatch.binders.GetMetricStatisticsBinder;
import org.jclouds.cloudwatch.binders.MetricDataBinder;
import org.jclouds.cloudwatch.domain.GetMetricStatistics;
import org.jclouds.cloudwatch.domain.GetMetricStatisticsResponse;
import org.jclouds.cloudwatch.domain.ListMetricsResponse;
import org.jclouds.cloudwatch.domain.MetricDatum;
import org.jclouds.cloudwatch.options.GetMetricStatisticsOptions;
import org.jclouds.cloudwatch.options.ListMetricsOptions;
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.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
@ -88,4 +90,13 @@ public interface MetricAsyncClient {
@BinderParam(GetMetricStatisticsBinder.class) GetMetricStatistics statistics,
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;
import java.util.concurrent.TimeUnit;
import org.jclouds.cloudwatch.domain.GetMetricStatistics;
import org.jclouds.cloudwatch.domain.GetMetricStatisticsResponse;
import org.jclouds.cloudwatch.domain.ListMetricsResponse;
import org.jclouds.cloudwatch.domain.MetricDatum;
import org.jclouds.cloudwatch.options.GetMetricStatisticsOptions;
import org.jclouds.cloudwatch.options.ListMetricsOptions;
import org.jclouds.concurrent.Timeout;
import java.util.concurrent.TimeUnit;
/**
* Provides access to Amazon CloudWatch via the Query API
* <p/>
@ -45,10 +46,10 @@ public interface MetricClient {
* use returned NextToken (
* {@link org.jclouds.cloudwatch.domain.ListMetricsResponse#getNextToken()}) value with
* 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
* the options describing the metrics query
* @param options the options describing the metrics query
*
* @return the response object
*/
@ -59,10 +60,8 @@ public interface MetricClient {
/**
* Gets statistics for the specified metric.
*
* @param statistics
* the statistics to gather
* @param options
* the options describing the metric statistics query
* @param statistics the statistics to gather
* @param options the options describing the metric statistics query
*
* @return the response object
*/
@ -70,4 +69,12 @@ public interface MetricClient {
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;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Set;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import org.jclouds.aws.util.AWSUtils;
import org.jclouds.cloudwatch.domain.Dimension;
import org.jclouds.cloudwatch.domain.Unit;
import org.jclouds.http.options.BaseHttpRequestOptions;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import java.util.Set;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Options used to control metric statistics are returned
@ -42,39 +39,32 @@ import com.google.common.collect.Sets;
*/
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
*
* @return this {@code Builder} object
*
* @throws IllegalArgumentException if the number of dimensions would be greater than 10 after adding
*/
public GetMetricStatisticsOptions dimension(Dimension dimension) {
if (dimension != null) {
Preconditions.checkArgument(dimensions.size() < 10, "dimension member maximum count of 10 exceeded.");
this.dimensions.add(dimension);
if (dimensions == null) {
dimensions = Sets.newLinkedHashSet();
}
this.dimensions.add(dimension);
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
*
* @return this {@code Builder} object
*
* @throws IllegalArgumentException if this is invoked more than 10 times
*/
public GetMetricStatisticsOptions dimensions(Set<Dimension> dimensions) {
if (dimensions != null) {
Preconditions.checkArgument(dimensions.size() <= 10, "dimensions can have 10 or fewer members.");
this.dimensions = ImmutableSet.<Dimension>copyOf(dimensions);
}
this.dimensions = dimensions;
return this;
}
@ -137,10 +127,12 @@ public class GetMetricStatisticsOptions extends BaseHttpRequestOptions {
public Multimap<String, String> buildFormParameters() {
Multimap<String, String> formParameters = super.buildFormParameters();
int dimensionIndex = 1;
for (Dimension dimension : dimensions) {
formParameters.put("Dimensions.member." + dimensionIndex + ".Name", dimension.getName());
formParameters.put("Dimensions.member." + dimensionIndex + ".Value", dimension.getValue());
dimensionIndex++;
if (dimensions != null) {
for (Dimension dimension : dimensions) {
formParameters.put("Dimensions.member." + dimensionIndex + ".Name", dimension.getName());
formParameters.put("Dimensions.member." + dimensionIndex + ".Value", dimension.getValue());
dimensionIndex++;
}
}
return formParameters;
}

View File

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

View File

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

View File

@ -18,13 +18,25 @@
*/
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 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.predicates.RetryablePredicate;
import org.jclouds.rest.RestContext;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
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;
/**
@ -58,4 +70,38 @@ public class CloudWatchLiveTest extends BaseContextLiveTest<RestContext<CloudWat
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.expect;
import java.util.List;
import java.util.Set;
import org.easymock.EasyMock;
import org.jclouds.cloudwatch.domain.ListMetricsResponse;
import org.jclouds.cloudwatch.domain.Metric;
import org.jclouds.cloudwatch.domain.MetricDatum;
import org.jclouds.cloudwatch.features.MetricClient;
import org.jclouds.cloudwatch.options.ListMetricsOptions;
import org.testng.Assert;
@ -32,12 +36,14 @@ import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
/**
* Tests behavior of {@code CloudWatch}.
*
* @author Jeremy Whitlock
*/
@Test(testName = "CloudWatchTest")
public class CloudWatchTest {
/**
@ -97,4 +103,37 @@ public class CloudWatchTest {
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;
import static org.testng.Assert.assertEquals;
import java.net.URI;
import java.util.Date;
import java.util.TimeZone;
import com.google.common.collect.ImmutableMultimap;
import org.jclouds.cloudwatch.CloudWatchClient;
import org.jclouds.cloudwatch.domain.Dimension;
import org.jclouds.cloudwatch.domain.EC2Constants;
@ -39,7 +34,11 @@ import org.jclouds.http.HttpResponse;
import org.jclouds.rest.ResourceNotFoundException;
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
@ -59,14 +58,14 @@ public class MetricClientExpectTest extends BaseCloudWatchClientExpectTest {
.build())
.payload(
payloadFromStringWithContentType(
new StringBuilder()
.append("Action=ListMetrics").append('&')
.append("Signature=KSh9oQydCR0HMAV6QPYwDzqwQIpxs8I%2Fig7brYgHVZU%3D").append('&')
.append("SignatureMethod=HmacSHA256").append('&')
.append("SignatureVersion=2").append('&')
.append("Timestamp=2009-11-08T15%3A54%3A08.897Z").append('&')
.append("Version=2010-08-01").append('&')
.append("AWSAccessKeyId=identity").toString(), "application/x-www-form-urlencoded"))
"Action=ListMetrics" +
"&Signature=KSh9oQydCR0HMAV6QPYwDzqwQIpxs8I%2Fig7brYgHVZU%3D" +
"&SignatureMethod=HmacSHA256" +
"&SignatureVersion=2" +
"&Timestamp=2009-11-08T15%3A54%3A08.897Z" +
"&Version=2010-08-01" +
"&AWSAccessKeyId=identity",
"application/x-www-form-urlencoded"))
.build();
public void testListMetricsWhenResponseIs2xx() throws Exception {
@ -78,7 +77,8 @@ public class MetricClientExpectTest extends BaseCloudWatchClientExpectTest {
listMetrics, listMetricsResponse);
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
@ -94,28 +94,28 @@ public class MetricClientExpectTest extends BaseCloudWatchClientExpectTest {
}
public void testListMetricsWithOptionsWhenResponseIs2xx() throws Exception {
HttpRequest listMetricsWithOptions = HttpRequest.builder()
.method("POST")
.endpoint(URI.create("https://monitoring.us-east-1.amazonaws.com/"))
.headers(ImmutableMultimap.<String, String> builder()
.put("Host", "monitoring.us-east-1.amazonaws.com")
.build())
.payload(
payloadFromStringWithContentType(
new StringBuilder()
.append("Action=ListMetrics").append('&')
.append("Dimensions.member.1.Name=InstanceId").append('&')
.append("Dimensions.member.1.Value=SOMEINSTANCEID").append('&')
.append("MetricName=CPUUtilization").append('&')
.append("Namespace=SOMENEXTTOKEN").append('&')
.append("NextToken=AWS%2FEC2").append('&')
.append("Signature=G05HKEx9FJpGZBk02OVYwt3u4g%2FilAY9nU5hJI9LDXA%3D").append('&')
.append("SignatureMethod=HmacSHA256").append('&')
.append("SignatureVersion=2").append('&')
.append("Timestamp=2009-11-08T15%3A54%3A08.897Z").append('&')
.append("Version=2010-08-01").append('&')
.append("AWSAccessKeyId=identity").toString(), "application/x-www-form-urlencoded"))
.build();
HttpRequest listMetricsWithOptions =
HttpRequest.builder()
.method("POST")
.endpoint(URI.create("https://monitoring.us-east-1.amazonaws.com/"))
.headers(ImmutableMultimap.<String, String>builder()
.put("Host", "monitoring.us-east-1.amazonaws.com")
.build())
.payload(payloadFromStringWithContentType(
"Action=ListMetrics" +
"&Dimensions.member.1.Name=InstanceId" +
"&Dimensions.member.1.Value=SOMEINSTANCEID" +
"&MetricName=CPUUtilization" +
"&Namespace=SOMENEXTTOKEN" +
"&NextToken=AWS%2FEC2" +
"&Signature=G05HKEx9FJpGZBk02OVYwt3u4g%2FilAY9nU5hJI9LDXA%3D" +
"&SignatureMethod=HmacSHA256" +
"&SignatureVersion=2" +
"&Timestamp=2009-11-08T15%3A54%3A08.897Z" +
"&Version=2010-08-01" +
"&AWSAccessKeyId=identity",
"application/x-www-form-urlencoded"))
.build();
HttpResponse listMetricsWithOptionsResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType("/list_metrics.xml", "text/xml")).build();
@ -126,12 +126,14 @@ public class MetricClientExpectTest extends BaseCloudWatchClientExpectTest {
assertEquals(
clientWhenMetricsWithOptionsExist.getMetricClientForRegion(null).listMetrics(
ListMetricsOptions.builder()
.dimension(new Dimension(EC2Constants.Dimension.INSTANCE_ID, "SOMEINSTANCEID"))
.dimension(new Dimension(EC2Constants.Dimension.INSTANCE_ID,
"SOMEINSTANCEID"))
.metricName(EC2Constants.MetricName.CPU_UTILIZATION)
.namespace("SOMENEXTTOKEN")
.nextToken( Namespaces.EC2)
.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()
@ -152,21 +154,22 @@ public class MetricClientExpectTest extends BaseCloudWatchClientExpectTest {
.build())
.payload(
payloadFromStringWithContentType(
new StringBuilder()
.append("Action=GetMetricStatistics").append('&')
.append("EndTime=1970-01-01T02%3A46%3A40Z").append('&')
.append("MetricName=CPUUtilization").append('&')
.append("Namespace=AWS%2FEC2").append('&')
.append("Period=60").append('&')
.append("Signature=rmg8%2Ba7w4ycy%2FKfO8rnuj6rDL0jNE96m8GKfjh3SWcw%3D").append('&')
.append("SignatureMethod=HmacSHA256").append('&')
.append("SignatureVersion=2").append('&')
.append("StartTime=1970-01-01T02%3A46%3A40Z").append('&')
.append("Statistics.member.1=Maximum").append('&')
.append("Statistics.member.2=Minimum").append('&')
.append("Timestamp=2009-11-08T15%3A54%3A08.897Z").append('&')
.append("Unit=Percent").append('&').append("Version=2010-08-01").append('&')
.append("AWSAccessKeyId=identity").toString(), "application/x-www-form-urlencoded"))
"Action=GetMetricStatistics" +
"&EndTime=1970-01-01T02%3A46%3A40Z" +
"&MetricName=CPUUtilization" +
"&Namespace=AWS%2FEC2" +
"&Period=60" +
"&Signature=rmg8%2Ba7w4ycy%2FKfO8rnuj6rDL0jNE96m8GKfjh3SWcw%3D" +
"&SignatureMethod=HmacSHA256" +
"&SignatureVersion=2" +
"&StartTime=1970-01-01T02%3A46%3A40Z" +
"&Statistics.member.1=Maximum" +
"&Statistics.member.2=Minimum" +
"&Timestamp=2009-11-08T15%3A54%3A08.897Z" +
"&Unit=Percent" +
"&Version=2010-08-01" +
"&AWSAccessKeyId=identity",
"application/x-www-form-urlencoded"))
.build();
public void testGetMetricStatisticsWhenResponseIs2xx() throws Exception {
@ -179,7 +182,11 @@ public class MetricClientExpectTest extends BaseCloudWatchClientExpectTest {
assertEquals(
clientWhenMetricsExist.getMetricClientForRegion(null).getMetricStatistics(stats).toString(),
// 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
@ -194,35 +201,35 @@ public class MetricClientExpectTest extends BaseCloudWatchClientExpectTest {
}
public void testGetMetricStatisticsWithOptionsWhenResponseIs2xx() throws Exception {
HttpRequest getMetricStatistics = HttpRequest.builder()
.method("POST")
.endpoint(URI.create("https://monitoring.us-east-1.amazonaws.com/"))
.headers(ImmutableMultimap.<String, String> builder()
.put("Host", "monitoring.us-east-1.amazonaws.com")
.build())
.payload(
payloadFromStringWithContentType(
new StringBuilder()
.append("Action=GetMetricStatistics").append('&')
.append("Dimensions.member.1.Name=InstanceId").append('&')
.append("Dimensions.member.1.Value=SOMEINSTANCEID").append('&')
.append("Dimensions.member.2.Name=InstanceType").append('&')
.append("Dimensions.member.2.Value=t1.micro").append('&')
.append("EndTime=1970-01-01T02%3A46%3A40Z").append('&')
.append("MetricName=CPUUtilization").append('&')
.append("Namespace=AWS%2FEC2").append('&')
.append("Period=60").append('&')
.append("Signature=e0WyI%2FNm4hN2%2BMEm1mjRUzsvgvMCdFXbVJWi4ORpwic%3D").append('&')
.append("SignatureMethod=HmacSHA256").append('&')
.append("SignatureVersion=2").append('&')
.append("StartTime=1970-01-01T02%3A46%3A40Z").append('&')
.append("Statistics.member.1=Maximum").append('&')
.append("Statistics.member.2=Minimum").append('&')
.append("Timestamp=2009-11-08T15%3A54%3A08.897Z").append('&')
.append("Unit=Percent").append('&')
.append("Version=2010-08-01").append('&')
.append("AWSAccessKeyId=identity").toString(), "application/x-www-form-urlencoded"))
.build();
HttpRequest getMetricStatistics =
HttpRequest.builder()
.method("POST")
.endpoint(URI.create("https://monitoring.us-east-1.amazonaws.com/"))
.headers(ImmutableMultimap.<String, String> builder()
.put("Host", "monitoring.us-east-1.amazonaws.com")
.build())
.payload(payloadFromStringWithContentType(
"Action=GetMetricStatistics" +
"&Dimensions.member.1.Name=InstanceId" +
"&Dimensions.member.1.Value=SOMEINSTANCEID" +
"&Dimensions.member.2.Name=InstanceType" +
"&Dimensions.member.2.Value=t1.micro" +
"&EndTime=1970-01-01T02%3A46%3A40Z" +
"&MetricName=CPUUtilization" +
"&Namespace=AWS%2FEC2" +
"&Period=60" +
"&Signature=e0WyI%2FNm4hN2%2BMEm1mjRUzsvgvMCdFXbVJWi4ORpwic%3D" +
"&SignatureMethod=HmacSHA256" +
"&SignatureVersion=2" +
"&StartTime=1970-01-01T02%3A46%3A40Z" +
"&Statistics.member.1=Maximum" +
"&Statistics.member.2=Minimum" +
"&Timestamp=2009-11-08T15%3A54%3A08.897Z" +
"&Unit=Percent" +
"&Version=2010-08-01" +
"&AWSAccessKeyId=identity",
"application/x-www-form-urlencoded"))
.build();
HttpResponse getMetricStatisticsResponse = HttpResponse.builder().statusCode(200).payload(
payloadFromResourceWithContentType("/get_metric_statistics.xml", "text/xml")).build();
@ -236,7 +243,11 @@ public class MetricClientExpectTest extends BaseCloudWatchClientExpectTest {
clientWhenMetricsExist.getMetricClientForRegion(null).getMetricStatistics(stats,
GetMetricStatisticsOptions.Builder.dimension(dimension1).dimension(dimension2)).toString(),
// 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.Date;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.jclouds.cloudwatch.domain.Datapoint;
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.ListMetricsResponse;
import org.jclouds.cloudwatch.domain.Metric;
import org.jclouds.cloudwatch.domain.MetricDatum;
import org.jclouds.cloudwatch.domain.Namespaces;
import org.jclouds.cloudwatch.domain.StatisticValues;
import org.jclouds.cloudwatch.domain.Statistics;
import org.jclouds.cloudwatch.domain.Unit;
import org.jclouds.cloudwatch.internal.BaseCloudWatchClientLiveTest;
import org.jclouds.cloudwatch.options.ListMetricsOptions;
import org.jclouds.predicates.RetryablePredicate;
import org.testng.Assert;
import org.testng.annotations.Test;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
/**
* @author Jeremy Whitlock, Adrian Cole
@ -47,6 +54,95 @@ import com.google.common.collect.ImmutableSet;
@Test(groups = "live", testName = "MetricClientLiveTest")
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
@Test
protected void testGetMetricStatistics() {

View File

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

View File

@ -50,12 +50,20 @@
<properties>
<test.deltacloud.endpoint>http://localhost:3001/api</test.deltacloud.endpoint>
<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.credential>mockpassword</test.deltacloud.credential>
<test.deltacloud.image-id />
<test.deltacloud.image.login-user />
<test.deltacloud.image.authenticate-sudo />
<test.deltacloud.image-id></test.deltacloud.image-id>
<test.deltacloud.image.login-user></test.deltacloud.image.login-user>
<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>
<dependencies>
<dependency>
@ -125,25 +133,4 @@
</profile>
</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>

View File

@ -23,6 +23,7 @@ import javax.inject.Singleton;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.ImageBuilder;
import org.jclouds.compute.domain.Image.Status;
import com.google.common.base.Function;
@ -47,6 +48,7 @@ public class DeltacloudImageToImage implements Function<org.jclouds.deltacloud.d
builder.name(from.getName());
builder.description(from.getDescription());
builder.operatingSystem(imageToOperatingSystem.apply(from));
builder.status(Status.AVAILABLE);
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.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.NodeMetadata.Status;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.deltacloud.domain.Instance;
@ -54,11 +54,11 @@ import com.google.common.collect.Iterables;
@Singleton
public class InstanceToNodeMetadata implements Function<Instance, NodeMetadata> {
public static final Map<Instance.State, NodeState> instanceToNodeState = ImmutableMap
.<Instance.State, NodeState> builder().put(Instance.State.STOPPED, NodeState.SUSPENDED)
.put(Instance.State.RUNNING, NodeState.RUNNING).put(Instance.State.PENDING, NodeState.PENDING)
.put(Instance.State.UNRECOGNIZED, NodeState.UNRECOGNIZED).put(Instance.State.SHUTTING_DOWN, NodeState.PENDING)
.put(Instance.State.START, NodeState.PENDING).build();
public static final Map<Instance.State, Status> instanceToNodeStatus = ImmutableMap
.<Instance.State, Status> builder().put(Instance.State.STOPPED, Status.SUSPENDED)
.put(Instance.State.RUNNING, Status.RUNNING).put(Instance.State.PENDING, Status.PENDING)
.put(Instance.State.UNRECOGNIZED, Status.UNRECOGNIZED).put(Instance.State.SHUTTING_DOWN, Status.PENDING)
.put(Instance.State.START, Status.PENDING).build();
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
@ -155,7 +155,7 @@ public class InstanceToNodeMetadata implements Function<Instance, NodeMetadata>
builder.imageId(from.getImage().toASCIIString());
builder.operatingSystem(parseOperatingSystem(from));
builder.hardware(parseHardware(from));
builder.state(instanceToNodeState.get(from.getState()));
builder.status(instanceToNodeStatus.get(from.getState()));
builder.publicAddresses(from.getPublicAddresses());
builder.privateAddresses(from.getPrivateAddresses());
return builder.build();

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