Issue 551: initial support for rackspace cloud load balancers

This commit is contained in:
Adrian Cole 2011-05-09 01:27:01 -07:00
parent 19672407e7
commit bf358b58de
52 changed files with 4472 additions and 0 deletions

View File

@ -49,6 +49,11 @@ our blobstore api supports: aws-s3, cloudfiles-us, cloudfiles-uk, filesystem,
* note * the pom dependency org.jclouds/jclouds-allblobstore gives you access to
to all of these providers
our loadbalancer api supports: cloudloadbalancers-us
* note * the pom dependency org.jclouds/jclouds-allloadbalancer gives you access to
to all of these providers
we also have support for: ibmdev, mezeo, nirvanix, boxdotnet, rimuhosting, openstack nova,
azurequeue, simpledb, cloudstack as well as a async-http-client
driver in the sandbox

View File

@ -29,6 +29,11 @@
<artifactId>jclouds-all</artifactId>
<name>all</name>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-allloadbalancer</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-allcompute</artifactId>

View File

@ -160,6 +160,9 @@ softlayer.propertiesbuilder=org.jclouds.softlayer.SoftLayerPropertiesBuilder
savvis-symphonyvpdc.contextbuilder=org.jclouds.savvis.vpdc.VPDCContextBuilder
savvis-symphonyvpdc.propertiesbuilder=org.jclouds.savvis.vpdc.VPDCPropertiesBuilder
cloudloadbalancers-us.contextbuilder=org.jclouds.cloudloadbalancers.CloudLoadBalancersContextBuilder
cloudloadbalancers-us.propertiesbuilder=org.jclouds.cloudloadbalancers.CloudLoadBalancersUSPropertiesBuilder
cloudfiles-us.contextbuilder=org.jclouds.cloudfiles.CloudFilesContextBuilder
cloudfiles-us.propertiesbuilder=org.jclouds.rackspace.cloudfiles.CloudFilesUSPropertiesBuilder

View File

@ -0,0 +1,125 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2010 Cloud Conscious, LLC <info@cloudconscious.com>
====================================================================
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0.html
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
====================================================================
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-project</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../../project/pom.xml</relativePath>
</parent>
<groupId>org.jclouds.provider</groupId>
<artifactId>cloudloadbalancers-us</artifactId>
<name>jclouds cloudloadbalancers-us core</name>
<description>jclouds components to access cloudloadbalancers-us</description>
<properties>
<test.cloudloadbalancers-us.endpoint>https://auth.api.rackspacecloud.com</test.cloudloadbalancers-us.endpoint>
<test.cloudloadbalancers-us.apiversion>1.0</test.cloudloadbalancers-us.apiversion>
<test.cloudloadbalancers-us.identity>${test.rackspace-us.identity}</test.cloudloadbalancers-us.identity>
<test.cloudloadbalancers-us.credential>${test.rackspace-us.credential}</test.cloudloadbalancers-us.credential>
</properties>
<dependencies>
<dependency>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-loadbalancer</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.jclouds.common</groupId>
<artifactId>openstack-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-core</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-loadbalancer</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jclouds.common</groupId>
<artifactId>openstack-common</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jclouds.driver</groupId>
<artifactId>jclouds-log4j</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<profiles>
<profile>
<id>live</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<id>integration</id>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<systemProperties>
<property>
<name>test.cloudloadbalancers-us.endpoint</name>
<value>${test.cloudloadbalancers-us.endpoint}</value>
</property>
<property>
<name>test.cloudloadbalancers-us.apiversion</name>
<value>${test.cloudloadbalancers-us.apiversion}</value>
</property>
<property>
<name>test.cloudloadbalancers-us.identity</name>
<value>${test.cloudloadbalancers-us.identity}</value>
</property>
<property>
<name>test.cloudloadbalancers-us.credential</name>
<value>${test.cloudloadbalancers-us.credential}</value>
</property>
</systemProperties>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

View File

@ -0,0 +1,58 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.cloudloadbalancers;
import java.util.Set;
import org.jclouds.cloudloadbalancers.features.LoadBalancerAsyncClient;
import org.jclouds.location.Region;
import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
import org.jclouds.rest.annotations.Delegate;
import org.jclouds.rest.annotations.EndpointParam;
import com.google.inject.Provides;
/**
* Provides asynchronous access to CloudLoadBalancers via their REST API.
* <p/>
*
* @see CloudLoadBalancersClient
* @see <a
* href="http://docs.rackspacecloud.com/loadbalancers/api/v1.0/clb-devguide/content/ch04s01.html"
* />
* @author Adrian Cole
*/
public interface CloudLoadBalancersAsyncClient {
/**
*
* @return the region codes configured
*/
@Provides
@Region
Set<String> getConfiguredRegions();
/**
* Provides asynchronous access to LoadBalancer features.
*/
@Delegate
LoadBalancerAsyncClient getLoadBalancerClient(
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) String region);
}

View File

@ -0,0 +1,60 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.cloudloadbalancers;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.jclouds.cloudloadbalancers.features.LoadBalancerClient;
import org.jclouds.concurrent.Timeout;
import org.jclouds.location.Region;
import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
import org.jclouds.rest.annotations.Delegate;
import org.jclouds.rest.annotations.EndpointParam;
import com.google.inject.Provides;
/**
* Provides synchronous access to CloudLoadBalancers.
* <p/>
*
* @see CloudLoadBalancersAsyncClient
* @see <a
* href="http://docs.rackspacecloud.com/loadbalancers/api/v1.0/clb-devguide/content/ch04s01.html"
* />
* @author Adrian Cole
*/
@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS)
public interface CloudLoadBalancersClient {
/**
*
* @return the region codes configured
*/
@Provides
@Region
Set<String> getConfiguredRegions();
/**
* Provides synchronous access to LoadBalancer features.
*/
@Delegate
LoadBalancerClient getLoadBalancerClient(
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) String region);
}

View File

@ -0,0 +1,50 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.cloudloadbalancers;
import java.util.List;
import java.util.Properties;
import org.jclouds.cloudloadbalancers.config.CloudLoadBalancersRestClientModule;
import org.jclouds.cloudloadbalancers.loadbalancer.config.CloudLoadBalancersLoadBalancerContextModule;
import org.jclouds.loadbalancer.LoadBalancerServiceContextBuilder;
import com.google.inject.Module;
/**
*
* @author Adrian Cole
*/
public class CloudLoadBalancersContextBuilder extends
LoadBalancerServiceContextBuilder<CloudLoadBalancersClient, CloudLoadBalancersAsyncClient> {
public CloudLoadBalancersContextBuilder(Properties props) {
super(CloudLoadBalancersClient.class, CloudLoadBalancersAsyncClient.class, props);
}
@Override
protected void addContextModule(List<Module> modules) {
modules.add(new CloudLoadBalancersLoadBalancerContextModule());
}
protected void addClientModule(List<Module> modules) {
modules.add(new CloudLoadBalancersRestClientModule());
}
}

View File

@ -0,0 +1,68 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.cloudloadbalancers;
import static org.jclouds.Constants.PROPERTY_API_VERSION;
import static org.jclouds.Constants.PROPERTY_ENDPOINT;
import static org.jclouds.Constants.PROPERTY_ISO3166_CODES;
import static org.jclouds.cloudloadbalancers.reference.RackspaceConstants.PROPERTY_ACCOUNT_ID;
import static org.jclouds.cloudloadbalancers.reference.Region.DFW;
import static org.jclouds.cloudloadbalancers.reference.Region.ORD;
import static org.jclouds.location.reference.LocationConstants.ENDPOINT;
import static org.jclouds.location.reference.LocationConstants.ISO3166_CODES;
import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGION;
import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS;
import java.util.Properties;
import org.jclouds.PropertiesBuilder;
import com.google.common.base.Joiner;
/**
* Builds properties used inRackspace Cloud Load Balancers Clients
*
* @author Adrian Cole
*/
public class CloudLoadBalancersUSPropertiesBuilder extends PropertiesBuilder {
@Override
protected Properties defaultProperties() {
Properties properties = super.defaultProperties();
properties.setProperty(PROPERTY_API_VERSION, "1.0");
properties.setProperty(PROPERTY_ENDPOINT, "https://auth.api.rackspacecloud.com");
properties.setProperty(PROPERTY_REGIONS, Joiner.on(',').join(ORD, DFW));
properties.setProperty(PROPERTY_ISO3166_CODES, "US-IL,US-TX");
properties.setProperty(PROPERTY_REGION + "." + ORD + "." + ISO3166_CODES, "US-IL");
properties.setProperty(PROPERTY_REGION + "." + ORD + "." + ENDPOINT, String
.format("https://ord.loadbalancers.api.rackspacecloud.com/v{%s}/{%s}", PROPERTY_API_VERSION,
PROPERTY_ACCOUNT_ID));
properties.setProperty(PROPERTY_REGION + "." + DFW + "." + ISO3166_CODES, "US-TX");
properties.setProperty(PROPERTY_REGION + "." + DFW + "." + ENDPOINT, String
.format("https://dfw.loadbalancers.api.rackspacecloud.com/v{%s}/{%s}", PROPERTY_API_VERSION,
PROPERTY_ACCOUNT_ID));
return properties;
}
public CloudLoadBalancersUSPropertiesBuilder(Properties properties) {
super(properties);
}
}

View File

