Issue 158: started softlayer

This commit is contained in:
Adrian Cole 2011-02-21 14:43:14 -08:00
parent 90d3cf4654
commit 56f1d7266a
11 changed files with 1223 additions and 0 deletions

View File

@ -0,0 +1,129 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
$HeadURL$
$Revision$
$Date$
Copyright (C) 2011 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>softlayer</artifactId>
<name>jclouds SoftLayer core</name>
<description>jclouds components to access SoftLayer</description>
<!-- bootstrapping: need to fetch the project POM -->
<repositories>
<repository>
<id>jclouds-sona-snapshots-nexus</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<properties>
<test.softlayer.endpoint>https://api.softlayer.com/rest</test.softlayer.endpoint>
<test.softlayer.apiversion>3</test.softlayer.apiversion>
<test.softlayer.identity>FIXME</test.softlayer.identity>
<test.softlayer.credential>FIXME</test.softlayer.credential>
</properties>
<dependencies>
<dependency>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-core</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>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
<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.softlayer.endpoint</name>
<value>${test.softlayer.endpoint}</value>
</property>
<property>
<name>test.softlayer.apiversion</name>
<value>${test.softlayer.apiversion}</value>
</property>
<property>
<name>test.softlayer.identity</name>
<value>${test.softlayer.identity}</value>
</property>
<property>
<name>test.softlayer.credential</name>
<value>${test.softlayer.credential}</value>
</property>
</systemProperties>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

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.softlayer;
import java.util.Set;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.MediaType;
import org.jclouds.http.filters.BasicAuthentication;
import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404;
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
import org.jclouds.softlayer.domain.VirtualGuest;
import com.google.common.util.concurrent.ListenableFuture;
/**
* Provides asynchronous access to SoftLayer via their REST API.
* <p/>
*
* @see SoftLayerClient
* @see <a href="http://sldn.softlayer.com/wiki/index.php/REST" />
* @author Adrian Cole
*/
@RequestFilters(BasicAuthentication.class)
@Path("/v{jclouds.api-version}")
public interface SoftLayerAsyncClient {
/**
* @see SoftLayerClient#listVirtualGuests
*/
@GET
@Path("/SoftLayer_Account/VirtualGuests.json")
@Consumes(MediaType.APPLICATION_JSON)
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
ListenableFuture<Set<VirtualGuest>> listVirtualGuests();
/**
* @see SoftLayerClient#getVirtualGuest
*/
@GET
@Path("/SoftLayer_Virtual_Guest/{id}.json")
@Consumes(MediaType.APPLICATION_JSON)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<VirtualGuest> getVirtualGuest(@PathParam("id") long 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.softlayer;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.jclouds.concurrent.Timeout;
import org.jclouds.softlayer.domain.VirtualGuest;
/**
* Provides synchronous access to SoftLayer.
* <p/>
*
* @see SoftLayerAsyncClient
* @see <a href="http://sldn.softlayer.com/wiki/index.php/REST" />
* @author Adrian Cole
*/
@Timeout(duration = 4, timeUnit = TimeUnit.SECONDS)
public interface SoftLayerClient {
/**
*
* @return an account's associated virtual guest objects.
*/
Set<VirtualGuest> listVirtualGuests();
/**
*
* @param id
* id of the virtual guest
* @return virtual guest or null if not found
*/
VirtualGuest getVirtualGuest(long id);
}

View File

@ -0,0 +1,45 @@
/**
*
* 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.softlayer;
import java.util.List;
import java.util.Properties;
import org.jclouds.softlayer.config.SoftLayerRestClientModule;
import org.jclouds.rest.RestContextBuilder;
import com.google.inject.Module;
/**
*
* @author Adrian Cole
*/
public class SoftLayerContextBuilder extends
RestContextBuilder<SoftLayerClient, SoftLayerAsyncClient> {
public SoftLayerContextBuilder(Properties props) {
super(SoftLayerClient.class, SoftLayerAsyncClient.class, props);
}
protected void addClientModule(List<Module> modules) {
modules.add(new SoftLayerRestClientModule());
}
}

View File

@ -0,0 +1,47 @@
/**
*
* 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.softlayer;
import static org.jclouds.Constants.PROPERTY_API_VERSION;
import static org.jclouds.Constants.PROPERTY_ENDPOINT;
import java.util.Properties;
import org.jclouds.PropertiesBuilder;
/**
* Builds properties used in SoftLayer Clients
*
* @author Adrian Cole
*/
public class SoftLayerPropertiesBuilder extends PropertiesBuilder {
@Override
protected Properties defaultProperties() {
Properties properties = super.defaultProperties();
properties.setProperty(PROPERTY_ENDPOINT, "https://api.softlayer.com/rest");
properties.setProperty(PROPERTY_API_VERSION, "3");
return properties;
}
public SoftLayerPropertiesBuilder(Properties properties) {
super(properties);
}
}

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.softlayer.config;
import org.jclouds.http.HttpErrorHandler;
import org.jclouds.http.HttpRetryHandler;
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.http.handlers.BackoffLimitedRetryHandler;
import org.jclouds.json.config.GsonModule.DateAdapter;
import org.jclouds.json.config.GsonModule.Iso8601DateAdapter;
import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.config.RestClientModule;
import org.jclouds.softlayer.SoftLayerAsyncClient;
import org.jclouds.softlayer.SoftLayerClient;
import org.jclouds.softlayer.handlers.SoftLayerErrorHandler;
/**
* Configures the SoftLayer connection.
*
* @author Adrian Cole
*/
@RequiresHttp
@ConfiguresRestClient
public class SoftLayerRestClientModule extends RestClientModule<SoftLayerClient, SoftLayerAsyncClient> {
public SoftLayerRestClientModule() {
super(SoftLayerClient.class, SoftLayerAsyncClient.class);
}
@Override
protected void configure() {
bind(DateAdapter.class).to(Iso8601DateAdapter.class);
super.configure();
}
@Override
protected void bindErrorHandlers() {
bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(SoftLayerErrorHandler.class);
bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(SoftLayerErrorHandler.class);
bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(SoftLayerErrorHandler.class);
}
@Override
protected void bindRetryHandlers() {
bind(HttpRetryHandler.class).annotatedWith(ClientError.class).to(BackoffLimitedRetryHandler.class);
}
}

View File

@ -0,0 +1,397 @@
/**
*
* 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.softlayer.domain;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Date;
import com.google.common.base.CaseFormat;
import com.google.gson.annotations.SerializedName;
/**
* The virtual guest data type presents the structure in which all virtual guests will be presented.
* Internally, the structure supports various virtualization platforms with no change to external
* interaction. <br/>
* A guest, also known as a virtual server or CloudLayer Computing Instance, represents an
* allocation of resources on a virtual host.
*
* @author Adrian Cole
* @see <a href=
* "http://sldn.softlayer.com/wiki/index.php/SoftLayer_Virtual_Guest_%28type%29#Local_Properties"
* />
*/
public class VirtualGuest implements Comparable<VirtualGuest> {
public static Builder builder() {
return new Builder();
}
public static class Builder {
}
public static enum State {
STARTING, RUNNING, STOPPING, STOPPED, DESTROYED, EXPUNGING, MIGRATING, ERROR, UNKNOWN, SHUTDOWNED, UNRECOGNIZED;
@Override
public String toString() {
return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, name());
}
public static State fromValue(String state) {
try {
return valueOf(CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, checkNotNull(state, "state")));
} catch (IllegalArgumentException e) {
return UNRECOGNIZED;
}
}
}
private long accountId = -1;
private Date createDate;
@SerializedName("dedicatedAccountHostOnlyFlag")
private boolean dedicatedAccountHostOnly;
private String domain;
private String fullyQualifiedDomainName;
private String hostname;
private long id = -1;
private Date lastVerifiedDate;
private int maxCpu = -1;
private String maxCpuUnits;
private int maxMemory = -1;
private Date metricPollDate;
private Date modifyDate;
private String notes;
@SerializedName("privateNetworkOnlyFlag")
private boolean privateNetworkOnly;
private int startCpus = -1;
private int statusId = -1;
private String uuid;
private String primaryBackendIpAddress;
private String primaryIpAddress;
// for deserializer
VirtualGuest() {
}
public VirtualGuest(long accountId, Date createDate, boolean dedicatedAccountHostOnly, String domain,
String fullyQualifiedDomainName, String hostname, long id, Date lastVerifiedDate, int maxCpu,
String maxCpuUnits, int maxMemory, Date metricPollDate, Date modifyDate, String notes,
boolean privateNetworkOnly, int startCpus, int statusId, String uuid, String primaryBackendIpAddress,
String primaryIpAddress) {
this.accountId = accountId;
this.createDate = createDate;
this.dedicatedAccountHostOnly = dedicatedAccountHostOnly;
this.domain = domain;
this.fullyQualifiedDomainName = fullyQualifiedDomainName;
this.hostname = hostname;
this.id = id;
this.lastVerifiedDate = lastVerifiedDate;
this.maxCpu = maxCpu;
this.maxCpuUnits = maxCpuUnits;
this.maxMemory = maxMemory;
this.metricPollDate = metricPollDate;
this.modifyDate = modifyDate;
this.notes = notes;
this.privateNetworkOnly = privateNetworkOnly;
this.startCpus = startCpus;
this.statusId = statusId;
this.uuid = uuid;
this.primaryBackendIpAddress = primaryBackendIpAddress;
this.primaryIpAddress = primaryIpAddress;
}
@Override
public int compareTo(VirtualGuest arg0) {
return new Long(id).compareTo(arg0.getId());
}
/**
* @return A computing instance's associated account id
*/
public long getAccountId() {
return accountId;
}
/**
* @return The date a virtual computing instance was created.
*/
public Date getCreateDate() {
return createDate;
}
/**
* @return When true this flag specifies that a compute instance is to run on hosts that only
* have guests from the same account.
*/
public boolean isDedicatedAccountHostOnly() {
return dedicatedAccountHostOnly;
}
/**
* @return A computing instance's domain name
*/
public String getDomain() {
return domain;
}
/**
* @return A name reflecting the hostname and domain of the computing instance.
*/
public String getFullyQualifiedDomainName() {
return fullyQualifiedDomainName;
}
/**
* @return A virtual computing instance's hostname
*/
public String getHostname() {
return hostname;
}
/**
* @return Unique ID for a computing instance.
*/
public long getId() {
return id;
}
/**
* @return The last timestamp of when the guest was verified as a resident virtual machine on the
* host's hypervisor platform.
*/
public Date getLastVerifiedDate() {
return lastVerifiedDate;
}
/**
* @return The maximum amount of CPU resources a computing instance may utilize.
*/
public int getMaxCpu() {
return maxCpu;
}
/**
* @return The unit of the maximum amount of CPU resources a computing instance may utilize.
*/
public String getMaxCpuUnits() {
return maxCpuUnits;
}
/**
* @return The maximum amount of memory a computing instance may utilize.
*/
public int getMaxMemory() {
return maxMemory;
}
/**
* @return The date of the most recent metric tracking poll performed.
*/
public Date getMetricPollDate() {
return metricPollDate;
}
/**
* @return The date a virtual computing instance was last modified.
*/
public Date getModifyDate() {
return modifyDate;
}
/**
* @return A small note about a cloud instance to use at your discretion.
*/
public String getNotes() {
return notes;
}
/**
* @return Whether the computing instance only has access to the private network.
*/
public boolean isPrivateNetworkOnly() {
return privateNetworkOnly;
}
/**
* @return The number of CPUs available to a computing instance upon startup.
*/
public int getStartCpus() {
return startCpus;
}
/**
* @return A computing instances status ID
*/
public int getStatusId() {
return statusId;
}
/**
* @return Unique ID for a computing instance's record on a virtualization platform.
*/
public String getUuid() {
return uuid;
}
/**
* @return private ip address
*/
public String getPrimaryBackendIpAddress() {
return primaryBackendIpAddress;
}
/**
* @return public ip address
*/
public String getPrimaryIpAddress() {
return primaryIpAddress;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (int) (accountId ^ (accountId >>> 32));
result = prime * result + ((createDate == null) ? 0 : createDate.hashCode());
result = prime * result + (dedicatedAccountHostOnly ? 1231 : 1237);
result = prime * result + ((domain == null) ? 0 : domain.hashCode());
result = prime * result + ((fullyQualifiedDomainName == null) ? 0 : fullyQualifiedDomainName.hashCode());
result = prime * result + ((hostname == null) ? 0 : hostname.hashCode());
result = prime * result + (int) (id ^ (id >>> 32));
result = prime * result + ((lastVerifiedDate == null) ? 0 : lastVerifiedDate.hashCode());
result = prime * result + maxCpu;
result = prime * result + ((maxCpuUnits == null) ? 0 : maxCpuUnits.hashCode());
result = prime * result + maxMemory;
result = prime * result + ((metricPollDate == null) ? 0 : metricPollDate.hashCode());
result = prime * result + ((modifyDate == null) ? 0 : modifyDate.hashCode());
result = prime * result + ((notes == null) ? 0 : notes.hashCode());
result = prime * result + ((primaryBackendIpAddress == null) ? 0 : primaryBackendIpAddress.hashCode());
result = prime * result + ((primaryIpAddress == null) ? 0 : primaryIpAddress.hashCode());
result = prime * result + (privateNetworkOnly ? 1231 : 1237);
result = prime * result + startCpus;
result = prime * result + statusId;
result = prime * result + ((uuid == null) ? 0 : uuid.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;
VirtualGuest other = (VirtualGuest) obj;
if (accountId != other.accountId)
return false;
if (createDate == null) {
if (other.createDate != null)
return false;
} else if (!createDate.equals(other.createDate))
return false;
if (dedicatedAccountHostOnly != other.dedicatedAccountHostOnly)
return false;
if (domain == null) {
if (other.domain != null)
return false;
} else if (!domain.equals(other.domain))
return false;
if (fullyQualifiedDomainName == null) {
if (other.fullyQualifiedDomainName != null)
return false;
} else if (!fullyQualifiedDomainName.equals(other.fullyQualifiedDomainName))
return false;
if (hostname == null) {
if (other.hostname != null)
return false;
} else if (!hostname.equals(other.hostname))
return false;
if (id != other.id)
return false;
if (lastVerifiedDate == null) {
if (other.lastVerifiedDate != null)
return false;
} else if (!lastVerifiedDate.equals(other.lastVerifiedDate))
return false;
if (maxCpu != other.maxCpu)
return false;
if (maxCpuUnits == null) {
if (other.maxCpuUnits != null)
return false;
} else if (!maxCpuUnits.equals(other.maxCpuUnits))
return false;
if (maxMemory != other.maxMemory)
return false;
if (metricPollDate == null) {
if (other.metricPollDate != null)
return false;
} else if (!metricPollDate.equals(other.metricPollDate))
return false;
if (modifyDate == null) {
if (other.modifyDate != null)
return false;
} else if (!modifyDate.equals(other.modifyDate))
return false;
if (notes == null) {
if (other.notes != null)
return false;
} else if (!notes.equals(other.notes))
return false;
if (primaryBackendIpAddress == null) {
if (other.primaryBackendIpAddress != null)
return false;
} else if (!primaryBackendIpAddress.equals(other.primaryBackendIpAddress))
return false;
if (primaryIpAddress == null) {
if (other.primaryIpAddress != null)
return false;
} else if (!primaryIpAddress.equals(other.primaryIpAddress))
return false;
if (privateNetworkOnly != other.privateNetworkOnly)
return false;
if (startCpus != other.startCpus)
return false;
if (statusId != other.statusId)
return false;
if (uuid == null) {
if (other.uuid != null)
return false;
} else if (!uuid.equals(other.uuid))
return false;
return true;
}
@Override
public String toString() {
return "[accountId=" + accountId + ", createDate=" + createDate + ", dedicatedAccountHostOnly="
+ dedicatedAccountHostOnly + ", domain=" + domain + ", fullyQualifiedDomainName="
+ fullyQualifiedDomainName + ", hostname=" + hostname + ", id=" + id + ", lastVerifiedDate="
+ lastVerifiedDate + ", maxCpu=" + maxCpu + ", maxCpuUnits=" + maxCpuUnits + ", maxMemory=" + maxMemory
+ ", metricPollDate=" + metricPollDate + ", modifyDate=" + modifyDate + ", notes=" + notes
+ ", primaryBackendIpAddress=" + primaryBackendIpAddress + ", primaryIpAddress=" + primaryIpAddress
+ ", privateNetworkOnly=" + privateNetworkOnly + ", startCpus=" + startCpus + ", statusId=" + statusId
+ ", uuid=" + uuid + "]";
}
}

View File

@ -0,0 +1,91 @@
/**
*
* 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.softlayer.handlers;
import java.io.IOException;
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;
import com.google.common.base.Throwables;
import com.google.common.io.Closeables;
/**
* This will parse and set an appropriate exception on the command object.
*
* @author Adrian Cole
*
*/
@Singleton
public class SoftLayerErrorHandler implements HttpErrorHandler {
@Resource
protected Logger logger = Logger.NULL;
public void handleError(HttpCommand command, HttpResponse response) {
// it is important to always read fully and close streams
String message = parseMessage(response);
Exception exception = message != null ? new HttpResponseException(command, response, message)
: new HttpResponseException(command, response);
try {
message = message != null ? message : String.format("%s -> %s", command.getCurrentRequest().getRequestLine(),
response.getStatusLine());
switch (response.getStatusCode()) {
case 401:
case 403:
exception = new AuthorizationException(message, exception);
break;
case 404:
if (!command.getCurrentRequest().getMethod().equals("DELETE")) {
exception = new ResourceNotFoundException(message, exception);
}
break;
}
} finally {
if (response.getPayload() != null)
Closeables.closeQuietly(response.getPayload().getInput());
command.setException(exception);
}
}
public String parseMessage(HttpResponse response) {
if (response.getPayload() == null)
return null;
try {
return Strings2.toStringAndClose(response.getPayload().getInput());
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
try {
response.getPayload().getInput().close();
} catch (IOException e) {
Throwables.propagate(e);
}
}
}
}

View File

@ -0,0 +1,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.softlayer;
import static org.jclouds.rest.RestContextFactory.contextSpec;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import java.lang.reflect.Method;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.filters.BasicAuthentication;
import org.jclouds.http.functions.ParseJson;
import org.jclouds.rest.RestClientTest;
import org.jclouds.rest.RestContextSpec;
import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404;
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.testng.annotations.Test;
import com.google.common.collect.Iterables;
import com.google.inject.TypeLiteral;
/**
* Tests annotation parsing of {@code SoftLayerAsyncClient}
*
* @author Adrian Cole
*/
@Test(groups = "unit")
public class SoftLayerAsyncClientTest extends RestClientTest<SoftLayerAsyncClient> {
public void testListVirtualGuests() throws SecurityException, NoSuchMethodException, IOException {
Method method = SoftLayerAsyncClient.class.getMethod("listVirtualGuests");
HttpRequest httpRequest = processor.createRequest(method);
assertRequestLineEquals(httpRequest,
"GET https://api.softlayer.com/rest/v3/SoftLayer_Account/VirtualGuests.json HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null, null, false);
// now make sure request filters apply by replaying
httpRequest = Iterables.getOnlyElement(httpRequest.getFilters()).filter(httpRequest);
httpRequest = Iterables.getOnlyElement(httpRequest.getFilters()).filter(httpRequest);
assertRequestLineEquals(httpRequest,
"GET https://api.softlayer.com/rest/v3/SoftLayer_Account/VirtualGuests.json HTTP/1.1");
// for example, using basic authentication, we should get "only one"
// header
assertNonPayloadHeadersEqual(httpRequest,
"Accept: application/json\nAuthorization: Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==\n");
assertPayloadEquals(httpRequest, null, null, false);
assertResponseParserClassEquals(method, httpRequest, ParseJson.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, ReturnEmptySetOnNotFoundOr404.class);
checkFilters(httpRequest);
}
public void testGetVirtualGuest() throws SecurityException, NoSuchMethodException, IOException {
Method method = SoftLayerAsyncClient.class.getMethod("getVirtualGuest", long.class);
HttpRequest httpRequest = processor.createRequest(method, 1234);
assertRequestLineEquals(httpRequest,
"GET https://api.softlayer.com/rest/v3/SoftLayer_Virtual_Guest/1234.json HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null, null, false);
assertResponseParserClassEquals(method, httpRequest, ParseJson.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
checkFilters(httpRequest);
}
@Override
protected void checkFilters(HttpRequest request) {
assertEquals(request.getFilters().size(), 1);
assertEquals(request.getFilters().get(0).getClass(), BasicAuthentication.class);
}
@Override
protected TypeLiteral<RestAnnotationProcessor<SoftLayerAsyncClient>> createTypeLiteral() {
return new TypeLiteral<RestAnnotationProcessor<SoftLayerAsyncClient>>() {
};
}
@Override
public RestContextSpec<SoftLayerClient, SoftLayerAsyncClient> createContextSpec() {
return contextSpec("softlayer", "https://api.softlayer.com/rest", "3", "", "identity", "credential",
SoftLayerClient.class, SoftLayerAsyncClient.class);
}
}

View File

@ -0,0 +1,103 @@
/**
*
* 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.softlayer;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import java.util.Properties;
import java.util.Set;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.rest.RestContext;
import org.jclouds.rest.RestContextFactory;
import org.jclouds.softlayer.domain.VirtualGuest;
import org.testng.annotations.AfterGroups;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Module;
/**
* Tests behavior of {@code SoftLayerClient}
*
* @author Adrian Cole
*/
@Test(groups = "live")
public class SoftLayerClientLiveTest {
private SoftLayerClient client;
private RestContext<SoftLayerClient, SoftLayerAsyncClient> context;
@BeforeGroups(groups = { "live" })
public void setupClient() {
String identity = checkNotNull(System.getProperty("test.softlayer.identity"), "test.softlayer.identity");
String credential = checkNotNull(System.getProperty("test.softlayer.credential"), "test.softlayer.credential");
Properties restProperties = new Properties();
restProperties.setProperty("softlayer.contextbuilder", SoftLayerContextBuilder.class.getName());
restProperties.setProperty("softlayer.propertiesbuilder", SoftLayerPropertiesBuilder.class.getName());
context = new RestContextFactory(restProperties).createContext("softlayer", identity, credential, ImmutableSet
.<Module> of(new Log4JLoggingModule()));
client = context.getApi();
}
@AfterGroups(groups = "live")
void tearDown() {
if (context != null)
context.close();
}
@Test
public void testListVirtualGuests() throws Exception {
Set<VirtualGuest> response = client.listVirtualGuests();
assert null != response;
assertTrue(response.size() >= 0);
for (VirtualGuest vg : response) {
VirtualGuest newDetails = client.getVirtualGuest(vg.getId());
assertEquals(vg.getId(), newDetails.getId());
checkVirtualGuest(vg);
}
}
private void checkVirtualGuest(VirtualGuest vg) {
assert vg.getAccountId() > 0 : vg;
assert vg.getCreateDate() != null : vg;
assert vg.getDomain() != null : vg;
assert vg.getFullyQualifiedDomainName() != null : vg;
assert vg.getHostname() != null : vg;
assert vg.getId() > 0 : vg;
assert vg.getMaxCpu() > 0 : vg;
assert vg.getMaxCpuUnits() != null : vg;
assert vg.getMaxMemory() > 0 : vg;
assert vg.getMetricPollDate() != null : vg;
assert vg.getModifyDate() != null : vg;
assert vg.getStartCpus() > 0 : vg;
assert vg.getStatusId() >= 0 : vg;
assert vg.getUuid() != null : vg;
assert vg.getPrimaryBackendIpAddress() != null : vg;
assert vg.getPrimaryIpAddress() != null : vg;
}
}

View File

@ -0,0 +1,110 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2009 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${symbol_escape}n -->
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n" />
<!--
The full pattern: Date MS Priority [Category] (Thread:NDC) Message${symbol_escape}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${symbol_escape}n -->
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n" />
<!--
The full pattern: Date MS Priority [Category] (Thread:NDC) Message${symbol_escape}n
<param name="ConversionPattern" value="%d %-5r %-5p [%c] (%t:%x)
%m%n"/>
-->
</layout>
</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.wire">
<priority value="DEBUG" />
<appender-ref ref="ASYNCWIRE" />
</category>
<!-- ======================= -->
<!-- Setup the Root category -->
<!-- ======================= -->
<root>
<priority value="WARN" />
</root>
</log4j:configuration>