You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by an...@apache.org on 2014/10/02 23:53:09 UTC

[05/11] JCLOUDS-664 Updating Azure compute provider

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/6ab58bd2/azurecompute/pom.xml
----------------------------------------------------------------------
diff --git a/azurecompute/pom.xml b/azurecompute/pom.xml
new file mode 100644
index 0000000..9271498
--- /dev/null
+++ b/azurecompute/pom.xml
@@ -0,0 +1,151 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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
+
+    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.apache.jclouds</groupId>
+    <artifactId>jclouds-project</artifactId>
+    <version>2.0.0-SNAPSHOT</version>
+    <relativePath />
+  </parent>
+
+  <!-- TODO: when out of labs, switch to org.jclouds.provider -->
+  <groupId>org.apache.jclouds.labs</groupId>
+  <artifactId>azurecompute</artifactId>
+  <version>2.0.0-SNAPSHOT</version>
+  <name>Apache jclouds :: Azure :: Compute API</name>
+  <description>jclouds components to access an implementation of Azure's Compute Service</description>
+  <packaging>bundle</packaging>
+
+  <properties>
+    <test.jclouds.azurecompute.subscription-id>FIXME_subscription-id</test.jclouds.azurecompute.subscription-id>
+    <!-- note that there's no prefix of "test." in the url.  This is to ensure that jclouds inteprets the value, as opposed to maven -->
+    <test.azurecompute.endpoint>https://management.core.windows.net/${jclouds.azurecompute.subscription-id}</test.azurecompute.endpoint>
+    <test.azurecompute.api-version>2012-03-01</test.azurecompute.api-version>
+    <test.azurecompute.build-version />
+    <test.azurecompute.identity>/path/to/cert.p12</test.azurecompute.identity>
+    <test.azurecompute.credential>password to cert</test.azurecompute.credential>
+    <jclouds.osgi.export>org.jclouds.azure.management*;version="${project.version}"</jclouds.osgi.export>
+    <jclouds.osgi.import>org.jclouds*;version="${project.version}",*</jclouds.osgi.import>
+  </properties>
+
+  <repositories>
+    <repository>
+      <id>apache-snapshots</id>
+      <url>https://repository.apache.org/content/repositories/snapshots</url>
+      <releases>
+        <enabled>false</enabled>
+      </releases>
+      <snapshots>
+        <enabled>true</enabled>
+      </snapshots>
+    </repository>
+  </repositories>
+
+  <dependencies>
+    <dependency>
+      <groupId>com.jamesmurty.utils</groupId>
+      <artifactId>java-xmlbuilder</artifactId>
+      <version>1.1</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.jclouds</groupId>
+      <artifactId>jclouds-compute</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.jclouds</groupId>
+      <artifactId>jclouds-compute</artifactId>
+      <version>${project.parent.version}</version>
+      <type>test-jar</type>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.jclouds</groupId>
+      <artifactId>jclouds-core</artifactId>
+      <version>${project.parent.version}</version>
+      <type>test-jar</type>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.jclouds.driver</groupId>
+      <artifactId>jclouds-slf4j</artifactId>
+      <version>${project.parent.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.jclouds.driver</groupId>
+      <artifactId>jclouds-sshj</artifactId>
+      <version>${project.parent.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>ch.qos.logback</groupId>
+      <artifactId>logback-classic</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>com.squareup.okhttp</groupId>
+      <artifactId>mockwebserver</artifactId>
+      <scope>test</scope>
+      <exclusions>
+        <!-- Already provided by jclouds-sshj -->
+        <exclusion>
+          <groupId>org.bouncycastle</groupId>
+          <artifactId>bcprov-jdk15on</artifactId>
+        </exclusion>
+      </exclusions>
+    </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>
+                  <systemPropertyVariables>
+                    <test.azurecompute.endpoint>${test.azurecompute.endpoint}</test.azurecompute.endpoint>
+                    <test.azurecompute.api-version>${test.azurecompute.api-version}</test.azurecompute.api-version>
+                    <test.azurecompute.build-version>${test.azurecompute.build-version}</test.azurecompute.build-version>
+                    <test.azurecompute.identity>${test.azurecompute.identity}</test.azurecompute.identity>
+                    <test.azurecompute.credential>${test.azurecompute.credential}</test.azurecompute.credential>
+                    <test.jclouds.azurecompute.subscription-id>${test.jclouds.azurecompute.subscription-id}</test.jclouds.azurecompute.subscription-id>
+                  </systemPropertyVariables>
+                </configuration>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
+
+</project>

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/6ab58bd2/azurecompute/src/main/java/org/jclouds/azurecompute/AzureComputeApi.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/AzureComputeApi.java b/azurecompute/src/main/java/org/jclouds/azurecompute/AzureComputeApi.java
new file mode 100644
index 0000000..7dc946b
--- /dev/null
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/AzureComputeApi.java
@@ -0,0 +1,101 @@
+/*
+ * 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
+ *
+ * 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.azurecompute;
+
+import java.io.Closeable;
+import javax.ws.rs.PathParam;
+import org.jclouds.azurecompute.features.DeploymentApi;
+import org.jclouds.azurecompute.features.DiskApi;
+import org.jclouds.azurecompute.features.HostedServiceApi;
+import org.jclouds.azurecompute.features.ImageApi;
+import org.jclouds.azurecompute.features.LocationApi;
+import org.jclouds.azurecompute.features.OperationApi;
+import org.jclouds.azurecompute.features.VirtualMachineApi;
+import org.jclouds.rest.annotations.Delegate;
+
+/**
+ * The Windows Azure Service Management API is a REST API for managing your services and
+ * deployments.
+ * <p/>
+ *
+ * @see <a href="http://msdn.microsoft.com/en-us/library/ee460799" >doc</a>
+ */
+public interface AzureComputeApi extends Closeable {
+   /**
+    * The Service Management API includes operations for listing the available data center locations
+    * for a hosted service in your subscription.
+    *
+    * @see <a href="http://msdn.microsoft.com/en-us/library/gg441299">docs</a>
+    */
+   @Delegate
+   LocationApi getLocationApi();
+
+   /**
+    * The Service Management API includes operations for managing the hosted services beneath your
+    * subscription.
+    *
+    * @see <a href="http://msdn.microsoft.com/en-us/library/ee460812">docs</a>
+    */
+   @Delegate
+   HostedServiceApi getHostedServiceApi();
+
+   /**
+    * The Service Management API includes operations for managing the virtual machines in your
+    * subscription.
+    *
+    * @see <a href="http://msdn.microsoft.com/en-us/library/jj157206">docs</a>
+    */
+   @Delegate
+   DeploymentApi getDeploymentApiForService(@PathParam("serviceName") String serviceName);
+
+   /**
+    * The Service Management API includes operations for managing the virtual machines in your
+    * subscription.
+    *
+    * @see <a href="http://msdn.microsoft.com/en-us/library/jj157206">docs</a>
+    */
+   // TODO: revisit once we have multi-level @Delegate working
+   @Delegate
+   VirtualMachineApi getVirtualMachineApiForDeploymentInService(@PathParam("deploymentName") String deploymentName,
+         @PathParam("serviceName") String serviceName);
+
+   /**
+    * The Service Management API includes operations for managing the OS images in your
+    * subscription.
+    *
+    * @see <a href="http://msdn.microsoft.com/en-us/library/jj157175">docs</a>
+    */
+   @Delegate
+   ImageApi getImageApi();
+
+   /**
+    * The Service Management API includes operations for Tracking Asynchronous Service Management
+    * Requests.
+    *
+    * @see <a href="http://msdn.microsoft.com/en-us/library/ee460791">docs</a>
+    */
+   @Delegate
+   OperationApi getOperationApi();
+
+   /**
+    * The Service Management API includes operations for managing Disks in your subscription.
+    *
+    * @see <a href="http://msdn.microsoft.com/en-us/library/jj157188">docs</a>
+    */
+   @Delegate
+   DiskApi getDiskApi();
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/6ab58bd2/azurecompute/src/main/java/org/jclouds/azurecompute/AzureComputeProviderMetadata.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/AzureComputeProviderMetadata.java b/azurecompute/src/main/java/org/jclouds/azurecompute/AzureComputeProviderMetadata.java
new file mode 100644
index 0000000..8fcb560
--- /dev/null
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/AzureComputeProviderMetadata.java
@@ -0,0 +1,78 @@
+/*
+ * 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
+ *
+ * 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.azurecompute;
+
+import java.net.URI;
+import java.util.Properties;
+import org.jclouds.providers.ProviderMetadata;
+import org.jclouds.providers.internal.BaseProviderMetadata;
+
+import static org.jclouds.azurecompute.config.AzureComputeProperties.SUBSCRIPTION_ID;
+
+/**
+ * Implementation of {@link ProviderMetadata} for Microsoft Azure Service Management Service.
+ */
+public class AzureComputeProviderMetadata extends BaseProviderMetadata {
+
+   public static Builder builder() {
+      return new Builder();
+   }
+
+   @Override
+   public Builder toBuilder() {
+      return builder().fromProviderMetadata(this);
+   }
+
+   public AzureComputeProviderMetadata() {
+      super(builder());
+   }
+
+   public AzureComputeProviderMetadata(Builder builder) {
+      super(builder);
+   }
+
+   public static Properties defaultProperties() {
+      Properties properties = new Properties();
+      return properties;
+   }
+
+   public static class Builder extends BaseProviderMetadata.Builder {
+
+      protected Builder() {
+         id("azurecompute")
+         .name("Microsoft Azure Service Management Service")
+         .apiMetadata(new AzureManagementApiMetadata())
+         .endpoint("https://management.core.windows.net/${" + SUBSCRIPTION_ID + "}")
+         .homepage(URI.create("https://www.windowsazure.com/"))
+         .console(URI.create("https://windows.azure.com/default.aspx"))
+         .linkedServices("azureblob", "azurequeue", "azuretable")
+         .iso3166Codes("US-TX", "US-IL", "IE-D", "SG", "NL-NH", "HK")
+         .defaultProperties(AzureComputeProviderMetadata.defaultProperties());
+      }
+
+      @Override
+      public AzureComputeProviderMetadata build() {
+         return new AzureComputeProviderMetadata(this);
+      }
+
+      @Override
+      public Builder fromProviderMetadata(ProviderMetadata in) {
+         super.fromProviderMetadata(in);
+         return this;
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/6ab58bd2/azurecompute/src/main/java/org/jclouds/azurecompute/AzureManagementApiMetadata.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/AzureManagementApiMetadata.java b/azurecompute/src/main/java/org/jclouds/azurecompute/AzureManagementApiMetadata.java
new file mode 100644
index 0000000..e941dfa
--- /dev/null
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/AzureManagementApiMetadata.java
@@ -0,0 +1,80 @@
+/*
+ * 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
+ *
+ * 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.azurecompute;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Module;
+import java.net.URI;
+import java.util.Properties;
+import org.jclouds.apis.ApiMetadata;
+import org.jclouds.azurecompute.compute.config.AzureComputeServiceContextModule;
+import org.jclouds.azurecompute.config.AzureComputeHttpApiModule;
+import org.jclouds.rest.internal.BaseHttpApiMetadata;
+
+import static org.jclouds.azurecompute.config.AzureComputeProperties.SUBSCRIPTION_ID;
+
+/**
+ * Implementation of {@link ApiMetadata} for Microsoft Service Management Service API
+ */
+public class AzureManagementApiMetadata extends BaseHttpApiMetadata<AzureComputeApi> {
+
+   @Override
+   public Builder toBuilder() {
+      return new Builder().fromApiMetadata(this);
+   }
+
+   public AzureManagementApiMetadata() {
+      this(new Builder());
+   }
+
+   protected AzureManagementApiMetadata(Builder builder) {
+      super(builder);
+   }
+
+   public static Properties defaultProperties() {
+      Properties properties = BaseHttpApiMetadata.defaultProperties();
+      return properties;
+   }
+
+   public static class Builder extends BaseHttpApiMetadata.Builder<AzureComputeApi, Builder> {
+
+      protected Builder() {
+         id("azurecompute")
+         .name("Microsoft Azure Service Management Service API")
+         .version("2012-03-01")
+         .identityName("Path to Management Certificate .p12 file, or PEM string")
+         .credentialName("Password to Management Certificate")
+         .defaultEndpoint("https://management.core.windows.net/${" + SUBSCRIPTION_ID + "}")
+         .endpointName("Service Management Endpoint ending in your Subscription Id")
+         .documentation(URI.create("http://msdn.microsoft.com/en-us/library/ee460799"))
+         .defaultProperties(AzureManagementApiMetadata.defaultProperties())
+         .defaultModules(ImmutableSet.<Class<? extends Module>>builder()
+               .add(AzureComputeServiceContextModule.class)
+               .add(AzureComputeHttpApiModule.class).build());
+      }
+
+      @Override
+      public AzureManagementApiMetadata build() {
+         return new AzureManagementApiMetadata(this);
+      }
+
+      @Override
+      protected Builder self() {
+         return this;
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/6ab58bd2/azurecompute/src/main/java/org/jclouds/azurecompute/binders/BindCreateHostedServiceToXmlPayload.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/binders/BindCreateHostedServiceToXmlPayload.java b/azurecompute/src/main/java/org/jclouds/azurecompute/binders/BindCreateHostedServiceToXmlPayload.java
new file mode 100644
index 0000000..900c9a7
--- /dev/null
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/binders/BindCreateHostedServiceToXmlPayload.java
@@ -0,0 +1,79 @@
+/*
+ * 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
+ *
+ * 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.azurecompute.binders;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Throwables;
+import com.jamesmurty.utils.XMLBuilder;
+import java.util.Map;
+import java.util.Map.Entry;
+import javax.inject.Singleton;
+import org.jclouds.azurecompute.options.CreateHostedServiceOptions;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.rest.MapBinder;
+
+import static com.google.common.base.Charsets.UTF_8;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.io.BaseEncoding.base64;
+
+@Singleton
+public class BindCreateHostedServiceToXmlPayload implements MapBinder {
+
+   private static final CreateHostedServiceOptions NO_OPTIONS = new CreateHostedServiceOptions();
+
+   @Override
+   public <R extends HttpRequest> R bindToRequest(R request, Map<String, Object> postParams) {
+      String serviceName = checkNotNull(postParams.get("name"), "name").toString();
+      String label = base64().encode(checkNotNull(postParams.get("label"), "label").toString().getBytes(UTF_8));
+
+      Optional<String> location = Optional.fromNullable((String) postParams.get("location"));
+      Optional<String> affinityGroup = Optional.fromNullable((String) postParams.get("affinityGroup"));
+      CreateHostedServiceOptions options = Optional
+               .fromNullable((CreateHostedServiceOptions) postParams.get("options")).or(NO_OPTIONS);
+      try {
+         XMLBuilder createHostedService = XMLBuilder.create("CreateHostedService")
+                  .a("xmlns", "http://schemas.microsoft.com/windowsazure").e("ServiceName").t(serviceName).up()
+                  .e("Label").t(label).up();
+
+         if (options.getDescription().isPresent())
+            createHostedService.e("Description").t(options.getDescription().get()).up();
+
+         if (location.isPresent())
+            createHostedService.e("Location").t(location.get()).up();
+         else if (affinityGroup.isPresent())
+            createHostedService.e("AffinityGroup").t(affinityGroup.get()).up();
+         else
+            throw new IllegalArgumentException("you must specify either Location or AffinityGroup!");
+
+         if (options.getExtendedProperties().isPresent() && options.getExtendedProperties().get().size() > 0) {
+            XMLBuilder extendedProperties = createHostedService.e("ExtendedProperties");
+            for (Entry<String, String> entry : options.getExtendedProperties().get().entrySet())
+               extendedProperties.e("ExtendedProperty").e("Name").t(entry.getKey()).up().e("Value").t(entry.getValue());
+         }
+         return (R) request.toBuilder().payload(createHostedService.asString()).build();
+      } catch (Exception e) {
+         throw Throwables.propagate(e);
+      }
+
+   }
+
+   @Override
+   public <R extends HttpRequest> R bindToRequest(R request, Object input) {
+      throw new IllegalStateException("BindCreateHostedServiceToXmlPayload is needs parameters");
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/6ab58bd2/azurecompute/src/main/java/org/jclouds/azurecompute/binders/BindDeploymentParamsToXmlPayload.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/binders/BindDeploymentParamsToXmlPayload.java b/azurecompute/src/main/java/org/jclouds/azurecompute/binders/BindDeploymentParamsToXmlPayload.java
new file mode 100644
index 0000000..5c50740
--- /dev/null
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/binders/BindDeploymentParamsToXmlPayload.java
@@ -0,0 +1,112 @@
+/*
+ * 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
+ *
+ * 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.azurecompute.binders;
+
+import com.google.common.base.Throwables;
+import com.jamesmurty.utils.XMLBuilder;
+import javax.inject.Singleton;
+import org.jclouds.azurecompute.domain.DeploymentParams;
+import org.jclouds.azurecompute.domain.InputEndpoint;
+import org.jclouds.azurecompute.domain.OSType;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.rest.Binder;
+
+@Singleton
+public class BindDeploymentParamsToXmlPayload implements Binder {
+
+   @Override
+   public <R extends HttpRequest> R bindToRequest(R request, Object input) {
+      DeploymentParams params = DeploymentParams.class.cast(input);
+      try {
+         XMLBuilder builder = XMLBuilder.create("Deployment").a("xmlns", "http://schemas.microsoft.com/windowsazure")
+            .e("Name").t(params.getName()).up()
+            .e("DeploymentSlot").t("Production").up()
+            .e("Label").t(params.getName()).up()
+            .e("RoleList")
+            .e("Role")
+            .e("RoleName").t(params.getName()).up()
+            .e("RoleType").t("PersistentVMRole").up()
+            .e("ConfigurationSets");
+
+         if (params.getOsType() == OSType.WINDOWS) {
+            XMLBuilder configBuilder = builder.e("ConfigurationSet"); // Windows
+            configBuilder.e("ConfigurationSetType").t("WindowsProvisioningConfiguration").up()
+               .e("ComputerName").t(params.getUsername()).up()
+               .e("AdminPassword").t(params.getPassword()).up()
+               .e("ResetPasswordOnFirstLogon").t("false").up()
+               .e("EnableAutomaticUpdate").t("false").up()
+               .e("DomainJoin")
+               .e("Credentials")
+                  .e("Domain").t(params.getName()).up()
+                  .e("Username").t(params.getUsername()).up()
+                  .e("Password").t(params.getPassword()).up()
+               .up() // Credentials
+               .e("JoinDomain").t(params.getName()).up()
+               .up() // Domain Join
+               .e("StoredCertificateSettings").up()
+               .up(); // Windows ConfigurationSet
+         } else if (params.getOsType() == OSType.LINUX) {
+            XMLBuilder configBuilder = builder.e("ConfigurationSet"); // Linux
+            configBuilder.e("ConfigurationSetType").t("LinuxProvisioningConfiguration").up()
+               .e("HostName").t(params.getName()).up()
+               .e("UserName").t(params.getUsername()).up()
+               .e("UserPassword").t(params.getPassword()).up()
+               .e("DisableSshPasswordAuthentication").t("false").up()
+               .e("SSH").up()
+               .up(); // Linux ConfigurationSet
+         }
+
+         XMLBuilder configBuilder = builder.e("ConfigurationSet"); // Network
+         configBuilder.e("ConfigurationSetType").t("NetworkConfiguration").up();
+
+         XMLBuilder inputEndpoints = configBuilder.e("InputEndpoints");
+         for (InputEndpoint endpoint : params.getEndpoints()) {
+            XMLBuilder inputBuilder = inputEndpoints.e("InputEndpoint");
+            inputBuilder.e("LocalPort").t(endpoint.getLocalPort().toString()).up()
+               .e("Name").t(endpoint.getName()).up()
+               .e("Port").t(endpoint.getExternalPort().toString()).up()
+               .e("Protocol").t(endpoint.getProtocol().name()).up()
+               .up(); //InputEndpoint
+         }
+
+         inputEndpoints.up();
+         configBuilder.e("SubnetNames").up()
+            .up();
+
+         builder.up() //ConfigurationSets
+            .e("DataVirtualHardDisks").up()
+            .e("OSVirtualHardDisk")
+            .e("HostCaching").t("ReadWrite").up()
+            .e("MediaLink").t(url(params)).up()
+            .e("SourceImageName").t(params.getSourceImageName()).up()
+            .e("OS").t("Linux").up()
+            .up() //OSVirtualHardDisk
+            .e("RoleSize").t(params.getSize().value()).up()
+            .up() //Role
+            .up(); //RoleList
+
+         return (R) request.toBuilder().payload(builder.asString()).build();
+      } catch (Exception e) {
+         throw Throwables.propagate(e);
+      }
+   }
+
+   private static String url(DeploymentParams params) {
+      return String.format("http://%s.blob.core.windows.net/disks/%s/%s", params.getStorageAccount(), params.getName(),
+            params.getSourceImageName());
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/6ab58bd2/azurecompute/src/main/java/org/jclouds/azurecompute/binders/BindOSImageParamsToXmlPayload.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/binders/BindOSImageParamsToXmlPayload.java b/azurecompute/src/main/java/org/jclouds/azurecompute/binders/BindOSImageParamsToXmlPayload.java
new file mode 100644
index 0000000..bbe0459
--- /dev/null
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/binders/BindOSImageParamsToXmlPayload.java
@@ -0,0 +1,46 @@
+/*
+ * 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
+ *
+ * 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.azurecompute.binders;
+
+import com.google.common.base.Throwables;
+import com.jamesmurty.utils.XMLBuilder;
+import javax.inject.Singleton;
+import org.jclouds.azurecompute.domain.ImageParams;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.rest.Binder;
+
+@Singleton
+public class BindOSImageParamsToXmlPayload implements Binder {
+
+
+   @Override
+   public <R extends HttpRequest> R bindToRequest(R request, Object input) {
+      ImageParams params = ImageParams.class.cast(input);
+      try {
+         return (R) request.toBuilder().payload(XMLBuilder.create("OSImage").a("xmlns", "http://schemas.microsoft.com/windowsazure")
+                                                          .e("Label").t(params.getLabel()).up()
+                                                          .e("MediaLink").t(params.getMediaLink().toASCIIString()).up()
+                                                          .e("Name").t(params.getName()).up()
+                                                          .e("OS").t(params.getOS().toString()).up()
+                                                          .up().asString()).build();
+      } catch (Exception e) {
+         throw Throwables.propagate(e);
+      }
+
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/6ab58bd2/azurecompute/src/main/java/org/jclouds/azurecompute/compute/AzureComputeServiceAdapter.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/AzureComputeServiceAdapter.java b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/AzureComputeServiceAdapter.java
new file mode 100644
index 0000000..4ce0ee4
--- /dev/null
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/AzureComputeServiceAdapter.java
@@ -0,0 +1,103 @@
+/*
+ * 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
+ *
+ * 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.azurecompute.compute;
+
+import javax.inject.Singleton;
+import org.jclouds.azurecompute.AzureComputeApi;
+import org.jclouds.azurecompute.domain.Deployment;
+import org.jclouds.azurecompute.domain.Image;
+import org.jclouds.azurecompute.domain.RoleSize;
+import org.jclouds.compute.ComputeServiceAdapter;
+import org.jclouds.compute.domain.Template;
+
+/**
+ * defines the connection between the {@link AzureComputeApi} implementation and the
+ * jclouds {@link org.jclouds.compute.ComputeService}
+ */
+@Singleton
+public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Deployment, RoleSize, Image, String> {
+
+   @Override
+   public NodeAndInitialCredentials<Deployment> createNodeWithGroupEncodedIntoName(
+         String group, String name, Template template) {
+      // TODO Auto-generated method stub
+      return null;
+   }
+
+   @Override
+   public Iterable<RoleSize> listHardwareProfiles() {
+      // TODO Auto-generated method stub
+      return null;
+   }
+
+   @Override
+   public Iterable<Image> listImages() {
+      // TODO Auto-generated method stub
+      return null;
+   }
+
+   @Override
+   public Image getImage(String id) {
+      // TODO Auto-generated method stub
+      return null;
+   }
+
+   @Override
+   public Iterable<String> listLocations() {
+      // TODO Auto-generated method stub
+      return null;
+   }
+
+   @Override
+   public Deployment getNode(String id) {
+      // TODO Auto-generated method stub
+      return null;
+   }
+
+   @Override
+   public void destroyNode(String id) {
+      // TODO Auto-generated method stub
+
+   }
+
+   @Override
+   public void rebootNode(String id) {
+      // TODO Auto-generated method stub
+   }
+
+   @Override
+   public void resumeNode(String id) {
+      // TODO Auto-generated method stub
+   }
+
+   @Override
+   public void suspendNode(String id) {
+      // TODO Auto-generated method stub
+
+   }
+
+   @Override
+   public Iterable<Deployment> listNodes() {
+      // TODO Auto-generated method stub
+      return null;
+   }
+
+   @Override public Iterable<Deployment> listNodesByIds(Iterable<String> ids) {
+      // TODO Auto-generated method stub
+      return null;
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/6ab58bd2/azurecompute/src/main/java/org/jclouds/azurecompute/compute/config/AzureComputeServiceContextModule.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/config/AzureComputeServiceContextModule.java b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/config/AzureComputeServiceContextModule.java
new file mode 100644
index 0000000..2edd8a0
--- /dev/null
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/config/AzureComputeServiceContextModule.java
@@ -0,0 +1,48 @@
+/*
+ * 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
+ *
+ * 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.azurecompute.compute.config;
+
+import com.google.common.base.Function;
+import com.google.inject.TypeLiteral;
+import org.jclouds.azurecompute.compute.AzureComputeServiceAdapter;
+import org.jclouds.azurecompute.compute.functions.AzureImageToImage;
+import org.jclouds.azurecompute.compute.functions.DeploymentToNodeMetadata;
+import org.jclouds.azurecompute.compute.functions.RoleSizeToHardware;
+import org.jclouds.azurecompute.domain.Deployment;
+import org.jclouds.azurecompute.domain.Image;
+import org.jclouds.azurecompute.domain.RoleSize;
+import org.jclouds.compute.ComputeServiceAdapter;
+import org.jclouds.compute.config.ComputeServiceAdapterContextModule;
+import org.jclouds.compute.domain.Hardware;
+import org.jclouds.compute.domain.NodeMetadata;
+
+public class AzureComputeServiceContextModule
+      extends ComputeServiceAdapterContextModule<Deployment, RoleSize, Image, String> {
+
+   @Override
+   protected void configure() {
+      super.configure();
+      bind(new TypeLiteral<ComputeServiceAdapter<Deployment, RoleSize, Image, String>>() {
+      }).to(AzureComputeServiceAdapter.class);
+      bind(new TypeLiteral<Function<Image, org.jclouds.compute.domain.Image>>() {
+      }).to(AzureImageToImage.class);
+      bind(new TypeLiteral<Function<RoleSize, Hardware>>() {
+      }).to(RoleSizeToHardware.class);
+      bind(new TypeLiteral<Function<Deployment, NodeMetadata>>() {
+      }).to(DeploymentToNodeMetadata.class);
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/6ab58bd2/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/AzureImageToImage.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/AzureImageToImage.java b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/AzureImageToImage.java
new file mode 100644
index 0000000..4da1c34
--- /dev/null
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/AzureImageToImage.java
@@ -0,0 +1,29 @@
+/*
+ * 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
+ *
+ * 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.azurecompute.compute.functions;
+
+import com.google.common.base.Function;
+import org.jclouds.azurecompute.domain.Image;
+
+public class AzureImageToImage implements Function<Image, org.jclouds.compute.domain.Image> {
+
+   @Override
+   public org.jclouds.compute.domain.Image apply(Image input) {
+      return null;
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/6ab58bd2/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/DeploymentToNodeMetadata.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/DeploymentToNodeMetadata.java b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/DeploymentToNodeMetadata.java
new file mode 100644
index 0000000..7e02ee6
--- /dev/null
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/DeploymentToNodeMetadata.java
@@ -0,0 +1,30 @@
+/*
+ * 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
+ *
+ * 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.azurecompute.compute.functions;
+
+import com.google.common.base.Function;
+import org.jclouds.azurecompute.domain.Deployment;
+import org.jclouds.compute.domain.NodeMetadata;
+
+public class DeploymentToNodeMetadata implements Function<Deployment, NodeMetadata> {
+
+	@Override
+	public NodeMetadata apply(Deployment input) {
+		return null;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/6ab58bd2/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/RoleSizeToHardware.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/RoleSizeToHardware.java b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/RoleSizeToHardware.java
new file mode 100644
index 0000000..09dbf78
--- /dev/null
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/RoleSizeToHardware.java
@@ -0,0 +1,30 @@
+/*
+ * 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
+ *
+ * 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.azurecompute.compute.functions;
+
+import com.google.common.base.Function;
+import org.jclouds.azurecompute.domain.RoleSize;
+import org.jclouds.compute.domain.Hardware;
+
+public class RoleSizeToHardware implements Function<RoleSize, Hardware> {
+
+	@Override
+	public Hardware apply(RoleSize input) {
+		return null;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/6ab58bd2/azurecompute/src/main/java/org/jclouds/azurecompute/config/AzureComputeHttpApiModule.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/config/AzureComputeHttpApiModule.java b/azurecompute/src/main/java/org/jclouds/azurecompute/config/AzureComputeHttpApiModule.java
new file mode 100644
index 0000000..8c85c0a
--- /dev/null
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/config/AzureComputeHttpApiModule.java
@@ -0,0 +1,41 @@
+/*
+ * 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
+ *
+ * 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.azurecompute.config;
+
+import com.google.common.base.Supplier;
+import com.google.inject.TypeLiteral;
+import java.security.KeyStore;
+import javax.net.ssl.SSLContext;
+import org.jclouds.azurecompute.AzureComputeApi;
+import org.jclouds.azurecompute.suppliers.KeyStoreSupplier;
+import org.jclouds.azurecompute.suppliers.SSLContextWithKeysSupplier;
+import org.jclouds.rest.ConfiguresHttpApi;
+import org.jclouds.rest.config.HttpApiModule;
+
+@ConfiguresHttpApi
+public class AzureComputeHttpApiModule extends HttpApiModule<AzureComputeApi> {
+   @Override
+   protected void configure() {
+      super.configure();
+      bind(new TypeLiteral<Supplier<SSLContext>>() {
+      }).to(new TypeLiteral<SSLContextWithKeysSupplier>() {
+      });
+      bind(new TypeLiteral<Supplier<KeyStore>>() {
+      }).to(new TypeLiteral<KeyStoreSupplier>() {
+      });
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/6ab58bd2/azurecompute/src/main/java/org/jclouds/azurecompute/config/AzureComputeProperties.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/config/AzureComputeProperties.java b/azurecompute/src/main/java/org/jclouds/azurecompute/config/AzureComputeProperties.java
new file mode 100644
index 0000000..0981c7c
--- /dev/null
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/config/AzureComputeProperties.java
@@ -0,0 +1,36 @@
+/*
+ * 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
+ *
+ * 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.azurecompute.config;
+
+/**
+ * Configuration properties and constants used in Azure Service Management
+ * connections.
+ */
+public class AzureComputeProperties {
+	/**
+	 * Every call to the Service Management API must include the subscription ID
+	 * for your subscription. The subscription ID is appended to the base URI,
+	 * as follows:
+	 *
+	 * <pre>
+	 * https://management.core.windows.net/${subscriptionId}
+	 * </pre>
+	 *
+	 * @see <a href="http://msdn.microsoft.com/en-us/library/ee460786">docs</a>
+	 */
+	public static final String SUBSCRIPTION_ID = "jclouds.azurecompute.subscription-id";
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/6ab58bd2/azurecompute/src/main/java/org/jclouds/azurecompute/domain/Deployment.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/domain/Deployment.java b/azurecompute/src/main/java/org/jclouds/azurecompute/domain/Deployment.java
new file mode 100644
index 0000000..6bd179b
--- /dev/null
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/domain/Deployment.java
@@ -0,0 +1,309 @@
+/*
+ * 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
+ *
+ * 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.azurecompute.domain;
+
+import java.net.URI;
+
+public class Deployment {
+
+   public static Builder builder() {
+      return new Builder();
+   }
+
+   public static class Builder {
+      private String deploymentName;
+      private DeploymentSlot deploymentSlot;
+      private DeploymentStatus deploymentStatus;
+      private String deploymentLabel;
+      private URI deploymentURL;
+      private String roleName;
+      private String instanceName;
+      private InstanceStatus instanceStatus;
+      private String instanceStateDetails;
+      private String instanceErrorCode;
+      private RoleSize instanceSize;
+      private String privateIpAddress;
+      private String publicIpAddress;
+
+      public Builder deploymentName(final String deploymentName) {
+         this.deploymentName = deploymentName;
+         return this;
+      }
+
+      public Builder deploymentSlot(final DeploymentSlot deploymentSlot) {
+         this.deploymentSlot = deploymentSlot;
+         return this;
+      }
+
+      public Builder deploymentStatus(final DeploymentStatus deploymentStatus) {
+         this.deploymentStatus = deploymentStatus;
+         return this;
+      }
+
+      public Builder deploymentLabel(final String deploymentLabel) {
+         this.deploymentLabel = deploymentLabel;
+         return this;
+      }
+
+      public Builder deploymentURL(final URI deploymentURL) {
+         this.deploymentURL = deploymentURL;
+         return this;
+      }
+
+      public Builder instanceSize(final RoleSize instanceSize) {
+         this.instanceSize = instanceSize;
+         return this;
+      }
+
+      public Builder instanceName(final String instanceName) {
+         this.instanceName = instanceName;
+         return this;
+      }
+
+      public Builder instanceStatus(final InstanceStatus instanceStatus) {
+         this.instanceStatus = instanceStatus;
+         return this;
+      }
+
+      public Builder instanceStateDetails(final String instanceStateDetails) {
+         this.instanceStateDetails = instanceStateDetails;
+         return this;
+      }
+
+      public Builder instanceErrorCode(final String instanceErrorCode) {
+         this.instanceErrorCode = instanceErrorCode;
+         return this;
+      }
+
+      public Builder privateIpAddress(final String privateIpAddress) {
+         this.privateIpAddress = privateIpAddress;
+         return this;
+      }
+
+      public Builder publicIpAddress(final String publicIpAddress) {
+         this.publicIpAddress = publicIpAddress;
+         return this;
+      }
+
+      public Builder roleName(final String roleName) {
+         this.roleName = roleName;
+         return this;
+      }
+
+      public Deployment build() {
+         return new Deployment(deploymentName, deploymentSlot, deploymentStatus, deploymentLabel, deploymentURL,
+               roleName, instanceName, instanceStatus, instanceStateDetails, instanceErrorCode, instanceSize,
+               privateIpAddress, publicIpAddress);
+      }
+
+   }
+
+   /**
+    * The user-supplied name for this deployment.
+    */
+   private final String deploymentName;
+
+   /**
+    * The environment to which the hosted service is deployed, either staging
+    * or production.
+    */
+   private final DeploymentSlot deploymentSlot;
+
+   /**
+    * The status of the deployment.
+    */
+   private final DeploymentStatus deploymentStatus;
+
+   /**
+    * The user-supplied name of the deployment returned as a base-64 encoded
+    * string. This name can be used identify the deployment for your tracking
+    * purposes.
+    */
+   private final String deploymentLabel;
+
+   /**
+    * The URL used to access the hosted service. For example, if the service
+    * name is MyService you could access the access the service by calling:
+    * http://MyService.cloudapp.net
+    */
+   private final URI deploymentURL;
+
+   /**
+    * Specifies the name for the virtual machine. The name must be unique
+    * within Windows Azure.
+    */
+   private final String roleName;
+
+   /**
+    * The name of the specific role instance (if any).
+    */
+   private final String instanceName;
+
+   /**
+    * The current status of this instance.
+    */
+   private final InstanceStatus instanceStatus;
+
+   /**
+    * The instance state is returned as an English human-readable string that,
+    * when present, provides a snapshot of the state of the virtual machine at
+    * the time the operation was called.
+    *
+    * For example, when the instance is first being initialized a
+    * "Preparing Windows for first use." could be returned.
+    */
+   private final String instanceStateDetails;
+
+   /**
+    * Error code of the latest role or VM start
+    *
+    * For VMRoles the error codes are:
+    *
+    * WaitTimeout - The virtual machine did not communicate back to Azure
+    * infrastructure within 25 minutes. Typically this indicates that the
+    * virtual machine did not start or that the guest agent is not installed.
+    *
+    * VhdTooLarge - The VHD image selected was too large for the virtual
+    * machine hosting the role.
+    *
+    * AzureInternalError – An internal error has occurred that has caused to
+    * virtual machine to fail to start. Contact support for additional
+    * assistance.
+    *
+    * For web and worker roles this field returns an error code that can be provided to Windows Azure support to assist
+    * in resolution of errors. Typically this field will be empty.
+    */
+   private final String instanceErrorCode;
+
+   /**
+    * The size of the role instance
+    */
+   private final RoleSize instanceSize;
+   private final String privateIpAddress;
+   private final String publicIpAddress;
+
+   public Deployment(String deploymentName, DeploymentSlot deploymentSlot, DeploymentStatus deploymentStatus,
+         String deploymentLabel, URI deploymentURL, String roleName, String instanceName, InstanceStatus instanceStatus,
+         String instanceStateDetails, String instanceErrorCode, RoleSize instanceSize, String privateIpAddress,
+         String publicIpAddress) {
+      this.deploymentName = deploymentName;
+      this.deploymentSlot = deploymentSlot;
+      this.deploymentStatus = deploymentStatus;
+      this.deploymentLabel = deploymentLabel;
+      this.deploymentURL = deploymentURL;
+      this.roleName = roleName;
+      this.instanceName = instanceName;
+      this.instanceStatus = instanceStatus;
+      this.instanceStateDetails = instanceStateDetails;
+      this.instanceErrorCode = instanceErrorCode;
+      this.instanceSize = instanceSize;
+      this.privateIpAddress = privateIpAddress;
+      this.publicIpAddress = publicIpAddress;
+   }
+
+   public String getDeploymentName() {
+      return deploymentName;
+   }
+
+   public DeploymentSlot getDeploymentSlot() {
+      return deploymentSlot;
+   }
+
+   public DeploymentStatus getDeploymentStatus() {
+      return deploymentStatus;
+   }
+
+   public String getDeploymentLabel() {
+      return deploymentLabel;
+   }
+
+   public URI getDeploymentURL() {
+      return deploymentURL;
+   }
+
+   public String getRoleName() {
+      return roleName;
+   }
+
+   public String getInstanceName() {
+      return instanceName;
+   }
+
+   public InstanceStatus getInstanceStatus() {
+      return instanceStatus;
+   }
+
+   public String getInstanceStateDetails() {
+      return instanceStateDetails;
+   }
+
+   public String getInstanceErrorCode() {
+      return instanceErrorCode;
+   }
+
+   public RoleSize getInstanceSize() {
+      return instanceSize;
+   }
+
+   public String getPrivateIpAddress() {
+      return privateIpAddress;
+   }
+
+   public String getPublicIpAddress() {
+      return publicIpAddress;
+   }
+
+   @Override
+   public int hashCode() {
+      final int prime = 31;
+      int result = 1;
+      result = prime * result + ((deploymentName == null) ? 0 : deploymentName.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;
+      }
+      Deployment other = (Deployment) obj;
+      if (deploymentName == null) {
+         if (other.deploymentName != null) {
+            return false;
+         }
+      } else if (!deploymentName.equals(other.deploymentName)) {
+         return false;
+      }
+      return true;
+   }
+
+   @Override
+   public String toString() {
+      return "Deployment [deploymentName=" + deploymentName + ", deploymentSlot=" + deploymentSlot
+            + ", deploymentStatus=" + deploymentStatus + ", deploymentLabel=" + deploymentLabel + ", deploymentURL="
+            + deploymentURL + ", roleName=" + roleName + ", instanceName=" + instanceName + ", instanceStatus="
+            + instanceStatus + ", instanceStateDetails=" + instanceStateDetails + ", instanceErrorCode="
+            + instanceErrorCode + ", instanceSize=" + instanceSize + ", privateIpAddress=" + privateIpAddress
+            + ", publicIpAddress=" + publicIpAddress + "]";
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/6ab58bd2/azurecompute/src/main/java/org/jclouds/azurecompute/domain/DeploymentParams.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/domain/DeploymentParams.java b/azurecompute/src/main/java/org/jclouds/azurecompute/domain/DeploymentParams.java
new file mode 100644
index 0000000..9ee4423
--- /dev/null
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/domain/DeploymentParams.java
@@ -0,0 +1,208 @@
+/*
+ * 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
+ *
+ * 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.azurecompute.domain;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.MoreObjects.ToStringHelper;
+import com.google.common.base.Objects;
+import com.google.common.collect.Lists;
+import java.util.List;
+
+/**
+ * To create a new deployment/role
+ *
+ * Warning : the OSType must be the one of the source image used to create the VM
+ */
+public class DeploymentParams {
+
+   public static Builder builder() {
+      return new Builder();
+   }
+
+   public Builder toBuilder() {
+      return builder().fromDeploymentParams(this);
+   }
+
+   public static class Builder {
+
+      private String name;
+      private String sourceImageName;
+      private String username;
+      private String password;
+      private String storageAccount;
+      private OSType osType;
+      private RoleSize size = RoleSize.SMALL;
+      private List<InputEndpoint> endpoints = Lists.newArrayList();
+
+      public Builder name(String name) {
+         this.name = name;
+         return this;
+      }
+
+      public Builder sourceImageName(String sourceImageName) {
+         this.sourceImageName = sourceImageName;
+         return this;
+      }
+
+      public Builder username(String username) {
+         this.username = username;
+         return this;
+      }
+
+      public Builder password(String password) {
+         this.password = password;
+         return this;
+      }
+
+      public Builder storageAccount(String storageAccount) {
+         this.storageAccount = storageAccount;
+         return this;
+      }
+
+      public Builder size(RoleSize size) {
+         this.size = size;
+         return this;
+      }
+
+      public Builder osType(OSType osType) {
+         this.osType = osType;
+         return this;
+      }
+
+      public Builder endpoint(InputEndpoint endpoint) {
+         endpoints.add(endpoint);
+         return this;
+      }
+
+      public DeploymentParams build() {
+         return new DeploymentParams(name, sourceImageName, username, password, storageAccount, size, osType,
+               endpoints);
+      }
+
+      public Builder fromDeploymentParams(DeploymentParams in) {
+         // TODO Since the roleName should be unique, is it a good idea to copy it ?
+         return this.name(in.getName()).sourceImageName(in.getSourceImageName()).username(in.getUsername())
+               .password(in.getPassword()).size(in.getSize());
+      }
+   }
+
+   private final String name;
+   private final String sourceImageName;
+   private final String username;
+   private final String password;
+   private final String storageAccount;
+   private final RoleSize size;
+   private final OSType osType;
+   private final List<InputEndpoint> endpoints;
+
+   public DeploymentParams(String name, String sourceImageName, String username, String password, String storageAccount,
+         RoleSize size, OSType osType, final List<InputEndpoint> endpoints) {
+      this.name = name;
+      this.sourceImageName = sourceImageName;
+      this.username = username;
+      this.password = password;
+      this.storageAccount = storageAccount;
+      this.size = size;
+      this.osType = osType;
+      this.endpoints = endpoints;
+   }
+
+   /**
+    * Specifies the name for the deployment and its virtual machine. The name must be unique
+    * within Windows Azure.
+    */
+   public String getName() {
+      return name;
+   }
+
+   /**
+    * Specifies the name of an operating system image in the image repository.
+    */
+   public String getSourceImageName() {
+      return sourceImageName;
+   }
+
+   /**
+    * Specifies the name of a user to be created in the sudoer group of the
+    * virtual machine. User names are ASCII character strings 1 to 32
+    * characters in length.
+    */
+   public String getUsername() {
+      return username;
+   }
+
+   /**
+    * Specifies the associated password for the user name.
+    * PasswoazureManagement are ASCII character strings 6 to 72 characters in
+    * length.
+    */
+   public String getPassword() {
+      return password;
+   }
+
+   public String getStorageAccount() {
+      return storageAccount;
+   }
+
+   /**
+    * The size of the virtual machine to allocate. The default value is Small.
+    */
+   public RoleSize getSize() {
+      return size;
+   }
+
+   /**
+    * Os type of the given sourceImage
+    */
+   public OSType getOsType() {
+      return osType;
+   }
+
+   public List<InputEndpoint> getEndpoints() {
+      return endpoints;
+   }
+
+   @Override
+   public int hashCode() {
+      return Objects.hashCode(name);
+   }
+
+   @Override
+   public boolean equals(Object obj) {
+      if (this == obj) {
+         return true;
+      }
+      if (obj == null) {
+         return false;
+      }
+      if (getClass() != obj.getClass()) {
+         return false;
+      }
+      DeploymentParams other = (DeploymentParams) obj;
+      return Objects.equal(this.name, other.name);
+   }
+
+   @Override
+   public String toString() {
+      return string().toString();
+   }
+
+   private ToStringHelper string() {
+      return MoreObjects.toStringHelper(this).add("name", name).add("sourceImageName", sourceImageName)
+            .add("size", size);
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/6ab58bd2/azurecompute/src/main/java/org/jclouds/azurecompute/domain/DeploymentSlot.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/domain/DeploymentSlot.java b/azurecompute/src/main/java/org/jclouds/azurecompute/domain/DeploymentSlot.java
new file mode 100644
index 0000000..2e76b88
--- /dev/null
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/domain/DeploymentSlot.java
@@ -0,0 +1,42 @@
+/*
+ * 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
+ *
+ * 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.azurecompute.domain;
+
+import com.google.common.base.CaseFormat;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+public enum DeploymentSlot {
+   PRODUCTION, STAGING;
+
+   public String value() {
+      return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, name());
+   }
+
+   @Override
+   public String toString() {
+      return value();
+   }
+
+   public static DeploymentSlot fromValue(String type) {
+      try {
+         return valueOf(CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, checkNotNull(type, "type")));
+      } catch (IllegalArgumentException e) {
+         return null;
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/6ab58bd2/azurecompute/src/main/java/org/jclouds/azurecompute/domain/DeploymentStatus.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/domain/DeploymentStatus.java b/azurecompute/src/main/java/org/jclouds/azurecompute/domain/DeploymentStatus.java
new file mode 100644
index 0000000..eb34aa5
--- /dev/null
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/domain/DeploymentStatus.java
@@ -0,0 +1,43 @@
+/*
+ * 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
+ *
+ * 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.azurecompute.domain;
+
+import com.google.common.base.CaseFormat;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+public enum DeploymentStatus {
+	RUNNING, SUSPENDED, RUNNING_TRANSITIONING, SUSPENDED_TRANSITIONING, STARTING, SUSPENDING, DEPLOYING, DELETING;
+
+	public String value() {
+		return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, name());
+	}
+
+	@Override
+	public String toString() {
+		return value();
+	}
+
+	public static DeploymentStatus fromValue(String type) {
+		try {
+			return valueOf(CaseFormat.UPPER_CAMEL.to(
+					CaseFormat.UPPER_UNDERSCORE, checkNotNull(type, "type")));
+		} catch (IllegalArgumentException e) {
+			return null;
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/6ab58bd2/azurecompute/src/main/java/org/jclouds/azurecompute/domain/DetailedHostedServiceProperties.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/domain/DetailedHostedServiceProperties.java b/azurecompute/src/main/java/org/jclouds/azurecompute/domain/DetailedHostedServiceProperties.java
new file mode 100644
index 0000000..f954fd0
--- /dev/null
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/domain/DetailedHostedServiceProperties.java
@@ -0,0 +1,173 @@
+/*
+ * 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
+ *
+ * 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.azurecompute.domain;
+
+import com.google.common.base.MoreObjects.ToStringHelper;
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableMap;
+import java.util.Date;
+import java.util.Map;
+import org.jclouds.azurecompute.domain.HostedService.Status;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+public class DetailedHostedServiceProperties extends HostedServiceProperties {
+   public static Builder builder() {
+      return new Builder();
+   }
+
+   public Builder toBuilder() {
+      return new Builder().fromDetailedHostedServiceProperties(this);
+   }
+
+   public static class Builder extends HostedServiceProperties.Builder<Builder> {
+
+      protected String rawStatus;
+      protected Status status;
+      protected Date created;
+      protected Date lastModified;
+      protected ImmutableMap.Builder<String, String> extendedProperties = ImmutableMap.<String, String>builder();
+
+      /**
+       * @see DetailedHostedServiceProperties#getRawStatus()
+       */
+      public Builder rawStatus(String rawStatus) {
+         this.rawStatus = rawStatus;
+         return this;
+      }
+
+      /**
+       * @see DetailedHostedServiceProperties#getStatus()
+       */
+      public Builder status(Status status) {
+         this.status = status;
+         return this;
+      }
+
+      /**
+       * @see DetailedHostedServiceProperties#getCreated()
+       */
+      public Builder created(Date created) {
+         this.created = created;
+         return this;
+      }
+
+      /**
+       * @see DetailedHostedServiceProperties#getLastModified()
+       */
+      public Builder lastModified(Date lastModified) {
+         this.lastModified = lastModified;
+         return this;
+      }
+
+      /**
+       * @see DetailedHostedServiceProperties#getExtendedProperties()
+       */
+      public Builder extendedProperties(Map<String, String> extendedProperties) {
+         this.extendedProperties.putAll(checkNotNull(extendedProperties, "extendedProperties"));
+         return this;
+      }
+
+      /**
+       * @see DetailedHostedServiceProperties#getExtendedProperties()
+       */
+      public Builder addExtendedProperty(String name, String value) {
+         this.extendedProperties.put(checkNotNull(name, "name"), checkNotNull(value, "value"));
+         return this;
+      }
+
+      @Override protected Builder self() {
+         return this;
+      }
+
+      public DetailedHostedServiceProperties build() {
+         return new DetailedHostedServiceProperties(description, location, affinityGroup, label, rawStatus, status,
+               created, lastModified, extendedProperties.build());
+      }
+
+      public Builder fromDetailedHostedServiceProperties(DetailedHostedServiceProperties in) {
+         return fromHostedServiceProperties(in).rawStatus(in.getRawStatus()).status(in.getStatus())
+               .created(in.getCreated()).lastModified(in.getLastModified())
+               .extendedProperties(in.getExtendedProperties());
+      }
+   }
+
+   protected final String rawStatus;
+   protected final Status status;
+   protected final Date created;
+   protected final Date lastModified;
+   protected final Map<String, String> extendedProperties;
+
+   protected DetailedHostedServiceProperties(Optional<String> description, Optional<String> location,
+         Optional<String> affinityGroup, String label, String rawStatus, Status status, Date created, Date lastModified,
+         Map<String, String> extendedProperties) {
+      super(description, location, affinityGroup, label);
+      this.rawStatus = checkNotNull(rawStatus, "rawStatus of %s", description);
+      this.status = checkNotNull(status, "status of %s", description);
+      this.created = checkNotNull(created, "created of %s", description);
+      this.lastModified = checkNotNull(lastModified, "lastModified of %s", description);
+      this.extendedProperties = ImmutableMap
+            .copyOf(checkNotNull(extendedProperties, "extendedProperties of %s", description));
+   }
+
+   /**
+    * The status of the hosted service.
+    */
+   public Status getStatus() {
+      return status;
+   }
+
+   /**
+    * The status of the hosted service unparsed.
+    */
+   public String getRawStatus() {
+      return rawStatus;
+   }
+
+   /**
+    * The date that the hosted service was created.
+    */
+   public Date getCreated() {
+      return created;
+   }
+
+   /**
+    * The date that the hosted service was last updated.
+    */
+   public Date getLastModified() {
+      return lastModified;
+   }
+
+   /**
+    * Represents the name of an extended hosted service property. Each extended property must have
+    * both a defined name and value. You can have a maximum of 50 extended property name/value
+    * pairs.
+    *
+    * The maximum length of the Name element is 64 characters, only alphanumeric characters and
+    * underscores are valid in the Name, and the name must start with a letter. Each extended
+    * property value has a maximum length of 255 characters.
+    */
+   public Map<String, String> getExtendedProperties() {
+      return extendedProperties;
+   }
+
+   @Override
+   public ToStringHelper string() {
+      return super.string().add("status", rawStatus).add("created", created).add("lastModified", lastModified)
+            .add("extendedProperties", extendedProperties);
+   }
+}