@ -0,0 +1,40 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.cloudloadbalancers;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.inject.Qualifier;
/**
* Represents a Load Balancer endpoint
*
* @author Adrian Cole
*
*/
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = { ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
@Qualifier
public @interface LoadBalancer {
}

View File

@ -0,0 +1,131 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.cloudloadbalancers.config;
import java.net.URI;
import java.util.Map;
import java.util.Set;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.cloudloadbalancers.CloudLoadBalancersAsyncClient;
import org.jclouds.cloudloadbalancers.CloudLoadBalancersClient;
import org.jclouds.cloudloadbalancers.features.LoadBalancerAsyncClient;
import org.jclouds.cloudloadbalancers.features.LoadBalancerClient;
import org.jclouds.cloudloadbalancers.handlers.ParseCloudLoadBalancersErrorFromHttpResponse;
import org.jclouds.cloudloadbalancers.reference.RackspaceConstants;
import org.jclouds.http.HttpErrorHandler;
import org.jclouds.http.RequiresHttp;
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.Region;
import org.jclouds.location.config.ProvideRegionToURIViaProperties;
import org.jclouds.openstack.OpenStackAuthAsyncClient.AuthenticationResponse;
import org.jclouds.openstack.config.OpenStackAuthenticationModule;
import org.jclouds.openstack.reference.AuthHeaders;
import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.config.RestClientModule;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multimap;
import com.google.inject.Injector;
import com.google.inject.Provides;
import com.google.inject.Scopes;
import com.google.inject.TypeLiteral;
/**
* Configures theRackspace Cloud Load Balancers connection.
*
* @author Adrian Cole
*/
@RequiresHttp
@ConfiguresRestClient
public class CloudLoadBalancersRestClientModule extends
RestClientModule<CloudLoadBalancersClient, CloudLoadBalancersAsyncClient> {
public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap.<Class<?>, Class<?>> builder()//
.put(LoadBalancerClient.class, LoadBalancerAsyncClient.class)//
.build();
public CloudLoadBalancersRestClientModule() {
super(CloudLoadBalancersClient.class, CloudLoadBalancersAsyncClient.class, DELEGATE_MAP);
}
protected void bindRegionsToProvider() {
bindRegionsToProvider(ProvideRegionToURIViaPropertiesWithAccountID.class);
}
@Singleton
public static class ProvideRegionToURIViaPropertiesWithAccountID extends ProvideRegionToURIViaProperties {
@Inject
protected ProvideRegionToURIViaPropertiesWithAccountID(Injector injector,
@Named("CONSTANTS") Multimap<String, String> constants,
@Named(RackspaceConstants.PROPERTY_ACCOUNT_ID) String accountID) {
super(injector, constants);
constants.replaceValues(RackspaceConstants.PROPERTY_ACCOUNT_ID, ImmutableSet.of(accountID));
}
}
protected void bindRegionsToProvider(Class<? extends javax.inject.Provider<Map<String, URI>>> providerClass) {
bind(new TypeLiteral<Map<String, URI>>() {
}).annotatedWith(Region.class).toProvider(providerClass).in(Scopes.SINGLETON);
}
@Override
protected void configure() {
install(new OpenStackAuthenticationModule());
bind(DateAdapter.class).to(Iso8601DateAdapter.class);
bindRegionsToProvider();
super.configure();
}
@Provides
@Singleton
@Named(RackspaceConstants.PROPERTY_ACCOUNT_ID)
protected String accountID(Supplier<AuthenticationResponse> in) {
URI serverURL = in.get().getServices().get(AuthHeaders.SERVER_MANAGEMENT_URL);
return serverURL.getPath().substring(serverURL.getPath().lastIndexOf('/') + 1);
}
@Provides
@Singleton
@Region
public Set<String> regions(@Region Map<String, URI> endpoints) {
return endpoints.keySet();
}
@Override
protected void bindErrorHandlers() {
bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(
ParseCloudLoadBalancersErrorFromHttpResponse.class);
bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(
ParseCloudLoadBalancersErrorFromHttpResponse.class);
bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(
ParseCloudLoadBalancersErrorFromHttpResponse.class);
}
}

View File

@ -0,0 +1,310 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.cloudloadbalancers.domain;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Date;
import java.util.Set;
import org.jclouds.cloudloadbalancers.domain.internal.BaseLoadBalancer;
import com.google.common.collect.ImmutableSet;
/**
*
* @author Adrian Cole
* @see <a href=
* "http://docs.rackspacecloud.com/loadbalancers/api/v1.0/clb-devguide/content/ch04s01s02.html"
* />
*/
public class LoadBalancer extends BaseLoadBalancer<Node, LoadBalancer> {
@SuppressWarnings("unchecked")
public static Builder builder() {
return new Builder();
}
/**
* {@inheritDoc}
*/
@Override
public Builder toBuilder() {
return new Builder().from(this);
}
public static class Builder extends BaseLoadBalancer.Builder<Node, LoadBalancer> {
private String region;
private int id = -1;
private Status status;
private Set<VirtualIP> virtualIPs = ImmutableSet.<VirtualIP> of();
private String sessionPersistenceType;
private String clusterName;
private Date created;
private Date updated;
private boolean connectionLoggingEnabled;
public Builder region(String region) {
this.region = region;
return this;
}
public Builder id(int id) {
this.id = id;
return this;
}
public Builder status(Status status) {
this.status = status;
return this;
}
public Builder virtualIPs(Iterable<VirtualIP> virtualIPs) {
this.virtualIPs = ImmutableSet.<VirtualIP> copyOf(checkNotNull(virtualIPs, "virtualIPs"));
return this;
}
public Builder sessionPersistenceType(String sessionPersistenceType) {
this.sessionPersistenceType = sessionPersistenceType;
return this;
}
public Builder clusterName(String clusterName) {
this.clusterName = clusterName;
return this;
}
public Builder created(Date created) {
this.created = created;
return this;
}
public Builder updated(Date updated) {
this.updated = updated;
return this;
}
public Builder connectionLoggingEnabled(boolean connectionLoggingEnabled) {
this.connectionLoggingEnabled = connectionLoggingEnabled;
return this;
}
public LoadBalancer build() {
return new LoadBalancer(region, id, name, protocol, port, algorithm, status, virtualIPs, nodes,
sessionPersistenceType, clusterName, created, updated, connectionLoggingEnabled);
}
@Override
public Builder nodes(Iterable<Node> nodes) {
this.nodes = ImmutableSet.<Node> copyOf(checkNotNull(nodes, "nodes"));
return this;
}
@Override
public Builder node(Node nodes) {
this.nodes.add(checkNotNull(nodes, "nodes"));
return this;
}
@Override
public Builder algorithm(String algorithm) {
return Builder.class.cast(super.algorithm(algorithm));
}
@Override
public Builder from(LoadBalancer in) {
return Builder.class.cast(super.from(in)).id(in.getId()).status(in.getStatus()).virtualIPs(in.getVirtualIPs())
.clusterName(in.getClusterName()).created(in.getCreated()).updated(in.getUpdated())
.connectionLoggingEnabled(in.isConnectionLoggingEnabled());
}
@Override
public Builder name(String name) {
return Builder.class.cast(super.name(name));
}
@Override
public Builder port(int port) {
return Builder.class.cast(super.port(port));
}
@Override
public Builder protocol(String protocol) {
return Builder.class.cast(super.protocol(protocol));
}
}
/**
* All load balancers also have a status attribute to signify the current configuration status of
* the device. This status is immutable by the caller and is updated automatically based on state
* changes within the service. When a load balancer is first created, it will be placed into a
* BUILD status while the configuration is being generated and applied based on the request. Once
* the configuration is applied and finalized, it will be in an ACTIVE status. In the event of a
* configuration change or update, the status of the load balancer will change to PENDING_UPDATE
* to signify configuration changes are in progress but have not yet been finalized. Load
* balancers in a SUSPENDED status are configured to reject traffic and will not forward requests
* to back-end nodess.
*/
public static enum Status {
/**
* Load balancer is being provisioned for the first time and configuration is being applied to
* bring the service online. The service will not yet be ready to serve incoming requests.
*/
BUILD,
/**
* Load balancer is configured properly and ready to serve traffic to incoming requests via
* the configured virtual IPs.
*/
ACTIVE,
/**
* Load balancer is online but configuration changes are being applied to update the service
* based on a previous request.
*/
PENDING_UPDATE,
/**
* Load balancer has been taken offline and disabled; contact Support.
*/
SUSPENDED,
/**
* Load balancer is online but configuration changes are being applied to begin deletion of
* the service based on a previous request.
*/
PENDING_DELETE,
/**
* Load balancers in DELETED status can be displayed for at least 90 days after deletion.
*/
DELETED,
/**
* The system encountered an error when attempting to configure the load balancer; contact
* Support.
*/
ERROR, UNRECOGNIZED;
public static Status fromValue(String status) {
try {
return valueOf(checkNotNull(status, "status"));
} catch (IllegalArgumentException e) {
return UNRECOGNIZED;
}
}
}
private final String region;
private final int id;
private final Status status;
private final Set<VirtualIP> virtualIPs;
private final String sessionPersistenceType;
private final String clusterName;
private final Date created;
private final Date updated;
private final boolean connectionLoggingEnabled;
public LoadBalancer(String region, int id, String name, String protocol, int port, String algorithm, Status status,
Iterable<VirtualIP> virtualIPs, Iterable<Node> nodes, String sessionPersistenceType, String clusterName,
Date created, Date updated, boolean connectionLoggingEnabled) {
super(name, protocol, port, algorithm, nodes);
this.region = checkNotNull(region, "region");
checkArgument(id != -1, "id must be specified");
this.id = id;
this.status = checkNotNull(status, "status");
this.virtualIPs = ImmutableSet.copyOf(checkNotNull(virtualIPs, "virtualIPs"));
this.sessionPersistenceType = sessionPersistenceType;
this.clusterName = clusterName;
this.created = checkNotNull(created, "created");
this.updated = checkNotNull(updated, "updated");
this.connectionLoggingEnabled = connectionLoggingEnabled;
}
public String getRegion() {
return region;
}
public int getId() {
return id;
}
public Status getStatus() {
return status;
}
public Set<VirtualIP> getVirtualIPs() {
return virtualIPs;
}
public String getClusterName() {
return clusterName;
}
public String getSessionPersistenceType() {
return sessionPersistenceType;
}
public Date getCreated() {
return created;
}
public Date getUpdated() {
return updated;
}
public boolean isConnectionLoggingEnabled() {
return connectionLoggingEnabled;
}
@Override
public String toString() {
return String
.format(
"[region=%s, id=%s, name=%s, protocol=%s, port=%s, algorithm=%s, status=%s, virtualIPs=%s, nodes=%s, sessionPersistenceType=%s, created=%s, updated=%s, clusterName=%s, connectionLoggingEnabled=%s]",
region, id, name, protocol, port, algorithm, status, virtualIPs, nodes, sessionPersistenceType,
created, updated, clusterName, connectionLoggingEnabled);
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + id;
result = prime * result + ((region == null) ? 0 : region.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
LoadBalancer other = (LoadBalancer) obj;
if (id != other.id)
return false;
if (region == null) {
if (other.region != null)
return false;
} else if (!region.equals(other.region))
return false;
return true;
}
}

View File

@ -0,0 +1,125 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.cloudloadbalancers.domain;
import org.jclouds.cloudloadbalancers.domain.internal.BaseLoadBalancer;
/**
*
* @author Adrian Cole
* @see <a href=
* "http://docs.rackspacecloud.com/loadbalancers/api/v1.0/clb-devguide/content/ch04s01s02.html"
* />
*/
public class LoadBalancerAttributes {
protected String name;
protected String protocol;
protected Integer port;
protected String algorithm;
public LoadBalancerAttributes name(String name) {
this.name = name;
return this;
}
public LoadBalancerAttributes protocol(String protocol) {
this.protocol = protocol;
return this;
}
public LoadBalancerAttributes port(int port) {
this.port = port;
return this;
}
public LoadBalancerAttributes algorithm(String algorithm) {
this.algorithm = algorithm;
return this;
}
public static <T extends BaseLoadBalancer<?, T>> LoadBalancerAttributes fromLoadBalancer(T lb) {
return Builder.name(lb.getName()).port(lb.getPort()).protocol(lb.getProtocol()).algorithm(lb.getAlgorithm());
}
public static class Builder {
public static LoadBalancerAttributes name(String name) {
return new LoadBalancerAttributes().name(name);
}
public static LoadBalancerAttributes protocol(String protocol) {
return new LoadBalancerAttributes().protocol(protocol);
}
public static LoadBalancerAttributes port(int port) {
return new LoadBalancerAttributes().port(port);
}
public static LoadBalancerAttributes algorithm(String algorithm) {
return new LoadBalancerAttributes().algorithm(algorithm);
}
}
@Override
public String toString() {
return String.format("[algorithm=%s, name=%s, port=%s, protocol=%s]", algorithm, name, port, protocol);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((algorithm == null) ? 0 : algorithm.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((port == null) ? 0 : port.hashCode());
result = prime * result + ((protocol == null) ? 0 : protocol.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
LoadBalancerAttributes other = (LoadBalancerAttributes) obj;
if (algorithm == null) {
if (other.algorithm != null)
return false;
} else if (!algorithm.equals(other.algorithm))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (port == null) {
if (other.port != null)
return false;
} else if (!port.equals(other.port))
return false;
if (protocol == null) {
if (other.protocol != null)
return false;
} else if (!protocol.equals(other.protocol))
return false;
return true;
}
}

View File

@ -0,0 +1,149 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.cloudloadbalancers.domain;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.List;
import java.util.Map;
import org.jclouds.cloudloadbalancers.domain.internal.BaseLoadBalancer;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
/**
*
* @author Adrian Cole
* @see <a href=
* "http://docs.rackspacecloud.com/loadbalancers/api/v1.0/clb-devguide/content/ch04s01s02.html"
* />
*/
public class LoadBalancerRequest extends BaseLoadBalancer<NodeRequest, LoadBalancerRequest> {
@SuppressWarnings("unchecked")
public static Builder builder() {
return new Builder();
}
/**
* {@inheritDoc}
*/
@Override
public Builder toBuilder() {
return new Builder().from(this);
}
public static class Builder extends BaseLoadBalancer.Builder<NodeRequest, LoadBalancerRequest> {
private VirtualIP.Type virtualIPType;
private Integer virtualIPId;
private List<Map<String, String>> virtualIps;
public Builder virtualIPId(Integer virtualIPId) {
this.virtualIPId = virtualIPId;
return this;
}
public Builder virtualIPType(VirtualIP.Type virtualIPType) {
this.virtualIPType = virtualIPType;
return this;
}
public LoadBalancerRequest build() {
return virtualIps == null ? new LoadBalancerRequest(name, protocol, port, algorithm, nodes, virtualIPType,
virtualIPId) : new LoadBalancerRequest(name, protocol, port, algorithm, nodes, virtualIps);
}
@Override
public Builder nodes(Iterable<NodeRequest> nodes) {
this.nodes = ImmutableSet.<NodeRequest> copyOf(checkNotNull(nodes, "nodes"));
return this;
}
@Override
public Builder node(NodeRequest nodes) {
this.nodes.add(checkNotNull(nodes, "nodes"));
return this;
}
private Builder virtualIPs(List<Map<String, String>> virtualIPs) {
this.virtualIps = virtualIPs;
return this;
}
@Override
public Builder algorithm(String algorithm) {
return Builder.class.cast(super.algorithm(algorithm));
}
@Override
public Builder from(LoadBalancerRequest in) {
return Builder.class.cast(super.from(in)).virtualIPs(in.virtualIps);
}
@Override
public Builder name(String name) {
return Builder.class.cast(super.name(name));
}
@Override
public Builder port(int port) {
return Builder.class.cast(super.port(port));
}
@Override
public Builder protocol(String protocol) {
return Builder.class.cast(super.protocol(protocol));
}
}
private final List<Map<String, String>> virtualIps;
public LoadBalancerRequest(String name, String protocol, int port, String algorithm, Iterable<NodeRequest> nodes,
VirtualIP.Type virtualIPType, Integer virtualIPId) {
this(name, protocol, port, algorithm, nodes, getVirtualIPsFromOptions(virtualIPType, virtualIPId));
}
private LoadBalancerRequest(String name, String protocol, int port, String algorithm, Iterable<NodeRequest> nodes,
List<Map<String, String>> virtualIPsFromOptions) {
super(name, protocol, port, algorithm, nodes);
this.virtualIps = checkNotNull(virtualIPsFromOptions, "virtualIPsFromOptions");
}
static List<Map<String, String>> getVirtualIPsFromOptions(VirtualIP.Type virtualIPType, Integer virtualIPId) {
checkArgument(virtualIPType == null || virtualIPId == null,
"virtualIPType and virtualIPId cannot both be specified");
if (virtualIPType != null)
return ImmutableList.<Map<String, String>> of(ImmutableMap.of("type", virtualIPType.name()));
else if (virtualIPId != null)
return ImmutableList.<Map<String, String>> of(ImmutableMap.of("id", virtualIPId.toString()));
else
throw new IllegalArgumentException("virtualIPType or virtualIPId must be specified");
}
@Override
public String toString() {
return String.format("[algorithm=%s, name=%s, nodes=%s, port=%s, protocol=%s, virtualIps=%s]", algorithm, name,
nodes, port, protocol, virtualIps);
}
}

View File

@ -0,0 +1,200 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.cloudloadbalancers.domain;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import org.jclouds.cloudloadbalancers.domain.internal.BaseNode;
/**
* The nodes defined by the load balancer are responsible for servicing the requests received
* through the load balancer's virtual IP. By default, the load balancer employs a basic health
* check that ensures the node is listening on its defined port. The node is checked at the time of
* addition and at regular intervals as defined by the load balancer health check configuration. If
* a back-end node is not listening on its port or does not meet the conditions of the defined
* active health check for the load balancer, then the load balancer will not forward connections
* and its status will be listed as OFFLINE. Only nodes that are in an ONLINE status will receive
* and be able to service traffic from the load balancer.
* <p/>
* All nodes have an associated status that indicates whether the node is ONLINE, OFFLINE, or
* DRAINING. Only nodes that are in ONLINE status will receive and be able to service traffic from
* the load balancer. The OFFLINE status represents a node that cannot accept or service traffic. A
* node in DRAINING status represents a node that stops the traffic manager from sending any
* additional new connections to the node, but honors established sessions. If the traffic manager
* receives a request and session persistence requires that the node is used, the traffic manager
* will use it. The status is determined by the passive or active health monitors.
* <p/>
* If the WEIGHTED_ROUND_ROBIN load balancer algorithm mode is selected, then the caller should
* assign the relevant weights to the node as part of the weight attribute of the node element. When
* the algorithm of the load balancer is changed to WEIGHTED_ROUND_ROBIN and the nodes do not
* already have an assigned weight, the service will automatically set the weight to "1" for all
* nodes.
*
* @author Adrian Cole
* @see <a href=
* "http://docs.rackspacecloud.com/loadbalancers/api/v1.0/clb-devguide/content/ch04s02.html" />
*/
public class Node extends BaseNode<Node> {
@SuppressWarnings("unchecked")
public static Builder builder() {
return new Builder();
}
/**
* {@inheritDoc}
*/
@Override
public Builder toBuilder() {
return new Builder().from(this);
}
public static class Builder extends BaseNode.Builder<Node> {
private int id = -1;
private Status status;
public Builder id(int id) {
this.id = id;
return this;
}
public Builder status(Status status) {
this.status = status;
return this;
}
@Override
public Node build() {
return new Node(id, address, port, condition, status, weight);
}
@Override
public Builder address(String address) {
return Builder.class.cast(super.address(address));
}
@Override
public Builder condition(Condition condition) {
return Builder.class.cast(super.condition(condition));
}
@Override
public Builder from(Node in) {
return Builder.class.cast(super.from(in)).id(in.getId()).status(in.getStatus());
}
@Override
public Builder port(int port) {
return Builder.class.cast(super.port(port));
}
@Override
public Builder weight(Integer weight) {
return Builder.class.cast(super.weight(weight));
}
}
/**
* The status is determined by the passive or active health monitors.
*
*/
public static enum Status {
/**
* Only nodes that are in an ONLINE status will receive and be able to service traffic from
* the load balancer.
*/
ONLINE,
/**
* represents a node that cannot accept or service traffic
*/
OFFLINE,
/**
* represents a node that stops the traffic manager from sending any additional new
* connections to the node, but honors established sessions.
*/
DRAINING,
UNRECOGNIZED;
public static Status fromValue(String status) {
try {
return valueOf(checkNotNull(status, "status"));
} catch (IllegalArgumentException e) {
return UNRECOGNIZED;
}
}
}
private int id;
private Status status;
// for serialization only
Node() {
}
public Node(int id, String address, int port, Condition condition, Status status, Integer weight) {
super(address, port, condition, weight);
checkArgument(id != -1, "id must be specified");
this.id = id;
this.status = checkNotNull(status, "status");
}
public int getId() {
return id;
}
public Status getStatus() {
return status;
}
@Override
public String toString() {
return String.format("[id=%s, address=%s, condition=%s, port=%s, weight=%s,status=%s]", id, address, condition,
port, weight, status);
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + id;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
Node other = (Node) obj;
if (id != other.id)
return false;
return true;
}
}

View File

@ -0,0 +1,109 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.cloudloadbalancers.domain;
import org.jclouds.cloudloadbalancers.domain.internal.BaseNode;
/**
* The nodes defined by the load balancer are responsible for servicing the requests received
* through the load balancer's virtual IP. By default, the load balancer employs a basic health
* check that ensures the node is listening on its defined port. The node is checked at the time of
* addition and at regular intervals as defined by the load balancer health check configuration. If
* a back-end node is not listening on its port or does not meet the conditions of the defined
* active health check for the load balancer, then the load balancer will not forward connections
* and its status will be listed as OFFLINE. Only nodes that are in an ONLINE status will receive
* and be able to service traffic from the load balancer.
* <p/>
* All nodes have an associated status that indicates whether the node is ONLINE, OFFLINE, or
* DRAINING. Only nodes that are in ONLINE status will receive and be able to service traffic from
* the load balancer. The OFFLINE status represents a node that cannot accept or service traffic. A
* node in DRAINING status represents a node that stops the traffic manager from sending any
* additional new connections to the node, but honors established sessions. If the traffic manager
* receives a request and session persistence requires that the node is used, the traffic manager
* will use it. The status is determined by the passive or active health monitors.
* <p/>
* If the WEIGHTED_ROUND_ROBIN load balancer algorithm mode is selected, then the caller should
* assign the relevant weights to the node as part of the weight attribute of the node element. When
* the algorithm of the load balancer is changed to WEIGHTED_ROUND_ROBIN and the nodes do not
* already have an assigned weight, the service will automatically set the weight to "1" for all
* nodes.
*
* @author Adrian Cole
* @see <a href=
* "http://docs.rackspacecloud.com/loadbalancers/api/v1.0/clb-devguide/content/ch04s02.html" />
*/
public class NodeRequest extends BaseNode<NodeRequest> {
@SuppressWarnings("unchecked")
public static Builder builder() {
return new Builder();
}
/**
* {@inheritDoc}
*/
@Override
public Builder toBuilder() {
return new Builder().from(this);
}
public static class Builder extends BaseNode.Builder<NodeRequest> {
@Override
public NodeRequest build() {
return new NodeRequest(address, port, condition, weight);
}
@Override
public Builder address(String address) {
return Builder.class.cast(super.address(address));
}
@Override
public Builder condition(Condition condition) {
return Builder.class.cast(super.condition(condition));
}
@Override
public Builder from(NodeRequest in) {
return Builder.class.cast(super.from(in));
}
@Override
public Builder port(int port) {
return Builder.class.cast(super.port(port));
}
@Override
public Builder weight(Integer weight) {
return Builder.class.cast(super.weight(weight));
}
}
// for serialization only
NodeRequest() {
}
public NodeRequest(String address, int port, Condition condition, Integer weight) {
super(address, port, condition, weight);
}
}

View File

@ -0,0 +1,176 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.cloudloadbalancers.domain;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* A virtual IP (VIP) makes a load balancer accessible by clients. The load balancing service
* supports either a public VIP, routable on the public Internet, or a ServiceNet address, routable
* only within the region in which the load balancer resides.
*
* @author Adrian Cole
* @see <a href=
* "http://docs.rackspacecloud.com/loadbalancers/api/v1.0/clb-devguide/content/ch04s03s01.html"
* />
*/
public class VirtualIP implements Comparable<VirtualIP> {
public static Builder builder() {
return new Builder();
}
public static class Builder {
private int id = -1;
private String address;
private Type type;
private IPVersion ipVersion = IPVersion.IPV4;
public Builder id(int id) {
this.id = id;
return this;
}
public Builder address(String address) {
this.address = address;
return this;
}
public Builder type(Type type) {
this.type = type;
return this;
}
public Builder ipVersion(IPVersion ipVersion) {
this.ipVersion = ipVersion;
return this;
}
public VirtualIP build() {
return new VirtualIP(id, address, type, ipVersion);
}
}
/**
* Virtual IP Types
*/
public static enum Type {
/**
* An address that is routable on the public Internet.
*/
PUBLIC,
/**
* An address that is routable only on ServiceNet.
*/
SERVICENET, UNRECOGNIZED;
public static Type fromValue(String type) {
try {
return valueOf(checkNotNull(type, "type"));
} catch (IllegalArgumentException e) {
return UNRECOGNIZED;
}
}
}
/**
* Virtual IP Versions
*/
public static enum IPVersion {
IPV4, IPV6, UNRECOGNIZED;
public static IPVersion fromValue(String ipVersion) {
try {
return valueOf(checkNotNull(ipVersion, "ipVersion"));
} catch (IllegalArgumentException e) {
return UNRECOGNIZED;
}
}
}
// for serialization only
VirtualIP() {
}
private int id;
private String address;
private Type type;
private IPVersion ipVersion;
public VirtualIP(int id, String address, Type type, IPVersion ipVersion) {
checkArgument(id != -1, "id must be specified");
this.id = id;
this.address = checkNotNull(address, "address");
this.type = checkNotNull(type, "type");
this.ipVersion = checkNotNull(ipVersion, "ipVersion");
}
public int getId() {
return id;
}
public String getAddress() {
return address;
}
public Type getType() {
return type;
}
public IPVersion getIpVersion() {
return ipVersion;
}
@Override
public int compareTo(VirtualIP arg0) {
return address.compareTo(arg0.address);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + id;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
VirtualIP other = (VirtualIP) obj;
if (id != other.id)
return false;
return true;
}
@Override
public String toString() {
return String.format("[address=%s, id=%s, ipVersion=%s, type=%s]", address, id, ipVersion, type);
}
}

View File

@ -0,0 +1,175 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.cloudloadbalancers.domain.internal;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Set;
import java.util.SortedSet;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Sets;
/**
*
* @author Adrian Cole
* @see <a href=
* "http://docs.rackspacecloud.com/loadbalancers/api/v1.0/clb-devguide/content/ch04s01s02.html"
* />
*/
public class BaseLoadBalancer<N extends BaseNode<N>, T extends BaseLoadBalancer<N, T>> implements
Comparable<BaseLoadBalancer<N, T>> {
public static <N extends BaseNode<N>, T extends BaseLoadBalancer<N, T>> Builder<N, T> builder() {
return new Builder<N, T>();
}
@SuppressWarnings("unchecked")
public Builder<N, T> toBuilder() {
return new Builder<N, T>().from((T) this);
}
public static class Builder<N extends BaseNode<N>, T extends BaseLoadBalancer<N, T>> {
protected String name;
protected String protocol;
protected int port = -1;
protected String algorithm;
protected Set<N> nodes = Sets.newLinkedHashSet();
public Builder<N, T> name(String name) {
this.name = name;
return this;
}
public Builder<N, T> protocol(String protocol) {
this.protocol = protocol;
return this;
}
public Builder<N, T> port(int port) {
this.port = port;
return this;
}
public Builder<N, T> algorithm(String algorithm) {
this.algorithm = algorithm;
return this;
}
public Builder<N, T> nodes(Iterable<N> nodes) {
this.nodes = ImmutableSet.<N> copyOf(checkNotNull(nodes, "nodes"));
return this;
}
@SuppressWarnings("unchecked")
public Builder<N, T> node(N node) {
this.nodes.add((N) checkNotNull(nodes, "nodes"));
return this;
}
public BaseLoadBalancer<N, T> build() {
return new BaseLoadBalancer<N, T>(name, protocol, port, algorithm, nodes);
}
public Builder<N, T> from(T baseLoadBalancer) {
return name(baseLoadBalancer.getName()).port(baseLoadBalancer.getPort()).protocol(
baseLoadBalancer.getProtocol()).algorithm(baseLoadBalancer.getAlgorithm()).nodes(
baseLoadBalancer.getNodes());
}
}
// for serialization only
protected BaseLoadBalancer() {
}
protected String name;
protected String protocol;
protected int port;
protected String algorithm;
// so tests will come out consistently
protected SortedSet<N> nodes = ImmutableSortedSet.of();
public BaseLoadBalancer(String name, String protocol, int port, String algorithm, Iterable<N> nodes) {
this.name = checkNotNull(name, "name");
this.protocol = checkNotNull(protocol, "protocol");
checkArgument(port != -1, "port must be specified");
this.port = port;
this.algorithm = algorithm;
this.nodes = ImmutableSortedSet.copyOf(checkNotNull(nodes, "nodes"));
}
@Override
public int compareTo(BaseLoadBalancer<N, T> arg0) {
return name.compareTo(arg0.name);
}
public String getName() {
return name;
}
public String getProtocol() {
return protocol;
}
public int getPort() {
return port;
}
public String getAlgorithm() {
return algorithm;
}
public Set<N> getNodes() {
return nodes;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
BaseLoadBalancer<?, ?> other = (BaseLoadBalancer<?, ?>) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
@Override
public String toString() {
return String.format("[name=%s, port=%s, protocol=%s, algorithm=%s, nodes=%s]", name, port, protocol, algorithm,
nodes);
}
}

View File

@ -0,0 +1,210 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.cloudloadbalancers.domain.internal;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* The nodes defined by the load balancer are responsible for servicing the requests received
* through the load balancer's virtual IP. By default, the load balancer employs a basic health
* check that ensures the node is listening on its defined port. The node is checked at the time of
* addition and at regular intervals as defined by the load balancer health check configuration. If
* a back-end node is not listening on its port or does not meet the conditions of the defined
* active health check for the load balancer, then the load balancer will not forward connections
* and its status will be listed as OFFLINE. Only nodes that are in an ONLINE status will receive
* and be able to service traffic from the load balancer.
* <p/>
* All nodes have an associated status that indicates whether the node is ONLINE, OFFLINE, or
* DRAINING. Only nodes that are in ONLINE status will receive and be able to service traffic from
* the load balancer. The OFFLINE status represents a node that cannot accept or service traffic. A
* node in DRAINING status represents a node that stops the traffic manager from sending any
* additional new connections to the node, but honors established sessions. If the traffic manager
* receives a request and session persistence requires that the node is used, the traffic manager
* will use it. The status is determined by the passive or active health monitors.
* <p/>
* If the WEIGHTED_ROUND_ROBIN load balancer algorithm mode is selected, then the caller should
* assign the relevant weights to the node as part of the weight attribute of the node element. When
* the algorithm of the load balancer is changed to WEIGHTED_ROUND_ROBIN and the nodes do not
* already have an assigned weight, the service will automatically set the weight to "1" for all
* nodes.
*
* @author Adrian Cole
* @see <a href=
* "http://docs.rackspacecloud.com/loadbalancers/api/v1.0/clb-devguide/content/ch04s02.html" />
*/
public class BaseNode<T extends BaseNode<T>> implements Comparable<BaseNode<T>> {
public static <T extends BaseNode<T>> Builder<T> builder() {
return new Builder<T>();
}
@SuppressWarnings("unchecked")
public Builder<T> toBuilder() {
return new Builder<T>().from((T) this);
}
public static class Builder<T extends BaseNode<T>> {
protected String address;
protected int port = -1;
protected Condition condition = Condition.ENABLED;
protected Integer weight;
public Builder<T> address(String address) {
this.address = address;
return this;
}
public Builder<T> port(int port) {
this.port = port;
return this;
}
public Builder<T> condition(Condition condition) {
this.condition = condition;
return this;
}
public Builder<T> weight(Integer weight) {
this.weight = weight;
return this;
}
public BaseNode<T> build() {
return new BaseNode<T>(address, port, condition, weight);
}
public Builder<T> from(T in) {
return address(in.getAddress()).port(in.getPort()).condition(in.getCondition()).weight(in.getWeight());
}
}
/**
* Virtual IP Conditions
*/
public static enum Condition {
/**
* Node is permitted to accept new connections.
*/
ENABLED,
/**
* Node is not permitted to accept any new connections regardless of session persistence
* configuration. Existing connections are forcibly terminated.
*/
DISABLED,
/**
* Node is allowed to service existing established connections and connections that are being
* directed to it as a result of the session persistence configuration.
*/
DRAINING,
UNRECOGNIZED;
public static Condition fromValue(String condition) {
try {
return valueOf(checkNotNull(condition, "condition"));
} catch (IllegalArgumentException e) {
return UNRECOGNIZED;
}
}
}
protected String address;
protected int port;
protected Condition condition;
protected Integer weight;
// for serialization only
protected BaseNode() {
}
public BaseNode(String address, int port, Condition condition, Integer weight) {
this.address = checkNotNull(address, "address");
checkArgument(port != -1, "port must be specified");
this.port = port;
this.condition = checkNotNull(condition, "condition");
this.weight = weight;
}
public String getAddress() {
return address;
}
public int getPort() {
return port;
}
public Condition getCondition() {
return condition;
}
/**
* the maximum weight of a node is 100.
*/
public Integer getWeight() {
return weight;
}
@Override
public int compareTo(BaseNode<T> arg0) {
return address.compareTo(arg0.address);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((address == null) ? 0 : address.hashCode());
result = prime * result + ((condition == null) ? 0 : condition.hashCode());
result = prime * result + port;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
BaseNode<?> other = (BaseNode<?>) obj;
if (address == null) {
if (other.address != null)
return false;
} else if (!address.equals(other.address))
return false;
if (condition == null) {
if (other.condition != null)
return false;
} else if (!condition.equals(other.condition))
return false;
if (port != other.port)
return false;
return true;
}
@Override
public String toString() {
return String.format("[address=%s, condition=%s, port=%s, weight=%s]", address, condition, port, weight);
}
}

View File

@ -0,0 +1,111 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.cloudloadbalancers.features;
import java.util.Set;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.MediaType;
import org.jclouds.cloudloadbalancers.domain.LoadBalancer;
import org.jclouds.cloudloadbalancers.domain.LoadBalancerAttributes;
import org.jclouds.cloudloadbalancers.domain.LoadBalancerRequest;
import org.jclouds.cloudloadbalancers.functions.UnwrapLoadBalancer;
import org.jclouds.cloudloadbalancers.functions.UnwrapLoadBalancers;
import org.jclouds.openstack.filters.AuthenticateRequest;
import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SkipEncoding;
import org.jclouds.rest.annotations.WrapWith;
import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404;
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404;
import com.google.common.util.concurrent.ListenableFuture;
/**
* Provides asynchronous access toRackspace Cloud Load Balancers via their REST API.
* <p/>
*
* @see LoadBalancerClient
* @see <a
* href="http://docs.rackspacecloud.com/loadbalancers/api/v1.0/clb-devguide/content/ch04s01.html"
* />
* @author Adrian Cole
*/
@SkipEncoding('/')
@RequestFilters(AuthenticateRequest.class)
public interface LoadBalancerAsyncClient {
/**
* @see LoadBalancerClient#createLoadBalancer
*/
@POST
@ResponseParser(UnwrapLoadBalancer.class)
@Consumes(MediaType.APPLICATION_JSON)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
@Path("/loadbalancers")
ListenableFuture<LoadBalancer> createLoadBalancer(@WrapWith("loadBalancer") LoadBalancerRequest lb);
/**
* @see LoadBalancerClient#updateLoadBalancerAttributes
*/
@PUT
@ResponseParser(UnwrapLoadBalancer.class)
@Consumes(MediaType.APPLICATION_JSON)
@Path("/loadbalancers/{id}")
ListenableFuture<Void> updateLoadBalancerAttributes(@PathParam("id") int id,
@WrapWith("loadBalancer") LoadBalancerAttributes attrs);
/**
* @see CloudServersClient#listLoadBalancers
*/
@GET
@ResponseParser(UnwrapLoadBalancers.class)
@Consumes(MediaType.APPLICATION_JSON)
@Path("/loadbalancers")
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
ListenableFuture<Set<LoadBalancer>> listLoadBalancers();
/**
* @see LoadBalancerClient#getLoadBalancer
*/
@GET
@ResponseParser(UnwrapLoadBalancer.class)
@Consumes(MediaType.APPLICATION_JSON)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
@Path("/loadbalancers/{id}")
ListenableFuture<LoadBalancer> getLoadBalancer(@PathParam("id") int id);
/**
* @see LoadBalancerClient#removeLoadBalancer
*/
@DELETE
@ExceptionParser(ReturnVoidOnNotFoundOr404.class)
@Path("/loadbalancers/{id}")
ListenableFuture<Void> removeLoadBalancer(@PathParam("id") int id);
}

View File

@ -0,0 +1,110 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.cloudloadbalancers.features;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.jclouds.cloudloadbalancers.domain.LoadBalancer;
import org.jclouds.cloudloadbalancers.domain.LoadBalancerAttributes;
import org.jclouds.cloudloadbalancers.domain.LoadBalancerRequest;
import org.jclouds.concurrent.Timeout;
import org.jclouds.http.HttpResponseException;
/**
* Provides synchronous access to CloudLoadBalancers LoadBalancer features.
* <p/>
*
* @see LoadBalancerAsyncClient
* @see <a
* href="http://docs.rackspacecloud.com/loadbalancers/api/v1.0/clb-devguide/content/ch04s01.html"
* />
* @author Adrian Cole
*/
@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS)
public interface LoadBalancerClient {
/**
* Create a new load balancer with the configuration defined by the request.
*
* <p/>
* This operation asynchronously provisions a new load balancer based on the configuration
* defined in the request object. Once the request is validated and progress has started on the
* provisioning process, a response object will be returned.
*
*
* @param lb
* configuration to create
* @return The object will contain a unique identifier and status of the request. Using the
* identifier, the caller can check on the progress of the operation by performing a
* {@link LoadBalancerClient#getLoadBalancer}.
* @throws HttpResponseException
* If the corresponding request cannot be fulfilled due to insufficient or invalid
* data
*
*/
LoadBalancer createLoadBalancer(LoadBalancerRequest lb);
/**
*
* Update the properties of a load balancer.
*
* <p/>
* This operation asynchronously updates the attributes of the specified load balancer. Upon
* successful validation of the request, the service will return a 202 (Accepted) response code.
* A caller can poll the load balancer with its ID to wait for the changes to be applied and the
* load balancer to return to an ACTIVE status.
*
* @param id
* id of the loadbalancer to change
* @param attrs
* what to change
* @return The object will contain a unique identifier and status of the request. Using the
* identifier, the caller can check on the progress of the operation by performing a
* {@link LoadBalancerClient#getLoadBalancer}.
* @see LoadBalancerAttributes#fromLoadBalancer
*/
void updateLoadBalancerAttributes(int id, LoadBalancerAttributes attrs);
/**
*
* @return all load balancers configured for the account, or empty set if none available
*/
Set<LoadBalancer> listLoadBalancers();
/**
*
*
* @param id
* id of the loadbalancer to retrieve
* @return details of the specified load balancer, or null if not found
*/
LoadBalancer getLoadBalancer(int id);
/**
* Remove a load balancer from the account.
* <p/>
* The remove load balancer function removes the specified load balancer and its associated
* configuration from the account. Any and all configuration data is immediately purged and is
* not recoverable.
*
* @param id
* to remove
*/
void removeLoadBalancer(int id);
}

View File

@ -0,0 +1,56 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.cloudloadbalancers.functions;
import org.jclouds.cloudloadbalancers.domain.LoadBalancer;
import org.jclouds.cloudloadbalancers.domain.LoadBalancer.Builder;
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
/**
* @author Adrian Cole
*/
public class ConvertLB implements Function<LB, LoadBalancer> {
private final String region;
ConvertLB(String region) {
this.region = region.toUpperCase();
}
@Override
public LoadBalancer apply(LB lb) {
Builder builder = LoadBalancer.builder().region(region).name(lb.getName()).port(lb.getPort()).protocol(
lb.getProtocol()).algorithm(lb.getAlgorithm()).nodes(lb.getNodes()).id(lb.id).status(lb.status)
.virtualIPs(lb.virtualIps);
if (lb.cluster.size() == 1)
builder.clusterName(Iterables.get(lb.cluster.values(), 0));
if (lb.sessionPersistence.size() == 1)
builder.sessionPersistenceType(Iterables.get(lb.sessionPersistence.values(), 0));
if (lb.created.size() == 1)
builder.created(Iterables.get(lb.created.values(), 0));
if (lb.updated.size() == 1)
builder.updated(Iterables.get(lb.updated.values(), 0));
if (lb.connectionLogging.size() == 1)
builder.connectionLoggingEnabled(Iterables.get(lb.connectionLogging.values(), 0));
return builder.build();
}
}

View File

@ -0,0 +1,46 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.cloudloadbalancers.functions;
import java.util.Date;
import java.util.Map;
import java.util.Set;
import org.jclouds.cloudloadbalancers.domain.Node;
import org.jclouds.cloudloadbalancers.domain.VirtualIP;
import org.jclouds.cloudloadbalancers.domain.LoadBalancer.Status;
import org.jclouds.cloudloadbalancers.domain.internal.BaseLoadBalancer;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
/**
* only here as the datatype for cloudloadbalancers is awkward.
*
**/
class LB extends BaseLoadBalancer<Node, LB> {
int id;
Status status;
Set<VirtualIP> virtualIps = Sets.newLinkedHashSet();
Map<String, String> sessionPersistence = Maps.newLinkedHashMap();
Map<String, String> cluster = Maps.newLinkedHashMap();
Map<String, Date> created = Maps.newLinkedHashMap();
Map<String, Date> updated = Maps.newLinkedHashMap();
Map<String, Boolean> connectionLogging = Maps.newLinkedHashMap();
}

View File

@ -0,0 +1,66 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.cloudloadbalancers.functions;
import java.util.Map;
import javax.inject.Inject;
import org.jclouds.cloudloadbalancers.domain.LoadBalancer;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.functions.ParseJson;
import org.jclouds.rest.InvocationContext;
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
/**
* @author Adrian Cole
*/
public class UnwrapLoadBalancer implements Function<HttpResponse, LoadBalancer>, InvocationContext<UnwrapLoadBalancer> {
private final ParseJson<Map<String, LB>> json;
private ConvertLB convertLB;
@Inject
UnwrapLoadBalancer(ParseJson<Map<String, LB>> json) {
this.json = json;
}
@Override
public LoadBalancer apply(HttpResponse arg0) {
Map<String, LB> map = json.apply(arg0);
if (map == null || map.size() == 0)
return null;
LB lb = Iterables.get(map.values(), 0);
return convertLB.apply(lb);
}
@Override
public UnwrapLoadBalancer setContext(HttpRequest request) {
return setRegion(request.getEndpoint().getHost().substring(0, request.getEndpoint().getHost().indexOf('.')));
}
UnwrapLoadBalancer setRegion(String region) {
this.convertLB = new ConvertLB(region);
return this;
}
}

View File

@ -0,0 +1,69 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.cloudloadbalancers.functions;
import java.util.Map;
import java.util.Set;
import javax.inject.Inject;
import org.jclouds.cloudloadbalancers.domain.LoadBalancer;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.functions.ParseJson;
import org.jclouds.rest.InvocationContext;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
/**
* @author Adrian Cole
*/
public class UnwrapLoadBalancers implements Function<HttpResponse, Set<LoadBalancer>>,
InvocationContext<UnwrapLoadBalancers> {
private final ParseJson<Map<String, Set<LB>>> json;
private ConvertLB convertLB;
@Inject
UnwrapLoadBalancers(ParseJson<Map<String, Set<LB>>> json) {
this.json = json;
}
@Override
public Set<LoadBalancer> apply(HttpResponse arg0) {
Map<String, Set<LB>> map = json.apply(arg0);
if (map.size() == 0)
return ImmutableSet.<LoadBalancer> of();
;
return ImmutableSet.copyOf(Iterables.transform(Iterables.get(map.values(), 0), convertLB));
}
@Override
public UnwrapLoadBalancers setContext(HttpRequest request) {
return setRegion(request.getEndpoint().getHost().substring(0, request.getEndpoint().getHost().indexOf('.')));
}
UnwrapLoadBalancers setRegion(String region) {
this.convertLB = new ConvertLB(region);
return this;
}
}

View File

@ -0,0 +1,95 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.cloudloadbalancers.handlers;
import static org.jclouds.http.HttpUtils.releasePayload;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Resource;
import javax.inject.Singleton;
import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpErrorHandler;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpResponseException;
import org.jclouds.logging.Logger;
import org.jclouds.rest.AuthorizationException;
import org.jclouds.rest.ResourceNotFoundException;
import org.jclouds.util.Strings2;
/**
*
* @author Adrian Cole
*
*/
@Singleton
public class ParseCloudLoadBalancersErrorFromHttpResponse implements HttpErrorHandler {
@Resource
protected Logger logger = Logger.NULL;
public static final Pattern RESOURCE_PATTERN = Pattern.compile("^/v1[^/]*/[0-9]+/([^/]+)/([0-9]+)");
public void handleError(HttpCommand command, HttpResponse response) {
Exception exception = new HttpResponseException(command, response);
try {
String content = parseErrorFromContentOrNull(command, response);
exception = content != null ? new HttpResponseException(command, response, content) : exception;
switch (response.getStatusCode()) {
case 401:
exception = new AuthorizationException(exception.getMessage(), exception);
break;
case 404:
if (!command.getCurrentRequest().getMethod().equals("DELETE")) {
String path = command.getCurrentRequest().getEndpoint().getPath();
Matcher matcher = RESOURCE_PATTERN.matcher(path);
String message;
if (matcher.find()) {
message = String.format("%s %s not found", matcher.group(1), matcher.group(2));
} else {
message = path;
}
exception = new ResourceNotFoundException(message);
}
break;
case 409:
exception = new IllegalStateException(content);
break;
default:
exception = new HttpResponseException(command, response, content);
break;
}
} finally {
releasePayload(response);
command.setException(exception);
}
}
String parseErrorFromContentOrNull(HttpCommand command, HttpResponse response) {
if (response.getPayload() != null) {
try {
return Strings2.toStringAndClose(response.getPayload().getInput());
} catch (IOException e) {
logger.warn(e, "exception reading error from response", response);
}
}
return null;
}
}

View File

@ -0,0 +1,55 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.cloudloadbalancers.loadbalancer.config;
import org.jclouds.cloudloadbalancers.loadbalancer.strategy.CloudLoadBalancersDestroyLoadBalancerStrategy;
import org.jclouds.cloudloadbalancers.loadbalancer.strategy.CloudLoadBalancersGetLoadBalancerMetadataStrategy;
import org.jclouds.cloudloadbalancers.loadbalancer.strategy.CloudLoadBalancersListLoadBalancersStrategy;
import org.jclouds.cloudloadbalancers.loadbalancer.strategy.CloudLoadBalancersLoadBalanceNodesStrategy;
import org.jclouds.loadbalancer.config.BindLoadBalancerStrategiesByClass;
import org.jclouds.loadbalancer.strategy.DestroyLoadBalancerStrategy;
import org.jclouds.loadbalancer.strategy.GetLoadBalancerMetadataStrategy;
import org.jclouds.loadbalancer.strategy.ListLoadBalancersStrategy;
import org.jclouds.loadbalancer.strategy.LoadBalanceNodesStrategy;
/**
* @author Adrian Cole
*/
public class CloudLoadBalancersBindLoadBalancerStrategiesByClass extends BindLoadBalancerStrategiesByClass {
@Override
protected Class<? extends LoadBalanceNodesStrategy> defineLoadBalanceNodesStrategy() {
return CloudLoadBalancersLoadBalanceNodesStrategy.class;
}
@Override
protected Class<? extends DestroyLoadBalancerStrategy> defineDestroyLoadBalancerStrategy() {
return CloudLoadBalancersDestroyLoadBalancerStrategy.class;
}
@Override
protected Class<? extends GetLoadBalancerMetadataStrategy> defineGetLoadBalancerMetadataStrategy() {
return CloudLoadBalancersGetLoadBalancerMetadataStrategy.class;
}
@Override
protected Class<? extends ListLoadBalancersStrategy> defineListLoadBalancersStrategy() {
return CloudLoadBalancersListLoadBalancersStrategy.class;
}
}

View File

@ -0,0 +1,38 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.cloudloadbalancers.loadbalancer.config;
import java.util.Set;
import org.jclouds.domain.Location;
import org.jclouds.loadbalancer.config.BindLoadBalancerSuppliersByClass;
import org.jclouds.location.suppliers.RegionToProviderOrJustProvider;
import com.google.common.base.Supplier;
/**
* @author Adrian Cole
*/
public class CloudLoadBalancersBindLoadBalancerSuppliersByClass extends BindLoadBalancerSuppliersByClass {
@Override
protected Class<? extends Supplier<Set<? extends Location>>> defineLocationSupplier() {
return RegionToProviderOrJustProvider.class;
}
}

View File

@ -0,0 +1,38 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.cloudloadbalancers.loadbalancer.config;
import org.jclouds.loadbalancer.config.BaseLoadBalancerServiceContextModule;
/**
* Configures the CloudLoadBalancers connection.
*
* @author Adrian Cole
*/
public class CloudLoadBalancersLoadBalancerContextModule extends BaseLoadBalancerServiceContextModule {
@Override
protected void configure() {
install(new CloudLoadBalancersBindLoadBalancerSuppliersByClass());
install(new CloudLoadBalancersBindLoadBalancerStrategiesByClass());
install(new CloudLoadBalancersLoadBalancerServiceDependenciesModule());
super.configure();
}
}

View File

@ -0,0 +1,41 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.cloudloadbalancers.loadbalancer.config;
import org.jclouds.cloudloadbalancers.domain.LoadBalancer;
import org.jclouds.cloudloadbalancers.loadbalancer.functions.LoadBalancerToLoadBalancerMetadata;
import org.jclouds.loadbalancer.domain.LoadBalancerMetadata;
import com.google.common.base.Function;
import com.google.inject.AbstractModule;
import com.google.inject.TypeLiteral;
/**
*
* @author Adrian Cole
*/
public class CloudLoadBalancersLoadBalancerServiceDependenciesModule extends AbstractModule {
@Override
protected void configure() {
bind(new TypeLiteral<Function<LoadBalancer, LoadBalancerMetadata>>() {
}).to(LoadBalancerToLoadBalancerMetadata.class);
}
}

View File

@ -0,0 +1,72 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.cloudloadbalancers.loadbalancer.functions;
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.cloudloadbalancers.domain.LoadBalancer;
import org.jclouds.cloudloadbalancers.domain.VirtualIP;
import org.jclouds.domain.Location;
import org.jclouds.loadbalancer.domain.LoadBalancerMetadata;
import org.jclouds.loadbalancer.domain.LoadBalancerType;
import org.jclouds.loadbalancer.domain.internal.LoadBalancerMetadataImpl;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
/**
*
* @author Adrian Cole
*/
@Singleton
public class LoadBalancerToLoadBalancerMetadata implements Function<LoadBalancer, LoadBalancerMetadata> {
protected final Supplier<Map<String, ? extends Location>> locationMap;
protected final Supplier<Location> defaultLocationSupplier;
@Inject
public LoadBalancerToLoadBalancerMetadata(Supplier<Location> defaultLocationSupplier,
Supplier<Map<String, ? extends Location>> locationMap) {
this.locationMap = locationMap;
this.defaultLocationSupplier = defaultLocationSupplier;
}
@Override
public LoadBalancerMetadata apply(LoadBalancer input) {
Location location = locationMap.get().get(input.getRegion());
String id = input.getRegion() + "/" + input.getId();
// TODO Builder
return new LoadBalancerMetadataImpl(LoadBalancerType.LB, input.getName(), input.getName(), id, location, null,
ImmutableMap.<String, String> of(), Iterables.transform(input.getVirtualIPs(),
new Function<VirtualIP, String>() {
@Override
public String apply(VirtualIP arg0) {
return arg0.getAddress();
}
}));
}
}

View File

@ -0,0 +1,63 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.cloudloadbalancers.loadbalancer.strategy;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.cloudloadbalancers.CloudLoadBalancersClient;
import org.jclouds.loadbalancer.domain.LoadBalancerMetadata;
import org.jclouds.loadbalancer.reference.LoadBalancerConstants;
import org.jclouds.loadbalancer.strategy.DestroyLoadBalancerStrategy;
import org.jclouds.loadbalancer.strategy.GetLoadBalancerMetadataStrategy;
import org.jclouds.logging.Logger;
/**
*
* @author Adrian Cole
*/
@Singleton
public class CloudLoadBalancersDestroyLoadBalancerStrategy implements DestroyLoadBalancerStrategy {
@Resource
@Named(LoadBalancerConstants.LOADBALANCER_LOGGER)
protected Logger logger = Logger.NULL;
private final CloudLoadBalancersClient client;
private final GetLoadBalancerMetadataStrategy getLoadBalancer;
@Inject
protected CloudLoadBalancersDestroyLoadBalancerStrategy(CloudLoadBalancersClient client,
GetLoadBalancerMetadataStrategy getLoadBalancer) {
this.client = checkNotNull(client, "client");
this.getLoadBalancer = checkNotNull(getLoadBalancer, "getLoadBalancer");
}
@Override
public LoadBalancerMetadata destroyLoadBalancer(String id) {
String[] parts = checkNotNull(id, "id").split("/");
String region = parts[0];
int lbId = Integer.parseInt(parts[1]);
client.getLoadBalancerClient(region).removeLoadBalancer(lbId);
return getLoadBalancer.getLoadBalancer(id);
}
}

View File

@ -0,0 +1,58 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.cloudloadbalancers.loadbalancer.strategy;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.cloudloadbalancers.CloudLoadBalancersClient;
import org.jclouds.cloudloadbalancers.domain.LoadBalancer;
import org.jclouds.loadbalancer.domain.LoadBalancerMetadata;
import org.jclouds.loadbalancer.strategy.GetLoadBalancerMetadataStrategy;
import com.google.common.base.Function;
/**
*
* @author Adrian Cole
*/
@Singleton
public class CloudLoadBalancersGetLoadBalancerMetadataStrategy implements GetLoadBalancerMetadataStrategy {
private final org.jclouds.cloudloadbalancers.CloudLoadBalancersClient client;
private final Function<LoadBalancer, LoadBalancerMetadata> converter;
@Inject
protected CloudLoadBalancersGetLoadBalancerMetadataStrategy(CloudLoadBalancersClient client,
Function<LoadBalancer, LoadBalancerMetadata> converter) {
this.client = checkNotNull(client, "client");
this.converter = checkNotNull(converter, "converter");
}
@Override
public LoadBalancerMetadata getLoadBalancer(String id) {
String[] parts = checkNotNull(id, "id").split("/");
String region = parts[0];
int lbId = Integer.parseInt(parts[1]);
return converter.apply(client.getLoadBalancerClient(region).getLoadBalancer(lbId));
}
}

View File

@ -0,0 +1,84 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.cloudloadbalancers.loadbalancer.strategy;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.concat;
import static com.google.common.collect.Iterables.transform;
import static org.jclouds.concurrent.FutureIterables.transformParallel;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import javax.annotation.Nullable;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.Constants;
import org.jclouds.cloudloadbalancers.CloudLoadBalancersAsyncClient;
import org.jclouds.cloudloadbalancers.domain.LoadBalancer;
import org.jclouds.loadbalancer.domain.LoadBalancerMetadata;
import org.jclouds.loadbalancer.reference.LoadBalancerConstants;
import org.jclouds.loadbalancer.strategy.ListLoadBalancersStrategy;
import org.jclouds.location.Region;
import org.jclouds.logging.Logger;
import com.google.common.base.Function;
import com.google.common.util.concurrent.ListenableFuture;
/**
*
* @author Adrian Cole
*/
@Singleton
public class CloudLoadBalancersListLoadBalancersStrategy implements ListLoadBalancersStrategy {
@Resource
@Named(LoadBalancerConstants.LOADBALANCER_LOGGER)
protected Logger logger = Logger.NULL;
private final CloudLoadBalancersAsyncClient aclient;
private final Function<LoadBalancer, LoadBalancerMetadata> converter;
private final ExecutorService executor;
private final Set<String> regions;
@Inject
protected CloudLoadBalancersListLoadBalancersStrategy(CloudLoadBalancersAsyncClient aclient,
Function<LoadBalancer, LoadBalancerMetadata> converter,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor, @Nullable @Region Set<String> regions) {
this.aclient = checkNotNull(aclient, "aclient");
this.regions = checkNotNull(regions, "regions");
this.converter = checkNotNull(converter, "converter");
this.executor = checkNotNull(executor, "executor");
}
@Override
public Iterable<? extends LoadBalancerMetadata> listLoadBalancers() {
return transform(concat(transformParallel(regions, new Function<String, Future<Set<LoadBalancer>>>() {
@Override
public ListenableFuture<Set<LoadBalancer>> apply(String from) {
return aclient.getLoadBalancerClient(from).listLoadBalancers();
}
}, executor, null, logger, "loadbalancers")), converter);
}
}

View File

@ -0,0 +1,85 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.cloudloadbalancers.loadbalancer.strategy;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.cloudloadbalancers.CloudLoadBalancersClient;
import org.jclouds.cloudloadbalancers.domain.LoadBalancer;
import org.jclouds.cloudloadbalancers.domain.LoadBalancerRequest;
import org.jclouds.cloudloadbalancers.domain.NodeRequest;
import org.jclouds.cloudloadbalancers.domain.VirtualIP.Type;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.domain.Location;
import org.jclouds.loadbalancer.domain.LoadBalancerMetadata;
import org.jclouds.loadbalancer.reference.LoadBalancerConstants;
import org.jclouds.loadbalancer.strategy.GetLoadBalancerMetadataStrategy;
import org.jclouds.loadbalancer.strategy.LoadBalanceNodesStrategy;
import org.jclouds.logging.Logger;
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
/**
*
* @author Adrian Cole
*/
@Singleton
public class CloudLoadBalancersLoadBalanceNodesStrategy implements LoadBalanceNodesStrategy {
@Resource
@Named(LoadBalancerConstants.LOADBALANCER_LOGGER)
protected Logger logger = Logger.NULL;
protected final CloudLoadBalancersClient client;
protected final GetLoadBalancerMetadataStrategy getLB;
@Inject
protected CloudLoadBalancersLoadBalanceNodesStrategy(CloudLoadBalancersClient client,
GetLoadBalancerMetadataStrategy getLB) {
this.client = checkNotNull(client, "client");
this.getLB = checkNotNull(getLB, "getLB");
}
@Override
public LoadBalancerMetadata createLoadBalancerInLocation(Location location, String name, String protocol,
int loadBalancerPort, final int instancePort, Iterable<? extends NodeMetadata> nodes) {
String region = checkNotNull(location, "location").getId();
// TODO need to query and update the LB per current design.
LoadBalancer lb = client.getLoadBalancerClient(region).createLoadBalancer(
LoadBalancerRequest.builder().name(name).protocol(protocol.toUpperCase()).port(loadBalancerPort)
.virtualIPType(Type.PUBLIC).nodes(
Iterables.transform(nodes, new Function<NodeMetadata, NodeRequest>() {
@Override
public NodeRequest apply(NodeMetadata arg0) {
return NodeRequest.builder().address(
Iterables.get(arg0.getPrivateAddresses(), 0)).port(instancePort)
.build();
}
})).build());
return getLB.getLoadBalancer(region + "/" + lb.getId());
}
}

View File

@ -0,0 +1,63 @@
package org.jclouds.cloudloadbalancers.options;
import static com.google.common.base.Preconditions.checkArgument;
import org.jclouds.http.options.BaseHttpRequestOptions;
import com.google.common.collect.ImmutableSet;
/**
* To reduce load on the service, list operations will return a maximum of 100 items at a time. To
* navigate the collection, the limit and marker parameters (for example, ?limit=50&marker=1 ) can
* be set in the URI. If a marker beyond the end of a list is given, an empty list is returned. Note
* that list operations never return 404 (itemNotFound) faults.
*
* @see <a
* href="http://docs.rackspacecloud.com/loadbalancers/api/v1.0/clb-devguide/content/ch03s06.html"
* />
* @author Adrian Cole
*/
public class ListOptions extends BaseHttpRequestOptions {
public static final ListOptions NONE = new ListOptions();
/**
* Indicates where to begin listing, if the previous list was larger than the limit.
*/
public ListOptions marker(String marker) {
checkArgument(marker != null, "marker cannot be null");
queryParameters.replaceValues("marker", ImmutableSet.of(marker));
return this;
}
/**
* To reduce load on the service, list operations will return a maximum of 100 items at a time.
* <p/>
* Note that list operations never return itemNotFound (404) faults.
*/
public ListOptions limit(int limit) {
checkArgument(limit >= 0, "limit must be >= 0");
checkArgument(limit <= 10000, "limit must be <= 10000");
queryParameters.replaceValues("limit", ImmutableSet.of(limit + ""));
return this;
}
public static class Builder {
/**
* @see ListOptions#marker(marker)
*/
public static ListOptions marker(String marker) {
ListOptions options = new ListOptions();
return options.marker(marker);
}
/**
* @see ListOptions#limit(long)
*/
public static ListOptions limit(int limit) {
ListOptions options = new ListOptions();
return options.limit(limit);
}
}
}

View File

@ -0,0 +1,68 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.cloudloadbalancers.predicates;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.annotation.Resource;
import javax.inject.Singleton;
import org.jclouds.cloudloadbalancers.CloudLoadBalancersClient;
import org.jclouds.cloudloadbalancers.domain.LoadBalancer;
import org.jclouds.cloudloadbalancers.domain.LoadBalancer.Status;
import org.jclouds.logging.Logger;
import com.google.common.base.Predicate;
import com.google.inject.Inject;
/**
*
* Tests to see if a loadBalancer is running
*
* @author Adrian Cole
*/
@Singleton
public class LoadBalancerActive implements Predicate<LoadBalancer> {
private final CloudLoadBalancersClient client;
@Resource
protected Logger logger = Logger.NULL;
@Inject
public LoadBalancerActive(CloudLoadBalancersClient client) {
this.client = client;
}
public boolean apply(LoadBalancer loadBalancer) {
logger.trace("looking for status on loadBalancer %s", checkNotNull(loadBalancer, "loadBalancer"));
loadBalancer = refresh(loadBalancer);
if (loadBalancer == null)
return false;
logger.trace("%s: looking for loadBalancer status %s: currently: %s", loadBalancer.getId(), Status.ACTIVE,
loadBalancer.getStatus());
if (loadBalancer.getStatus() == Status.ERROR)
throw new IllegalStateException("loadBalancer in error status: " + loadBalancer);
return loadBalancer.getStatus() == Status.ACTIVE;
}
private LoadBalancer refresh(LoadBalancer loadBalancer) {
return client.getLoadBalancerClient(loadBalancer.getRegion()).getLoadBalancer(loadBalancer.getId());
}
}

View File

@ -0,0 +1,66 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.cloudloadbalancers.predicates;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.annotation.Resource;
import javax.inject.Singleton;
import org.jclouds.cloudloadbalancers.CloudLoadBalancersClient;
import org.jclouds.cloudloadbalancers.domain.LoadBalancer;
import org.jclouds.cloudloadbalancers.domain.LoadBalancer.Status;
import org.jclouds.logging.Logger;
import com.google.common.base.Predicate;
import com.google.inject.Inject;
/**
*
* Tests to see if a loadBalancer is deleted
*
* @author Adrian Cole
*/
@Singleton
public class LoadBalancerDeleted implements Predicate<LoadBalancer> {
private final CloudLoadBalancersClient client;
@Resource
protected Logger logger = Logger.NULL;
@Inject
public LoadBalancerDeleted(CloudLoadBalancersClient client) {
this.client = client;
}
public boolean apply(LoadBalancer loadBalancer) {
logger.trace("looking for status on loadBalancer %s", checkNotNull(loadBalancer, "loadBalancer"));
loadBalancer = refresh(loadBalancer);
if (loadBalancer == null)
return true;
logger.trace("%s: looking for loadBalancer status %s: currently: %s", loadBalancer.getId(), Status.DELETED,
loadBalancer.getStatus());
return loadBalancer.getStatus() == Status.DELETED;
}
private LoadBalancer refresh(LoadBalancer loadBalancer) {
return client.getLoadBalancerClient(loadBalancer.getRegion()).getLoadBalancer(loadBalancer.getId());
}
}

View File

@ -0,0 +1,29 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.cloudloadbalancers.reference;
/**
* Configuration properties and constants used in rackspace connections.
*
* @author Adrian Cole
*/
public interface RackspaceConstants {
public static final String PROPERTY_ACCOUNT_ID = "jclouds.rackspace.account-id";
}

View File

@ -0,0 +1,53 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.cloudloadbalancers.reference;
/**
* The load balancing service is a regionalized service. It allows the caller to select a region
* into which a load balancer is to be provisioned.
* <p/>
* If load balancing Cloud Servers, you can determine the appropriate region to select by viewing
* your Cloud Servers list and creating a load balancer within the same region as the data center in
* which your Cloud Server resides. When your resources reside in the same region as your load
* balancer, devices are in close proximity to each other and can take advantage of ServiceNet
* connectivity for free data transfer between services.
* <p/>
* If load balancing external servers, you can determine the appropriate region to select by
* choosing the region that is geographically as close to your external servers as possible.
*
* @see <a
* href="http://docs.rackspacecloud.com/loadbalancers/api/v1.0/clb-devguide/content/ch03s02.html"
* />
* @author Adrian Cole
*/
public interface Region {
/**
* Chicago (ORD) https://ord.loadbalancers.api.rackspacecloud.com/v1.0/1234/
*/
public final static String ORD = "ORD";
/**
* Dallas/Ft. Worth (DFW) https://dfw.loadbalancers.api.rackspacecloud.com/v1.0/1234/
*/
public final static String DFW = "DFW";
}

View File

@ -0,0 +1,70 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.cloudloadbalancers;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import org.jclouds.cloudloadbalancers.features.BaseCloudLoadBalancersAsyncClientTest;
import org.jclouds.http.HttpRequest;
import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import com.google.inject.TypeLiteral;
/**
* Tests behavior of {@code CloudLoadBalancersAsyncClient}
*
* @author Adrian Cole
*/
// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
@Test(groups = "unit", testName = "CloudLoadBalancersAsyncClientTest")
public class CloudLoadBalancersAsyncClientTest extends BaseCloudLoadBalancersAsyncClientTest<CloudLoadBalancersAsyncClient> {
private CloudLoadBalancersAsyncClient asyncClient;
private CloudLoadBalancersClient syncClient;
public void testSync() throws SecurityException, NoSuchMethodException, InterruptedException, ExecutionException {
assert syncClient.getLoadBalancerClient("DFW") != null;
}
public void testAsync() throws SecurityException, NoSuchMethodException, InterruptedException, ExecutionException {
assert asyncClient.getLoadBalancerClient("DFW") != null;
}
@Override
protected TypeLiteral<RestAnnotationProcessor<CloudLoadBalancersAsyncClient>> createTypeLiteral() {
return new TypeLiteral<RestAnnotationProcessor<CloudLoadBalancersAsyncClient>>() {
};
}
@BeforeClass
@Override
protected void setupFactory() throws IOException {
super.setupFactory();
asyncClient = injector.getInstance(CloudLoadBalancersAsyncClient.class);
syncClient = injector.getInstance(CloudLoadBalancersClient.class);
}
@Override
protected void checkFilters(HttpRequest request) {
}
}

View File

@ -0,0 +1,88 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.cloudloadbalancers.features;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import java.util.Properties;
import org.jclouds.cloudloadbalancers.CloudLoadBalancersAsyncClient;
import org.jclouds.cloudloadbalancers.CloudLoadBalancersClient;
import org.jclouds.cloudloadbalancers.config.CloudLoadBalancersRestClientModule;
import org.jclouds.cloudloadbalancers.reference.Region;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.RequiresHttp;
import org.jclouds.internal.ClassMethodArgs;
import org.jclouds.openstack.OpenStackAuthAsyncClient.AuthenticationResponse;
import org.jclouds.openstack.filters.AuthenticateRequest;
import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.RestClientTest;
import org.jclouds.rest.RestContextFactory;
import org.jclouds.rest.RestContextSpec;
import org.testng.annotations.BeforeClass;
import com.google.common.base.Supplier;
import com.google.common.base.Throwables;
import com.google.inject.Module;
/**
* @author Adrian Cole
*/
public abstract class BaseCloudLoadBalancersAsyncClientTest<T> extends RestClientTest<T> {
@RequiresHttp
@ConfiguresRestClient
public static class CloudLoadBalancersRestClientModuleExtension extends CloudLoadBalancersRestClientModule {
@Override
protected String accountID(Supplier<AuthenticationResponse> in) {
return "1234";
}
}
@Override
protected void checkFilters(HttpRequest request) {
assertEquals(request.getFilters().size(), 1);
assertEquals(request.getFilters().get(0).getClass(), AuthenticateRequest.class);
}
@Override
protected Module createModule() {
return new CloudLoadBalancersRestClientModuleExtension();
}
@Override
public RestContextSpec<CloudLoadBalancersClient, CloudLoadBalancersAsyncClient> createContextSpec() {
Properties props = new Properties();
return new RestContextFactory().createContextSpec("cloudloadbalancers-us", "email", "apikey", props);
}
@BeforeClass
@Override
protected void setupFactory() throws IOException {
super.setupFactory();
try {
processor.setCaller(new ClassMethodArgs(CloudLoadBalancersAsyncClient.class,
CloudLoadBalancersAsyncClient.class.getMethod("getLoadBalancerClient", String.class),
new Object[] { Region.DFW }));
} catch (Exception e) {
Throwables.propagate(e);
}
}
}

View File

@ -0,0 +1,112 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.cloudloadbalancers.features;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
import org.jclouds.Constants;
import org.jclouds.cloudloadbalancers.CloudLoadBalancersAsyncClient;
import org.jclouds.cloudloadbalancers.CloudLoadBalancersClient;
import org.jclouds.cloudloadbalancers.domain.LoadBalancer;
import org.jclouds.cloudloadbalancers.predicates.LoadBalancerActive;
import org.jclouds.cloudloadbalancers.predicates.LoadBalancerDeleted;
import org.jclouds.loadbalancer.LoadBalancerServiceContextFactory;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.net.IPSocket;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.rest.RestContext;
import org.testng.annotations.AfterGroups;
import org.testng.annotations.BeforeGroups;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Module;
/**
*
* @author Adrian Cole
*/
public class BaseCloudLoadBalancersClientLiveTest {
protected String prefix = System.getProperty("user.name");
protected CloudLoadBalancersClient client;
protected RestContext<CloudLoadBalancersClient, CloudLoadBalancersAsyncClient> context;
protected String provider = "cloudloadbalancers-us";
protected String identity;
protected String credential;
protected String endpoint;
protected String apiversion;
protected Predicate<IPSocket> socketTester;
protected RetryablePredicate<LoadBalancer> loadBalancerActive;
protected RetryablePredicate<LoadBalancer> loadBalancerDeleted;
protected Injector injector;
protected void setupCredentials() {
identity = checkNotNull(System.getProperty("test." + provider + ".identity"), "test." + provider
+ ".identity must be set. ex. apiKey");
credential = checkNotNull(System.getProperty("test." + provider + ".credential"), "test." + provider
+ ".credential must be set. ex. secretKey");
endpoint = System.getProperty("test." + provider + ".endpoint");
apiversion = System.getProperty("test." + provider + ".apiversion");
}
protected Properties setupProperties() {
Properties overrides = new Properties();
overrides.setProperty(Constants.PROPERTY_TRUST_ALL_CERTS, "true");
overrides.setProperty(Constants.PROPERTY_RELAX_HOSTNAME, "true");
overrides.setProperty(provider + ".identity", identity);
overrides.setProperty(provider + ".credential", credential);
if (endpoint != null)
overrides.setProperty(provider + ".endpoint", endpoint);
if (apiversion != null)
overrides.setProperty(provider + ".apiversion", apiversion);
return overrides;
}
@BeforeGroups(groups = "live")
public void setupClient() {
setupCredentials();
Properties overrides = setupProperties();
context = new LoadBalancerServiceContextFactory().createContext(provider, ImmutableSet.<Module> of(new Log4JLoggingModule()),
overrides).getProviderSpecificContext();
client = context.getApi();
injector = Guice.createInjector(new Log4JLoggingModule());
loadBalancerActive = new RetryablePredicate<LoadBalancer>(new LoadBalancerActive(client), 30, 1, 1,
TimeUnit.SECONDS);
injector.injectMembers(loadBalancerActive);
loadBalancerDeleted = new RetryablePredicate<LoadBalancer>(new LoadBalancerDeleted(client), 30, 1, 1,
TimeUnit.SECONDS);
injector.injectMembers(loadBalancerDeleted);
}
@AfterGroups(groups = "live")
protected void tearDown() {
if (context != null)
context.close();
}
}

View File

@ -0,0 +1,166 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.cloudloadbalancers.features;
import java.io.IOException;
import java.lang.reflect.Method;
import org.jclouds.cloudloadbalancers.domain.LoadBalancerAttributes;
import org.jclouds.cloudloadbalancers.domain.LoadBalancerRequest;
import org.jclouds.cloudloadbalancers.domain.LoadBalancerAttributes.Builder;
import org.jclouds.cloudloadbalancers.domain.VirtualIP.Type;
import org.jclouds.cloudloadbalancers.functions.UnwrapLoadBalancer;
import org.jclouds.cloudloadbalancers.functions.UnwrapLoadBalancers;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.functions.ReleasePayloadAndReturn;
import org.jclouds.rest.functions.MapHttp4xxCodesToExceptions;
import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404;
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404;
import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.testng.annotations.Test;
import com.google.inject.TypeLiteral;
/**
* Tests behavior of {@code LoadBalancerAsyncClient}
*
* @author Adrian Cole
*/
// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
@Test(groups = "unit", testName = "LoadBalancerAsyncClientTest")
public class LoadBalancerAsyncClientTest extends BaseCloudLoadBalancersAsyncClientTest<LoadBalancerAsyncClient> {
public void testListLoadBalancers() throws SecurityException, NoSuchMethodException, IOException {
Method method = LoadBalancerAsyncClient.class.getMethod("listLoadBalancers");
HttpRequest httpRequest = processor.createRequest(method);
assertRequestLineEquals(httpRequest,
"GET https://dfw.loadbalancers.api.rackspacecloud.com/v1.0/1234/loadbalancers HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null, null, false);
assertResponseParserClassEquals(method, httpRequest, UnwrapLoadBalancers.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, ReturnEmptySetOnNotFoundOr404.class);
checkFilters(httpRequest);
}
public void testGetLoadBalancer() throws SecurityException, NoSuchMethodException, IOException {
Method method = LoadBalancerAsyncClient.class.getMethod("getLoadBalancer", int.class);
HttpRequest httpRequest = processor.createRequest(method, 5);
assertRequestLineEquals(httpRequest,
"GET https://dfw.loadbalancers.api.rackspacecloud.com/v1.0/1234/loadbalancers/5 HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null, null, false);
assertResponseParserClassEquals(method, httpRequest, UnwrapLoadBalancer.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
checkFilters(httpRequest);
}
public void testCreateLoadBalancerWithType() throws SecurityException, NoSuchMethodException, IOException {
Method method = LoadBalancerAsyncClient.class.getMethod("createLoadBalancer", LoadBalancerRequest.class);
HttpRequest httpRequest = processor.createRequest(method, LoadBalancerRequest.builder().name("goo").protocol(
"HTTP").port(80).virtualIPType(Type.PUBLIC).build());
assertRequestLineEquals(httpRequest,
"POST https://dfw.loadbalancers.api.rackspacecloud.com/v1.0/1234/loadbalancers HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(
httpRequest,
"{\"loadBalancer\":{\"virtualIps\":[{\"type\":\"PUBLIC\"}],\"name\":\"goo\",\"protocol\":\"HTTP\",\"port\":80,\"nodes\":[]}}",
"application/json", false);
assertResponseParserClassEquals(method, httpRequest, UnwrapLoadBalancer.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
checkFilters(httpRequest);
}
public void testCreateLoadBalancerWithId() throws SecurityException, NoSuchMethodException, IOException {
Method method = LoadBalancerAsyncClient.class.getMethod("createLoadBalancer", LoadBalancerRequest.class);
HttpRequest httpRequest = processor.createRequest(method, LoadBalancerRequest.builder().name("goo").protocol(
"HTTP").port(80).virtualIPId(4).build());
assertRequestLineEquals(httpRequest,
"POST https://dfw.loadbalancers.api.rackspacecloud.com/v1.0/1234/loadbalancers HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(
httpRequest,
"{\"loadBalancer\":{\"virtualIps\":[{\"id\":\"4\"}],\"name\":\"goo\",\"protocol\":\"HTTP\",\"port\":80,\"nodes\":[]}}",
"application/json", false);
assertResponseParserClassEquals(method, httpRequest, UnwrapLoadBalancer.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
checkFilters(httpRequest);
}
public void testUpdateLoadBalancerAttributes() throws SecurityException, NoSuchMethodException, IOException {
Method method = LoadBalancerAsyncClient.class.getMethod("updateLoadBalancerAttributes", int.class,
LoadBalancerAttributes.class);
HttpRequest httpRequest = processor.createRequest(method, 2, Builder.name("foo"));
assertRequestLineEquals(httpRequest,
"PUT https://dfw.loadbalancers.api.rackspacecloud.com/v1.0/1234/loadbalancers/2 HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, "{\"loadBalancer\":{\"name\":\"foo\"}}", "application/json", false);
assertResponseParserClassEquals(method, httpRequest, UnwrapLoadBalancer.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, MapHttp4xxCodesToExceptions.class);
checkFilters(httpRequest);
}
public void testRemoveLoadBalancer() throws SecurityException, NoSuchMethodException, IOException {
Method method = LoadBalancerAsyncClient.class.getMethod("removeLoadBalancer", int.class);
HttpRequest httpRequest = processor.createRequest(method, 5);
assertRequestLineEquals(httpRequest,
"DELETE https://dfw.loadbalancers.api.rackspacecloud.com/v1.0/1234/loadbalancers/5 HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "");
assertPayloadEquals(httpRequest, null, null, false);
assertResponseParserClassEquals(method, httpRequest, ReleasePayloadAndReturn.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, ReturnVoidOnNotFoundOr404.class);
checkFilters(httpRequest);
}
@Override
protected TypeLiteral<RestAnnotationProcessor<LoadBalancerAsyncClient>> createTypeLiteral() {
return new TypeLiteral<RestAnnotationProcessor<LoadBalancerAsyncClient>>() {
};
}
}

View File

@ -0,0 +1,129 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.cloudloadbalancers.features;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import java.util.Set;
import java.util.logging.Logger;
import org.jclouds.cloudloadbalancers.domain.LoadBalancer;
import org.jclouds.cloudloadbalancers.domain.LoadBalancerAttributes;
import org.jclouds.cloudloadbalancers.domain.LoadBalancerRequest;
import org.jclouds.cloudloadbalancers.domain.NodeRequest;
import org.jclouds.cloudloadbalancers.domain.VirtualIP.Type;
import org.testng.annotations.AfterGroups;
import org.testng.annotations.Test;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
/**
* Tests behavior of {@code LoadBalancerClientLiveTest}
*
* @author Adrian Cole
*/
@Test(groups = "live", singleThreaded = true, testName = "LoadBalancerClientLiveTest")
public class LoadBalancerClientLiveTest extends BaseCloudLoadBalancersClientLiveTest {
private Set<LoadBalancer> lbs = Sets.newLinkedHashSet();
// ticket 130960 getting 500 errors deleting load balancers
@AfterGroups(groups = "live")
protected void tearDown() {
for (LoadBalancer lb : lbs) {
client.getLoadBalancerClient(lb.getRegion()).removeLoadBalancer(lb.getId());
assert loadBalancerDeleted.apply(lb) : lb;
}
super.tearDown();
}
public void testListLoadBalancers() throws Exception {
for (String region : client.getConfiguredRegions()) {
Set<LoadBalancer> response = client.getLoadBalancerClient(region).listLoadBalancers();
assert null != response;
assertTrue(response.size() >= 0);
for (LoadBalancer lb : response) {
assert lb.getRegion() != null : lb;
assert lb.getName() != null : lb;
assert lb.getId() != -1 : lb;
assert lb.getProtocol() != null : lb;
assert lb.getPort() != -1 : lb;
assert lb.getStatus() != null : lb;
assert lb.getCreated() != null : lb;
assert lb.getUpdated() != null : lb;
assert lb.getVirtualIPs().size() > 0 : lb;
// node info not available during list;
assert lb.getNodes().size() == 0 : lb;
LoadBalancer getDetails = client.getLoadBalancerClient(region).getLoadBalancer(lb.getId());
assertEquals(getDetails.getRegion(), lb.getRegion());
assertEquals(getDetails.getName(), lb.getName());
assertEquals(getDetails.getId(), lb.getId());
assertEquals(getDetails.getProtocol(), lb.getProtocol());
assertEquals(getDetails.getPort(), lb.getPort());
assertEquals(getDetails.getStatus(), lb.getStatus());
assertEquals(getDetails.getCreated(), lb.getCreated());
assertEquals(getDetails.getUpdated(), lb.getUpdated());
assertEquals(getDetails.getVirtualIPs(), lb.getVirtualIPs());
// node info not available during list;
assert getDetails.getNodes().size() > 0 : lb;
}
}
}
public void testCreateLoadBalancer() throws Exception {
for (String region : client.getConfiguredRegions()) {
Logger.getAnonymousLogger().info("starting lb in region " + region);
LoadBalancer lb = client.getLoadBalancerClient(region).createLoadBalancer(
LoadBalancerRequest.builder().name(prefix + "-" + region).protocol("HTTP").port(80).virtualIPType(
Type.PUBLIC).node(NodeRequest.builder().address("192.168.1.1").port(8080).build()).build());
checkLBInRegion(region, lb, prefix + "-" + region);
assertEquals(lb.getStatus(), LoadBalancer.Status.BUILD);
lbs.add(lb);
assert loadBalancerActive.apply(lb) : lb;
LoadBalancer newLb = client.getLoadBalancerClient(region).getLoadBalancer(lb.getId());
checkLBInRegion(region, newLb, prefix + "-" + region);
assertEquals(newLb.getStatus(), LoadBalancer.Status.ACTIVE);
}
}
@Test(dependsOnMethods = "testCreateLoadBalancer")
public void testUpdateLoadBalancer() throws Exception {
for (LoadBalancer lb : lbs) {
client.getLoadBalancerClient(lb.getRegion()).updateLoadBalancerAttributes(lb.getId(),
LoadBalancerAttributes.Builder.name("foo" + "-" + lb.getRegion()));
assert loadBalancerActive.apply(lb) : lb;
LoadBalancer newLb = client.getLoadBalancerClient(lb.getRegion()).getLoadBalancer(lb.getId());
checkLBInRegion(newLb.getRegion(), newLb, "foo" + "-" + lb.getRegion());
assertEquals(newLb.getStatus(), LoadBalancer.Status.ACTIVE);
}
}
private void checkLBInRegion(String region, LoadBalancer lb, String name) {
assertEquals(lb.getRegion(), region);
assertEquals(lb.getName(), name);
assertEquals(lb.getProtocol(), "HTTP");
assertEquals(lb.getPort(), 80);
assertEquals(Iterables.get(lb.getVirtualIPs(), 0).getType(), Type.PUBLIC);
}
}

View File

@ -0,0 +1,79 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.cloudloadbalancers.functions;
import org.jclouds.cloudloadbalancers.domain.LoadBalancer;
import org.jclouds.cloudloadbalancers.domain.Node;
import org.jclouds.cloudloadbalancers.domain.VirtualIP;
import org.jclouds.cloudloadbalancers.domain.LoadBalancer.Status;
import org.jclouds.cloudloadbalancers.domain.VirtualIP.IPVersion;
import org.jclouds.date.internal.SimpleDateFormatDateService;
import org.jclouds.http.HttpResponse;
import org.jclouds.json.BaseItemParserTest;
import org.testng.annotations.Test;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Injector;
/**
*
* @author Adrian Cole
*/
@Test(groups = "unit")
public class UnwrapLoadBalancerTest extends BaseItemParserTest<LoadBalancer> {
@Override
public Class<LoadBalancer> type() {
return LoadBalancer.class;
}
@Override
public String resource() {
return "/getloadbalancer.json";
}
@Override
public LoadBalancer expected() {
return LoadBalancer.builder().region("DFW").id(2000).name("sample-loadbalancer").protocol("HTTP").port(80)
.algorithm("RANDOM").status(Status.ACTIVE).connectionLoggingEnabled(true).virtualIPs(
ImmutableSet.of(VirtualIP.builder().id(1000).address("206.10.10.210").type(
VirtualIP.Type.PUBLIC).ipVersion(IPVersion.IPV4).build()))
.nodes(
ImmutableSet.of(Node.builder().id(1041).address("10.1.1.1").port(80).condition(
Node.Condition.ENABLED).status(Node.Status.ONLINE).build(), Node.builder().id(1411)
.address("10.1.1.2").port(80).condition(Node.Condition.ENABLED).status(
Node.Status.ONLINE).build())).sessionPersistenceType("HTTP_COOKIE")
// connectionThrottle({
// minConnections(10)
// maxConnections(100)
// maxConnectionRate(50)
// rateInterval(60
// })
.clusterName("c1.dfw1").created(
new SimpleDateFormatDateService().iso8601SecondsDateParse("2010-11-30T03:23:42Z")).updated(
new SimpleDateFormatDateService().iso8601SecondsDateParse("2010-11-30T03:23:44Z")).build();
}
@Override
protected Function<HttpResponse, LoadBalancer> getParser(Injector i) {
return i.getInstance(UnwrapLoadBalancer.class).setRegion("DFW");
}
}

View File

@ -0,0 +1,76 @@
/**
*
* Copyright (C) 2011 Cloud Conscious) LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.cloudloadbalancers.functions;
import java.util.Set;
import org.jclouds.cloudloadbalancers.domain.LoadBalancer;
import org.jclouds.cloudloadbalancers.domain.VirtualIP;
import org.jclouds.cloudloadbalancers.domain.LoadBalancer.Status;
import org.jclouds.date.internal.SimpleDateFormatDateService;
import org.jclouds.http.HttpResponse;
import org.jclouds.json.BaseSetParserTest;
import org.testng.annotations.Test;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Injector;
/**
*
* @author Adrian Cole
*/
@Test(groups = "unit")
public class UnwrapLoadBalancersTest extends BaseSetParserTest<LoadBalancer> {
@Override
public Class<LoadBalancer> type() {
return LoadBalancer.class;
}
@Override
public String resource() {
return "/listloadbalancers.json";
}
@Override
public Set<LoadBalancer> expected() {
return ImmutableSet.of(
LoadBalancer.builder().region("DFW").name("lb-site1").id(71).protocol("HTTP").port(80).algorithm("RANDOM")
.status(Status.ACTIVE).virtualIPs(
ImmutableSet.of(VirtualIP.builder().id(403).address("206.55.130.1").type(VirtualIP.Type.PUBLIC)
.ipVersion(VirtualIP.IPVersion.IPV4).build())).created(
new SimpleDateFormatDateService().iso8601SecondsDateParse("2010-11-30T03:23:42Z")).updated(
new SimpleDateFormatDateService().iso8601SecondsDateParse("2010-11-30T03:23:44Z")).build(),
LoadBalancer.builder().region("DFW").name("lb-site2").id(166).protocol("HTTP").port(80).algorithm(
"RANDOM").status(Status.ACTIVE).virtualIPs(
ImmutableSet.of(VirtualIP.builder().id(401).address("206.55.130.2").type(VirtualIP.Type.PUBLIC)
.ipVersion(VirtualIP.IPVersion.IPV4).build())).created(
new SimpleDateFormatDateService().iso8601SecondsDateParse("2010-11-30T03:23:42Z")).updated(
new SimpleDateFormatDateService().iso8601SecondsDateParse("2010-11-30T03:23:44Z")).build());
}
@Override
protected Function<HttpResponse, Set<LoadBalancer>> getParser(Injector i) {
return i.getInstance(UnwrapLoadBalancers.class).setRegion("DFW");
}
}

View File

@ -0,0 +1,50 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.cloudloadbalancers.handlers;
import java.net.URI;
import org.jclouds.http.handlers.BaseHttpErrorHandlerTest;
import org.jclouds.rest.ResourceNotFoundException;
import org.testng.annotations.Test;
/**
*
* @author Adrian Cole
*/
@Test(groups = { "unit" })
public class ParseCloudLoadBalancersErrorFromHttpResponseTest extends
BaseHttpErrorHandlerTest<ParseCloudLoadBalancersErrorFromHttpResponse> {
@Test
public void test404NotFound() {
assertCodeMakes(
"GET",
URI.create("https://ord.loadbalancers.api.rackspacecloud.com/v1.0/1234/loadbalancers/2000"),
404,
"Not Found",
"<itemNotFound code=\"404\" xmlns=\"http://docs.openstack.org/loadbalancers/api/v1.0\">\n <message>Object not Found</message>\n</itemNotFound>",
ResourceNotFoundException.class, "loadbalancers 2000 not found");
}
@Override
protected Class<ParseCloudLoadBalancersErrorFromHttpResponse> getClassToTest() {
return ParseCloudLoadBalancersErrorFromHttpResponse.class;
}
}

View File

@ -0,0 +1,59 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.cloudloadbalancers.options;
import static org.jclouds.cloudloadbalancers.options.ListOptions.Builder.limit;
import static org.jclouds.cloudloadbalancers.options.ListOptions.Builder.marker;
import static org.testng.Assert.assertEquals;
import org.jclouds.cloudloadbalancers.options.ListOptions;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
/**
* Tests behavior of {@code ListOptions}
*
* @author Adrian Cole
*/
@Test(groups = "unit")
public class ListOptionsTest {
public void testMarker() {
ListOptions options = new ListOptions().marker("1");
assertEquals(ImmutableList.of("1"), options.buildQueryParameters().get("marker"));
}
public void testLimit() {
int limit = 1;
ListOptions options = new ListOptions().limit(limit);
assertEquals(ImmutableList.of("1"), options.buildQueryParameters().get("limit"));
}
public void testMarkerStatic() {
ListOptions options = marker("1");
assertEquals(ImmutableList.of("1"), options.buildQueryParameters().get("marker"));
}
public void testLimitStatic() {
ListOptions options = limit(1);
assertEquals(ImmutableList.of("1"), options.buildQueryParameters().get("limit"));
}
}

View File

@ -0,0 +1,55 @@
{
"loadBalancer":{
"id": 2000,
"name":"sample-loadbalancer",
"protocol":"HTTP",
"port": 80,
"algorithm":"RANDOM",
"status":"ACTIVE",
"connectionLogging":{
"enabled":"true"
},
"virtualIps":[
{
"id": 1000,
"address":"206.10.10.210",
"type":"PUBLIC",
"ipVersion":"IPV4"
}
],
"nodes":[
{
"id": 1041,
"address":"10.1.1.1",
"port": 80,
"condition":"ENABLED",
"status":"ONLINE"
},
{
"id": 1411,
"address":"10.1.1.2",
"port": 80,
"condition":"ENABLED",
"status":"ONLINE"
}
],
"sessionPersistence":{
"persistenceType":"HTTP_COOKIE"
},
"connectionThrottle":{
"minConnections": 10,
"maxConnections": 100,
"maxConnectionRate": 50,
"rateInterval": 60
},
"cluster":{
"name":"c1.dfw1"
},
"created":{
"time":"2010-11-30T03:23:42Z"
},
"updated":{
"time":"2010-11-30T03:23:44Z"
}
}
}

View File

@ -0,0 +1,48 @@
{
"loadBalancers":[
{
"name":"lb-site1",
"id":"71",
"protocol":"HTTP",
"port":"80",
"algorithm":"RANDOM",
"status":"ACTIVE",
"virtualIps":[
{
"id":"403",
"address":"206.55.130.1",
"type":"PUBLIC",
"ipVersion":"IPV4"
}
],
"created":{
"time":"2010-11-30T03:23:42Z"
},
"updated":{
"time":"2010-11-30T03:23:44Z"
}
},
{
"name":"lb-site2",
"id":"166",
"protocol":"HTTP",
"port":"80",
"algorithm":"RANDOM",
"status":"ACTIVE",
"virtualIps":[
{
"id":"401",
"address":"206.55.130.2",
"type":"PUBLIC",
"ipVersion":"IPV4"
}
],
"created":{
"time":"2010-11-30T03:23:42Z"
},
"updated":{
"time":"2010-11-30T03:23:44Z"
}
}
]
}

View File

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

View File

@ -52,6 +52,7 @@
<module>cloudservers-uk</module>
<module>cloudfiles-us</module>
<module>cloudfiles-uk</module>
<module>cloudloadbalancers-us</module>
<module>bluelock-vcdirector</module>
<module>trmk-ecloud</module>
<module>trmk-vcloudexpress</module>